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!
This commit is contained in:
SenseiKiwi 2013-09-05 22:43:11 -04:00
parent 03660699cf
commit b795c411be
2 changed files with 99 additions and 17 deletions

View file

@ -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<Point4D> matches = new ArrayList<Point4D>();
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<NewDimData> 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;
}
}

View file

@ -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<Point4D> linkWatcher = new UpdateWatcherProxy<Point4D>();
private static final UpdateWatcherProxy<ClientDimData> dimWatcher = new UpdateWatcherProxy<ClientDimData>();
private static ArrayList<NewDimData> rootDimensions = null;
//HashMap that maps all the dimension IDs registered with DimDoors to their DD data.
private static HashMap<Integer, InnerDimData> dimensionData = null;
@ -123,6 +125,7 @@ public class PocketManager
isLoading = true;
dimensionData = new HashMap<Integer, InnerDimData>();
rootDimensions = new ArrayList<NewDimData>();
//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<NewDimData> getRootDimensions()
{
return (ArrayList<NewDimData>) rootDimensions.clone();
}
public static void unload()
{
if (!isLoaded)
@ -391,6 +407,7 @@ public class PocketManager
save();
unregisterPockets();
dimensionData = null;
rootDimensions = null;
isLoaded = false;
}