Reorganise BOP config system to make it all a bit cleaner and easier to use

This commit is contained in:
Cheeserolls 2015-05-26 15:04:13 +01:00
parent ee0b4d69b6
commit 42da4d197c
18 changed files with 621 additions and 489 deletions

View File

@ -16,8 +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;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class BOPBiome extends BiomeGenBase implements IExtendedBiome
{
@ -36,7 +35,7 @@ public class BOPBiome extends BiomeGenBase implements IExtendedBiome
this.theBiomeDecorator.clayPerChunk = -999;
}
public void configure(ConfigHelper conf)
public void configure(IConfigObj conf)
{
// Allow name to be overridden
@ -52,7 +51,7 @@ public class BOPBiome extends BiomeGenBase implements IExtendedBiome
this.waterColorMultiplier = conf.getInt("waterColorMultiplier", this.waterColorMultiplier);
// Allow weights to be overridden
WrappedJsonObject confWeights = conf.getObject("weights");
IConfigObj confWeights = conf.getObject("weights");
if (confWeights != null)
{
for (BiomeType type : BiomeType.values())
@ -71,7 +70,7 @@ public class BOPBiome extends BiomeGenBase implements IExtendedBiome
}
// Allow generators to be configured
WrappedJsonObject confGenerators = conf.getObject("generators");
IConfigObj confGenerators = conf.getObject("generators");
if (confGenerators != null)
{
for (String name : confGenerators.getKeys())

View File

@ -12,7 +12,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import biomesoplenty.common.world.feature.*;
import biomesoplenty.common.world.feature.tree.*;
@ -57,7 +57,7 @@ public class GenerationManager
return this.generators.get(name);
}
public void configureWith(String name, WrappedJsonObject conf)
public void configureWith(String name, IConfigObj conf)
{
if (this.generators.containsKey(name))
{
@ -88,10 +88,10 @@ public class GenerationManager
{
FLORA, DOUBLE_FLORA, GRASS, ORE_CLUSTER, ORE_SINGLE, WATERSIDE, BASIC_TREE, BIG_TREE, BUSH;
public static IGenerator create(WrappedJsonObject conf)
public static IGenerator create(IConfigObj conf)
{
GeneratorStage stage = conf.getEnum("stage", null, GeneratorStage.class);
GeneratorFactory factory = conf.getEnum("type", null, GeneratorFactory.class);
GeneratorStage stage = conf.getEnum("stage", GeneratorStage.class);
GeneratorFactory factory = conf.getEnum("type", GeneratorFactory.class);
if (stage == null || factory == null) {return null;}
IGenerator generator = factory.create();
generator.setStage(stage);

View File

@ -8,8 +8,9 @@
package biomesoplenty.api.biome.generation;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
// TODO - scrap this?
public abstract class GeneratorCustomizable implements IGenerator
{
private final String identifier;
@ -57,7 +58,7 @@ public abstract class GeneratorCustomizable implements IGenerator
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
;
}

View File

@ -15,7 +15,7 @@ import java.util.Random;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.GenerationManager.GeneratorFactory;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorWeighted extends GeneratorCustomizable
{
@ -104,10 +104,10 @@ public class GeneratorWeighted extends GeneratorCustomizable
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
WrappedJsonObject confGenerators = conf.getObject("generators");
IConfigObj confGenerators = conf.getObject("generators");
if (confGenerators != null)
{
for (String name : confGenerators.getKeys())

View File

@ -10,9 +10,9 @@ package biomesoplenty.api.biome.generation;
import java.util.Random;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
public interface IGenerator
{
@ -30,5 +30,5 @@ public interface IGenerator
public String getIdentifier();
public GeneratorStage getStage();
public void configure(WrappedJsonObject conf);
public void configure(IConfigObj conf);
}

View File

@ -18,7 +18,7 @@ import biomesoplenty.common.block.BlockBOPPlant;
import biomesoplenty.common.block.BlockGem;
import biomesoplenty.common.enums.BOPGems;
import biomesoplenty.common.enums.BOPPlants;
import biomesoplenty.common.util.config.ConfigHelper;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import biomesoplenty.common.world.feature.GeneratorFlora;
import biomesoplenty.common.world.feature.GeneratorGrass;
import biomesoplenty.common.world.feature.GeneratorOreSingle;
@ -74,7 +74,7 @@ public class BiomeGenDenseForest extends BOPBiome
}
@Override
public void configure(ConfigHelper conf)
public void configure(IConfigObj conf)
{
super.configure(conf);

View File

@ -18,7 +18,6 @@ import java.util.Map.Entry;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.common.BiomeManager.BiomeEntry;
import net.minecraftforge.common.BiomeManager.BiomeType;
import biomesoplenty.api.biome.BOPBiome;
import biomesoplenty.api.biome.IExtendedBiome;
import biomesoplenty.common.biome.BOPBiomeManager;
@ -33,7 +32,7 @@ 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.ConfigHelper;
import biomesoplenty.common.util.config.BOPConfig;
import biomesoplenty.common.world.WorldTypeBOP;
import biomesoplenty.core.BiomesOPlenty;
@ -45,7 +44,7 @@ public class ModBiomes
private static int nextBiomeId = 40;
private static File biomeIdMapFile;
private static ConfigHelper biomeIdMapConf;
private static BOPConfig.IConfigObj biomeIdMapConf;
private static Map<String, Integer> biomeIdMap;
public static void init()
@ -54,14 +53,14 @@ public class ModBiomes
// get BOP biome ids from the config file (if it exists)
biomeIdMapFile = new File(BiomesOPlenty.configDirectory, "biome_ids.json");
biomeIdMapConf = new ConfigHelper(biomeIdMapFile);
biomeIdMapConf = new BOPConfig.ConfigFileObj(biomeIdMapFile);
biomeIdMap = new HashMap<String, Integer>();
registerBiomes();
registerExternalBiomes();
// save the biome ids to the config file (creating it if it doesn't exist)
ConfigHelper.writeFile(biomeIdMapFile, biomeIdMap);
BOPConfig.writeFile(biomeIdMapFile, biomeIdMap);
}
@ -90,15 +89,15 @@ public class ModBiomes
if (id > -1) {
File configFile = new File(new File(BiomesOPlenty.configDirectory, "biomes"), idName + ".json");
ConfigHelper conf = new ConfigHelper(configFile);
BOPConfig.IConfigObj conf = new BOPConfig.ConfigFileObj(configFile);
BOPCommand.biomeCount++;
biome.biomeID = id;
biome.setBiomeName(name);
// If there was a valid config file, then use it to configure the biome
if (!conf.isNull()) {biome.configure(conf);}
if (!conf.isEmpty()) {biome.configure(conf);}
// log any warnings from parsing the config file
for (String msg : conf.messages) {BiomesOPlenty.logger.warn(idName+" config "+msg);}
for (String msg : conf.flushMessages()) {BiomesOPlenty.logger.warn(idName+" config "+msg);}
BiomeGenBase.getBiomeGenArray()[id] = biome;

View File

@ -0,0 +1,577 @@
/*******************************************************************************
* 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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import org.apache.commons.io.FileUtils;
import biomesoplenty.common.util.block.BlockStateUtils;
import biomesoplenty.core.BiomesOPlenty;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class BOPConfig
{
public static Gson serializer = new GsonBuilder().setPrettyPrinting().create();
public static JsonParser parser = new JsonParser();
private static enum Types {BOOLEAN, STRING, INTEGER, FLOAT, BLOCKSTATE}
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;
}
}
public static interface IConfigObj
{
public void addMessage(String message);
public void addMessage(String extraPrefix, String message);
public List<String> flushMessages();
public boolean isEmpty();
public boolean has(String name);
public Set<String> getKeys();
public IConfigObj getObject(String name);
public ArrayList<IConfigObj> getObjectArray(String name);
public IConfigObj getObject(String name, boolean warnIfMissing);
public ArrayList<IConfigObj> getObjectArray(String name, boolean warnIfMissing);
// Use the methods below when you want to obtain a value from a config file, if it is present, but you have a default value to use if it isn't
// No warning messages will be logged using these methods if the value is missing
public Boolean getBool(String name, Boolean defaultVal);
public String getString(String name, String defaultVal);
public Integer getInt(String name, Integer defaultVal);
public Float getFloat(String name, Float defaultVal);
public IBlockState getBlockState(String name, IBlockState defaultVal);
public <E extends Enum> E getEnum(String name, E defaultVal, Class<E> clazz);
// Use the methods below when you want to obtain a value from a config file which SHOULD be present
// If the value is missing, a warning message is logged, and null is returned
public Boolean getBool(String name);
public String getString(String name);
public Integer getInt(String name);
public Float getFloat(String name);
public IBlockState getBlockState(String name);
public <E extends Enum> E getEnum(String name, Class<E> clazz);
// Use the methods below when you want to obtain an array of values from a config file, if it is present, but you have a default value to use if it isn't
// No warning messages will be logged using these methods if the value is missing
public ArrayList<Boolean> getBoolArray(String name, ArrayList<Boolean> defaultVal);
public ArrayList<String> getStringArray(String name, ArrayList<String> defaultVal);
public ArrayList<Integer> getIntArray(String name, ArrayList<Integer> defaultVal);
public ArrayList<Float> getFloatArray(String name, ArrayList<Float> defaultVal);
public ArrayList<IBlockState> getBlockStateArray(String name, ArrayList<IBlockState> defaultVal);
public <E extends Enum> ArrayList<E> getEnumArray(String name, ArrayList<E> defaultVal, Class<E> clazz);
// Use the methods below when you want to obtain an array of values from a config file which SHOULD be present
// If the value is missing, a warning message is logged, and null is returned
public ArrayList<Boolean> getBoolArray(String name);
public ArrayList<String> getStringArray(String name);
public ArrayList<Integer> getIntArray(String name);
public ArrayList<Float> getFloatArray(String name);
public ArrayList<IBlockState> getBlockStateArray(String name);
public <E extends Enum> ArrayList<E> getEnumArray(String name, Class<E> clazz);
}
// Abstract base class for a config object
public static abstract class ConfigObjBase implements IConfigObj
{
protected Map<String,JsonElement> members;
protected List<String> messages = new ArrayList<String>();
protected String prefix = "";
public void parse(String jsonString)
{
this.members = new HashMap<String, JsonElement>();
if (jsonString != null) {return;}
JsonElement rootElement = null;
try
{
rootElement = parser.parse(jsonString);
if (rootElement != null)
{
if (rootElement.isJsonObject())
{
for (Entry<String, JsonElement> entry : rootElement.getAsJsonObject().entrySet())
{
this.members.put(entry.getKey(), entry.getValue());
}
} else {
this.addMessage("Error parsing config: not a JSON object");
}
}
} catch (Exception e) {
this.addMessage("Error parsing config: "+e.getMessage());
}
}
@Override
public void addMessage(String message)
{
this.messages.add(this.prefix + ": " + message);
}
@Override
public void addMessage(String extraPrefix, String message)
{
this.messages.add(this.prefix + "." + extraPrefix + ": " + message);
}
@Override
public List<String> flushMessages()
{
ArrayList out = new ArrayList<String>(this.messages);
this.messages.clear();
return out;
}
@Override
public boolean isEmpty()
{
return this.members == null || this.members.isEmpty();
}
@Override
public boolean has(String name)
{
return this.members != null && this.members.containsKey(name);
}
@Override
public Set<String> getKeys()
{
return this.members.keySet();
}
@Override
public IConfigObj getObject(String name)
{
return this.getObject(name, false);
}
@Override
public IConfigObj getObject(String name, boolean warnIfMissing)
{
if (!this.has(name))
{
if (warnIfMissing)
{
this.addMessage(name, "Error - missing value");
}
return null;
}
try
{
JsonObject obj = this.members.get(name).getAsJsonObject();
return new ConfigChildObj(this.prefix + "." + name, obj);
} catch (Exception e) {
this.addMessage("Error fetching object " + name + ": " + e.getMessage());
return null;
}
}
@Override
public ArrayList<IConfigObj> getObjectArray(String name)
{
return this.getObjectArray(name, false);
}
@Override
public ArrayList<IConfigObj> getObjectArray(String name, boolean warnIfMissing)
{
if (!this.has(name))
{
if (warnIfMissing)
{
this.addMessage(name, "Error - missing value");
}
return null;
}
ArrayList<IConfigObj> list = new ArrayList<IConfigObj>();
try
{
JsonArray arr = this.members.get(name).getAsJsonArray();
for (int i = 0; i < arr.size(); i++)
{
try
{
JsonObject obj = arr.get(i).getAsJsonObject();
if (obj != null) {list.add( new ConfigChildObj(this.prefix + "." + name + "." + i, obj) );}
} catch (Exception e) {
this.addMessage("Error fetching object from array " + name + " at index " + i + ": " + e.getMessage());
}
}
} catch (Exception e) {
this.addMessage("Error fetching object array " + name + ": " + e.getMessage());
return null;
}
return list;
}
// Implement the simple getter methods
@Override
public Boolean getBool(String name, Boolean defaultVal) {return this.<Boolean>get(name, defaultVal, false, Types.BOOLEAN);}
@Override
public String getString(String name, String defaultVal) {return this.<String>get(name, defaultVal, false, Types.STRING);}
@Override
public Integer getInt(String name, Integer defaultVal) {return this.<Integer>get(name, defaultVal, false, Types.INTEGER);}
@Override
public Float getFloat(String name, Float defaultVal) {return this.<Float>get(name, defaultVal, false, Types.FLOAT);}
@Override
public IBlockState getBlockState(String name, IBlockState defaultVal) {return this.<IBlockState>get(name, defaultVal, false, Types.BLOCKSTATE);}
@Override
public <E extends Enum> E getEnum(String name, E defaultVal, Class<E> clazz) {return this.getEnum(name, defaultVal, false, clazz);}
@Override
public Boolean getBool(String name) {return this.<Boolean>get(name, null, true, Types.BOOLEAN);}
@Override
public String getString(String name) {return this.<String>get(name, null, true, Types.STRING);}
@Override
public Integer getInt(String name) {return this.<Integer>get(name, null, true, Types.INTEGER);}
@Override
public Float getFloat(String name) {return this.<Float>get(name, null, true, Types.FLOAT);}
@Override
public IBlockState getBlockState(String name) {return this.<IBlockState>get(name, null, true, Types.BLOCKSTATE);}
@Override
public <E extends Enum> E getEnum(String name, Class<E> clazz) {return this.getEnum(name, null, true, clazz);}
@Override
public ArrayList<Boolean> getBoolArray(String name, ArrayList<Boolean> defaultVal) {return this.<Boolean>getArray(name, defaultVal, false, Types.BOOLEAN);}
@Override
public ArrayList<String> getStringArray(String name, ArrayList<String> defaultVal) {return this.<String>getArray(name, defaultVal, false, Types.STRING);}
@Override
public ArrayList<Integer> getIntArray(String name, ArrayList<Integer> defaultVal) {return this.<Integer>getArray(name, defaultVal, false, Types.INTEGER);}
@Override
public ArrayList<Float> getFloatArray(String name, ArrayList<Float> defaultVal) {return this.<Float>getArray(name, defaultVal, false, Types.FLOAT);}
@Override
public ArrayList<IBlockState> getBlockStateArray(String name, ArrayList<IBlockState> defaultVal) {return this.<IBlockState>getArray(name, defaultVal, false, Types.BLOCKSTATE);}
@Override
public <E extends Enum> ArrayList<E> getEnumArray(String name, ArrayList<E> defaultVal, Class<E> clazz) {return this.getEnumArray(name, defaultVal, false, clazz);}
@Override
public ArrayList<Boolean> getBoolArray(String name) {return this.<Boolean>getArray(name, null, true, Types.BOOLEAN);}
@Override
public ArrayList<String> getStringArray(String name) {return this.<String>getArray(name, null, true, Types.STRING);}
@Override
public ArrayList<Integer> getIntArray(String name) {return this.<Integer>getArray(name, null, true, Types.INTEGER);}
@Override
public ArrayList<Float> getFloatArray(String name) {return this.<Float>getArray(name, null, true, Types.FLOAT);}
@Override
public ArrayList<IBlockState> getBlockStateArray(String name) {return this.<IBlockState>getArray(name, null, true, Types.BLOCKSTATE);}
@Override
public <E extends Enum> ArrayList<E> getEnumArray(String name, Class<E> clazz) {return this.getEnumArray(name, null, true, clazz);}
protected <E extends Enum> ArrayList<E> getEnumArray(String name, ArrayList<E> defaultVal, boolean warnIfMissing, Class<E> clazz)
{
if (!this.has(name))
{
if (warnIfMissing)
{
this.addMessage(name, "Error - missing value");
}
return defaultVal;
}
ArrayList<E> list = new ArrayList<E>();
try
{
JsonArray arr = this.members.get(name).getAsJsonArray();
for (int i = 0; i < arr.size(); i++)
{
E ele = this.<E>asEnum(arr.get(i), clazz, name + "." + i);
if (ele != null) {list.add(ele);}
}
} catch (Exception e) {
this.addMessage(name, "Error fetching " + clazz.getName() + " array: " + e.getMessage());
}
return list;
}
protected <E extends Enum> E getEnum(String name, E defaultVal, boolean warnIfMissing, Class<E> clazz)
{
if (!this.has(name))
{
if (warnIfMissing)
{
this.addMessage(name, "Error - missing value");
}
return defaultVal;
}
E out = this.<E>asEnum(this.members.get(name), clazz, name);
return out == null ? defaultVal : out;
}
private <T> T get(String name, T defaultVal, boolean warnIfMissing, Types type)
{
if (!this.has(name))
{
if (warnIfMissing)
{
this.addMessage(name, "Error - missing value");
}
return defaultVal;
}
T out = this.<T>as(this.members.get(name), type, name);
return out == null ? defaultVal : out;
}
private <T> ArrayList<T> getArray(String name, ArrayList<T> defaultVal, boolean warnIfMissing, Types type)
{
if (!this.has(name))
{
if (warnIfMissing)
{
this.addMessage(name, "Error - missing value");
}
return defaultVal;
}
ArrayList<T> list = new ArrayList<T>();
try
{
JsonArray arr = this.members.get(name).getAsJsonArray();
for (int i = 0; i < arr.size(); i++)
{
T ele = this.<T>as(arr.get(i), type, name + "." + i);
if (ele != null) {list.add(ele);}
}
} catch (Exception e) {
this.addMessage(name, "Error fetching " + type.toString().toLowerCase() + " array: " + e.getMessage());
}
return list;
}
private <T> T as(JsonElement ele, Types type, String extraPrefix)
{
switch (type) {
case BOOLEAN:
return (T)this.asBool(ele, extraPrefix);
case STRING:
return (T)this.asString(ele, extraPrefix);
case INTEGER:
return (T)this.asInt(ele, extraPrefix);
case FLOAT:
return (T)this.asFloat(ele, extraPrefix);
case BLOCKSTATE:
return (T)this.asBlockState(ele, extraPrefix);
default:
return null;
}
}
protected <E extends Enum> E asEnum(JsonElement ele, Class<E>clazz, String extraPrefix)
{
try
{
String val = ele.getAsString();
E[] enums = clazz.getEnumConstants();
if (enums == null)
{
this.addMessage(extraPrefix, "Class " + clazz.getName() + " contains no enum constants");
return null;
}
for (E enumVal : enums)
{
if (enumVal.name().equalsIgnoreCase(val))
{
return enumVal;
}
}
this.addMessage(extraPrefix, "Value " + val + " does not exist in enum " + clazz);
return null;
} catch (Exception e) {
this.addMessage(extraPrefix, "Error fetching string: " + e.getMessage());
return null;
}
}
protected Boolean asBool(JsonElement ele, String extraPrefix)
{
try
{
return ele.getAsBoolean();
} catch (Exception e) {
this.addMessage(extraPrefix, "Error fetching boolean: " + e.getMessage());
return null;
}
}
protected String asString(JsonElement ele, String extraPrefix)
{
try
{
return ele.getAsString();
} catch (Exception e) {
this.addMessage(extraPrefix, "Error fetching string: " + e.getMessage());
return null;
}
}
protected Integer asInt(JsonElement ele, String extraPrefix)
{
try
{
return ele.getAsInt();
} catch (Exception e) {
this.addMessage(extraPrefix, "Error fetching integer: " + e.getMessage());
return null;
}
}
protected Float asFloat(JsonElement ele, String extraPrefix)
{
try
{
return ele.getAsFloat();
} catch (Exception e) {
this.addMessage(extraPrefix, "Error fetching float: " + e.getMessage());
return null;
}
}
protected IBlockState asBlockState(JsonElement ele, String extraPrefix)
{
try {
JsonObject obj = ele.getAsJsonObject();
// attempt to load the specified block
if (!obj.has("block"))
{
this.addMessage(extraPrefix, "Block name missing");
return null;
}
JsonElement blockName = obj.get("block");
if (!blockName.isJsonPrimitive())
{
this.addMessage(extraPrefix, "Invalid block name - must be a string");
return null;
}
Block block = Block.getBlockFromName(blockName.getAsString());
if (block == null)
{
this.addMessage(extraPrefix, "Unrecognised block name " + blockName.getAsString());
return null;
}
IBlockState state = block.getDefaultState();
// attempt to add properties
if (obj.has("properties")) {
JsonElement properties = obj.get("properties");
if (!properties.isJsonObject())
{
this.addMessage(extraPrefix, "Invalid properties list - must be a JSON object");
return state;
}
for (Entry<String, JsonElement> 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(extraPrefix, "Invalid value " + entry.getValue().getAsString() + " for property " + entry.getKey());
}
}
else
{
this.addMessage(extraPrefix, "Invalid property name: " + entry.getKey());
}
}
}
return state;
} catch (Exception e) {
this.addMessage(extraPrefix, "Error fetching blockstate: " + e.getMessage());
return null;
}
}
}
// Concrete class for a config object created by supplying the JSON in a string
public static class ConfigObj extends ConfigObjBase
{
public ConfigObj(String jsonString)
{
this.parse(jsonString);
}
}
// Concrete class for a config object created from a file
public static class ConfigFileObj extends ConfigObjBase
{
public ConfigFileObj(File configFile)
{
this.prefix = configFile.getAbsolutePath();
String jsonString = null;
if (configFile.exists())
{
try
{
jsonString = FileUtils.readFileToString(configFile);
} catch (IOException e) {
this.addMessage("Error reading config file "+e.getMessage());
}
}
this.parse(jsonString);
}
}
// Concrete class for a config object which is a child of another config object
public static class ConfigChildObj extends ConfigObjBase
{
protected ConfigChildObj(String prefix, JsonObject obj)
{
this.prefix = prefix;
this.members = new HashMap<String, JsonElement>();
for (Entry<String, JsonElement> entry : obj.entrySet())
{
this.members.put(entry.getKey(), entry.getValue());
}
}
}
}

View File

@ -1,443 +0,0 @@
/*******************************************************************************
* 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.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import biomesoplenty.common.util.block.BlockStateUtils;
import biomesoplenty.core.BiomesOPlenty;
public class ConfigHelper
{
public static Gson serializer = new GsonBuilder().setPrettyPrinting().create();
public static JsonParser parser = new JsonParser();
public WrappedJsonObject root = null;
public ArrayList<String> messages = new ArrayList<String>();
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 boolean isNull()
{
return this.root == null;
}
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 = new WrappedJsonObject(this, 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 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;
}
}
public WrappedJsonObject getObject(String name)
{
return this.root == null ? null : this.root.getObject(name);
}
public ArrayList<WrappedJsonObject> getObjectArray(String name)
{
return this.root == null ? new ArrayList<WrappedJsonObject>() : this.root.getObjectArray(name);
}
public ArrayList<Boolean> getBoolArray(String name, ArrayList<Boolean> defaultVal)
{
return this.root == null ? new ArrayList<Boolean>() : this.root.getBoolArray(name, defaultVal);
}
public Boolean getBool(String name, Boolean defaultVal)
{
return this.root == null ? defaultVal : this.root.getBool(name, defaultVal);
}
public ArrayList<String> getStringArray(String name, ArrayList<String> defaultVal)
{
return this.root == null ? new ArrayList<String>() : this.root.getStringArray(name, defaultVal);
}
public String getString(String name, String defaultVal)
{
return this.root == null ? defaultVal : this.root.getString(name, defaultVal);
}
public ArrayList<Integer> getIntArray(String name, ArrayList<Integer> defaultVal)
{
return this.root == null ? new ArrayList<Integer>() : this.root.getIntArray(name, defaultVal);
}
public Integer getInt(String name, Integer defaultVal)
{
return this.root == null ? defaultVal : this.root.getInt(name, defaultVal);
}
public ArrayList<Float> getFloatArray(String name, ArrayList<Float> defaultVal)
{
return this.root == null ? new ArrayList<Float>() : this.root.getFloatArray(name, defaultVal);
}
public Float getFloat(String name, Float defaultVal)
{
return this.root == null ? defaultVal : this.root.getFloat(name, defaultVal);
}
public ArrayList<IBlockState> getBlockStateArray(String name, ArrayList<IBlockState> defaultVal)
{
return this.root == null ? new ArrayList<IBlockState>() : this.root.getBlockStateArray(name, defaultVal);
}
public IBlockState getBlockState(String name, IBlockState defaultVal)
{
return this.root == null ? defaultVal : this.root.getBlockState(name, defaultVal);
}
private static enum Types {BOOLEAN, STRING, INTEGER, FLOAT, BLOCKSTATE}
public class WrappedJsonObject
{
private JsonObject obj;
private ConfigHelper conf;
public WrappedJsonObject(ConfigHelper conf, JsonObject obj)
{
this.obj = obj;
this.conf = conf;
}
public ArrayList<String> getKeys()
{
ArrayList<String> out = new ArrayList<String>();
for (Entry<String, JsonElement> entry : this.obj.entrySet())
{
out.add(entry.getKey());
}
return out;
}
public WrappedJsonObject getObject(String name)
{
if (this.obj == null || !this.obj.has(name)) {return null;}
try
{
JsonObject obj = this.obj.getAsJsonObject(name);
if (obj == null) {return null;}
return new WrappedJsonObject(this.conf, obj);
} catch (Exception e) {
this.conf.addMessage("Error fetching object " + name + ": " + e.getMessage());
return null;
}
}
public ArrayList<WrappedJsonObject> getObjectArray(String name)
{
ArrayList<WrappedJsonObject> list = new ArrayList<WrappedJsonObject>();
if (this.obj != null && this.obj.has(name)) {
try
{
JsonArray arr = this.obj.getAsJsonArray(name);
for (int i = 0; i < arr.size(); i++)
{
try
{
JsonObject obj = arr.get(i).getAsJsonObject();
if (obj != null) {list.add( new WrappedJsonObject(this.conf, obj) );}
} catch (Exception e) {
this.conf.addMessage("Error fetching object from array " + name + " at index " + i + ": " + e.getMessage());
}
}
} catch (Exception e) {
this.conf.addMessage("Error fetching object array " + name + ": " + e.getMessage());
return null;
}
}
return list;
}
public ArrayList<Boolean> getBoolArray(String name, ArrayList<Boolean> defaultVal) {return this.<Boolean>getArray(name, defaultVal, Types.BOOLEAN);}
public Boolean getBool(String name, Boolean defaultVal) {return this.<Boolean>get(name, defaultVal, Types.BOOLEAN);}
public ArrayList<String> getStringArray(String name, ArrayList<String> defaultVal) {return this.<String>getArray(name, defaultVal, Types.STRING);}
public String getString(String name, String defaultVal) {return this.<String>get(name, defaultVal, Types.STRING);}
public ArrayList<Integer> getIntArray(String name, ArrayList<Integer> defaultVal) {return this.<Integer>getArray(name, defaultVal, Types.INTEGER);}
public Integer getInt(String name, Integer defaultVal) {return this.<Integer>get(name, defaultVal, Types.INTEGER);}
public ArrayList<Float> getFloatArray(String name, ArrayList<Float> defaultVal) {return this.<Float>getArray(name, defaultVal, Types.FLOAT);}
public Float getFloat(String name, Float defaultVal) {return this.<Float>get(name, defaultVal, Types.FLOAT);}
public ArrayList<IBlockState> getBlockStateArray(String name, ArrayList<IBlockState> defaultVal) {return this.<IBlockState>getArray(name, defaultVal, Types.BLOCKSTATE);}
public IBlockState getBlockState(String name, IBlockState defaultVal) {return this.<IBlockState>get(name, defaultVal, Types.BLOCKSTATE);}
public <E extends Enum> ArrayList<E> getEnumArray(String name, ArrayList<E> defaultVal, Class<E> clazz)
{
if (this.obj == null || !this.obj.has(name)) {return defaultVal;}
ArrayList<E> list = new ArrayList<E>();
try
{
JsonArray arr = this.obj.getAsJsonArray(name);
for (int i = 0; i < arr.size(); i++)
{
E ele = this.<E>asEnum(arr.get(i), clazz);
if (ele != null) {list.add(ele);}
}
} catch (Exception e) {
this.conf.addMessage("Error fetching " + clazz.getName() + " array: " + e.getMessage());
}
return list;
}
public <E extends Enum> E getEnum(String name, E defaultVal, Class<E> clazz)
{
if (this.obj == null || !this.obj.has(name)) {return defaultVal;}
E out = this.<E>asEnum(this.obj.get(name), clazz);
return out == null ? defaultVal : out;
}
private <T> T get(String name, T defaultVal, Types type)
{
if (this.obj == null || !this.obj.has(name)) {return defaultVal;}
T out = this.<T>as(this.obj.get(name), type);
return out == null ? defaultVal : out;
}
private <T> ArrayList<T> getArray(String name, ArrayList<T> defaultVal, Types type)
{
if (this.obj == null || !this.obj.has(name)) {return defaultVal;}
ArrayList<T> list = new ArrayList<T>();
try
{
JsonArray arr = this.obj.getAsJsonArray(name);
for (int i = 0; i < arr.size(); i++)
{
T ele = this.<T>as(arr.get(i), type);
if (ele != null) {list.add(ele);}
}
} catch (Exception e) {
this.conf.addMessage("Error fetching " + type.toString().toLowerCase() + " array: " + e.getMessage());
}
return list;
}
private <T> T as(JsonElement ele, Types type)
{
switch (type) {
case BOOLEAN:
return (T)this.asBool(ele);
case STRING:
return (T)this.asString(ele);
case INTEGER:
return (T)this.asInt(ele);
case FLOAT:
return (T)this.asFloat(ele);
case BLOCKSTATE:
return (T)this.asBlockState(ele);
default:
return null;
}
}
public <E extends Enum> E asEnum(JsonElement ele, Class<E>clazz)
{
try
{
String val = ele.getAsString();
E[] enums = clazz.getEnumConstants();
if (enums == null)
{
this.conf.addMessage("Class " + clazz.getName() + " contains no enum constants");
return null;
}
for (E enumVal : enums)
{
if (enumVal.name().equalsIgnoreCase(val))
{
return enumVal;
}
}
this.conf.addMessage("Value " + val + " does not exist in enum " + clazz);
return null;
} catch (Exception e) {
this.conf.addMessage("Error fetching string: " + e.getMessage());
return null;
}
}
public Boolean asBool(JsonElement ele)
{
try
{
return ele.getAsBoolean();
} catch (Exception e) {
this.conf.addMessage("Error fetching boolean: " + e.getMessage());
return null;
}
}
public String asString(JsonElement ele)
{
try
{
return ele.getAsString();
} catch (Exception e) {
this.conf.addMessage("Error fetching string: " + e.getMessage());
return null;
}
}
public Integer asInt(JsonElement ele)
{
try
{
return ele.getAsInt();
} catch (Exception e) {
this.conf.addMessage("Error fetching integer: " + e.getMessage());
return null;
}
}
public Float asFloat(JsonElement ele)
{
try
{
return ele.getAsFloat();
} catch (Exception e) {
this.conf.addMessage("Error fetching float: " + e.getMessage());
return null;
}
}
public IBlockState asBlockState(JsonElement arse)
{
try {
JsonObject ele = arse.getAsJsonObject();
// attempt to load the specified block
if (!ele.has("block"))
{
this.conf.addMessage("Block name missing");
return null;
}
JsonElement blockName = ele.get("block");
if (!blockName.isJsonPrimitive())
{
this.conf.addMessage("Invalid block name - must be a string");
return null;
}
Block block = Block.getBlockFromName(blockName.getAsString());
if (block == null)
{
this.conf.addMessage("Unrecognised block name " + blockName.getAsString());
return null;
}
IBlockState state = block.getDefaultState();
// attempt to add properties
if (ele.has("properties")) {
JsonElement properties = ele.get("properties");
if (!properties.isJsonObject())
{
this.conf.addMessage("Invalid properties list - must be a JSON object");
return state;
}
for (Entry<String, JsonElement> 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.conf.addMessage("Invalid value " + entry.getValue().getAsString() + " for property " + entry.getKey());
}
}
else
{
this.conf.addMessage("Invalid property name: " + entry.getKey());
}
}
}
return state;
} catch (Exception e) {
this.conf.addMessage("Error fetching blockstate: " + e.getMessage());
return null;
}
}
}
}

View File

@ -16,7 +16,7 @@ import biomesoplenty.common.block.BlockBOPDoublePlant;
import biomesoplenty.common.block.BlockDecoration;
import biomesoplenty.common.block.BlockDoubleDecoration;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BlockPos;
@ -91,7 +91,7 @@ public class GeneratorDoubleFlora extends GeneratorCustomizable
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
this.bottomState = conf.getBlockState("bottomState", this.bottomState);

View File

@ -18,7 +18,7 @@ import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.GeneratorCustomizable;
import biomesoplenty.common.block.BlockDecoration;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorFlora extends GeneratorCustomizable
{
@ -80,7 +80,7 @@ public class GeneratorFlora extends GeneratorCustomizable
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
this.state = conf.getBlockState("state", this.state);

View File

@ -17,7 +17,7 @@ import org.apache.commons.lang3.tuple.Pair;
import biomesoplenty.api.biome.generation.GeneratorCustomizable;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public abstract class GeneratorOreBase extends GeneratorCustomizable
{
@ -46,7 +46,7 @@ public abstract class GeneratorOreBase extends GeneratorCustomizable
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
int minHeight = conf.getInt("minHeight", this.minHeight).intValue();

View File

@ -10,12 +10,12 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenMinable;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
public class GeneratorOreCluster extends GeneratorOreBase
{
@ -41,7 +41,7 @@ public class GeneratorOreCluster extends GeneratorOreBase
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
super.configure(conf);

View File

@ -15,7 +15,7 @@ import net.minecraft.block.state.pattern.BlockHelper;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import com.google.common.base.Predicate;
@ -50,7 +50,7 @@ public class GeneratorOreSingle extends GeneratorOreBase
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
super.configure(conf);

View File

@ -19,7 +19,7 @@ import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.GeneratorCustomizable;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorWaterside extends GeneratorCustomizable
{
@ -106,7 +106,7 @@ public class GeneratorWaterside extends GeneratorCustomizable
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
this.maxRadius = conf.getInt("maxRadius", this.maxRadius);

View File

@ -24,7 +24,7 @@ import org.apache.commons.lang3.tuple.Pair;
import biomesoplenty.api.biome.generation.GeneratorCustomizable;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorBasicTree extends GeneratorCustomizable
{
@ -302,7 +302,7 @@ public class GeneratorBasicTree extends GeneratorCustomizable
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
this.updateNeighbours = conf.getBool("updateNeighbours", this.updateNeighbours);

View File

@ -23,7 +23,7 @@ import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.GeneratorCustomizable;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import com.google.common.collect.Lists;
@ -535,7 +535,7 @@ public class GeneratorBigTree extends GeneratorCustomizable
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
this.updateNeighbours = conf.getBool("updateNeighbours", this.updateNeighbours);

View File

@ -17,9 +17,8 @@ import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.GeneratorCustomizable;
import biomesoplenty.common.util.config.ConfigHelper.WrappedJsonObject;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorBush extends GeneratorCustomizable
{
@ -110,7 +109,7 @@ public class GeneratorBush extends GeneratorCustomizable
}
@Override
public void configure(WrappedJsonObject conf)
public void configure(IConfigObj conf)
{
this.amountPerChunk = conf.getInt("amountPerChunk", this.amountPerChunk);
this.log = conf.getBlockState("logState", this.log);