Completed Doorway Placement

All doorways are placed sensibly now, including vertical passages
between different floors.
This commit is contained in:
SenseiKiwi 2013-12-30 19:59:17 -04:00
parent 3e33b94c98
commit 5e60960661
2 changed files with 183 additions and 75 deletions

View file

@ -1,14 +1,8 @@
package StevenDimDoors.experimental; package StevenDimDoors.experimental;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random; import java.util.Random;
import net.minecraft.block.Block; import net.minecraft.block.Block;
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.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
@ -22,9 +16,18 @@ public class MazeBuilder
{ {
MazeDesign design = MazeDesigner.generate(random); MazeDesign design = MazeDesigner.generate(random);
Point3D offset = new Point3D(x - design.width() / 2, y - design.height() - 1, z - design.length() / 2); 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); buildRooms(design.getRoomGraph(), world, offset);
carveDoorways(design.getRoomGraph(), world, offset, random); 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) private static void buildRooms(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, Point3D offset)
@ -36,14 +39,11 @@ public class MazeBuilder
} }
} }
private static void carveDoorways(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, Point3D offset, Random random) private static void carveDoorways(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world,
Point3D offset, SphereDecayOperation decay, Random random)
{ {
final int MIN_DOUBLE_DOOR_SPAN = 10;
int gap;
char axis; char axis;
Point3D lower; Point3D lower;
Point3D upper;
DoorwayData doorway; DoorwayData doorway;
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes()) for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes())
@ -53,71 +53,94 @@ public class MazeBuilder
doorway = passage.data(); doorway = passage.data();
axis = doorway.axis(); axis = doorway.axis();
lower = doorway.minCorner(); lower = doorway.minCorner();
upper = doorway.maxCorner(); 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) switch (axis)
{ {
case DoorwayData.X_AXIS: case DoorwayData.X_AXIS:
if (doorway.length() >= MIN_DOUBLE_DOOR_SPAN) if (length >= MIN_DOUBLE_DOOR_SPAN)
{ {
gap = (doorway.length() - 2) / 3; gap = (length - 2) / 3;
carveDoorAlongX(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + gap); carveDoorAlongX(world, x, y + 1, z + gap);
carveDoorAlongX(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 1, offset.getZ() + upper.getZ() - gap); carveDoorAlongX(world, x, y + 1, z + length - gap - 1);
} }
else if (doorway.length() > 3) else if (length > 3)
{ {
switch (random.nextInt(3)) switch (random.nextInt(3))
{ {
case 0: case 0:
carveDoorAlongX(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 1, offset.getZ() + (lower.getZ() + upper.getZ()) / 2); carveDoorAlongX(world, x, y + 1, z + (length - 1) / 2);
break; break;
case 1: case 1:
carveDoorAlongX(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + 2); carveDoorAlongX(world, x, y + 1, z + 2);
break; break;
case 2: case 2:
carveDoorAlongX(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 1, offset.getZ() + upper.getZ() - 2); carveDoorAlongX(world, x, y + 1, z + length - 3);
break; break;
} }
} }
else else
{ {
carveDoorAlongX(world, offset.getX() + lower.getX(), offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ() + 1); carveDoorAlongX(world, x, y + 1, z + 1);
} }
break; break;
case DoorwayData.Z_AXIS: case DoorwayData.Z_AXIS:
if (doorway.width() >= MIN_DOUBLE_DOOR_SPAN) if (width >= MIN_DOUBLE_DOOR_SPAN)
{ {
gap = (doorway.width() - 2) / 3; gap = (width - 2) / 3;
carveDoorAlongZ(world, offset.getX() + lower.getX() + gap, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ()); carveDoorAlongZ(world, x + gap, y + 1, z);
carveDoorAlongZ(world, offset.getX() + upper.getX() - gap, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ()); carveDoorAlongZ(world, x + width - gap - 1, y + 1, z);
} }
else if (doorway.length() > 3) else if (length > 3)
{ {
switch (random.nextInt(3)) switch (random.nextInt(3))
{ {
case 0: case 0:
carveDoorAlongZ(world, offset.getX() + (lower.getX() + upper.getX()) / 2, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ()); carveDoorAlongZ(world, x + (width - 1) / 2, y + 1, z);
break; break;
case 1: case 1:
carveDoorAlongZ(world, offset.getX() + lower.getX() + 2, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ()); carveDoorAlongZ(world, x + 2, y + 1, z);
break; break;
case 2: case 2:
carveDoorAlongZ(world, offset.getX() + upper.getX() - 2, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ()); carveDoorAlongZ(world, x + width - 3, y + 1, z);
break; break;
} }
} }
else else
{ {
carveDoorAlongZ(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY() + 1, offset.getZ() + lower.getZ()); carveDoorAlongZ(world, x + 1, y + 1, z);
} }
break; break;
case DoorwayData.Y_AXIS: case DoorwayData.Y_AXIS:
carveHole(world, offset.getX() + lower.getX() + 1, offset.getY() + lower.getY(), offset.getZ() + lower.getZ() + 1); 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; break;
} }
} }
}
}
private static void carveDoorAlongX(World world, int x, int y, int z) private static void carveDoorAlongX(World world, int x, int y, int z)
{ {
@ -141,6 +164,7 @@ public class MazeBuilder
setBlockDirectly(world, x, y + 1, 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) private static void buildBox(World world, Point3D offset, Point3D minCorner, Point3D maxCorner, int blockID, int metadata)
{ {
int minX = minCorner.getX() + offset.getX(); int minX = minCorner.getX() + offset.getX();

View file

@ -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;
}
}