Progress on Rewrite

Completed exit door code. Also fixed noise calculation for dungeon door
destinations - we were attempting to use pack depth in the calculation
before it had been initialized.
This commit is contained in:
SenseiKiwi
2013-09-07 12:27:28 -04:00
parent 06c90572f1
commit 07a5e2a64d
4 changed files with 164 additions and 64 deletions

View File

@@ -30,7 +30,11 @@ import cpw.mods.fml.common.registry.GameRegistry;
public class DDTeleporter public class DDTeleporter
{ {
private static final Random random = new Random(); private static final Random random = new Random();
private static int END_DIMENSION_ID = 1; private static final int END_DIMENSION_ID = 1;
private static final int MAX_ROOT_SHIFT_CHANCE = 100;
private static final int START_ROOT_SHIFT_CHANCE = 0;
private static final int ROOT_SHIFT_CHANCE_PER_LEVEL = 5;
public static int cooldown = 0; public static int cooldown = 0;
private DDTeleporter() { } private DDTeleporter() { }
@@ -465,16 +469,26 @@ public class DDTeleporter
// A dungeon exit acts the same as a safe exit, but has the chance of // 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. // taking the user to any non-pocket dimension, excluding Limbo and The End.
NewDimData current = PocketManager.getDimensionData(link.source.getDimension());
ArrayList<NewDimData> roots = PocketManager.getRootDimensions(); ArrayList<NewDimData> roots = PocketManager.getRootDimensions();
for (int attempts = 0; attempts < 10; attempts++) int shiftChance = START_ROOT_SHIFT_CHANCE + ROOT_SHIFT_CHANCE_PER_LEVEL * (current.packDepth() - 1);
if (random.nextInt(MAX_ROOT_SHIFT_CHANCE) < shiftChance)
{ {
NewDimData selection = roots.get( random.nextInt(roots.size()) ); for (int attempts = 0; attempts < 10; attempts++)
if (selection.id() != END_DIMENSION_ID && selection.id() != properties.LimboDimensionID)
{ {
return generateSafeExit(selection, link, properties); NewDimData selection = roots.get( random.nextInt(roots.size()) );
if (selection.id() != END_DIMENSION_ID &&
selection.id() != properties.LimboDimensionID &&
selection != current.root())
{
return generateSafeExit(selection, link, properties);
}
} }
} }
return false;
// Yes, this could lead you back into Limbo. That's intentional.
return generateSafeExit(current.root(), link, properties);
} }
private static boolean generateSafeExit(NewDimData destinationDim, DimLink link, DDProperties properties) private static boolean generateSafeExit(NewDimData destinationDim, DimLink link, DDProperties properties)
@@ -482,16 +496,9 @@ public class DDTeleporter
// A safe exit attempts to place a Warp Door in a dimension with // A safe exit attempts to place a Warp Door in a dimension with
// some precautions to protect the player. The X and Z coordinates // some precautions to protect the player. The X and Z coordinates
// are fixed to match the source (mostly - may be shifted a little), // are fixed to match the source (mostly - may be shifted a little),
// but the Y coordinate is chosen by searching for a safe location // but the Y coordinate is chosen by searching for the nearest
// to place the door. // 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 goes down. If a player is near the bottom
// of the map, the search goes up. If a safe destination cannot be
// found, then we return false and the source-side door slams shut.
Point3D destination;
Point4D source = link.source(); Point4D source = link.source();
World world = PocketManager.loadDimension(destinationDim.id()); World world = PocketManager.loadDimension(destinationDim.id());
if (world == null) if (world == null)
@@ -499,11 +506,26 @@ public class DDTeleporter
return false; return false;
} }
boolean searchDown = (source.getY() >= world.getActualHeight() / 2); int startY = source.getY() - 2;
destination = yCoordHelper.findSafeCube(world, source.getX(), source.getY() - 2, source.getZ(), searchDown); Point3D destination;
if (destination == null) Point3D locationUp = yCoordHelper.findSafeCubeUp(world, source.getX(), startY, source.getZ());
Point3D locationDown = yCoordHelper.findSafeCubeDown(world, source.getX(), startY, source.getZ());
if (locationUp == null)
{ {
destination = yCoordHelper.findSafeCube(world, source.getX(), source.getY() - 2, source.getZ(), !searchDown); destination = locationDown;
}
else if (locationDown == null)
{
destination = locationUp;
}
else if (locationUp.getY() - startY <= startY - locationDown.getY())
{
destination = locationUp;
}
else
{
destination = locationDown;
} }
if (destination != null) if (destination != null)
{ {

View File

@@ -447,7 +447,7 @@ public abstract class NewDimData
this.packDepth = calculatePackDepth(parent, dungeon); this.packDepth = calculatePackDepth(parent, dungeon);
} }
private static int calculatePackDepth(NewDimData parent, DungeonData current) public static int calculatePackDepth(NewDimData parent, DungeonData current)
{ {
DungeonData predecessor = parent.dungeon(); DungeonData predecessor = parent.dungeon();
if (current == null) if (current == null)

View File

@@ -5,6 +5,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.util.MathHelper; import net.minecraft.util.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import StevenDimDoors.mod_pocketDim.Point3D; import StevenDimDoors.mod_pocketDim.Point3D;
public class yCoordHelper public class yCoordHelper
@@ -70,7 +71,7 @@ public class yCoordHelper
return (material.isLiquid() || !material.isReplaceable()); return (material.isLiquid() || !material.isReplaceable());
} }
public static Point3D findSafeCube(World world, int x, int startY, int z, boolean searchDown) public static Point3D findSafeCubeUp(World world, int x, int startY, int z)
{ {
// Search for a 3x3x3 cube of air with blocks underneath // Search for a 3x3x3 cube of air with blocks underneath
// We can also match against a 3x2x3 box with // We can also match against a 3x2x3 box with
@@ -84,62 +85,139 @@ public class yCoordHelper
localX = MathHelper.clamp_int(localX, 1, 14); localX = MathHelper.clamp_int(localX, 1, 14);
localZ = MathHelper.clamp_int(localZ, 1, 14); localZ = MathHelper.clamp_int(localZ, 1, 14);
Chunk chunk = world.getChunkProvider().loadChunk(x >> 4, z >> 4); Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4);
int layers = 0;
int height = world.getActualHeight(); int height = world.getActualHeight();
int y, dx, dz, blockID; int y, dx, dz, blockID;
boolean filled; boolean isSafe;
Block block; Block block;
Point3D location = null;
// Initialize layers to a huge negative number so that we won't
if (searchDown) // consider an area as usable unless it gets reset to 0 first
// when we find a foundation upon which to build.
int layers = -1000000;
// Check if a 3x3 layer of blocks is empty
// If we find a layer that contains replaceable blocks, it can
// serve as the base where we'll place the player and door.
for (y = Math.max(startY - 1, 0); y < height; y++)
{ {
/*for (y = startY; y >= 0; y--) isSafe = true;
for (dx = -1; dx <= 1 && isSafe; dx++)
{ {
blockID = chunk.getBlockID(localX, y, localZ); for (dz = -1; dz <= 1 && isSafe; dz++)
}*/
}
else
{
// Check if a 3x3 layer of blocks is empty
// If we find a layer that contains replaceable blocks, it can
// serve as the base where we'll place the player and door.
for (y = Math.max(startY, 0); y < height; y++)
{
filled = false;
for (dx = -1; dx <= 1 && !filled; dx++)
{ {
for (dz = -1; dz <= 1 && !filled; dz++) blockID = chunk.getBlockID(localX + dx, y, localZ + dz);
if (blockID != 0)
{ {
blockID = chunk.getBlockID(localX + dx, y, localZ + dz); block = Block.blocksList[blockID];
if (blockID != 0) if (!block.blockMaterial.isReplaceable())
{ {
block = Block.blocksList[blockID]; isSafe = false;
if (block != null && !block.blockMaterial.isReplaceable())
{
filled = true;
}
layers = 0;
} }
} layers = 0;
}
if (!filled)
{
layers++;
if (layers == 3)
{
location = new Point3D(localX + cornerX, y - 2, localZ + cornerZ);
break;
} }
} }
} }
if (isSafe)
{
layers++;
if (layers == 3)
{
return new Point3D(localX + cornerX, y - 2, localZ + cornerZ);
}
}
} }
return null;
return location;
} }
public static Point3D findSafeCubeDown(World world, int x, int startY, int z)
{
// Search for a 3x3x3 cube of air with blocks underneath
// We can also match against a 3x2x3 box with
// We shift the search area into the bounds of a chunk for the sake of simplicity,
// so that we don't need to worry about working across chunks.
int localX = x < 0 ? (x % 16) + 16 : (x % 16);
int localZ = z < 0 ? (z % 16) + 16 : (z % 16);
int cornerX = x - localX;
int cornerZ = z - localZ;
localX = MathHelper.clamp_int(localX, 1, 14);
localZ = MathHelper.clamp_int(localZ, 1, 14);
Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4);
int height = world.getActualHeight();
int y, dx, dz, blockID;
boolean isSafe;
boolean hasBlocks;
Block block;
int layers = 0;
// Check if a 3x3 layer of blocks is empty
// If we find a layer that contains replaceable blocks, it can
// serve as the base where we'll place the player and door.
for (y = Math.min(startY + 2, height - 1); y >= 0; y--)
{
isSafe = true;
hasBlocks = false;
for (dx = -1; dx <= 1 && isSafe; dx++)
{
for (dz = -1; dz <= 1 && isSafe; dz++)
{
blockID = chunk.getBlockID(localX + dx, y, localZ + dz);
if (blockID != 0)
{
block = Block.blocksList[blockID];
if (!block.blockMaterial.isReplaceable())
{
if (layers >= 3)
{
return new Point3D(localX + cornerX, y + 1, localZ + cornerZ);
}
isSafe = false;
}
hasBlocks = true;
}
}
}
if (isSafe)
{
layers++;
if (hasBlocks)
{
if (layers >= 3)
{
return new Point3D(localX + cornerX, y, localZ + cornerZ);
}
layers = 0;
}
}
}
return null;
}
private static Chunk initializeChunkArea(World world, int chunkX, int chunkZ)
{
// We initialize a 3x3 area of chunks instead of just initializing
// the target chunk because things generated in adjacent chunks
// (e.g. trees) might intrude into the target chunk.
IChunkProvider provider = world.getChunkProvider();
Chunk target = provider.loadChunk(chunkX, chunkZ);
for (int dx = -1; dx <= 1; dx++)
{
for (int dz = -1; dz <= 1; dz++)
{
if (!provider.chunkExists(chunkX + dx, chunkZ + dz))
{
provider.loadChunk(chunkX, chunkZ);
}
}
}
return target;
}
public static int adjustDestinationY(int y, int worldHeight, int entranceY, int dungeonHeight) public static int adjustDestinationY(int y, int worldHeight, int entranceY, int dungeonHeight)
{ {
//The goal here is to guarantee that the dungeon fits within the vertical bounds //The goal here is to guarantee that the dungeon fits within the vertical bounds

View File

@@ -87,7 +87,7 @@ public class PocketBuilder
if (packConfig != null && packConfig.doDistortDoorCoordinates()) if (packConfig != null && packConfig.doDistortDoorCoordinates())
{ {
destination = calculateNoisyDestination(source, dimension, orientation); destination = calculateNoisyDestination(source, dimension, dungeon, orientation);
} }
else else
{ {
@@ -111,9 +111,9 @@ public class PocketBuilder
} }
} }
private static Point3D calculateNoisyDestination(Point4D source, NewDimData dimension, int orientation) private static Point3D calculateNoisyDestination(Point4D source, NewDimData dimension, DungeonData dungeon, int orientation)
{ {
int depth = dimension.packDepth(); int depth = NewDimData.calculatePackDepth(dimension.parent(), dungeon);
int forwardNoise = MathHelper.getRandomIntegerInRange(random, -50 * depth, 150 * depth); int forwardNoise = MathHelper.getRandomIntegerInRange(random, -50 * depth, 150 * depth);
int sidewaysNoise = MathHelper.getRandomIntegerInRange(random, -10 * depth, 10 * depth); int sidewaysNoise = MathHelper.getRandomIntegerInRange(random, -10 * depth, 10 * depth);