feat: custom dimensions
This commit is contained in:
parent
24af45798e
commit
58164c7554
9 changed files with 304 additions and 6 deletions
src/main/java/dev/tilera/cwg
|
@ -11,8 +11,12 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
|||
import dev.tilera.cwg.api.CwgGlobals;
|
||||
import dev.tilera.cwg.api.hooks.IHookProvider;
|
||||
import dev.tilera.cwg.api.utils.BooleanOption;
|
||||
import dev.tilera.cwg.api.utils.IntOption;
|
||||
import dev.tilera.cwg.api.utils.StringOption;
|
||||
import dev.tilera.cwg.classic.ClassicChunkManagerFactory;
|
||||
import dev.tilera.cwg.command.CommandChangeWorld;
|
||||
import dev.tilera.cwg.dimensions.CustomDimensions;
|
||||
import dev.tilera.cwg.dimensions.DimProvider;
|
||||
import dev.tilera.cwg.hooks.DefaultCavegenHook;
|
||||
import dev.tilera.cwg.hooks.DefaultTemperatureHook;
|
||||
import dev.tilera.cwg.hooks.HookOption;
|
||||
|
@ -23,10 +27,12 @@ import dev.tilera.cwg.noisegen.NoiseGeneratorOctavesFarlands;
|
|||
import dev.tilera.cwg.options.ChunkManagerOption;
|
||||
import dev.tilera.cwg.options.ConfigProvider;
|
||||
import dev.tilera.cwg.proxy.CommonProxy;
|
||||
import dev.tilera.cwg.vanilla.SingleBiomeChunkManagerFactory;
|
||||
import dev.tilera.cwg.vanilla.VanillaChunkManagerFactory;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraft.world.gen.NoiseGenerator;
|
||||
import net.minecraft.world.gen.NoiseGeneratorOctaves;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.terraingen.InitMapGenEvent;
|
||||
import net.minecraftforge.event.terraingen.InitNoiseGensEvent;
|
||||
|
@ -47,6 +53,7 @@ public class ClassicWorldgen {
|
|||
@EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
Config.initConfig();
|
||||
CustomDimensions.INSTANCE = new CustomDimensions(CUSTOM);
|
||||
CwgGlobals.setOptionRegistry(CUSTOM);
|
||||
CwgGlobals.setDefaultProvider(CONFIG);
|
||||
CwgGlobals.setGeneratorRegistry(CUSTOM);
|
||||
|
@ -62,6 +69,9 @@ public class ClassicWorldgen {
|
|||
registerGenerators();
|
||||
registerOptions();
|
||||
registerHooks();
|
||||
DimensionManager.registerProviderType(Config.dimensionProviderID, DimProvider.class, false);
|
||||
CustomDimensions.INSTANCE.readConfig(Config.dimensionsDefinition);
|
||||
CustomDimensions.INSTANCE.registerDimensions();
|
||||
}
|
||||
|
||||
public void registerOptions() {
|
||||
|
@ -75,6 +85,9 @@ public class ClassicWorldgen {
|
|||
CwgGlobals.getOptionRegistry().registerOption(new BooleanOption("cwg:disable_jungle_melons", "Disable Jungle Melons", false));
|
||||
CwgGlobals.getOptionRegistry().registerOption(new BooleanOption("cwg:disable_new_flowers", "Disable new Flowers", false));
|
||||
CwgGlobals.getOptionRegistry().registerOption(new BooleanOption("cwg:disable_tall_flowers", "Disable Tall Flowers", false));
|
||||
CwgGlobals.getOptionRegistry().registerOption(new StringOption("cwg:dimensions:name", "Dimension Name", "Custom Dimension", true));
|
||||
CwgGlobals.getOptionRegistry().registerOption(new IntOption("cwg:dimensions:provider", "Provider ID", Config.dimensionProviderID, true, false));
|
||||
CwgGlobals.getOptionRegistry().registerOption(new IntOption("cwg:generator.singleBiome:biomeID", "Biome ID", 0, false, true));
|
||||
}
|
||||
|
||||
public void registerHooks() {
|
||||
|
@ -91,6 +104,7 @@ public class ClassicWorldgen {
|
|||
VanillaChunkManagerFactory def = new VanillaChunkManagerFactory();
|
||||
CwgGlobals.getGeneratorRegistry().registerChunkManager(def);
|
||||
CwgGlobals.getGeneratorRegistry().registerChunkManager(new ClassicChunkManagerFactory());
|
||||
CwgGlobals.getGeneratorRegistry().registerChunkManager(new SingleBiomeChunkManagerFactory());
|
||||
CwgGlobals.getOptionRegistry().registerOption(new ChunkManagerOption(
|
||||
"cwg:generator",
|
||||
"Generator",
|
||||
|
|
|
@ -7,6 +7,7 @@ import net.minecraftforge.common.config.Configuration;
|
|||
|
||||
public class Config {
|
||||
|
||||
public static File dimensionsDefinition;
|
||||
static Configuration conf;
|
||||
public static boolean enableSwissCheeseCaves = false;
|
||||
public static boolean addNewVanillaBiomes = false;
|
||||
|
@ -17,9 +18,13 @@ public class Config {
|
|||
public static boolean disableModdedBiomes = false;
|
||||
public static boolean enableDesertLakes = true;
|
||||
public static boolean enableModdedWorldgen = true;
|
||||
public static int dimensionProviderID = 88;
|
||||
|
||||
public static void initConfig() {
|
||||
conf = new Configuration(new File(Loader.instance().getConfigDir(), "ClassicWorldgen.cfg"));
|
||||
File cwgDir = new File(Loader.instance().getConfigDir(), "cwg");
|
||||
cwgDir.mkdirs();
|
||||
dimensionsDefinition = new File(cwgDir, "dimensions.json");
|
||||
conf.load();
|
||||
enableSwissCheeseCaves = conf.getBoolean("enableSwissCheeseCaves", "caves", enableSwissCheeseCaves, "enable classic (1.6) cavegen");
|
||||
addNewVanillaBiomes = conf.getBoolean("addNewVanillaBiomes", "worldgen", addNewVanillaBiomes, "generate new 1.7 vanilla biomes with classic/1.6 WorldType");
|
||||
|
@ -30,6 +35,7 @@ public class Config {
|
|||
disableModdedBiomes = conf.getBoolean("disableModdedBiomes", "worldgen", disableModdedBiomes, "prevent modded biomes from generating in classic worldgen");
|
||||
enableDesertLakes = conf.getBoolean("enableDesertLakes", "worldgen", enableDesertLakes, "enable lakes in desert in classic worldgen");
|
||||
enableModdedWorldgen = conf.getBoolean("enableModdedWorldgen", "worldgen", enableModdedWorldgen, "enable worldgen features from other mods");
|
||||
dimensionProviderID = conf.getInt("providerID", "dimensions", dimensionProviderID, Integer.MIN_VALUE, Integer.MAX_VALUE, null);
|
||||
conf.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,13 +41,17 @@ public class WorldTypeCustom extends WorldType implements IGeneratorOptionRegist
|
|||
public WorldChunkManager getChunkManager(World world) {
|
||||
String opts = world.getWorldInfo().getGeneratorOptions();
|
||||
IGeneratorOptionProvider options;
|
||||
try {
|
||||
options = decodeOptions(opts);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (opts.isEmpty()) {
|
||||
options = this;
|
||||
} else {
|
||||
try {
|
||||
options = decodeOptions(opts);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
options = this;
|
||||
}
|
||||
}
|
||||
AbstractChunkManager manager = options.getValue("cwg:generator", IChunkManagerFactory.class).createChunkManager(ClassicWorldgen.CONFIG, world);
|
||||
AbstractChunkManager manager = options.getValue("cwg:generator", IChunkManagerFactory.class).createChunkManager(options, world);
|
||||
CwgGlobals.setCurrentState(world);
|
||||
return manager;
|
||||
}
|
||||
|
@ -181,4 +185,25 @@ public class WorldTypeCustom extends WorldType implements IGeneratorOptionRegist
|
|||
return chunkManagerRegistry.values().stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> IOption<T> getOption(String id, Class<T> type) {
|
||||
IOption<?> opt = optionRegistry.get(id);
|
||||
if (opt != null && opt.getType() == type) {
|
||||
return (IOption<T>) optionRegistry.get(id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getOptionType(String id) {
|
||||
IOption<?> opt = optionRegistry.get(id);
|
||||
if (opt != null) {
|
||||
return opt.getType();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,4 +14,8 @@ public interface IGeneratorOptionRegistry extends IGeneratorOptionProvider {
|
|||
|
||||
<T> boolean isRegistered(String id, Class<T> type);
|
||||
|
||||
<T> IOption<T> getOption(String id, Class<T> type);
|
||||
|
||||
Class<?> getOptionType(String id);
|
||||
|
||||
}
|
||||
|
|
79
src/main/java/dev/tilera/cwg/api/utils/IntOption.java
Normal file
79
src/main/java/dev/tilera/cwg/api/utils/IntOption.java
Normal file
|
@ -0,0 +1,79 @@
|
|||
package dev.tilera.cwg.api.utils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import dev.tilera.cwg.api.options.IOption;
|
||||
|
||||
public class IntOption implements IOption<Integer> {
|
||||
|
||||
private String id;
|
||||
private String displayName;
|
||||
private int defaultValue;
|
||||
private boolean isInternal = false;
|
||||
private boolean isGeneratorSpecific = false;
|
||||
|
||||
public IntOption(String id, String displayName, int defaultValue) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public IntOption(String id, String displayName, int defaultValue, boolean isInternal, boolean isGeneratorSpecific) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.defaultValue = defaultValue;
|
||||
this.isInternal = isInternal;
|
||||
this.isGeneratorSpecific = isGeneratorSpecific;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefault() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVisableName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Integer> getType() {
|
||||
return Integer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOptionType() {
|
||||
return isInternal ? Type.INTERNAL : Type.STRING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, String> getPossibleValues() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer decodeString(String input) {
|
||||
return Integer.parseInt(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer fromRepresentation(String repr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toRepresentation(Integer obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeneratorSpecific() {
|
||||
return isGeneratorSpecific;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ public class StringOption implements IOption<String> {
|
|||
private String id;
|
||||
private String displayName;
|
||||
private String defaultValue;
|
||||
private boolean isInternal = false;
|
||||
|
||||
public StringOption(String id, String displayName, String defaultValue) {
|
||||
this.id = id;
|
||||
|
@ -16,6 +17,11 @@ public class StringOption implements IOption<String> {
|
|||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public StringOption(String id, String displayName, String defaultValue, boolean isInternal) {
|
||||
this(id, displayName, defaultValue);
|
||||
this.isInternal = isInternal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefault() {
|
||||
return defaultValue;
|
||||
|
@ -58,7 +64,7 @@ public class StringOption implements IOption<String> {
|
|||
|
||||
@Override
|
||||
public Type getOptionType() {
|
||||
return Type.STRING;
|
||||
return isInternal ? Type.INTERNAL : Type.STRING;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package dev.tilera.cwg.dimensions;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonIOException;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import dev.tilera.cwg.api.options.IGeneratorOptionProvider;
|
||||
import dev.tilera.cwg.api.options.IGeneratorOptionRegistry;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class CustomDimensions {
|
||||
|
||||
public static CustomDimensions INSTANCE;
|
||||
private Gson gson = new GsonBuilder().create();
|
||||
private IGeneratorOptionRegistry registry;
|
||||
private Map<Integer, IGeneratorOptionProvider> dimensions = new HashMap<>();
|
||||
|
||||
public CustomDimensions(IGeneratorOptionRegistry registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public IGeneratorOptionProvider getDimensionOptions(int id) {
|
||||
return dimensions.get(id);
|
||||
}
|
||||
|
||||
public Integer[] getCustomDimensions() {
|
||||
return dimensions.keySet().toArray(new Integer[0]);
|
||||
}
|
||||
|
||||
public void registerDimensions() {
|
||||
for (int id : getCustomDimensions()) {
|
||||
IGeneratorOptionProvider options = getDimensionOptions(id);
|
||||
int providerId = options.getInt("cwg:dimensions:provider");
|
||||
DimensionManager.registerDimension(id, providerId);
|
||||
}
|
||||
}
|
||||
|
||||
public void readConfig(File file) {
|
||||
JsonObject[] dims = decodeConfig(file);
|
||||
for (JsonObject dim : dims) {
|
||||
Integer id = getDimID(dim);
|
||||
IGeneratorOptionProvider options = decodeOptions(dim);
|
||||
dimensions.put(id, options);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonObject[] decodeConfig(File file) {
|
||||
try {
|
||||
return gson.fromJson(new FileReader(file), JsonObject[].class);
|
||||
} catch (FileNotFoundException e) {
|
||||
return new JsonObject[0];
|
||||
} catch (JsonSyntaxException | JsonIOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int getDimID(JsonObject def) throws IllegalStateException {
|
||||
JsonElement id = def.get("id");
|
||||
if (id == null || !id.isJsonPrimitive()) throw new IllegalStateException("Dimension definition does not contain a valid dimension ID: " + def);
|
||||
return id.getAsInt();
|
||||
}
|
||||
|
||||
private IGeneratorOptionProvider decodeOptions(JsonObject def) throws IllegalStateException {
|
||||
JsonElement options = def.get("options");
|
||||
String encodedJson = null;
|
||||
if (options == null) {
|
||||
throw new IllegalStateException("Dimension definition does not contain valid options: " + def);
|
||||
} else if (options.isJsonObject()) {
|
||||
encodedJson = Base64.getEncoder().encodeToString(gson.toJson(options).getBytes());
|
||||
} else if (options.isJsonPrimitive() && options.getAsJsonPrimitive().isString()) {
|
||||
encodedJson = options.getAsJsonPrimitive().getAsString();
|
||||
} else {
|
||||
throw new IllegalStateException("Dimension definition does not contain valid options: " + def);
|
||||
}
|
||||
return registry.decodeOptions(encodedJson);
|
||||
}
|
||||
|
||||
}
|
36
src/main/java/dev/tilera/cwg/dimensions/DimProvider.java
Normal file
36
src/main/java/dev/tilera/cwg/dimensions/DimProvider.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
package dev.tilera.cwg.dimensions;
|
||||
|
||||
import dev.tilera.cwg.api.generator.AbstractChunkManager;
|
||||
import dev.tilera.cwg.api.generator.IChunkManagerFactory;
|
||||
import dev.tilera.cwg.api.options.IGeneratorOptionProvider;
|
||||
import net.minecraft.world.WorldProvider;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
|
||||
public class DimProvider extends WorldProvider {
|
||||
|
||||
@Override
|
||||
public String getDimensionName() {
|
||||
return getOptions().getString("cwg:dimensions:name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSaveFolder() {
|
||||
return "cwg/DIM" + dimensionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkProvider createChunkGenerator() {
|
||||
return ((AbstractChunkManager)this.worldChunkMgr).getGenerator(this.worldObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerWorldChunkManager() {
|
||||
IGeneratorOptionProvider options = CustomDimensions.INSTANCE.getDimensionOptions(dimensionId);
|
||||
this.worldChunkMgr = options.getValue("cwg:generator", IChunkManagerFactory.class).createChunkManager(options, worldObj);
|
||||
}
|
||||
|
||||
protected IGeneratorOptionProvider getOptions() {
|
||||
return ((AbstractChunkManager)this.worldChunkMgr).getOptionProvider();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package dev.tilera.cwg.vanilla;
|
||||
|
||||
import dev.tilera.cwg.DelegateChunkManager;
|
||||
import dev.tilera.cwg.api.generator.AbstractChunkManager;
|
||||
import dev.tilera.cwg.api.generator.IChunkManagerFactory;
|
||||
import dev.tilera.cwg.api.options.IGeneratorOptionProvider;
|
||||
import dev.tilera.cwg.api.options.IOption;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraft.world.biome.WorldChunkManagerHell;
|
||||
import net.minecraft.world.gen.ChunkProviderGenerate;
|
||||
|
||||
public class SingleBiomeChunkManagerFactory implements IChunkManagerFactory {
|
||||
|
||||
@Override
|
||||
public AbstractChunkManager createChunkManager(IGeneratorOptionProvider options, World world) {
|
||||
int biomeID = options.getInt("cwg:generator.singleBiome:biomeID");
|
||||
return new DelegateChunkManager(
|
||||
options,
|
||||
new ChunkProviderGenerate(world, world.getSeed(), world.getWorldInfo().isMapFeaturesEnabled()),
|
||||
new WorldChunkManagerHell(BiomeGenBase.getBiome(biomeID), 1.0f)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "cwg:singleBiome";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Single Biome";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSpecificOption(IOption<?> option) {
|
||||
return option.getID().startsWith("cwg:generator.singleBiome");
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue