Progress on Rewrite #86

Merged
SenseiKiwi merged 6 commits from rewrite into DevBranch 2013-09-08 00:22:04 +00:00
4 changed files with 164 additions and 64 deletions
Showing only changes of commit 07a5e2a64d - Show all commits

View File

@@ -30,7 +30,11 @@ import cpw.mods.fml.common.registry.GameRegistry;
public class DDTeleporter
{
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;
private DDTeleporter() { }
@@ -465,16 +469,26 @@ public class DDTeleporter
// 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.
NewDimData current = PocketManager.getDimensionData(link.source.getDimension());
ArrayList<NewDimData> roots = PocketManager.getRootDimensions();
int shiftChance = START_ROOT_SHIFT_CHANCE + ROOT_SHIFT_CHANCE_PER_LEVEL * (current.packDepth() - 1);
if (random.nextInt(MAX_ROOT_SHIFT_CHANCE) < shiftChance)
{
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)
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)
@@ -482,16 +496,9 @@ public class DDTeleporter
// 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 (mostly - may be shifted a little),
// but the Y coordinate is chosen by searching for a safe location
// to place the door.
// but the Y coordinate is chosen by searching for the nearest
// 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();
World world = PocketManager.loadDimension(destinationDim.id());
if (world == null)
@@ -499,11 +506,26 @@ public class DDTeleporter
return false;
}
boolean searchDown = (source.getY() >= world.getActualHeight() / 2);
destination = yCoordHelper.findSafeCube(world, source.getX(), source.getY() - 2, source.getZ(), searchDown);
if (destination == null)
int startY = source.getY() - 2;
Point3D destination;
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)
{

View File

@@ -447,7 +447,7 @@ public abstract class NewDimData
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();
if (current == null)

View File

@@ -5,6 +5,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import StevenDimDoors.mod_pocketDim.Point3D;
public class yCoordHelper
@@ -70,7 +71,7 @@ public class yCoordHelper
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
// We can also match against a 3x2x3 box with
@@ -84,60 +85,137 @@ public class yCoordHelper
localX = MathHelper.clamp_int(localX, 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 y, dx, dz, blockID;
boolean filled;
boolean isSafe;
Block block;
Point3D location = null;
if (searchDown)
{
/*for (y = startY; y >= 0; y--)
{
blockID = chunk.getBlockID(localX, y, localZ);
// Initialize layers to a huge negative number so that we won't
// consider an area as usable unless it gets reset to 0 first
// when we find a foundation upon which to build.
int layers = -1000000;
}*/
}
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++)
for (y = Math.max(startY - 1, 0); y < height; y++)
{
filled = false;
for (dx = -1; dx <= 1 && !filled; dx++)
isSafe = true;
for (dx = -1; dx <= 1 && isSafe; dx++)
{
for (dz = -1; dz <= 1 && !filled; dz++)
for (dz = -1; dz <= 1 && isSafe; dz++)
{
blockID = chunk.getBlockID(localX + dx, y, localZ + dz);
if (blockID != 0)
{
block = Block.blocksList[blockID];
if (block != null && !block.blockMaterial.isReplaceable())
if (!block.blockMaterial.isReplaceable())
{
filled = true;
isSafe = false;
}
layers = 0;
}
}
}
if (!filled)
if (isSafe)
{
layers++;
if (layers == 3)
{
location = new Point3D(localX + cornerX, y - 2, localZ + cornerZ);
break;
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)

View File

@@ -87,7 +87,7 @@ public class PocketBuilder
if (packConfig != null && packConfig.doDistortDoorCoordinates())
{
destination = calculateNoisyDestination(source, dimension, orientation);
destination = calculateNoisyDestination(source, dimension, dungeon, orientation);
}
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 sidewaysNoise = MathHelper.getRandomIntegerInRange(random, -10 * depth, 10 * depth);