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.
}
repositories {
ivy {
name "Pillar"
artifactPattern "https://addons-origin.cursecdn.com/files/2318/492/[module]-[revision].[ext]"
}
}
dependencies {
compile 'com.flowpowered:flow-math:1.0.3'
compile name: 'Pillar', version: '1.0-5', ext: 'jar'
}
processResources

View file

@ -5,8 +5,12 @@
*/
package com.zixiken.dimdoors;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
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.Property;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@ -17,11 +21,12 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
*/
public class DDConfig {
public static File configurationFolder;
private static int pocketGridSize = 8;
private static int maxPocketSize = 4;
private static int privatePocketSize = 3;
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) {
Property prop = config.get(category, key, defaultValue,
@ -39,6 +44,14 @@ public class DDConfig {
public static void loadConfig(FMLPreInitializationEvent event) {
// 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());
config.load();

View file

@ -8,14 +8,19 @@ package com.zixiken.dimdoors.shared;
import com.zixiken.dimdoors.DimDoors;
import com.zixiken.dimdoors.blocks.ModBlocks;
import com.zixiken.dimdoors.tileentities.DDTileEntityBase;
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.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;
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)
private final int[] weights; //weights for chanced generation of dungeons per depth level | weights[0] is the weight for depth "minDepth"
private final int minDepth;
private final int maxDepth;
//generation parameters
private StructureSchema schematic;
private final int size;
private final Schematic schematic;
private final int entranceDoorX;
private final int entranceDoorY;
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 floorThickness;
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.minDepth = minDepth; //pocket will only be generated from 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;
}
//@todo about everything
//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, 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);
}
int getSize() {
return size;
}
@ -64,7 +78,7 @@ class PocketTemplate { //there is exactly one pocket placer for each different s
int getMaxDepth() {
return maxDepth;
}
int getWeight(int depth) {
int index = depth - minDepth;
if (index >= 0 && index < weights.length) {
@ -73,6 +87,18 @@ class PocketTemplate { //there is exactly one pocket placer for each different s
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
IBlockState outerWallBlock = ModBlocks.blockDimWall.getStateFromMeta(2); //@todo, does this return the correct wall?
IBlockState innerWallBlock;
@ -85,7 +111,7 @@ class PocketTemplate { //there is exactly one pocket placer for each different s
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 yLimit = roofThickness > 0 ? hLimit : 256 - yBase; //vertical relative limit (build-height + 1)
@ -172,16 +198,20 @@ 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
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);
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;

View file

@ -5,10 +5,26 @@
*/
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.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.List;
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 static final SchematicHandler Instance = new SchematicHandler();
private PocketTemplate personalPocketSchematic;
private PocketTemplate publicPocketSchematic;
private List<PocketTemplate> dungeonSchematics;
private PocketTemplate personalPocketTemplate;
private PocketTemplate publicPocketTemplate;
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) {
return personalPocketSchematic;
return personalPocketTemplate;
}
PocketTemplate getPublicPocketSchematic(int maxPocketSize) {
return publicPocketSchematic;
return publicPocketTemplate;
}
PocketTemplate getRandomDungeonPocketTemplate(int depth, int maxPocketSize) {
List<PocketTemplate> validTemplates = new ArrayList();
int totalWeight = 0;
for (PocketTemplate template : dungeonSchematics) {
for (PocketTemplate template : dungeonTemplates) {
if (template.getMinDepth() > depth || template.getMaxDepth() < depth) {
//do nothing
} else {
@ -40,11 +57,11 @@ public class SchematicHandler {
totalWeight += template.getWeight(depth);
}
}
Random random = new Random();
int chosenTemplatePointer = random.nextInt(totalWeight);
for (PocketTemplate template : validTemplates) {
if (chosenTemplatePointer < 0) {
if (chosenTemplatePointer < 0) {
return template;
}
chosenTemplatePointer -= template.getWeight(depth);
@ -53,23 +70,124 @@ public class SchematicHandler {
}
public void loadSchematics() {
personalPocketSchematic = loadSchematicsFromJson("defaultPersonal", PocketRegistry.Instance.getPrivatePocketSize()).get(0);
publicPocketSchematic = loadSchematicsFromJson("defaultPublic", PocketRegistry.Instance.getPublicPocketSize()).get(0);
dungeonSchematics = new ArrayList();
//@todo, extend the Pillar StructureLoader, so we can load the structures from a different location?
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();
List<String> dungeonSchematicNameStrings = DDConfig.getDungeonSchematicNames();
int maxPocketSize = PocketRegistry.Instance.getMaxPocketSize();
for (String nameString : dungeonSchematicNameStrings) {
List<PocketTemplate> schematics = loadSchematicsFromJson(nameString, maxPocketSize);
if (schematics != null) {
for (PocketTemplate schematic : schematics) {
dungeonSchematics.add(schematic);
List<PocketTemplate> templates = loadTemplatesFromJson(nameString, maxPocketSize);
if (templates != null) {
for (PocketTemplate template : templates) {
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
//check for json files in both directories (inside the mod jar, and inside the dimdoors config folder)
//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
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");
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;
}
}