Default biome config files are now generated. Please note, you CANNOT directly copy and paste these, the game WILL crash INTENTIONALLY. You must only include the sections you have changed from default.

This commit is contained in:
Adubbz 2017-06-10 20:48:04 +10:00
parent 3cebe1d3e6
commit 0af17b32fd
9 changed files with 194 additions and 72 deletions

View file

@ -12,11 +12,13 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import biomesoplenty.api.block.IBlockPosQuery; import biomesoplenty.api.block.IBlockPosQuery;
import com.google.gson.JsonElement;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
public interface IConfigObj public interface IConfigObj
{ {
public JsonElement serializeDefaults();
public void addMessage(String message); public void addMessage(String message);
public void addMessage(String extraPrefix, String message); public void addMessage(String extraPrefix, String message);
public List<String> flushMessages(); public List<String> flushMessages();

View file

@ -17,5 +17,5 @@ public interface IGenerationManager
ImmutableCollection<IGenerator> getGeneratorsForStage(GeneratorStage stage); ImmutableCollection<IGenerator> getGeneratorsForStage(GeneratorStage stage);
void removeGenerator(String name); void removeGenerator(String name);
IGenerator getGenerator(String name); IGenerator getGenerator(String name);
void configureWith(String name, IConfigObj conf); void configure(IConfigObj conf);
} }

View file

@ -14,7 +14,6 @@ import biomesoplenty.api.config.IConfigObj;
import biomesoplenty.api.enums.BOPClimates; import biomesoplenty.api.enums.BOPClimates;
import biomesoplenty.api.generation.GeneratorStage; import biomesoplenty.api.generation.GeneratorStage;
import biomesoplenty.api.generation.IGenerator; import biomesoplenty.api.generation.IGenerator;
import biomesoplenty.common.biome.overworld.BOPOverworldBiome;
import biomesoplenty.common.init.ModBiomes; import biomesoplenty.common.init.ModBiomes;
import biomesoplenty.common.world.GenerationManager; import biomesoplenty.common.world.GenerationManager;
import biomesoplenty.core.BiomesOPlenty; import biomesoplenty.core.BiomesOPlenty;
@ -105,11 +104,9 @@ public abstract class BOPBiome extends Biome implements IExtendedBiome
// Allow weights to be overridden // Allow weights to be overridden
IConfigObj confWeights = conf.getObject("weights"); IConfigObj confWeights = conf.getObject("weights");
if (confWeights != null)
{
for (BOPClimates climate : BOPClimates.values()) for (BOPClimates climate : BOPClimates.values())
{ {
Integer weight = confWeights.getInt(climate.name().toLowerCase(), null); Integer weight = confWeights.getInt(climate.name().toLowerCase(), this.weightMap.get(climate));
if (weight == null) {continue;} if (weight == null) {continue;}
if (weight.intValue() < 1) if (weight.intValue() < 1)
{ {
@ -120,17 +117,10 @@ public abstract class BOPBiome extends Biome implements IExtendedBiome
this.weightMap.put(climate, weight); this.weightMap.put(climate, weight);
} }
} }
}
// Allow generators to be configured // Allow generators to be configured
IConfigObj confGenerators = conf.getObject("generators"); IConfigObj confGenerators = conf.getObject("generators");
if (confGenerators != null) this.generationManager.configure(confGenerators);
{
for (String name : confGenerators.getKeys())
{
this.generationManager.configureWith(name, confGenerators.getObject(name));
}
}
// Allow spawnable entites to be configured // Allow spawnable entites to be configured
ArrayList<IConfigObj> confEntities = conf.getObjectArray("entities"); ArrayList<IConfigObj> confEntities = conf.getObjectArray("entities");

View file

@ -17,6 +17,7 @@ import biomesoplenty.api.generation.GeneratorStage;
import biomesoplenty.api.generation.IGenerationManager; import biomesoplenty.api.generation.IGenerationManager;
import biomesoplenty.api.generation.IGenerator; import biomesoplenty.api.generation.IGenerator;
import biomesoplenty.common.biome.BOPBiome; import biomesoplenty.common.biome.BOPBiome;
import biomesoplenty.common.init.ModBiomes;
import biomesoplenty.common.util.biome.GeneratorUtils; import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.world.generator.GeneratorHive; import biomesoplenty.common.world.generator.GeneratorHive;
import biomesoplenty.common.world.generator.GeneratorSplatter; import biomesoplenty.common.world.generator.GeneratorSplatter;
@ -70,6 +71,9 @@ public class BOPHellBiome extends BOPBiome
this.wallBlock = conf.getBlockState("wallBlock", this.wallBlock); this.wallBlock = conf.getBlockState("wallBlock", this.wallBlock);
this.roofTopBlock = conf.getBlockState("roofTopBlock", this.roofTopBlock); this.roofTopBlock = conf.getBlockState("roofTopBlock", this.roofTopBlock);
this.roofFillerBlock = conf.getBlockState("roofFillerBlock", this.roofFillerBlock); this.roofFillerBlock = conf.getBlockState("roofFillerBlock", this.roofFillerBlock);
// write default values to a file
ModBiomes.writeDefaultConfigFile(ModBiomes.BOP_DEFAULTS_DIR, this.getResourceLocation().getResourcePath(), conf);
} }
@Override @Override

