Package games.stendhal.server.entity.mapstuff.useable

Source Code of games.stendhal.server.entity.mapstuff.useable.PlayerActivityEntity$Activity

/* $Id: PlayerActivityEntity.java,v 1.4 2010/10/28 18:54:18 kymara Exp $ */
/***************************************************************************
*                   (C) Copyright 2003-2010 - Stendhal                    *
***************************************************************************
***************************************************************************
*                                                                         *
*   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.entity.mapstuff.useable;


import games.stendhal.common.MathHelper;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.events.TurnListener;
import games.stendhal.server.entity.RPEntity;
import games.stendhal.server.entity.player.Player;

import java.lang.ref.WeakReference;

/**
* An entity that performs some activity for a player. The activity takes some
* time to perform and can succeed or fail. The player must be standing next to
* the entity when it finished to succeed. The activity must finish before being
* initiated again.
*/
public abstract class PlayerActivityEntity extends UseableEntity {

  private static final long PENALTY_TIMEOUT = 30 * 60 * 1000;
  private static final long PENALTY_COUNT = 3000;

  /**
   * Create a player activity entity.
   */
  public PlayerActivityEntity() {
    setResistance(0);
  }

  //
  // PlayerActivityEntity
  //
 
  /**
   * Returns source name (type of source).
   */
  protected abstract String getName();

  /**
   * Process the results of the activity.
   *
   * @param player
   *            The player that performed the activity.
   */
  protected void activityDone(final Player player) {
    /*
     * Verify that the player is still standing next to this, else their
     * activity fails.
     */
    if (nextTo(player)) {
      if (isPenalized(player)) {
        onFinished(player, false);
      } else {
        onFinished(player, isSuccessful(player));
      }
    } else {
      player.sendPrivateText("You are too far away from the "+this.getName()+
                   ", try to come closer.");
      onFinished(player, false);
    }
  }

  /**
   * Get the time it takes to perform this activity.
   *
   * @return The time to perform the activity (in seconds).
   */
  protected abstract int getDuration();

  /**
   * Decides if the activity can be done.
   * @param player for whom to perform the activity
   *
   * @return <code>true</code> if can be done
   */
  protected abstract boolean isPrepared(final Player player);

  /**
   * Decides if the activity was successful.
   * @param player for whom to perform the activity
   *
   * @return <code>true</code> if successful.
   */
  protected abstract boolean isSuccessful(final Player player);

  /**
   * Called when the activity has finished.
   *
   * @param player
   *            The player that did the activity.
   * @param successful
   *            If the activity was successful.
   */
  protected abstract void onFinished(final Player player,
      final boolean successful);

  /**
   * Called when the activity has started.
   *
   * @param player
   *            The player starting the activity.
   */
  protected abstract void onStarted(final Player player);

  /**
   * Check for excessive usage
   *
   * @param player
   *            The player starting the activity.
   *           
   * @return <code>true</code> if the usage was excessive
   */
  protected boolean isPenalized(final Player player) {
    String timestamp = player.get("source_usage", this.getName() + ".lastused");
    int usageCount = 0;
    if (MathHelper.parseLong(timestamp) > System.currentTimeMillis() - PENALTY_TIMEOUT) {
      usageCount = player.getInt("source_usage", this.getName() + ".count");
    }
    usageCount++;
    player.put("source_usage", this.getName() + ".lastused",  Long.toString(System.currentTimeMillis()));
    player.put("source_usage", this.getName() + ".count", usageCount);

    return usageCount > PENALTY_COUNT;
  }

  //
  // UseListener
  //

  /**
   * Is called when a player initiates the activity.
   *
   * @param entity
   *            The initiating entity.
   *
   * @return <code>true</code> if the entity was used.
   */
  public boolean onUsed(final RPEntity entity) {

    if (!(entity instanceof Player)) {
      return false;
    }
   
    final Player player = (Player) entity;
   
    // The player must be next to the source to start to use it.
    if (!player.nextTo(this)) {
      player.sendPrivateText("You are too far away from " + this.getName()+
        ", try to come closer.");
      return false;
    }

    if (isPrepared(player)) {
      final Activity activity = new Activity(player);

      /*
       * You can't start a new activity before the last one has finished.
       */
      if (SingletonRepository.getTurnNotifier().getRemainingTurns(activity) == -1) {
        player.faceToward(this);
        onStarted(player);

        SingletonRepository.getTurnNotifier().notifyInSeconds(getDuration(), activity);
      }
    }

    player.notifyWorldAboutChanges();
    return true;
  }

  //
  //

  /**
   * An occurrence of activity.
   */
  protected class Activity implements TurnListener {
    /*
     * The player holder.
     */
    protected WeakReference<Player> ref;

    /**
     * Create an activity.
     *
     * @param player
     *            The player.
     */
    public Activity(final Player player) {
      ref = new WeakReference<Player>(player);
    }

    //
    // Activity
    //

    /**
     * Get the holder entity.
     *
     * @return The holder entity.
     */
    public PlayerActivityEntity getEntity() {
      return PlayerActivityEntity.this;
    }

    /**
     * Get the player.
     *
     * @return The player (or <code>null</code> if GC'd).
     */
    public Player getPlayer() {
      return ref.get();
    }

    //
    // TurnListener
    //

    /**
     * This method is called when the turn number is reached.
     *
     * @param currentTurn
     *            The current turn number.
     */
    public void onTurnReached(final int currentTurn) {
      final Player player = getPlayer();

      if (player != null) {
        activityDone(player);
      }
    }

    //
    // Object
    //

    @Override
    public boolean equals(final Object obj) {
      if (obj instanceof Activity) {
        final Activity activity = (Activity) obj;

        /*
         * Equal in context of same parent entity
         */
        if (getEntity() != activity.getEntity()) {
          return false;
        }

        return (getPlayer() == activity.getPlayer());
      } else {
        return false;
      }
    }

    @Override
    public int hashCode() {
      final Object player = getPlayer();

      if (player != null) {
        return player.hashCode();
      } else {
        return 0;
      }
    }
  }
}
TOP

Related Classes of games.stendhal.server.entity.mapstuff.useable.PlayerActivityEntity$Activity

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.