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
This commit is contained in:
Mathijs Riezebos 2017-01-24 08:11:12 +01:00
parent 732ceee40b
commit d0b6a74664
4 changed files with 67 additions and 177 deletions

View file

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

View file

@ -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<DDTileEntityBase> 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<TileEntityDimDoor> 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();
}
}
}

View file

@ -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<String, String> propertyAndBlockStringsMap = new HashMap();
for (int i = 0; i < properties.length; i++) {
String propertyString = properties[i];

View file

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