View file

@ -34,6 +34,7 @@ import biomesoplenty.common.init.ModBiomes;
import biomesoplenty.common.util.biome.BiomeUtils; import biomesoplenty.common.util.biome.BiomeUtils;
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod; import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
import biomesoplenty.common.util.block.BlockQuery; import biomesoplenty.common.util.block.BlockQuery;
import biomesoplenty.common.util.config.BOPConfig;
import biomesoplenty.common.world.GenerationManager; import biomesoplenty.common.world.GenerationManager;
import biomesoplenty.common.world.TerrainSettings; import biomesoplenty.common.world.TerrainSettings;
import biomesoplenty.common.world.generator.GeneratorColumns; import biomesoplenty.common.world.generator.GeneratorColumns;
@ -117,12 +118,14 @@ public class BOPOverworldBiome extends BOPBiome
this.canGenerateRivers = conf.getBool("canGenerateRivers", this.canGenerateRivers); this.canGenerateRivers = conf.getBool("canGenerateRivers", this.canGenerateRivers);
this.beachBiomeLocation = conf.getResourceLocation("beachBiomeLocation", this.beachBiomeLocation); this.beachBiomeLocation = conf.getResourceLocation("beachBiomeLocation", this.beachBiomeLocation);
// write default values to a file
ModBiomes.writeDefaultConfigFile(ModBiomes.BOP_DEFAULTS_DIR, this.getResourceLocation().getResourcePath(), conf);
} }
@Override @Override
public void genTerrainBlocks(World world, Random rand, ChunkPrimer primer, int x, int z, double stoneNoiseVal) public void genTerrainBlocks(World world, Random rand, ChunkPrimer primer, int x, int z, double stoneNoiseVal)
{ {
IBlockState topBlock = this.topBlock; IBlockState topBlock = this.topBlock;
IBlockState fillerBlock = this.fillerBlock; IBlockState fillerBlock = this.fillerBlock;
IBlockState seaFloorBlock = this.seaFloorBlock; IBlockState seaFloorBlock = this.seaFloorBlock;

View file

@ -16,6 +16,7 @@ import biomesoplenty.api.enums.BOPPlants;
import biomesoplenty.api.generation.GeneratorStage; import biomesoplenty.api.generation.GeneratorStage;
import biomesoplenty.api.generation.IGenerator; import biomesoplenty.api.generation.IGenerator;
import biomesoplenty.common.block.BlockBOPMushroom; import biomesoplenty.common.block.BlockBOPMushroom;
import biomesoplenty.common.init.ModBiomes;
import biomesoplenty.common.util.biome.BiomeUtils; import biomesoplenty.common.util.biome.BiomeUtils;
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod; import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
import biomesoplenty.common.util.block.BlockQuery; import biomesoplenty.common.util.block.BlockQuery;
@ -64,13 +65,10 @@ public class ExtendedBiomeWrapper implements IExtendedBiome
// Allow generators to be configured // Allow generators to be configured
IConfigObj confGenerators = conf.getObject("generators"); IConfigObj confGenerators = conf.getObject("generators");
if (confGenerators != null) this.generationManager.configure(confGenerators);
{
for (String name : confGenerators.getKeys()) // write default values to a file
{ ModBiomes.writeDefaultConfigFile(ModBiomes.VANILLA_DEFAULTS_DIR, this.getResourceLocation().getResourcePath(), conf);
this.generationManager.configureWith(name, confGenerators.getObject(name));
}
}
} }
@Override @Override

View file

