Package marauroa.server.game.rp

Source Code of marauroa.server.game.rp.RPWorld

/* $Id: RPWorld.java,v 1.27 2009/12/25 13:15:30 nhnb 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 marauroa.server.game.rp;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import marauroa.common.Log4J;
import marauroa.common.game.IRPZone;
import marauroa.common.game.RPObject;
import marauroa.common.game.RPObjectInvalidException;
import marauroa.server.game.container.PlayerEntry;
import marauroa.server.game.container.PlayerEntryContainer;

/**
* This class is a container of RPZones.
* <p>
* Worlds in Marauroa can be so big, so huge, that we need to split them in to
* several pieces. Each of these pieces are what we call an IRPZone.
* <p>
* So our world is made of several IRPZones that are independent of each other.
* <p>
* RPWorld provides onInit and onFinish methods that are called on server
* initialisation and server finalization to define what to do with the world on
* these events.<br>
* <b>There is no default behaviour and you need to extend this class to
* implement the behaviour</b>.
*
* @author miguel
*/
public class RPWorld implements Iterable<IRPZone> {

  /** the logger instance. */
  private static final marauroa.common.Logger logger = Log4J.getLogger(RPWorld.class);

  /** The Singleton instance */
  private static RPWorld instance;

  /** A map containing the zones. */
  Map<IRPZone.ID, IRPZone> zones;

  /** The all-mighty player container. */
  PlayerEntryContainer playerContainer;

  /**
   * creates a new RPWorld. Note this class is designed as a singleton.
   */
  protected RPWorld() {
    zones = new ConcurrentHashMap<IRPZone.ID, IRPZone>();
  }

  /**
   * Initialize the player entry container so RPWorld knows about players.
   *
   */
  protected void initialize() {
    playerContainer = PlayerEntryContainer.getContainer();
  }

  /**
   * Sets the instance of RPWorld we are going to use, so we are truly using a
   * singleton pattern.
   *
   * @param implementation
   *            the instance of RPWorld we are going to use.
   */
  static void set(RPWorld implementation) {
    instance = implementation;
  }

  /**
   * Returns an unique World method.
   *
   * @return an instance of RPWorld
   */
  public static RPWorld get() {
    if (instance == null) {
      RPWorld instance = new RPWorld();
      instance.initialize();
      RPWorld.instance = instance;
    }
    return instance;
  }

  /** This method is called when RPWorld is created by RPServerManager */
  public void onInit() {
    // implement in subclasses
  }

  /** This method is called when server is going to shutdown. */
  public void onFinish() {
    /*
     * Call onFinish for each of the zones.
     */
    for (IRPZone zone : zones.values()) {
      try {
        zone.onFinish();
      } catch (Exception e) {
        logger.warn("Exception at onFinish", e);
      }
    }
  }

  /**
   * Adds a new zone to World
   *
   * @param zone
   *            a zone to add to world.
   */
  public void addRPZone(IRPZone zone) {
    zones.put(zone.getID(), zone);
  }

  /**
   * Returns true if world has such zone
   *
   * @param zoneid
   *            the zone to query
   * @return true of the zone exists
   */
  public boolean hasRPZone(IRPZone.ID zoneid) {
    return zones.containsKey(zoneid);
  }

  /**
   * Returns the zone or null if it doesn't exists
   *
   * @param zoneid
   *            the zone to query
   * @return the zone or null if it is not found.
   */
  public IRPZone getRPZone(IRPZone.ID zoneid) {
    return zones.get(zoneid);
  }

  /**
   * Returns the zone or null if it doesn't exists
   *
   * @param objectid
   *            an id of an object that is in the zone to query
   * @return the zone or null if it is not found.
   */
  public IRPZone getRPZone(RPObject.ID objectid) {
    return zones.get(new IRPZone.ID(objectid.getZoneID()));
  }

  /**
   * Removes a zone from world.
   * It calls zone.onFinish method to free resources zone could have allocated.   *
   *
   * @param zoneid
   * @return the zone removed or null if not found
   * @throws Exception caused by onFinish
   */
  public IRPZone removeRPZone(IRPZone.ID zoneid) throws Exception {
    IRPZone zone=zones.remove(zoneid);
   
    if(zone!=null) {
      zone.onFinish();
    }
   
    return zone;
  }

