Implement structure biome config

This commit is contained in:
dfsek 2020-09-29 02:11:55 -07:00
parent eb208ed9fe
commit 114a9302bc
9 changed files with 70 additions and 64 deletions

View File

@ -32,6 +32,7 @@ public class Terra extends JavaPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
instance = this;
ConfigUtil.loadConfig(this); ConfigUtil.loadConfig(this);
PluginCommand command = getCommand("terra"); PluginCommand command = getCommand("terra");
@ -47,7 +48,7 @@ public class Terra extends JavaPlugin {
saveDefaultConfig(); saveDefaultConfig();
config = getConfig(); config = getConfig();
Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, TerraChunkGenerator::saveAll, ConfigUtil.dataSave, ConfigUtil.dataSave); Bukkit.getScheduler().scheduleAsyncRepeatingTask(this, TerraChunkGenerator::saveAll, ConfigUtil.dataSave, ConfigUtil.dataSave);
instance = this;
} }
public static void register(JavaPlugin plugin, Command pluginCommand, Commodore commodore) throws Exception { public static void register(JavaPlugin plugin, Command pluginCommand, Commodore commodore) throws Exception {

View File

@ -41,9 +41,9 @@ public class ConfigUtil {
new ConfigLoader("flora").load(main, FloraConfig.class); new ConfigLoader("flora").load(main, FloraConfig.class);
new ConfigLoader("abstract" + File.separator + "biomes").load(main, AbstractBiomeConfig.class); new ConfigLoader("structures" + File.separator + "single").load(main, StructureConfig.class);
new ConfigLoader("structure" + File.separator + "single").load(main, StructureConfig.class); new ConfigLoader("abstract" + File.separator + "biomes").load(main, AbstractBiomeConfig.class);
TerraBiomeGrid.invalidate(); TerraBiomeGrid.invalidate();
BiomeZone.invalidate(); // Invalidate BiomeZone and BiomeGrid caches to prevent old instances from being accessed. BiomeZone.invalidate(); // Invalidate BiomeZone and BiomeGrid caches to prevent old instances from being accessed.

View File

@ -48,6 +48,7 @@ public class AbstractBiomeConfig extends TerraConfigObject {
private Map<String, Object> oreData; private Map<String, Object> oreData;
private Map<String, Object> treeData; private Map<String, Object> treeData;
private List<Map<?, ?>> carvingData; private List<Map<?, ?>> carvingData;
private List<String> structureConfigs;
public AbstractBiomeConfig(File file) throws IOException, InvalidConfigurationException { public AbstractBiomeConfig(File file) throws IOException, InvalidConfigurationException {
super(file); super(file);
@ -90,6 +91,8 @@ public class AbstractBiomeConfig extends TerraConfigObject {
} }
} }
if(contains("structures")) structureConfigs = getStringList("structures");
biomes.put(biomeID, this); biomes.put(biomeID, this);
} }
@ -177,4 +180,8 @@ public class AbstractBiomeConfig extends TerraConfigObject {
public String getOceanPalette() { public String getOceanPalette() {
return oceanPalette; return oceanPalette;
} }
public List<String> getStructureConfigs() {
return structureConfigs;
}
} }

View File