@ -141,9 +141,15 @@ import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.BiomeDictionary.Type; import net.minecraftforge.common.BiomeDictionary.Type;
import net.minecraftforge.common.BiomeManager; import net.minecraftforge.common.BiomeManager;
import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.DimensionManager;
import org.apache.commons.io.FileUtils;
public class ModBiomes implements BOPBiomes.IBiomeRegistry public class ModBiomes implements BOPBiomes.IBiomeRegistry
{ {
public static final File BIOMES_DIR = new File(BiomesOPlenty.configDirectory, "biomes");
public static final File DEFAULTS_DIR = new File(BIOMES_DIR, "defaults");
public static final File BOP_DEFAULTS_DIR = new File(DEFAULTS_DIR, "biomesoplenty");
public static final File VANILLA_DEFAULTS_DIR = new File(DEFAULTS_DIR, "vanilla");
public static WorldTypeBOP worldTypeBOP; public static WorldTypeBOP worldTypeBOP;
private static int nextBiomeId = 40; private static int nextBiomeId = 40;
@ -181,19 +187,27 @@ public class ModBiomes implements BOPBiomes.IBiomeRegistry
} }
//Create a folder and temp file to show people where to put biome config files //Create a folder and temp file to show people where to put biome config files
File biomesDir = new File(BiomesOPlenty.configDirectory, "biomes"); if (!BIOMES_DIR.exists())
if (!biomesDir.exists())
{ {
biomesDir.mkdir(); BIOMES_DIR.mkdir();
try try
{ {
(new File(biomesDir, "Put biome config files here")).createNewFile(); (new File(BIOMES_DIR, "Put biome config files here")).createNewFile();
} }
catch (IOException e) {} catch (IOException e) {}
} }
// remove any existing default files and recreate the directory
try {
FileUtils.deleteDirectory(DEFAULTS_DIR);
}
catch (Exception e)
{
BiomesOPlenty.logger.error("Could not delete default biome config directory!");
}
DEFAULTS_DIR.mkdir();
initSubBiomes(); initSubBiomes();
registerBiomes(); registerBiomes();
@ -535,6 +549,20 @@ public class ModBiomes implements BOPBiomes.IBiomeRegistry
return conf; return conf;
} }
public static void writeDefaultConfigFile(File basePath, String idName, IConfigObj conf)
{
File defaultFile = new File(basePath, idName + ".json");
String json = BOPConfig.serializer.toJson(conf.serializeDefaults());
try {
FileUtils.write(defaultFile, json);
}
catch (Exception e)
{
BiomesOPlenty.logger.error("Could not write default biome config file " + defaultFile.getName());
}
}
private static void setSubBiome(Optional<Biome> parent, Optional<Biome>... subBiomes) private static void setSubBiome(Optional<Biome> parent, Optional<Biome>... subBiomes)
{ {
if (parent.isPresent()) if (parent.isPresent())

View file

@ -17,15 +17,10 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import com.google.common.collect.Maps;
import com.google.gson.*;
import org.apache.commons.io.FileUtils; 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.api.block.IBlockPosQuery; import biomesoplenty.api.block.IBlockPosQuery;
import biomesoplenty.api.config.IConfigObj; import biomesoplenty.api.config.IConfigObj;
import biomesoplenty.common.util.block.BlockQuery; import biomesoplenty.common.util.block.BlockQuery;
@ -59,9 +54,17 @@ public class BOPConfig
public static abstract class ConfigObjBase implements IConfigObj public static abstract class ConfigObjBase implements IConfigObj
{ {
protected Map<String,JsonElement> members; protected Map<String,JsonElement> members;
protected Map<String, JsonElement> defaults;
protected Map<String, ConfigChildObj> childObjs;
protected List<String> messages = new ArrayList<String>(); protected List<String> messages = new ArrayList<String>();
protected String prefix = ""; protected String prefix = "";
private ConfigObjBase()
{
this.defaults = Maps.newHashMap();
this.childObjs = Maps.newHashMap();
}
public void parse(String jsonString) public void parse(String jsonString)
{ {
this.members = new HashMap<String, JsonElement>(); this.members = new HashMap<String, JsonElement>();
@ -87,6 +90,29 @@ public class BOPConfig
} }
} }
@Override
public JsonElement serializeDefaults()
{
if (this.defaults.isEmpty())
{
this.addMessage("No defaults found!");
}
// add top-level properties
JsonObject rootObject = new JsonObject();
for (Entry<String, JsonElement> entry : defaults.entrySet())
{
rootObject.add(entry.getKey(), entry.getValue());
}
// serialize children
for (Entry<String, ConfigChildObj> entry : this.childObjs.entrySet())
{
rootObject.add(entry.getKey(), entry.getValue().serializeDefaults());
}
return rootObject;
}
@Override @Override
public void addMessage(String message) public void addMessage(String message)
@ -135,16 +161,27 @@ public class BOPConfig
{ {
this.addMessage(name, "Error - missing value"); this.addMessage(name, "Error - missing value");
} }
return null;
} }
// attempt to return cached child first
if (this.childObjs.containsKey(name))
{
return this.childObjs.get(name);
}
JsonObject obj = new JsonObject();
try try
{ {
JsonObject obj = this.members.get(name).getAsJsonObject(); obj = this.members.get(name).getAsJsonObject();
return new ConfigChildObj(this.prefix + "." + name, obj);
} catch (Exception e) { } catch (Exception e) {
this.addMessage("Error fetching object " + name + ": " + e.getMessage()); this.addMessage("Error fetching object " + name + ": " + e.getMessage());
return null;
} }
ConfigChildObj childObj = new ConfigChildObj(this.prefix + "." + name, obj);
// store the child for later serialization
this.childObjs.put(name, childObj);
return childObj;
} }
@Override @Override
@ -299,6 +336,14 @@ public class BOPConfig
private <T> T get(String name, T defaultVal, boolean warnIfMissing, Types type) private <T> T get(String name, T defaultVal, boolean warnIfMissing, Types type)
{ {
// if a default value is set, store it for later use
if (defaultVal != null)
{
JsonElement element = this.from(defaultVal, type);
// don't store if conversion to a JsonElement failed
if (element != null) this.defaults.put(name, element);
}
// check if the property exists, if not, use the default
if (!this.has(name)) if (!this.has(name))
{ {
if (warnIfMissing) if (warnIfMissing)
@ -308,6 +353,11 @@ public class BOPConfig
return defaultVal; return defaultVal;
} }
T out = this.<T>as(this.members.get(name), type, name); T out = this.<T>as(this.members.get(name), type, name);
// prevent people from trying to copy-paste default configs
if (out != null && out.equals(defaultVal))
{
throw new RuntimeException("NOTE: This is YOUR fault, DO NOT report this to any developers.\n You can't set a property to its default value, only changed properties can be included in config files. \n Property: " + name + " Value: " + out + " Location: " + this.prefix);
}
return out == null ? defaultVal : out; return out == null ? defaultVal : out;
} }
@ -351,12 +401,13 @@ public class BOPConfig
return (T)this.asBlockState(ele, extraPrefix); return (T)this.asBlockState(ele, extraPrefix);
case BLOCKPOSQUERY: case BLOCKPOSQUERY:
return (T)this.asBlockPosQuery(ele, extraPrefix); return (T)this.asBlockPosQuery(ele, extraPrefix);
case RESOURCELOCATION:
return (T)this.asResourceLocation(ele, extraPrefix);
default: default:
return null; return null;
} }
} }
protected <E extends Enum> E asEnum(JsonElement ele, Class<E>clazz, String extraPrefix) protected <E extends Enum> E asEnum(JsonElement ele, Class<E>clazz, String extraPrefix)
{ {
try try
@ -522,6 +573,51 @@ public class BOPConfig
} }
} }
private JsonElement from(Object value, Types type)
{
switch (type) {
case BOOLEAN:
return new JsonPrimitive((Boolean)value);
case STRING:
return new JsonPrimitive((String)value);
case INTEGER:
return new JsonPrimitive((Integer)value);
case FLOAT:
return new JsonPrimitive((Float)value);
case BLOCKSTATE:
return fromState((IBlockState)value);
case BLOCKPOSQUERY:
return null; // ignore for now
case RESOURCELOCATION:
return fromResourceLocation((ResourceLocation)value);
default:
BiomesOPlenty.logger.error("Undefined type " + type);
return null;
}
}
private JsonElement fromState(IBlockState state)
{
JsonObject root = new JsonObject();
// add block name
root.add("block", new JsonPrimitive(state.getBlock().getRegistryName().toString()));
JsonObject properties = new JsonObject();
root.add("properties", properties);
// add all property values
for (Entry<IProperty<?>, Comparable<?>> entry : state.getProperties().entrySet())
{
properties.add(entry.getKey().getName(), new JsonPrimitive(entry.getValue().toString()));
}
return root;
}
private JsonElement fromResourceLocation(ResourceLocation location)
{
return new JsonPrimitive(location.toString());
}
} }
// Concrete class for a config object created by supplying the JSON in a string // Concrete class for a config object created by supplying the JSON in a string

View file

@ -58,30 +58,31 @@ public class GenerationManager implements IGenerationManager
return this.generators.get(name); return this.generators.get(name);
} }
public void configureWith(String name, IConfigObj conf) public void configure(IConfigObj generatorsObj)
{ {
if (this.generators.containsKey(name)) // iterate over all registered generators
for (String name : generators.keySet())
{ {
if (conf.getBool("enable", true)) IConfigObj currentObj = generatorsObj.getObject(name);
// there was previously no generator of this name - attempt to add it
if (generatorsObj.has(name))
{ {
// configure the existing generator IGenerator generator = GeneratorRegistry.createGenerator(currentObj);
this.generators.get(name).configure(conf); if (generator != null) {
this.generators.put(name, generator);
} }
else }
{
// configure the generator
// always attempt to do this so defaults are generated
if (currentObj.getBool("enable", true)) {
this.generators.get(name).configure(currentObj);
} else {
// remove this generator // remove this generator
this.generators.remove(name); this.generators.remove(name);
} }
} }
else
{
// there was previously no generator of this name - attempt to add it
IGenerator generator = GeneratorRegistry.createGenerator(conf);
if (generator != null)
{
this.generators.put(name, generator);
}
}
} }
} }