I derped. Oh well. #122
134
src/main/java/StevenDimDoors/experimental/DisjointSet.java
Normal file
134
src/main/java/StevenDimDoors/experimental/DisjointSet.java
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
package StevenDimDoors.experimental;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class DisjointSet<T>
|
||||||
|
{
|
||||||
|
// This class implements a disjoint set data structure that associates objects with sets.
|
||||||
|
|
||||||
|
private static class SetNode<P>
|
||||||
|
{
|
||||||
|
private int rank;
|
||||||
|
private SetNode<P> parent;
|
||||||
|
private P data;
|
||||||
|
|
||||||
|
public SetNode(P data)
|
||||||
|
{
|
||||||
|
this.data = data;
|
||||||
|
this.rank = 0;
|
||||||
|
this.parent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashMap<T, SetNode<T>> mapping;
|
||||||
|
|
||||||
|
public DisjointSet(int initialCapacity)
|
||||||
|
{
|
||||||
|
mapping = new HashMap<T, SetNode<T>>(initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean makeSet(T element)
|
||||||
|
{
|
||||||
|
if (!mapping.containsKey(element))
|
||||||
|
{
|
||||||
|
mapping.put(element, new SetNode<T>(element));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SetNode<T> findRootNode(T element)
|
||||||
|
{
|
||||||
|
SetNode<T> node = mapping.get(element);
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (node.parent != null)
|
||||||
|
{
|
||||||
|
node.parent = findRootNode(node.parent);
|
||||||
|
return node.parent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SetNode<T> findRootNode(SetNode<T> node)
|
||||||
|
{
|
||||||
|
if (node.parent != null)
|
||||||
|
{
|
||||||
|
node.parent = findRootNode(node.parent);
|
||||||
|
return node.parent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean mergeSets(T first, T second)
|
||||||
|
{
|
||||||
|
SetNode<T> firstRoot = findRootNode(first);
|
||||||
|
SetNode<T> secondRoot = findRootNode(second);
|
||||||
|
|
||||||
|
if (firstRoot == null || secondRoot == null ||
|
||||||
|
firstRoot == secondRoot)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstRoot.rank < secondRoot.rank)
|
||||||
|
{
|
||||||
|
firstRoot.parent = secondRoot;
|
||||||
|
}
|
||||||
|
else if (firstRoot.rank > secondRoot.rank)
|
||||||
|
{
|
||||||
|
secondRoot.parent = firstRoot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
secondRoot.parent = firstRoot;
|
||||||
|
firstRoot.rank++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T find(T element)
|
||||||
|
{
|
||||||
|
SetNode<T> root = findRootNode(element);
|
||||||
|
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
return root.data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean haveSameSet(T first, T second)
|
||||||
|
{
|
||||||
|
SetNode<T> firstRoot = findRootNode(first);
|
||||||
|
SetNode<T> secondRoot = findRootNode(second);
|
||||||
|
|
||||||
|
if (firstRoot == null || secondRoot == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (firstRoot == secondRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
mapping.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,4 +33,19 @@ public class DoorwayData
|
|||||||
{
|
{
|
||||||
return axis;
|
return axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ public class LinkedList<T> implements Iterable<T>
|
|||||||
Node<T> addition = new Node(node, node.next, data, this);
|
Node<T> addition = new Node(node, node.next, data, this);
|
||||||
node.next = addition;
|
node.next = addition;
|
||||||
addition.next.prev = addition;
|
addition.next.prev = addition;
|
||||||
|
size++;
|
||||||
return addition;
|
return addition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
232
src/main/java/StevenDimDoors/experimental/MazeBuilder.java
Normal file
232
src/main/java/StevenDimDoors/experimental/MazeBuilder.java
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
package StevenDimDoors.experimental;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
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 MazeBuilder
|
||||||
|
{
|
||||||
|
private MazeBuilder() { }
|
||||||
|
|
||||||
|
public static void generate(World world, int x, int y, int z, Random random)
|
||||||
|
{
|
||||||
|
MazeDesign design = MazeDesigner.generate(random);
|
||||||
|
Point3D offset = new Point3D(x - design.width() / 2, y - design.height() - 1, z - design.length() / 2);
|
||||||
|
SphereDecayOperation decay = new SphereDecayOperation(random, 0, 0, Block.stoneBrick.blockID, 2);
|
||||||
|
|
||||||
|
buildRooms(design.getRoomGraph(), world, offset);
|
||||||
|
carveDoorways(design.getRoomGraph(), world, offset, decay, random);
|
||||||
|
|
||||||
|
applyRandomDestruction(design, world, offset, decay, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyRandomDestruction(MazeDesign design, World world,
|
||||||
|
Point3D offset, SphereDecayOperation decay, Random random)
|
||||||
|
{
|
||||||
|
//final int DECAY_BOX_SIZE = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildRooms(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, Point3D offset)
|
||||||
|
{
|
||||||
|
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
||||||
|
{
|
||||||
|
PartitionNode room = node.data();
|
||||||
|
buildBox(world, offset, room.minCorner(), room.maxCorner(), Block.stoneBrick.blockID, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void carveDoorways(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world,
|
||||||
|
Point3D offset, SphereDecayOperation decay, Random random)
|
||||||
|
{
|
||||||
|
char axis;
|
||||||
|
Point3D lower;
|
||||||
|
DoorwayData doorway;
|
||||||
|
|
||||||
|
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
||||||
|
{
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> passage : node.outbound())
|
||||||
|
{
|
||||||
|
doorway = passage.data();
|
||||||
|
axis = doorway.axis();
|
||||||
|
lower = doorway.minCorner();
|
||||||
|
carveDoorway(world, axis, offset.getX() + lower.getX(), offset.getY() + lower.getY(),
|
||||||
|
offset.getZ() + lower.getZ(), doorway.width(), doorway.height(), doorway.length(),
|
||||||
|
decay, random);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void carveDoorway(World world, char axis, int x, int y, int z, int width, int height,
|
||||||
|
int length, SphereDecayOperation decay, Random random)
|
||||||
|
{
|
||||||
|
final int MIN_DOUBLE_DOOR_SPAN = 10;
|
||||||
|
|
||||||
|
int gap;
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case DoorwayData.X_AXIS:
|
||||||
|
if (length >= MIN_DOUBLE_DOOR_SPAN)
|
||||||
|
{
|
||||||
|
gap = (length - 2) / 3;
|
||||||
|
carveDoorAlongX(world, x, y + 1, z + gap);
|
||||||
|
carveDoorAlongX(world, x, y + 1, z + length - gap - 1);
|
||||||
|
}
|
||||||
|
else if (length > 3)
|
||||||
|
{
|
||||||
|
switch (random.nextInt(3))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
carveDoorAlongX(world, x, y + 1, z + (length - 1) / 2);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
carveDoorAlongX(world, x, y + 1, z + 2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
carveDoorAlongX(world, x, y + 1, z + length - 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
carveDoorAlongX(world, x, y + 1, z + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DoorwayData.Z_AXIS:
|
||||||
|
if (width >= MIN_DOUBLE_DOOR_SPAN)
|
||||||
|
{
|
||||||
|
gap = (width - 2) / 3;
|
||||||
|
carveDoorAlongZ(world, x + gap, y + 1, z);
|
||||||
|
carveDoorAlongZ(world, x + width - gap - 1, y + 1, z);
|
||||||
|
}
|
||||||
|
else if (length > 3)
|
||||||
|
{
|
||||||
|
switch (random.nextInt(3))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
carveDoorAlongZ(world, x + (width - 1) / 2, y + 1, z);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
carveDoorAlongZ(world, x + 2, y + 1, z);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
carveDoorAlongZ(world, x + width - 3, y + 1, z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
carveDoorAlongZ(world, x + 1, y + 1, z);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DoorwayData.Y_AXIS:
|
||||||
|
gap = Math.min(width, length) - 2;
|
||||||
|
if (gap > 1)
|
||||||
|
{
|
||||||
|
if (gap > 6)
|
||||||
|
{
|
||||||
|
gap = 6;
|
||||||
|
}
|
||||||
|
decay.apply(world,
|
||||||
|
x + random.nextInt(width - gap - 1) + 1, y - 1,
|
||||||
|
z + random.nextInt(length - gap - 1) + 1, gap, 4, gap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
carveHole(world, x + 1, y, z + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void carveDoorAlongX(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
setBlockDirectly(world, x, y, z, 0, 0);
|
||||||
|
setBlockDirectly(world, x, y + 1, z, 0, 0);
|
||||||
|
setBlockDirectly(world, x + 1, y, z, 0, 0);
|
||||||
|
setBlockDirectly(world, x + 1, y + 1, z, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void carveDoorAlongZ(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
setBlockDirectly(world, x, y, z, 0, 0);
|
||||||
|
setBlockDirectly(world, x, y + 1, z, 0, 0);
|
||||||
|
setBlockDirectly(world, x, y, z + 1, 0, 0);
|
||||||
|
setBlockDirectly(world, x, y + 1, z + 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void carveHole(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
setBlockDirectly(world, x, y, z, 0, 0);
|
||||||
|
setBlockDirectly(world, x, y + 1, z, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void buildBox(World world, Point3D offset, Point3D minCorner, Point3D maxCorner, int blockID, int metadata)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
for (x = minX; x <= maxX; x++)
|
||||||
|
{
|
||||||
|
for (z = minZ; z <= maxZ; z++)
|
||||||
|
{
|
||||||
|
setBlockDirectly(world, x, minY, z, blockID, metadata);
|
||||||
|
setBlockDirectly(world, x, maxY, z, blockID, metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (x = minX; x <= maxX; x++)
|
||||||
|
{
|
||||||
|
for (y = minY; y <= maxY; y++)
|
||||||
|
{
|
||||||
|
setBlockDirectly(world, x, y, minZ, blockID, metadata);
|
||||||
|
setBlockDirectly(world, x, y, maxZ, blockID, metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (z = minZ; z <= maxZ; z++)
|
||||||
|
{
|
||||||
|
for (y = minY; y <= maxY; y++)
|
||||||
|
{
|
||||||
|
setBlockDirectly(world, minX, y, z, blockID, metadata);
|
||||||
|
setBlockDirectly(world, maxX, y, z, blockID, metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/main/java/StevenDimDoors/experimental/MazeDesign.java
Normal file
48
src/main/java/StevenDimDoors/experimental/MazeDesign.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package StevenDimDoors.experimental;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class MazeDesign
|
||||||
|
{
|
||||||
|
private PartitionNode root;
|
||||||
|
private DirectedGraph<PartitionNode, DoorwayData> rooms;
|
||||||
|
private ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores;
|
||||||
|
|
||||||
|
public MazeDesign(PartitionNode root, DirectedGraph<PartitionNode, DoorwayData> rooms,
|
||||||
|
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
this.rooms = rooms;
|
||||||
|
this.cores = cores;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartitionNode getRootPartition()
|
||||||
|
{
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirectedGraph<PartitionNode, DoorwayData> getRoomGraph()
|
||||||
|
{
|
||||||
|
return rooms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<IGraphNode<PartitionNode, DoorwayData>> getCoreNodes()
|
||||||
|
{
|
||||||
|
return cores;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int width()
|
||||||
|
{
|
||||||
|
return root.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int height()
|
||||||
|
{
|
||||||
|
return root.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int length()
|
||||||
|
{
|
||||||
|
return root.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,29 +6,26 @@ import java.util.HashMap;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.util.MathHelper;
|
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;
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
|
||||||
public class MazeGenerator
|
public class MazeDesigner
|
||||||
{
|
{
|
||||||
public static final int ROOT_WIDTH = 40;
|
private static final int MAZE_WIDTH = 34;
|
||||||
public static final int ROOT_LENGTH = 40;
|
private static final int MAZE_LENGTH = 34;
|
||||||
public static final int ROOT_HEIGHT = 20;
|
private static final int MAZE_HEIGHT = 20;
|
||||||
private static final int MIN_HEIGHT = 4;
|
private static final int MIN_HEIGHT = 4;
|
||||||
private static final int MIN_SIDE = 3;
|
private static final int MIN_SIDE = 3;
|
||||||
private static final int SPLIT_COUNT = 9;
|
private static final int SPLIT_COUNT = 9;
|
||||||
|
|
||||||
private MazeGenerator() { }
|
private MazeDesigner() { }
|
||||||
|
|
||||||
public static void generate(World world, int x, int y, int z, Random random)
|
public static MazeDesign generate(Random random)
|
||||||
{
|
{
|
||||||
// Construct a random binary space partitioning of our maze volume
|
// Construct a random binary space partitioning of our maze volume
|
||||||
PartitionNode root = partitionRooms(ROOT_WIDTH, ROOT_HEIGHT, ROOT_LENGTH, SPLIT_COUNT, random);
|
PartitionNode root = partitionRooms(MAZE_WIDTH, MAZE_HEIGHT, MAZE_LENGTH, SPLIT_COUNT, random);
|
||||||
|
|
||||||
// List all the leaf nodes of the partition tree, which denote individual rooms
|
// List all the leaf nodes of the partition tree, which denote individual rooms
|
||||||
ArrayList<PartitionNode> partitions = new ArrayList<PartitionNode>(1 << SPLIT_COUNT);
|
ArrayList<PartitionNode> partitions = new ArrayList<PartitionNode>(1 << SPLIT_COUNT);
|
||||||
@@ -42,8 +39,13 @@ public class MazeGenerator
|
|||||||
// Cut out random subgraphs from the adjacency graph
|
// Cut out random subgraphs from the adjacency graph
|
||||||
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores = createMazeSections(rooms, random);
|
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores = createMazeSections(rooms, random);
|
||||||
|
|
||||||
|
// Remove unnecessary passages through floors/ceilings and some from the walls
|
||||||
|
for (IGraphNode<PartitionNode, DoorwayData> core : cores)
|
||||||
|
{
|
||||||
|
pruneDoorways(core, rooms, random);
|
||||||
|
}
|
||||||
|
|
||||||
buildRooms(rooms, world, new Point3D(x - ROOT_WIDTH / 2, y - ROOT_HEIGHT - 1, z - ROOT_WIDTH / 2));
|
return new MazeDesign(root, rooms, cores);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void listRoomPartitions(PartitionNode node, ArrayList<PartitionNode> partitions)
|
private static void listRoomPartitions(PartitionNode node, ArrayList<PartitionNode> partitions)
|
||||||
@@ -59,18 +61,7 @@ public class MazeGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void removeRandomRooms(ArrayList<PartitionNode> rooms, Random random)
|
private static void removeRoomPartitions(PartitionNode node)
|
||||||
{
|
|
||||||
// Randomly remove a fraction of the rooms
|
|
||||||
Collections.shuffle(rooms, random);
|
|
||||||
int remaining = rooms.size() / 2;
|
|
||||||
for (int k = rooms.size() - 1; k >= remaining; k--)
|
|
||||||
{
|
|
||||||
removeRoom(rooms.remove(k));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void removeRoom(PartitionNode node)
|
|
||||||
{
|
{
|
||||||
// Remove a node and any of its ancestors that become leaf nodes
|
// Remove a node and any of its ancestors that become leaf nodes
|
||||||
PartitionNode parent;
|
PartitionNode parent;
|
||||||
@@ -243,11 +234,11 @@ public class MazeGenerator
|
|||||||
minYI = Math.max(minY, otherMin.getY());
|
minYI = Math.max(minY, otherMin.getY());
|
||||||
maxYI = Math.min(maxY, otherMax.getY());
|
maxYI = Math.min(maxY, otherMax.getY());
|
||||||
|
|
||||||
for (p = a; p <= maxXI - minXI; p++)
|
for (p = 0; p <= maxXI - minXI; p++)
|
||||||
{
|
{
|
||||||
for (q = b; q <= maxYI - minYI; q++)
|
for (q = 0; q <= maxYI - minYI; q++)
|
||||||
{
|
{
|
||||||
detected[p][q] = true;
|
detected[p + a][q + b] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if we meet the minimum dimensions needed for a doorway
|
// Check if we meet the minimum dimensions needed for a doorway
|
||||||
@@ -291,11 +282,11 @@ public class MazeGenerator
|
|||||||
minZI = Math.max(minZ, otherMin.getZ());
|
minZI = Math.max(minZ, otherMin.getZ());
|
||||||
maxZI = Math.min(maxZ, otherMax.getZ());
|
maxZI = Math.min(maxZ, otherMax.getZ());
|
||||||
|
|
||||||
for (q = b; q <= maxYI - minYI; q++)
|
for (q = 0; q <= maxYI - minYI; q++)
|
||||||
{
|
{
|
||||||
for (r = c; r <= maxZI - minZI; r++)
|
for (r = 0; r <= maxZI - minZI; r++)
|
||||||
{
|
{
|
||||||
detected[q][r] = true;
|
detected[q + b][r + c] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if we meet the minimum dimensions needed for a doorway
|
// Check if we meet the minimum dimensions needed for a doorway
|
||||||
@@ -339,11 +330,11 @@ public class MazeGenerator
|
|||||||
minZI = Math.max(minZ, otherMin.getZ());
|
minZI = Math.max(minZ, otherMin.getZ());
|
||||||
maxZI = Math.min(maxZ, otherMax.getZ());
|
maxZI = Math.min(maxZ, otherMax.getZ());
|
||||||
|
|
||||||
for (p = a; p <= maxXI - minXI; p++)
|
for (p = 0; p <= maxXI - minXI; p++)
|
||||||
{
|
{
|
||||||
for (r = c; r <= maxZI - minZI; r++)
|
for (r = 0; r <= maxZI - minZI; r++)
|
||||||
{
|
{
|
||||||
detected[p][r] = true;
|
detected[p + a][r + c] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if we meet the minimum dimensions needed for a doorway
|
// Check if we meet the minimum dimensions needed for a doorway
|
||||||
@@ -375,35 +366,31 @@ public class MazeGenerator
|
|||||||
// that was handled in a previous step!
|
// that was handled in a previous step!
|
||||||
|
|
||||||
final int MAX_DISTANCE = 2;
|
final int MAX_DISTANCE = 2;
|
||||||
|
final int MIN_SECTION_ROOMS = 5;
|
||||||
|
|
||||||
int distance;
|
int distance;
|
||||||
IGraphNode<PartitionNode, DoorwayData> current;
|
IGraphNode<PartitionNode, DoorwayData> current;
|
||||||
IGraphNode<PartitionNode, DoorwayData> neighbor;
|
IGraphNode<PartitionNode, DoorwayData> neighbor;
|
||||||
|
|
||||||
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>();
|
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>();
|
||||||
|
ArrayList<IGraphNode<PartitionNode, DoorwayData>> removals = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>();
|
||||||
|
ArrayList<IGraphNode<PartitionNode, DoorwayData>> section = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>();
|
||||||
|
|
||||||
Queue<IGraphNode<PartitionNode, DoorwayData>> ordering = new LinkedList<IGraphNode<PartitionNode, DoorwayData>>();
|
Queue<IGraphNode<PartitionNode, DoorwayData>> ordering = new LinkedList<IGraphNode<PartitionNode, DoorwayData>>();
|
||||||
HashMap<IGraphNode<PartitionNode, DoorwayData>, Integer> distances = new HashMap<IGraphNode<PartitionNode, DoorwayData>, Integer>();
|
HashMap<IGraphNode<PartitionNode, DoorwayData>, Integer> distances = new HashMap<IGraphNode<PartitionNode, DoorwayData>, Integer>();
|
||||||
|
|
||||||
// Repeatedly generate sections until all nodes have been visited
|
// Repeatedly generate sections until all nodes have been visited
|
||||||
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
||||||
{
|
{
|
||||||
// If this node has an indegree and outdegree of 0, then it has no neighbors,
|
|
||||||
// which means it could not have been visited. This could happen if its neighbors
|
|
||||||
// were pruned away before. Single rooms look weird, so remove it.
|
|
||||||
if (node.indegree() == 0 && node.outdegree() == 0)
|
|
||||||
{
|
|
||||||
roomGraph.removeNode(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this node hasn't been visited, then use it as the core of a new section
|
// If this node hasn't been visited, then use it as the core of a new section
|
||||||
// Otherwise, ignore it, since it already belongs to a section
|
// Otherwise, ignore it, since it was already processed
|
||||||
else if (!distances.containsKey(node))
|
if (!distances.containsKey(node))
|
||||||
{
|
{
|
||||||
cores.add(node);
|
|
||||||
|
|
||||||
// Perform a breadth-first search to tag surrounding nodes with distances
|
// Perform a breadth-first search to tag surrounding nodes with distances
|
||||||
distances.put(node, 0);
|
distances.put(node, 0);
|
||||||
ordering.add(node);
|
ordering.add(node);
|
||||||
|
section.clear();
|
||||||
|
|
||||||
while (!ordering.isEmpty())
|
while (!ordering.isEmpty())
|
||||||
{
|
{
|
||||||
current = ordering.remove();
|
current = ordering.remove();
|
||||||
@@ -411,6 +398,8 @@ public class MazeGenerator
|
|||||||
|
|
||||||
if (distance <= MAX_DISTANCE + 1)
|
if (distance <= MAX_DISTANCE + 1)
|
||||||
{
|
{
|
||||||
|
section.add(current);
|
||||||
|
|
||||||
// Visit neighboring nodes and assign them distances, if they don't
|
// Visit neighboring nodes and assign them distances, if they don't
|
||||||
// have a distance assigned already
|
// have a distance assigned already
|
||||||
for (IEdge<PartitionNode, DoorwayData> edge : current.inbound())
|
for (IEdge<PartitionNode, DoorwayData> edge : current.inbound())
|
||||||
@@ -434,128 +423,157 @@ public class MazeGenerator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
roomGraph.removeNode(current);
|
removals.add(current);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all nodes that have a distance of exactly MAX_DISTANCE + 1
|
// List nodes that have a distance of exactly MAX_DISTANCE + 1
|
||||||
// Those are precisely the nodes that remain in the queue
|
// Those are precisely the nodes that remain in the queue
|
||||||
|
// We can't remove them immediately because that could break
|
||||||
|
// the iterator for the graph.
|
||||||
while (!ordering.isEmpty())
|
while (!ordering.isEmpty())
|
||||||
{
|
{
|
||||||
roomGraph.removeNode( ordering.remove() );
|
removals.add(ordering.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this section contains enough rooms
|
||||||
|
if (section.size() >= MIN_SECTION_ROOMS)
|
||||||
|
{
|
||||||
|
cores.add(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removals.addAll(section);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all the nodes that were listed for removal
|
||||||
|
// Also remove unused partitions from the partition tree
|
||||||
|
for (IGraphNode<PartitionNode, DoorwayData> node : removals)
|
||||||
|
{
|
||||||
|
removeRoomPartitions(node.data());
|
||||||
|
roomGraph.removeNode(node);
|
||||||
|
}
|
||||||
return cores;
|
return cores;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void buildRooms(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, Point3D offset)
|
private static void pruneDoorways(IGraphNode<PartitionNode, DoorwayData> core,
|
||||||
|
DirectedGraph<PartitionNode, DoorwayData> rooms, Random random)
|
||||||
{
|
{
|
||||||
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
// We receive a node for one of the rooms in a section of the maze
|
||||||
|
// and we need to remove as many floor doorways as possible while
|
||||||
|
// still allowing any room to be reachable from any other room.
|
||||||
|
// In technical terms, we receive a node from a connected subgraph
|
||||||
|
// and we need to remove as many Y_AXIS-type edges as possible while
|
||||||
|
// preserving connectedness. We also want to randomly remove some of
|
||||||
|
// the other doorways without breaking connectedness.
|
||||||
|
|
||||||
|
// An efficient solution is to assign nodes to disjoint sets based
|
||||||
|
// on their components, ignoring all Y_AXIS edges, then iterate over
|
||||||
|
// a list of those edges and remove them if they connect two nodes
|
||||||
|
// in the same set. Otherwise, merge their sets and keep the edge.
|
||||||
|
// This is similar to algorithms for spanning trees. The same
|
||||||
|
// idea applies for the other doorways, plus some randomness.
|
||||||
|
|
||||||
|
// First, list all nodes in the subgraph
|
||||||
|
IGraphNode<PartitionNode, DoorwayData> current;
|
||||||
|
IGraphNode<PartitionNode, DoorwayData> neighbor;
|
||||||
|
|
||||||
|
Stack<IGraphNode<PartitionNode, DoorwayData>> ordering = new Stack<IGraphNode<PartitionNode, DoorwayData>>();
|
||||||
|
ArrayList<IGraphNode<PartitionNode, DoorwayData>> subgraph = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>(64);
|
||||||
|
DisjointSet<IGraphNode<PartitionNode, DoorwayData>> components = new DisjointSet<IGraphNode<PartitionNode, DoorwayData>>(128);
|
||||||
|
|
||||||
|
ordering.add(core);
|
||||||
|
components.makeSet(core);
|
||||||
|
while (!ordering.isEmpty())
|
||||||
{
|
{
|
||||||
PartitionNode room = node.data();
|
current = ordering.pop();
|
||||||
buildBox(world, offset, room.minCorner(), room.maxCorner(), Block.stoneBrick.blockID, 0);
|
subgraph.add(current);
|
||||||
|
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> edge : current.inbound())
|
||||||
|
{
|
||||||
|
neighbor = edge.head();
|
||||||
|
if (components.makeSet(neighbor))
|
||||||
|
{
|
||||||
|
ordering.add(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> edge : current.outbound())
|
||||||
|
{
|
||||||
|
neighbor = edge.tail();
|
||||||
|
if (components.makeSet(neighbor))
|
||||||
|
{
|
||||||
|
ordering.add(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTING!!!
|
// Now iterate over the list of nodes and merge their sets
|
||||||
// This code carves out cheap doorways
|
// We only have to look at outbound edges since inbound edges mirror them
|
||||||
// The final system will be better
|
// Also list any Y_AXIS doorways we come across
|
||||||
// This has to happen after all the rooms have been built or the passages will be overwritten sometimes
|
ArrayList<IEdge<PartitionNode, DoorwayData>> targets =
|
||||||
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
|
new ArrayList<IEdge<PartitionNode, DoorwayData>>();
|
||||||
{
|
|
||||||
for (IEdge<PartitionNode, DoorwayData> doorway : node.outbound())
|
|
||||||
{
|
|
||||||
char axis = doorway.data().axis();
|
|
||||||
Point3D lower = doorway.data().minCorner();
|
|
||||||
|
|
||||||
if (axis == DoorwayData.Z_AXIS)
|
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph)
|
||||||
{
|
{
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ(), 0, 0);
|
for (IEdge<PartitionNode, DoorwayData> passage : room.outbound())
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 2, offset.getZ() + lower.getZ(), 0, 0);
|
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + 1, 0, 0);
|
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 2, offset.getZ() + lower.getZ() + 1, 0, 0);
|
|
||||||
}
|
|
||||||
else if (axis == DoorwayData.X_AXIS)
|
|
||||||
{
|
{
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + 1, 0, 0);
|
if (passage.data().axis() != DoorwayData.Y_AXIS)
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 2, offset.getZ() + lower.getZ() + 1, 0, 0);
|
{
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + 1, 0, 0);
|
components.mergeSets(passage.head(), passage.tail());
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 2, offset.getZ() + lower.getZ() + 1, 0, 0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY(), offset.getZ() + lower.getZ() + 1, 0, 0);
|
targets.add(passage);
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY(), offset.getZ() + lower.getZ() + 1, 0, 0);
|
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + 1, 0, 0);
|
|
||||||
setBlockDirectly(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + 1, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void buildBox(World world, Point3D offset, Point3D minCorner, Point3D maxCorner, int blockID, int metadata)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
for (x = minX; x <= maxX; x++)
|
|
||||||
{
|
|
||||||
for (z = minZ; z <= maxZ; z++)
|
|
||||||
{
|
|
||||||
setBlockDirectly(world, x, minY, z, blockID, metadata);
|
|
||||||
setBlockDirectly(world, x, maxY, z, blockID, metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (x = minX; x <= maxX; x++)
|
|
||||||
{
|
|
||||||
for (y = minY; y <= maxY; y++)
|
|
||||||
{
|
|
||||||
setBlockDirectly(world, x, y, minZ, blockID, metadata);
|
|
||||||
setBlockDirectly(world, x, y, maxZ, blockID, metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (z = minZ; z <= maxZ; z++)
|
|
||||||
{
|
|
||||||
for (y = minY; y <= maxY; y++)
|
|
||||||
{
|
|
||||||
setBlockDirectly(world, minX, y, z, blockID, metadata);
|
|
||||||
setBlockDirectly(world, maxX, y, z, blockID, metadata);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setBlockDirectly(World world, int x, int y, int z, int blockID, int metadata)
|
// Shuffle the list of doorways to randomize which ones are removed
|
||||||
|
Collections.shuffle(targets, random);
|
||||||
|
|
||||||
|
// Merge sets together and remove unnecessary doorways
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> passage : targets)
|
||||||
{
|
{
|
||||||
if (blockID != 0 && Block.blocksList[blockID] == null)
|
if (!components.mergeSets(passage.head(), passage.tail()))
|
||||||
{
|
{
|
||||||
return;
|
rooms.removeEdge(passage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cX = x >> 4;
|
// Repeat the pruning process with X_AXIS and Z_AXIS doorways
|
||||||
int cZ = z >> 4;
|
// In this case, unnecessary edges might be kept at random
|
||||||
int cY = y >> 4;
|
components.clear();
|
||||||
Chunk chunk;
|
targets.clear();
|
||||||
|
|
||||||
int localX = (x % 16) < 0 ? (x % 16) + 16 : (x % 16);
|
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph)
|
||||||
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);
|
components.makeSet(room);
|
||||||
chunk.getBlockStorageArray()[cY] = extBlockStorage;
|
|
||||||
}
|
}
|
||||||
extBlockStorage.setExtBlockID(localX, y & 15, localZ, blockID);
|
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph)
|
||||||
extBlockStorage.setExtBlockMetadata(localX, y & 15, localZ, metadata);
|
{
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> passage : room.outbound())
|
||||||
|
{
|
||||||
|
if (passage.data().axis() == DoorwayData.Y_AXIS)
|
||||||
|
{
|
||||||
|
components.mergeSets(passage.head(), passage.tail());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targets.add(passage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.shuffle(targets, random);
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> passage : targets)
|
||||||
|
{
|
||||||
|
if (!components.mergeSets(passage.head(), passage.tail()) && random.nextBoolean())
|
||||||
|
{
|
||||||
|
rooms.removeEdge(passage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package StevenDimDoors.experimental;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockContainer;
|
||||||
|
import net.minecraft.inventory.IInventory;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.tileentity.TileEntityChest;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import StevenDimDoors.mod_pocketDim.DDLoot;
|
||||||
|
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||||
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
|
import StevenDimDoors.mod_pocketDim.schematic.WorldOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an operation for damaging structures based on a spherical area. The chance of damage decreases
|
||||||
|
* with the square of the distance from the center of the sphere.
|
||||||
|
* @author SenseiKiwi
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SphereDecayOperation extends WorldOperation
|
||||||
|
{
|
||||||
|
private Random random;
|
||||||
|
private double scaling;
|
||||||
|
private double centerX;
|
||||||
|
private double centerY;
|
||||||
|
private double centerZ;
|
||||||
|
private int primaryBlockID;
|
||||||
|
private int primaryMetadata;
|
||||||
|
private int secondaryBlockID;
|
||||||
|
private int secondaryMetadata;
|
||||||
|
|
||||||
|
public SphereDecayOperation(Random random, int primaryBlockID, int primaryMetadata, int secondaryBlockID, int secondaryMetadata)
|
||||||
|
{
|
||||||
|
super("SphereDecayOperation");
|
||||||
|
this.random = random;
|
||||||
|
this.primaryBlockID = primaryBlockID;
|
||||||
|
this.primaryMetadata = primaryMetadata;
|
||||||
|
this.secondaryBlockID = secondaryBlockID;
|
||||||
|
this.secondaryMetadata = secondaryMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean initialize(World world, int x, int y, int z, int width, int height, int length)
|
||||||
|
{
|
||||||
|
// Calculate a scaling factor so that the probability of decay
|
||||||
|
// at the edge of the largest dimension of our bounds is 20%.
|
||||||
|
scaling = Math.max(width - 1, Math.max(height - 1, length - 1)) / 2.0;
|
||||||
|
scaling *= scaling * 0.20;
|
||||||
|
|
||||||
|
centerX = x + width / 2.0;
|
||||||
|
centerY = y + height / 2.0;
|
||||||
|
centerZ = z + length / 2.0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyToBlock(World world, int x, int y, int z)
|
||||||
|
{
|
||||||
|
// Don't raise any notifications. This operation is only designed to run
|
||||||
|
// when a dimension is being generated, which means there are no players around.
|
||||||
|
if (!world.isAirBlock(x, y, z))
|
||||||
|
{
|
||||||
|
double dx = (centerX - x - 0.5);
|
||||||
|
double dy = (centerY - y - 0.5);
|
||||||
|
double dz = (centerZ - z - 0.5);
|
||||||
|
double squareDistance = dx * dx + dy * dy + dz * dz;
|
||||||
|
|
||||||
|
if (squareDistance < 0.5 || random.nextDouble() < scaling / squareDistance)
|
||||||
|
{
|
||||||
|
world.setBlock(x, y, z, primaryBlockID, primaryMetadata, 1);
|
||||||
|
}
|
||||||
|
else if (random.nextDouble() < scaling / squareDistance)
|
||||||
|
{
|
||||||
|
world.setBlock(x, y, z, secondaryBlockID, secondaryMetadata, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import net.minecraft.world.World;
|
|||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
import net.minecraftforge.common.DimensionManager;
|
import net.minecraftforge.common.DimensionManager;
|
||||||
import StevenDimDoors.experimental.MazeGenerator;
|
import StevenDimDoors.experimental.MazeBuilder;
|
||||||
import StevenDimDoors.mod_pocketDim.DDProperties;
|
import StevenDimDoors.mod_pocketDim.DDProperties;
|
||||||
import StevenDimDoors.mod_pocketDim.Point3D;
|
import StevenDimDoors.mod_pocketDim.Point3D;
|
||||||
import StevenDimDoors.mod_pocketDim.blocks.IDimDoor;
|
import StevenDimDoors.mod_pocketDim.blocks.IDimDoor;
|
||||||
@@ -484,7 +484,7 @@ public class PocketBuilder
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MazeGenerator.generate(world, x, y, z, random);
|
MazeBuilder.generate(world, x, y, z, random);
|
||||||
|
|
||||||
//Build the door
|
//Build the door
|
||||||
int doorOrientation = BlockRotator.transformMetadata(BlockRotator.EAST_DOOR_METADATA, orientation - BlockRotator.EAST_DOOR_METADATA + 2, properties.DimensionalDoorID);
|
int doorOrientation = BlockRotator.transformMetadata(BlockRotator.EAST_DOOR_METADATA, orientation - BlockRotator.EAST_DOOR_METADATA + 2, properties.DimensionalDoorID);
|
||||||
|
|||||||
Reference in New Issue
Block a user