Package games.stendhal.server.core.engine

Source Code of games.stendhal.server.core.engine.StendhalRPWorld

/* $Id: StendhalRPWorld.java,v 1.45 2011/05/01 19:50:08 martinfuchs 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.core.engine;

import games.stendhal.common.parser.WordList;
import games.stendhal.server.core.config.ZoneGroupsXMLLoader;
import games.stendhal.server.entity.Entity;
import games.stendhal.server.entity.mapstuff.portal.OneWayPortalDestination;
import games.stendhal.server.entity.mapstuff.portal.Portal;

import java.net.URI;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import marauroa.common.game.IRPZone;
import marauroa.common.game.IRPZone.ID;
import marauroa.server.game.rp.RPWorld;

import org.apache.log4j.Logger;

public class StendhalRPWorld extends RPWorld {
  /** the logger instance. */
  private static final Logger logger = Logger.getLogger(StendhalRPWorld.class);

  public final static String MAPS_FOLDER;

  static {
    if (StendhalRPWorld.class.getClassLoader().getResource(
        "tiled/tileset/README") == null) {
      MAPS_FOLDER = "data/maps/";
    } else {
      logger.warn("Developing mode, loading maps from tiled/ instead of data/maps");
      MAPS_FOLDER = "tiled/";
    }
  }

  /**
   * A common place for milliseconds per turn.
   */
  public static final int MILLISECONDS_PER_TURN = 300;
 
  private final RPClassGenerator genRPClass = new RPClassGenerator();

  /** The Singleton instance. */
  protected static StendhalRPWorld instance;

  // /** The pathfinder thread. */
  // private PathfinderThread pathfinderThread;

  private final Map<String, Set<StendhalRPZone>> regionMap = new HashMap<String, Set<StendhalRPZone>>();


  protected StendhalRPWorld() {
    super();
  }

  @Override
  public IRPZone removeRPZone(final ID zoneid) throws Exception {
    final StendhalRPZone zone = (StendhalRPZone) super.getRPZone(zoneid);
    for(final Set<StendhalRPZone> zones : regionMap.values()) {
      if(zones.contains(zone)) {
        zones.remove(zone);
      }
    }
    return super.removeRPZone(zoneid);
  }
 
  public void removeZone(final StendhalRPZone toBeRemoved) {
    try {
      removeRPZone(toBeRemoved.getID());
    } catch (final Exception e) {
      logger.error(e, e);
    }
  }


  public static StendhalRPWorld get() {
    synchronized(StendhalRPWorld.class) {
      if (instance == null) {
        instance = new StendhalRPWorld();
        instance.initialize();
      }
    }

    return instance;
  }

 
  @Override
  protected void initialize() {
    super.initialize();
    genRPClass.createRPClasses();
  }
 
  /**
   * This method is a workaround for a groovy bug:
   * http://jira.codehaus.org/browse/GROOVY-1484
   *
   * Don't use it in Java code, only in Groovy. Remove this method once the
   * Groovy bug has been resolved.
   *
   * @return StendhalRPWorld
   * @deprecated use StendhalRPWorld.get()
   */
  @Deprecated
  public static StendhalRPWorld getInstance() {
    return SingletonRepository.getRPWorld();
  }

  /**
   * Gives the number of turns that will take place during a given number of
   * seconds.
   *
   * @param seconds
   *            The number of seconds.
   *
   * @return The number of turns.
   */
  public int getTurnsInSeconds(final int seconds) {
    return seconds * 1000 / MILLISECONDS_PER_TURN;
  }

 

  @Override
  public void onInit() {
    try {
      super.onInit();

      // Create the NPC parser word list.
      WordList.getInstance();

      // create the pathfinder thread and start it
      // pathfinderThread = new PathfinderThread(this);
      // pathfinderThread.start();

      final ZoneGroupsXMLLoader loader = new ZoneGroupsXMLLoader(new URI(
          "/data/conf/zones.xml"));

      loader.load();

      validatePortals();
      SingletonRepository.getAchievementNotifier().initialize();
      SingletonRepository.getGagManager();
      SingletonRepository.getJail();
    } catch (final Exception e) {
      logger.error("Error on Init the server.", e);
    }
  }

  /**
   * Checks for unpaired portals.
   */
  private void validatePortals() {
    for (final IRPZone zone : this) {
      for (final Portal portal : ((StendhalRPZone) zone).getPortals()) {
        validatePortal(portal);
      }
    }
  }

  @Override
  public void onFinish() {
    super.onFinish();
    new GameEvent("server system", "shutdown").raise();
    try {
      //TODO: find a more appropriate way to do this
      // give gameevents a chance to be processed;
      Thread.sleep(500);
    } catch (final InterruptedException e) {
      //do nothing
    }
   
  }

  protected void validatePortal(final Portal portal) {
    if (!portal.loaded()) {
      logger.warn(portal + " has no destination");
      return;
    }

    if (portal instanceof OneWayPortalDestination) {
      return;
    }

    final String id = portal.getDestinationZone();

    if (id == null) {
      logger.warn(portal + " has no destination zone");
      return;
    }

    final StendhalRPZone zone = getZone(id);

    if (zone == null) {
      logger.warn(portal + " has an invalid destination zone: " + id);
      return;
    }

    final Object ref = portal.getDestinationReference();

    if (ref == null) {
      logger.warn(portal + " has no destination reference");
      return;
    }

    if (zone.getPortal(ref) == null) {
      logger.warn(portal + " has an invalid destination reference: " + id
          + "[" + ref + "]");
    }
  }

  public IRPZone getRPZone(final String zone) {
    return getRPZone(new IRPZone.ID(zone));
  }

  /**
   * Finds a zone by its id.
   *
   * @param id
   *            The zone's id
   *
   * @return The matching zone, or <code>null</code> if not found.
   */
  public StendhalRPZone getZone(final String id) {
    return (StendhalRPZone) getRPZone(new IRPZone.ID(id));
  }

  /**
   * Find the zone that would contain an entity at global coordinates.
   *
   * TODO: This is likely broken for entity larger than 2x2, because parts of
   * them will exist in multiple zones (and not in collision)
   *
   * @param level
   *            The level.
   * @param wx
   *            The global X coordinate.
   * @param wy
   *            The global Y coordinate.
   * @param entity
   *            The entity.
   *
   * @return The matching zone, or <code>null</code> if not found.
   */
  public StendhalRPZone getZoneAt(final int level, final int wx, final int wy, final Entity entity) {
    for (final IRPZone izone : this) {
      final StendhalRPZone zone = (StendhalRPZone) izone;

      if (zone.isInterior()) {
        continue;
      }

      if (zone.getLevel() != level) {
        continue;
      }

      if (zone.intersects(entity.getArea(wx, wy))) {
        logger.debug("Contained at :" + zone.getID());
        return zone;
      }
    }

    return null;
  }
 
  /**
   * Adds a zone to a certain region in this world
   * @param region
   * @param zone
   */
  public void addRPZone(final String region, final StendhalRPZone zone) {
    super.addRPZone(zone);
    if(!regionMap.containsKey(region)) {
      regionMap.put(region, new HashSet<StendhalRPZone>());
    }
    regionMap.get(region).add(zone);
  }
 
  /**
   * Retrieves all zones from a specified region with the given flags
   *
   * @param region the name of the region to search for
   * @param exterior only exterior zones(true), interior zones(false) or all zones (null)
   * @param aboveGround only zones above ground(true), zones below ground(false) or all (null)
   * @param accessible use true to filter out zones that are not accessible for everyone
   * @return a list of zones
   */
  public Collection<StendhalRPZone> getAllZonesFromRegion(final String region, final Boolean exterior, final Boolean aboveGround, final Boolean accessible) {
    final Set<StendhalRPZone> zonesInRegion = new HashSet<StendhalRPZone>();
    if(regionMap.containsKey(region)) {
      zonesInRegion.addAll(regionMap.get(region));
      if(exterior != null) {
        filterOutInteriorOrExteriorZones(zonesInRegion, exterior);
      }
      if(aboveGround != null && exterior != null && exterior) {
        filterOutAboveOrBelowGround(zonesInRegion, aboveGround);
      }
      if(accessible != null) {
        filterByAccessibility(zonesInRegion, accessible);
      }
    }
    return zonesInRegion;
  }

  /**
   * Filter out exterior or interior zones from the given set
   * @param zonesInRegion the set to filter
   * @param exterior if true only exterior zones stay in the set
   */
  private void filterOutInteriorOrExteriorZones(final Set<StendhalRPZone> zonesInRegion, final Boolean exterior) {
    final Set<StendhalRPZone> removals = new HashSet<StendhalRPZone>();
    for (StendhalRPZone zone : zonesInRegion) {
      if(exterior) {
        if(zone.isInterior()) {
          removals.add(zone);
        }
      } else {
        if(!zone.isInterior()) {
          removals.add(zone);
        }
      }
    }
    zonesInRegion.removeAll(removals);
  }
 
  /**
   * Filter out zones above or below ground
   *
   * @param zonesInRegion
   * @param aboveGround
   */
  private void filterOutAboveOrBelowGround(final Set<StendhalRPZone> zonesInRegion, final Boolean aboveGround) {
    final Set<StendhalRPZone> removals = new HashSet<StendhalRPZone>();
    for (StendhalRPZone zone : zonesInRegion) {
      if(aboveGround.booleanValue()) {
        if(zone.getLevel() < 0) {
          removals.add(zone);
        }
      } else {
        if(zone.getLevel() >= 0) {
          removals.add(zone);
        }
      }
    }
    zonesInRegion.removeAll(removals);
  }

  private void filterByAccessibility(final Set<StendhalRPZone> zonesInRegion, final Boolean accessible) {
    final Set<StendhalRPZone> removals = new HashSet<StendhalRPZone>();
    for (StendhalRPZone zone : zonesInRegion) {
      boolean addToRemovals = false;
      if(accessible.booleanValue()) {
        addToRemovals = !zone.isPublicAccessible();
      } else {
        addToRemovals = zone.isPublicAccessible();
      }
      if (addToRemovals) {
        removals.add(zone);
      }
    }
    zonesInRegion.removeAll(removals);
  }

}
TOP

Related Classes of games.stendhal.server.core.engine.StendhalRPWorld

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.