Added First Step of Maze Generation

Added classes for generating maze dungeons. At the moment, the dungeons
are generated in place of our pocket dimensions to make testing easy.
We'll need to restore pocket generation later and integrate the mazes
into the dungeon packs later. Currently, the structures are very
incomplete (they don't even have doorways), but this is only the first
step.
This commit is contained in:
SenseiKiwi 2013-12-26 15:29:20 -04:00
parent 72196c6afd
commit 820e72f17a
3 changed files with 282 additions and 0 deletions

View file

@ -0,0 +1,172 @@
package StevenDimDoors.experimental;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import StevenDimDoors.mod_pocketDim.Point3D;
public class MazeGenerator
{
public static final int ROOT_WIDTH = 40;
public static final int ROOT_LENGTH = 40;
public static final int ROOT_HEIGHT = 19;
private static final int MIN_HEIGHT = 4;
private static final int MIN_SIDE = 3;
private static final int SPLIT_COUNT = 8;
private MazeGenerator() { }
public static void generate(World world, int x, int y, int z, Random random)
{
SpatialNode root = partitionRooms(ROOT_WIDTH, ROOT_HEIGHT, ROOT_LENGTH, SPLIT_COUNT, random);
buildRooms(root, world, new Point3D(x - ROOT_WIDTH / 2, y - ROOT_HEIGHT - 1, z - ROOT_WIDTH / 2));
}
private static SpatialNode partitionRooms(int width, int height, int length, int maxLevels, Random random)
{
SpatialNode root = new SpatialNode(width, height, length);
splitByRandomX(root, maxLevels, random);
return root;
}
private static void splitByRandomX(SpatialNode node, int levels, Random random)
{
if (node.width() >= 2 * MIN_SIDE)
{
node.splitByX(MathHelper.getRandomIntegerInRange(random,
node.minCorner().getX() + MIN_SIDE, node.maxCorner().getX() - MIN_SIDE + 1));
if (levels > 1)
{
splitByRandomZ(node.leftChild(), levels - 1, random);
splitByRandomZ(node.rightChild(), levels - 1, random);
}
}
else if (levels > 1)
{
splitByRandomZ(node, levels - 1, random);
}
}
private static void splitByRandomZ(SpatialNode node, int levels, Random random)
{
if (node.length() >= 2 * MIN_SIDE)
{
node.splitByZ(MathHelper.getRandomIntegerInRange(random,
node.minCorner().getZ() + MIN_SIDE, node.maxCorner().getZ() - MIN_SIDE + 1));
if (levels > 1)
{
splitByRandomY(node.leftChild(), levels - 1, random);
splitByRandomY(node.rightChild(), levels - 1, random);
}
}
else if (levels > 1)
{
splitByRandomY(node, levels - 1, random);
}
}
private static void splitByRandomY(SpatialNode node, int levels, Random random)
{
if (node.height() >= 2 * MIN_HEIGHT)
{
node.splitByY(MathHelper.getRandomIntegerInRange(random,
node.minCorner().getY() + MIN_HEIGHT, node.maxCorner().getY() - MIN_HEIGHT + 1));
if (levels > 1)
{
splitByRandomX(node.leftChild(), levels - 1, random);
splitByRandomX(node.rightChild(), levels - 1, random);
}
}
else if (levels > 1)
{
splitByRandomX(node, levels - 1, random);
}
}
private static void buildRooms(SpatialNode node, World world, Point3D offset)
{
if (node.isLeaf())
{
buildBox(world, offset, node.minCorner(), node.maxCorner());
}
else
{
buildRooms(node.leftChild(), world, offset);
buildRooms(node.rightChild(), world, offset);
}
}
private static void buildBox(World world, Point3D offset, Point3D minCorner, Point3D maxCorner)
{
int minX = minCorner.getX() + offset.getX();
int minY = minCorner.getY() + offset.getY();
int minZ = minCorner.getZ() + offset.getZ();
int maxX = maxCorner.getX() + offset.getX();
int maxY = maxCorner.getY() + offset.getY();
int maxZ = maxCorner.getZ() + offset.getZ();
int x, y, z;
int blockID = Block.stoneBrick.blockID;
for (x = minX; x <= maxX; x++)
{
for (z = minZ; z <= maxZ; z++)
{
setBlockDirectly(world, x, minY, z, blockID, 0);
setBlockDirectly(world, x, maxY, z, blockID, 0);
}
}
for (x = minX; x <= maxX; x++)
{
for (y = minY; y <= maxY; y++)
{
setBlockDirectly(world, x, y, minZ, blockID, 0);
setBlockDirectly(world, x, y, maxZ, blockID, 0);
}
}
for (z = minZ; z <= maxZ; z++)
{
for (y = minY; y <= maxY; y++)
{
setBlockDirectly(world, minX, y, z, blockID, 0);
setBlockDirectly(world, maxX, y, z, blockID, 0);
}
}
}
private static void setBlockDirectly(World world, int x, int y, int z, int blockID, int metadata)
{
if (blockID != 0 && Block.blocksList[blockID] == null)
{
return;
}
int cX = x >> 4;
int cZ = z >> 4;
int cY = y >> 4;
Chunk chunk;
int localX = (x % 16) < 0 ? (x % 16) + 16 : (x % 16);
int localZ = (z % 16) < 0 ? (z % 16) + 16 : (z % 16);
ExtendedBlockStorage extBlockStorage;
chunk = world.getChunkFromChunkCoords(cX, cZ);
extBlockStorage = chunk.getBlockStorageArray()[cY];
if (extBlockStorage == null)
{
extBlockStorage = new ExtendedBlockStorage(cY << 4, !world.provider.hasNoSky);
chunk.getBlockStorageArray()[cY] = extBlockStorage;
}
extBlockStorage.setExtBlockID(localX, y & 15, localZ, blockID);
extBlockStorage.setExtBlockMetadata(localX, y & 15, localZ, metadata);
}
}

View file

@ -0,0 +1,105 @@
package StevenDimDoors.experimental;
import StevenDimDoors.mod_pocketDim.Point3D;
public class SpatialNode
{
private Point3D minCorner;
private Point3D maxCorner;
private SpatialNode leftChild = null;
private SpatialNode rightChild = null;
public SpatialNode(int width, int height, int length)
{
minCorner = new Point3D(0, 0, 0);
maxCorner = new Point3D(width - 1, height - 1, length - 1);
}
private SpatialNode(Point3D minCorner, Point3D maxCorner)
{
this.minCorner = minCorner;
this.maxCorner = maxCorner;
}
public int width()
{
return (maxCorner.getX() - minCorner.getX() + 1);
}
public int height()
{
return (maxCorner.getY() - minCorner.getY() + 1);
}
public int length()
{
return (maxCorner.getZ() - minCorner.getZ() + 1);
}
public boolean isLeaf()
{
return (leftChild == null);
}
public SpatialNode leftChild()
{
return leftChild;
}
public SpatialNode rightChild()
{
return rightChild;
}
public Point3D minCorner()
{
return minCorner;
}
public Point3D maxCorner()
{
return maxCorner;
}
public void splitByX(int rightStart)
{
if (leftChild != null)
{
throw new IllegalStateException("This node has already been split.");
}
if (rightStart <= minCorner.getX() || rightStart > maxCorner.getX())
{
throw new IllegalArgumentException("The specified cutting plane is invalid.");
}
leftChild = new SpatialNode(minCorner, new Point3D(rightStart - 1, maxCorner.getY(), maxCorner.getZ()));
rightChild = new SpatialNode(new Point3D(rightStart, minCorner.getY(), minCorner.getZ()), maxCorner);
}
public void splitByY(int rightStart)
{
if (leftChild != null)
{
throw new IllegalStateException("This node has already been split.");
}
if (rightStart <= minCorner.getY() || rightStart > maxCorner.getY())
{
throw new IllegalArgumentException("The specified cutting plane is invalid.");
}
leftChild = new SpatialNode(minCorner, new Point3D(maxCorner.getX(), rightStart - 1, maxCorner.getZ()));
rightChild = new SpatialNode(new Point3D(minCorner.getX(), rightStart, minCorner.getZ()), maxCorner);
}
public void splitByZ(int rightStart)
{
if (leftChild != null)
{
throw new IllegalStateException("This node has already been split.");
}
if (rightStart <= minCorner.getZ() || rightStart > maxCorner.getZ())
{
throw new IllegalArgumentException("The specified cutting plane is invalid.");
}
leftChild = new SpatialNode(minCorner, new Point3D(maxCorner.getX(), maxCorner.getY(), rightStart - 1));
rightChild = new SpatialNode(new Point3D(minCorner.getX(), minCorner.getY(), rightStart), maxCorner);
}
}

View file

@ -8,6 +8,7 @@ import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraftforge.common.DimensionManager;
import StevenDimDoors.experimental.MazeGenerator;
import StevenDimDoors.mod_pocketDim.DDProperties;
import StevenDimDoors.mod_pocketDim.Point3D;
import StevenDimDoors.mod_pocketDim.blocks.IDimDoor;
@ -472,6 +473,7 @@ public class PocketBuilder
Point3D door = new Point3D(x, y, z);
BlockRotator.transformPoint(center, door, orientation - BlockRotator.EAST_DOOR_METADATA, door);
/*
//Build the outer layer of Eternal Fabric
buildBox(world, center.getX(), center.getY(), center.getZ(), (size / 2), properties.PermaFabricBlockID, false, 0);
@ -481,6 +483,9 @@ public class PocketBuilder
buildBox(world, center.getX(), center.getY(), center.getZ(), (size / 2) - layer, properties.FabricBlockID,
layer < (wallThickness - 1) && properties.TNFREAKINGT_Enabled, properties.NonTntWeight);
}
*/
MazeGenerator.generate(world, x, y, z, random);
//Build the door
int doorOrientation = BlockRotator.transformMetadata(BlockRotator.EAST_DOOR_METADATA, orientation - BlockRotator.EAST_DOOR_METADATA + 2, properties.DimensionalDoorID);