  /**
   * Removes a zone from world.
   * It calls zone.onFinish method to free resources zone could have allocated.
   *
   * @param objectid
   * @return the zone removed or null if not found
   * @throws Exception caused by onFinish
   */
  public IRPZone removeRPZone(RPObject.ID objectid) throws Exception {
    IRPZone.ID zoneid=new IRPZone.ID(objectid.getZoneID());
    IRPZone zone=zones.remove(zoneid);
   
    if(zone!=null) {
      zone.onFinish();
    }
   
    return zone;
  }
 
  /**
   * This method adds an object to the zone it points with its zoneid
   * attribute. And if it is a player, it request also a sync perception.
   *
   * @param object
   *            the object to add
   */
  public void add(RPObject object) {
    String zoneid = object.get("zoneid");
    if (zoneid != null) {
      IRPZone zone = zones.get(new IRPZone.ID(zoneid));
      if (zone == null) {
        logger.error("Unknown zone: " + zoneid);
        return;
      }
      zone.assignRPObjectID(object);

      zone.add(object);
    }
  }

  /**
   * When a player is added to a zone, it needs his status to be synced.
   *
   * @param object
   *            the player object
   */
  public void requestSync(RPObject object) {
    /* A player object will have always the clientid attribute. */
    if (object.has("#clientid")) {
      /*
       * So if object has the attribute, we request a sync perception as
       * we have entered a new zone.
       */
      PlayerEntry entry = playerContainer.get(object);
      if (entry != null) {
        entry.requestSync();
      }
    }
  }

  /**
   * This method returns an object from a zone using it ID<object, zone>
   *
   * @param id
   *            the object's id
   * @return the object
   */
  public RPObject get(RPObject.ID id) {
    IRPZone zone = zones.get(new IRPZone.ID(id.getZoneID()));
    return zone.get(id);
  }

  /**
   * This method returns true if an object exists in a zone using it ID<object,
   * zone>
   *
   * @param id
   *            the object's id
   * @return true if the object exists
   */
  public boolean has(RPObject.ID id) {
    IRPZone zone = zones.get(new IRPZone.ID(id.getZoneID()));
    return zone.has(id);
  }

  /**
   * This method returns an object from a zone using it ID<object, zone> and
   * remove it
   *
   * @param id
   *            the object's id
   * @return the object or null if it not found.
   */
  public RPObject remove(RPObject.ID id) {
    IRPZone zone = zones.get(new IRPZone.ID(id.getZoneID()));
    if (zone != null) {
      return zone.remove(id);
    }

    logger.error("Cannot remove rpobject with id " + id + " from zone because there is no zone with that name in the RPWorld");
    return null;
  }

  /**
   * This method returns an iterator over all the zones contained.
   *
   * @return iterator over zones.
   */
  public Iterator<IRPZone> iterator() {
    return zones.values().iterator();
  }

  /**
   * This method notify zone that object has been modified. Used in Delta^2
   *
   * @param object
   *            the object that has been modified.
   */
  public void modify(RPObject object) {
    IRPZone zone = zones.get(new IRPZone.ID(object.get("zoneid")));
    if (zone != null) {
      zone.modify(object);
    } else {
      logger.warn("calling RPWorld.modify on a zoneless object: " + object + " parent: " + object.getContainerBaseOwner(), new Throwable());
    }
  }

  /**
   * This methods make a player/object to change zone.
   *
   * @param newzoneid
   *            the new zone id
   * @param object
   *            the object we are going to change zone to.
   * @throws RPObjectInvalidException
   */
  public void changeZone(IRPZone.ID newzoneid, RPObject object) {
    try {
      String targetZoneid = newzoneid.getID();
      if (targetZoneid.equals(object.get("zoneid"))) {
        return;
      }

      remove(object.getID());

      object.put("zoneid", targetZoneid);

      add(object);

      requestSync(object);

    } catch (Exception e) {
      logger.error("error changing Zone", e);
      throw new RPObjectInvalidException("zoneid");
    }
  }

  /**
   * This methods make a player/object to change zone.
   *
   * @param newzone
   *            the new zone id
   * @param object
   *            the object we are going to change zone to.
   */
  public void changeZone(String newzone, RPObject object) {
    changeZone(new IRPZone.ID(newzone), object);
  }

  /**
   * This method make world to move to the next turn, calling each zone
   * nextTurn method. *
   */
  public void nextTurn() {
    for (IRPZone zone : zones.values()) {
      zone.nextTurn();
    }
  }

  /**
   * This methods return the amount of objects added to world.
   *
   * @return the amount of objects added to world.
   */
  public int size() {
    int size = 0;

    for (IRPZone zone : zones.values()) {
      size += zone.size();
    }

    return size;
  }
}
TOP

Related Classes of marauroa.server.game.rp.RPWorld

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.