From d0b6a746645f8e28e8052804c4c9555a997c147a Mon Sep 17 00:00:00 2001 From: Mathijs Riezebos Date: Tue, 24 Jan 2017 08:11:12 +0100 Subject: [PATCH] Implemented usage of Sponge Schematics -Implemented a way to load these schematics -Implemented a way to place these schematics -Removed "ye olde ways" (Pillar-ways) Todo: -Finding out how and where TileEntities are being created wrongly. -Make pocket-generation a lot less "coupled". Just store the RiftIDs in the Pocket and afterwards ask the pocket for a random RiftID -Do some code cleanup in the SchematicHandler class -Config Dim ID def: 684 --- .../dimdoors/blocks/BlockDimDoorBase.java | 1 + .../dimdoors/shared/PocketTemplate.java | 197 ++++-------------- .../zixiken/dimdoors/shared/Schematic.java | 7 +- .../dimdoors/shared/SchematicHandler.java | 39 ++-- 4 files changed, 67 insertions(+), 177 deletions(-) diff --git a/src/main/java/com/zixiken/dimdoors/blocks/BlockDimDoorBase.java b/src/main/java/com/zixiken/dimdoors/blocks/BlockDimDoorBase.java index fd881233..b4abfad0 100644 --- a/src/main/java/com/zixiken/dimdoors/blocks/BlockDimDoorBase.java +++ b/src/main/java/com/zixiken/dimdoors/blocks/BlockDimDoorBase.java @@ -114,6 +114,7 @@ public abstract class BlockDimDoorBase extends BlockDoor implements IDimDoor, IT @Override public TileEntity createNewTileEntity(World world, int metadata) { + Thread.currentThread().getStackTrace(); return new TileEntityDimDoor(); } diff --git a/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java b/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java index 7cc4ac24..82199728 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java +++ b/src/main/java/com/zixiken/dimdoors/shared/PocketTemplate.java @@ -6,18 +6,15 @@ package com.zixiken.dimdoors.shared; import com.zixiken.dimdoors.DimDoors; -import com.zixiken.dimdoors.blocks.ModBlocks; import com.zixiken.dimdoors.tileentities.DDTileEntityBase; +import com.zixiken.dimdoors.tileentities.TileEntityDimDoor; +import java.util.ArrayList; +import java.util.List; import java.util.Random; -import net.minecraft.block.BlockDoor; -import net.minecraft.block.BlockDoor.EnumDoorHalf; import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import net.minecraft.world.WorldServer; /** @@ -29,12 +26,6 @@ class PocketTemplate { //there is exactly one pocket placer for each different s //generation parameters private Schematic schematic; private final int size; - private final int entranceDoorX; - private final int entranceDoorY; - private final int entranceDoorZ; - private final int wallThickness; //determines the thickness of the wall around the pocket. Set to 1 to only generate the "bedRock" outer layer - private final int floorThickness; - private final int roofThickness; private final EnumPocketType typeID; //selection parameters private final String variantName; @@ -43,7 +34,7 @@ class PocketTemplate { //there is exactly one pocket placer for each different s private final int[] weights; //weights for chanced generation of dungeons per depth level | weights[0] is the weight for depth "minDepth" //this class should contain the actual schematic info, as well as some of the Json info (placement of Rifts and stuff) - public PocketTemplate(String variantName, Schematic schematic, int size, int entranceDoorX, int entranceDoorY, int entranceDoorZ, int wallThickness, int floorThickness, int roofThickness, EnumPocketType typeID, + public PocketTemplate(String variantName, Schematic schematic, int size, EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) { this.variantName = variantName; this.weights = weights; //chance that this Pocket will get generated @@ -51,18 +42,11 @@ class PocketTemplate { //there is exactly one pocket placer for each different s this.maxDepth = maxDepth; //to this pocket depth this.size = size; //size of content of pocket in chunks (walls are 5 thick, so size 0 will be 6*6 blocks, size 1 will be 22*22 blocks, etc. this.schematic = schematic; - this.entranceDoorX = entranceDoorX; //coords of the TOP HALF of the door - this.entranceDoorY = entranceDoorY; - this.entranceDoorZ = entranceDoorZ; this.typeID = typeID; - this.wallThickness = wallThickness; - this.floorThickness = floorThickness; - this.roofThickness = roofThickness; } - public PocketTemplate(String variantName, int size, int entranceDoorX, int entranceDoorY, int entranceDoorZ, int wallThickness, int floorThickness, int roofThickness, EnumPocketType typeID, - int minDepth, int maxDepth, int[] weights) { - this(variantName, null, size, entranceDoorX, entranceDoorY, entranceDoorZ, wallThickness, floorThickness, roofThickness, typeID, minDepth, maxDepth, weights); + public PocketTemplate(String variantName, int size, EnumPocketType typeID, int minDepth, int maxDepth, int[] weights) { + this(variantName, null, size, typeID, minDepth, maxDepth, weights); } int getSize() { @@ -102,140 +86,49 @@ class PocketTemplate { //there is exactly one pocket placer for each different s DimDoors.log(this.getClass(), "The schematic for variant " + variantName + " somehow didn't load correctly against despite all precautions."); } //@todo make sure that the door tile entities get registered! - - //String tileEntityID = tileEntityTagCompound.getString("id"); - - - IBlockState outerWallBlock = ModBlocks.blockDimWall.getStateFromMeta(2); //@todo, does this return the correct wall? - IBlockState innerWallBlock; - IBlockState entryDoorBlock; - if (typeID == EnumPocketType.PRIVATE) { - innerWallBlock = ModBlocks.blockDimWall.getStateFromMeta(1); //@todo, does this return the correct wall? - entryDoorBlock = ModBlocks.blockDimDoorPersonal.getDefaultState(); - } else { - innerWallBlock = ModBlocks.blockDimWall.getStateFromMeta(0); //@todo, does this return the correct wall? - entryDoorBlock = ModBlocks.blockDimDoor.getDefaultState(); - } - WorldServer world = DimDoors.proxy.getWorldServer(dimID); - int hLimit = (size + 1) * 16; //horizontal relative limit - int yLimit = roofThickness > 0 ? hLimit : 256 - yBase; //vertical relative limit (build-height + 1) - - //Place walls parallel to the X-axis - if (wallThickness > 0) { //only place the walls if there are any walls to be placed - //@todo, if I generate all walls from outside to inside in the outer for-loop, that might be better - for (int wallLayer = 0; wallLayer < wallThickness; wallLayer++) { - IBlockState wallBlock; - if (wallLayer == 0) { - wallBlock = outerWallBlock; - } else { - wallBlock = innerWallBlock; - } - for (int relativeY = 1; relativeY < yLimit - 1; relativeY++) { //the bottom layer will only be generated if the bottom is solid, just like the top - if (relativeY == 1) { - wallBlock = innerWallBlock; //the outer layer of the wall should be "bedrock", however the bottom of the dimensionwall should always be pitch-black if the dimension doesn't have a bottom for if you fall out of it. - } - //generate blocks in wall along the x-axis - for (int relativeX = 0; relativeX < hLimit; relativeX++) { - if (relativeX < wallLayer) { - //don't generate - } else { - world.setBlockState(new BlockPos(xBase + relativeX, yBase + relativeY, zBase + wallLayer), wallBlock); - world.setBlockState(new BlockPos(xBase + relativeX, yBase + relativeY, zBase + hLimit - 1 - wallLayer), wallBlock); - } - } - //generate blocks in wall alont the z-axis - for (int relativeZ = 0; relativeZ < hLimit; relativeZ++) { - if (relativeZ < wallLayer + 1) { //"+1" explanation: The corner blocks are already being placed by the wall along the x-axis - //don't generate - } else { - world.setBlockState(new BlockPos(xBase + wallLayer, yBase + relativeY, zBase + relativeZ), wallBlock); - world.setBlockState(new BlockPos(xBase + hLimit - 1 - wallLayer, yBase + relativeY, zBase + relativeZ), wallBlock); - } - } - } - } - } - - //Generate the floor - if (floorThickness > 0) { - for (int relativeY = 0; relativeY < floorThickness; relativeY++) { - IBlockState floorBlock; - if (relativeY == 0) { - floorBlock = outerWallBlock; - } else { - floorBlock = innerWallBlock; - } - for (int relativeX = 0; relativeX < hLimit; relativeX++) { - for (int relativeZ = 0; relativeZ < hLimit; relativeZ++) { - if (relativeX < wallThickness || relativeX > hLimit - 1 - wallThickness - || relativeZ < wallThickness || relativeZ > hLimit - 1 - wallThickness) { //under the walls - if (relativeY == 0) { //only the bottom layer - world.setBlockState(new BlockPos(xBase + relativeX, yBase + relativeY, zBase + relativeZ), floorBlock); - } - } else { //not under the walls - world.setBlockState(new BlockPos(xBase + relativeX, yBase + relativeY, zBase + relativeZ), floorBlock); - } - } - } - } - } - - //Generate the roof - if (roofThickness > 0) { - for (int relativeY = yLimit - 1; relativeY > yLimit - 1 - roofThickness; relativeY--) { - IBlockState floorBlock; - if (relativeY == 0) { - floorBlock = outerWallBlock; - } else { - floorBlock = innerWallBlock; - } - for (int relativeX = 0; relativeX < hLimit; relativeX++) { - for (int relativeZ = 0; relativeZ < hLimit; relativeZ++) { - if (relativeX < wallThickness || relativeX > hLimit - 1 - wallThickness - || relativeZ < wallThickness || relativeZ > hLimit - 1 - wallThickness) { // above the walls - if (relativeY == yLimit - 1) { //only the top layer - world.setBlockState(new BlockPos(xBase + relativeX, yBase + relativeY, zBase + relativeZ), floorBlock); - } - } else { //not above the walls - world.setBlockState(new BlockPos(xBase + relativeX, yBase + relativeY, zBase + relativeZ), floorBlock); - } - } - } - } - } - - BlockPos dungeonBasePos = new BlockPos(xBase + wallThickness, yBase + floorThickness, zBase + wallThickness); //Place the Dungeon content structure - StructureGenerator.placeStructureAtPosition(new Random(), schematic, Rotation.NONE, world, dungeonBasePos, true); - - //Place the door - BlockPos doorPos = dungeonBasePos.offset(EnumFacing.EAST, entranceDoorX).offset(EnumFacing.UP, entranceDoorY).offset(EnumFacing.SOUTH, entranceDoorZ); - EnumFacing facing = getAdjacentAirBlockFacing(world, doorPos); - entryDoorBlock = entryDoorBlock.withProperty(BlockDoor.FACING, facing); - world.setBlockState(doorPos, entryDoorBlock.withProperty(BlockDoor.HALF, EnumDoorHalf.UPPER)); - world.setBlockState(doorPos, entryDoorBlock.withProperty(BlockDoor.HALF, EnumDoorHalf.LOWER)); - TileEntity newTileEntity = world.getTileEntity(doorPos); - - //Register the rift and return its ID - if (newTileEntity instanceof DDTileEntityBase) { - DDTileEntityBase newTileEntityDimDoor = (DDTileEntityBase) newTileEntity; - newTileEntityDimDoor.register(); - return newTileEntityDimDoor.getRiftID(); + for (int x = 0; x < schematic.width; x++) { + for (int y = 0; y < schematic.height; y++) { + for (int z = 0; z < schematic.width; z++) { + world.setBlockState(new BlockPos(xBase + x, yBase + y, zBase + z), schematic.pallette.get(schematic.blockData[x][y][z])); + } + } } - return -1; - } + //Place TileEntities + List rifts = new ArrayList(); + for (NBTTagCompound tileEntityNBT : schematic.tileEntities) { + BlockPos pos = new BlockPos(xBase + tileEntityNBT.getInteger("x"), yBase + tileEntityNBT.getInteger("y"), zBase + tileEntityNBT.getInteger("z")); + IBlockState state = world.getBlockState(pos); + state.getBlock().createTileEntity(world, state); + TileEntity tileEntity = world.getTileEntity(pos); + tileEntity.readFromNBT(tileEntityNBT); + tileEntity.markDirty(); - private EnumFacing getAdjacentAirBlockFacing(World world, BlockPos pos) { //@todo, maybe this should be in some utility class? - if (world.getBlockState(pos.east()) == Blocks.AIR) { - return EnumFacing.EAST; - } else if (world.getBlockState(pos.south()) == Blocks.AIR) { - return EnumFacing.SOUTH; - } else if (world.getBlockState(pos.west()) == Blocks.AIR) { - return EnumFacing.WEST; - } else { //north or no air blocks adjacent - return EnumFacing.NORTH; + if (tileEntity instanceof DDTileEntityBase) { + DDTileEntityBase rift = (DDTileEntityBase) tileEntity; + rifts.add(rift); + } + } + + List dimDoorTiles = new ArrayList(); + for (DDTileEntityBase rift : rifts) { + rift.register(); + if (rift instanceof TileEntityDimDoor) { + TileEntityDimDoor dimDoorTile = (TileEntityDimDoor) rift; + dimDoorTiles.add(dimDoorTile); + } + } + + if (dimDoorTiles.isEmpty()) { + return -1; + } else if (dimDoorTiles.size() == 1) { + return dimDoorTiles.get(0).getRiftID(); + } else { + Random random = new Random(); + int index = random.nextInt(dimDoorTiles.size()); + return dimDoorTiles.get(index).getRiftID(); } } } diff --git a/src/main/java/com/zixiken/dimdoors/shared/Schematic.java b/src/main/java/com/zixiken/dimdoors/shared/Schematic.java index e69cbea4..c2368ec6 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/Schematic.java +++ b/src/main/java/com/zixiken/dimdoors/shared/Schematic.java @@ -19,7 +19,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.registry.ForgeRegistries; -import net.minecraftforge.fml.common.registry.GameData; /** * @@ -44,7 +43,7 @@ class Schematic { private Schematic() { } - Schematic loadFromNBT(NBTTagCompound nbt) { + static Schematic loadFromNBT(NBTTagCompound nbt) { Schematic schematic = new Schematic(); schematic.version = nbt.getInteger("Version"); @@ -93,7 +92,7 @@ class Schematic { blockstate = getBlockStateWithProperties(block, properties); //@todo get the blockState from string } else { } - pallette.add(blockstate); + schematic.pallette.add(blockstate); } byte[] blockDataIntArray = nbt.getByteArray("BlockData"); @@ -115,7 +114,7 @@ class Schematic { return schematic; } - private IBlockState getBlockStateWithProperties(Block block, String[] properties) { + private static IBlockState getBlockStateWithProperties(Block block, String[] properties) { Map propertyAndBlockStringsMap = new HashMap(); for (int i = 0; i < properties.length; i++) { String propertyString = properties[i]; diff --git a/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java b/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java index cce62fe5..d109d307 100644 --- a/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java +++ b/src/main/java/com/zixiken/dimdoors/shared/SchematicHandler.java @@ -20,9 +20,10 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Random; -import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.CompressedStreamTools; /** * @@ -68,8 +69,6 @@ public class SchematicHandler { } public void loadSchematics() { - - StructureLoader.loadStructures(DimDoors.getDefWorld()); //@todo change this to get the DimDoors Dimension? personalPocketTemplate = loadTemplatesFromJson("defaultPersonal", PocketRegistry.Instance.getPrivatePocketSize()).get(0); publicPocketTemplate = loadTemplatesFromJson("defaultPublic", PocketRegistry.Instance.getPublicPocketSize()).get(0); dungeonTemplates = new ArrayList(); @@ -90,6 +89,7 @@ public class SchematicHandler { private List loadTemplatesFromJson(String nameString, int maxPocketSize) { //depending on the "jSonType" value in the jSon, this might load several variations of a pocket at once, hence loadTemplate -->s<-- File jsonFolder = new File(DDConfig.configurationFolder, "/Jsons"); File jsonFile = new File(jsonFolder, "/" + nameString + ".json"); + File schematicFolder = new File(DDConfig.configurationFolder, "/Schematics"); String jsonString = null; try { jsonString = readFile(jsonFile.getAbsolutePath(), StandardCharsets.UTF_8); @@ -102,9 +102,20 @@ public class SchematicHandler { List validTemplates = getAllValidVariations(jsonTemplate, maxPocketSize); for (PocketTemplate template : validTemplates) { //it's okay to "tap" this for-loop, even if validTemplates is empty. - Schematic schematic = StructureLoader.loadedSchemas.get(template.getName()); + File schematicFile = new File(schematicFolder, "/" + template.getName() + ".schem"); + NBTTagCompound schematicNBT; + Schematic schematic = null; + try { + schematicNBT = CompressedStreamTools.read(schematicFile); + schematic = Schematic.loadFromNBT(schematicNBT); + } catch (IOException ex) { + Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Schematic file for schematic " + template.getName() + " was not found in template folder.", ex); + } + if (schematic != null && (schematic.width > (template.getSize()) * 16 || schematic.length > (template.getSize()) * 16)) { + schematic = null; + DimDoors.log(this.getClass(), "Schematic " + template.getName() + ".schem was bigger than specified in " + nameString + ".json and therefore wasn't loaded"); + } template.setSchematic(schematic); - //@todo make sure that the dungeon content fits inside the pocket walls (and floor and roof) and otherwise ¿crop it? } //@todo check for json files in both directories (inside the mod jar, and inside the dimdoors config folder) return validTemplates; @@ -139,12 +150,6 @@ public class SchematicHandler { if (chosenVariation != null) { //this block equals String variantName = chosenVariation.get("variantName").getAsString(); - int entranceDoorX = chosenVariation.get("entranceDoorX").getAsInt(); - int entranceDoorY = chosenVariation.get("entranceDoorY").getAsInt(); - int entranceDoorZ = chosenVariation.get("entranceDoorZ").getAsInt(); - int wallThickness = chosenVariation.get("wallThickness").getAsInt(); - int floorThickness = chosenVariation.get("floorThickness").getAsInt(); - int roofThickness = chosenVariation.get("roofThickness").getAsInt(); EnumPocketType typeID = EnumPocketType.getFromInt(chosenVariation.get("typeID").getAsInt()); int minDepth = chosenVariation.get("minDepth").getAsInt(); int maxDepth = chosenVariation.get("maxDepth").getAsInt(); @@ -153,8 +158,7 @@ public class SchematicHandler { for (int i = 0; i < weightsJsonArray.size(); i++) { weights[i] = weightsJsonArray.get(i).getAsInt(); } - PocketTemplate pocketTemplate = new PocketTemplate(variantName, chosenVariationSize, entranceDoorX, entranceDoorY, entranceDoorZ, - wallThickness, floorThickness, roofThickness, typeID, minDepth, maxDepth, weights); + PocketTemplate pocketTemplate = new PocketTemplate(variantName, chosenVariationSize, typeID, minDepth, maxDepth, weights); pocketTemplates.add(pocketTemplate); ///this block equals } @@ -165,12 +169,6 @@ public class SchematicHandler { if (variationSize <= maxPocketSize) { //this block String variantName = variation.get("variantName").getAsString(); - int entranceDoorX = variation.get("entranceDoorX").getAsInt(); - int entranceDoorY = variation.get("entranceDoorY").getAsInt(); - int entranceDoorZ = variation.get("entranceDoorZ").getAsInt(); - int wallThickness = variation.get("wallThickness").getAsInt(); - int floorThickness = variation.get("floorThickness").getAsInt(); - int roofThickness = variation.get("roofThickness").getAsInt(); EnumPocketType typeID = EnumPocketType.getFromInt(variation.get("typeID").getAsInt()); int minDepth = variation.get("minDepth").getAsInt(); int maxDepth = variation.get("maxDepth").getAsInt(); @@ -179,8 +177,7 @@ public class SchematicHandler { for (int j = 0; j < weightsJsonArray.size(); j++) { weights[j] = weightsJsonArray.get(j).getAsInt(); } - PocketTemplate pocketTemplate = new PocketTemplate(variantName, variationSize, entranceDoorX, entranceDoorY, entranceDoorZ, - wallThickness, floorThickness, roofThickness, typeID, minDepth, maxDepth, weights); + PocketTemplate pocketTemplate = new PocketTemplate(variantName, variationSize, typeID, minDepth, maxDepth, weights); pocketTemplates.add(pocketTemplate); ///this block }