Rewrite biome configuration system to be simpler and less fragile

This commit is contained in:
Cheeserolls 2015-05-22 22:11:26 +01:00
parent 5016917fb9
commit 7faffa5a89
3 changed files with 313 additions and 62 deletions

View file

@ -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
{
@ -34,6 +35,20 @@ public class BOPBiome extends BiomeGenBase implements IExtendedBiome
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()
{

View file

@ -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,41 +33,91 @@ 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<String, Integer> 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<String, Integer>();
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<BiomeGenBase> 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<BiomeType, Integer> 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()
{
/*registerExternalBiome(BiomeGenBase.ocean, "ocean");
@ -107,14 +162,6 @@ public class ModBiomes
registerExternalBiome(BiomeGenBase.mesaPlateau, "mesa_plateau");*/
}
private static Optional<BiomeGenBase> 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);
@ -140,41 +187,4 @@ public class ModBiomes
return -1;
}
private static Optional<BiomeGenBase> 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();
}
}

View file

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