diff --git a/StevenDimDoors/mod_pocketDim/SchematicLoader.java b/StevenDimDoors/mod_pocketDim/SchematicLoader.java index 332c535..8116cec 100644 --- a/StevenDimDoors/mod_pocketDim/SchematicLoader.java +++ b/StevenDimDoors/mod_pocketDim/SchematicLoader.java @@ -1,1235 +1,21 @@ package StevenDimDoors.mod_pocketDim; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Random; +import java.io.FileNotFoundException; -import net.minecraft.block.Block; -import net.minecraft.block.BlockComparator; -import net.minecraft.block.BlockContainer; -import net.minecraft.block.BlockDoor; -import net.minecraft.block.BlockRedstoneRepeater; -import net.minecraft.block.BlockStairs; -import net.minecraft.entity.Entity; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompressedStreamTools; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.tileentity.TileEntityChest; -import net.minecraft.tileentity.TileEntityDispenser; -import net.minecraft.util.MathHelper; -import net.minecraft.util.WeightedRandomChestContent; import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -import net.minecraftforge.common.ChestGenHooks; +import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.dimHelper; -import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; -import StevenDimDoors.mod_pocketDim.ticking.MobMonolith; +import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException; public class SchematicLoader -{ - private final static int EAST_DOOR_METADATA = 0; - private final static int SOUTH_DOOR_METADATA = 1; - private final static int WEST_DOOR_METADATA = 2; - private final static int NORTH_DOOR_METADATA = 3; - private final static int MAX_VANILLA_BLOCK_ID = 158; - - private DDProperties properties = DDProperties.instance(); +{ + private SchematicLoader() { } - public SchematicLoader() { } - - private static int transformMetadata(int metadata, int orientation, int blockID) + public static void generateDungeonPocket(LinkData link, DDProperties properties) { - if (DungeonHelper.instance().metadataFlipList.contains(blockID)) - { - switch (orientation) - { - case EAST_DOOR_METADATA: - - if (blockID == Block.hopperBlock.blockID) - { - switch (metadata) - { - case 2: - metadata = 5; - break; - case 3: - metadata = 4; - break; - case 4: - metadata = 2; - break; - case 5: - metadata = 3; - break; - } - } - if(Block.blocksList[blockID] instanceof BlockStairs) - { - - switch (metadata) - { - case 0: - metadata = 2; - break; - case 1: - metadata = 3; - break; - case 2: - metadata = 1; - break; - case 3: - metadata = 0; - break; - case 7: - metadata = 4; - break; - case 6: - metadata = 5; - break; - case 5: - metadata = 7; - break; - case 4: - metadata = 6; - break; - - } - } - - else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID== Block.ladder.blockID) - { - switch (metadata) - { - - case 2: - metadata = 5; - break; - case 3: - metadata = 4; - break; - case 4: - metadata = 2; - break; - case 5: - metadata = 3; - break; - } - - } - else if (blockID==Block.vine.blockID) - { - switch (metadata) - { - - case 1: - metadata = 2; - break; - case 2: - metadata = 4; - break; - case 4: - metadata = 8; - break; - case 8: - metadata = 1; - break; - } - } - else if(blockID== Block.lever.blockID||blockID== Block.stoneButton.blockID||blockID== Block.woodenButton.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID) - { - switch (metadata) - { - case 12: - metadata = 9; - break; - case 11: - metadata = 10; - break; - case 10: - metadata = 12; - break; - case 9: - metadata = 11; - break; - case 2: - metadata = 4; - break; - case 3: - metadata = 2; - break; - case 1: - metadata = 3; - break; - case 4: - metadata = 1; - break; - } - } - else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonExtension.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID) - { - switch (metadata) - { - case 4: - metadata = 2; - break; - case 5: - metadata = 3; - break; - case 13: - metadata = 11; - break; - case 12: - metadata = 10; - break; - case 3: - metadata = 4; - break; - case 2: - metadata = 5; - break; - case 11: - metadata = 12; - break; - case 10: - metadata = 13; - break; - } - } - else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor ||blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator) - { - switch (metadata) - { - case 0: - metadata = 1; - break; - case 1: - metadata = 2; - break; - case 2: - metadata = 3; - break; - case 3: - metadata = 0; - break; - case 4: - metadata = 5; - break; - case 5: - metadata = 6; - break; - case 6: - metadata = 7; - break; - case 7: - metadata = 4; - break; - case 8: - metadata = 9; - break; - case 9: - metadata = 10; - break; - case 10: - metadata = 11; - break; - case 11: - metadata = 8; - break; - case 12: - metadata = 13; - break; - case 13: - metadata = 14; - break; - case 14: - metadata = 15; - break; - case 15: - metadata = 12; - break; - } - } - break; - case SOUTH_DOOR_METADATA: - - if (blockID == Block.hopperBlock.blockID) - { - switch (metadata) - { - case 2: - metadata = 3; - break; - case 3: - metadata = 2; - break; - case 4: - metadata = 5; - break; - case 5: - metadata = 4; - break; - } - } - - if(Block.blocksList[blockID] instanceof BlockStairs) - { - switch (metadata) - { - case 0: - metadata = 1; - break; - case 1: - metadata = 0; - break; - case 2: - metadata = 3; - break; - case 3: - metadata = 2; - break; - case 7: - metadata = 6; - break; - case 6: - metadata = 7; - break; - case 5: - metadata = 4; - break; - case 4: - metadata = 5; - break; - } - } - - else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID==Block.ladder.blockID) - { - switch (metadata) - { - case 2: - metadata = 3; - break; - case 3: - metadata = 2; - break; - case 4: - metadata = 5; - break; - case 5: - metadata = 4; - break; - } - - } - - else if(blockID==Block.vine.blockID) - { - switch (metadata) - { - - case 1: - metadata = 4; - break; - case 2: - metadata = 8; - break; - case 4: - metadata = 1; - break; - case 8: - metadata = 2; - break; - } - } - - - - - else if(blockID== Block.lever.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID) - { - switch (metadata) - { - case 12: - metadata = 11; - break; - case 11: - metadata = 12; - break; - case 10: - metadata = 9; - break; - case 9: - metadata = 10; - break; - case 2: - metadata = 1; - break; - case 3: - metadata = 4; - break; - case 1: - metadata = 2; - break; - case 4: - metadata = 3; - - break; - - } - - } - - else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID) - { - switch (metadata) - { - case 4: - metadata = 5; - break; - case 5: - metadata = 4; - break; - case 13: - metadata = 12; - break; - case 12: - metadata = 13; - break; - case 3: - metadata = 2; - break; - case 2: - metadata = 3; - break; - case 11: - metadata = 10; - break; - case 10: - metadata = 11; - break; - - } - - - - } - - else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor ||blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator) - { - switch (metadata) - { - case 0: - metadata = 2; - break; - case 1: - metadata = 3; - break; - case 2: - metadata = 0; - break; - case 3: - metadata = 1; - break; - case 4: - metadata = 6; - break; - case 5: - metadata = 7; - break; - case 6: - metadata = 4; - break; - case 7: - metadata = 5; - break; - case 8: - metadata = 10; - break; - case 9: - metadata = 11; - break; - case 10: - metadata = 8; - break; - case 11: - metadata = 9; - break; - case 12: - metadata = 14; - break; - case 13: - metadata = 15; - break; - case 14: - metadata = 12; - break; - case 15: - metadata = 13; - break; - - - } - - - - } - - break; - case WEST_DOOR_METADATA: - - if (blockID == Block.hopperBlock.blockID) - { - switch (metadata) - { - case 2: - metadata = 4; - break; - case 3: - metadata = 5; - break; - case 4: - metadata = 3; - break; - case 5: - metadata = 2; - break; - } - } - - if(Block.blocksList[blockID] instanceof BlockStairs) - { - - switch (metadata) - { - case 2: - metadata = 0; - break; - case 3: - metadata = 1; - break; - case 1: - metadata = 2; - break; - case 0: - metadata = 3; - break; - case 4: - metadata = 7; - break; - case 5: - metadata = 6; - break; - case 7: - metadata = 5; - break; - case 6: - metadata = 4; - break; - - } - } - - else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID==Block.ladder.blockID) - { - switch (metadata) - { - - case 2: - metadata = 4; - break; - case 3: - metadata = 5; - break; - case 4: - metadata = 3; - break; - case 5: - metadata = 2; - break; - - - - } - - } - - else if(blockID==Block.vine.blockID) - { - switch (metadata) - { - - case 1: - metadata = 8; - break; - case 2: - metadata = 1; - break; - case 4: - metadata = 2; - break; - case 8: - metadata = 4; - break; - } - } - - - - - else if(blockID== Block.lever.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID) - { - switch (metadata) - { - case 9: - metadata = 12; - break; - case 10: - metadata = 11; - break; - case 12: - metadata = 10; - break; - case 11: - metadata = 9; - break; - case 4: - metadata = 2; - break; - case 2: - metadata = 3; - break; - case 3: - metadata = 1; - break; - case 1: - metadata = 4; - - break; - - } - - } - - else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID) - - { - switch (metadata) - { - case 2: - metadata = 4; - break; - case 3: - metadata = 5; - break; - case 11: - metadata = 13; - break; - case 10: - metadata = 12; - break; - case 4: - metadata = 3; - break; - case 5: - metadata = 2; - break; - case 12: - metadata = 11; - break; - case 13: - metadata = 10; - break; - } - } - else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor ||blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator) - { - switch (metadata) - { - case 1: - metadata = 0; - break; - case 2: - metadata = 1; - break; - case 3: - metadata = 2; - break; - case 0: - metadata = 3; - break; - case 5: - metadata = 4; - break; - case 6: - metadata = 5; - break; - case 7: - metadata = 6; - break; - case 4: - metadata = 7; - break; - case 9: - metadata = 8; - break; - case 10: - metadata = 9; - break; - case 11: - metadata = 10; - break; - case 8: - metadata = 11; - break; - case 13: - metadata = 12; - break; - case 14: - metadata = 13; - break; - case 15: - metadata = 14; - break; - case 12: - metadata = 15; - break; - } - } - break; - case NORTH_DOOR_METADATA: - /** - * this is the default case- never need to change anything here - * - */ - break; - } - } - return metadata; - } - - public void generateSchematic(int riftX, int riftY, int riftZ, int orientation, int destDimID, int originDimID, String schematicPath) - { - short width = 0; - short height = 0; - short length = 0; - - //list of combined blockIds - short[] blocks = new short[0]; - - //block metaData - byte[] blockData = new byte[0]; - - //first 8 bits of the block ID - byte[] blockId = new byte[0]; - - //additional 4 bits of the block ID - byte[] addId = new byte[0]; - - //Variables for loading tile entities - boolean blockChanged = false; - NBTTagList tileEntities = null; - HashMap pointToTileEntityMap = new HashMap(); - - //the wooden door leading into the pocket - Point3D schematicEntrance = new Point3D(0,0,0); - - //the iron dim doors leading to more pockets - ArrayList sideLinks = new ArrayList(); - - //the wooden dim doors leading to the surface - ArrayList exitLinks = new ArrayList(); - - //the locations to spawn monoliths - ArrayList monolithSpawns = new ArrayList(); - - //load the schematic from disk - try - { - InputStream input; - String fname = schematicPath ; - - if(!(new File(fname).exists())) - { - //get file if its in the Jar - input = this.getClass().getResourceAsStream(fname); - } - else - { - //get file if in external library - System.out.println(new File(fname).exists()); - input = new FileInputStream(fname); - } - - NBTTagCompound schematicTag = CompressedStreamTools.readCompressed(input); - input.close(); //readCompressed() probably closes the stream anyway, but close again to be sure. - - //load size of schematic to generate - width = schematicTag.getShort("Width"); - height = schematicTag.getShort("Height"); - length = schematicTag.getShort("Length"); - - //load block info - blockId = schematicTag.getByteArray("Blocks"); - blockData = schematicTag.getByteArray("Data"); - addId = schematicTag.getByteArray("AddBlocks"); - - //create combined block list - blocks = new short[blockId.length]; - - //Combine the split block IDs into a single short[] - for (int index = 0; index < blockId.length; index++) - { - if ((index >> 1) >= addId.length) - { - blocks[index] = (short) (blockId[index] & 0xFF); - } - else - { - if ((index & 1) == 0) - { - blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (blockId[index] & 0xFF)); - } - else - { - blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (blockId[index] & 0xFF)); - } - } - } - - //Get the list of tile entities - tileEntities = schematicTag.getTagList("TileEntities"); - - //Map tile entity positions to the tile entity itself using a hash map - int count = tileEntities.tagCount(); - for (int index = 0; index < count; index++) - { - NBTTagCompound tileEntityData = (NBTTagCompound) tileEntities.tagAt(index); - Point3D location = new Point3D( - tileEntityData.getInteger("x"), - tileEntityData.getInteger("y"), - tileEntityData.getInteger("z")); - pointToTileEntityMap.put(location, tileEntityData); - } - } - catch (Exception e) - { - System.out.println("Error- could not find file "+schematicPath); - e.printStackTrace(); - } - - World world; - dimHelper.dimList.get(destDimID).hasBeenFilled = true; - - if (dimHelper.getWorld(destDimID) == null) - { - dimHelper.initDimension(destDimID); - } - world = dimHelper.getWorld(destDimID); + //TODO: Phase this function out in the next update. ~SenseiKiwi - //The following Random initialization code is based on code from ChunkProviderGenerate. - //It makes our generation depend on the world seed. - Random rand = new Random(world.getSeed()); - long factorA = rand.nextLong() / 2L * 2L + 1L; - long factorB = rand.nextLong() / 2L * 2L + 1L; - rand.setSeed((riftX >> 4) * factorA + (riftZ >> 4) * factorB ^ world.getSeed()); - - //Coordinates relative to the schematic, start at 0 and increase up to max width/height/length - int x, y, z; - Point3D schematicPoint = new Point3D(0, 0, 0); - - //The real point where a block will be placed - int realX, realY, realZ; - Point3D pocketPoint = new Point3D(0, 0, 0); - - //The central point of the pocket where we'll be placing the schematic - Point3D pocketCenter = new Point3D(riftX, riftY, riftZ); - Point3D zeroPoint = new Point3D(0, 0, 0); - - //The direction in which the player will enter. Will be set below. The direction is encoded using - //the same values as door metadata. Those values are not the same as Minecraft's cardinal directions. - int entryDirection = 0; - - //First loop through the schematic to load in all rift locations and Monolith spawn locations. - //Also find the entry door, which determines the final position and orientation of the dungeon. - for (y = 0; y < height; y++) - { - for (z = 0; z < length; z++) - { - for (x = 0; x < width; x++) - { - int index = y * width * length + z * width + x; - int indexBelow = (y - 1) * width * length + z * width + x; - int indexDoubleBelow = (y - 2) * width * length + z * width + x; - - int currentBlock = blocks[index]; - - //NBTTagList tileEntity = tileEntities; - //int size = tileEntity.tagCount(); - - if (currentBlock == Block.doorIron.blockID && indexBelow >= 0 && blocks[indexBelow] == Block.doorIron.blockID) - { - sideLinks.add(new Point3D(x, y, z)); - } - else if (currentBlock == Block.doorWood.blockID) - { - if (indexDoubleBelow >= 0 && blocks[indexDoubleBelow] == Block.sandStone.blockID && - blocks[indexBelow] == Block.doorWood.blockID) - { - exitLinks.add(new Point3D(x, y, z)); - } - else if (indexBelow >= 0 && blocks[indexBelow] == Block.doorWood.blockID) - { - schematicEntrance = new Point3D(x, y, z); - entryDirection = Math.abs(blockData[indexBelow] + 2) % 4; //TODO: Write a function for extracting a door's orientation from its metadata or at least change this to use bitwise operations. - } - } - else if (currentBlock == Block.endPortalFrame.blockID) - { - monolithSpawns.add(new Point3D(x, y, z)); - } - } - } - } - - //Loop to actually place the blocks - for (y = 0; y < height; y++) - { - schematicPoint.setY(y); - for (z = 0; z < length; z++) - { - schematicPoint.setZ(z); - for (x = 0; x < width; x++) - { - schematicPoint.setX(x); - - //Reinitialize pocketPoint with the current schematic coordinate system - pocketPoint.setX(x); - pocketPoint.setY(y); - pocketPoint.setZ(z); - //Transform pocketPoint into the pocket coordinate system - transformPoint(pocketPoint, schematicEntrance, orientation - entryDirection, pocketCenter); - //Store the transformed coordinates - realX = pocketPoint.getX(); - realY = pocketPoint.getY(); - realZ = pocketPoint.getZ(); - - int index = y * width * length + z * width + x; - int currentBlock = blocks[index]; - int blockMetadata = blockData[index]; - blockChanged = false; - - //replace tagging blocks with air, and mod blocks with FoR - if (currentBlock == Block.endPortalFrame.blockID) - { - currentBlock = 0; - blockChanged = true; - } - else if (currentBlock == DungeonHelper.FABRIC_OF_REALITY_EXPORT_ID) - { - currentBlock = mod_pocketDim.blockDimWall.blockID; - } - else if (currentBlock == DungeonHelper.PERMAFABRIC_EXPORT_ID) - { - currentBlock = mod_pocketDim.blockDimWallPerm.blockID; - } - else if ((Block.blocksList[currentBlock] == null && currentBlock != 0) || currentBlock > MAX_VANILLA_BLOCK_ID) - { - currentBlock = mod_pocketDim.blockDimWall.blockID; - blockChanged = true; - } - - //Place blocks and set metadata - if (currentBlock > 0) - { - int fixedMetadata; - - if (!blockChanged) - { - //Calculate new metadata for blocks that have orientations (e.g. doors, pistons) - //We're using a workaround to get the desired rotation relative to the schematic's entrance - fixedMetadata = transformMetadata(blockMetadata, (orientation + NORTH_DOOR_METADATA - entryDirection + 16) % 4, currentBlock); - } - else - { - //Don't include metadata for changed blocks. It's possible that the metadata belonged to a mod block. - //If we include it now, it could cause our Fabric of Reality to change into permafabric. - fixedMetadata = 0; - } - - //Convert vanilla doors to dim doors or place blocks - if (currentBlock == Block.doorIron.blockID) - { - setBlockDirectly(world, realX, realY, realZ, properties.DimensionalDoorID, fixedMetadata); - } - else if (currentBlock == Block.doorWood.blockID) - { - setBlockDirectly(world, realX, realY, realZ, properties.WarpDoorID, fixedMetadata); - } - else - { - setBlockDirectly(world, realX, realY, realZ, currentBlock, fixedMetadata); - } - - //Load the tile entity at this location if any exists, but only if the block wasn't changed - if (!blockChanged) - { - NBTTagCompound tileEntityData = pointToTileEntityMap.get(schematicPoint); - - if (tileEntityData != null) - { - //Change the tile entity's position - tileEntityData.setInteger("x", realX); - tileEntityData.setInteger("y", realY); - tileEntityData.setInteger("z", realZ); - //Load the tile entity into the world - world.setBlockTileEntity(realX, realY, realZ, TileEntity.createAndLoadEntity(tileEntityData)); - } - } - - //Fill empty chests and dispensers - if (Block.blocksList[currentBlock] instanceof BlockContainer) - { - TileEntity tileEntity = world.getBlockTileEntity(realX, realY, realZ); - - //Fill chests - if (tileEntity instanceof TileEntityChest) - { - TileEntityChest chest = (TileEntityChest) tileEntity; - if (isInventoryEmpty(chest)) - { - ChestGenHooks info = DDLoot.DungeonChestInfo; - WeightedRandomChestContent.generateChestContents(rand, info.getItems(rand), chest, info.getCount(rand)); - } - } - - //Fill dispensers - if (tileEntity instanceof TileEntityDispenser) - { - TileEntityDispenser dispenser = (TileEntityDispenser) tileEntity; - if (isInventoryEmpty(dispenser)) - { - dispenser.addItem(new ItemStack(Item.arrow, 64)); - } - } - } - } - } - } - } - - //We'll use an extra block here to restrict the scope of these variables to just inside the block - //This is to avoid declaration conflicts with the loops below - { - //Set the orientation of the rift exit - Point3D entranceRiftLocation = schematicEntrance.clone(); - transformPoint(entranceRiftLocation, schematicEntrance, orientation - entryDirection, pocketCenter); - LinkData sideLink = dimHelper.instance.getLinkDataFromCoords( - entranceRiftLocation.getX(), - entranceRiftLocation.getY(), - entranceRiftLocation.getZ(), - world); - sideLink.linkOrientation = world.getBlockMetadata( - entranceRiftLocation.getX(), - entranceRiftLocation.getY() - 1, - entranceRiftLocation.getZ()); - } - - //Generate the LinkData defined by the door placement, Iron Dim doors first - for(Point3D point : sideLinks) - { - int depth = dimHelper.instance.getDimDepth(originDimID) + 1; - int forwardNoise = MathHelper.getRandomIntegerInRange(rand, -50 * depth, 150 * depth); - int sidewaysNoise = MathHelper.getRandomIntegerInRange(rand, -10 * depth, 10 * depth); - - //Transform doorLocation to the pocket coordinate system - Point3D doorLocation = point.clone(); - transformPoint(doorLocation, schematicEntrance, orientation - entryDirection, pocketCenter); - int blockDirection = world.getBlockMetadata(doorLocation.getX(), doorLocation.getY() - 1, doorLocation.getZ()); - - //Rotate the link destination noise to point in the same direction as the door exit - //and add it to the door's location. Use EAST as the reference orientation since linkDestination - //is constructed as if pointing East. - Point3D linkDestination = new Point3D(forwardNoise, 0, sidewaysNoise); - transformPoint(linkDestination, zeroPoint, blockDirection - EAST_DOOR_METADATA, doorLocation); - - //Create the link between our current door and its intended exit in destination pocket - LinkData sideLink = new LinkData(destDimID, 0, - doorLocation.getX(), - doorLocation.getY(), - doorLocation.getZ(), - linkDestination.getX(), - linkDestination.getY() + 1, - linkDestination.getZ(), - true, blockDirection); - dimHelper.instance.createPocket(sideLink, true, true); - } - - //Generate linkData for wooden dim doors leading to the overworld - for(Point3D point : exitLinks) - { - try - { - //Transform doorLocation to the pocket coordinate system. - Point3D doorLocation = point.clone(); - transformPoint(doorLocation, schematicEntrance, orientation - entryDirection, pocketCenter); - int blockDirection = world.getBlockMetadata(doorLocation.getX(), doorLocation.getY() - 1, doorLocation.getZ()); - Point3D linkDestination = doorLocation.clone(); - - LinkData randomLink = dimHelper.instance.getRandomLinkData(false); - LinkData sideLink = new LinkData(destDimID, - dimHelper.dimList.get(originDimID).exitDimLink.destDimID, - doorLocation.getX(), - doorLocation.getY(), - doorLocation.getZ(), - linkDestination.getX(), - linkDestination.getY() + 1, - linkDestination.getZ(), - true, blockDirection); - - if (sideLink.destDimID == properties.LimboDimensionID) - { - sideLink.destDimID = 0; - } - else if ((rand.nextBoolean() && randomLink != null)) - { - sideLink.destDimID = randomLink.locDimID; - } - sideLink.destYCoord = yCoordHelper.getFirstUncovered(sideLink.destDimID, linkDestination.getX(), 10, linkDestination.getZ()); - - if (sideLink.destYCoord < 5) - { - sideLink.destYCoord = 70; - } - sideLink.linkOrientation = world.getBlockMetadata(linkDestination.getX(), linkDestination.getY() - 1, linkDestination.getZ()); - - dimHelper.instance.createLink(sideLink); - dimHelper.instance.createLink(sideLink.destDimID , - sideLink.locDimID, - sideLink.destXCoord, - sideLink.destYCoord, - sideLink.destZCoord, - sideLink.locXCoord, - sideLink.locYCoord, - sideLink.locZCoord, - dimHelper.instance.flipDoorMetadata(sideLink.linkOrientation)); - - if (world.getBlockId(linkDestination.getX(),linkDestination.getY() -3,linkDestination.getZ()) == properties.FabricBlockID) - { - setBlockDirectly(world,linkDestination.getX(),linkDestination.getY()-2,linkDestination.getZ(),Block.stoneBrick.blockID,0); - } - else - { - setBlockDirectly(world,linkDestination.getX(), - linkDestination.getY() - 2, - linkDestination.getZ(), - world.getBlockId(linkDestination.getX(), - linkDestination.getY() -3, - linkDestination.getZ()), - world.getBlockMetadata(linkDestination.getX(), - linkDestination.getY() -3, - linkDestination.getZ())); - } - } - catch (Exception E) - { - E.printStackTrace(); - } - } - - //Spawn monoliths - for(Point3D point : monolithSpawns) - { - //Transform the frame block's location to the pocket coordinate system - Point3D frameLocation = point.clone(); - transformPoint(frameLocation, schematicEntrance, orientation - entryDirection, pocketCenter); - - Entity mob = new MobMonolith(world); - mob.setLocationAndAngles(frameLocation.getX(), frameLocation.getY(), frameLocation.getZ(), 1, 1); //TODO: Why not set the angles to 0? @.@ ~SenseiKiwi - world.spawnEntityInWorld(mob); - } - } - - private static boolean isInventoryEmpty(IInventory inventory) - { - int size = inventory.getSizeInventory(); - for (int index = 0; index < size; index++) - { - if (inventory.getStackInSlot(index) != null) - { - return false; - } - } - return true; - } - - private static void transformPoint(Point3D position, Point3D srcOrigin, int angle, Point3D destOrigin) - { - //This function receives a position (e.g. point in schematic space), translates it relative - //to a source coordinate system (e.g. the point that will be the center of a schematic), - //then rotates and translates it to obtain the corresponding point in a destination - //coordinate system (e.g. the location of the entry rift in the pocket being generated). - //The result is returned by overwriting the original position so that new object references - //aren't needed. That way, repeated use of this function will not incur as much overhead. - - //Position is only overwritten at the end, so it's okay to provide it as srcOrigin or destOrigin as well. - - int tx = position.getX() - srcOrigin.getX(); - int ty = position.getY() - srcOrigin.getY(); - int tz = position.getZ() - srcOrigin.getZ(); - - //"int angle" specifies a rotation consistent with Minecraft's orientation system. - //That means each increment of 1 in angle would be a 90-degree clockwise turn. - //Given a starting direction A and a destination direction B, the rotation would be - //calculated by (B - A). - - //Adjust angle into the expected range - if (angle < 0) - { - int correction = -(angle / 4); - angle = angle + 4 * (correction + 1); - } - angle = angle % 4; - - int rx; - int rz; - switch (angle) - { - case 0: //No rotation - rx = tx; - rz = tz; - break; - case 1: //90 degrees clockwise - rx = -tz; - rz = tx; - break; - case 2: //180 degrees - rx = -tx; - rz = -tz; - break; - case 3: //270 degrees clockwise - rx = tz; - rz = -tx; - - break; - default: //This should never happen - throw new IllegalStateException("Invalid angle value. This should never happen!"); - } - - position.setX( rx + destOrigin.getX() ); - position.setY( ty + destOrigin.getY() ); - position.setZ( rz + destOrigin.getZ() ); - } - - public void generateDungeonPocket(LinkData link) - { String filePath=DungeonHelper.instance().defaultBreak.schematicPath; if(dimHelper.dimList.containsKey(link.destDimID)) { @@ -1239,39 +25,38 @@ public class SchematicLoader } filePath = dimHelper.dimList.get(link.destDimID).dungeonGenerator.schematicPath; } - this.generateSchematic(link.destXCoord, link.destYCoord, link.destZCoord, link.linkOrientation, link.destDimID, link.locDimID, filePath); - } - - - public void setBlockDirectly(World world, int x, int y, int z,int id, int metadata) - { - if (Block.blocksList[id] == null) - { - return; - } - - int cX = x >> 4; - int cZ = z >> 4; - int cY = y >> 4; - Chunk chunk; - - //TODO: This really seems odd to me. Like it's wrong. ~SenseiKiwi - int chunkX=(x % 16)< 0 ? ((x) % 16)+16 : ((x) % 16); - int chunkZ=((z) % 16)< 0 ? ((z) % 16)+16 : ((z) % 16); - + + //this.generateSchematic(link.destXCoord, link.destYCoord, link.destZCoord, link.linkOrientation, link.destDimID, link.locDimID, filePath); + try { - chunk = world.getChunkFromChunkCoords(cX, cZ); - if (chunk.getBlockStorageArray()[cY] == null) + int originDimID = link.locDimID; + int destDimID = link.destDimID; + DungeonSchematic dungeon; + if ((new File(filePath)).exists()) { - chunk.getBlockStorageArray()[cY] = new ExtendedBlockStorage(cY << 4, !world.provider.hasNoSky); + dungeon = DungeonSchematic.readFromFile(filePath); } - - - chunk.getBlockStorageArray()[cY].setExtBlockID(chunkX, (y) & 15, chunkZ, id); - chunk.getBlockStorageArray()[cY].setExtBlockMetadata(chunkX, (y) & 15, chunkZ, metadata); + else + { + dungeon = DungeonSchematic.readFromResource(filePath); + } + dungeon.applyImportFilters(properties); + + dimHelper.dimList.get(destDimID).hasBeenFilled = true; + if (dimHelper.getWorld(destDimID) == null) + { + dimHelper.initDimension(destDimID); + } + World world = dimHelper.getWorld(destDimID); + + dungeon.copyToWorld(world, new Point3D(link.destXCoord, link.destYCoord, link.destZCoord), link.linkOrientation, originDimID, destDimID); } - catch(Exception e) + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + catch (InvalidSchematicException e) { e.printStackTrace(); } diff --git a/StevenDimDoors/mod_pocketDim/commands/CommandCreateDungeonRift.java b/StevenDimDoors/mod_pocketDim/commands/CommandCreateDungeonRift.java index 281df90..a924fd8 100644 --- a/StevenDimDoors/mod_pocketDim/commands/CommandCreateDungeonRift.java +++ b/StevenDimDoors/mod_pocketDim/commands/CommandCreateDungeonRift.java @@ -1,17 +1,13 @@ package StevenDimDoors.mod_pocketDim.commands; import java.io.File; -import java.io.FileNotFoundException; import java.util.Collection; import net.minecraft.entity.player.EntityPlayer; -import StevenDimDoors.mod_pocketDim.DDProperties; import StevenDimDoors.mod_pocketDim.DungeonGenerator; import StevenDimDoors.mod_pocketDim.LinkData; -import StevenDimDoors.mod_pocketDim.dungeon.DungeonSchematic; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.dimHelper; -import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException; public class CommandCreateDungeonRift extends DDCommandBase { @@ -96,7 +92,7 @@ public class CommandCreateDungeonRift extends DDCommandBase { dungeon = DungeonSchematic.readFromResource(result.schematicPath); } - dungeon.ApplyImportFilters(DDProperties.instance()); + dungeon.applyImportFilters(DDProperties.instance()); dungeon.copyToWorld(sender.worldObj, x, y, z); } catch (InvalidSchematicException e) { e.printStackTrace(); diff --git a/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java b/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java index b364cbf..5827666 100644 --- a/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java +++ b/StevenDimDoors/mod_pocketDim/dungeon/DungeonSchematic.java @@ -4,25 +4,51 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; +import java.util.Random; import java.util.TreeMap; +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MathHelper; import net.minecraft.world.World; import StevenDimDoors.mod_pocketDim.DDProperties; +import StevenDimDoors.mod_pocketDim.LinkData; +import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.helpers.dimHelper; +import StevenDimDoors.mod_pocketDim.helpers.yCoordHelper; +import StevenDimDoors.mod_pocketDim.schematic.BlockRotator; import StevenDimDoors.mod_pocketDim.schematic.CompoundFilter; import StevenDimDoors.mod_pocketDim.schematic.InvalidSchematicException; import StevenDimDoors.mod_pocketDim.schematic.ReplacementFilter; import StevenDimDoors.mod_pocketDim.schematic.Schematic; +import StevenDimDoors.mod_pocketDim.ticking.MobMonolith; public class DungeonSchematic extends Schematic { private static final short MAX_VANILLA_BLOCK_ID = 158; private static final short STANDARD_FABRIC_OF_REALITY_ID = 1973; private static final short STANDARD_ETERNAL_FABRIC_ID = 220; + private static final short STANDARD_WARP_DOOR_ID = (short) Block.doorWood.blockID;//1975; + private static final short STANDARD_DIMENSIONAL_DOOR_ID = (short) Block.doorIron.blockID;//1970; + private static final short MONOLITH_SPAWN_MARKER_ID = (short) Block.endPortalFrame.blockID; + private static final short EXIT_DOOR_MARKER_ID = (short) Block.sandStone.blockID; + + private int orientation; + private Point3D entranceDoorLocation; + private ArrayList exitDoorLocations; + private ArrayList dimensionalDoorLocations; + private ArrayList monolithSpawnLocations; + private static final short[] MOD_BLOCK_FILTER_EXCEPTIONS = new short[] { STANDARD_FABRIC_OF_REALITY_ID, - STANDARD_ETERNAL_FABRIC_ID + STANDARD_ETERNAL_FABRIC_ID//, + //STANDARD_WARP_DOOR_ID, + //STANDARD_DIMENSIONAL_DOOR_ID }; private DungeonSchematic(Schematic source) @@ -30,6 +56,16 @@ public class DungeonSchematic extends Schematic { super(source); } + public int getOrientation() + { + return orientation; + } + + public Point3D getEntranceDoorLocation() + { + return entranceDoorLocation; + } + private DungeonSchematic() { //Used to create a dummy instance for readFromResource() @@ -59,8 +95,25 @@ public class DungeonSchematic extends Schematic { return new DungeonSchematic(Schematic.readFromStream(schematicStream)); } - public void ApplyImportFilters(DDProperties properties) + public void applyImportFilters(DDProperties properties) { + //Search for special blocks (warp doors, dim doors, and end portal frames that mark Monolith spawn points) + SpecialBlockFinder finder = new SpecialBlockFinder(STANDARD_WARP_DOOR_ID, STANDARD_DIMENSIONAL_DOOR_ID, + MONOLITH_SPAWN_MARKER_ID, EXIT_DOOR_MARKER_ID); + applyFilter(finder); + + orientation = (finder.getEntranceOrientation() + 2) & 3; //Flip the entrance's orientation to get the dungeon's orientation + entranceDoorLocation = finder.getEntranceDoorLocation(); + exitDoorLocations = finder.getExitDoorLocations(); + dimensionalDoorLocations = finder.getDimensionalDoorLocations(); + monolithSpawnLocations = finder.getMonolithSpawnLocations(); + + //TODO: Debug prints below. Please remove them before the next release! + System.out.println(entranceDoorLocation != null ? "Entrance was found" : "Entrance was not found"); + System.out.printf("There are %d exit doors in this room\n", exitDoorLocations.size()); + System.out.printf("There are %d dim doors in this room\n", dimensionalDoorLocations.size()); + System.out.printf("There are %d monolith spawn points in this room\n", monolithSpawnLocations.size()); + //Filter out mod blocks except some of our own CompoundFilter standardizer = new CompoundFilter(); standardizer.addFilter(new ModBlockFilter(MAX_VANILLA_BLOCK_ID, MOD_BLOCK_FILTER_EXCEPTIONS, @@ -76,11 +129,11 @@ public class DungeonSchematic extends Schematic { standardizer.addFilter(new ReplacementFilter(entry.getValue(), entry.getKey())); } } - standardizer.apply(this, this.blocks, this.metadata); + applyFilter(standardizer); } - public void ApplyExportFilters(DDProperties properties) - { + public void applyExportFilters(DDProperties properties) + { //Check if some block IDs assigned by Forge differ from our standard IDs //If so, change the IDs to standard values CompoundFilter standardizer = new CompoundFilter(); @@ -93,7 +146,14 @@ public class DungeonSchematic extends Schematic { standardizer.addFilter(new ReplacementFilter(entry.getKey(), entry.getValue())); } } - standardizer.apply(this, this.blocks, this.metadata); + + //Filter out mod blocks except some of our own + //This comes after ID standardization because the mod block filter relies on standardized IDs + standardizer.addFilter(new ModBlockFilter(MAX_VANILLA_BLOCK_ID, MOD_BLOCK_FILTER_EXCEPTIONS, + (short) properties.FabricBlockID, (byte) 0)); + + + applyFilter(standardizer); } private Map getAssignedToStandardIDMapping(DDProperties properties) @@ -102,6 +162,8 @@ public class DungeonSchematic extends Schematic { TreeMap mapping = new TreeMap(); mapping.put((short) properties.FabricBlockID, STANDARD_FABRIC_OF_REALITY_ID); mapping.put((short) properties.PermaFabricBlockID, STANDARD_ETERNAL_FABRIC_ID); + mapping.put((short) properties.WarpDoorID, STANDARD_WARP_DOOR_ID); + mapping.put((short) properties.DimensionalDoorID, STANDARD_DIMENSIONAL_DOOR_ID); return mapping; } @@ -109,4 +171,254 @@ public class DungeonSchematic extends Schematic { { return new DungeonSchematic(Schematic.copyFromWorld(world, x, y, z, width, height, length, doCompactBounds)); } + + public void copyToWorld(World world, Point3D pocketCenter, int dungeonOrientation, int originDimID, int destDimID) + { + //TODO: This function is an improvised solution so we can get the release moving. In the future, + //we should generalize block tranformations and implement support for them at the level of Schematic, + //then just use that support from DungeonSchematic instead of making this local fix. + //It might be easiest to support transformations using a WorldOperation + + final int turnAngle = dungeonOrientation - orientation; + + + int index; + int count; + int blockID; + int blockMeta; + int dx, dy, dz; + Point3D pocketPoint = new Point3D(0, 0, 0); + + //Copy blocks and metadata into the world + index = 0; + for (dy = 0; dy < height; dy++) + { + for (dz = 0; dz < length; dz++) + { + for (dx = 0; dx < width; dx++) + { + pocketPoint.setX(dx); + pocketPoint.setY(dy); + pocketPoint.setZ(dz); + blockID = blocks[index]; + BlockRotator.transformPoint(pocketPoint, entranceDoorLocation, turnAngle, pocketCenter); + blockMeta = BlockRotator.transformMetadata(metadata[index], turnAngle + BlockRotator.NORTH_DOOR_METADATA, blockID); + + //In the future, we might want to make this more efficient by building whole chunks at a time + setBlockDirectly(world, pocketPoint.getX(), pocketPoint.getY(), pocketPoint.getZ(), blockID, blockMeta); + index++; + } + } + } + //Copy tile entities into the world + count = tileEntities.tagCount(); + for (index = 0; index < count; index++) + { + NBTTagCompound tileTag = (NBTTagCompound) tileEntities.tagAt(index); + //Rewrite its location to be in world coordinates + pocketPoint.setX(tileTag.getInteger("x")); + pocketPoint.setY(tileTag.getInteger("y")); + pocketPoint.setZ(tileTag.getInteger("z")); + BlockRotator.transformPoint(pocketPoint, entranceDoorLocation, turnAngle, pocketCenter); + tileTag.setInteger("x", pocketPoint.getX()); + tileTag.setInteger("y", pocketPoint.getY()); + tileTag.setInteger("z", pocketPoint.getZ()); + //Load the tile entity and put it in the world + world.setBlockTileEntity(pocketPoint.getX(), pocketPoint.getY(), pocketPoint.getZ(), TileEntity.createAndLoadEntity(tileTag)); + } + + setUpDungeon(world, pocketCenter, turnAngle, originDimID, destDimID); + } + + private void setUpDungeon(World world, Point3D pocketCenter, int turnAngle, int originDimID, int destDimID) + { + //The following Random initialization code is based on code from ChunkProviderGenerate. + //It makes our generation depend on the world seed. + Random random = new Random(world.getSeed()); + long factorA = random.nextLong() / 2L * 2L + 1L; + long factorB = random.nextLong() / 2L * 2L + 1L; + random.setSeed((pocketCenter.getX() >> 4) * factorA + (pocketCenter.getZ() >> 4) * factorB ^ world.getSeed()); + + //Transform dungeon corners + Point3D minCorner = new Point3D(0, 0, 0); + Point3D maxCorner = new Point3D(width - 1, height - 1, length - 1); + transformCorners(entranceDoorLocation, pocketCenter, turnAngle, minCorner, maxCorner); + + //Fill empty chests and dispensers + FillContainersOperation filler = new FillContainersOperation(random); + filler.apply(world, minCorner, maxCorner); + + //Set up entrance door rift + setUpEntranceDoorLink(world, entranceDoorLocation, turnAngle, pocketCenter); + + //Set up link data for dimensional doors + for (Point3D location : dimensionalDoorLocations) + { + setUpDimensionalDoorLink(world, location, entranceDoorLocation, turnAngle, pocketCenter, originDimID, destDimID, random); + } + + //Set up link data for exit door + for (Point3D location : exitDoorLocations) + { + setUpExitDoorLink(world, location, entranceDoorLocation, turnAngle, pocketCenter, originDimID, destDimID, random); + } + + //Remove end portal frames and spawn Monoliths + for (Point3D location : monolithSpawnLocations) + { + spawnMonolith(world, location, entranceDoorLocation, turnAngle, pocketCenter); + } + } + + private static void transformCorners(Point3D schematicEntrance, Point3D pocketCenter, int turnAngle, Point3D minCorner, Point3D maxCorner) + { + int temp; + BlockRotator.transformPoint(minCorner, schematicEntrance, turnAngle, pocketCenter); + BlockRotator.transformPoint(maxCorner, schematicEntrance, turnAngle, pocketCenter); + if (minCorner.getX() > maxCorner.getX()) + { + temp = minCorner.getX(); + minCorner.setX(maxCorner.getX()); + maxCorner.setX(temp); + } + if (minCorner.getY() > maxCorner.getY()) + { + temp = minCorner.getY(); + minCorner.setY(maxCorner.getY()); + maxCorner.setY(temp); + } + if (minCorner.getZ() > maxCorner.getZ()) + { + temp = minCorner.getZ(); + minCorner.setZ(maxCorner.getZ()); + maxCorner.setZ(temp); + } + } + + private static void setUpEntranceDoorLink(World world, Point3D entrance, int rotation, Point3D pocketCenter) + { + //Set the orientation of the rift exit + Point3D entranceRiftLocation = entrance.clone(); + BlockRotator.transformPoint(entranceRiftLocation, entrance, rotation, pocketCenter); + LinkData sideLink = dimHelper.instance.getLinkDataFromCoords( + entranceRiftLocation.getX(), + entranceRiftLocation.getY(), + entranceRiftLocation.getZ(), + world); + sideLink.linkOrientation = world.getBlockMetadata( + entranceRiftLocation.getX(), + entranceRiftLocation.getY() - 1, + entranceRiftLocation.getZ()); + } + + private static void setUpExitDoorLink(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter, int originDimID, int destDimID, Random random) + { + try + { + //TODO: Hax, remove this later + DDProperties properties = DDProperties.instance(); + + //Transform doorLocation to the pocket coordinate system. + Point3D location = point.clone(); + BlockRotator.transformPoint(location, entrance, rotation, pocketCenter); + int blockDirection = world.getBlockMetadata(location.getX(), location.getY() - 1, location.getZ()); + Point3D linkDestination = location.clone(); + + LinkData randomLink = dimHelper.instance.getRandomLinkData(false); + LinkData sideLink = new LinkData(destDimID, + dimHelper.dimList.get(originDimID).exitDimLink.destDimID, + location.getX(), + location.getY(), + location.getZ(), + linkDestination.getX(), + linkDestination.getY() + 1, + linkDestination.getZ(), + true, blockDirection); + + if (sideLink.destDimID == properties.LimboDimensionID) + { + sideLink.destDimID = 0; + } + else if ((random.nextBoolean() && randomLink != null)) + { + sideLink.destDimID = randomLink.locDimID; + } + sideLink.destYCoord = yCoordHelper.getFirstUncovered(sideLink.destDimID, linkDestination.getX(), 10, linkDestination.getZ()); + + if (sideLink.destYCoord < 5) + { + sideLink.destYCoord = 70; + } + sideLink.linkOrientation = world.getBlockMetadata(linkDestination.getX(), linkDestination.getY() - 1, linkDestination.getZ()); + + dimHelper.instance.createLink(sideLink); + dimHelper.instance.createLink(sideLink.destDimID , + sideLink.locDimID, + sideLink.destXCoord, + sideLink.destYCoord, + sideLink.destZCoord, + sideLink.locXCoord, + sideLink.locYCoord, + sideLink.locZCoord, + dimHelper.instance.flipDoorMetadata(sideLink.linkOrientation)); + + if (world.getBlockId(linkDestination.getX(), linkDestination.getY() - 3, linkDestination.getZ()) == properties.FabricBlockID) + { + setBlockDirectly(world, linkDestination.getX(), linkDestination.getY() - 2, linkDestination.getZ(), Block.stoneBrick.blockID, 0); + } + else + { + setBlockDirectly(world,linkDestination.getX(), linkDestination.getY() - 2, linkDestination.getZ(), + world.getBlockId(linkDestination.getX(), linkDestination.getY() - 3, linkDestination.getZ()), + world.getBlockMetadata(linkDestination.getX(), linkDestination.getY() - 3, linkDestination.getZ())); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + private static void setUpDimensionalDoorLink(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter, int originDimID, int destDimID, Random random) + { + int depth = dimHelper.instance.getDimDepth(originDimID) + 1; + int forwardNoise = MathHelper.getRandomIntegerInRange(random, -50 * depth, 150 * depth); + int sidewaysNoise = MathHelper.getRandomIntegerInRange(random, -10 * depth, 10 * depth); + + //Transform doorLocation to the pocket coordinate system + Point3D location = point.clone(); + BlockRotator.transformPoint(location, entrance, rotation, pocketCenter); + int blockDirection = world.getBlockMetadata(location.getX(), location.getY() - 1, location.getZ()); + + //Rotate the link destination noise to point in the same direction as the door exit + //and add it to the door's location. Use EAST as the reference orientation since linkDestination + //is constructed as if pointing East. + Point3D linkDestination = new Point3D(forwardNoise, 0, sidewaysNoise); + Point3D zeroPoint = new Point3D(0, 0, 0); + BlockRotator.transformPoint(linkDestination, zeroPoint, blockDirection - BlockRotator.EAST_DOOR_METADATA, location); + + //Create the link between our current door and its intended exit in destination pocket + LinkData sideLink = new LinkData(destDimID, 0, + location.getX(), + location.getY(), + location.getZ(), + linkDestination.getX(), + linkDestination.getY() + 1, + linkDestination.getZ(), + true, blockDirection); + dimHelper.instance.createPocket(sideLink, true, true); + } + + private static void spawnMonolith(World world, Point3D point, Point3D entrance, int rotation, Point3D pocketCenter) + { + //Transform the frame block's location to the pocket coordinate system + Point3D location = point.clone(); + BlockRotator.transformPoint(location, entrance, rotation, pocketCenter); + //Remove frame block + setBlockDirectly(world, location.getX(), location.getY(), location.getZ(), 0, 0); + //Spawn Monolith + Entity mob = new MobMonolith(world); + mob.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), 1, 1); + world.spawnEntityInWorld(mob); + } } diff --git a/StevenDimDoors/mod_pocketDim/dungeon/FillContainersOperation.java b/StevenDimDoors/mod_pocketDim/dungeon/FillContainersOperation.java new file mode 100644 index 0000000..7979eaf --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/dungeon/FillContainersOperation.java @@ -0,0 +1,75 @@ +package StevenDimDoors.mod_pocketDim.dungeon; + +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.util.WeightedRandomChestContent; +import net.minecraft.world.World; +import net.minecraftforge.common.ChestGenHooks; +import StevenDimDoors.mod_pocketDim.DDLoot; +import StevenDimDoors.mod_pocketDim.schematic.WorldOperation; + +public class FillContainersOperation extends WorldOperation +{ + private Random random; + + public FillContainersOperation(Random random) + { + super("FillContainersOperation"); + this.random = random; + } + + @Override + protected boolean applyToBlock(World world, int x, int y, int z) + { + int blockID = world.getBlockId(x, y, z); + + //Fill empty chests and dispensers + if (Block.blocksList[blockID] instanceof BlockContainer) + { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + //Fill chests + if (tileEntity instanceof TileEntityChest) + { + TileEntityChest chest = (TileEntityChest) tileEntity; + if (isInventoryEmpty(chest)) + { + ChestGenHooks info = DDLoot.DungeonChestInfo; + WeightedRandomChestContent.generateChestContents(random, info.getItems(random), chest, info.getCount(random)); + } + } + + //Fill dispensers + if (tileEntity instanceof TileEntityDispenser) + { + TileEntityDispenser dispenser = (TileEntityDispenser) tileEntity; + if (isInventoryEmpty(dispenser)) + { + dispenser.addItem(new ItemStack(Item.arrow, 64)); + } + } + } + return true; + } + + private static boolean isInventoryEmpty(IInventory inventory) + { + int size = inventory.getSizeInventory(); + for (int index = 0; index < size; index++) + { + if (inventory.getStackInSlot(index) != null) + { + return false; + } + } + return true; + } +} diff --git a/StevenDimDoors/mod_pocketDim/dungeon/SpecialBlockFinder.java b/StevenDimDoors/mod_pocketDim/dungeon/SpecialBlockFinder.java new file mode 100644 index 0000000..94efdd4 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/dungeon/SpecialBlockFinder.java @@ -0,0 +1,107 @@ +package StevenDimDoors.mod_pocketDim.dungeon; + +import java.util.ArrayList; + +import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.schematic.Schematic; +import StevenDimDoors.mod_pocketDim.schematic.SchematicFilter; + +public class SpecialBlockFinder extends SchematicFilter { + + private short warpDoorID; + private short dimensionalDoorID; + private short monolithSpawnMarkerID; + private short exitMarkerID; + private int entranceOrientation; + private Schematic schematic; + private Point3D entranceDoorLocation; + private ArrayList exitDoorLocations; + private ArrayList dimensionalDoorLocations; + private ArrayList monolithSpawnLocations; + + public SpecialBlockFinder(short warpDoorID, short dimensionalDoorID, short monolithSpawnMarkerID, short exitMarkerID) + { + super("SpecialBlockFinder"); + this.warpDoorID = warpDoorID; + this.dimensionalDoorID = dimensionalDoorID; + this.monolithSpawnMarkerID = monolithSpawnMarkerID; + this.exitMarkerID = exitMarkerID; + this.entranceDoorLocation = null; + this.entranceOrientation = 0; + this.exitDoorLocations = new ArrayList(); + this.dimensionalDoorLocations = new ArrayList(); + this.monolithSpawnLocations = new ArrayList(); + this.schematic = null; + } + + public int getEntranceOrientation() { + return entranceOrientation; + } + + public Point3D getEntranceDoorLocation() { + return entranceDoorLocation; + } + + public ArrayList getExitDoorLocations() { + return exitDoorLocations; + } + + public ArrayList getDimensionalDoorLocations() { + return dimensionalDoorLocations; + } + + public ArrayList getMonolithSpawnLocations() { + return monolithSpawnLocations; + } + + @Override + protected boolean initialize(Schematic schematic, short[] blocks, byte[] metadata) + { + this.schematic = schematic; + return true; + } + + @Override + protected boolean applyToBlock(int index, short[] blocks, byte[] metadata) + { + int indexBelow; + int indexDoubleBelow; + + if (blocks[index] == monolithSpawnMarkerID) + { + monolithSpawnLocations.add(schematic.calculatePoint(index)); + } + else if (blocks[index] == dimensionalDoorID) + { + indexBelow = schematic.calculateIndexBelow(index); + if (indexBelow >= 0 && blocks[indexBelow] == dimensionalDoorID) + { + dimensionalDoorLocations.add(schematic.calculatePoint(index)); + } + } + else if (blocks[index] == warpDoorID) + { + indexBelow = schematic.calculateIndexBelow(index); + if (indexBelow >= 0 && blocks[indexBelow] == warpDoorID) + { + indexDoubleBelow = schematic.calculateIndexBelow(indexBelow); + if (indexDoubleBelow >= 0 && blocks[indexDoubleBelow] == exitMarkerID) + { + exitDoorLocations.add(schematic.calculatePoint(index)); + } + else if (entranceDoorLocation == null) + { + entranceDoorLocation = schematic.calculatePoint(index); + entranceOrientation = (metadata[indexBelow] & 3); + } + } + } + return true; + } + + @Override + protected boolean terminates() + { + return false; + } +} diff --git a/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java b/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java index 9390339..6812ccf 100644 --- a/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java +++ b/StevenDimDoors/mod_pocketDim/helpers/DungeonHelper.java @@ -385,7 +385,7 @@ public class DungeonHelper short size = (short) 2 * MAX_EXPORT_RADIUS + 1; DungeonSchematic dungeon = DungeonSchematic.copyFromWorld(world, centerX - MAX_EXPORT_RADIUS, centerY - MAX_EXPORT_RADIUS, centerZ - MAX_EXPORT_RADIUS, size, size, size, true); - dungeon.ApplyExportFilters(properties); + dungeon.applyExportFilters(properties); dungeon.writeToFile(exportPath); return true; } diff --git a/StevenDimDoors/mod_pocketDim/helpers/dimHelper.java b/StevenDimDoors/mod_pocketDim/helpers/dimHelper.java index 795c603..dd4e979 100644 --- a/StevenDimDoors/mod_pocketDim/helpers/dimHelper.java +++ b/StevenDimDoors/mod_pocketDim/helpers/dimHelper.java @@ -39,6 +39,7 @@ import StevenDimDoors.mod_pocketDim.LinkData; import StevenDimDoors.mod_pocketDim.ObjectSaveInputStream; import StevenDimDoors.mod_pocketDim.PacketHandler; import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.SchematicLoader; import StevenDimDoors.mod_pocketDim.TileEntityRift; import StevenDimDoors.mod_pocketDim.mod_pocketDim; import StevenDimDoors.mod_pocketDim.world.LimboProvider; @@ -759,12 +760,8 @@ public class dimHelper extends DimensionManager } else if(!data.hasBeenFilled&&data.isPocket&&data.isDimRandomRift) { - //System.out.println("genning dungeon pocket"); - - - mod_pocketDim.loader.generateDungeonPocket(incomingLink); + SchematicLoader.generateDungeonPocket(incomingLink, properties); data.hasBeenFilled=true; - } } @@ -778,7 +775,7 @@ public class dimHelper extends DimensionManager mod_pocketDim.hasInitDims=true; this.load(); - if(!this.dimList.isEmpty()) + if(!dimHelper.dimList.isEmpty()) { diff --git a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java index 21c47d7..d360e09 100644 --- a/StevenDimDoors/mod_pocketDim/mod_pocketDim.java +++ b/StevenDimDoors/mod_pocketDim/mod_pocketDim.java @@ -32,7 +32,6 @@ import StevenDimDoors.mod_pocketDim.commands.CommandExportDungeon; import StevenDimDoors.mod_pocketDim.commands.CommandPrintDimensionData; import StevenDimDoors.mod_pocketDim.commands.CommandPruneDimensions; import StevenDimDoors.mod_pocketDim.commands.CommandResetDungeons; -import StevenDimDoors.mod_pocketDim.helpers.BlockRotationHelper; import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; import StevenDimDoors.mod_pocketDim.helpers.dimHelper; import StevenDimDoors.mod_pocketDim.items.ItemBlockDimWall; @@ -98,9 +97,7 @@ public class mod_pocketDim @Instance("PocketDimensions") public static mod_pocketDim instance = new mod_pocketDim(); - public static SchematicLoader loader; public static pocketTeleporter teleporter; - public static BlockRotationHelper rotationHelper; public static Block transientDoor; public static Block ExitDoor; @@ -169,11 +166,9 @@ public class mod_pocketDim //These fields MUST be initialized after properties are loaded to prevent //instances from holding onto null references to the properties. - loader = new SchematicLoader(); teleporter = new pocketTeleporter(); tracker = new PlayerRespawnTracker(); riftGen = new RiftGenerator(); - rotationHelper = new BlockRotationHelper(); } @Init diff --git a/StevenDimDoors/mod_pocketDim/schematic/BlockRotator.java b/StevenDimDoors/mod_pocketDim/schematic/BlockRotator.java new file mode 100644 index 0000000..8960c23 --- /dev/null +++ b/StevenDimDoors/mod_pocketDim/schematic/BlockRotator.java @@ -0,0 +1,755 @@ +package StevenDimDoors.mod_pocketDim.schematic; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockComparator; +import net.minecraft.block.BlockDoor; +import net.minecraft.block.BlockRedstoneRepeater; +import net.minecraft.block.BlockStairs; +import StevenDimDoors.mod_pocketDim.Point3D; +import StevenDimDoors.mod_pocketDim.helpers.DungeonHelper; + +public class BlockRotator +{ + //This class is temporary. It's just a place in which to hold the old block rotation and transformation code + //until we can rewrite it. + + public final static int EAST_DOOR_METADATA = 0; + private final static int SOUTH_DOOR_METADATA = 1; + private final static int WEST_DOOR_METADATA = 2; + public final static int NORTH_DOOR_METADATA = 3; + + public static int transformMetadata(int metadata, int orientation, int blockID) + { + //TODO: Replace this horrible function with something prettier. We promise we will for the next version, + //after switching to MC 1.6. + + //Hax to fix negative orientations + orientation += 1 << 16; + orientation %= 4; + + if (DungeonHelper.instance().metadataFlipList.contains(blockID)) + { + switch (orientation) + { + case EAST_DOOR_METADATA: + + if (blockID == Block.hopperBlock.blockID) + { + switch (metadata) + { + case 2: + metadata = 5; + break; + case 3: + metadata = 4; + break; + case 4: + metadata = 2; + break; + case 5: + metadata = 3; + break; + } + } + if(Block.blocksList[blockID] instanceof BlockStairs) + { + + switch (metadata) + { + case 0: + metadata = 2; + break; + case 1: + metadata = 3; + break; + case 2: + metadata = 1; + break; + case 3: + metadata = 0; + break; + case 7: + metadata = 4; + break; + case 6: + metadata = 5; + break; + case 5: + metadata = 7; + break; + case 4: + metadata = 6; + break; + + } + } + + else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID== Block.ladder.blockID) + { + switch (metadata) + { + + case 2: + metadata = 5; + break; + case 3: + metadata = 4; + break; + case 4: + metadata = 2; + break; + case 5: + metadata = 3; + break; + } + + } + else if (blockID==Block.vine.blockID) + { + switch (metadata) + { + + case 1: + metadata = 2; + break; + case 2: + metadata = 4; + break; + case 4: + metadata = 8; + break; + case 8: + metadata = 1; + break; + } + } + else if(blockID== Block.lever.blockID||blockID== Block.stoneButton.blockID||blockID== Block.woodenButton.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID) + { + switch (metadata) + { + case 12: + metadata = 9; + break; + case 11: + metadata = 10; + break; + case 10: + metadata = 12; + break; + case 9: + metadata = 11; + break; + case 2: + metadata = 4; + break; + case 3: + metadata = 2; + break; + case 1: + metadata = 3; + break; + case 4: + metadata = 1; + break; + } + } + else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonExtension.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID) + { + switch (metadata) + { + case 4: + metadata = 2; + break; + case 5: + metadata = 3; + break; + case 13: + metadata = 11; + break; + case 12: + metadata = 10; + break; + case 3: + metadata = 4; + break; + case 2: + metadata = 5; + break; + case 11: + metadata = 12; + break; + case 10: + metadata = 13; + break; + } + } + else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor ||blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator) + { + switch (metadata) + { + case 0: + metadata = 1; + break; + case 1: + metadata = 2; + break; + case 2: + metadata = 3; + break; + case 3: + metadata = 0; + break; + case 4: + metadata = 5; + break; + case 5: + metadata = 6; + break; + case 6: + metadata = 7; + break; + case 7: + metadata = 4; + break; + case 8: + metadata = 9; + break; + case 9: + metadata = 10; + break; + case 10: + metadata = 11; + break; + case 11: + metadata = 8; + break; + case 12: + metadata = 13; + break; + case 13: + metadata = 14; + break; + case 14: + metadata = 15; + break; + case 15: + metadata = 12; + break; + } + } + break; + case SOUTH_DOOR_METADATA: + + if (blockID == Block.hopperBlock.blockID) + { + switch (metadata) + { + case 2: + metadata = 3; + break; + case 3: + metadata = 2; + break; + case 4: + metadata = 5; + break; + case 5: + metadata = 4; + break; + } + } + + if(Block.blocksList[blockID] instanceof BlockStairs) + { + switch (metadata) + { + case 0: + metadata = 1; + break; + case 1: + metadata = 0; + break; + case 2: + metadata = 3; + break; + case 3: + metadata = 2; + break; + case 7: + metadata = 6; + break; + case 6: + metadata = 7; + break; + case 5: + metadata = 4; + break; + case 4: + metadata = 5; + break; + } + } + + else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID==Block.ladder.blockID) + { + switch (metadata) + { + case 2: + metadata = 3; + break; + case 3: + metadata = 2; + break; + case 4: + metadata = 5; + break; + case 5: + metadata = 4; + break; + } + + } + + else if(blockID==Block.vine.blockID) + { + switch (metadata) + { + + case 1: + metadata = 4; + break; + case 2: + metadata = 8; + break; + case 4: + metadata = 1; + break; + case 8: + metadata = 2; + break; + } + } + + + + + else if(blockID== Block.lever.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID) + { + switch (metadata) + { + case 12: + metadata = 11; + break; + case 11: + metadata = 12; + break; + case 10: + metadata = 9; + break; + case 9: + metadata = 10; + break; + case 2: + metadata = 1; + break; + case 3: + metadata = 4; + break; + case 1: + metadata = 2; + break; + case 4: + metadata = 3; + + break; + + } + + } + + else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID) + { + switch (metadata) + { + case 4: + metadata = 5; + break; + case 5: + metadata = 4; + break; + case 13: + metadata = 12; + break; + case 12: + metadata = 13; + break; + case 3: + metadata = 2; + break; + case 2: + metadata = 3; + break; + case 11: + metadata = 10; + break; + case 10: + metadata = 11; + break; + + } + + + + } + + else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor ||blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator) + { + switch (metadata) + { + case 0: + metadata = 2; + break; + case 1: + metadata = 3; + break; + case 2: + metadata = 0; + break; + case 3: + metadata = 1; + break; + case 4: + metadata = 6; + break; + case 5: + metadata = 7; + break; + case 6: + metadata = 4; + break; + case 7: + metadata = 5; + break; + case 8: + metadata = 10; + break; + case 9: + metadata = 11; + break; + case 10: + metadata = 8; + break; + case 11: + metadata = 9; + break; + case 12: + metadata = 14; + break; + case 13: + metadata = 15; + break; + case 14: + metadata = 12; + break; + case 15: + metadata = 13; + break; + + + } + + + + } + + break; + case WEST_DOOR_METADATA: + + if (blockID == Block.hopperBlock.blockID) + { + switch (metadata) + { + case 2: + metadata = 4; + break; + case 3: + metadata = 5; + break; + case 4: + metadata = 3; + break; + case 5: + metadata = 2; + break; + } + } + + if(Block.blocksList[blockID] instanceof BlockStairs) + { + + switch (metadata) + { + case 2: + metadata = 0; + break; + case 3: + metadata = 1; + break; + case 1: + metadata = 2; + break; + case 0: + metadata = 3; + break; + case 4: + metadata = 7; + break; + case 5: + metadata = 6; + break; + case 7: + metadata = 5; + break; + case 6: + metadata = 4; + break; + + } + } + + else if(blockID== Block.chest.blockID||blockID== Block.chestTrapped.blockID||blockID==Block.ladder.blockID) + { + switch (metadata) + { + + case 2: + metadata = 4; + break; + case 3: + metadata = 5; + break; + case 4: + metadata = 3; + break; + case 5: + metadata = 2; + break; + + + + } + + } + + else if(blockID==Block.vine.blockID) + { + switch (metadata) + { + + case 1: + metadata = 8; + break; + case 2: + metadata = 1; + break; + case 4: + metadata = 2; + break; + case 8: + metadata = 4; + break; + } + } + + + + + else if(blockID== Block.lever.blockID||blockID== Block.torchWood.blockID||blockID== Block.torchRedstoneIdle.blockID||blockID== Block.torchRedstoneActive.blockID) + { + switch (metadata) + { + case 9: + metadata = 12; + break; + case 10: + metadata = 11; + break; + case 12: + metadata = 10; + break; + case 11: + metadata = 9; + break; + case 4: + metadata = 2; + break; + case 2: + metadata = 3; + break; + case 3: + metadata = 1; + break; + case 1: + metadata = 4; + + break; + + } + + } + + else if(blockID== Block.pistonBase.blockID||blockID==Block.pistonStickyBase.blockID||blockID==Block.dispenser.blockID||blockID==Block.dropper.blockID) + + { + switch (metadata) + { + case 2: + metadata = 4; + break; + case 3: + metadata = 5; + break; + case 11: + metadata = 13; + break; + case 10: + metadata = 12; + break; + case 4: + metadata = 3; + break; + case 5: + metadata = 2; + break; + case 12: + metadata = 11; + break; + case 13: + metadata = 10; + break; + } + } + else if(Block.blocksList[blockID] instanceof BlockRedstoneRepeater ||Block.blocksList[blockID] instanceof BlockDoor ||blockID== Block.tripWireSource.blockID||Block.blocksList[blockID] instanceof BlockComparator) + { + switch (metadata) + { + case 1: + metadata = 0; + break; + case 2: + metadata = 1; + break; + case 3: + metadata = 2; + break; + case 0: + metadata = 3; + break; + case 5: + metadata = 4; + break; + case 6: + metadata = 5; + break; + case 7: + metadata = 6; + break; + case 4: + metadata = 7; + break; + case 9: + metadata = 8; + break; + case 10: + metadata = 9; + break; + case 11: + metadata = 10; + break; + case 8: + metadata = 11; + break; + case 13: + metadata = 12; + break; + case 14: + metadata = 13; + break; + case 15: + metadata = 14; + break; + case 12: + metadata = 15; + break; + } + } + break; + case NORTH_DOOR_METADATA: + /** + * this is the default case- never need to change anything here + * + */ + break; + } + } + return metadata; + } + + public static void transformPoint(Point3D position, Point3D srcOrigin, int angle, Point3D destOrigin) + { + //This function receives a position (e.g. point in schematic space), translates it relative + //to a source coordinate system (e.g. the point that will be the center of a schematic), + //then rotates and translates it to obtain the corresponding point in a destination + //coordinate system (e.g. the location of the entry rift in the pocket being generated). + //The result is returned by overwriting the original position so that new object references + //aren't needed. That way, repeated use of this function will not incur as much overhead. + + //Position is only overwritten at the end, so it's okay to provide it as srcOrigin or destOrigin as well. + + int tx = position.getX() - srcOrigin.getX(); + int ty = position.getY() - srcOrigin.getY(); + int tz = position.getZ() - srcOrigin.getZ(); + + //"int angle" specifies a rotation consistent with Minecraft's orientation system. + //That means each increment of 1 in angle would be a 90-degree clockwise turn. + //Given a starting direction A and a destination direction B, the rotation would be + //calculated by (B - A). + + //Adjust angle into the expected range + if (angle < 0) + { + int correction = -(angle / 4); + angle = angle + 4 * (correction + 1); + } + angle = angle % 4; + + int rx; + int rz; + switch (angle) + { + case 0: //No rotation + rx = tx; + rz = tz; + break; + case 1: //90 degrees clockwise + rx = -tz; + rz = tx; + break; + case 2: //180 degrees + rx = -tx; + rz = -tz; + break; + case 3: //270 degrees clockwise + rx = tz; + rz = -tx; + + break; + default: //This should never happen + throw new IllegalStateException("Invalid angle value. This should never happen!"); + } + + position.setX( rx + destOrigin.getX() ); + position.setY( ty + destOrigin.getY() ); + position.setZ( rz + destOrigin.getZ() ); + } +} diff --git a/StevenDimDoors/mod_pocketDim/schematic/Schematic.java b/StevenDimDoors/mod_pocketDim/schematic/Schematic.java index 4f00dab..c81da44 100644 --- a/StevenDimDoors/mod_pocketDim/schematic/Schematic.java +++ b/StevenDimDoors/mod_pocketDim/schematic/Schematic.java @@ -53,7 +53,7 @@ public class Schematic { this.tileEntities = source.tileEntities; } - protected int calculateIndex(int x, int y, int z) + public int calculateIndex(int x, int y, int z) { if (x < 0 || x >= width) throw new IndexOutOfBoundsException("x must be non-negative and less than width"); @@ -64,7 +64,38 @@ public class Schematic { return (y * width * length + z * width + x); } + + public Point3D calculatePoint(int index) + { + int y = index / (width * length); + index -= y * width * length; + int z = index / width; + index -= z * width; + int x = index; + + return new Point3D(x, y, z); + } + + public int calculateIndexBelow(int index) + { + return index - (width * length); + } + public short getWidth() + { + return width; + } + + public short getHeight() + { + return height; + } + + public short getLength() + { + return length; + } + public short getBlockID(int x, int y, int z) { return blocks[calculateIndex(x, y, z)]; diff --git a/StevenDimDoors/mod_pocketDim/schematic/WorldOperation.java b/StevenDimDoors/mod_pocketDim/schematic/WorldOperation.java index 35798a5..85fa540 100644 --- a/StevenDimDoors/mod_pocketDim/schematic/WorldOperation.java +++ b/StevenDimDoors/mod_pocketDim/schematic/WorldOperation.java @@ -1,5 +1,6 @@ package StevenDimDoors.mod_pocketDim.schematic; +import StevenDimDoors.mod_pocketDim.Point3D; import net.minecraft.world.World; public abstract class WorldOperation { @@ -23,6 +24,17 @@ public abstract class WorldOperation { return true; } + public boolean apply(World world, Point3D minCorner, Point3D maxCorner) + { + int x = minCorner.getX(); + int y = minCorner.getY(); + int z = minCorner.getZ(); + int width = maxCorner.getX() - x + 1; + int height = maxCorner.getY() - y + 1; + int length = maxCorner.getZ() - z + 1; + return apply(world, x, y, z, width, height, length); + } + public boolean apply(World world, int x, int y, int z, int width, int height, int length) { if (!initialize(world, x, y, z, width, height, length))