@ -55,6 +55,7 @@ public class BiomeConfig extends TerraConfigObject {
private FastNoise floraNoise; private FastNoise floraNoise;
private Palette<BlockData> ocean; private Palette<BlockData> ocean;
private int seaLevel; private int seaLevel;
private List<StructureConfig> structures;
public BiomeConfig(File file) throws InvalidConfigurationException, IOException { public BiomeConfig(File file) throws InvalidConfigurationException, IOException {
super(file); super(file);
@ -335,6 +336,19 @@ public class BiomeConfig extends TerraConfigObject {
Bukkit.getLogger().info("[Terra] Slabs: " + slabs.size()); Bukkit.getLogger().info("[Terra] Slabs: " + slabs.size());
} }
// Structure stuff
structures = new ArrayList<>();
List<String> st = new ArrayList<>();
if(abstractBiome != null && abstractBiome.getStructureConfigs() != null) st = abstractBiome.getStructureConfigs();
if(contains("structures")) st = getStringList("structures");
for(String s : st) {
try {
structures.add(Objects.requireNonNull(StructureConfig.fromID(s)));
} catch(NullPointerException e) {
throw new InvalidConfigurationException("No such structure " + s);
}
}
try { try {
// Get UserDefinedBiome instance representing this config. // Get UserDefinedBiome instance representing this config.
this.biome = new UserDefinedBiome(vanillaBiome, dec, new UserDefinedGenerator(eq, Collections.emptyList(), paletteMap), biomeID); this.biome = new UserDefinedBiome(vanillaBiome, dec, new UserDefinedGenerator(eq, Collections.emptyList(), paletteMap), biomeID);
@ -427,4 +441,8 @@ public class BiomeConfig extends TerraConfigObject {
public int getSeaLevel() { public int getSeaLevel() {
return seaLevel; return seaLevel;
} }
public List<StructureConfig> getStructures() {
return structures;
}
} }

View File

@ -2,18 +2,23 @@ package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.Range; import com.dfsek.terra.Range;
import com.dfsek.terra.Terra; import com.dfsek.terra.Terra;
import com.dfsek.terra.config.ConfigUtil;
import com.dfsek.terra.config.TerraConfigObject; import com.dfsek.terra.config.TerraConfigObject;
import com.dfsek.terra.population.StructurePopulator; import com.dfsek.terra.population.StructurePopulator;
import com.dfsek.terra.structure.GaeaStructure; import com.dfsek.terra.structure.GaeaStructure;
import com.dfsek.terra.structure.StructureSpawn; import com.dfsek.terra.structure.StructureSpawn;
import com.dfsek.terra.structure.StructureSpawnRequirement; import com.dfsek.terra.structure.StructureSpawnRequirement;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
public class StructureConfig extends TerraConfigObject { public class StructureConfig extends TerraConfigObject {
private static final Map<String, StructureConfig> configs = new HashMap<>();
private GaeaStructure structure; private GaeaStructure structure;
private StructureSpawn spawn; private StructureSpawn spawn;
private String id; private String id;
@ -27,8 +32,12 @@ public class StructureConfig extends TerraConfigObject {
@Override @Override
public void init() throws InvalidConfigurationException { public void init() throws InvalidConfigurationException {
try { try {
structure = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "config" + File.separator + "structures" + File.separator + "data", Objects.requireNonNull(getString("file")))); File file = new File(Terra.getInstance().getDataFolder() + File.separator + "config" + File.separator + "structures" + File.separator + "data", Objects.requireNonNull(getString("file")));
structure = GaeaStructure.load(file);
} catch(IOException | NullPointerException e) { } catch(IOException | NullPointerException e) {
if(ConfigUtil.debug) {
e.printStackTrace();
}
throw new InvalidConfigurationException("Unable to locate structure: " + getString("file")); throw new InvalidConfigurationException("Unable to locate structure: " + getString("file"));
} }
if(!contains("id")) throw new InvalidConfigurationException("No ID specified!"); if(!contains("id")) throw new InvalidConfigurationException("No ID specified!");
@ -37,10 +46,11 @@ public class StructureConfig extends TerraConfigObject {
searchStart = new Range(getInt("spawn.start.min", 72), getInt("spawn.start.max", 72)); searchStart = new Range(getInt("spawn.start.min", 72), getInt("spawn.start.max", 72));
bound = new Range(getInt("spawn.bound.min", 48), getInt("spawn.bound.max", 72)); bound = new Range(getInt("spawn.bound.min", 48), getInt("spawn.bound.max", 72));
try { try {
type = StructurePopulator.SearchType.valueOf(getString("spawn,search", "DOWN")); type = StructurePopulator.SearchType.valueOf(getString("spawn.search", "DOWN"));
} catch(IllegalArgumentException e) { } catch(IllegalArgumentException e) {
throw new InvalidConfigurationException("Invalid search type, " + getString("spawn,search")); throw new InvalidConfigurationException("Invalid search type, " + getString("spawn.search"));
} }
configs.put(id, this);
} }
@Override @Override
@ -63,4 +73,8 @@ public class StructureConfig extends TerraConfigObject {
public Range getSearchStart() { public Range getSearchStart() {
return searchStart; return searchStart;
} }
public static StructureConfig fromID(String id) {
return configs.get(id);
}
} }

View File

@ -120,12 +120,7 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
@Override @Override
public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) { public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
try {
return Arrays.asList(new CavePopulator(), new StructurePopulator(), popMan); return Arrays.asList(new CavePopulator(), new StructurePopulator(), popMan);
} catch(IOException e) {
e.printStackTrace();
throw new IllegalArgumentException();
}
} }
@Override @Override

View File

@ -1,14 +1,10 @@
package com.dfsek.terra.generation; package com.dfsek.terra.generation;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.UserDefinedGrid;
import com.dfsek.terra.math.NoiseFunction2; import com.dfsek.terra.math.NoiseFunction2;
import com.dfsek.terra.math.NoiseFunction3; import com.dfsek.terra.math.NoiseFunction3;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.polydev.gaea.biome.Generator; import org.polydev.gaea.biome.Generator;
import org.polydev.gaea.generation.GenerationPhase;
import org.polydev.gaea.math.FastNoise; import org.polydev.gaea.math.FastNoise;
import org.polydev.gaea.math.parsii.eval.Expression; import org.polydev.gaea.math.parsii.eval.Expression;
import org.polydev.gaea.math.parsii.eval.Parser; import org.polydev.gaea.math.parsii.eval.Parser;
@ -94,5 +90,4 @@ public class UserDefinedGenerator extends Generator {
} }
return null; return null;
} }
} }

