Package games.stendhal.server.entity.player

Source Code of games.stendhal.server.entity.player.Jail$Jailer

/* $Id: Jail.java,v 1.34 2010/12/05 13:30:12 martinfuchs 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.player;

import games.stendhal.common.Direction;
import games.stendhal.common.MathHelper;
import games.stendhal.server.core.config.ZoneConfigurator;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPWorld;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.core.events.LoginListener;
import games.stendhal.server.core.events.TurnListener;
import games.stendhal.server.core.events.ZoneEnterExitListener;
import games.stendhal.server.entity.RPEntity;
import games.stendhal.server.entity.mapstuff.office.ArrestWarrant;
import games.stendhal.server.entity.mapstuff.office.ArrestWarrantList;

import java.awt.Point;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import marauroa.common.game.IRPZone;
import marauroa.common.game.RPObject;

import org.apache.log4j.Logger;

/**
* This class is responsible of keeping players who have misbehaved in a special
* jail area where they can't do any harm. The misbehaving player will be
* automatically released after a specified number of minutes.
*
* @author daniel
*/
public class Jail implements ZoneConfigurator, LoginListener {

  static StendhalRPZone jailzone;

  private static final Logger LOGGER = Logger.getLogger(Jail.class);
  private static final List<Point> cellEntryPoints = Arrays.asList(
      new Point(3, 3),
      new Point(8, 3),
      // elf cell(13, 3),
      new Point(18, 3),
      new Point(23, 3),
      new Point(28, 3),
      new Point(8, 11),
      new Point(13, 11),
      new Point(18, 11),
      new Point(23, 11),
      new Point(28, 11)
    );

    private static final Rectangle[] cellBlocks = {
      new Rectangle(1, 1, 30, 3),
      new Rectangle(7, 10, 30, 3)
    };

  private ArrestWarrantList arrestWarrants;

  private List<Cell> cells = new LinkedList<Cell>();
 
  private ZoneEnterExitListener listener = new ZoneEnterExitListener() {
    public void onEntered(final RPObject object, final StendhalRPZone zone) {
      if (object.getRPClass().subclassOf("player")) {
        //TODO: could this be a bug ? (durkham)
       
      }
    }

    public void onExited(final RPObject object, final StendhalRPZone zone) {
      if (object instanceof RPEntity && object.getRPClass().subclassOf("player")) {
        String playerName = ((RPEntity)object).getName();

        for (final Cell cell : cells) {
          cell.remove(playerName);
        }
      }
    }
  };


  private final class Jailer implements TurnListener {

    private final String criminalName;

    Jailer(final String name) {
      criminalName = name;
    }

    @Override
    public boolean equals(final Object obj) {
      if (obj instanceof Jailer) {
        final Jailer other = (Jailer) obj;
        return criminalName.equals(other.criminalName);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return criminalName.hashCode();
    }

    public void onTurnReached(final int currentTurn) {
      release(criminalName);
    }
  }

  /**
   * @param criminalName
   *            The name of the player who should be jailed
   * @param policeman
   *            The name of the admin who wants to jail the criminal
   * @param minutes
   *            The duration of the sentence
   * @param reason why criminal was jailed
   */
  public void imprison(final String criminalName, final Player policeman,
      final int minutes, final String reason) {

    final Player criminal = SingletonRepository.getRuleProcessor().getPlayer(
            criminalName);

    arrestWarrants.removeByName(criminalName);
    final ArrestWarrant arrestWarrant = new ArrestWarrant(criminalName, policeman, minutes, reason);

    policeman.sendPrivateText("You have jailed " + criminalName
      + " for " + minutes + " minutes. Reason: " + reason + ".");
    SingletonRepository.getRuleProcessor().sendMessageToSupporters("JailKeeper",
      policeman.getName() + " jailed " + criminalName
      + " for " + minutes + " minutes. Reason: " + reason
      + ".");

    if (criminal == null) {
      final String text = "Player " + criminalName + " is not online, but the arrest warrant has been recorded anyway.";
      policeman.sendPrivateText(text);
      LOGGER.debug(text);
    } else {
      arrestWarrant.setStarted();
      imprison(criminal, policeman, minutes);
      criminal.sendPrivateText("You have been jailed for " + minutes
          + " minutes. Reason: " + reason + ".");
    }
    arrestWarrants.add(arrestWarrant);
  }

  protected void imprison(final Player criminal, final Player policeman, final int minutes) {

    if (jailzone == null) {
      final String text = "No zone has been configured to be Jailzone";
      policeman.sendPrivateText(text);
      LOGGER.debug(text);
      return;
    }
    final boolean successful = teleportToAvailableCell(criminal, policeman);
    if (successful) {
      final Jailer jailer = new Jailer(criminal.getName());
      SingletonRepository.getTurnNotifier().dontNotify(jailer);

      // Set a timer so that the inmate is automatically released after
      // serving his sentence. Negative times are treated as "forever",
      // thus no turn notifiers are needed. Zero is useful for freeing
      // players, so we handle that normally.
      if (minutes >= 0) {
        SingletonRepository.getTurnNotifier().notifyInSeconds(minutes * 60, jailer);
      }
    } else {
      policeman.sendPrivateText("Could not find a cell for "
          + criminal.getName());
    }
  }

