diff --git a/.editorconfig b/.editorconfig
index 182e9199e..8fbad9dcd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -6,7 +6,7 @@ end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = false
-max_line_length = 120
+max_line_length = 140
tab_width = 4
ij_continuation_indent_size = 8
ij_formatter_off_tag = @formatter:off
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 6eeb63b56..0a108328a 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -6,6 +6,16 @@
+
+
+
+
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index f689e9701..27b35c5b4 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -81,5 +81,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 594038a0a..aa71de0f2 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -4,8 +4,9 @@
-
-
+
+
+
diff --git a/build.gradle.kts b/build.gradle.kts
index 973dd071c..0558df4a7 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -30,12 +30,12 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}
-val versionObj = Version("1", "5", "0", true)
+val versionObj = Version("2", "0", "0", true)
version = versionObj
dependencies {
- val gaeaVersion = "1.14.3"
+ val gaeaVersion = "1.15.0"
compileOnly(name = "Gaea-${gaeaVersion}", group = "")
testImplementation(name = "Gaea-${gaeaVersion}", group = "")
@@ -49,13 +49,15 @@ dependencies {
compileOnly("com.googlecode.json-simple:json-simple:1.1")
- implementation(name = "parsii-1.2.1", group = "")
+ implementation("com.scireum:parsii:1.2.1")
compileOnly("org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT")
implementation("io.papermc:paperlib:1.0.5")
implementation("net.jafama:jafama:2.3.2")
+ implementation(name = "Tectonic-1.0.2", group = "")
+
// JUnit.
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
@@ -107,6 +109,7 @@ tasks.named("shadowJar") {
relocate("parsii", "com.dfsek.terra.lib.parsii")
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
+ relocate("com.dfsek.tectonic", "com.dfsek.terra.lib.tectonic")
minimize()
}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index e708b1c02..000000000
Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/lib/Gaea-1.14.3.jar b/lib/Gaea-1.14.3.jar
deleted file mode 100644
index 42ac42aac..000000000
Binary files a/lib/Gaea-1.14.3.jar and /dev/null differ
diff --git a/lib/Gaea-1.15.0.jar b/lib/Gaea-1.15.0.jar
new file mode 100644
index 000000000..42d013ec6
Binary files /dev/null and b/lib/Gaea-1.15.0.jar differ
diff --git a/lib/Tectonic-1.0.2.jar b/lib/Tectonic-1.0.2.jar
new file mode 100644
index 000000000..f78f2ab6f
Binary files /dev/null and b/lib/Tectonic-1.0.2.jar differ
diff --git a/lib/parsii-1.2.1.jar b/lib/parsii-1.2.1.jar
deleted file mode 100644
index cb19dfd90..000000000
Binary files a/lib/parsii-1.2.1.jar and /dev/null differ
diff --git a/src/main/java/com/dfsek/terra/Debug.java b/src/main/java/com/dfsek/terra/Debug.java
index 606ecd53f..9e4843cfc 100644
--- a/src/main/java/com/dfsek/terra/Debug.java
+++ b/src/main/java/com/dfsek/terra/Debug.java
@@ -1,6 +1,6 @@
package com.dfsek.terra;
-import com.dfsek.terra.config.base.ConfigUtil;
+import com.dfsek.terra.config.base.PluginConfig;
import org.bukkit.plugin.java.JavaPlugin;
public class Debug {
@@ -11,18 +11,18 @@ public class Debug {
}
public static void info(String message) {
- if(ConfigUtil.debug) main.getLogger().info(message);
+ if(PluginConfig.isDebug()) main.getLogger().info(message);
}
public static void warn(String message) {
- if(ConfigUtil.debug) main.getLogger().warning(message);
+ if(PluginConfig.isDebug()) main.getLogger().warning(message);
}
public static void error(String message) {
- if(ConfigUtil.debug) main.getLogger().severe(message);
+ if(PluginConfig.isDebug()) main.getLogger().severe(message);
}
public static void stack(Exception e) {
- if(ConfigUtil.debug) e.printStackTrace();
+ if(PluginConfig.isDebug()) e.printStackTrace();
}
}
diff --git a/src/main/java/com/dfsek/terra/EventListener.java b/src/main/java/com/dfsek/terra/EventListener.java
index 15551566c..1d65c6825 100644
--- a/src/main/java/com/dfsek/terra/EventListener.java
+++ b/src/main/java/com/dfsek/terra/EventListener.java
@@ -2,8 +2,8 @@ package com.dfsek.terra;
import com.dfsek.terra.async.AsyncStructureFinder;
import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.genconfig.TreeConfig;
-import com.dfsek.terra.config.genconfig.structure.StructureConfig;
+import com.dfsek.terra.generation.items.TerraStructure;
+import com.dfsek.terra.generation.items.tree.TerraTree;
import com.dfsek.terra.registry.TreeRegistry;
import com.dfsek.terra.util.StructureTypeEnum;
import org.bukkit.Material;
@@ -39,7 +39,7 @@ public class EventListener implements Listener {
Debug.info("Detected Ender Signal...");
TerraWorld tw = TerraWorld.getWorld(e.getEntity().getWorld());
EnderSignal signal = (EnderSignal) entity;
- StructureConfig config = tw.getConfig().getLocatable().get(StructureTypeEnum.STRONGHOLD);
+ TerraStructure config = tw.getConfig().getStructureLocatable(StructureTypeEnum.STRONGHOLD);
if(config != null) {
Debug.info("Overriding Ender Signal...");
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getGrid(), config, e.getLocation(), 0, 500, location -> {
@@ -72,7 +72,7 @@ public class EventListener implements Listener {
if(!TerraWorld.isTerraWorld(e.getWorld())) return;
TerraWorld tw = TerraWorld.getWorld(e.getWorld());
ConfigPack c = tw.getConfig();
- if(c.preventSaplingOverride) return;
+ if(c.getTemplate().isDisableSaplings()) return;
e.setCancelled(true);
Block block = e.getLocation().getBlock();
BlockData data = block.getBlockData();
@@ -80,10 +80,10 @@ public class EventListener implements Listener {
TreeRegistry registry = c.getTreeRegistry();
Tree tree = registry.get(TreeType.fromBukkit(e.getSpecies()).toString());
Debug.info("Overriding tree type: " + e.getSpecies());
- if(tree instanceof TreeConfig) {
- if(!((TreeConfig) tree).plantBlockCheck(e.getLocation(), new FastRandom())) {
+ if(tree instanceof TerraTree) {
+ if(!((TerraTree) tree).plantBlockCheck(e.getLocation().subtract(0, 1, 0), new FastRandom())) {
block.setBlockData(data);
}
- } else if(!tree.plant(e.getLocation(), new FastRandom(), Terra.getInstance())) block.setBlockData(data);
+ } else if(!tree.plant(e.getLocation().subtract(0, 1, 0), new FastRandom(), Terra.getInstance())) block.setBlockData(data);
}
}
diff --git a/src/main/java/com/dfsek/terra/Terra.java b/src/main/java/com/dfsek/terra/Terra.java
index 7999adc6a..f385f18fe 100644
--- a/src/main/java/com/dfsek/terra/Terra.java
+++ b/src/main/java/com/dfsek/terra/Terra.java
@@ -2,10 +2,11 @@ package com.dfsek.terra;
import com.dfsek.terra.command.TerraCommand;
import com.dfsek.terra.command.structure.LocateCommand;
-import com.dfsek.terra.config.base.ConfigUtil;
+import com.dfsek.terra.config.base.PluginConfig;
import com.dfsek.terra.config.base.WorldConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.generation.TerraChunkGenerator;
+import com.dfsek.terra.registry.ConfigRegistry;
import com.dfsek.terra.util.PaperUtil;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
@@ -39,10 +40,17 @@ public class Terra extends GaeaPlugin {
@Override
public void onEnable() {
instance = this;
+
+ saveDefaultConfig();
+
Metrics metrics = new Metrics(this, 9017);
metrics.addCustomChart(new Metrics.SingleLineChart("worlds", TerraWorld::numWorlds));
+
Debug.setMain(this);
- ConfigUtil.loadConfig(this);
+ PluginConfig.load(this);
+ LangUtil.load(PluginConfig.getLanguage(), this); // Load language.
+ TerraWorld.invalidate();
+ ConfigRegistry.loadAll(this);
PluginCommand c = Objects.requireNonNull(getCommand("terra"));
TerraCommand command = new TerraCommand(this);
@@ -54,8 +62,9 @@ public class Terra extends GaeaPlugin {
locatePl.setExecutor(locate);
locatePl.setTabCompleter(locate);
- saveDefaultConfig();
- Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, TerraChunkGenerator::saveAll, ConfigUtil.dataSave, ConfigUtil.dataSave);
+
+ long save = PluginConfig.getDataSaveInterval();
+ Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, TerraChunkGenerator::saveAll, save, save);
Bukkit.getPluginManager().registerEvents(new EventListener(this), this);
PaperUtil.checkPaper(this);
}
@@ -71,7 +80,7 @@ public class Terra extends GaeaPlugin {
@Override
public boolean isDebug() {
- return ConfigUtil.debug;
+ return PluginConfig.isDebug();
}
@Override
diff --git a/src/main/java/com/dfsek/terra/TerraProfiler.java b/src/main/java/com/dfsek/terra/TerraProfiler.java
index 02cd702cb..1680465d9 100644
--- a/src/main/java/com/dfsek/terra/TerraProfiler.java
+++ b/src/main/java/com/dfsek/terra/TerraProfiler.java
@@ -20,8 +20,7 @@ public class TerraProfiler extends WorldProfiler {
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "CaveTime")
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime")
- .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "ElevationTime")
- .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "SnowTime");
+ .addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "ElevationTime");
}
public static TerraProfiler fromWorld(World w) {
diff --git a/src/main/java/com/dfsek/terra/TerraWorld.java b/src/main/java/com/dfsek/terra/TerraWorld.java
index ea25f2f8d..0d0297296 100644
--- a/src/main/java/com/dfsek/terra/TerraWorld.java
+++ b/src/main/java/com/dfsek/terra/TerraWorld.java
@@ -1,19 +1,18 @@
package com.dfsek.terra;
import com.dfsek.terra.biome.BiomeZone;
-import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
-import com.dfsek.terra.biome.grid.UserDefinedGrid;
import com.dfsek.terra.config.base.ConfigPack;
+import com.dfsek.terra.config.base.ConfigPackTemplate;
import com.dfsek.terra.config.base.WorldConfig;
-import com.dfsek.terra.config.genconfig.BiomeGridConfig;
+import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
import com.dfsek.terra.generation.TerraChunkGenerator;
import org.bukkit.Bukkit;
import org.bukkit.World;
+import org.polydev.gaea.biome.BiomeGrid;
import java.util.HashMap;
import java.util.Map;
-import java.util.Objects;
public class TerraWorld {
private static final Map map = new HashMap<>();
@@ -28,21 +27,18 @@ public class TerraWorld {
safe = true;
worldConfig = loaded.get(w.getName());
config = worldConfig.getConfig();
- UserDefinedGrid[] definedGrids = new UserDefinedGrid[config.biomeList.size()];
- for(int i = 0; i < config.biomeList.size(); i++) {
- String partName = config.biomeList.get(i);
+
+ ConfigPackTemplate template = config.getTemplate();
+
+ int zoneSize = template.getGrids().size();
+
+ BiomeGrid[] definedGrids = new BiomeGrid[zoneSize];
+ for(int i = 0; i < zoneSize; i++) {
+ String partName = template.getGrids().get(i);
try {
- if(partName.startsWith("BIOME:")) {
- UserDefinedBiome[][] temp = new UserDefinedBiome[1][1];
- UserDefinedBiome b = config.getBiomes().get(partName.substring(6)).getBiome();
- temp[0][0] = b;
- definedGrids[i] = new UserDefinedGrid(w, config.freq1, config.freq2, temp, worldConfig);
- Debug.info("Loaded single-biome grid " + partName);
- } else {
- BiomeGridConfig g = config.getBiomeGrid(partName);
- Debug.info("Loaded BiomeGrid " + g.getID());
- definedGrids[i] = g.getGrid(w, worldConfig);
- }
+ BiomeGridBuilder g = config.getBiomeGrid(partName);
+ BiomeGrid b = g.build(w, worldConfig);
+ definedGrids[i] = b;
} catch(NullPointerException e) {
safe = false;
Debug.stack(e);
@@ -52,31 +48,8 @@ public class TerraWorld {
Bukkit.getLogger().severe("Terrain will NOT generate properly at this point. Correct your config before using your server!");
}
}
- UserDefinedGrid erosion = null;
- if(config.erosionEnable) {
- try {
- if(config.erosionName.startsWith("BIOME:")) {
- UserDefinedBiome[][] temp = new UserDefinedBiome[1][1];
- UserDefinedBiome b = Objects.requireNonNull(config.getBiome(config.erosionName.substring(6)).getBiome());
- temp[0][0] = b;
- erosion = new UserDefinedGrid(w, config.freq1, config.freq2, temp, worldConfig);
- Debug.info("Loaded single-biome erosion grid " + config.erosionName);
- } else {
- BiomeGridConfig g = Objects.requireNonNull(config.getBiomeGrid(config.erosionName));
- Debug.info("Loaded BiomeGrid " + g.getID());
- erosion = g.getGrid(w, worldConfig);
- }
- } catch(NullPointerException e) {
- safe = false;
- Debug.stack(e);
- Bukkit.getLogger().severe("No such BiomeGrid (erosion): " + config.erosionName);
- Bukkit.getLogger().severe("Please check configuration files for errors. Configuration errors will have been reported during initialization.");
- Bukkit.getLogger().severe("ONLY report this to Terra if you are SURE your config is error-free.");
- Bukkit.getLogger().severe("Terrain will NOT generate properly at this point. Correct your config before using your server!");
- }
- }
zone = new BiomeZone(w, worldConfig, definedGrids);
- grid = new TerraBiomeGrid(w, config.freq1, config.freq2, zone, config, erosion);
+ grid = new TerraBiomeGrid(w, template.getGridFreqX(), template.getGridFreqZ(), zone, config);
}
public static void loadWorld(WorldConfig w) {
diff --git a/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java b/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java
index df05abaee..275f2cb6a 100644
--- a/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java
+++ b/src/main/java/com/dfsek/terra/async/AsyncBiomeFinder.java
@@ -1,7 +1,7 @@
package com.dfsek.terra.async;
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
-import com.dfsek.terra.config.base.ConfigUtil;
+import com.dfsek.terra.config.base.PluginConfig;
import org.bukkit.Location;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
@@ -28,11 +28,12 @@ public class AsyncBiomeFinder extends AsyncFeatureFinder {
*/
@Override
public boolean isValid(int x, int z, Biome target) {
- return getGrid().getBiome(x * ConfigUtil.biomeSearchRes, z * ConfigUtil.biomeSearchRes, GenerationPhase.POST_GEN).equals(target);
+ int res = PluginConfig.getBiomeSearchResolution();
+ return getGrid().getBiome(x * res, z * res, GenerationPhase.POST_GEN).equals(target);
}
@Override
public Vector finalizeVector(Vector orig) {
- return orig.multiply(ConfigUtil.biomeSearchRes);
+ return orig.multiply(PluginConfig.getBiomeSearchResolution());
}
}
diff --git a/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java b/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java
index 8a22f1158..59058cce0 100644
--- a/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java
+++ b/src/main/java/com/dfsek/terra/async/AsyncStructureFinder.java
@@ -2,7 +2,7 @@ package com.dfsek.terra.async;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
-import com.dfsek.terra.config.genconfig.structure.StructureConfig;
+import com.dfsek.terra.generation.items.TerraStructure;
import com.dfsek.terra.structure.Rotation;
import com.dfsek.terra.structure.Structure;
import org.bukkit.Location;
@@ -17,8 +17,8 @@ import java.util.function.Consumer;
/**
* Runnable to locate structures asynchronously
*/
-public class AsyncStructureFinder extends AsyncFeatureFinder {
- public AsyncStructureFinder(TerraBiomeGrid grid, StructureConfig target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback) {
+public class AsyncStructureFinder extends AsyncFeatureFinder {
+ public AsyncStructureFinder(TerraBiomeGrid grid, TerraStructure target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback) {
super(grid, target, origin, startRadius, maxRadius, callback);
setSearchSize(target.getSpawn().getWidth() + 2 * target.getSpawn().getSeparation());
}
@@ -30,15 +30,15 @@ public class AsyncStructureFinder extends AsyncFeatureFinder {
* @param z Z coordinate
* @return Whether location is a valid spawn for StructureConfig
*/
- public boolean isValid(int x, int z, StructureConfig target) {
+ public boolean isValid(int x, int z, TerraStructure target) {
World world = getWorld();
Location spawn = target.getSpawn().getChunkSpawn(x, z, world.getSeed()).toLocation(world);
if(!((UserDefinedBiome) getGrid().getBiome(spawn)).getConfig().getStructures().contains(target))
return false;
Random r2 = new FastRandom(spawn.hashCode());
- Structure struc = target.getStructure(r2);
+ Structure struc = target.getStructures().get(r2);
Rotation rotation = Rotation.fromDegrees(r2.nextInt(4) * 90);
- for(int y = target.getSearchStart().get(r2); y > 0; y--) {
+ for(int y = target.getSpawnStart().get(r2); y > 0; y--) {
if(!target.getBound().isInRange(y)) return false;
spawn.setY(y);
if(!struc.checkSpawns(spawn, rotation)) continue;
diff --git a/src/main/java/com/dfsek/terra/biome/BiomeZone.java b/src/main/java/com/dfsek/terra/biome/BiomeZone.java
index fd216bf54..2631789da 100644
--- a/src/main/java/com/dfsek/terra/biome/BiomeZone.java
+++ b/src/main/java/com/dfsek/terra/biome/BiomeZone.java
@@ -26,7 +26,7 @@ public class BiomeZone {
this.noise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
this.noise.setFractalType(FastNoiseLite.FractalType.FBm);
this.noise.setFractalOctaves(4);
- this.noise.setFrequency(wc.getConfig().zoneFreq);
+ this.noise.setFrequency(1D / wc.getConfig().getTemplate().getZoneFreq());
this.grids = grids;
imageLoader = wc.imageLoader;
useImage = wc.fromImage;
diff --git a/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java b/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java
index 687a2a1d9..295772b59 100644
--- a/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java
+++ b/src/main/java/com/dfsek/terra/biome/UserDefinedBiome.java
@@ -1,7 +1,8 @@
package com.dfsek.terra.biome;
-import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
-import com.dfsek.terra.config.genconfig.biome.GeneratorOptions;
+import com.dfsek.terra.config.base.ConfigPack;
+import com.dfsek.terra.config.builder.GeneratorBuilder;
+import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.generation.UserDefinedDecorator;
import org.bukkit.World;
import org.polydev.gaea.biome.Biome;
@@ -15,21 +16,22 @@ import java.util.List;
* Class representing a config-defined biome
*/
public class UserDefinedBiome implements Biome {
- private final GeneratorOptions gen;
+ private final GeneratorBuilder gen;
private final UserDefinedDecorator decorator;
private final org.bukkit.block.Biome vanilla;
private final String id;
- private final BiomeConfig config;
- private final boolean erode;
+ private final BiomeTemplate config;
+ private final ConfigPack pack;
+ private UserDefinedBiome erode;
- public UserDefinedBiome(org.bukkit.block.Biome vanilla, UserDefinedDecorator dec, GeneratorOptions gen, boolean erode, BiomeConfig config) {
+ public UserDefinedBiome(org.bukkit.block.Biome vanilla, UserDefinedDecorator dec, GeneratorBuilder gen, BiomeTemplate config, ConfigPack pack) {
this.vanilla = vanilla;
this.decorator = dec;
this.gen = gen;
this.id = config.getID();
- this.erode = erode;
this.config = config;
+ this.pack = pack;
}
/**
@@ -49,7 +51,7 @@ public class UserDefinedBiome implements Biome {
*/
@Override
public Generator getGenerator() {
- return gen.getGenerator(0);
+ return gen.build(0);
}
/**
@@ -76,16 +78,20 @@ public class UserDefinedBiome implements Biome {
return id;
}
- public boolean isErodible() {
+ public UserDefinedBiome getErode() {
+ if(erode == null) {
+ erode = (config.getErode() == null) ? this : pack.getBiome(config.getErode());
+ }
return erode;
}
- public BiomeConfig getConfig() {
+
+ public BiomeTemplate getConfig() {
return config;
}
@Override
public Generator getGenerator(World w) {
- return gen.getGenerator(w.getSeed());
+ return gen.build(w.getSeed());
}
}
diff --git a/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java b/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java
new file mode 100644
index 000000000..43219dbec
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/biome/grid/SingleBiomeGrid.java
@@ -0,0 +1,29 @@
+package com.dfsek.terra.biome.grid;
+
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.polydev.gaea.biome.Biome;
+import org.polydev.gaea.biome.BiomeGrid;
+import org.polydev.gaea.generation.GenerationPhase;
+
+/**
+ * BiomeGrid implementation that holds a single biome.
+ */
+public class SingleBiomeGrid extends BiomeGrid {
+ private final Biome biome;
+
+ public SingleBiomeGrid(World w, Biome biome) {
+ super(w, 0, 0, 1, 1);
+ this.biome = biome;
+ }
+
+ @Override
+ public Biome getBiome(int x, int z, GenerationPhase phase) {
+ return biome;
+ }
+
+ @Override
+ public Biome getBiome(Location l) {
+ return biome;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/biome/grid/TerraBiomeGrid.java b/src/main/java/com/dfsek/terra/biome/grid/TerraBiomeGrid.java
index d57aedb4e..4812a0c03 100644
--- a/src/main/java/com/dfsek/terra/biome/grid/TerraBiomeGrid.java
+++ b/src/main/java/com/dfsek/terra/biome/grid/TerraBiomeGrid.java
@@ -5,7 +5,8 @@ import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.postprocessing.CoordinatePerturb;
import com.dfsek.terra.biome.postprocessing.ErosionNoise;
import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.base.ConfigUtil;
+import com.dfsek.terra.config.base.ConfigPackTemplate;
+import com.dfsek.terra.config.base.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.procgen.math.Vector2;
import org.bukkit.Location;
@@ -21,17 +22,16 @@ public class TerraBiomeGrid extends BiomeGrid {
private final BiomeZone zone;
private CoordinatePerturb perturb;
private ErosionNoise erode;
- private UserDefinedGrid erosionGrid;
- public TerraBiomeGrid(World w, double freq1, double freq2, BiomeZone zone, ConfigPack c, UserDefinedGrid erosion) {
+ public TerraBiomeGrid(World w, double freq1, double freq2, BiomeZone zone, ConfigPack c) {
super(w, freq1, freq2, 0, 0);
- if(c.biomeBlend) {
- perturb = new CoordinatePerturb(c.blendFreq, c.blendAmp, w.getSeed());
+ ConfigPackTemplate t = c.getTemplate();
+ if(c.getTemplate().isBlend()) {
+ perturb = new CoordinatePerturb(t.getBlendFreq(), t.getBlendAmp(), w.getSeed());
}
this.zone = zone;
- if(c.erosionEnable) {
- erode = new ErosionNoise(c.erosionFreq, c.erosionThresh, c.erosionOctaves, w.getSeed());
- this.erosionGrid = erosion;
+ if(c.getTemplate().isErode()) {
+ erode = new ErosionNoise(t.getErodeFreq(), t.getErodeThresh(), t.getErodeOctaves(), w.getSeed());
}
}
@@ -43,7 +43,7 @@ public class TerraBiomeGrid extends BiomeGrid {
public Biome getBiome(int x, int z, GenerationPhase phase) {
int xp = x;
int zp = z;
- if(perturb != null && phase.equals(GenerationPhase.PALETTE_APPLY)) {
+ if(perturb != null && (phase.equals(GenerationPhase.PALETTE_APPLY) || phase.equals(GenerationPhase.POPULATE))) {
Vector2 perturbCoords = perturb.getShiftedCoords(x, z);
xp = (int) perturbCoords.getX();
zp = (int) perturbCoords.getZ();
@@ -53,15 +53,13 @@ public class TerraBiomeGrid extends BiomeGrid {
try {
b = (UserDefinedBiome) zone.getGrid(xp, zp).getBiome(xp, zp, phase);
} catch(NullPointerException e) {
- if(ConfigUtil.debug) e.printStackTrace();
+ if(PluginConfig.isDebug()) e.printStackTrace();
if(failNum % 256 == 0)
LangUtil.log("error.severe-config", Level.SEVERE, String.valueOf(x), String.valueOf(z));
failNum++;
return null;
}
- if(erode != null && b.isErodible() && erode.isEroded(xp, zp)) {
- return erosionGrid.getBiome(xp, zp, phase);
- }
+ if(erode != null && erode.isEroded(xp, zp)) return b.getErode();
return b;
}
diff --git a/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java b/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java
index 4a7d547cf..98b8f6c64 100644
--- a/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java
+++ b/src/main/java/com/dfsek/terra/biome/grid/UserDefinedGrid.java
@@ -1,6 +1,5 @@
package com.dfsek.terra.biome.grid;
-import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.base.WorldConfig;
import com.dfsek.terra.image.ImageLoader;
import org.bukkit.Location;
@@ -16,7 +15,7 @@ public class UserDefinedGrid extends BiomeGrid {
private final ImageLoader.Channel channelX;
private final ImageLoader.Channel channelZ;
- public UserDefinedGrid(World w, double freq1, double freq2, UserDefinedBiome[][] b, WorldConfig c) {
+ public UserDefinedGrid(World w, double freq1, double freq2, Biome[][] b, WorldConfig c) {
super(w, freq1, freq2, b.length, b[0].length);
super.setGrid(b);
imageLoader = c.imageLoader;
diff --git a/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java b/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java
new file mode 100644
index 000000000..3dd6cf88d
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/biome/palette/PaletteHolder.java
@@ -0,0 +1,16 @@
+package com.dfsek.terra.biome.palette;
+
+import org.bukkit.block.data.BlockData;
+import org.polydev.gaea.world.palette.Palette;
+
+public class PaletteHolder {
+ private final Palette[] palettes;
+
+ protected PaletteHolder(Palette[] palettes) {
+ this.palettes = palettes;
+ }
+
+ public Palette getPalette(int y) {
+ return palettes[y];
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java b/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java
new file mode 100644
index 000000000..39ce7ba8d
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/biome/palette/PaletteHolderBuilder.java
@@ -0,0 +1,34 @@
+package com.dfsek.terra.biome.palette;
+
+import com.dfsek.terra.util.DataUtil;
+import net.jafama.FastMath;
+import org.bukkit.block.data.BlockData;
+import org.polydev.gaea.world.palette.Palette;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+public class PaletteHolderBuilder {
+ private final TreeMap> paletteMap = new TreeMap<>();
+
+ public PaletteHolderBuilder add(int y, Palette palette) {
+ paletteMap.put(y, palette);
+ return this;
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
+ public PaletteHolder build() {
+ Palette[] palettes = new Palette[paletteMap.lastKey() + 1];
+ for(int y = 0; y <= FastMath.max(paletteMap.lastKey(), 255); y++) {
+ Palette d = DataUtil.BLANK_PALETTE;
+ for(Map.Entry> e : paletteMap.entrySet()) {
+ if(e.getKey() >= y) {
+ d = e.getValue();
+ break;
+ }
+ }
+ palettes[y] = d;
+ }
+ return new PaletteHolder(palettes);
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java b/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java
new file mode 100644
index 000000000..21a57e049
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/biome/palette/PaletteLayer.java
@@ -0,0 +1,24 @@
+package com.dfsek.terra.biome.palette;
+
+import org.bukkit.block.data.BlockData;
+import org.jetbrains.annotations.NotNull;
+import org.polydev.gaea.math.ProbabilityCollection;
+
+public class PaletteLayer {
+ private final ProbabilityCollection layer;
+ private final int size;
+
+ public PaletteLayer(@NotNull ProbabilityCollection layer, int size) {
+ this.layer = layer;
+ this.size = size;
+ }
+
+ @NotNull
+ public ProbabilityCollection getLayer() {
+ return layer;
+ }
+
+ public int getSize() {
+ return size;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java b/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java
new file mode 100644
index 000000000..cb6ad3ca3
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/biome/palette/SinglePalette.java
@@ -0,0 +1,16 @@
+package com.dfsek.terra.biome.palette;
+
+import org.polydev.gaea.world.palette.Palette;
+
+public class SinglePalette extends Palette {
+ private final E item;
+
+ public SinglePalette(E item) {
+ this.item = item;
+ }
+
+ @Override
+ public E get(int i, int i1, int i2) {
+ return item;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java b/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java
index 00b57b122..334caefea 100644
--- a/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java
+++ b/src/main/java/com/dfsek/terra/biome/postprocessing/CoordinatePerturb.java
@@ -9,7 +9,7 @@ import org.polydev.gaea.math.FastNoiseLite;
public class CoordinatePerturb {
private final FastNoiseLite perturbX;
private final FastNoiseLite perturbZ;
- private final int amplitude;
+ private final double amplitude;
/**
* Create a CoordinatePerturb object with a given frequency, amplitude, and seed.
@@ -18,7 +18,7 @@ public class CoordinatePerturb {
* @param amplitude Offset amplitude
* @param seed Noise seed
*/
- public CoordinatePerturb(double frequency, int amplitude, long seed) {
+ public CoordinatePerturb(double frequency, double amplitude, long seed) {
perturbX = new FastNoiseLite((int) seed);
perturbX.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
perturbX.setFrequency(frequency);
diff --git a/src/main/java/com/dfsek/terra/carving/CarverPalette.java b/src/main/java/com/dfsek/terra/carving/CarverPalette.java
new file mode 100644
index 000000000..bc6001104
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/carving/CarverPalette.java
@@ -0,0 +1,53 @@
+package com.dfsek.terra.carving;
+
+import com.dfsek.terra.util.MaterialSet;
+import org.bukkit.Material;
+import org.bukkit.block.data.BlockData;
+import org.polydev.gaea.math.ProbabilityCollection;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
+public class CarverPalette {
+ private final boolean blacklist;
+ private final MaterialSet replace;
+ private final TreeMap> map = new TreeMap<>();
+ private ProbabilityCollection[] layers;
+
+ public CarverPalette(MaterialSet replaceable, boolean blacklist) {
+ this.blacklist = blacklist;
+ this.replace = replaceable;
+ }
+
+ public CarverPalette add(ProbabilityCollection collection, int y) {
+ map.put(y, collection);
+ return this;
+ }
+
+ public ProbabilityCollection get(int y) {
+ return layers[y];
+ }
+
+ public boolean canReplace(Material material) {
+ return blacklist != replace.contains(material);
+ }
+
+ /**
+ * Build the palette to an array.
+ */
+ public void build() {
+ int size = map.lastKey() + 1;
+ layers = new ProbabilityCollection[size];
+ for(int y = 0; y < size; y++) {
+ ProbabilityCollection d = new ProbabilityCollection().add(Material.AIR.createBlockData(), 1); // Blank layer
+ for(Map.Entry> e : map.entrySet()) {
+ if(e.getKey() >= y) {
+ d = e.getValue();
+ break;
+ }
+ }
+ layers[y] = d;
+ }
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/carving/SimplexCarver.java b/src/main/java/com/dfsek/terra/carving/SimplexCarver.java
deleted file mode 100644
index 8641dd229..000000000
--- a/src/main/java/com/dfsek/terra/carving/SimplexCarver.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.dfsek.terra.carving;
-
-import net.jafama.FastMath;
-import org.bukkit.World;
-import org.bukkit.util.Vector;
-import org.polydev.gaea.math.FastNoiseLite;
-import org.polydev.gaea.world.carving.Carver;
-import org.polydev.gaea.world.carving.CarvingData;
-import org.polydev.gaea.world.carving.Worm;
-
-import java.util.Random;
-
-@SuppressWarnings("unused")
-public class SimplexCarver extends Carver {
- private final FastNoiseLite noise;
- private final FastNoiseLite height;
- private final FastNoiseLite column;
- private final FastNoiseLite hasCaves;
- private final double root2inverse = 1D / FastMath.sqrt(2);
-
- public SimplexCarver(int minY, int maxY) {
- super(minY, maxY);
- noise = new FastNoiseLite(2403);
- noise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- noise.setFractalType(FastNoiseLite.FractalType.FBm);
- noise.setFractalOctaves(3);
- noise.setFrequency(0.02f);
-
- height = new FastNoiseLite(2404);
- height.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- height.setFrequency(0.01f);
-
- column = new FastNoiseLite(2404);
- column.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- column.setFractalType(FastNoiseLite.FractalType.FBm);
- column.setFractalOctaves(5);
- column.setFrequency(0.05f);
-
- hasCaves = new FastNoiseLite(2405);
- hasCaves.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- hasCaves.setFrequency(0.005f);
- }
-
- private static double acot(double x) {
- return FastMath.PI / 2 - FastMath.atan(x);
- }
-
- @Override
- public CarvingData carve(int chunkX, int chunkZ, World w) {
- CarvingData c = new CarvingData(chunkX, chunkZ);
- int ox = chunkX << 4;
- int oz = chunkZ << 4;
- for(int x = ox; x < ox + 16; x++) {
- for(int z = oz; z < oz + 16; z++) {
- double heightNoise = height.getNoise(x, z);
- double mainNoise = noise.getNoise(x, z) * 2;
- double columnNoise = FastMath.pow(FastMath.max(column.getNoise(x, z), 0) * 2, 3);
- double hc = (acot(16 * (hasCaves.getNoise(x, z) - 0.2)) / FastMath.PI) - 0.1;
- CarvingData.CarvingType type = CarvingData.CarvingType.BOTTOM;
- double simplex = (FastMath.pow(mainNoise + root2inverse, 3) / 2 + columnNoise) * hc;
- for(int y = 0; y < 64; y++) {
- double finalNoise = (-0.05 * FastMath.abs(y - (heightNoise * 16 + 24)) + 1 - simplex) * hc;
- if(finalNoise > 0.5) {
- c.carve(x - ox, y, z - oz, type);
- double finalNoiseUp = (-0.05 * FastMath.abs((y + 1) - (heightNoise * 16 + 24)) + 1 - simplex) * hc;
- if(finalNoiseUp > 0.5) {
- type = CarvingData.CarvingType.CENTER;
- } else type = CarvingData.CarvingType.TOP;
- }
- }
- }
- }
- return c;
- }
-
- @Override
- public Worm getWorm(long l, Vector vector) {
- return null;
- }
-
- @Override
- public boolean isChunkCarved(World world, int i, int i1, Random random) {
- return true;
- }
-}
diff --git a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java
index 3ea0e040f..1e881072a 100644
--- a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java
+++ b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java
@@ -2,47 +2,83 @@ package com.dfsek.terra.carving;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.UserDefinedBiome;
-import com.dfsek.terra.config.base.ConfigPack;
+import com.dfsek.terra.biome.grid.TerraBiomeGrid;
+import com.dfsek.terra.config.templates.BiomeTemplate;
+import com.dfsek.terra.config.templates.CarverTemplate;
+import com.dfsek.terra.math.RandomFunction;
import net.jafama.FastMath;
import org.bukkit.World;
import org.bukkit.util.Vector;
+import org.polydev.gaea.biome.Biome;
import org.polydev.gaea.generation.GenerationPhase;
+import org.polydev.gaea.math.MathUtil;
import org.polydev.gaea.math.Range;
import org.polydev.gaea.util.FastRandom;
+import org.polydev.gaea.util.GlueList;
import org.polydev.gaea.world.carving.Carver;
import org.polydev.gaea.world.carving.Worm;
+import parsii.eval.Expression;
+import parsii.eval.Parser;
+import parsii.eval.Scope;
+import parsii.eval.Variable;
+import parsii.tokenizer.ParseException;
+import java.util.List;
import java.util.Random;
+import java.util.function.BiConsumer;
public class UserDefinedCarver extends Carver {
private final double[] start; // 0, 1, 2 = x, y, z.
private final double[] mutate; // 0, 1, 2 = x, y, z. 3 = radius.
- private final double[] radiusMultiplier;
private final Range length;
- private final Range radius;
private final int hash;
private final int topCut;
private final int bottomCut;
private double step = 2;
private Range recalc = new Range(8, 10);
private double recalcMagnitude = 3;
+ private final CarverTemplate config;
+ private final Expression xRad;
+ private final Expression yRad;
+ private final Expression zRad;
+ private final Variable lengthVar;
+ private final Variable position;
+ private final Variable seedVar;
+ private final Range height;
+ private final double sixtyFourSq = FastMath.pow(64, 2);
- public UserDefinedCarver(Range height, Range radius, Range length, double[] start, double[] mutate, double[] radiusMultiplier, int hash, int topCut, int bottomCut) {
+ public UserDefinedCarver(Range height, Range length, double[] start, double[] mutate, List radii, Scope parent, int hash, int topCut, int bottomCut, CarverTemplate config) throws ParseException {
super(height.getMin(), height.getMax());
- this.radius = radius;
this.length = length;
+ this.height = height;
this.start = start;
this.mutate = mutate;
- this.radiusMultiplier = radiusMultiplier;
this.hash = hash;
this.topCut = topCut;
this.bottomCut = bottomCut;
+ this.config = config;
+
+ Parser p = new Parser();
+
+ p.registerFunction("rand", new RandomFunction());
+
+ Scope s = new Scope().withParent(parent);
+
+ lengthVar = s.create("length");
+ position = s.create("position");
+ seedVar = s.create("seed");
+
+
+ xRad = p.parse(radii.get(0), s);
+ yRad = p.parse(radii.get(1), s);
+ zRad = p.parse(radii.get(2), s);
+
}
@Override
public Worm getWorm(long l, Vector vector) {
Random r = new FastRandom(l + hash);
- return new UserDefinedWorm(length.get(r) / 2, r, vector, radius.getMax(), topCut, bottomCut);
+ return new UserDefinedWorm(length.get(r) / 2, r, vector, topCut, bottomCut);
}
public void setStep(double step) {
@@ -53,35 +89,77 @@ public class UserDefinedCarver extends Carver {
this.recalc = recalc;
}
+ @Override
+ public void carve(int chunkX, int chunkZ, World w, BiConsumer consumer) {
+ int carvingRadius = getCarvingRadius();
+ TerraBiomeGrid grid = TerraWorld.getWorld(w).getGrid();
+ for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) {
+ z:
+ for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) {
+ if(isChunkCarved(w, x, z, new FastRandom(MathUtil.hashToLong(this.getClass().getName() + "_" + x + "&" + z)))) {
+ long seed = MathUtil.getCarverChunkSeed(x, z, w.getSeed());
+ seedVar.setValue(seed);
+ Random r = new FastRandom(seed);
+ Worm carving = getWorm(seed, new Vector((x << 4) + r.nextInt(16), height.get(r), (z << 4) + r.nextInt(16)));
+ Vector origin = carving.getOrigin();
+ List points = new GlueList<>();
+ for(int i = 0; i < carving.getLength(); i++) {
+ carving.step();
+ Biome biome = grid.getBiome(carving.getRunning().toLocation(w), GenerationPhase.POPULATE);
+ if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(this)) { // Stop if we enter a biome this carver is not present in
+ continue z;
+ }
+ if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) { // Only carve in the current chunk.
+ continue;
+ }
+ points.add(carving.getPoint());
+ }
+ points.forEach(point -> point.carve(chunkX, chunkZ, consumer));
+ }
+ }
+ }
+ }
+
public void setRecalcMagnitude(double recalcMagnitude) {
this.recalcMagnitude = recalcMagnitude;
}
@Override
public boolean isChunkCarved(World w, int chunkX, int chunkZ, Random random) {
- ConfigPack c = TerraWorld.getWorld(w).getConfig();
- return new FastRandom(random.nextLong() + hash).nextInt(100) < ((UserDefinedBiome) TerraWorld.getWorld(w).getGrid().getBiome(chunkX << 4, chunkZ << 4, GenerationPhase.POPULATE)).getConfig().getCarverChance(this);
+ BiomeTemplate conf = ((UserDefinedBiome) TerraWorld.getWorld(w).getGrid().getBiome(chunkX << 4, chunkZ << 4, GenerationPhase.POPULATE)).getConfig();
+ if(conf.getCarvers().get(this) != null) {
+ return new FastRandom(random.nextLong() + hash).nextInt(100) < conf.getCarvers().get(this);
+ }
+ return false;
+ }
+
+ public CarverTemplate getConfig() {
+ return config;
}
private class UserDefinedWorm extends Worm {
private final Vector direction;
- private final int maxRad;
- private double runningRadius;
private int steps;
private int nextDirection = 0;
private double[] currentRotation = new double[3];
- public UserDefinedWorm(int length, Random r, Vector origin, int maxRad, int topCut, int bottomCut) {
+ public UserDefinedWorm(int length, Random r, Vector origin, int topCut, int bottomCut) {
super(length, r, origin);
super.setTopCut(topCut);
super.setBottomCut(bottomCut);
- runningRadius = radius.get(r);
- this.maxRad = maxRad;
direction = new Vector((r.nextDouble() - 0.5D) * start[0], (r.nextDouble() - 0.5D) * start[1], (r.nextDouble() - 0.5D) * start[2]).normalize().multiply(step);
+ position.setValue(0);
+ lengthVar.setValue(length);
+ setRadius(new int[] {(int) (xRad.evaluate()), (int) (yRad.evaluate()), (int) (zRad.evaluate())});
}
@Override
- public void step() {
+ public WormPoint getPoint() {
+ return new WormPoint(getRunning().clone(), getRadius(), config.getCutTop(), config.getCutBottom());
+ }
+
+ @Override
+ public synchronized void step() {
if(steps == nextDirection) {
direction.rotateAroundX(FastMath.toRadians((getRandom().nextGaussian()) * mutate[0] * recalcMagnitude));
direction.rotateAroundY(FastMath.toRadians((getRandom().nextGaussian()) * mutate[1] * recalcMagnitude));
@@ -92,9 +170,8 @@ public class UserDefinedCarver extends Carver {
nextDirection += recalc.get(getRandom());
}
steps++;
- setRadius(new int[] {(int) (runningRadius * radiusMultiplier[0]), (int) (runningRadius * radiusMultiplier[1]), (int) (runningRadius * radiusMultiplier[2])});
- runningRadius += (getRandom().nextDouble() - 0.5) * mutate[3];
- runningRadius = FastMath.max(FastMath.min(runningRadius, maxRad), 1);
+ position.setValue(steps);
+ setRadius(new int[] {(int) (xRad.evaluate()), (int) (yRad.evaluate()), (int) (zRad.evaluate())});
direction.rotateAroundX(FastMath.toRadians(currentRotation[0] * mutate[0]));
direction.rotateAroundY(FastMath.toRadians(currentRotation[1] * mutate[1]));
direction.rotateAroundZ(FastMath.toRadians(currentRotation[2] * mutate[2]));
diff --git a/src/main/java/com/dfsek/terra/command/OreCommand.java b/src/main/java/com/dfsek/terra/command/OreCommand.java
index c5a13a29d..337f8848f 100644
--- a/src/main/java/com/dfsek/terra/command/OreCommand.java
+++ b/src/main/java/com/dfsek/terra/command/OreCommand.java
@@ -1,18 +1,11 @@
package com.dfsek.terra.command;
-import com.dfsek.terra.TerraWorld;
-import com.dfsek.terra.config.genconfig.OreConfig;
-import com.dfsek.terra.config.lang.LangUtil;
-import net.jafama.FastMath;
import org.bukkit.World;
-import org.bukkit.block.Block;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.command.WorldCommand;
-import org.polydev.gaea.util.FastRandom;
import java.util.Collections;
import java.util.List;
@@ -24,6 +17,7 @@ public class OreCommand extends WorldCommand {
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) {
+ /*
Block bl = sender.getTargetBlockExact(25);
if(args.length > 0) {
OreConfig ore = TerraWorld.getWorld(w).getConfig().getOre(args[0]);
@@ -40,7 +34,11 @@ public class OreCommand extends WorldCommand {
} else {
LangUtil.send("command.ore.main-menu", sender);
}
+ */
return true;
+
+
+ // TODO: implementation
}
@Override
diff --git a/src/main/java/com/dfsek/terra/command/PacksCommand.java b/src/main/java/com/dfsek/terra/command/PacksCommand.java
new file mode 100644
index 000000000..844201f64
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/command/PacksCommand.java
@@ -0,0 +1,56 @@
+package com.dfsek.terra.command;
+
+import com.dfsek.terra.config.base.ConfigPackTemplate;
+import com.dfsek.terra.config.lang.LangUtil;
+import com.dfsek.terra.registry.ConfigRegistry;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.polydev.gaea.command.Command;
+
+import java.util.Collections;
+import java.util.List;
+
+public class PacksCommand extends Command {
+ public PacksCommand(Command parent) {
+ super(parent);
+ }
+
+ @Override
+ public String getName() {
+ return "packs";
+ }
+
+ @Override
+ public List getSubCommands() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandSender commandSender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) {
+
+ ConfigRegistry registry = ConfigRegistry.getRegistry();
+
+ if(registry.entries().size() == 0) {
+ LangUtil.send("command.packs.none", commandSender);
+ return true;
+ }
+
+ LangUtil.send("command.packs.main", commandSender);
+ registry.entries().forEach(entry -> {
+ ConfigPackTemplate template = entry.getTemplate();
+ LangUtil.send("command.packs.pack", commandSender, template.getID(), template.getAuthor());
+ });
+
+ return true;
+ }
+
+ @Override
+ public int arguments() {
+ return 0;
+ }
+
+ @Override
+ public List getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) {
+ return Collections.emptyList();
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/command/ReloadCommand.java b/src/main/java/com/dfsek/terra/command/ReloadCommand.java
index ab874d5da..42ebba93f 100644
--- a/src/main/java/com/dfsek/terra/command/ReloadCommand.java
+++ b/src/main/java/com/dfsek/terra/command/ReloadCommand.java
@@ -1,8 +1,9 @@
package com.dfsek.terra.command;
-import com.dfsek.terra.Terra;
-import com.dfsek.terra.config.base.ConfigUtil;
+import com.dfsek.terra.TerraWorld;
+import com.dfsek.terra.config.base.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
+import com.dfsek.terra.registry.ConfigRegistry;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.command.Command;
@@ -28,7 +29,10 @@ public class ReloadCommand extends Command implements DebugCommand {
@Override
public boolean execute(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, @NotNull String[] args) {
- ConfigUtil.loadConfig(Terra.getInstance());
+ PluginConfig.load(getMain());
+ LangUtil.load(PluginConfig.getLanguage(), getMain()); // Load language.
+ if(!ConfigRegistry.loadAll(getMain())) LangUtil.send("command.reload-error", sender);
+ TerraWorld.invalidate();
LangUtil.send("command.reload", sender);
return true;
}
diff --git a/src/main/java/com/dfsek/terra/command/TerraCommand.java b/src/main/java/com/dfsek/terra/command/TerraCommand.java
index abaa14356..07a8d23a7 100644
--- a/src/main/java/com/dfsek/terra/command/TerraCommand.java
+++ b/src/main/java/com/dfsek/terra/command/TerraCommand.java
@@ -25,7 +25,8 @@ public class TerraCommand extends Command {
new ImageCommand(this),
new GeometryCommand(this),
new FixChunkCommand(this),
- new VersionCommand(this));
+ new VersionCommand(this),
+ new PacksCommand(this));
public TerraCommand(GaeaPlugin main) {
super(main);
diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java b/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java
index 26b3f4b80..bcf1cc99d 100644
--- a/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java
+++ b/src/main/java/com/dfsek/terra/command/biome/BiomeInfoCommand.java
@@ -3,11 +3,10 @@ package com.dfsek.terra.command.biome;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
-import com.dfsek.terra.config.genconfig.biome.BiomeSnowConfig;
-import com.dfsek.terra.config.genconfig.structure.StructureConfig;
import com.dfsek.terra.config.lang.LangUtil;
+import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.generation.TerraChunkGenerator;
+import com.dfsek.terra.generation.items.TerraStructure;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -30,60 +29,27 @@ public class BiomeInfoCommand extends WorldCommand {
ConfigPack cfg = TerraWorld.getWorld(world).getConfig();
UserDefinedBiome b;
try {
- b = cfg.getBiome(id).getBiome();
+ b = cfg.getBiome(id);
} catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.biome.invalid", sender, id);
return true;
}
sender.sendMessage("Biome info for \"" + b.getID() + "\".");
sender.sendMessage("Vanilla biome: " + b.getVanillaBiome());
- sender.sendMessage("Erodible: " + b.isErodible());
+ sender.sendMessage("Eroded by: " + b.getErode());
- BiomeConfig bio = b.getConfig();
- List structureConfigs = bio.getStructures();
+ BiomeTemplate bio = b.getConfig();
+ List structureConfigs = bio.getStructures();
if(structureConfigs.size() == 0) sender.sendMessage("No Structures");
else {
sender.sendMessage("-------Structures-------");
- for(StructureConfig c : structureConfigs) {
- sender.sendMessage(" - " + c.getID());
+ for(TerraStructure c : structureConfigs) {
+ sender.sendMessage(" - " + c.getTemplate().getID());
}
}
- // Get snow info
- BiomeSnowConfig snowConfig = bio.getSnow();
- StringBuilder snowMessage = new StringBuilder("----------Snow----------\n");
- int comp = snowConfig.getSnowChance(0);
- int compHeight = 0;
- boolean changed = false;
- // Rebuild original snow data (rather than simply getting it, since it may have changed during initial assembly, if any overlaps occurred)
- for(int i = 0; i <= 255; i++) {
- int snow = snowConfig.getSnowChance(i);
- if(snow != comp) {
- changed = true;
- snowMessage.append("Y=")
- .append(compHeight)
- .append("-")
- .append(i)
- .append(": ")
- .append(comp)
- .append("% snow\n");
- comp = snow;
- compHeight = i;
- }
- }
- if(!changed) {
- snowMessage.append("Y=0")
- .append("-255")
- .append(": ")
- .append(comp)
- .append("% snow\n");
- }
- sender.sendMessage(snowMessage.toString());
-
- sender.sendMessage("Do snow: " + snowConfig.doSnow());
-
return true;
}
diff --git a/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java b/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java
index a6608cffa..39f405130 100644
--- a/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java
+++ b/src/main/java/com/dfsek/terra/command/biome/BiomeLocateCommand.java
@@ -4,6 +4,7 @@ import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.async.AsyncBiomeFinder;
import com.dfsek.terra.biome.UserDefinedBiome;
+import com.dfsek.terra.config.base.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.generation.TerraChunkGenerator;
import org.bukkit.Bukkit;
@@ -39,12 +40,12 @@ public class BiomeLocateCommand extends WorldCommand {
}
UserDefinedBiome b;
try {
- b = TerraWorld.getWorld(world).getConfig().getBiome(id).getBiome();
+ b = TerraWorld.getWorld(world).getConfig().getBiome(id);
} catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.biome.invalid", sender, id);
return true;
}
- Bukkit.getScheduler().runTaskAsynchronously(Terra.getInstance(), new AsyncBiomeFinder(TerraWorld.getWorld(world).getGrid(), b, sender.getLocation(), 0, maxRadius, location -> {
+ Bukkit.getScheduler().runTaskAsynchronously(Terra.getInstance(), new AsyncBiomeFinder(TerraWorld.getWorld(world).getGrid(), b, sender.getLocation().clone().multiply((1D / PluginConfig.getBiomeSearchResolution())), 0, maxRadius, location -> {
if(location != null) {
LangUtil.send("command.biome.biome-found", sender, String.valueOf(location.getBlockX()), String.valueOf(location.getBlockZ()));
if(tp) {
diff --git a/src/main/java/com/dfsek/terra/command/image/gui/RawGUICommand.java b/src/main/java/com/dfsek/terra/command/image/gui/RawGUICommand.java
index 7dba2c174..68e978625 100644
--- a/src/main/java/com/dfsek/terra/command/image/gui/RawGUICommand.java
+++ b/src/main/java/com/dfsek/terra/command/image/gui/RawGUICommand.java
@@ -1,7 +1,7 @@
package com.dfsek.terra.command.image.gui;
import com.dfsek.terra.TerraWorld;
-import com.dfsek.terra.config.base.ConfigUtil;
+import com.dfsek.terra.config.base.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.image.ImageLoader;
import org.bukkit.World;
@@ -21,7 +21,7 @@ public class RawGUICommand extends WorldCommand {
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
- if(!ConfigUtil.debug) {
+ if(!PluginConfig.isDebug()) {
LangUtil.send("command.image.gui.debug", sender);
return true;
}
diff --git a/src/main/java/com/dfsek/terra/command/image/gui/StepGUICommand.java b/src/main/java/com/dfsek/terra/command/image/gui/StepGUICommand.java
index 2b32bef89..0cc1f9929 100644
--- a/src/main/java/com/dfsek/terra/command/image/gui/StepGUICommand.java
+++ b/src/main/java/com/dfsek/terra/command/image/gui/StepGUICommand.java
@@ -1,7 +1,7 @@
package com.dfsek.terra.command.image.gui;
import com.dfsek.terra.TerraWorld;
-import com.dfsek.terra.config.base.ConfigUtil;
+import com.dfsek.terra.config.base.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.image.ImageLoader;
import org.bukkit.World;
@@ -21,7 +21,7 @@ public class StepGUICommand extends WorldCommand {
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
- if(!ConfigUtil.debug) {
+ if(!PluginConfig.isDebug()) {
LangUtil.send("command.image.gui.debug", sender);
return true;
}
diff --git a/src/main/java/com/dfsek/terra/command/structure/LocateCommand.java b/src/main/java/com/dfsek/terra/command/structure/LocateCommand.java
index 9d6c5ec85..7649e3f2f 100644
--- a/src/main/java/com/dfsek/terra/command/structure/LocateCommand.java
+++ b/src/main/java/com/dfsek/terra/command/structure/LocateCommand.java
@@ -3,9 +3,9 @@ package com.dfsek.terra.command.structure;
import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.async.AsyncStructureFinder;
-import com.dfsek.terra.config.genconfig.structure.StructureConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.generation.TerraChunkGenerator;
+import com.dfsek.terra.generation.items.TerraStructure;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -38,7 +38,7 @@ public class LocateCommand extends WorldCommand {
LangUtil.send("command.structure.invalid-radius", sender, args[1]);
return true;
}
- StructureConfig s;
+ TerraStructure s;
try {
s = Objects.requireNonNull(TerraWorld.getWorld(world).getConfig().getStructure(id));
} catch(IllegalArgumentException | NullPointerException e) {
diff --git a/src/main/java/com/dfsek/terra/config/ConfigLoader.java b/src/main/java/com/dfsek/terra/config/ConfigLoader.java
deleted file mode 100644
index 98d9c61e6..000000000
--- a/src/main/java/com/dfsek/terra/config/ConfigLoader.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.dfsek.terra.config;
-
-import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.base.ConfigUtil;
-import com.dfsek.terra.config.lang.LangUtil;
-import org.apache.commons.io.FilenameUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.stream.Stream;
-
-public class ConfigLoader {
- public static Map load(Path file, ConfigPack config, Class clazz) {
- long l = System.nanoTime();
- Map configs = new HashMap<>();
- //noinspection ResultOfMethodCallIgnored
- file.toFile().mkdirs();
- List ids = new ArrayList<>();
- try(Stream paths = Files.walk(file)) {
- paths.filter(path -> FilenameUtils.wildcardMatch(path.toFile().getName(), "*.yml"))
- .forEach(path -> {
- try {
- Constructor c = clazz.getConstructor(File.class, ConfigPack.class);
- T o = c.newInstance(path.toFile(), config);
- if(ids.contains(o.getID()))
- LangUtil.log("config.error.duplicate", Level.SEVERE, path.toString());
- ids.add(o.getID());
- configs.put(o.getID(), o);
- LangUtil.log("config.loaded", Level.INFO, o.toString(), path.toString());
- } catch(IllegalAccessException | InstantiationException | NoSuchMethodException e) {
- e.printStackTrace();
- LangUtil.log("config.error.generic", Level.SEVERE, path.toString());
- } catch(IllegalArgumentException | InvocationTargetException e) {
- if(ConfigUtil.debug) e.printStackTrace();
- LangUtil.log("config.error.file", Level.SEVERE, path.toString(), e.getMessage());
- }
- });
- LangUtil.log("config.loaded-all", Level.INFO, String.valueOf(configs.size()), clazz.getSimpleName(), String.valueOf((System.nanoTime() - l) / 1000000D));
- } catch(IOException e) {
- e.printStackTrace();
- }
- return configs;
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/TerraConfig.java b/src/main/java/com/dfsek/terra/config/TerraConfig.java
deleted file mode 100644
index 7334c3e8a..000000000
--- a/src/main/java/com/dfsek/terra/config/TerraConfig.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.dfsek.terra.config;
-
-import com.dfsek.terra.config.base.ConfigPack;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-public abstract class TerraConfig extends YamlConfiguration {
- private final ConfigPack config;
-
- public TerraConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
- load(file);
- this.config = config;
- }
-
- public TerraConfig(InputStream stream, ConfigPack config) throws IOException, InvalidConfigurationException {
- load(new InputStreamReader(stream));
- this.config = config;
- }
-
- public ConfigPack getConfig() {
- return config;
- }
-
- public abstract String getID();
-}
diff --git a/src/main/java/com/dfsek/terra/config/TerraConfigSection.java b/src/main/java/com/dfsek/terra/config/TerraConfigSection.java
deleted file mode 100644
index a53765911..000000000
--- a/src/main/java/com/dfsek/terra/config/TerraConfigSection.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.dfsek.terra.config;
-
-import org.jetbrains.annotations.NotNull;
-
-public abstract class TerraConfigSection {
- private final TerraConfig parent;
-
- public TerraConfigSection(@NotNull TerraConfig parent) {
- this.parent = parent;
- }
-
- @NotNull
- public TerraConfig getParent() {
- return parent;
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java b/src/main/java/com/dfsek/terra/config/base/ConfigPack.java
index 618bfebaf..3f8141d43 100644
--- a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java
+++ b/src/main/java/com/dfsek/terra/config/base/ConfigPack.java
@@ -1,322 +1,223 @@
package com.dfsek.terra.config.base;
-import com.dfsek.terra.Debug;
-import com.dfsek.terra.Terra;
+import com.dfsek.tectonic.abstraction.AbstractConfigLoader;
+import com.dfsek.tectonic.exception.ConfigException;
+import com.dfsek.tectonic.exception.LoadException;
+import com.dfsek.tectonic.loading.ConfigLoader;
+import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.carving.UserDefinedCarver;
-import com.dfsek.terra.config.ConfigLoader;
-import com.dfsek.terra.config.exception.ConfigException;
-import com.dfsek.terra.config.exception.NotFoundException;
-import com.dfsek.terra.config.genconfig.BiomeGridConfig;
-import com.dfsek.terra.config.genconfig.CarverConfig;
-import com.dfsek.terra.config.genconfig.FloraConfig;
-import com.dfsek.terra.config.genconfig.OreConfig;
-import com.dfsek.terra.config.genconfig.PaletteConfig;
-import com.dfsek.terra.config.genconfig.TreeConfig;
-import com.dfsek.terra.config.genconfig.biome.AbstractBiomeConfig;
-import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
-import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
-import com.dfsek.terra.config.genconfig.structure.StructureConfig;
+import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
+import com.dfsek.terra.config.exception.FileMissingException;
+import com.dfsek.terra.config.factories.BiomeFactory;
+import com.dfsek.terra.config.factories.BiomeGridFactory;
+import com.dfsek.terra.config.factories.CarverFactory;
+import com.dfsek.terra.config.factories.FloraFactory;
+import com.dfsek.terra.config.factories.OreFactory;
+import com.dfsek.terra.config.factories.PaletteFactory;
+import com.dfsek.terra.config.factories.StructureFactory;
+import com.dfsek.terra.config.factories.TerraFactory;
+import com.dfsek.terra.config.factories.TreeFactory;
+import com.dfsek.terra.config.files.FolderLoader;
+import com.dfsek.terra.config.files.Loader;
+import com.dfsek.terra.config.files.ZIPLoader;
import com.dfsek.terra.config.lang.LangUtil;
+import com.dfsek.terra.config.loaders.LootTableLoader;
+import com.dfsek.terra.config.loaders.StructureLoader;
+import com.dfsek.terra.config.templates.AbstractableTemplate;
+import com.dfsek.terra.config.templates.BiomeGridTemplate;
+import com.dfsek.terra.config.templates.BiomeTemplate;
+import com.dfsek.terra.config.templates.CarverTemplate;
+import com.dfsek.terra.config.templates.FloraTemplate;
+import com.dfsek.terra.config.templates.OreTemplate;
+import com.dfsek.terra.config.templates.PaletteTemplate;
+import com.dfsek.terra.config.templates.StructureTemplate;
+import com.dfsek.terra.config.templates.TreeTemplate;
+import com.dfsek.terra.generation.items.TerraStructure;
+import com.dfsek.terra.generation.items.ores.Ore;
+import com.dfsek.terra.registry.BiomeGridRegistry;
+import com.dfsek.terra.registry.BiomeRegistry;
+import com.dfsek.terra.registry.CarverRegistry;
import com.dfsek.terra.registry.FloraRegistry;
+import com.dfsek.terra.registry.OreRegistry;
+import com.dfsek.terra.registry.PaletteRegistry;
+import com.dfsek.terra.registry.StructureRegistry;
+import com.dfsek.terra.registry.TerraRegistry;
import com.dfsek.terra.registry.TreeRegistry;
+import com.dfsek.terra.structure.Structure;
+import com.dfsek.terra.util.ConfigUtil;
import com.dfsek.terra.util.StructureTypeEnum;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.plugin.java.JavaPlugin;
+import org.polydev.gaea.biome.Biome;
+import org.polydev.gaea.structures.loot.LootTable;
+import org.polydev.gaea.tree.Tree;
+import org.polydev.gaea.world.Flora;
+import org.polydev.gaea.world.palette.Palette;
import parsii.eval.Scope;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
+import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Level;
-import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
/**
* Represents a Terra configuration pack.
*/
-public class ConfigPack extends YamlConfiguration {
- private static final Map configs = new HashMap<>();
- public final List biomeList;
- public final double zoneFreq;
- public final double freq1;
- public final double freq2;
- public final double erosionFreq;
- public final double erosionThresh;
- public final boolean erosionEnable;
- public final int erosionOctaves;
- public final String erosionName;
- public final int blendAmp;
- public final boolean biomeBlend;
- public final double blendFreq;
- public final boolean vanillaCaves;
- public final boolean vanillaStructures;
- public final boolean vanillaDecoration;
- public final boolean vanillaMobs;
- public final boolean preventSaplingOverride;
-
- private final Map locatable = new HashMap<>();
- private final Map ores;
- private final Map palettes;
- private final Map carvers;
- private final Map structures;
- private final Map abstractBiomes;
- private final Map biomes;
- private final Map grids;
- private final TreeRegistry treeRegistry = new TreeRegistry();
+public class ConfigPack {
+ private final ConfigPackTemplate template = new ConfigPackTemplate();
+ private final BiomeRegistry biomeRegistry = new BiomeRegistry();
+ private final BiomeGridRegistry biomeGridRegistry = new BiomeGridRegistry(biomeRegistry);
+ private final StructureRegistry structureRegistry = new StructureRegistry();
+ private final CarverRegistry carverRegistry = new CarverRegistry();
+ private final PaletteRegistry paletteRegistry = new PaletteRegistry();
private final FloraRegistry floraRegistry = new FloraRegistry();
- private final Set allStructures = new HashSet<>();
- private final Map noiseBuilders = new HashMap<>();
- private final Scope vScope;
- private final File dataFolder;
- private final String id;
+ private final OreRegistry oreRegistry = new OreRegistry();
+ private final TreeRegistry treeRegistry = new TreeRegistry();
- public ConfigPack(File file) throws IOException, InvalidConfigurationException {
+ private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader();
+ private final ConfigLoader selfLoader = new ConfigLoader();
+ private final Scope varScope = new Scope();
+
+ private final Map structureMap = new HashMap<>();
+
+ {
+ abstractConfigLoader
+ .registerLoader(Palette.class, paletteRegistry)
+ .registerLoader(Biome.class, biomeRegistry)
+ .registerLoader(UserDefinedCarver.class, carverRegistry)
+ .registerLoader(Flora.class, floraRegistry)
+ .registerLoader(Ore.class, oreRegistry)
+ .registerLoader(Tree.class, treeRegistry)
+ .registerLoader(TerraStructure.class, structureRegistry);
+ ConfigUtil.registerAllLoaders(abstractConfigLoader);
+ ConfigUtil.registerAllLoaders(selfLoader);
+ }
+
+ public ConfigPack(File folder) throws ConfigException {
long l = System.nanoTime();
- load(new File(file, "pack.yml"));
- dataFolder = file;
- if(!contains("id")) throw new ConfigException("No ID specified!", "null");
- this.id = getString("id");
+ File pack = new File(folder, "pack.yml");
- Map noise = Objects.requireNonNull(getConfigurationSection("noise")).getValues(false);
- for(Map.Entry entry : noise.entrySet()) {
- NoiseConfig noiseConfig = new NoiseConfig((ConfigurationSection) entry.getValue());
- noiseBuilders.put(entry.getKey(), noiseConfig);
- Debug.info("Loaded noise function " + entry.getKey() + " with type " + noiseConfig.getBuilder().getType());
- }
-
- ores = ConfigLoader.load(new File(file, "ores").toPath(), this, OreConfig.class);
-
- palettes = ConfigLoader.load(new File(file, "palettes").toPath(), this, PaletteConfig.class);
-
- carvers = ConfigLoader.load(new File(file, "carving").toPath(), this, CarverConfig.class);
-
- Map flora = ConfigLoader.load(new File(file, "flora").toPath(), this, FloraConfig.class);
- for(Map.Entry entry : flora.entrySet()) {
- if(floraRegistry.add(entry.getKey(), entry.getValue()))
- Debug.info("Overriding Gaea flora: " + entry.getKey());
- }
-
- structures = ConfigLoader.load(new File(file, "structures").toPath(), this, StructureConfig.class);
-
- Map trees = ConfigLoader.load(new File(file, "trees").toPath(), this, TreeConfig.class);
-
- for(Map.Entry entry : trees.entrySet()) {
- if(treeRegistry.add(entry.getKey(), entry.getValue()))
- Debug.info("Overriding Vanilla tree: " + entry.getKey());
- }
-
- vScope = new Scope();
- if(contains("variables")) {
- Map vars = Objects.requireNonNull(getConfigurationSection("variables")).getValues(false);
- for(Map.Entry entry : vars.entrySet()) {
- try {
- vScope.getVariable(entry.getKey()).setValue(Double.parseDouble(entry.getValue().toString()));
- Debug.info("Registered variable " + entry.getKey() + " with value " + entry.getValue());
- } catch(ClassCastException | NumberFormatException e) {
- Debug.stack(e);
- throw new ConfigException("Variable value " + entry.getValue().toString() + " could not be parsed to a double.", getID());
- }
- }
- }
-
-
- abstractBiomes = ConfigLoader.load(new File(file, "abstract" + File.separator + "biomes").toPath(), this, AbstractBiomeConfig.class);
-
- biomes = ConfigLoader.load(new File(file, "biomes").toPath(), this, BiomeConfig.class);
-
- grids = ConfigLoader.load(new File(file, "grids").toPath(), this, BiomeGridConfig.class);
-
- zoneFreq = 1f / getInt("frequencies.zone", 1536);
- freq1 = 1f / getInt("frequencies.grid-x", 256);
- freq2 = 1f / getInt("frequencies.grid-z", 512);
-
- biomeBlend = getBoolean("blend.enable", false);
- blendAmp = getInt("blend.amplitude", 8);
- blendFreq = getDouble("blend.frequency", 0.01);
-
- erosionEnable = getBoolean("erode.enable", false);
- erosionFreq = getDouble("erode.frequency", 0.01);
- erosionThresh = getDouble("erode.threshold", 0.04);
- erosionOctaves = getInt("erode.octaves", 3);
-
- erosionName = getString("erode.grid");
-
- vanillaCaves = getBoolean("vanilla.caves", false);
- vanillaStructures = getBoolean("vanilla.structures", false);
- vanillaDecoration = getBoolean("vanilla.decorations", false);
- vanillaMobs = getBoolean("vanilla.mobs", false);
-
- preventSaplingOverride = getBoolean("prevent-sapling-override", false);
-
- if(vanillaMobs || vanillaDecoration || vanillaStructures || vanillaCaves) {
- Terra.getInstance().getLogger().warning("WARNING: Vanilla features have been enabled! These features may not work properly, and are not officially supported! Use at your own risk!");
- }
-
- // Load BiomeGrids from BiomeZone
- biomeList = getStringList("grids");
-
- for(String biome : biomeList) {
- if(getBiomeGrid(biome) == null) {
- if(biome.startsWith("BIOME:") && biomes.containsKey(biome.substring(6))) continue;
- throw new ConfigException("No such BiomeGrid: " + biome, getID());
- }
- }
-
- configs.put(id, this);
-
- for(BiomeConfig b : getBiomes().values()) {
- allStructures.addAll(b.getStructures());
- }
-
- ConfigurationSection st = getConfigurationSection("locatable");
- if(st != null) {
- Map strucLocatable = st.getValues(false);
- for(Map.Entry e : strucLocatable.entrySet()) {
- StructureConfig c = getStructure((String) e.getValue());
- if(c == null) throw new NotFoundException("Structure", (String) e.getValue(), getID());
- try {
- locatable.put(StructureTypeEnum.valueOf(e.getKey()), c);
- } catch(IllegalArgumentException ex) {
- throw new NotFoundException("Structure Type", e.getKey(), getID());
- }
- }
- }
-
- LangUtil.log("config-pack.loaded", Level.INFO, getID(), String.valueOf((System.nanoTime() - l) / 1000000D));
- }
-
- public static synchronized void loadAll(JavaPlugin main) {
- configs.clear();
- File file = new File(main.getDataFolder(), "packs");
- //noinspection ResultOfMethodCallIgnored
- file.mkdirs();
- List subfolder;
try {
- subfolder = Files.walk(file.toPath(), 1)
- .filter(Files::isDirectory)
- .collect(Collectors.toList());
- } catch(IOException e) {
- e.printStackTrace();
- return;
+ selfLoader.load(template, new FileInputStream(pack));
+ } catch(FileNotFoundException e) {
+ throw new FileMissingException("No pack.yml file found in " + folder.getAbsolutePath(), e);
}
- subfolder.remove(0);
- for(Path folder : subfolder) {
- ConfigPack config;
+
+ load(new FolderLoader(folder.toPath()), l);
+ }
+
+ public ConfigPack(ZipFile file) throws ConfigException {
+ long l = System.nanoTime();
+
+ InputStream stream = null;
+
+ try {
+ Enumeration extends ZipEntry> entries = file.entries();
+ while(entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if(entry.getName().equals("pack.yml")) stream = file.getInputStream(entry);
+ }
+ } catch(IOException e) {
+ throw new LoadException("Unable to load pack.yml from ZIP file", e);
+ }
+ if(stream == null) throw new FileMissingException("No pack.yml file found in " + file.getName());
+
+ selfLoader.load(template, stream);
+
+ load(new ZIPLoader(file), l);
+ }
+
+ private void load(Loader loader, long start) throws ConfigException {
+ for(Map.Entry var : template.getVariables().entrySet()) {
+ varScope.create(var.getKey()).setValue(var.getValue());
+ }
+ abstractConfigLoader.registerLoader(Structure.class, new StructureLoader(loader))
+ .registerLoader(LootTable.class, new LootTableLoader(loader)); // These loaders need access to the Loader instance to get files.
+ loader
+ .open("palettes").then(streams -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.load(streams, PaletteTemplate::new))).close()
+ .open("ores").then(streams -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.load(streams, OreTemplate::new))).close()
+ .open("flora").then(streams -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.load(streams, FloraTemplate::new))).close()
+ .open("carving").then(streams -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.load(streams, CarverTemplate::new))).close()
+ .open("structures/trees").then(streams -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.load(streams, TreeTemplate::new))).close()
+ .open("structures/single").then(streams -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.load(streams, StructureTemplate::new))).close()
+ .open("biomes").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this)))).close()
+ .open("grids").then(streams -> buildAll(new BiomeGridFactory(), biomeGridRegistry, abstractConfigLoader.load(streams, BiomeGridTemplate::new))).close();
+ for(UserDefinedBiome b : biomeRegistry.entries()) {
try {
- config = new ConfigPack(folder.toFile());
- if(configs.containsKey(config.getID())) {
- //Bukkit.getLogger().severe("Duplicate Config Pack ID: \"" + config.getID() + "\"");
- continue;
- }
- configs.put(config.getID(), config);
- } catch(IOException | InvalidConfigurationException e) {
- e.printStackTrace();
+ Objects.requireNonNull(b.getErode()); // Throws NPE if it cannot load erosion biomes.
+ } catch(NullPointerException e) {
+ throw new LoadException("Invalid erosion biome defined in biome \"" + b.getID() + "\"", e);
}
}
+ template.getStructureLocatables().forEach((type, name) -> structureMap.put(Objects.requireNonNull(type), Objects.requireNonNull(structureRegistry.get(name))));
+
+ LangUtil.log("config-pack.loaded", Level.INFO, template.getID(), String.valueOf((System.nanoTime() - start) / 1000000D), template.getAuthor(), template.getVersion());
}
- public static synchronized ConfigPack fromID(String id) {
- return configs.get(id);
+ private void buildAll(TerraFactory factory, TerraRegistry registry, List configTemplates) throws LoadException {
+ for(C template : configTemplates) registry.add(template.getID(), factory.build(template));
}
- public String getID() {
- return id;
+ public UserDefinedBiome getBiome(String id) {
+ return biomeRegistry.get(id);
}
- public Scope getVariableScope() {
- return vScope;
- }
-
- public Map getBiomes() {
- return biomes;
- }
-
- public StructureConfig getStructure(String id) {
- return structures.get(id);
- }
-
- public BiomeGridConfig getBiomeGrid(String id) {
- return grids.get(id);
- }
-
- public Map getNoiseBuilders() {
- return noiseBuilders;
- }
-
- public Map getLocatable() {
- return locatable;
- }
-
- public Map getAbstractBiomes() {
- return abstractBiomes;
- }
-
- public Map getCarvers() {
- return carvers;
- }
-
- public Set getAllStructures() {
- return allStructures;
- }
-
- public File getDataFolder() {
- return dataFolder;
- }
-
- public BiomeConfig getBiome(String id) {
- return biomes.get(id);
- }
-
- public CarverConfig getCarver(String id) {
- return carvers.get(id);
- }
-
- public CarverConfig getCarver(UserDefinedCarver c) {
- for(CarverConfig co : carvers.values()) {
- if(co.getCarver().equals(c)) return co;
- }
- throw new IllegalArgumentException("Unable to find carver!");
- }
-
- public PaletteConfig getPalette(String id) {
- return palettes.get(id);
- }
-
- public OreConfig getOre(String id) {
- return ores.get(id);
+ public BiomeGridBuilder getBiomeGrid(String id) {
+ return biomeGridRegistry.get(id);
}
public List getBiomeIDs() {
- List fill = new ArrayList<>();
- for(BiomeConfig b : biomes.values()) {
- fill.add(b.getID());
- }
- return fill;
+ List biomeIDs = new ArrayList<>();
+ biomeRegistry.forEach(biome -> biomeIDs.add(biome.getID()));
+ return biomeIDs;
+ }
+
+ public TerraStructure getStructure(String id) {
+ return structureRegistry.get(id);
+ }
+
+ public Set getStructures() {
+ return structureRegistry.entries();
+ }
+
+ public Collection getCarvers() {
+ return carverRegistry.entries();
+ }
+
+ public UserDefinedCarver getCarver(String id) {
+ return carverRegistry.get(id);
}
public List getStructureIDs() {
- List fill = new ArrayList<>();
- for(StructureConfig s : structures.values()) {
- fill.add(s.getID());
- }
- return fill;
- }
-
- public FloraRegistry getFloraRegistry() {
- return floraRegistry;
+ List ids = new ArrayList<>();
+ structureRegistry.forEach(structure -> ids.add(structure.getTemplate().getID()));
+ return ids;
}
public TreeRegistry getTreeRegistry() {
return treeRegistry;
}
+
+ public ConfigPackTemplate getTemplate() {
+ return template;
+ }
+
+ public Scope getVarScope() {
+ return varScope;
+ }
+
+ public TerraStructure getStructureLocatable(StructureTypeEnum type) {
+ return structureMap.get(type);
+ }
}
diff --git a/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java b/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java
new file mode 100644
index 000000000..4de6e3ae1
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/base/ConfigPackTemplate.java
@@ -0,0 +1,187 @@
+package com.dfsek.terra.config.base;
+
+import com.dfsek.tectonic.annotations.Default;
+import com.dfsek.tectonic.annotations.Value;
+import com.dfsek.tectonic.config.ConfigTemplate;
+import com.dfsek.terra.generation.config.NoiseBuilder;
+import com.dfsek.terra.util.StructureTypeEnum;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings({"unused", "FieldMayBeFinal"})
+public class ConfigPackTemplate implements ConfigTemplate {
+ @Value("id")
+ private String id;
+
+ @Value("noise")
+ private Map noiseBuilderMap;
+
+ @Value("variables")
+ @Default
+ private Map variables = new HashMap<>();
+
+ @Value("locatable")
+ @Default
+ private Map structureLocatables = new HashMap<>();
+
+ @Value("grids")
+ private List grids;
+
+ @Value("frequencies.grid-x")
+ @Default
+ private int gridFreqX = 4096;
+
+ @Value("frequencies.grid-z")
+ @Default
+ private int gridFreqZ = 4096;
+
+ @Value("frequencies.zone")
+ @Default
+ private int zoneFreq = 2048;
+
+ @Value("blend.enable")
+ @Default
+ private boolean blend = false;
+
+ @Value("blend.frequency")
+ @Default
+ private double blendFreq = 0.1;
+
+ @Value("blend.amplitude")
+ @Default
+ private double blendAmp = 4.0D;
+
+ @Value("erode.enable")
+ @Default
+ private boolean erode = false;
+
+ @Value("erode.frequency")
+ @Default
+ private double erodeFreq = 0.001D;
+
+ @Value("erode.threshold")
+ @Default
+ private double erodeThresh = 0.0015D;
+
+ @Value("erode.octaves")
+ @Default
+ private int erodeOctaves = 5;
+
+ @Value("vanilla.mobs")
+ @Default
+ private boolean vanillaMobs = true;
+
+ @Value("vanilla.caves")
+ @Default
+ private boolean vanillaCaves = false;
+
+ @Value("vanilla.decorations")
+ @Default
+ private boolean vanillaDecorations = false;
+
+ @Value("vanilla.structures")
+ @Default
+ private boolean vanillaStructures = false;
+
+ @Value("author")
+ @Default
+ private String author = "Anon Y. Mous";
+
+ @Value("disable.sapling")
+ @Default
+ private boolean disableSaplings = false;
+
+ @Value("version")
+ @Default
+ private String version = "0.1.0";
+
+ public String getVersion() {
+ return version;
+ }
+
+ public boolean isDisableSaplings() {
+ return disableSaplings;
+ }
+
+ public String getID() {
+ return id;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public boolean vanillaMobs() {
+ return vanillaMobs;
+ }
+
+ public boolean vanillaCaves() {
+ return vanillaCaves;
+ }
+
+ public boolean vanillaDecorations() {
+ return vanillaDecorations;
+ }
+
+ public boolean vanillaStructures() {
+ return vanillaStructures;
+ }
+
+ public Map getNoiseBuilderMap() {
+ return noiseBuilderMap;
+ }
+
+ public Map getVariables() {
+ return variables;
+ }
+
+ public Map getStructureLocatables() {
+ return structureLocatables;
+ }
+
+ public List getGrids() {
+ return grids;
+ }
+
+ public int getGridFreqX() {
+ return gridFreqX;
+ }
+
+ public int getGridFreqZ() {
+ return gridFreqZ;
+ }
+
+ public int getZoneFreq() {
+ return zoneFreq;
+ }
+
+ public boolean isBlend() {
+ return blend;
+ }
+
+ public double getBlendFreq() {
+ return blendFreq;
+ }
+
+ public double getBlendAmp() {
+ return blendAmp;
+ }
+
+ public boolean isErode() {
+ return erode;
+ }
+
+ public double getErodeFreq() {
+ return erodeFreq;
+ }
+
+ public double getErodeThresh() {
+ return erodeThresh;
+ }
+
+ public int getErodeOctaves() {
+ return erodeOctaves;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/base/ConfigUtil.java b/src/main/java/com/dfsek/terra/config/base/ConfigUtil.java
deleted file mode 100644
index a08824f44..000000000
--- a/src/main/java/com/dfsek/terra/config/base/ConfigUtil.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.dfsek.terra.config.base;
-
-import com.dfsek.terra.Debug;
-import com.dfsek.terra.Terra;
-import com.dfsek.terra.TerraWorld;
-import com.dfsek.terra.config.exception.ConfigException;
-import com.dfsek.terra.config.lang.LangUtil;
-import com.dfsek.terra.util.TagUtil;
-import org.bukkit.Bukkit;
-import org.bukkit.Material;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.plugin.java.JavaPlugin;
-import org.polydev.gaea.util.JarUtil;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.time.Duration;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.jar.JarFile;
-import java.util.logging.Logger;
-
-public final class ConfigUtil {
- public static boolean debug;
- public static long dataSave; // Period of population data saving, in ticks.
- public static boolean masterDisableCaves;
- public static int biomeSearchRes;
- public static int cacheSize;
-
- public static void loadConfig(JavaPlugin main) {
- main.saveDefaultConfig();
- main.reloadConfig();
- FileConfiguration config = main.getConfig();
- LangUtil.load(config.getString("language", "en_us"), main);
-
- debug = config.getBoolean("debug", false);
- dataSave = Duration.parse(Objects.requireNonNull(config.getString("data-save", "PT6M"))).toMillis() / 20L;
- masterDisableCaves = config.getBoolean("master-disable.caves", false);
- biomeSearchRes = config.getInt("biome-search-resolution", 4);
- cacheSize = config.getInt("cache-size", 384);
-
- if(config.getBoolean("dump-default", true)) {
- try(JarFile jar = new JarFile(new File(Terra.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
- JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString());
- } catch(IOException | URISyntaxException e) {
- Debug.error("Failed to dump default config files!");
- e.printStackTrace();
- Debug.error("Report this to Terra!");
- }
- }
-
- Logger logger = main.getLogger();
- logger.info("Loading config values");
-
- ConfigPack.loadAll(main);
- TerraWorld.invalidate();
- }
-
- public static Set toBlockData(List list, String phase, String id) throws InvalidConfigurationException {
- Set bl = EnumSet.noneOf(Material.class);
- for(String s : list) {
- try {
- if(s.startsWith("#")) {
- Debug.info("Loading Tag " + s);
- Set tag = TagUtil.getTag(s.substring(1));
- for(Material m : tag) {
- if(bl.contains(m)) {
- Bukkit.getLogger().warning("Duplicate material in " + phase + " list: " + m); // Check for duplicates in this tag
- }
- }
- bl.addAll(tag);
- } else {
- if(bl.contains(Bukkit.createBlockData(s).getMaterial()))
- Bukkit.getLogger().warning("Duplicate material in " + phase + " list: " + s);
- bl.add(Bukkit.createBlockData(s).getMaterial());
- }
- } catch(NullPointerException | IllegalArgumentException e) {
- throw new ConfigException("Could not load BlockData data for \"" + s + "\"", id);
- }
- }
- return bl;
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/base/PluginConfig.java b/src/main/java/com/dfsek/terra/config/base/PluginConfig.java
new file mode 100644
index 000000000..9cfba5641
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/base/PluginConfig.java
@@ -0,0 +1,94 @@
+package com.dfsek.terra.config.base;
+
+import com.dfsek.tectonic.annotations.Default;
+import com.dfsek.tectonic.annotations.Value;
+import com.dfsek.tectonic.config.ConfigTemplate;
+import com.dfsek.tectonic.exception.ConfigException;
+import com.dfsek.tectonic.loading.ConfigLoader;
+import com.dfsek.terra.Debug;
+import com.dfsek.terra.Terra;
+import org.polydev.gaea.GaeaPlugin;
+import org.polydev.gaea.util.JarUtil;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.time.Duration;
+import java.util.jar.JarFile;
+import java.util.logging.Logger;
+
+@SuppressWarnings("FieldMayBeFinal")
+public class PluginConfig implements ConfigTemplate {
+ private static final PluginConfig singleton = new PluginConfig();
+ private static boolean loaded = false;
+
+ @Value("debug")
+ @Default
+ private boolean debug = false;
+
+ @Value("language")
+ @Default
+ private String language = "en_us";
+
+ @Value("data-save")
+ @Default
+ private Duration dataSave = Duration.parse("PT6M");
+
+ @Value("biome-search-resolution")
+ @Default
+ private int biomeSearch = 4;
+
+ @Value("cache-size")
+ @Default
+ private int cacheSize = 384;
+
+ @Value("dump-default")
+ @Default
+ private boolean dumpDefaultConfig = true;
+
+ private PluginConfig() {
+ }
+
+ public static void load(GaeaPlugin main) {
+ Logger logger = main.getLogger();
+ logger.info("Loading config values");
+ try(FileInputStream file = new FileInputStream(new File(main.getDataFolder(), "config.yml"))) {
+ ConfigLoader loader = new ConfigLoader();
+ loader.load(singleton, file);
+ if(singleton.dumpDefaultConfig && !loaded) { // Don't dump default config if already loaded.
+ try(JarFile jar = new JarFile(new File(Terra.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
+ JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString());
+ } catch(IOException | URISyntaxException e) {
+ Debug.error("Failed to dump default config files!");
+ e.printStackTrace();
+ Debug.error("Report this to Terra!");
+ }
+ }
+ loaded = true;
+ } catch(ConfigException | IOException e) {
+ e.printStackTrace();
+ }
+ logger.info("Debug: " + isDebug());
+ }
+
+ public static String getLanguage() {
+ return singleton.language;
+ }
+
+ public static boolean isDebug() {
+ return singleton.debug;
+ }
+
+ public static long getDataSaveInterval() {
+ return singleton.dataSave.toMillis() / 20L;
+ }
+
+ public static int getBiomeSearchResolution() {
+ return singleton.biomeSearch;
+ }
+
+ public static int getCacheSize() {
+ return singleton.cacheSize;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/base/WorldConfig.java b/src/main/java/com/dfsek/terra/config/base/WorldConfig.java
index ab292d9ae..e8554ed48 100644
--- a/src/main/java/com/dfsek/terra/config/base/WorldConfig.java
+++ b/src/main/java/com/dfsek/terra/config/base/WorldConfig.java
@@ -1,9 +1,10 @@
package com.dfsek.terra.config.base;
+import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.Debug;
-import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.image.ImageLoader;
+import com.dfsek.terra.registry.ConfigRegistry;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
@@ -16,7 +17,7 @@ import java.io.IOException;
import java.util.Objects;
import java.util.logging.Level;
-public class WorldConfig {
+public class WorldConfig implements ConfigTemplate {
private final String worldID;
private final String configID;
private final GaeaPlugin main;
@@ -42,8 +43,6 @@ public class WorldConfig {
FileConfiguration config = new YamlConfiguration();
Debug.info("Loading config " + configID + " for world " + worldID);
try { // Load/create world config file
- if(configID == null || configID.isEmpty())
- throw new ConfigException("Config pack unspecified in bukkit.yml!", worldID);
File configFile = new File(main.getDataFolder() + File.separator + "worlds", worldID + ".yml");
if(!configFile.exists()) {
//noinspection ResultOfMethodCallIgnored
@@ -56,10 +55,7 @@ public class WorldConfig {
// Get values from config.
fromImage = config.getBoolean("image.enable", false);
- tConfig = ConfigPack.fromID(configID);
-
- if(tConfig == null)
- throw new ConfigException("No such config pack: \"" + configID + "\". This pack either does not exist, or failed to load due to configuration errors.", worldID);
+ tConfig = ConfigRegistry.getRegistry().get(configID);
// Load image stuff
try {
@@ -84,7 +80,7 @@ public class WorldConfig {
} catch(IllegalArgumentException | NullPointerException e) {
throw new InvalidConfigurationException(e.getCause());
}
- Bukkit.getLogger().log(Level.INFO, "Loaded {0} BiomeGrids from list.", tConfig.biomeList.size());
+ Bukkit.getLogger().log(Level.INFO, "Loaded {0} BiomeGrids from list.", tConfig.getTemplate().getGrids().size());
} catch(IOException | InvalidConfigurationException e) {
e.printStackTrace();
LangUtil.log("world-config.error", Level.SEVERE, worldID);
diff --git a/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java b/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java
new file mode 100644
index 000000000..d63460942
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java
@@ -0,0 +1,97 @@
+package com.dfsek.terra.config.builder;
+
+import com.dfsek.terra.biome.palette.PaletteHolder;
+import com.dfsek.terra.generation.config.NoiseBuilder;
+import com.dfsek.terra.generation.config.WorldGenerator;
+import parsii.eval.Scope;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GeneratorBuilder {
+ private final Map gens = new HashMap<>();
+
+ private String noiseEquation;
+
+ private String elevationEquation;
+
+ private Scope varScope;
+
+ private Map noiseBuilderMap;
+
+ private PaletteHolder palettes;
+
+ private PaletteHolder slantPalettes;
+
+ private boolean preventInterpolation;
+
+ private boolean interpolateElevation;
+
+ public WorldGenerator build(long seed) {
+ return gens.computeIfAbsent(seed, k -> new WorldGenerator(seed, noiseEquation, elevationEquation, varScope, noiseBuilderMap, palettes, slantPalettes, preventInterpolation, interpolateElevation));
+ }
+
+ public String getNoiseEquation() {
+ return noiseEquation;
+ }
+
+ public void setNoiseEquation(String noiseEquation) {
+ this.noiseEquation = noiseEquation;
+ }
+
+ public String getElevationEquation() {
+ return elevationEquation;
+ }
+
+ public void setElevationEquation(String elevationEquation) {
+ this.elevationEquation = elevationEquation;
+ }
+
+ public Scope getVarScope() {
+ return varScope;
+ }
+
+ public void setVarScope(Scope varScope) {
+ this.varScope = varScope;
+ }
+
+ public Map getNoiseBuilderMap() {
+ return noiseBuilderMap;
+ }
+
+ public void setNoiseBuilderMap(Map noiseBuilderMap) {
+ this.noiseBuilderMap = noiseBuilderMap;
+ }
+
+ public PaletteHolder getPalettes() {
+ return palettes;
+ }
+
+ public void setPalettes(PaletteHolder palettes) {
+ this.palettes = palettes;
+ }
+
+ public PaletteHolder getSlantPalettes() {
+ return slantPalettes;
+ }
+
+ public void setSlantPalettes(PaletteHolder slantPalettes) {
+ this.slantPalettes = slantPalettes;
+ }
+
+ public boolean isPreventInterpolation() {
+ return preventInterpolation;
+ }
+
+ public void setPreventInterpolation(boolean preventInterpolation) {
+ this.preventInterpolation = preventInterpolation;
+ }
+
+ public void setInterpolateElevation(boolean interpolateElevation) {
+ this.interpolateElevation = interpolateElevation;
+ }
+
+ public boolean interpolateElevation() {
+ return interpolateElevation;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java b/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java
new file mode 100644
index 000000000..76faee1f3
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/builder/biomegrid/BiomeGridBuilder.java
@@ -0,0 +1,9 @@
+package com.dfsek.terra.config.builder.biomegrid;
+
+import com.dfsek.terra.config.base.WorldConfig;
+import org.bukkit.World;
+import org.polydev.gaea.biome.BiomeGrid;
+
+public interface BiomeGridBuilder {
+ BiomeGrid build(World world, WorldConfig config);
+}
diff --git a/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java b/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java
new file mode 100644
index 000000000..b1c0af95b
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/builder/biomegrid/SingleGridBuilder.java
@@ -0,0 +1,19 @@
+package com.dfsek.terra.config.builder.biomegrid;
+
+import com.dfsek.terra.biome.grid.SingleBiomeGrid;
+import com.dfsek.terra.config.base.WorldConfig;
+import org.bukkit.World;
+import org.polydev.gaea.biome.Biome;
+
+public class SingleGridBuilder implements BiomeGridBuilder {
+ private final Biome biome;
+
+ public SingleGridBuilder(Biome biome) {
+ this.biome = biome;
+ }
+
+ @Override
+ public SingleBiomeGrid build(World world, WorldConfig config) {
+ return new SingleBiomeGrid(world, biome);
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java b/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java
new file mode 100644
index 000000000..6df57f2c9
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/builder/biomegrid/UserDefinedGridBuilder.java
@@ -0,0 +1,42 @@
+package com.dfsek.terra.config.builder.biomegrid;
+
+import com.dfsek.terra.biome.grid.UserDefinedGrid;
+import com.dfsek.terra.config.base.WorldConfig;
+import org.bukkit.World;
+import org.polydev.gaea.biome.Biome;
+
+public class UserDefinedGridBuilder implements BiomeGridBuilder {
+ private double xFreq;
+ private double zFreq;
+
+ private Biome[][] biomes;
+
+ @Override
+ public UserDefinedGrid build(World world, WorldConfig config) {
+ return new UserDefinedGrid(world, 1D / xFreq, 1D / zFreq, biomes, config);
+ }
+
+ public double getXFreq() {
+ return xFreq;
+ }
+
+ public void setXFreq(double xFreq) {
+ this.xFreq = xFreq;
+ }
+
+ public double getZFreq() {
+ return zFreq;
+ }
+
+ public void setZFreq(double zFreq) {
+ this.zFreq = zFreq;
+ }
+
+ public Biome[][] getBiomes() {
+ return biomes;
+ }
+
+ public void setBiomes(Biome[][] biomes) {
+ this.biomes = biomes;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/exception/ConfigException.java b/src/main/java/com/dfsek/terra/config/exception/ConfigException.java
deleted file mode 100644
index 7c1f24e68..000000000
--- a/src/main/java/com/dfsek/terra/config/exception/ConfigException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.dfsek.terra.config.exception;
-
-import org.bukkit.configuration.InvalidConfigurationException;
-
-/**
- * Thrown when a config item is not valid.
- */
-public class ConfigException extends InvalidConfigurationException {
- private static final long serialVersionUID = -4342864317005935979L;
- private final String message;
- private final String id;
-
- public ConfigException(String message, String id) {
- this.message = message;
- this.id = id;
- }
-
- @Override
- public String getMessage() {
- String ex = getStackTrace()[0].getClassName();
- return "Configuration error for " + ex.substring(ex.lastIndexOf(".") + 1) + " with ID \"" + id + "\": \n\n" + message;
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java b/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java
new file mode 100644
index 000000000..c4ac0ecf3
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/exception/FileMissingException.java
@@ -0,0 +1,15 @@
+package com.dfsek.terra.config.exception;
+
+import com.dfsek.tectonic.exception.ConfigException;
+
+public class FileMissingException extends ConfigException {
+ private static final long serialVersionUID = 4489395640246760802L;
+
+ public FileMissingException(String message) {
+ super(message);
+ }
+
+ public FileMissingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/exception/NotFoundException.java b/src/main/java/com/dfsek/terra/config/exception/NotFoundException.java
deleted file mode 100644
index 3a8dd3e16..000000000
--- a/src/main/java/com/dfsek/terra/config/exception/NotFoundException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.dfsek.terra.config.exception;
-
-/**
- * Thrown when a required config item is not found.
- */
-public class NotFoundException extends ConfigException {
- private static final long serialVersionUID = -3763471113262357426L;
-
- public NotFoundException(String item, String itemName, String id) {
- super(item + " \"" + itemName + "\" cannot be found!", id);
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java b/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java
new file mode 100644
index 000000000..5924bb9d8
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java
@@ -0,0 +1,32 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.terra.biome.UserDefinedBiome;
+import com.dfsek.terra.config.base.ConfigPack;
+import com.dfsek.terra.config.builder.GeneratorBuilder;
+import com.dfsek.terra.config.templates.BiomeTemplate;
+import com.dfsek.terra.generation.UserDefinedDecorator;
+import org.polydev.gaea.math.ProbabilityCollection;
+
+public class BiomeFactory implements TerraFactory {
+ private final ConfigPack pack;
+
+ public BiomeFactory(ConfigPack pack) {
+ this.pack = pack;
+ }
+
+ @Override
+ public UserDefinedBiome build(BiomeTemplate template) {
+ UserDefinedDecorator decorator = new UserDefinedDecorator(new ProbabilityCollection<>(), new ProbabilityCollection<>(), 0, 0);
+ GeneratorBuilder generatorBuilder = new GeneratorBuilder();
+ generatorBuilder.setElevationEquation(template.getElevationEquation());
+ generatorBuilder.setNoiseEquation(template.getNoiseEquation());
+ generatorBuilder.setNoiseBuilderMap(template.getPack().getTemplate().getNoiseBuilderMap());
+ generatorBuilder.setPalettes(template.getPalette());
+ generatorBuilder.setSlantPalettes(template.getSlantPalette());
+ generatorBuilder.setVarScope(pack.getVarScope());
+ generatorBuilder.setInterpolateElevation(template.interpolateElevation());
+
+
+ return new UserDefinedBiome(template.getVanilla(), decorator, generatorBuilder, template, pack);
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/BiomeGridFactory.java b/src/main/java/com/dfsek/terra/config/factories/BiomeGridFactory.java
new file mode 100644
index 000000000..9ab78df1f
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/BiomeGridFactory.java
@@ -0,0 +1,36 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.terra.biome.UserDefinedBiome;
+import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
+import com.dfsek.terra.config.builder.biomegrid.UserDefinedGridBuilder;
+import com.dfsek.terra.config.templates.BiomeGridTemplate;
+import org.polydev.gaea.biome.Biome;
+
+import java.util.List;
+
+public class BiomeGridFactory implements TerraFactory {
+
+ @Override
+ public UserDefinedGridBuilder build(BiomeGridTemplate config) {
+
+ UserDefinedGridBuilder holder = new UserDefinedGridBuilder();
+ holder.setXFreq(config.getXFreq());
+ holder.setZFreq(config.getZFreq());
+
+ int xSize = config.getGrid().size();
+ int zSize = config.getGrid().get(0).size();
+
+ Biome[][] biomes = new UserDefinedBiome[xSize][zSize];
+
+ for(int x = 0; x < xSize; x++) {
+ List layer = config.getGrid().get(x);
+ if(!(layer.size() == zSize)) throw new IllegalArgumentException();
+ for(int z = 0; z < zSize; z++) {
+ biomes[x][z] = layer.get(z);
+ }
+ }
+ holder.setBiomes(biomes);
+
+ return holder;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java b/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java
new file mode 100644
index 000000000..fb08f65b0
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java
@@ -0,0 +1,35 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.tectonic.exception.LoadException;
+import com.dfsek.terra.carving.UserDefinedCarver;
+import com.dfsek.terra.config.base.ConfigPack;
+import com.dfsek.terra.config.templates.CarverTemplate;
+import parsii.tokenizer.ParseException;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class CarverFactory implements TerraFactory {
+ private final ConfigPack pack;
+
+ public CarverFactory(ConfigPack pack) {
+ this.pack = pack;
+ }
+
+ @Override
+ public UserDefinedCarver build(CarverTemplate config) throws LoadException {
+ double[] start = new double[] {config.getStartX(), config.getStartY(), config.getStartZ()};
+ double[] mutate = new double[] {config.getMutateX(), config.getMutateY(), config.getMutateZ()};
+ List radius = Arrays.asList(config.getRadMX(), config.getRadMY(), config.getRadMZ());
+ int hash = config.getID().hashCode();
+ UserDefinedCarver carver;
+ try {
+ carver = new UserDefinedCarver(config.getHeight(), config.getLength(), start, mutate, radius, pack.getVarScope(), hash, config.getCutTop(), config.getCutBottom(), config);
+ } catch(ParseException e) {
+ throw new LoadException("Unable to parse radius equations", e);
+ }
+ carver.setRecalc(config.getRecalc());
+ carver.setRecalcMagnitude(config.getRecaclulateMagnitude());
+ return carver;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java b/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java
new file mode 100644
index 000000000..a9cd53d9a
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java
@@ -0,0 +1,21 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.terra.biome.palette.PaletteLayer;
+import com.dfsek.terra.config.templates.FloraTemplate;
+import com.dfsek.terra.generation.items.flora.TerraFlora;
+import org.bukkit.block.data.BlockData;
+import org.polydev.gaea.util.FastRandom;
+import org.polydev.gaea.world.Flora;
+import org.polydev.gaea.world.palette.Palette;
+import org.polydev.gaea.world.palette.RandomPalette;
+
+public class FloraFactory implements TerraFactory {
+ @Override
+ public TerraFlora build(FloraTemplate config) {
+ Palette palette = new RandomPalette<>(new FastRandom(2403));
+ for(PaletteLayer layer : config.getFloraPalette()) {
+ palette.add(layer.getLayer(), layer.getSize());
+ }
+ return new TerraFlora(palette, config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), config.getReplaceable(), config.getMaxPlacements(), config.getSearch(), config.isSpawnBlacklist(), config.getIrrigableOffset());
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/OreFactory.java b/src/main/java/com/dfsek/terra/config/factories/OreFactory.java
new file mode 100644
index 000000000..459f6ee6b
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/OreFactory.java
@@ -0,0 +1,21 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.terra.config.templates.OreTemplate;
+import com.dfsek.terra.generation.items.ores.DeformedSphereOre;
+import com.dfsek.terra.generation.items.ores.Ore;
+import com.dfsek.terra.generation.items.ores.VanillaOre;
+import org.bukkit.block.data.BlockData;
+
+public class OreFactory implements TerraFactory {
+ @Override
+ public Ore build(OreTemplate config) {
+ BlockData m = config.getMaterial();
+ switch(config.getType()) {
+ case SPHERE:
+ return new DeformedSphereOre(m, config.getReplaceable(), config.doPhysics(), config.getDeform(), config.getDeformFrequency(), config.getSize());
+ case VANILLA:
+ return new VanillaOre(m, config.getReplaceable(), config.doPhysics(), config.getSize());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java b/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java
new file mode 100644
index 000000000..8b6b68d08
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java
@@ -0,0 +1,27 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.terra.biome.palette.PaletteLayer;
+import com.dfsek.terra.config.templates.PaletteTemplate;
+import org.bukkit.block.data.BlockData;
+import org.polydev.gaea.math.FastNoiseLite;
+import org.polydev.gaea.util.FastRandom;
+import org.polydev.gaea.world.palette.Palette;
+import org.polydev.gaea.world.palette.RandomPalette;
+import org.polydev.gaea.world.palette.SimplexPalette;
+
+public class PaletteFactory implements TerraFactory> {
+ @Override
+ public Palette build(PaletteTemplate config) {
+ Palette palette;
+ if(config.isSimplex()) {
+ FastNoiseLite noise = new FastNoiseLite((int) config.getSeed());
+ noise.setFrequency(config.getFrequency());
+ palette = new SimplexPalette<>(noise);
+ } else palette = new RandomPalette<>(new FastRandom(config.getSeed()));
+
+ for(PaletteLayer layer : config.getPalette()) {
+ palette.add(layer.getLayer(), layer.getSize());
+ }
+ return palette;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java b/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java
new file mode 100644
index 000000000..fa20f3ff1
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java
@@ -0,0 +1,12 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.tectonic.exception.LoadException;
+import com.dfsek.terra.config.templates.StructureTemplate;
+import com.dfsek.terra.generation.items.TerraStructure;
+
+public class StructureFactory implements TerraFactory {
+ @Override
+ public TerraStructure build(StructureTemplate config) throws LoadException {
+ return new TerraStructure(config.getStructures(), config.getBound(), config.getY(), config.getSpawn(), config.getLoot(), config);
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java b/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java
new file mode 100644
index 000000000..6c868d7c8
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java
@@ -0,0 +1,8 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.tectonic.config.ConfigTemplate;
+import com.dfsek.tectonic.exception.LoadException;
+
+public interface TerraFactory {
+ O build(C config) throws LoadException;
+}
diff --git a/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java b/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java
new file mode 100644
index 000000000..6704716cc
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java
@@ -0,0 +1,13 @@
+package com.dfsek.terra.config.factories;
+
+import com.dfsek.tectonic.exception.LoadException;
+import com.dfsek.terra.config.templates.TreeTemplate;
+import com.dfsek.terra.generation.items.tree.TerraTree;
+import org.polydev.gaea.tree.Tree;
+
+public class TreeFactory implements TerraFactory {
+ @Override
+ public Tree build(TreeTemplate config) throws LoadException {
+ return new TerraTree(config.getSpawnable(), config.getyOffset(), config.getStructures());
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/files/ExceptionalConsumer.java b/src/main/java/com/dfsek/terra/config/files/ExceptionalConsumer.java
new file mode 100644
index 000000000..9705afe78
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/files/ExceptionalConsumer.java
@@ -0,0 +1,8 @@
+package com.dfsek.terra.config.files;
+
+import com.dfsek.tectonic.exception.ConfigException;
+
+@FunctionalInterface
+public interface ExceptionalConsumer {
+ void accept(T t) throws ConfigException;
+}
diff --git a/src/main/java/com/dfsek/terra/config/files/FolderLoader.java b/src/main/java/com/dfsek/terra/config/files/FolderLoader.java
new file mode 100644
index 000000000..12c73eb39
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/files/FolderLoader.java
@@ -0,0 +1,43 @@
+package com.dfsek.terra.config.files;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+
+/**
+ * Load all {@code *.yml} files from a {@link java.nio.file.Path}.
+ */
+public class FolderLoader extends Loader {
+ private final Path path;
+
+ public FolderLoader(Path path) {
+ this.path = path;
+ }
+
+ @Override
+ public InputStream get(String singleFile) throws IOException {
+ return new FileInputStream(new File(path.toFile(), singleFile));
+ }
+
+ @Override
+ protected void load(String directory) {
+ File newPath = new File(path.toFile(), directory);
+ newPath.mkdirs();
+ try(Stream paths = Files.walk(newPath.toPath())) {
+ paths.filter(Files::isRegularFile).filter(file -> file.toString().toLowerCase().endsWith(".yml")).forEach(file -> {
+ try {
+ streams.add(new FileInputStream(file.toFile()));
+ } catch(FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ });
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/files/Loader.java b/src/main/java/com/dfsek/terra/config/files/Loader.java
new file mode 100644
index 000000000..4d7257208
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/files/Loader.java
@@ -0,0 +1,58 @@
+package com.dfsek.terra.config.files;
+
+import com.dfsek.tectonic.exception.ConfigException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class Loader {
+ protected final List streams = new ArrayList<>();
+
+ /**
+ * Do something with the InputStreams.
+ *
+ * @param consumer Something to do with the streams.
+ */
+ public Loader then(ExceptionalConsumer> consumer) throws ConfigException {
+ consumer.accept(streams);
+ return this;
+ }
+
+ /**
+ * Get a single file from this Loader.
+ *
+ * @param singleFile File to get
+ * @return InputStream from file.
+ */
+ public abstract InputStream get(String singleFile) throws IOException;
+
+ /**
+ * Open a subdirectory.
+ *
+ * @param directory Directory to open
+ */
+ public Loader open(String directory) {
+ if(streams.size() != 0) throw new IllegalStateException("Attempted to load new directory before closing existing InputStreams");
+ load(directory);
+ return this;
+ }
+
+ protected abstract void load(String directory);
+
+ /**
+ * Close all InputStreams opened.
+ */
+ public Loader close() {
+ streams.forEach(input -> {
+ try {
+ input.close();
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ });
+ streams.clear();
+ return this;
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java b/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java
new file mode 100644
index 000000000..85da05f98
--- /dev/null
+++ b/src/main/java/com/dfsek/terra/config/files/ZIPLoader.java
@@ -0,0 +1,40 @@
+package com.dfsek.terra.config.files;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class ZIPLoader extends Loader {
+ private final ZipFile file;
+
+ public ZIPLoader(ZipFile file) {
+ this.file = file;
+ }
+
+ @Override
+ public InputStream get(String singleFile) throws IOException {
+ Enumeration extends ZipEntry> entries = file.entries();
+ while(entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if(!entry.isDirectory() && entry.getName().equals(singleFile)) return file.getInputStream(entry);
+ }
+ throw new IllegalArgumentException("No such file: " + singleFile);
+ }
+
+ @Override
+ protected void load(String directory) {
+ Enumeration extends ZipEntry> entries = file.entries();
+ while(entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if(!entry.isDirectory() && entry.getName().startsWith(directory) && entry.getName().endsWith(".yml")) {
+ try {
+ streams.add(file.getInputStream(entry));
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/dfsek/terra/config/genconfig/BiomeGridConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/BiomeGridConfig.java
deleted file mode 100644
index 5edbd517c..000000000
--- a/src/main/java/com/dfsek/terra/config/genconfig/BiomeGridConfig.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.dfsek.terra.config.genconfig;
-
-import com.dfsek.terra.biome.UserDefinedBiome;
-import com.dfsek.terra.biome.grid.UserDefinedGrid;
-import com.dfsek.terra.config.TerraConfig;
-import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.base.WorldConfig;
-import com.dfsek.terra.config.exception.ConfigException;
-import com.dfsek.terra.config.exception.NotFoundException;
-import org.bukkit.World;
-import org.bukkit.configuration.InvalidConfigurationException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-
-public class BiomeGridConfig extends TerraConfig {
- private final String gridID;
- private final UserDefinedBiome[][] gridRaw;
- private final int sizeX;
- private final int sizeZ;
-
- @SuppressWarnings("unchecked")
- public BiomeGridConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
- super(file, config);
- load(file);
- if(!contains("id")) throw new ConfigException("Grid ID unspecified!", "null");
- this.gridID = getString("id");
- if(!contains("grid")) throw new ConfigException("Grid key not found!", getID());
- this.sizeX = Objects.requireNonNull(getList("grid")).size();
- this.sizeZ = ((List>) Objects.requireNonNull(getList("grid"))).get(0).size();
- gridRaw = new UserDefinedBiome[sizeX][sizeZ];
- try {
- for(int x = 0; x < sizeX; x++) {
- for(int z = 0; z < sizeZ; z++) {
- try {
- gridRaw[x][z] = config.getBiome(((List>) Objects.requireNonNull(getList("grid"))).get(x).get(z)).getBiome();
- } catch(NullPointerException e) {
- throw new NotFoundException("Biome", ((List>) Objects.requireNonNull(getList("grid"))).get(x).get(z), getID());
- }
- }
- }
- } catch(ClassCastException | NullPointerException e) {
- throw new ConfigException("Malformed grid! Ensure all dimensions are correct.", getID());
- }
- }
-
- public String getID() {
- return gridID;
- }
-
- public UserDefinedBiome[][] getBiomeGrid() {
- return gridRaw;
- }
-
- public UserDefinedGrid getGrid(World w, WorldConfig wc) {
- ConfigPack c = wc.getConfig();
- return new UserDefinedGrid(w, c.freq1, c.freq2, gridRaw, wc);
- }
-
- @Override
- public String toString() {
- return "BiomeGrid with ID " + getID() + ", dimensions " + getSizeX() + ":" + getSizeZ();
- }
-
- public int getSizeX() {
- return sizeX;
- }
-
- public int getSizeZ() {
- return sizeZ;
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java
deleted file mode 100644
index 2fde8d449..000000000
--- a/src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package com.dfsek.terra.config.genconfig;
-
-import com.dfsek.terra.Debug;
-import com.dfsek.terra.carving.UserDefinedCarver;
-import com.dfsek.terra.config.TerraConfig;
-import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.base.ConfigUtil;
-import com.dfsek.terra.config.exception.ConfigException;
-import org.bukkit.Bukkit;
-import org.bukkit.Material;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.polydev.gaea.math.ProbabilityCollection;
-import org.polydev.gaea.math.Range;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeMap;
-
-public class CarverConfig extends TerraConfig {
- private final UserDefinedCarver carver;
- private final String id;
- private final Set replaceableInner;
- private final Set replaceableOuter;
- private final Set replaceableTop;
- private final Set replaceableBottom;
- private final Set update;
- private final Map> shift;
- private final Map> inner;
- private final Map> outer;
- private final Map> top;
- private final Map> bottom;
- private final boolean replaceIsBlacklistInner;
- private final boolean replaceIsBlacklistOuter;
- private final boolean replaceIsBlacklistTop;
- private final boolean replaceIsBlacklistBottom;
- private final boolean updateOcean;
-
- @SuppressWarnings("unchecked")
- public CarverConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
- super(file, config);
- load(file);
- if(!contains("id")) throw new ConfigException("No ID specified for Carver!", "null");
- id = Objects.requireNonNull(getString("id"));
-
- inner = getBlocks("palette.inner.layers");
-
- outer = getBlocks("palette.outer.layers");
-
- top = getBlocks("palette.top.layers");
-
- bottom = getBlocks("palette.bottom.layers");
-
- replaceableInner = ConfigUtil.toBlockData(getStringList("palette.inner.replace"), "replaceable inner", getID());
-
- replaceableOuter = ConfigUtil.toBlockData(getStringList("palette.outer.replace"), "replaceable outer", getID());
-
- replaceableTop = ConfigUtil.toBlockData(getStringList("palette.top.replace"), "replaceable top", getID());
-
- replaceableBottom = ConfigUtil.toBlockData(getStringList("palette.bottom.replace"), "replaceable bottom", getID());
-
- update = ConfigUtil.toBlockData(getStringList("update"), "update", getID());
-
- updateOcean = getBoolean("update-liquids", false);
-
- double step = getDouble("step", 2);
- Range recalc = new Range(getInt("recalculate-direction.min", 8), getInt("recalculate-direction.max", 12));
- double rm = getDouble("recalculate-magnitude", 4);
- shift = new HashMap<>();
- for(Map.Entry e : Objects.requireNonNull(getConfigurationSection("shift")).getValues(false).entrySet()) {
- Set l = EnumSet.noneOf(Material.class);
- for(String s : (List) e.getValue()) {
- l.add(Bukkit.createBlockData(s).getMaterial());
- Debug.info("Added " + s + " to shift-able blocks");
- }
- shift.put(Bukkit.createBlockData(e.getKey()).getMaterial(), l);
- Debug.info("Added " + e.getKey() + " as master block");
- }
-
- replaceIsBlacklistInner = getBoolean("palette.inner.replace-blacklist", false);
- replaceIsBlacklistOuter = getBoolean("palette.outer.replace-blacklist", false);
- replaceIsBlacklistTop = getBoolean("palette.top.replace-blacklist", false);
- replaceIsBlacklistBottom = getBoolean("palette.bottom.replace-blacklist", false);
-
- double[] start = new double[] {getDouble("start.x"), getDouble("start.y"), getDouble("start.z")};
- double[] mutate = new double[] {getDouble("mutate.x"), getDouble("mutate.y"), getDouble("mutate.z"), getDouble("mutate.radius")};
- double[] radiusMultiplier = new double[] {getDouble("start.radius.multiply.x"), getDouble("start.radius.multiply.y"), getDouble("start.radius.multiply.z")};
- Range length = new Range(getInt("length.min"), getInt("length.max"));
- Range radius = new Range(getInt("start.radius.min"), getInt("start.radius.max"));
- Range height = new Range(getInt("start.height.min"), getInt("start.height.max"));
-
- carver = new UserDefinedCarver(height, radius, length, start, mutate, radiusMultiplier, id.hashCode(), getInt("cut.top", 0), getInt("cut.bottom", 0));
- carver.setStep(step);
- carver.setRecalc(recalc);
- carver.setRecalcMagnitude(rm);
- }
-
- @SuppressWarnings("unchecked")
- private Map> getBlocks(String key) throws InvalidConfigurationException {
- if(!contains(key)) throw new ConfigException("Missing Carver Palette!", getID());
- Map> result = new TreeMap<>();
- for(Map, ?> m : getMapList(key)) {
- try {
- ProbabilityCollection layer = new ProbabilityCollection<>();
- for(Map.Entry type : ((Map) m.get("materials")).entrySet()) {
- layer.add(Bukkit.createBlockData(type.getKey()), type.getValue());
- Debug.info("Added " + type.getKey() + " with probability " + type.getValue());
- }
- result.put((Integer) m.get("y"), layer);
- Debug.info("Added at level " + m.get("y"));
- } catch(ClassCastException e) {
- throw new ConfigException("Unable to parse Carver Palette configuration! Check YAML syntax:" + e.getMessage(), getID());
- }
- }
- return result;
- }
-
- public String getID() {
- return id;
- }
-
- public UserDefinedCarver getCarver() {
- return carver;
- }
-
- public Map> getShiftedBlocks() {
- return shift;
- }
-
- public Set getUpdateBlocks() {
- return update;
- }
-
- public boolean isReplaceableInner(Material m) {
- if(replaceIsBlacklistInner) {
- return !replaceableInner.contains(m);
- }
- return replaceableInner.contains(m);
- }
-
- public boolean isReplaceableOuter(Material m) {
- if(replaceIsBlacklistOuter) {
- return !replaceableOuter.contains(m);
- }
- return replaceableOuter.contains(m);
- }
-
- public boolean isReplaceableTop(Material m) {
- if(replaceIsBlacklistTop) {
- return !replaceableTop.contains(m);
- }
- return replaceableTop.contains(m);
- }
-
- public boolean isReplaceableBottom(Material m) {
- if(replaceIsBlacklistBottom) {
- return !replaceableBottom.contains(m);
- }
- return replaceableBottom.contains(m);
- }
-
- public ProbabilityCollection getPaletteInner(int y) {
- for(Map.Entry> e : inner.entrySet()) {
- if(e.getKey() >= y) return e.getValue();
- }
- return null;
- }
-
- public ProbabilityCollection getPaletteOuter(int y) {
- for(Map.Entry> e : outer.entrySet()) {
- if(e.getKey() >= y) return e.getValue();
- }
- return null;
- }
-
- public ProbabilityCollection getPaletteBottom(int y) {
- for(Map.Entry> e : bottom.entrySet()) {
- if(e.getKey() >= y) return e.getValue();
- }
- return null;
- }
-
- public ProbabilityCollection getPaletteTop(int y) {
- for(Map.Entry> e : top.entrySet()) {
- if(e.getKey() >= y) return e.getValue();
- }
- return null;
- }
-
- public boolean shouldUpdateOcean() {
- return updateOcean;
- }
-
- @Override
- public String toString() {
- return "Carver with ID " + getID();
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/genconfig/FloraConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/FloraConfig.java
deleted file mode 100644
index 858e02fb3..000000000
--- a/src/main/java/com/dfsek/terra/config/genconfig/FloraConfig.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.dfsek.terra.config.genconfig;
-
-import com.dfsek.terra.config.TerraConfig;
-import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.base.ConfigUtil;
-import com.dfsek.terra.config.exception.ConfigException;
-import net.jafama.FastMath;
-import org.bukkit.Chunk;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.polydev.gaea.math.Range;
-import org.polydev.gaea.util.FastRandom;
-import org.polydev.gaea.world.Flora;
-import org.polydev.gaea.world.palette.Palette;
-import org.polydev.gaea.world.palette.RandomPalette;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-public class FloraConfig extends TerraConfig implements Flora {
- private final Palette floraPalette;
- private final String id;
- private final boolean physics;
- private final boolean ceiling;
-
- private final Set irrigable;
-
- private final Set spawnable;
- private final Set replaceable;
-
- public FloraConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
- super(file, config);
- load(file);
- if(!contains("id")) throw new ConfigException("Flora ID unspecified!", "null");
- this.id = getString("id");
- if(!contains("layers")) throw new ConfigException("No blocks defined in custom flora!", getID());
- if(!contains("spawnable")) throw new ConfigException("Flora spawnable blocks unspecified!", getID());
-
- spawnable = ConfigUtil.toBlockData(getStringList("spawnable"), "spawnable", getID());
- replaceable = ConfigUtil.toBlockData(getStringList("replaceable"), "replaceable", getID());
-
- if(contains("irrigable")) {
- irrigable = ConfigUtil.toBlockData(getStringList("irrigable"), "irrigable", getID());
- } else irrigable = null;
-
- physics = getBoolean("physics", false);
- ceiling = getBoolean("ceiling", false);
-
- Palette p = new RandomPalette<>(new FastRandom(getInt("seed", 4)));
-
- floraPalette = PaletteConfig.getPalette(getMapList("layers"), p);
- }
-
- public String getID() {
- return id;
- }
-
- @Override
- public List getValidSpawnsAt(Chunk chunk, int x, int z, Range range) {
- int size = floraPalette.getSize();
- Block current = chunk.getBlock(x, range.getMin(), z);
- List blocks = new ArrayList<>();
- for(int y : range) {
- if(y > 255 || y < 0) continue;
- current = current.getRelative(BlockFace.UP);
- if(spawnable.contains(current.getType()) && isIrrigated(current) && valid(size, current)) {
- blocks.add(current);
- }
- }
- return blocks;
- }
-
- private boolean valid(int size, Block block) {
- for(int i = 0; i < size; i++) { // Down if ceiling, up if floor
- if(block.getY() + 1 > 255 || block.getY() < 0) return false;
- block = block.getRelative(ceiling ? BlockFace.DOWN : BlockFace.UP);
- if(!replaceable.contains(block.getType())) return false;
- }
- return true;
- }
-
- private boolean isIrrigated(Block b) {
- if(irrigable == null) return true;
- return irrigable.contains(b.getRelative(BlockFace.NORTH).getType())
- || irrigable.contains(b.getRelative(BlockFace.SOUTH).getType())
- || irrigable.contains(b.getRelative(BlockFace.EAST).getType())
- || irrigable.contains(b.getRelative(BlockFace.WEST).getType());
- }
-
- @Override
- public boolean plant(Location location) {
- int size = floraPalette.getSize();
- int c = ceiling ? -1 : 1;
- for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor
- int lvl = (FastMath.abs(i));
- location.clone().add(0, i + c, 0).getBlock().setBlockData(floraPalette.get((ceiling ? lvl : size - lvl - 1), location.getBlockX(), location.getBlockZ()), physics);
- }
- return true;
- }
-
- @Override
- public String toString() {
- return "Flora with name ID " + getID();
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java
deleted file mode 100644
index 10383b116..000000000
--- a/src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.dfsek.terra.config.genconfig;
-
-import com.dfsek.terra.config.TerraConfig;
-import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.base.ConfigUtil;
-import com.dfsek.terra.config.exception.ConfigException;
-import net.jafama.FastMath;
-import org.bukkit.Bukkit;
-import org.bukkit.Chunk;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.util.Vector;
-import org.polydev.gaea.math.FastNoiseLite;
-import org.polydev.gaea.population.ChunkCoordinate;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Random;
-import java.util.Set;
-
-public class OreConfig extends TerraConfig {
- private final BlockData oreData;
- private final int min;
- private final int max;
- private final double deform;
- private final double deformFrequency;
- private final String id;
- private final boolean update;
- Set replaceable;
-
- public OreConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
- super(file, config);
- if(!contains("id")) throw new ConfigException("Ore ID not found!", "null");
- this.id = getString("id");
- if(!contains("material")) throw new ConfigException("Ore material not found!", getID());
- if(!contains("deform")) throw new ConfigException("Ore vein deformation not found!", getID());
- if(!contains("replace")) throw new ConfigException("Ore replaceable materials not found!", getID());
- min = getInt("radius.min", 1);
- max = getInt("radius.max", 1);
- deform = getDouble("deform", 0.75);
- deformFrequency = getDouble("deform-frequency", 0.1);
- update = getBoolean("update", false);
-
- replaceable = ConfigUtil.toBlockData(getStringList("replace"), "replaceable", getID());
-
- try {
- oreData = Bukkit.createBlockData(Objects.requireNonNull(getString("material")));
- } catch(NullPointerException | IllegalArgumentException e) {
- throw new ConfigException("Invalid ore material: " + getString("material"), getID());
- }
- }
-
- public String getID() {
- return id;
- }
-
- public void doVein(Vector l, Chunk chunk, Random r) {
- FastNoiseLite ore = new FastNoiseLite(r.nextInt());
- ore.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- ore.setFrequency(deformFrequency);
- int rad = randomInRange(r);
- Map chunks = new HashMap<>(); // Cache chunks to prevent re-loading chunks every time one is needed.
- chunks.put(new ChunkCoordinate(chunk), chunk);
- Vector orig = new Vector(l.getBlockX() + (chunk.getX() << 4), l.getBlockY(), l.getBlockZ() + (chunk.getZ() << 4));
- for(int x = -rad; x <= rad; x++) {
- for(int y = -rad; y <= rad; y++) {
- for(int z = -rad; z <= rad; z++) {
- Vector oreLoc = orig.clone().add(new Vector(x, y, z));
- Vector source = l.clone().add(new Vector(x, y, z));
- if(oreLoc.getBlockY() > 255 || oreLoc.getBlockY() < 0) continue;
- if(source.distance(l) < (rad + 0.5) * ((ore.getNoise(x, y, z) + 1) * deform)) {
- ChunkCoordinate coord = new ChunkCoordinate(FastMath.floorDiv(oreLoc.getBlockX(), 16), FastMath.floorDiv(oreLoc.getBlockZ(), 16), chunk.getWorld().getUID());
- Block b = chunks.computeIfAbsent(coord, k -> chunk.getWorld().getChunkAt(oreLoc.toLocation(chunk.getWorld())))
- .getBlock(FastMath.floorMod(source.getBlockX(), 16), source.getBlockY(), FastMath.floorMod(source.getBlockZ(), 16)); // Chunk caching conditional computation
- if(replaceable.contains(b.getType()) && b.getLocation().getY() >= 0)
- b.setBlockData(oreData, update);
- }
- }
- }
- }
- }
-
- private int randomInRange(Random r) {
- return r.nextInt(max - min + 1) + min;
- }
-
- public void doVeinSingle(Vector l, Chunk chunk, Random r) {
- FastNoiseLite ore = new FastNoiseLite(r.nextInt());
- ore.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- ore.setFrequency(deformFrequency);
- int rad = randomInRange(r);
- for(int x = -rad; x <= rad; x++) {
- for(int y = -rad; y <= rad; y++) {
- for(int z = -rad; z <= rad; z++) {
- Vector oreLoc = l.clone().add(new Vector(x, y, z));
- if(oreLoc.getBlockX() > 15 || oreLoc.getBlockZ() > 15 || oreLoc.getBlockY() > 255 || oreLoc.getBlockX() < 0 || oreLoc.getBlockZ() < 0 || oreLoc.getBlockY() < 0)
- continue;
- if(oreLoc.distance(l) < (rad + 0.5) * ((ore.getNoise(x, y, z) + 1) * deform)) {
- Block b = chunk.getBlock(oreLoc.getBlockX(), oreLoc.getBlockY(), oreLoc.getBlockZ());
- if(replaceable.contains(b.getType()) && b.getLocation().getY() >= 0)
- b.setBlockData(oreData, update);
- }
- }
- }
- }
- }
-
- @Override
- public String toString() {
- return "Ore with ID " + getID();
- }
-}
diff --git a/src/main/java/com/dfsek/terra/config/genconfig/PaletteConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/PaletteConfig.java
deleted file mode 100644
index 2d93a465c..000000000
--- a/src/main/java/com/dfsek/terra/config/genconfig/PaletteConfig.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.dfsek.terra.config.genconfig;
-
-import com.dfsek.terra.Debug;
-import com.dfsek.terra.config.TerraConfig;
-import com.dfsek.terra.config.base.ConfigPack;
-import com.dfsek.terra.config.exception.ConfigException;
-import org.bukkit.Bukkit;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.polydev.gaea.math.FastNoiseLite;
-import org.polydev.gaea.math.ProbabilityCollection;
-import org.polydev.gaea.util.FastRandom;
-import org.polydev.gaea.world.palette.Palette;
-import org.polydev.gaea.world.palette.RandomPalette;
-import org.polydev.gaea.world.palette.SimplexPalette;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-public class PaletteConfig extends TerraConfig {
- private final Palette palette;
- private final String paletteID;
- private boolean useNoise = false;
-
- public PaletteConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
- super(file, config);
- if(!contains("id")) throw new ConfigException("Palette ID unspecified!", "null");
- this.paletteID = getString("id");
- Palette pal;
- if(getBoolean("simplex", false)) {
- useNoise = true;
- FastNoiseLite pNoise = new FastNoiseLite(getInt("seed", 2403));
- pNoise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
- pNoise.setFractalOctaves(4);
- pNoise.setFrequency(getDouble("frequency", 0.02));
- pal = new SimplexPalette<>(pNoise);
- } else pal = new RandomPalette<>(new FastRandom(getInt("seed", 2403)));
- palette = getPalette(getMapList("layers"), pal);
- }
-
- @SuppressWarnings("unchecked")
- protected static Palette getPalette(List