View File

@ -1,29 +0,0 @@
package com.dfsek.terra.math;
import org.polydev.gaea.math.FastNoise;
import org.polydev.gaea.math.parsii.eval.Expression;
import org.polydev.gaea.math.parsii.eval.Function;
import java.util.List;
public class BaseHeightFunction implements Function {
private FastNoise gen;
@Override
public int getNumberOfArguments() {
return 3;
}
@Override
public double eval(List<Expression> list) {
return gen.getSimplexFractal((float) list.get(0).evaluate(), (float) list.get(1).evaluate(), (float) list.get(2).evaluate());
}
public void setNoise(FastNoise gen) {
this.gen = gen;
}
@Override
public boolean isNaturalFunction() {
return true;
}
}

View File

@ -2,6 +2,10 @@ package com.dfsek.terra.population;
import com.dfsek.terra.Terra; import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraProfiler; import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.genconfig.BiomeConfig;
import com.dfsek.terra.config.genconfig.StructureConfig;
import com.dfsek.terra.structure.GaeaStructure; import com.dfsek.terra.structure.GaeaStructure;
import com.dfsek.terra.structure.StructureSpawn; import com.dfsek.terra.structure.StructureSpawn;
import com.dfsek.terra.structure.StructureSpawnRequirement; import com.dfsek.terra.structure.StructureSpawnRequirement;
@ -11,6 +15,7 @@ import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.polydev.gaea.generation.GenerationPhase;
import org.polydev.gaea.population.GaeaBlockPopulator; import org.polydev.gaea.population.GaeaBlockPopulator;
import org.polydev.gaea.profiler.ProfileFuture; import org.polydev.gaea.profiler.ProfileFuture;
@ -23,33 +28,33 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
public class StructurePopulator extends BlockPopulator { public class StructurePopulator extends BlockPopulator {
StructureSpawn spawnTest = new StructureSpawn(75, 25);
GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", "desert.tstructure"));
double horizontal = struc.getStructureInfo().getMaxHorizontal();
public StructurePopulator() throws IOException {
}
@Override @Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) { public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("StructureTime")) { try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("StructureTime")) {
int cx = (chunk.getX() << 4); int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4); int cz = (chunk.getZ() << 4);
Location spawn = spawnTest.getNearestSpawn(cx+ 8, cz + 8, world.getSeed()).toLocation(world); UserDefinedBiome b = (UserDefinedBiome) TerraBiomeGrid.fromWorld(world).getBiome(cx+ 8, cz + 8, GenerationPhase.POPULATE);
main: for(int y = 72; y > 0; y--) { structure: for(StructureConfig conf : BiomeConfig.fromBiome(b).getStructures()) {
GaeaStructure struc = conf.getStructure();
Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world);
Random r2 = new Random(spawn.hashCode());
main: for(int y = conf.getSearchStart().get(r2); y > 0; y--) {
if(y > conf.getBound().getMax() || y < conf.getBound().getMin()) continue structure;
spawn.setY(y); spawn.setY(y);
for(StructureSpawnRequirement s : struc.getSpawns()) { for(StructureSpawnRequirement s : struc.getSpawns()) {
if(!s.isValidSpawn(spawn)) continue main; if(! s.isValidSpawn(spawn)) continue main;
} }
double horizontal = struc.getStructureInfo().getMaxHorizontal();
Bukkit.getLogger().info("Valid spawn at " + spawn); Bukkit.getLogger().info("Valid spawn at " + spawn);
if(Math.abs((cx+8)-spawn.getBlockX()) <= horizontal && Math.abs((cz+8)-spawn.getBlockZ()) <= horizontal) { if(Math.abs((cx + 8) - spawn.getBlockX()) <= horizontal && Math.abs((cz + 8) - spawn.getBlockZ()) <= horizontal) {
try(ProfileFuture ignore = TerraProfiler.fromWorld(world).measure("StructurePasteTime")) { try(ProfileFuture ignore = TerraProfiler.fromWorld(world).measure("StructurePasteTime")) {
struc.paste(spawn, chunk, GaeaStructure.Rotation.fromDegrees(new Random(spawn.hashCode()).nextInt(4)*90), Collections.emptyList()); struc.paste(spawn, chunk, GaeaStructure.Rotation.fromDegrees(r2.nextInt(4) * 90), Collections.emptyList());
break; break;
} }
} }
} }
}
} }
} }
public enum SearchType { public enum SearchType {