  private boolean teleportToAvailableCell(final Player criminal,
      final Player policeman) {
    Collections.shuffle(cells);
    for (final Cell cell : cells) {
      if (cell.isEmpty()) {
        if (criminal.teleport(jailzone, cell.getEntry().x, cell
            .getEntry().y, Direction.DOWN, policeman)) {
          cell.add(criminal.getName());
          return true;
        }
      }
     
    }

    return false;
  }

  /**
   * Releases an inmate and teleports him to Semos city, but only if he is
   * still in jail.
   *
   * @param inmateName
   *            the name of the inmate who should be released
   * @return true if the player has not logged out before he was released
   */
  public boolean release(final String inmateName) {
    final Player inmate = SingletonRepository.getRuleProcessor().getPlayer(inmateName);
    if (inmate == null) {
      LOGGER.debug("Jailed player " + inmateName + "has logged out.");
      return false;
    }

    release(inmate);
    return true;
  }

  void release(final Player inmate) {
    // Only teleport the player if he is still in jail.
    // It could be that an admin has teleported him out earlier.
    final StendhalRPWorld world = SingletonRepository.getRPWorld();
    if (isInJail(inmate)) {
      final IRPZone.ID zoneid = new IRPZone.ID("-3_semos_jail");
      if (!world.hasRPZone(zoneid)) {
        LOGGER.debug("Zone " + zoneid + " not found");
      }
      final StendhalRPZone exitZone = (StendhalRPZone) world.getRPZone(zoneid);

      inmate.teleport(exitZone, 6, 3, Direction.RIGHT, null);
      inmate.sendPrivateText("Your sentence is over. You can walk out now.");
      LOGGER.debug("Player " + inmate.getName() + "released from jail.");
    }

    // The player completed his sentence and did not logout
    // so destroy the ArrestWarrant
    arrestWarrants.removeByName(inmate.getName());
  }

  /**
   * Is player in a jail cell? Ignores visitors outside of cells.
   *
   * @param inmate
   *            player to check
   * @return true, if it is in jail, false otherwise.
   */
  public static boolean isInJail(final Player inmate) {
    final StendhalRPZone zone = inmate.getZone();

    if ((zone != null) && zone.equals(jailzone)) {
      for (final Rectangle cellBlock : cellBlocks) {
        if (cellBlock.contains(inmate.getX(), inmate.getY())) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Destroy the arrest warrent so that the player is not rejailed on next login.
   * @param player
   */
  public void grantParoleIfPlayerWasAPrisoner(final Player player) {
   
    arrestWarrants.removeByName(player.getName());
  }

  public void onLoggedIn(final Player player) {
    // we need to do this on the next turn because the
    // client does not get any private messages otherwise
    // sometime the client does not get the map content
    // if it gets a cross zone teleport too early. so we wait
    // 5 seconds.
    SingletonRepository.getTurnNotifier().notifyInSeconds(5, new TurnListener() {
      public void onTurnReached(final int currentTurn) {
        final String name = player.getName();

        final ArrestWarrant arrestWarrant = arrestWarrants.getByName(name);
        if (arrestWarrant == null) {
          return;
        }

        if (removeVeryOldWarrants(arrestWarrant)) {
          return;
        }

        final long timestamp = arrestWarrant.getTimestamp();
        player.sendPrivateText("You have been jailed "
          + " for " + arrestWarrant.getMinutes()
          + " minutes on " + String.format("%tF", timestamp)
          + ". Reason: " + arrestWarrant.getReason() + ".");

        handleEscapeMessages(arrestWarrant);
        imprison(player, player, arrestWarrant.getMinutes());
      }

      public boolean removeVeryOldWarrants(final ArrestWarrant arrestWarrant) {
        final long timestamp = arrestWarrant.getTimestamp();
        if (timestamp + 30 * MathHelper.MILLISECONDS_IN_ONE_DAY < System.currentTimeMillis()) {
          arrestWarrants.removeByName(arrestWarrant.getCriminal());
          return true;
        }

        return false;
      }
     

      public void handleEscapeMessages(final ArrestWarrant arrestWarrant) {
        if (arrestWarrant.isStarted()) {
          // Notify player that his sentences is starting again because he tried to escape by logging out
          player.sendPrivateText("Although you already spent some "
              + "time in jail, your sentence has been restarted "
              + "because of your failed escape attempt.");
        } else {
          // Jail player who was offline at the time /jail was issued.
          arrestWarrant.setStarted();
        }
      }
    });
  }

  public String listJailed() {
    if (arrestWarrants != null) {
      return arrestWarrants.toString();
    }
    return "jail not inited ?";
  }
 
  /**
   * Get the ArrestWarrant of a jailed player.
   *
   * @param name the name of the player
   * @return the ArrestWarrant for the player, or null if there is none
   */
  public ArrestWarrant getWarrant(final String name) {
    return arrestWarrants.getByName(name);
  }

  public void configureZone(final StendhalRPZone zone, final Map<String, String> attributes) {
    SingletonRepository.getLoginNotifier().addListener(this);
    SingletonRepository.setJail(this);
    zone.addZoneEnterExitListener(listener);
    initCells();
    arrestWarrants = new ArrestWarrantList(zone);
    jailzone = zone;
  }

  private void initCells() {
    for (final Point p : cellEntryPoints) {
      cells.add(new Cell(p));
    }
   
  }
}
TOP

Related Classes of games.stendhal.server.entity.player.Jail$Jailer

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.