par0List) {
+ int tweight = 0;
+
+ for (WeightedComponent wc : par0List) {
+ tweight += wc.componentWeight;
+ }
+
+ return tweight;
+ }
+ }
+}
diff --git a/src/main/java/ml/core/world/structure/MLStructureStart.java b/src/main/java/ml/core/world/structure/MLStructureStart.java
new file mode 100644
index 0000000..7fb4d2f
--- /dev/null
+++ b/src/main/java/ml/core/world/structure/MLStructureStart.java
@@ -0,0 +1,30 @@
+package ml.core.world.structure;
+
+import java.util.Random;
+
+import ml.core.world.structure.MLStructureComponent.InitialStructureComponent;
+import net.minecraft.world.World;
+import net.minecraft.world.gen.structure.StructureStart;
+
+public abstract class MLStructureStart extends StructureStart {
+
+ public MLStructureStart() {}
+
+ public MLStructureStart(InitialStructureComponent initialComponent, World world, Random rnd, int chunkX, int chunkZ) {
+ super(chunkX, chunkZ);
+
+ this.components.add(initialComponent);
+ initialComponent.buildComponent(initialComponent, this.components, rnd);
+
+ while (!initialComponent.unbuiltComponents.isEmpty()) {
+ //int i = rnd.nextInt(initialComponent.unbuiltComponents.size());
+ MLStructureComponent nextComponent = initialComponent.unbuiltComponents.remove(0);
+ nextComponent.buildComponent(initialComponent, this.components, rnd);
+
+ if (this.components.contains(nextComponent)) this.components.add(nextComponent);
+ }
+
+ updateBoundingBox();
+ }
+
+}
diff --git a/src/main/java/ml/core/world/structure/StructureBuilder.java b/src/main/java/ml/core/world/structure/StructureBuilder.java
new file mode 100644
index 0000000..05508aa
--- /dev/null
+++ b/src/main/java/ml/core/world/structure/StructureBuilder.java
@@ -0,0 +1,337 @@
+package ml.core.world.structure;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockButton;
+import net.minecraft.block.BlockDoor;
+import net.minecraft.block.BlockLever;
+import net.minecraft.block.BlockPistonBase;
+import net.minecraft.block.BlockRailBase;
+import net.minecraft.block.BlockRedstoneRepeater;
+import net.minecraft.block.BlockStairs;
+import net.minecraft.block.BlockTorch;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemDoor;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.world.ChunkPosition;
+import net.minecraft.world.World;
+import net.minecraft.world.gen.structure.StructureBoundingBox;
+import net.minecraftforge.common.util.ForgeDirection;
+
+/**
+ * Helper class for making the creation of rotatable structures easier.
+ * Imposes a custom coordinate system:
+ *
+ *
+ * Z-
+ * ^
+ * |
+ * N
+ * X- <------W + E------> X+
+ * S
+ * |
+ * v
+ * Z+
+ *
+ *
+ * N,E,S,W are default minecraft directions, in global space. Z-, X+, Z+, X- are in local space and are rotated depending on the passed rotation.
+ * Rotation works in 90-degree increments, rotating the axes in the above illustration clockwise. e.g. Z- becomes East, X+ becomes South, etc.
+ *
+ * @author Matchlighter
+ */
+public class StructureBuilder {
+
+ public final World world;
+ public final int rotation;
+ public final ChunkPosition center;
+ public ChunkCoordinates ioffset = new ChunkCoordinates();
+ public ChunkCoordinates absMinimum, absMaximum;
+
+ public boolean flipXZ = false;
+
+ public boolean symmetryX = false;
+ public boolean symmetryZ = false;
+
+ public boolean invertX = false;
+ public boolean invertY = false;
+ public boolean invertZ = false;
+
+ public int rotationOffset = 0;
+
+ /**
+ * See {@link StructureBuilder} for details.
+ * @param world
+ * @param pos The point to rotate the structure around.
+ * @param rot The number of clockwise, 90-degree increments to rotate the structure.
+ */
+ public StructureBuilder(World world, ChunkPosition pos, int rot) {
+ this.world = world;
+ this.center = pos;
+ this.rotation = rot;
+ }
+
+ public StructureBuilder(World world, ChunkCoordinates pos, int rot) {
+ this.world = world;
+ this.center = new ChunkPosition(pos.posX, pos.posY, pos.posZ);
+ this.rotation = rot;
+ }
+
+ public StructureBuilder(World world, int x, int y, int z, int rot) {
+ this.world = world;
+ this.center = new ChunkPosition(x, y, z);
+ this.rotation = rot;
+ }
+
+ /**
+ * Converts the local x passed to a global x-value.
+ */
+ public int getAbsX(int x, int z) {
+ if (invertX) x = -x; if (invertZ) z = -z;
+ x += ioffset.posX; z += ioffset.posZ;
+ int mrot = (rotation + rotationOffset) % 4;
+
+ switch (mrot) {
+ case 0:
+ return center.chunkPosX+x;
+ case 1:
+ return center.chunkPosX-z;
+ case 2:
+ return center.chunkPosX-x;
+ case 3:
+ return center.chunkPosX+z;
+ }
+ return center.chunkPosX;
+ }
+
+ public int getAbsY(int oy) {
+ if (invertY) oy = -oy;
+ return center.chunkPosY + oy + ioffset.posY;
+ }
+
+ /**
+ * Converts the local z passed to a global z-value.
+ */
+ public int getAbsZ(int x, int z) {
+ if (invertX) x = -x; if (invertZ) z = -z;
+ x += ioffset.posX; z += ioffset.posZ;
+ int mrot = (rotation + rotationOffset) % 4;
+
+ switch (mrot) {
+ case 0:
+ return center.chunkPosZ+z;
+ case 1:
+ return center.chunkPosZ+x;
+ case 2:
+ return center.chunkPosZ-z;
+ case 3:
+ return center.chunkPosZ-x;
+ }
+ return center.chunkPosZ;
+ }
+
+ public TileEntity getTileEntityAt(int rx, int ry, int rz) {
+ ChunkCoordinates abs = getAbsCoords(rx, ry, rz);
+ return world.getTileEntity(abs.posX, abs.posY, abs.posZ);
+ }
+
+ /**
+ * Converts the relative x,y,z into a global point.
+ */
+ public ChunkCoordinates getAbsCoords(int rx, int ry, int rz) {
+ int bx = flipXZ ? rz : rx;
+ int bz = flipXZ ? rx : rz;
+
+ return new ChunkCoordinates(getAbsX(bx, bz), getAbsY(ry), getAbsZ(bx, bz));
+ }
+
+ public boolean absCoordsInRange(int ax, int ay, int az) {
+ if (absMinimum == null || absMaximum == null) return true;
+ return (ax >= absMinimum.posX && ax <= absMaximum.posX) &&
+ (ay >= absMinimum.posY && ay <= absMaximum.posY) &
+ (az >= absMinimum.posZ && az <= absMaximum.posZ);
+ }
+
+ public boolean relCoordsInRange(int rx, int ry, int rz) {
+ if (absMinimum == null || absMaximum == null) return true;
+ ChunkCoordinates absPt = getAbsCoords(rx, ry, rz);
+ return (absPt.posX >= absMinimum.posX && absPt.posX <= absMaximum.posX) &&
+ (absPt.posY >= absMinimum.posY && absPt.posY <= absMaximum.posY) &
+ (absPt.posZ >= absMinimum.posZ && absPt.posZ <= absMaximum.posZ);
+ }
+
+ public void setMinMax(ChunkCoordinates min, ChunkCoordinates max) {
+ this.absMinimum = min;
+ this.absMaximum = max;
+ }
+
+ public void setMinMax(StructureBoundingBox bb) {
+ if (bb != null) {
+ this.absMinimum = new ChunkCoordinates(bb.minX, bb.minY, bb.minZ);
+ this.absMaximum = new ChunkCoordinates(bb.maxX, bb.maxY, bb.maxZ);
+ } else {
+ this.absMinimum = null;
+ this.absMaximum = null;
+ }
+ }
+
+ public Block getBlockAt(int rx, int ry, int rz) {
+ ChunkCoordinates p = getAbsCoords(rx, ry, rz);
+ return world.getBlock(p.posX, p.posY, p.posZ);
+ }
+
+ private void setBlockAtAbs(int ax, int ay, int az, Block block, int blockMeta) {
+ if (!absCoordsInRange(ax, ay, az)) return;
+
+ if (block instanceof BlockDoor) {
+ ItemDoor.placeDoorBlock(world, ax, ay, az, blockMeta, block);
+ } else {
+ world.setBlock(ax, ay, az, block != null ? block : Blocks.air, blockMeta, 3);
+ }
+ }
+
+ /**
+ * Set the block at the local coordinates (rx, ry, rz) to the specified block and meta.
+ * Takes symmetry booleans into account, so up to 4 blocks may be placed.
+ */
+ public void setBlockAt(int rx, int ry, int rz, Block block, int blockMeta) {
+
+ int bx = flipXZ ? rz : rx;
+ int bz = flipXZ ? rx : rz;
+
+ setBlockAtAbs(getAbsX(bx, bz), getAbsY(ry), getAbsZ(bx, bz), block, blockMeta);
+
+ if (symmetryX && symmetryZ && bx != 0 && bz != 0) {
+ setBlockAtAbs(getAbsX(-bx, -bz), getAbsY(ry), getAbsZ(-bx, -bz), block, blockMeta);
+ }
+ if (symmetryX && bx != 0) {
+ setBlockAtAbs(getAbsX(-bx, bz), getAbsY(ry), getAbsZ(-bx, bz), block, blockMeta);
+ }
+ if (symmetryZ && bz != 0) {
+ setBlockAtAbs(getAbsX(bx, -bz), getAbsY(ry), getAbsZ(bx, -bz), block, blockMeta);
+ }
+ }
+
+ /**
+ * Fills the specified area with blocks. start_ and end_ are both inclusive.
+ */
+ public void fillArea(int startX, int startY, int startZ, int endX, int endY, int endZ, Block block, int blockMeta) {
+ for (int x=startX; x<=endX; x++) {
+ for (int z=startZ; z<=endZ; z++) {
+ for (int y=startY; y<=endY; y++) {
+ setBlockAt(x, y, z, block, blockMeta);
+ }
+ }
+ }
+ }
+
+ /**
+ * Fills the edges of the specified area with blocks. start_ and end_ are both inclusive.
+ */
+ public void borderArea(int startX, int startY, int startZ, int endX, int endY, int endZ, Block block, int blockMeta) {
+ for (int x=startX; x<=endX; x++) {
+ boolean xc = x==startX || x==endX;
+
+ for (int z=startZ; z<=endZ; z++) {
+ boolean zc = z==startZ || z==endZ;
+
+ for (int y=startY; y<=endY; y++) {
+ boolean yc = y==startY || y==endY;
+
+ if ((yc && xc) || (yc && zc) || (xc && zc)) setBlockAt(x, y, z, block, blockMeta);
+ }
+ }
+ }
+ }
+
+ /**
+ * Fills the faces of the specified area with blocks. start_ and end_ are both inclusive.
+ */
+ public void wallArea(int startX, int startY, int startZ, int endX, int endY, int endZ, Block block, int blockMeta) {
+ wallArea(startX, startY, startZ, endX, endY, endZ, true, true, true, block, blockMeta);
+ }
+
+ /**
+ * Fills the faces of the specified area with blocks, if the w_ is true for the axis. start_ and end_ are both inclusive.
+ */
+ public void wallArea(int startX, int startY, int startZ, int endX, int endY, int endZ, boolean wx, boolean wy, boolean wz, Block block, int blockMeta) {
+ for (int x=startX; x<=endX; x++) {
+ boolean xc = (x==startX || x==endX) && wx;
+
+ for (int z=startZ; z<=endZ; z++) {
+ boolean zc = (z==startZ || z==endZ) && wz;
+
+ for (int y=startY; y<=endY; y++) {
+ boolean yc = (y==startY || y==endY) && wy;
+
+ if (xc || yc || zc) setBlockAt(x, y, z, block, blockMeta);
+ }
+ }
+ }
+ }
+
+ public void fillDown(int startX, int startY, int startZ, int endX, int endZ, Block block, int blockMeta) {
+ for (int x=startX; x<=endX; x++) {
+ for (int z=startZ; z<=endZ; z++) {
+ for (int y=startY; getAbsY(y)>0; y--) {
+ if (getBlockAt(x, y, z) != Blocks.air) {
+ break;
+ }
+ setBlockAt(x, y, z, block, blockMeta);
+ }
+ }
+ }
+ }
+
+ /**
+ * Attempts to get the rotated metadata of a rotatable block.
+ */
+ public int getRotatedMeta(Block block, int cRotation) {
+ int rot4 =(this.rotation + cRotation) % 4;
+
+ if (block instanceof BlockRailBase) {
+ return (this.rotation + cRotation) % 2;
+
+ } else if (block instanceof BlockDoor) {
+ return (this.rotation + cRotation + 1) % 4;
+
+ } else if (block instanceof BlockStairs) {
+ int rot = rot4;
+
+ if (rot4 == 0) rot = 2;
+ else if (rot4 == 2) rot = 3;
+ else if (rot4 == 3) rot = 0;
+
+ return rot | (cRotation & 8);
+
+ } else if (block == Blocks.ladder) {
+ if (rot4 == 0) return 2;
+ if (rot4 == 1) return 5;
+ else if (rot4 == 2) return 3;
+ else if (rot4 == 3) return 4;
+
+ } else if (block instanceof BlockButton || block instanceof BlockLever || block instanceof BlockTorch) {
+ if (rot4 == 0) return 4;
+ if (rot4 == 1) return 1;
+ else if (rot4 == 2) return 3;
+ else if (rot4 == 3) return 2;
+
+ } else if (block instanceof BlockPistonBase || block instanceof BlockLever || block == Blocks.dispenser) {
+ // TODO
+ } else if (block instanceof BlockRedstoneRepeater) {
+ return rot4;
+ }
+
+ return rot4;
+ }
+
+ private static final int[][] rotMatrix = {
+ {0,1, 2,3,4,5},
+ {0,1, 5,4,2,3},
+ {0,1, 3,2,5,4},
+ {0,1, 4,5,3,2},
+ };
+
+ public ForgeDirection rotateForgeDir(ForgeDirection fdir) {
+ return ForgeDirection.getOrientation(rotMatrix[rotation][fdir.ordinal()]);
+ }
+}
diff --git a/src/main/java/ml/core/world/structure/StructureHelper.java b/src/main/java/ml/core/world/structure/StructureHelper.java
new file mode 100644
index 0000000..51f7d6d
--- /dev/null
+++ b/src/main/java/ml/core/world/structure/StructureHelper.java
@@ -0,0 +1,68 @@
+package ml.core.world.structure;
+
+import java.util.Random;
+
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.world.World;
+
+public class StructureHelper {
+
+ public static boolean shouldGenerateAt(World world, int chunkX, int chunkZ, int minDist, int maxDist) {
+ int k = chunkX;
+ int l = chunkZ;
+
+ if (chunkX < 0) {
+ chunkX -= maxDist - 1;
+ }
+
+ if (chunkZ < 0) {
+ chunkZ -= maxDist - 1;
+ }
+
+ int i1 = chunkX / maxDist;
+ int j1 = chunkZ / maxDist;
+ Random random = world.setRandomSeed(i1, j1, 14357617);
+ i1 *= maxDist;
+ j1 *= maxDist;
+ i1 += random.nextInt(maxDist - minDist);
+ j1 += random.nextInt(maxDist - minDist);
+
+ return (k == i1 && l == j1);
+ }
+
+ public static int getRotatedX(int x, int z, int rotation) {
+ switch (rotation) {
+ case 0:
+ return x;
+ case 1:
+ return -z;
+ case 2:
+ return -x;
+ case 3:
+ return z;
+ }
+ return x;
+ }
+
+ public static int getRotatedZ(int x, int z, int rotation) {
+ switch (rotation) {
+ case 0:
+ return z;
+ case 1:
+ return x;
+ case 2:
+ return -z;
+ case 3:
+ return -x;
+ }
+ return z;
+ }
+
+ public static ChunkCoordinates getRotatedCoords(ChunkCoordinates coord, int rotation) {
+ return new ChunkCoordinates(getRotatedX(coord.posX, coord.posZ, rotation), coord.posY, getRotatedZ(coord.posX, coord.posZ, rotation));
+ }
+
+ public static ChunkCoordinates addCoords(ChunkCoordinates a, ChunkCoordinates b) {
+ return new ChunkCoordinates(a.posX + b.posX, a.posY + b.posY, a.posZ + b.posZ);
+ }
+}
diff --git a/src/main/java/ml/core/world/structure/WeightedComponent.java b/src/main/java/ml/core/world/structure/WeightedComponent.java
new file mode 100644
index 0000000..9bef15c
--- /dev/null
+++ b/src/main/java/ml/core/world/structure/WeightedComponent.java
@@ -0,0 +1,17 @@
+package ml.core.world.structure;
+
+
+public class WeightedComponent {
+
+ public Class extends MLStructureComponent> cls;
+ public final int componentWeight;
+ public int instancesCreated;
+ public int maxComponentInstances;
+
+ public WeightedComponent(Class extends MLStructureComponent> cls, int weight, int maxPieces) {
+ this.cls = cls;
+ this.componentWeight = weight;
+ this.maxComponentInstances = maxPieces;
+ }
+
+}
diff --git a/src/main/resources/mlcore_at.cfg b/src/main/resources/mlcore_at.cfg
new file mode 100644
index 0000000..1aa192c
--- /dev/null
+++ b/src/main/resources/mlcore_at.cfg
@@ -0,0 +1,2 @@
+public net.minecraft.client.gui.inventory.GuiContainer func_146977_a () #drawSlotContents
+public net.minecraft.client.gui.inventory.GuiContainer func_74187_b () #getSlotAtPosition
\ No newline at end of file