Progress on Rewrite #86
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user