Package games.stendhal.server.actions.move

Source Code of games.stendhal.server.actions.move.PushAction

/* $Id: PushAction.java,v 1.14 2010/08/03 14:27:45 kiheru Exp $ */
/***************************************************************************
*                      (C) Copyright 2003 - Marauroa                      *
***************************************************************************
***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/
package games.stendhal.server.actions.move;

import static games.stendhal.common.constants.Actions.PUSH;
import static games.stendhal.common.constants.Actions.TARGET;
import games.stendhal.common.Direction;
import games.stendhal.server.actions.ActionListener;
import games.stendhal.server.actions.CommandCenter;
import games.stendhal.server.core.engine.GameEvent;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.Entity;
import games.stendhal.server.entity.RPEntity;
import games.stendhal.server.entity.item.Item;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.util.EntityHelper;

import java.util.Set;

import marauroa.common.game.RPAction;

/**
* Pushes an entity which is next to the player one field forward.
* This can be used to push afk-players away who are blocking a portal
* for instance.
*/
public class PushAction implements ActionListener {

  public static void register() {
    final PushAction push = new PushAction();
    CommandCenter.register(PUSH, push);
  }

  public void onAction(final Player player, final RPAction action) {

    // evaluate the target parameter
    final Entity entity = EntityHelper.entityFromTargetName(
      action.get(TARGET), player);

    if ((entity == null) || !(entity instanceof RPEntity)) {
      return;
    }
    final RPEntity rpEntity = (RPEntity) entity;

    tryPush(player, rpEntity);
  }

  /**
   * Tries to push the entity.
   *
   * @param player player pushing
   * @param rpEntity entity pushed
   */
  private void tryPush(final Player player, final RPEntity rpEntity) {
    if (canPush(player, rpEntity)) {
      final Direction dir = player.getDirectionToward(rpEntity);

      final int x = rpEntity.getX() + dir.getdx();
      final int y = rpEntity.getY() + dir.getdy();

      final StendhalRPZone zone = player.getZone();
      if (!zone.collides(rpEntity, x, y)) {
        move(player, rpEntity, x, y);
        // Stop players running toward to make trapping harder. Don't
        // stop anyone just following a path (again to make annoying
        // others harder)
        if (dir.oppositeDirection() == rpEntity.getDirection()
            && !rpEntity.hasPath()) {
          rpEntity.stop();
        }
      }
    }
  }

  /**
   * Can this push be done according to the rules?
   *
   * @param player   player pushing
   * @param rpEntity entity pushed
   * @return true, if the push is possible, false otherwise
   */
  private boolean canPush(final Player player, final RPEntity rpEntity) {

    // If object is a NPC we ignore the push action because
    // NPC don't use the pathfinder and would get confused
    // outside their fixed path. Apart from that some NPCs
    // may block a way by intention.
    if (rpEntity instanceof SpeakerNPC) {
      return false;
    }

    // prevent pushing a player off an item
    if (rpEntity instanceof Player) {
      // prevent pushing a player off an item
      final Set<Item> items = player.getZone().getItemsOnGround();
      for (final Item item : items) {
        if (rpEntity.getArea().intersects(item.getArea())) {
          player.sendPrivateText("You cannot push now because there is an item below " + rpEntity.getName() + ".");
          return false;
        }
      }
    }
   
    // players cannot push rp entities with area larger than 4
    /* I (kymara) looked in java api for Rectangle2D and couldn't find how to
    * get the value for area so i have done w * h . I guessed at .size() but didn't work
    * if this is ok please delete these comments */
    if (rpEntity.getArea().getWidth() * rpEntity.getArea().getHeight() > 4) {
      player.sendPrivateText("You're strong, but not that strong!");
      return false;
    }

    // the number of pushes is limited per time
    if (!player.canPush(rpEntity)) {
      player.sendPrivateText("Give yourself a breather before you start pushing again.");
      return false;
    }

    // the player must be in range.
    return (player.nextTo(rpEntity));
  }

  /**
   * Moves the entity to the new position.
   *
   * @param player   player pushing
   * @param rpEntity entity pushed
   * @param x new x-position
   * @param y new y-position
   */
  private void move(final Player player, final RPEntity rpEntity, final int x, final int y) {
    new GameEvent(player.getName(), "push", rpEntity.getName(), rpEntity.getZone().getName(), rpEntity.getX() + " " + rpEntity.getY() + " --> " + x + " " + y).raise();
    rpEntity.setPosition(x, y);
    rpEntity.notifyWorldAboutChanges();
    player.onPush(rpEntity);
  }
}
TOP

Related Classes of games.stendhal.server.actions.move.PushAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.