Package games.stendhal.server.entity.mapstuff.area

Source Code of games.stendhal.server.entity.mapstuff.area.OnePlayerArea

/*
* @(#) src/games/stendhal/server/entity/OnePlayerArea.java
*
* $Id: OnePlayerArea.java,v 1.13 2011/02/28 20:04:52 nhnb Exp $
*/

package games.stendhal.server.entity.mapstuff.area;

import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.core.events.MovementListener;
import games.stendhal.server.entity.ActiveEntity;
import games.stendhal.server.entity.Entity;
import games.stendhal.server.entity.player.Player;

import java.lang.ref.WeakReference;

import org.apache.log4j.Logger;

/**
* An area that only allows one play at a time to enter.
*
*/
public class OnePlayerArea extends AreaEntity implements MovementListener {
  /**
   * The logger instance.
   */
  private static final Logger LOGGER = Logger.getLogger(OnePlayerArea.class);

  /**
   * The reference to the entity currently in the area.
   */
  protected WeakReference<Player> occupantRef;

  /**
   * Create a one player area.
   *
   * @param width
   *            The area width.
   * @param height
   *            The area height.
   */
  public OnePlayerArea(final int width, final int height) {
    super(width, height);

    hide();
    occupantRef = null;
  }

  //
  // OnePlayerArea
  //

  /**
   * Clear the occupant.
   */
  protected void clearOccupant() {
    occupantRef = null;
  }

  /**
   * Check if an entity is in this area.
   *
   * @param entity
   *            The entity to check.
   *
   * @return <code>true</code> if the entity is in this area.
   *
   */
  protected boolean contains(final Entity entity) {
    return ((getZone() == entity.getZone()) && getArea().intersects(
        entity.getArea()));
  }

  /**
   * Get the occupant.
   *
   * @return The area occupant, or <code>null</code> in none.
   */
  protected Player getOccupant() {
    if (occupantRef != null) {
      return occupantRef.get();
    } else {
      return null;
    }
  }

  /**
   * Set the occupant.
   *
   * @param player
   *            The occupant to set.
   */
  protected void setOccupant(final Player player) {
    occupantRef = new WeakReference<Player>(player);
  }

  //
  // Entity
  //

  /**
   * Checks whether players, NPC's, etc. can walk over this entity.
   *
   * @param entity
   *            The entity trying to enter.
   *
   * @return <code>true</code> if a Player is given and it is occupied by
   *         someone else.
   */
  @Override
  public boolean isObstacle(final Entity entity) {
    /*
     * Only applies to Players
     */
    if (!(entity instanceof Player)) {
      return super.isObstacle(entity);
    }
    final Player player = (Player) entity;

    /*
     * Ghosts shouldn't give away their presence
     */
    if (player.isGhost()) {
      return false;
    }

    final Player occupant = getOccupant();

    if (occupant != null) {
      /*
       * Verify the occupant (just incase)
       */
      if (contains(occupant)) {
        /*
         * Allow if it's the occupant (quick check).
         *
         * But don't block entities that got in the area (somehow) from
         * leaving.
         */
        return ((entity != occupant) && !contains(entity));
      }

      LOGGER.warn("Occupant vanished: " + occupant.getName());
      clearOccupant();
    }

    return false;
  }

  /**
   * Called when this object is added to a zone.
   *
   * @param zone
   *            The zone this was added to.
   */
  @Override
  public void onAdded(final StendhalRPZone zone) {
    super.onAdded(zone);
    zone.addMovementListener(this);
  }

  /**
   * Called when this object is being removed from a zone.
   *
   * @param zone
   *            The zone this will be removed from.
   */
  @Override
  public void onRemoved(final StendhalRPZone zone) {
    zone.removeMovementListener(this);
    super.onRemoved(zone);
  }

  /**
   * Handle object attribute change(s).
   */
  @Override
  public void update() {
    /*
     * Reregister incase coordinates/size changed (could be smarter)
     */
    final StendhalRPZone zone = getZone();

    if (zone != null) {
      zone.removeMovementListener(this);
    }

    super.update();

    if (zone != null) {
      zone.addMovementListener(this);
    }
  }

  //
  // MovementListener
  //

  /**
   * Invoked when an entity enters the object area.
   *
   * @param entity
   *            The entity that moved.
   * @param zone
   *            The new zone.
   * @param newX
   *            The new X coordinate.
   * @param newY
   *            The new Y coordinate.
   */
  public void onEntered(final ActiveEntity entity, final StendhalRPZone zone, final int newX,
      final int newY) {
    /*
     * Just players
     */
    if (entity instanceof Player) {
      /*
       * Ghosts don't occupy normal space
       */
      if (entity.isGhost()) {
        return;
      }

      final Player occupant = getOccupant();

      /*
       * Check to make sure things aren't buggy
       */
      if ((occupant != null) && (occupant != entity)) {
        if (occupant.isGhost()) {
          clearOccupant();
        }
        LOGGER.error("Existing occupant: " + occupant.getName(), new Throwable());
      }

      setOccupant((Player) entity);
    }
  }

  /**
   * Invoked when an entity leaves the object area.
   *
   * @param entity
   *            The entity that entered.
   * @param zone
   *            The old zone.
   * @param oldX
   *            The old X coordinate.
   * @param oldY
   *            The old Y coordinate.
   *
   */
  public void onExited(final ActiveEntity entity, final StendhalRPZone zone, final int oldX,
      final int oldY) {
    /*
     * Check against occupant incase something else is existing
     */
    if (entity == getOccupant()) {
      clearOccupant();
    }
  }

  /**
   * Invoked when an entity moves while over the object area.
   *
   * @param entity
   *            The entity that left.
   * @param zone
   *            The zone.
   * @param oldX
   *            The old X coordinate.
   * @param oldY
   *            The old Y coordinate.
   * @param newX
   *            The new X coordinate.
   * @param newY
   *            The new Y coordinate.
   */
  public void onMoved(final ActiveEntity entity, final StendhalRPZone zone, final int oldX,
      final int oldY, final int newX, final int newY) {
    // does nothing, but is specified in the implemented interface
  }
}
TOP

Related Classes of games.stendhal.server.entity.mapstuff.area.OnePlayerArea

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.