diff --git a/src/main/java/StevenDimDoors/experimental/MazeGenerator.java b/src/main/java/StevenDimDoors/experimental/MazeGenerator.java new file mode 100644 index 0000000..5eb9e63 --- /dev/null +++ b/src/main/java/StevenDimDoors/experimental/MazeGenerator.java @@ -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); + } +} diff --git a/src/main/java/StevenDimDoors/experimental/SpatialNode.java b/src/main/java/StevenDimDoors/experimental/SpatialNode.java new file mode 100644 index 0000000..0aef08f --- /dev/null +++ b/src/main/java/StevenDimDoors/experimental/SpatialNode.java @@ -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); + } +} diff --git a/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java b/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java index 70c1f01..a6172a3 100644 --- a/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java +++ b/src/main/java/StevenDimDoors/mod_pocketDim/world/PocketBuilder.java @@ -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);