Finished Pocket creation

-Added dependency on Vazkii's Pillar mod for "schematic" loading
-Added config directory for DimDoors
-Fixed entrance door placement coords
-Refractored some methods
-Added json-reader functionality

-Code compiles now

Todo:
-Make code added in SchematicHandler more modular
-Game gets stuck on world-load. Probably because the default json file
for "defaultPersonal" is not available yet at the saves directory.
This commit is contained in:
Mathijs Riezebos 2017-01-24 00:45:16 +01:00
parent 88dbcf152a
commit 5c383bde1d
4 changed files with 202 additions and 33 deletions

View file

@ -33,8 +33,16 @@ minecraft {
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
} }
repositories {
ivy {
name "Pillar"
artifactPattern "https://addons-origin.cursecdn.com/files/2318/492/[module]-[revision].[ext]"
}
}
dependencies { dependencies {
compile 'com.flowpowered:flow-math:1.0.3' compile 'com.flowpowered:flow-math:1.0.3'
compile name: 'Pillar', version: '1.0-5', ext: 'jar'
} }
processResources processResources

View file

@ -5,8 +5,12 @@
*/ */
package com.zixiken.dimdoors; package com.zixiken.dimdoors;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property; import net.minecraftforge.common.config.Property;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@ -17,11 +21,12 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
*/ */
public class DDConfig { public class DDConfig {
public static File configurationFolder;
private static int pocketGridSize = 8; private static int pocketGridSize = 8;
private static int maxPocketSize = 4; private static int maxPocketSize = 4;
private static int privatePocketSize = 3; private static int privatePocketSize = 3;
private static int publicPocketSize = 2; private static int publicPocketSize = 2;
private static String[] dungeonSchematicNames = {"", ""}; //@todo set default dungeon names private static String[] dungeonSchematicNames = {}; //@todo set default dungeon names
private static int setConfigIntWithMaxAndMin(Configuration config, String category, String key, int defaultValue, String comment, int minValue, int maxValue) { private static int setConfigIntWithMaxAndMin(Configuration config, String category, String key, int defaultValue, String comment, int minValue, int maxValue) {
Property prop = config.get(category, key, defaultValue, Property prop = config.get(category, key, defaultValue,
@ -39,6 +44,14 @@ public class DDConfig {
public static void loadConfig(FMLPreInitializationEvent event) { public static void loadConfig(FMLPreInitializationEvent event) {
// Load config // Load config
configurationFolder = new File(event.getModConfigurationDirectory(), "/DimDoors");
if (!configurationFolder.exists()) {
try {
configurationFolder.createNewFile();
} catch (IOException ex) {
Logger.getLogger(DDConfig.class.getName()).log(Level.SEVERE, "Dimdoors config folder could not be created.", ex);
}
}
Configuration config = new Configuration(event.getSuggestedConfigurationFile()); Configuration config = new Configuration(event.getSuggestedConfigurationFile());
config.load(); config.load();

View file

@ -8,14 +8,19 @@ package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.DimDoors; import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.blocks.ModBlocks; import com.zixiken.dimdoors.blocks.ModBlocks;
import com.zixiken.dimdoors.tileentities.DDTileEntityBase; import com.zixiken.dimdoors.tileentities.DDTileEntityBase;
import java.util.Random;
import net.minecraft.block.BlockDoor; import net.minecraft.block.BlockDoor;
import net.minecraft.block.BlockDoor.EnumDoorHalf; import net.minecraft.block.BlockDoor.EnumDoorHalf;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import vazkii.pillar.schema.StructureSchema;
import vazkii.pillar.StructureGenerator;
/** /**
* *
@ -23,20 +28,26 @@ import net.minecraft.world.World;
*/ */
class PocketTemplate { //there is exactly one pocket placer for each different schematic that is loaded into the game (a Json might load several schematics though) class PocketTemplate { //there is exactly one pocket placer for each different schematic that is loaded into the game (a Json might load several schematics though)
private final int[] weights; //weights for chanced generation of dungeons per depth level | weights[0] is the weight for depth "minDepth" //generation parameters
private final int minDepth; private StructureSchema schematic;
private final int maxDepth;
private final int size; private final int size;
private final Schematic schematic;
private final int entranceDoorX; private final int entranceDoorX;
private final int entranceDoorY; private final int entranceDoorY;
private final int entranceDoorZ; private final int entranceDoorZ;
private final EnumPocketType typeID;
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 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 floorThickness;
private final int roofThickness; private final int roofThickness;
private final EnumPocketType typeID;
//selection parameters
private final String variantName;
private final int minDepth;
private final int maxDepth;
private final int[] weights; //weights for chanced generation of dungeons per depth level | weights[0] is the weight for depth "minDepth"
public PocketTemplate(int minDepth, int maxDepth, int[] weights, int size, Schematic schematic, int entranceDoorX, int entranceDoorY, int entranceDoorZ, EnumPocketType typeID, int wallThickness, int floorThickness, int roofThickness) { //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, StructureSchema schematic, int size, int entranceDoorX, int entranceDoorY, int entranceDoorZ, int wallThickness, int floorThickness, int roofThickness, EnumPocketType typeID,
int minDepth, int maxDepth, int[] weights) {
this.variantName = variantName;
this.weights = weights; //chance that this Pocket will get generated this.weights = weights; //chance that this Pocket will get generated
this.minDepth = minDepth; //pocket will only be generated from this Pocket-depth this.minDepth = minDepth; //pocket will only be generated from this Pocket-depth
this.maxDepth = maxDepth; //to this pocket depth this.maxDepth = maxDepth; //to this pocket depth
@ -51,8 +62,11 @@ class PocketTemplate { //there is exactly one pocket placer for each different s
this.roofThickness = roofThickness; this.roofThickness = roofThickness;
} }
//@todo about everything public PocketTemplate(String variantName, int size, int entranceDoorX, int entranceDoorY, int entranceDoorZ, int wallThickness, int floorThickness, int roofThickness, EnumPocketType typeID,
//this class should contain the actual schematic info, as well as some of the Json info (placement of Rifts and stuff) int minDepth, int maxDepth, int[] weights) {
this(variantName, null, size, entranceDoorX, entranceDoorY, entranceDoorZ, wallThickness, floorThickness, roofThickness, typeID, minDepth, maxDepth, weights);
}
int getSize() { int getSize() {
return size; return size;
} }
@ -73,6 +87,18 @@ class PocketTemplate { //there is exactly one pocket placer for each different s
return 0; //do not generate return 0; //do not generate
} }
String getName() {
return variantName;
}
Object getSchematic() {
return schematic;
}
void setSchematic(StructureSchema schematic) {
this.schematic = schematic;
}
int place(int xBase, int yBase, int zBase, int dimID) { //returns the riftID of the entrance DimDoor int place(int xBase, int yBase, int zBase, int dimID) { //returns the riftID of the entrance DimDoor
IBlockState outerWallBlock = ModBlocks.blockDimWall.getStateFromMeta(2); //@todo, does this return the correct wall? IBlockState outerWallBlock = ModBlocks.blockDimWall.getStateFromMeta(2); //@todo, does this return the correct wall?
IBlockState innerWallBlock; IBlockState innerWallBlock;
@ -85,7 +111,7 @@ class PocketTemplate { //there is exactly one pocket placer for each different s
entryDoorBlock = ModBlocks.blockDimDoor.getDefaultState(); entryDoorBlock = ModBlocks.blockDimDoor.getDefaultState();
} }
World world = DimDoors.proxy.getWorldServer(dimID); WorldServer world = DimDoors.proxy.getWorldServer(dimID);
int hLimit = (size + 1) * 16; //horizontal relative limit int hLimit = (size + 1) * 16; //horizontal relative limit
int yLimit = roofThickness > 0 ? hLimit : 256 - yBase; //vertical relative limit (build-height + 1) int yLimit = roofThickness > 0 ? hLimit : 256 - yBase; //vertical relative limit (build-height + 1)
@ -172,10 +198,14 @@ class PocketTemplate { //there is exactly one pocket placer for each different s
} }
} }
} }
//@todo Place content from schematic starting at (wallthickness, floorthickness, wallthickness)
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 //Place the door
BlockPos doorPos = new BlockPos(entranceDoorX, entranceDoorY, entranceDoorZ); BlockPos doorPos = dungeonBasePos.offset(EnumFacing.EAST, entranceDoorX).offset(EnumFacing.UP, entranceDoorY).offset(EnumFacing.SOUTH, entranceDoorZ);
EnumFacing facing = getAdjacentAirBlockFacing(world, doorPos); EnumFacing facing = getAdjacentAirBlockFacing(world, doorPos);
entryDoorBlock = entryDoorBlock.withProperty(BlockDoor.FACING, facing); entryDoorBlock = entryDoorBlock.withProperty(BlockDoor.FACING, facing);
world.setBlockState(doorPos, entryDoorBlock.withProperty(BlockDoor.HALF, EnumDoorHalf.UPPER)); world.setBlockState(doorPos, entryDoorBlock.withProperty(BlockDoor.HALF, EnumDoorHalf.UPPER));

View file

@ -5,10 +5,26 @@
*/ */
package com.zixiken.dimdoors.shared; package com.zixiken.dimdoors.shared;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.zixiken.dimdoors.DDConfig; import com.zixiken.dimdoors.DDConfig;
import com.zixiken.dimdoors.DimDoors;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import vazkii.pillar.StructureLoader;
import vazkii.pillar.schema.StructureSchema;
/** /**
* *
@ -17,22 +33,23 @@ import java.util.Random;
public class SchematicHandler { public class SchematicHandler {
public static final SchematicHandler Instance = new SchematicHandler(); public static final SchematicHandler Instance = new SchematicHandler();
private PocketTemplate personalPocketSchematic; private PocketTemplate personalPocketTemplate;
private PocketTemplate publicPocketSchematic; private PocketTemplate publicPocketTemplate;
private List<PocketTemplate> dungeonSchematics; private List<PocketTemplate> dungeonTemplates;
//@todo, sort templates by depth over here? that'd mean that that doesn't have to be done on pocket placement each and every time
PocketTemplate getPersonalPocketSchematic(int maxPocketSize) { PocketTemplate getPersonalPocketSchematic(int maxPocketSize) {
return personalPocketSchematic; return personalPocketTemplate;
} }
PocketTemplate getPublicPocketSchematic(int maxPocketSize) { PocketTemplate getPublicPocketSchematic(int maxPocketSize) {
return publicPocketSchematic; return publicPocketTemplate;
} }
PocketTemplate getRandomDungeonPocketTemplate(int depth, int maxPocketSize) { PocketTemplate getRandomDungeonPocketTemplate(int depth, int maxPocketSize) {
List<PocketTemplate> validTemplates = new ArrayList(); List<PocketTemplate> validTemplates = new ArrayList();
int totalWeight = 0; int totalWeight = 0;
for (PocketTemplate template : dungeonSchematics) { for (PocketTemplate template : dungeonTemplates) {
if (template.getMinDepth() > depth || template.getMaxDepth() < depth) { if (template.getMinDepth() > depth || template.getMaxDepth() < depth) {
//do nothing //do nothing
} else { } else {
@ -53,23 +70,124 @@ public class SchematicHandler {
} }
public void loadSchematics() { public void loadSchematics() {
personalPocketSchematic = loadSchematicsFromJson("defaultPersonal", PocketRegistry.Instance.getPrivatePocketSize()).get(0); //@todo, extend the Pillar StructureLoader, so we can load the structures from a different location?
publicPocketSchematic = loadSchematicsFromJson("defaultPublic", PocketRegistry.Instance.getPublicPocketSize()).get(0); StructureLoader.loadStructures(DimDoors.getDefWorld()); //@todo change this to get the DimDoors Dimension?
dungeonSchematics = new ArrayList(); personalPocketTemplate = loadTemplatesFromJson("defaultPersonal", PocketRegistry.Instance.getPrivatePocketSize()).get(0);
publicPocketTemplate = loadTemplatesFromJson("defaultPublic", PocketRegistry.Instance.getPublicPocketSize()).get(0);
dungeonTemplates = new ArrayList();
List<String> dungeonSchematicNameStrings = DDConfig.getDungeonSchematicNames(); List<String> dungeonSchematicNameStrings = DDConfig.getDungeonSchematicNames();
int maxPocketSize = PocketRegistry.Instance.getMaxPocketSize(); int maxPocketSize = PocketRegistry.Instance.getMaxPocketSize();
for (String nameString : dungeonSchematicNameStrings) { for (String nameString : dungeonSchematicNameStrings) {
List<PocketTemplate> schematics = loadSchematicsFromJson(nameString, maxPocketSize); List<PocketTemplate> templates = loadTemplatesFromJson(nameString, maxPocketSize);
if (schematics != null) { if (templates != null) {
for (PocketTemplate schematic : schematics) { for (PocketTemplate template : templates) {
dungeonSchematics.add(schematic); if (template != null && template.getSchematic() != null) {
dungeonTemplates.add(template);
}
} }
} }
} }
} }
private List<PocketTemplate> loadSchematicsFromJson(String nameString, int maxPocketSize) { //depending on the "jSonType" value in the jSon, this might load several variations of a pocket at once 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<--
//check for json files in both directories (inside the mod jar, and inside the dimdoors config folder) File jsonFolder = new File(DDConfig.configurationFolder, "/Jsons");
//check if the json has a "variant" with the correct pocket size, if it doesn't, pick the largest smaller variant. If there's only bigger variants, cancel File jsonFile = new File(jsonFolder, "/" + nameString + ".json");
String jsonString = null;
try {
jsonString = readFile(jsonFile.getAbsolutePath(), StandardCharsets.UTF_8);
} catch (IOException ex) {
Logger.getLogger(SchematicHandler.class.getName()).log(Level.SEVERE, "Template Json file for template " + nameString + " was not found in template folder.", ex);
}
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(jsonString);
JsonObject jsonTemplate = jsonElement.getAsJsonObject();
List<PocketTemplate> validTemplates = getAllValidVariations(jsonTemplate, maxPocketSize);
for (PocketTemplate template : validTemplates) { //it's okay to "tap" this for-loop, even if validTemplates is empty.
StructureSchema schematic = StructureLoader.loadedSchemas.get(template.getName());
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;
}
static String readFile(String path, Charset encoding)
throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
private List<PocketTemplate> getAllValidVariations(JsonObject jsonTemplate, int maxPocketSize) {
String jsonType = jsonTemplate.get("jsonType").getAsString();
EnumPocketType pocketType = EnumPocketType.getFromInt(jsonTemplate.get("pocketType").getAsInt());
JsonArray variations = jsonTemplate.getAsJsonArray("variations");
List<PocketTemplate> pocketTemplates = new ArrayList();
if (jsonType.equals("Singular")) { //@todo, make sure there is only one Json-reader block, instead of one and its copy
JsonObject chosenVariation = null;
int chosenVariationSize = 0;
for (int i = 0; i < variations.size(); i++) {
JsonObject variation = variations.get(i).getAsJsonObject();
int variationSize = variation.get("size").getAsInt();
if (variationSize <= maxPocketSize && variationSize > chosenVariationSize) {
chosenVariationSize = variationSize;
chosenVariation = variation;
if (variationSize == maxPocketSize) {
break; //this one gets chosen
}
}
}
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();
JsonArray weightsJsonArray = chosenVariation.get("weights").getAsJsonArray();
int[] weights = new int[weightsJsonArray.size()];
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);
pocketTemplates.add(pocketTemplate);
///this block equals
}
} else if (jsonType.equals("Multiple")) {
for (int i = 0; i < variations.size(); i++) {
JsonObject variation = variations.get(i).getAsJsonObject();
int variationSize = variation.get("size").getAsInt();
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();
JsonArray weightsJsonArray = variation.get("weights").getAsJsonArray();
int[] weights = new int[weightsJsonArray.size()];
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);
pocketTemplates.add(pocketTemplate);
///this block
}
}
} //@todo, more options?
return pocketTemplates;
} }
} }