package net.alcuria.umbracraft.engine; import net.alcuria.umbracraft.Game; import net.alcuria.umbracraft.definitions.area.AreaDefinition; import net.alcuria.umbracraft.definitions.area.AreaNodeDefinition; import net.alcuria.umbracraft.definitions.map.TeleportDefinition.TeleportDirection; import net.alcuria.umbracraft.engine.entities.Entity; import net.alcuria.umbracraft.engine.entities.EntityManager.EntityScope; /** Builds areas/maps from the definitions for use in the engine. * @author Andrew Keturi */ public class AreaBuilder { private String currentArea, currentNode; /** Changes a node, updating the current map. Does not check if the direction * is valid. * @param direction */ public void changeNode(TeleportDirection direction) { final AreaDefinition area = Game.db().area(currentArea); if (area.root == null || area.root.teleport == null) { throw new NullPointerException("Area does not have node/teleports"); } final AreaNodeDefinition currentNodeDefinition = area.find(area.root, currentNode); String adjacentNodeName = currentNodeDefinition.teleport.adjacentMaps.get(direction.toString()); AreaNodeDefinition adjacentNode = null; if (adjacentNodeName == null) { // no adjacent maps, but we need a reference to the parent here to see if teleporting back is possible final AreaNodeDefinition parentDefinition = area.findParent(area.root, currentNode); final String adjacentOppositeNode = parentDefinition.teleport.adjacentMaps.get(direction.opposite().toString()); if (adjacentOppositeNode != null && adjacentOppositeNode.equals(currentNode)) { adjacentNode = area.find(area.root, parentDefinition.name); adjacentNodeName = parentDefinition.name; } else { throw new NullPointerException("Adjacent node " + adjacentNodeName + " could not be found in tree " + area.root.name); } } else { // teleport found in children so go for that adjacentNode = area.find(area.root, adjacentNodeName); } // create the map, get the starting coordinates Game.map().create(adjacentNode.mapDefinition); int newX = 0, newY = 0; switch (direction) { case EAST: newX = Game.db().map(adjacentNode.mapDefinition).westX * 16 + 12; newY = Game.db().map(adjacentNode.mapDefinition).westY * 16; break; case SOUTH: newX = Game.db().map(adjacentNode.mapDefinition).northX * 16; newY = Game.db().map(adjacentNode.mapDefinition).northY * 16 - 12; break; case NORTH: newX = Game.db().map(adjacentNode.mapDefinition).southX * 16; newY = Game.db().map(adjacentNode.mapDefinition).southY * 16 + 12; break; case WEST: newX = Game.db().map(adjacentNode.mapDefinition).eastX * 16 - 12; newY = Game.db().map(adjacentNode.mapDefinition).eastY * 16; break; } // add all map-specific entities to the map Game.entities().dispose(EntityScope.MAP); Game.entities().create(EntityScope.MAP, adjacentNode.mapDefinition); // set the player to his new position final Entity player = Game.entities().find(Entity.PLAYER); if (player != null) { player.position.set(newX, newY, player.position.z); } setAreaAndNode(currentArea, adjacentNodeName); //FIXME: area changes? } public void dispose() { } /** @return the current {@link AreaDefinition} id */ public String getArea() { return currentArea; } /** @return the current {@link AreaNodeDefinition} id */ public String getNode() { return currentNode; } /** Determines if from the current node the player is able to teleport in a * particular direction. * @param direction the {@link TeleportDirection} the player is trying to * teleport to * @return <code>true</code> if a direction exists. */ public boolean hasTeleportAt(TeleportDirection direction) { final AreaDefinition area = Game.db().area(currentArea); if (area.root == null || area.root.teleport == null) { return false; // no root } final AreaNodeDefinition currentNodeDefinition = area.find(area.root, currentNode); final String adjacentNodeName = currentNodeDefinition.teleport.adjacentMaps.get(direction.toString()); if (adjacentNodeName == null) { // no adjacent maps, but we need a reference to the parent here to see if teleporting back is possible final AreaNodeDefinition parentDefinition = area.findParent(area.root, currentNode); if (parentDefinition != null && parentDefinition.teleport != null && parentDefinition.teleport.adjacentMaps != null) { final String adjacentOppositeNode = parentDefinition.teleport.adjacentMaps.get(direction.opposite().toString()); if (adjacentOppositeNode != null && adjacentOppositeNode.equals(currentNode)) { return true; // teleport found! } else { return false; // no node found coming from parent, no path } } return false; } return true; // has a standard teleport to children } /** Updates the current area and node * @param area * @param node */ public void setAreaAndNode(String area, String node) { currentArea = area; currentNode = node; } }