From 7faffa5a89d983754f93b5ce35ddcb96c5c71bd4 Mon Sep 17 00:00:00 2001 From: Cheeserolls Date: Fri, 22 May 2015 22:11:26 +0100 Subject: [PATCH] Rewrite biome configuration system to be simpler and less fragile --- .../biomesoplenty/api/biome/BOPBiome.java | 15 ++ .../biomesoplenty/common/init/ModBiomes.java | 134 ++++++----- .../common/util/config/ConfigHelper.java | 226 ++++++++++++++++++ 3 files changed, 313 insertions(+), 62 deletions(-) create mode 100644 src/main/java/biomesoplenty/common/util/config/ConfigHelper.java diff --git a/src/main/java/biomesoplenty/api/biome/BOPBiome.java b/src/main/java/biomesoplenty/api/biome/BOPBiome.java index 7442e30a0..25ea7baa2 100644 --- a/src/main/java/biomesoplenty/api/biome/BOPBiome.java +++ b/src/main/java/biomesoplenty/api/biome/BOPBiome.java @@ -16,6 +16,7 @@ import net.minecraftforge.common.BiomeManager.BiomeType; import biomesoplenty.api.biome.generation.GenerationManager; import biomesoplenty.api.biome.generation.GeneratorStage; import biomesoplenty.api.biome.generation.IGenerator; +import biomesoplenty.common.util.config.ConfigHelper; public class BOPBiome extends BiomeGenBase implements IExtendedBiome { @@ -33,6 +34,20 @@ public class BOPBiome extends BiomeGenBase implements IExtendedBiome this.theBiomeDecorator.sandPerChunk2 = -999; this.theBiomeDecorator.clayPerChunk = -999; } + + public void configure(ConfigHelper conf) + { + this.biomeName = conf.getString("biomeName",this.biomeName); + + this.topBlock = conf.getBlockState("topBlock", this.topBlock); + this.fillerBlock = conf.getBlockState("fillerBlock", this.fillerBlock); + this.minHeight = conf.getFloat("rootHeight", this.minHeight); + this.maxHeight = conf.getFloat("variation", this.maxHeight); + this.temperature = conf.getFloat("temperature", this.temperature); + this.rainfall = conf.getFloat("rainfall", this.rainfall); + this.waterColorMultiplier = conf.getInt("waterColorMultiplier", this.waterColorMultiplier); + } + @Override public BiomeOwner getBiomeOwner() diff --git a/src/main/java/biomesoplenty/common/init/ModBiomes.java b/src/main/java/biomesoplenty/common/init/ModBiomes.java index fd1f7f36f..1558ab690 100644 --- a/src/main/java/biomesoplenty/common/init/ModBiomes.java +++ b/src/main/java/biomesoplenty/common/init/ModBiomes.java @@ -11,12 +11,17 @@ package biomesoplenty.common.init; import static biomesoplenty.api.biome.BOPBiomes.*; import java.io.File; -import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; import net.minecraft.world.biome.BiomeGenBase; +import net.minecraftforge.common.BiomeManager.BiomeEntry; +import net.minecraftforge.common.BiomeManager.BiomeType; -import org.apache.commons.io.FileUtils; - +import biomesoplenty.api.biome.BOPBiome; +import biomesoplenty.api.biome.IExtendedBiome; +import biomesoplenty.common.biome.BOPBiomeManager; import biomesoplenty.common.biome.overworld.BiomeGenAlps; import biomesoplenty.common.biome.overworld.BiomeGenArctic; import biomesoplenty.common.biome.overworld.BiomeGenCrag; @@ -28,40 +33,90 @@ import biomesoplenty.common.biome.overworld.BiomeGenShrubland; import biomesoplenty.common.biome.overworld.BiomeGenSteppe; import biomesoplenty.common.biome.overworld.BiomeGenThicket; import biomesoplenty.common.command.BOPCommand; -import biomesoplenty.common.util.config.JsonBiome; +import biomesoplenty.common.util.config.ConfigHelper; import biomesoplenty.common.world.WorldTypeBOP; import biomesoplenty.core.BiomesOPlenty; import com.google.common.base.Optional; -import com.google.gson.JsonSyntaxException; public class ModBiomes { public static WorldTypeBOP worldTypeBOP; private static int nextBiomeId = 40; + private static File biomeIdMapFile; + private static ConfigHelper biomeIdMapConf; + private static Map biomeIdMap; public static void init() { worldTypeBOP = new WorldTypeBOP(); - + + // get BOP biome ids from the config file (if it exists) + biomeIdMapFile = new File(BiomesOPlenty.configDirectory, "biome_ids.json"); + biomeIdMapConf = new ConfigHelper(biomeIdMapFile); + biomeIdMap = new HashMap(); + registerBiomes(); registerExternalBiomes(); + + // save the biome ids to the config file (creating it if it doesn't exist) + ConfigHelper.writeFile(biomeIdMapFile, biomeIdMap); + } + private static void registerBiomes() { - alps = registerBiome(new BiomeGenAlps().setBiomeName("Alps"), "alps"); - arctic = registerBiome(new BiomeGenArctic().setBiomeName("Arctic"), "arctic"); - crag = registerBiome(new BiomeGenCrag().setBiomeName("Crag"), "crag"); - denseForest = registerBiome(new BiomeGenDenseForest().setBiomeName("Dense Forest"), "dense_forest"); - flowerField = registerBiome(new BiomeGenFlowerField().setBiomeName("Flower Field"), "flower_field"); - lavenderFields = registerBiome(new BiomeGenLavenderFields().setBiomeName("Lavender Fields"), "lavender_fields"); - originValley = registerBiome(new BiomeGenOriginValley().setBiomeName("Origin Valley"), "origin_valley"); - shrubland = registerBiome(new BiomeGenShrubland().setBiomeName("Shrubland"), "shrubland"); - steppe = registerBiome(new BiomeGenSteppe().setBiomeName("Steppe"), "steppe"); - thicket = registerBiome(new BiomeGenThicket().setBiomeName("Thicket"), "thicket"); + alps = registerBOPBiome(new BiomeGenAlps(), "Alps", "alps"); + arctic = registerBOPBiome(new BiomeGenArctic(), "Arctic", "arctic"); + crag = registerBOPBiome(new BiomeGenCrag(), "Crag", "crag"); + denseForest = registerBOPBiome(new BiomeGenDenseForest(), "Dense Forest", "dense_forest"); + flowerField = registerBOPBiome(new BiomeGenFlowerField(), "Flower Field", "flower_field"); + lavenderFields = registerBOPBiome(new BiomeGenLavenderFields(), "Lavender Fields", "lavender_fields"); + originValley = registerBOPBiome(new BiomeGenOriginValley(), "Origin Valley", "origin_valley"); + shrubland = registerBOPBiome(new BiomeGenShrubland(), "Shrubland", "shrubland"); + steppe = registerBOPBiome(new BiomeGenSteppe(), "Steppe", "steppe"); + thicket = registerBOPBiome(new BiomeGenThicket(), "Thicket", "thicket"); } + + private static Optional registerBOPBiome(BOPBiome biome, String name, String idName) + { + + Integer id = biomeIdMapConf.getInt(idName, null); + if (id == null) {id = new Integer(getNextFreeBiomeId());} + biomeIdMap.put(idName, id); + + if (id > -1) { + + File configFile = new File(new File(BiomesOPlenty.configDirectory, "biomes"), idName + ".json"); + ConfigHelper conf = new ConfigHelper(configFile); + + BOPCommand.biomeCount++; + biome.biomeID = id; + biome.setBiomeName(name); + biome.configure(conf); + + BiomeGenBase.getBiomeGenArray()[id] = biome; + + for (Entry entry : ((IExtendedBiome)biome).getWeightMap().entrySet()) + { + if (entry != null) + { + BiomeType biomeType = entry.getKey(); + int weight = entry.getValue(); + BOPBiomeManager.addBiome(biomeType, new BiomeEntry(biome, weight)); + } + } + + return Optional.of((BiomeGenBase)biome); + + } else { + return Optional.absent(); + } + } + + private static void registerExternalBiomes() { @@ -107,14 +162,6 @@ public class ModBiomes registerExternalBiome(BiomeGenBase.mesaPlateau, "mesa_plateau");*/ } - private static Optional registerBiome(BiomeGenBase biome, String id) - { - biome.biomeID = getNextFreeBiomeId(); - BOPCommand.biomeCount++; - - return loadOrCreateConfig(biome, id); - } - /*private static void registerExternalBiome(BiomeGenBase biome, String id) { ExtendedBiomeRegistry.createExtension(biome); @@ -139,42 +186,5 @@ public class ModBiomes return -1; } - - private static Optional loadOrCreateConfig(BiomeGenBase biome, String fileName) - { - File configFile = new File(new File(BiomesOPlenty.configDirectory, "biomes"), fileName + ".json"); - - if (configFile.exists()) - { - try - { - JsonBiome jsonBiome = JsonBiome.serializer.fromJson(FileUtils.readFileToString(configFile), JsonBiome.class); - - return JsonBiome.configureBiomeWithJson(biome, jsonBiome); - } - catch (JsonSyntaxException e) - { - BiomesOPlenty.logger.error("An error occurred reading " + configFile.getName(), e); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - else - { - try - { - FileUtils.write(configFile, JsonBiome.serializer.toJson(JsonBiome.createFromBiomeGenBase(biome), JsonBiome.class)); - - return Optional.of(biome); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - return Optional.absent(); - } + } diff --git a/src/main/java/biomesoplenty/common/util/config/ConfigHelper.java b/src/main/java/biomesoplenty/common/util/config/ConfigHelper.java new file mode 100644 index 000000000..ca86d8d89 --- /dev/null +++ b/src/main/java/biomesoplenty/common/util/config/ConfigHelper.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright 2014, the Biomes O' Plenty Team + * + * This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License. + * + * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/. + ******************************************************************************/ + +package biomesoplenty.common.util.config; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map.Entry; + +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.state.IBlockState; + +import org.apache.commons.io.FileUtils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import biomesoplenty.common.util.block.BlockStateUtils; +import biomesoplenty.common.util.config.JsonBlockState; +import biomesoplenty.core.BiomesOPlenty; + +public class ConfigHelper +{ + + public static Gson serializer = new GsonBuilder().setPrettyPrinting().create(); + public static JsonParser parser = new JsonParser(); + public JsonBlockState blockStateParser = new JsonBlockState(); + public JsonObject root; + public ArrayList messages; + + public ConfigHelper() + { + + } + + public ConfigHelper(String jsonString) + { + this.parse(jsonString); + } + + public ConfigHelper(File configFile) + { + String jsonString = null; + if (configFile.exists()) + { + try + { + jsonString = FileUtils.readFileToString(configFile); + } catch (IOException e) { + BiomesOPlenty.logger.error("Error reading config file "+e.getMessage()); + } + } + this.parse(jsonString); + } + + public void parse(String jsonString) + { + this.root = null; + JsonElement rootElement = null; + if (jsonString != null) + { + try + { + rootElement = parser.parse(jsonString); + if (rootElement != null) + { + if (rootElement.isJsonObject()) + { + this.root = rootElement.getAsJsonObject(); + } else { + BiomesOPlenty.logger.error("Error parsing config: not a JSON object"); + } + } + } catch (Exception e) { + BiomesOPlenty.logger.error("Error parsing config: "+e.getMessage()); + } + } + } + + + public void addMessage(String message) + { + this.messages.add(message); + } + + + + public Boolean getBool(String name, Boolean defaultVal) + { + if (this.root == null || !this.root.has(name)) {return defaultVal;} + try + { + return this.root.get(name).getAsBoolean(); + } catch (Exception e) { + this.addMessage("Error fetching boolean " + name + ": " + e.getMessage()); + return defaultVal; + } + } + + public String getString(String name, String defaultVal) + { + if (this.root == null || !this.root.has(name)) {return defaultVal;} + try + { + return this.root.get(name).getAsString(); + } catch (Exception e) { + this.addMessage("Error fetching string " + name + ": " + e.getMessage()); + return defaultVal; + } + } + + public Integer getInt(String name, Integer defaultVal) + { + if (this.root == null || !this.root.has(name)) {return defaultVal;} + try + { + return this.root.get(name).getAsInt(); + } catch (Exception e) { + this.addMessage("Error fetching integer " + name + ": " + e.getMessage()); + return defaultVal; + } + } + + public Float getFloat(String name, Float defaultVal) + { + if (this.root == null || !this.root.has(name)) {return defaultVal;} + try + { + return this.root.get(name).getAsFloat(); + } catch (Exception e) { + this.addMessage("Error fetching float " + name + ": " + e.getMessage()); + return defaultVal; + } + } + + public IBlockState getBlockState(String name, IBlockState defaultVal) + { + if (this.root == null || !this.root.has(name)) {return defaultVal;} + try { + + JsonObject ele = this.root.get(name).getAsJsonObject(); + + // attempt to load the specified block + if (!ele.has("block")) + { + this.addMessage("Block name missing"); + return defaultVal; + } + JsonElement blockName = ele.get("block"); + if (!blockName.isJsonPrimitive()) + { + this.addMessage("Invalid block name - must be a string"); + return defaultVal; + } + Block block = Block.getBlockFromName(blockName.getAsString()); + if (block == null) + { + this.addMessage("Unrecognised block name " + blockName.getAsString()); + return defaultVal; + } + + IBlockState state = block.getDefaultState(); + + // attempt to add properties + if (ele.has("properties")) { + + JsonElement properties = ele.get("properties"); + if (!properties.isJsonObject()) + { + this.addMessage("Invalid properties list - must be a JSON object"); + return state; + } + + for (Entry entry : properties.getAsJsonObject().entrySet()) + { + IProperty property = BlockStateUtils.getPropertyByName(state, entry.getKey()); + if (property != null) + { + Comparable propertyValue = BlockStateUtils.getPropertyValueByName(state, property, entry.getValue().getAsString()); + if (propertyValue != null) + { + state = state.withProperty(property, propertyValue); + } + else + { + this.addMessage("Invalid value " + entry.getValue().getAsString() + " for property " + entry.getKey()); + } + } + else + { + this.addMessage("Invalid property name: " + entry.getKey()); + } + } + } + + return state; + + } catch (Exception e) { + this.addMessage("Error fetching block state " + name + ": " + e.getMessage()); + return defaultVal; + } + } + + + public static boolean writeFile(File outputFile, Object obj) + { + try { + FileUtils.write(outputFile, serializer.toJson(obj)); + return true; + } catch (Exception e) { + BiomesOPlenty.logger.error("Error writing config file " + outputFile.getAbsolutePath() + ": " + e.getMessage()); + return false; + } + } + +} \ No newline at end of file