From b795c411be782e36e5323b96785b9ff890f90e6e Mon Sep 17 00:00:00 2001 From: SenseiKiwi Date: Thu, 5 Sep 2013 22:43:11 -0400 Subject: [PATCH] Added Support for Missing Link Types Added functions for generating destinations for some link types that we hadn't included yet - player-made exits, trapdoors, and dungeon exits. The player-made and dungeon exits still don't generate anything, but there's a single function where we can write up the code: DDTeleporter.generateSafeExit(). Also added some simple code for listing root dimensions in PocketManager. None of this has been tested yet! --- .../mod_pocketDim/core/DDTeleporter.java | 99 +++++++++++++++---- .../mod_pocketDim/core/PocketManager.java | 17 ++++ 2 files changed, 99 insertions(+), 17 deletions(-) diff --git a/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java b/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java index 57c1dcd..c0d9b37 100644 --- a/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java +++ b/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java @@ -25,6 +25,7 @@ import cpw.mods.fml.common.registry.GameRegistry; public class DDTeleporter { private static final Random random = new Random(); + private static int END_DIMENSION_ID = 1; public static int cooldown = 0; private DDTeleporter() { } @@ -342,7 +343,7 @@ public class DDTeleporter if (link.linkType() == LinkTypes.RANDOM) { - Point4D randomDestination = prepareRandomDestination(); + Point4D randomDestination = getRandomDestination(); if (randomDestination != null) { entity = teleportEntity(entity, randomDestination); @@ -358,16 +359,16 @@ public class DDTeleporter private static boolean initializeDestination(DimLink link, DDProperties properties) { - //FIXME: Change this later to support rooms that have been wiped and must be regenerated. - //We might need to implement regeneration for REVERSE links as well. + // FIXME: Change this later to support rooms that have been wiped and must be regenerated. + // FIXME: Add code for restoring the destination-side door. + // We might need to implement regeneration for REVERSE links as well. + if (link.hasDestination()) { return true; } - //Check the destination type and respond accordingly - //FIXME: Add missing link types. - //FIXME: Add code for restoring the destination-side door. + // Check the destination type and respond accordingly switch (link.linkType()) { case LinkTypes.DUNGEON: @@ -375,10 +376,11 @@ public class DDTeleporter case LinkTypes.POCKET: return PocketBuilder.generateNewPocket(link, properties); case LinkTypes.SAFE_EXIT: + return generateSafeExit(link, properties); case LinkTypes.DUNGEON_EXIT: - return ; + return generateDungeonExit(link, properties); case LinkTypes.UNSAFE_EXIT: - return ; + return generateUnsafeExit(link); case LinkTypes.NORMAL: case LinkTypes.REVERSE: case LinkTypes.RANDOM: @@ -387,8 +389,8 @@ public class DDTeleporter throw new IllegalArgumentException("link has an unrecognized link type."); } } - - private static Point4D prepareRandomDestination() + + private static Point4D getRandomDestination() { // Our aim is to return a random link's source point // so that a link of type RANDOM can teleport a player there. @@ -397,17 +399,17 @@ public class DDTeleporter // 1. Ignore links with their source inside a pocket dimension. // 2. Ignore links with link type RANDOM. + // Iterate over the root dimensions. Pocket dimensions cannot be roots. + // Don't just pick a random root and a random link within that root + // because we want to have unbiased selection among all links. ArrayList matches = new ArrayList(); - for (NewDimData dimension : PocketManager.getDimensions()) + for (NewDimData dimension : PocketManager.getRootDimensions()) { - if (!dimension.isPocketDimension()) + for (DimLink link : dimension.getAllLinks()) { - for (DimLink link : dimension.getAllLinks()) + if (link.linkType() != LinkTypes.RANDOM) { - if (link.linkType() != LinkTypes.RANDOM) - { - matches.add(link.source()); - } + matches.add(link.source()); } } } @@ -422,4 +424,67 @@ public class DDTeleporter return null; } } + + private static boolean generateUnsafeExit(DimLink link) + { + // An unsafe exit teleports the user to exactly the same coordinates + // as the link source, except located at the dimension's root dimension. + // This is very risky, as we make no effort to clear an air pocket or + // place a platform at the destination. We also don't place a reverse + // link at the destination, so it's a one-way trip. Good luck! + + // To avoid loops, don't generate a destination if the player is + // already in a non-pocket dimension. + + NewDimData current = PocketManager.getDimensionData(link.source.getDimension()); + if (current.isPocketDimension()) + { + Point4D source = link.source(); + current.root().setDestination(link, source.getX(), source.getY(), source.getZ()); + return true; + } + else + { + return false; + } + } + + private static boolean generateSafeExit(DimLink link, DDProperties properties) + { + NewDimData current = PocketManager.getDimensionData(link.source.getDimension()); + return generateSafeExit(current.root(), link, properties); + } + + private static boolean generateDungeonExit(DimLink link, DDProperties properties) + { + // A dungeon exit acts the same as a safe exit, but has the chance of + // taking the user to any non-pocket dimension, excluding Limbo and The End. + + ArrayList roots = PocketManager.getRootDimensions(); + for (int attempts = 0; attempts < 10; attempts++) + { + NewDimData selection = roots.get( random.nextInt(roots.size()) ); + if (selection.id() != END_DIMENSION_ID && selection.id() != properties.LimboDimensionID) + { + return generateSafeExit(selection, link, properties); + } + } + return false; + } + + private static boolean generateSafeExit(NewDimData target, DimLink link, DDProperties properties) + { + // A safe exit attempts to place a Warp Door in a dimension with + // some precautions to protect the player. The X and Z coordinates + // are fixed to match the source, but the Y coordinate is chosen by + // searching for a safe location to place the door. The direction of + // the vertical search is away from the map boundary closest to + // the source Y. In other words, if a player is really high up, the + // search proceeds down. If a player is near the bottom of the map, + // the search proceeds up. If a safe destination cannot be found, + // then we return false and the source-side door slams shut. + + // FIXME: Add code here! + return false; + } } diff --git a/StevenDimDoors/mod_pocketDim/core/PocketManager.java b/StevenDimDoors/mod_pocketDim/core/PocketManager.java index 105843b..eda8947 100644 --- a/StevenDimDoors/mod_pocketDim/core/PocketManager.java +++ b/StevenDimDoors/mod_pocketDim/core/PocketManager.java @@ -4,6 +4,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import net.minecraft.world.World; @@ -97,6 +98,7 @@ public class PocketManager private static volatile boolean isSaving = false; private static final UpdateWatcherProxy linkWatcher = new UpdateWatcherProxy(); private static final UpdateWatcherProxy dimWatcher = new UpdateWatcherProxy(); + private static ArrayList rootDimensions = null; //HashMap that maps all the dimension IDs registered with DimDoors to their DD data. private static HashMap dimensionData = null; @@ -123,6 +125,7 @@ public class PocketManager isLoading = true; dimensionData = new HashMap(); + rootDimensions = new ArrayList(); //Register Limbo DDProperties properties = DDProperties.instance(); @@ -326,6 +329,10 @@ public class PocketManager InnerDimData dimension = new InnerDimData(dimensionID, parent, isPocket, isDungeon, linkWatcher); dimensionData.put(dimensionID, dimension); + if (!dimension.isPocketDimension()) + { + rootDimensions.add(dimension); + } dimWatcher.onCreated(new ClientDimData(dimension)); return dimension; @@ -336,6 +343,9 @@ public class PocketManager // No need to raise events here since this code should only run on the client side // getDimensionData() always handles root dimensions properly, even if the weren't defined before + // SenseiKiwi: I'm a little worried about how getDimensionData will raise + // an event when it creates any root dimensions... Needs checking later. + InnerDimData root = (InnerDimData) getDimensionData(rootID); InnerDimData dimension; @@ -381,6 +391,12 @@ public class PocketManager return dimensionData.values(); } + @SuppressWarnings("unchecked") + public static ArrayList getRootDimensions() + { + return (ArrayList) rootDimensions.clone(); + } + public static void unload() { if (!isLoaded) @@ -391,6 +407,7 @@ public class PocketManager save(); unregisterPockets(); dimensionData = null; + rootDimensions = null; isLoaded = false; }