package ttftcuts.physis.common.worldgen.structure.prop; import java.util.HashMap; import java.util.Map; import ttftcuts.physis.common.helper.WorldGenHelper; import ttftcuts.physis.common.worldgen.structure.BlockPalette; import ttftcuts.physis.common.worldgen.structure.StructureGenerator.StructurePiece; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.World; import net.minecraft.world.gen.structure.StructureBoundingBox; public class Prop { public PropType type; public Map<String, Integer> extraData; public int x,y,z; public int rotation; public boolean flipped; public StructureBoundingBox bounds = PropType.defaultBounds; public Prop(PropType type, int x, int y, int z) { this.type = type; this.x = x; this.y = y; this.z = z; this.extraData = new HashMap<String, Integer>(); this.rotation = 0; this.flipped = false; } public Prop setRotation(int rotation) { this.rotation = rotation; return this; } public Prop setFlip(boolean flip) { this.flipped = flip; return this; } public Prop setData(Object... args) { for (int i=0; i<args.length; i+=2) { if (i+1 < args.length) { if (args[i] instanceof String && args[i+1] instanceof Integer) { String key = (String)args[i]; Integer val = (int)args[i+1]; this.extraData.put(key, val); } } } return this; } public Prop updateBounds() { StructureBoundingBox newbounds = this.type.getBoundingBoxForProp(this); this.rotateBoundingBox(newbounds); this.bounds = newbounds; return this; } // ##### instance-level utils ############################################### public void placeBlock(World world, StructureBoundingBox limit, StructurePiece component, int x, int y, int z, BlockPalette.Entry block, int metaoffset) { this.placeBlock(world, limit, component, x, y, z, block, metaoffset, 0); } public void placeBlock(World world, StructureBoundingBox limit, StructurePiece component, int x, int y, int z, BlockPalette.Entry block, int metaoffset, int colour) { int tx = transformX(x,y,z, component); int ty = transformY(x,y,z, component); int tz = transformZ(x,y,z, component); int meta = block.getMeta(this.rotation, this.flipped, metaoffset, colour); if (limit.isVecInside(tx, ty, tz)) { BlockPalette.placeBlock(world, tx, ty, tz, block, meta); } } public void placeBlock(World world, StructureBoundingBox limit, StructurePiece component, int x, int y, int z, Block block, int meta) { int tx = transformX(x,y,z, component); int ty = transformY(x,y,z, component); int tz = transformZ(x,y,z, component); if (limit.isVecInside(tx, ty, tz)) { world.setBlock(tx, ty, tz, block, meta, 2); } } public void fillBlocks(World world, StructureBoundingBox limit, StructurePiece component, int minx, int miny, int minz, int maxx, int maxy, int maxz, BlockPalette.Entry block, int metaoffset) { this.fillBlocks(world, limit, component, minx, miny, minz, maxx, maxy, maxz, block, metaoffset, 0); } public void fillBlocks(World world, StructureBoundingBox limit, StructurePiece component, int minx, int miny, int minz, int maxx, int maxy, int maxz, BlockPalette.Entry block, int metaoffset, int colour) { this.fillBlocks(world, limit, component, minx, miny, minz, maxx, maxy, maxz, block.getBlock(), block.getMeta(this.rotation, this.flipped, metaoffset, colour)); } public void fillBlocks(World world, StructureBoundingBox limit, StructurePiece component, int minx, int miny, int minz, int maxx, int maxy, int maxz, Block block, int meta) { for (int x = minx; x<=maxx; x++) { for (int y = miny; y<=maxy; y++) { for (int z = minz; z<=maxz; z++) { this.placeBlock(world, limit, component, x, y, z, block, meta); } } } } public void fillFoundation(World world, StructureBoundingBox limit, StructurePiece component, int minx, int minz, int maxx, int maxz, int ylevel, BlockPalette.Entry block, int metaoffset) { int top = transformY(x,ylevel,z, component); int base = top; int tx,ty,tz; for (int x = minx; x<=maxx; x++) { for (int z = minz; z<=maxz; z++) { tx = transformX(x,ylevel,z, component); tz = transformZ(x,ylevel,z, component); if (!limit.isVecInside(tx, top, tz)) { continue; } ty = WorldGenHelper.getTopGroundBlockBelowLevel(world, tx, top, tz); if (ty > 0) { base = Math.min(base,ty); } } } base = Math.max(base - 3, 6); base -= this.y + component.bounds.minY + component.layoutOffsetY; this.fillBlocks(world, limit, component, minx, Math.min(base, ylevel), minz, maxx, ylevel, maxz, block, metaoffset); } public void clearBlock(World world, StructureBoundingBox limit, StructurePiece component, int x, int y, int z, boolean force) { int tx = transformX(x,y,z, component); int ty = transformY(x,y,z, component); int tz = transformZ(x,y,z, component); if (limit.isVecInside(tx, ty, tz)) { Block b = world.getBlock(tx, ty, tz); if (force || !b.isAir(world, tx, ty, tz)) { world.setBlockToAir(tx, ty, tz); } } } public void clearFill(World world, StructureBoundingBox limit, StructurePiece component, int minx, int miny, int minz, int maxx, int maxy, int maxz, boolean force) { for (int x = minx; x<=maxx; x++) { for (int y = miny; y<=maxy; y++) { for (int z = minz; z<=maxz; z++) { this.clearBlock(world, limit, component, x, y, z, force); } } } } protected int localTransformX(int x, int y, int z) { int fx = this.flipped ? -x : x; int rx = fx; switch (this.rotation) { case 1: rx = -z; break; case 2: rx = -fx; break; case 3: rx = z; break; default: rx = fx; } return this.x + rx; } protected int transformX(int x, int y, int z, StructurePiece component) { return this.localTransformX(x, y, z) + component.bounds.minX + component.layoutOffsetX; } protected int localTransformY(int x, int y, int z) { return this.y + y; } protected int transformY(int x, int y, int z, StructurePiece component) { return this.localTransformY(x, y, z) + component.bounds.minY + component.layoutOffsetY; } protected int localTransformZ(int x, int y, int z) { int fx = this.flipped ? -x : x; int rz = z; switch (this.rotation) { case 1: rz = fx; break; case 2: rz = -z; break; case 3: rz = -fx; break; default: rz = z; } return this.z + rz; } protected int transformZ(int x, int y, int z, StructurePiece component) { return this.localTransformZ(x, y, z) + component.bounds.minZ + component.layoutOffsetZ; } protected void rotateBoundingBox(StructureBoundingBox b) { int rminx = this.localTransformX(b.minX, b.minY, b.minZ); int rminy = this.localTransformY(b.minX, b.minY, b.minZ); int rminz = this.localTransformZ(b.minX, b.minY, b.minZ); int rmaxx = this.localTransformX(b.maxX, b.maxY, b.maxZ); int rmaxy = this.localTransformY(b.maxX, b.maxY, b.maxZ); int rmaxz = this.localTransformZ(b.maxX, b.maxY, b.maxZ); b.minX = Math.min(rminx, rmaxx); b.minY = Math.min(rminy, rmaxy); b.minZ = Math.min(rminz, rmaxz); b.maxX = Math.max(rminx, rmaxx); b.maxY = Math.max(rminy, rmaxy); b.maxZ = Math.max(rminz, rmaxz); } // ##### static utils ####################################################### public static Prop createFromNBT(NBTTagCompound tag) { int x = tag.getInteger("x"); int y = tag.getInteger("y"); int z = tag.getInteger("z"); String id = tag.getString("id"); PropType type = PropTypes.propTypes.get(id); if (type == null) { return null; } Prop prop = new Prop(type, x,y,z); prop.rotation = tag.getInteger("r"); prop.flipped = tag.getBoolean("f"); NBTTagList data = tag.getTagList("data", 10); for (int i=0; i<data.tagCount(); i++) { NBTTagCompound d = data.getCompoundTagAt(i); String key = d.getString("k"); int val = d.getInteger("v"); prop.extraData.put(key, val); } return prop; } public static NBTTagCompound writeToNBT(Prop prop) { NBTTagCompound tag = new NBTTagCompound(); tag.setInteger("x", prop.x); tag.setInteger("y", prop.y); tag.setInteger("z", prop.z); tag.setString("id", prop.type.id); tag.setInteger("r", prop.rotation); tag.setBoolean("f", prop.flipped); NBTTagList list = new NBTTagList(); for (Map.Entry<String, Integer> entry : prop.extraData.entrySet()) { NBTTagCompound datatag = new NBTTagCompound(); datatag.setString("k", entry.getKey()); datatag.setInteger("v", entry.getValue()); list.appendTag(datatag); } tag.setTag("data", list); return tag; } }