Merge pull request #84 from PolyhedralDev/dev/world-maps

World specific config pack instances
This commit is contained in:
dfsek 2021-03-01 18:41:30 -07:00 committed by GitHub
commit 01396e739c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 594 additions and 278 deletions

View File

@ -23,6 +23,8 @@ dependencies {
"compileOnly"("com.googlecode.json-simple:json-simple:1.1")
"compileOnly"("com.google.guava:guava:30.0-jre")
"testImplementation"("com.google.guava:guava:30.0-jre")
}
publishing {

View File

@ -1,13 +1,15 @@
package com.dfsek.terra.api.event.events.world;
import com.dfsek.terra.api.event.events.Event;
import com.dfsek.terra.api.event.events.PackEvent;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.world.TerraWorld;
/**
* Called upon initialization of a TerraWorld.
*/
public class TerraWorldLoadEvent implements PackEvent {
public class TerraWorldLoadEvent implements Event {
private final TerraWorld world;
public TerraWorldLoadEvent(TerraWorld world) {
@ -18,8 +20,7 @@ public class TerraWorldLoadEvent implements PackEvent {
return world;
}
@Override
public ConfigPack getPack() {
public WorldConfig getPack() {
return world.getConfig();
}
}

View File

@ -15,9 +15,9 @@ import java.util.function.Consumer;
* @param <T> Type in registry
*/
public class LockedRegistry<T> implements Registry<T> {
private final OpenRegistry<T> registry;
private final Registry<T> registry;
public LockedRegistry(OpenRegistry<T> registry) {
public LockedRegistry(Registry<T> registry) {
this.registry = registry;
}

View File

@ -31,7 +31,6 @@ import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer;
import com.dfsek.terra.registry.config.FunctionRegistry;
import com.dfsek.terra.registry.config.LootRegistry;
import com.dfsek.terra.registry.config.ScriptRegistry;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.jafama.FastMath;
@ -49,7 +48,7 @@ public class StructureScript {
private final TerraPlugin main;
private String tempID;
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache, FunctionRegistry functionRegistry) throws ParseException {
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, FunctionRegistry functionRegistry) throws ParseException {
Parser parser;
try {
parser = new Parser(IOUtils.toString(inputStream));
@ -60,7 +59,7 @@ public class StructureScript {
functionRegistry.forEach(parser::registerFunction); // Register registry functions.
parser.registerFunction("block", new BlockFunctionBuilder(main))
.registerFunction("check", new CheckFunctionBuilder(main, cache))
.registerFunction("check", new CheckFunctionBuilder(main))
.registerFunction("structure", new StructureFunctionBuilder(registry, main))
.registerFunction("randomInt", new RandomFunctionBuilder())
.registerFunction("recursions", new RecursionsFunctionBuilder())

View File

@ -12,17 +12,15 @@ import java.util.List;
public class CheckFunctionBuilder implements FunctionBuilder<CheckFunction> {
private final TerraPlugin main;
private final SamplerCache cache;
public CheckFunctionBuilder(TerraPlugin main, SamplerCache cache) {
public CheckFunctionBuilder(TerraPlugin main) {
this.main = main;
this.cache = cache;
}
@SuppressWarnings("unchecked")
@Override
public CheckFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new CheckFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), cache, position);
return new CheckFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
}
@Override

View File

@ -25,22 +25,23 @@ public class CheckFunction implements Function<String> {
private final TerraPlugin main;
private final Returnable<Number> x, y, z;
private final Position position;
private final SamplerCache cache;
public CheckFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, SamplerCache cache, Position position) {
public CheckFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
this.main = main;
this.x = x;
this.y = y;
this.z = z;
this.position = position;
this.cache = cache;
}
@Override
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
@ -52,7 +53,8 @@ public class CheckFunction implements Function<String> {
private String apply(Location vector, World world) {
TerraWorld tw = main.getWorld(world);
double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), world);
SamplerCache cache = tw.getConfig().getSamplerCache();
double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), cache);
if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land.
@ -64,10 +66,10 @@ public class CheckFunction implements Function<String> {
return "OCEAN"; // Below sea level
}
private double sample(int x, int y, int z, World w) {
private double sample(int x, int y, int z, SamplerCache cache) {
int cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 16);
return cache.get(w, x, z).sample(x - (cx << 4), y, z - (cz << 4));
return cache.get(x, z).sample(x - (cx << 4), y, z - (cz << 4));
}
@Override

View File

@ -2,24 +2,28 @@ package com.dfsek.terra.api.util.collections;
import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.util.mutable.MutableInteger;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;
@SuppressWarnings("unchecked")
public class ProbabilityCollection<E> implements Collection<E> {
private final Set<E> cont = new HashSet<>();
protected final Map<E, MutableInteger> cont = new HashMap<>();
private Object[] array = new Object[0];
private int size;
public ProbabilityCollection<E> add(E item, int probability) {
if(!cont.contains(item)) size++;
cont.add(item);
if(!cont.containsKey(item)) size++;
cont.computeIfAbsent(item, i -> new MutableInteger(0)).increment();
int oldLength = array.length;
Object[] newArray = new Object[array.length + probability];
System.arraycopy(array, 0, newArray, 0, array.length); // Expand array.
@ -43,10 +47,35 @@ public class ProbabilityCollection<E> implements Collection<E> {
return (E) array[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)];
}
public <T> ProbabilityCollection<T> map(Function<E, T> mapper, boolean carryNull) {
ProbabilityCollection<T> newCollection = new ProbabilityCollection<>();
newCollection.array = new Object[array.length];
for(int i = 0; i < array.length; i++) {
if(carryNull && array[i] == null) continue;
newCollection.array[i] = mapper.apply((E) array[i]);
}
return newCollection;
}
public int getTotalProbability() {
return array.length;
}
public int getProbability(E item) {
MutableInteger integer = cont.get(item);
return integer == null ? 0 : integer.get();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("[");
cont.forEach((item, prob) -> builder.append(item).append(": ").append(prob).append(", "));
return builder.append("]").toString();
}
@Override
public int size() {
return size;
@ -59,26 +88,26 @@ public class ProbabilityCollection<E> implements Collection<E> {
@Override
public boolean contains(Object o) {
return cont.contains(o);
return cont.containsKey(o);
}
@NotNull
@Override
public Iterator<E> iterator() {
return cont.iterator();
return cont.keySet().iterator();
}
@NotNull
@Override
public Object[] toArray() {
return cont.toArray();
return cont.keySet().toArray();
}
@SuppressWarnings("SuspiciousToArrayCall")
@NotNull
@Override
public <T> T[] toArray(@NotNull T[] a) {
return cont.toArray(a);
return cont.keySet().toArray(a);
}
/**
@ -97,7 +126,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
@Override
public boolean containsAll(@NotNull Collection<?> c) {
return cont.containsAll(c);
return cont.keySet().containsAll(c);
}
@Override
@ -123,7 +152,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
}
public Set<E> getContents() {
return new HashSet<>(cont);
return new HashSet<>(cont.keySet());
}
public static final class Singleton<T> extends ProbabilityCollection<T> {
@ -131,6 +160,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
public Singleton(T single) {
this.single = single;
cont.put(single, new MutableInteger(1));
}
@Override
@ -138,6 +168,12 @@ public class ProbabilityCollection<E> implements Collection<E> {
throw new UnsupportedOperationException();
}
@Override
public <T1> ProbabilityCollection<T1> map(Function<T, T1> mapper, boolean carryNull) {
if(carryNull && single == null) return new Singleton<>(null);
return new Singleton<>(mapper.apply(single));
}
@Override
public T get(Random r) {
return single;

View File

@ -3,17 +3,16 @@ package com.dfsek.terra.api.world.biome;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.config.builder.GeneratorBuilder;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.HashSet;
import java.util.Set;
/**
* Class representing a config-defined biome
*/
public class UserDefinedBiome implements TerraBiome {
private final GeneratorBuilder gen;
private final WorldGenerator gen;
private final ProbabilityCollection<Biome> vanilla;
private final String id;
private final BiomeTemplate config;
@ -21,13 +20,13 @@ public class UserDefinedBiome implements TerraBiome {
private final Set<String> tags;
public UserDefinedBiome(ProbabilityCollection<Biome> vanilla, GeneratorBuilder gen, BiomeTemplate config) {
public UserDefinedBiome(ProbabilityCollection<Biome> vanilla, WorldGenerator gen, BiomeTemplate config) {
this.vanilla = vanilla;
this.gen = gen;
this.id = config.getID();
this.config = config;
this.color = config.getColor();
this.tags = config.getTags() == null ? new HashSet<>() : config.getTags();
this.tags = config.getTags();
tags.add("BIOME:" + id);
}
@ -52,7 +51,7 @@ public class UserDefinedBiome implements TerraBiome {
@Override
public Generator getGenerator(World w) {
return gen.build(w.getSeed());
return gen;
}
@Override
@ -64,4 +63,9 @@ public class UserDefinedBiome implements TerraBiome {
public Set<String> getTags() {
return tags;
}
@Override
public String toString() {
return "{BIOME:" + getID() + "}";
}
}

View File

@ -4,4 +4,8 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeSource {
TerraBiome getBiome(double x, double z);
enum Type {
NOISE
}
}

View File

@ -1,5 +1,6 @@
package com.dfsek.terra.api.world.biome.provider;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.registry.OpenRegistry;
import net.jafama.FastMath;
@ -8,6 +9,7 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { // This provider does not need a seed, so it is its own builder.
private final Map<Color, TerraBiome> colorBiomeMap = new HashMap<>();
@ -15,7 +17,7 @@ public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomePro
private final int resolution;
private final Align align;
public ImageBiomeProvider(OpenRegistry<TerraBiome> registry, BufferedImage image, int resolution, Align align) {
public ImageBiomeProvider(Set<TerraBiome> registry, BufferedImage image, int resolution, Align align) {
this.image = image;
this.resolution = resolution;
this.align = align;

View File

@ -31,7 +31,5 @@ public interface TerraChunkGenerator {
TerraPlugin getMain();
SamplerCache getCache();
Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth);
}

View File

@ -13,6 +13,7 @@ import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
@ -32,6 +33,7 @@ import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.SourceBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.StageBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate;
@ -87,6 +89,7 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(ReplaceListMutatorTemplate.class, ReplaceListMutatorTemplate::new)
.registerLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new)
.registerLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new)
.registerLoader(NoiseSourceTemplate.class, NoiseSourceTemplate::new)
.registerLoader(FunctionTemplate.class, FunctionTemplate::new)
.registerLoader(LinkedHashMap.class, new LinkedHashMapLoader())
.registerLoader(CarverPalette.class, new CarverPaletteLoader())
@ -97,6 +100,7 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object))
.registerLoader(BiomeProvider.Type.class, (t, object, cf) -> BiomeProvider.Type.valueOf((String) object))
.registerLoader(BiomeSource.Type.class, (t, object, cf) -> BiomeSource.Type.valueOf((String) object))
.registerLoader(ImageBiomeProvider.Align.class, (t, object, cf) -> ImageBiomeProvider.Align.valueOf((String) object))
.registerLoader(ExpanderStage.Type.class, (t, object, cf) -> ExpanderStage.Type.valueOf((String) object))
.registerLoader(MutatorStage.Type.class, (t, object, cf) -> MutatorStage.Type.valueOf((String) object))

View File

@ -0,0 +1,10 @@
package com.dfsek.terra.config.builder;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeBuilder extends SeededBuilder<TerraBiome> {
ProbabilityCollection<Biome> getVanillaBiomes();
}

View File

@ -0,0 +1,69 @@
package com.dfsek.terra.config.builder;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class UserDefinedBiomeBuilder implements BiomeBuilder {
private final BiomeTemplate template;
private final ConfigPack pack;
private final Map<Long, UserDefinedBiome> biomeMap = new ConcurrentHashMap<>();
public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) {
this.template = template;
this.pack = pack;
}
@Override
public UserDefinedBiome apply(Long seed) {
synchronized(biomeMap) {
return biomeMap.computeIfAbsent(seed,
s -> {
NoiseSampler noise;
NoiseSampler elevation;
NoiseSampler carving;
Scope varScope = new Scope().withParent(pack.getVarScope());
template.getVariables().forEach(varScope::create);
Map<String, NoiseSeeded> noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap();
Map<String, FunctionTemplate> functionTemplateMap = new HashMap<>(template.getFunctions());
functionTemplateMap.putAll(template.getFunctions());
try {
noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
elevation = template.getElevationEquation() == null ? new ConstantSampler(0) : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
} catch(ParseException e) {
throw new RuntimeException(e);
}
WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlantPalette(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template);
}
);
}
}
@Override
public ProbabilityCollection<Biome> getVanillaBiomes() {
return template.getVanilla();
}
}

View File

@ -0,0 +1,79 @@
package com.dfsek.terra.config.dummy;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import java.io.File;
import java.util.UUID;
public class DummyWorld implements World {
@Override
public Object getHandle() {
throw new UnsupportedOperationException("Cannot get handle of DummyWorld");
}
@Override
public long getSeed() {
return 2403L;
}
@Override
public int getMaxHeight() {
return 155;
}
@Override
public ChunkGenerator getGenerator() {
return () -> (ChunkGenerator) () -> null;
}
@Override
public String getName() {
return "DUMMY";
}
@Override
public UUID getUID() {
return UUID.randomUUID();
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
throw new UnsupportedOperationException("Cannot get chunk in DummyWorld");
}
@Override
public File getWorldFolder() {
throw new UnsupportedOperationException("Cannot get folder of DummyWorld");
}
@Override
public Block getBlockAt(int x, int y, int z) {
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
}
@Override
public Block getBlockAt(Location l) {
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
}
@Override
public Entity spawnEntity(Location location, EntityType entityType) {
throw new UnsupportedOperationException("Cannot spawn entity in DummyWorld");
}
@Override
public int getMinHeight() {
return 0;
}
}

View File

@ -1,18 +1,12 @@
package com.dfsek.terra.config.factories;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.config.builder.GeneratorBuilder;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import java.util.LinkedHashMap;
import java.util.Map;
public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
public class BiomeFactory implements ConfigFactory<BiomeTemplate, BiomeBuilder> {
private final ConfigPack pack;
public BiomeFactory(ConfigPack pack) {
@ -20,32 +14,7 @@ public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
}
@Override
public UserDefinedBiome build(BiomeTemplate template, TerraPlugin main) {
GeneratorBuilder generatorBuilder = new GeneratorBuilder();
generatorBuilder.setElevationEquation(template.getElevationEquation());
generatorBuilder.setNoiseEquation(template.getNoiseEquation());
generatorBuilder.setCarvingEquation(template.getCarvingEquation());
generatorBuilder.setNoiseBuilderMap(pack.getTemplate().getNoiseBuilderMap());
Map<String, FunctionTemplate> functions = new LinkedHashMap<>(pack.getTemplate().getFunctions()); // linked map to preserve order.
functions.putAll(template.getFunctions());
generatorBuilder.setFunctionTemplateMap(functions);
generatorBuilder.setPalettes(template.getPalette());
generatorBuilder.setSlantPalettes(template.getSlantPalette());
Scope vars = new Scope().withParent(pack.getVarScope());
template.getVariables().forEach(vars::create);
generatorBuilder.setVarScope(vars);
generatorBuilder.setInterpolateElevation(template.interpolateElevation());
generatorBuilder.setElevationWeight(template.getElevationWeight());
generatorBuilder.setBiomeNoise(template.getBiomeNoise());
generatorBuilder.setBlendDistance(template.getBlendDistance());
generatorBuilder.setBlendStep(template.getBlendStep());
generatorBuilder.setBlendWeight(template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generatorBuilder, template);
public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) {
return new UserDefinedBiomeBuilder(template, pack);
}
}

View File

@ -11,7 +11,7 @@ import com.dfsek.terra.config.templates.CarverTemplate;
import java.util.Arrays;
import java.util.List;
public class CarverFactory implements TerraFactory<CarverTemplate, UserDefinedCarver> {
public class CarverFactory implements ConfigFactory<CarverTemplate, UserDefinedCarver> {
private final ConfigPack pack;
public CarverFactory(ConfigPack pack) {

View File

@ -4,6 +4,6 @@ import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.terra.api.TerraPlugin;
public interface TerraFactory<C extends ConfigTemplate, O> {
public interface ConfigFactory<C extends ConfigTemplate, O> {
O build(C config, TerraPlugin main) throws LoadException;
}

View File

@ -10,7 +10,7 @@ import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.config.templates.FloraTemplate;
import com.dfsek.terra.world.population.items.flora.TerraFlora;
public class FloraFactory implements TerraFactory<FloraTemplate, Flora> {
public class FloraFactory implements ConfigFactory<FloraTemplate, Flora> {
@Override
public TerraFlora build(FloraTemplate config, TerraPlugin main) {
Palette<BlockData> palette = new NoisePalette<>(new WhiteNoiseSampler(2403), false);

View File

@ -7,7 +7,7 @@ import com.dfsek.terra.world.population.items.ores.DeformedSphereOre;
import com.dfsek.terra.world.population.items.ores.Ore;
import com.dfsek.terra.world.population.items.ores.VanillaOre;
public class OreFactory implements TerraFactory<OreTemplate, Ore> {
public class OreFactory implements ConfigFactory<OreTemplate, Ore> {
@Override
public Ore build(OreTemplate config, TerraPlugin main) {
BlockData m = config.getMaterial();

View File

@ -7,7 +7,7 @@ import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.config.templates.PaletteTemplate;
public class PaletteFactory implements TerraFactory<PaletteTemplate, Palette<BlockData>> {
public class PaletteFactory implements ConfigFactory<PaletteTemplate, Palette<BlockData>> {
@Override
public Palette<BlockData> build(PaletteTemplate config, TerraPlugin main) {
NoisePalette<BlockData> palette = new NoisePalette<>(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2);

View File

@ -4,7 +4,7 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.config.templates.StructureTemplate;
import com.dfsek.terra.world.population.items.TerraStructure;
public class StructureFactory implements TerraFactory<StructureTemplate, TerraStructure> {
public class StructureFactory implements ConfigFactory<StructureTemplate, TerraStructure> {
@Override
public TerraStructure build(StructureTemplate config, TerraPlugin main) {
return new TerraStructure(config.getStructures(), config.getY(), config.getSpawn(), config);

View File

@ -5,7 +5,7 @@ import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.config.templates.TreeTemplate;
import com.dfsek.terra.world.population.items.tree.TerraTree;
public class TreeFactory implements TerraFactory<TreeTemplate, Tree> {
public class TreeFactory implements ConfigFactory<TreeTemplate, Tree> {
@Override
public Tree build(TreeTemplate config, TerraPlugin main) {
return new TerraTree(config.getSpawnable(), config.getyOffset(), config.getStructures());

View File

@ -4,9 +4,9 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import java.lang.reflect.Type;
import java.util.Map;

View File

@ -7,8 +7,10 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.loaders.Types;
import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate;
import java.lang.reflect.Type;
import java.util.Map;
@ -19,12 +21,10 @@ public class SourceBuilderLoader implements TypeLoader<SourceSeeded> {
public SourceSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> source = (Map<String, Object>) c;
String type = source.get("type").toString();
BiomeSource.Type type = loader.loadClass(BiomeSource.Type.class, source.get("type"));
if("NOISE".equals(type)) {
ProbabilityCollection<TerraBiome> sourceBiomes = (ProbabilityCollection<TerraBiome>) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes"));
NoiseSeeded sourceNoise = loader.loadClass(NoiseSeeded.class, source.get("noise"));
return seed -> new RandomSource(sourceBiomes, sourceNoise.apply(seed));
if(type == BiomeSource.Type.NOISE) {
return loader.loadClass(NoiseSourceTemplate.class, source);
}
throw new LoadException("No such loader type: " + type);
}

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
@ -8,7 +8,6 @@ import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.api.world.biome.pipeline.BiomePipeline;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
import java.util.List;
@ -25,8 +24,7 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate {
@Value("pipeline.source")
private SourceSeeded source;
public BiomePipelineTemplate(BiomeRegistry registry, TerraPlugin main) {
super(registry);
public BiomePipelineTemplate(TerraPlugin main) {
this.main = main;
}

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
@ -7,10 +7,8 @@ import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvider.BiomeProviderBuilder>, BiomeProvider.BiomeProviderBuilder {
protected final BiomeRegistry registry;
@Value("resolution")
@Default
protected int resolution = 1;
@ -33,10 +31,6 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvi
@Value("type")
BiomeProvider.Type type;
protected BiomeProviderTemplate(BiomeRegistry registry) {
this.registry = registry;
}
@Override
public BiomeProvider.BiomeProviderBuilder get() {
return this;

View File

@ -0,0 +1,28 @@
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.config.builder.BiomeBuilder;
import java.awt.image.BufferedImage;
import java.util.stream.Collectors;
public class ImageProviderTemplate extends BiomeProviderTemplate {
private final Registry<BiomeBuilder> biomes;
@Value("image.name")
private BufferedImage image;
@Value("image.align")
private ImageBiomeProvider.Align align;
public ImageProviderTemplate(Registry<BiomeBuilder> set) {
this.biomes = set;
}
@Override
public BiomeProvider build(long seed) {
return new ImageBiomeProvider(biomes.entries().stream().map(biomeBuilder -> biomeBuilder.apply(seed)).collect(Collectors.toSet()), image, resolution, align);
}
}

View File

@ -1,17 +1,15 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
public class SingleBiomeProviderTemplate extends BiomeProviderTemplate {
@Value("biome")
private TerraBiome biome;
public SingleBiomeProviderTemplate(BiomeRegistry registry) {
super(registry);
public SingleBiomeProviderTemplate() {
}
@Override

View File

@ -1,25 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
import java.awt.image.BufferedImage;
public class ImageProviderTemplate extends BiomeProviderTemplate {
@Value("image.name")
private BufferedImage image;
@Value("image.align")
private ImageBiomeProvider.Align align;
public ImageProviderTemplate(BiomeRegistry registry) {
super(registry);
}
@Override
public BiomeProvider build(long seed) {
return new ImageBiomeProvider(registry, image, resolution, align);
}
}

View File

@ -0,0 +1,21 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.builder.BiomeBuilder;
public class NoiseSourceTemplate extends SourceTemplate {
@Value("noise")
private NoiseSeeded noise;
@Value("biomes")
private ProbabilityCollection<BiomeBuilder> biomes;
@Override
public BiomeSource apply(Long seed) {
return new RandomSource(biomes.map((biome) -> biome.apply(seed), false), noise.apply(seed));
}
}

View File

@ -0,0 +1,12 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
public abstract class SourceTemplate implements ObjectTemplate<SourceSeeded>, SourceSeeded {
@Override
public SourceSeeded get() {
return this;
}
}

View File

@ -5,9 +5,12 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
public class BorderListMutatorTemplate extends MutatorStageTemplate {
@Value("from")
private String from;
@ -16,14 +19,18 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate {
private String defaultReplace;
@Value("default-to")
private ProbabilityCollection<TerraBiome> defaultTo;
private ProbabilityCollection<BiomeBuilder> defaultTo;
@Value("replace")
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
@Override
public BiomeMutator build(long seed) {
return new BorderListMutator(replace, from, defaultReplace, noise.apply(seed), defaultTo);
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>();
replace.forEach((keyBuilder, replacements) -> replaceMap.put(keyBuilder.apply(seed), replacements.map(replacement -> replacement.apply(seed), true)));
return new BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true));
}
}

View File

@ -2,9 +2,9 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
@SuppressWarnings("unused")
public class BorderMutatorTemplate extends MutatorStageTemplate {
@ -15,10 +15,10 @@ public class BorderMutatorTemplate extends MutatorStageTemplate {
private String replace;
@Value("to")
private ProbabilityCollection<TerraBiome> to;
private ProbabilityCollection<BiomeBuilder> to;
@Override
public BiomeMutator build(long seed) {
return new BorderMutator(from, replace, noise.apply(seed), to);
return new BorderMutator(from, replace, noise.apply(seed), to.map(biomeBuilder -> biomeBuilder.apply(seed), true));
}
}

View File

@ -5,7 +5,9 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
@ -14,13 +16,17 @@ public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
private String defaultFrom;
@Value("default-to")
private ProbabilityCollection<TerraBiome> defaultTo;
private ProbabilityCollection<BiomeBuilder> defaultTo;
@Value("to")
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
@Override
public BiomeMutator build(long seed) {
return new ReplaceListMutator(replace, defaultFrom, defaultTo, noise.apply(seed));
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>();
replace.forEach((biomeBuilder, biomeBuilders) -> replaceMap.put(biomeBuilder.apply(seed), biomeBuilders.map(builder -> builder.apply(seed), true)));
return new ReplaceListMutator(replaceMap, defaultFrom, defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed));
}
}

View File

@ -2,9 +2,9 @@ package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
@SuppressWarnings("unused")
public class ReplaceMutatorTemplate extends MutatorStageTemplate {
@ -12,10 +12,10 @@ public class ReplaceMutatorTemplate extends MutatorStageTemplate {
private String from;
@Value("to")
private ProbabilityCollection<TerraBiome> to;
private ProbabilityCollection<BiomeBuilder> to;
@Override
public BiomeMutator build(long seed) {
return new ReplaceMutator(from, to, noise.apply(seed));
return new ReplaceMutator(from, to.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed));
}
}

View File

@ -17,27 +17,28 @@ import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.dummy.DummyWorld;
import com.dfsek.terra.config.factories.BiomeFactory;
import com.dfsek.terra.config.factories.CarverFactory;
import com.dfsek.terra.config.factories.ConfigFactory;
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.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate;
import com.dfsek.terra.config.templates.AbstractableTemplate;
@ -60,7 +61,7 @@ import com.dfsek.terra.registry.config.PaletteRegistry;
import com.dfsek.terra.registry.config.ScriptRegistry;
import com.dfsek.terra.registry.config.StructureRegistry;
import com.dfsek.terra.registry.config.TreeRegistry;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.TerraStructure;
import com.dfsek.terra.world.population.items.ores.Ore;
import org.apache.commons.io.IOUtils;
@ -106,8 +107,6 @@ public class ConfigPack implements LoaderRegistrar {
private final ConfigLoader selfLoader = new ConfigLoader();
private final Scope varScope = new Scope();
private final SamplerCache samplerCache;
private final TerraPlugin main;
private final Loader loader;
@ -119,7 +118,6 @@ public class ConfigPack implements LoaderRegistrar {
this.loader = new FolderLoader(folder.toPath());
this.main = main;
long l = System.nanoTime();
this.samplerCache = new SamplerCache(main);
floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(main);
@ -148,6 +146,7 @@ public class ConfigPack implements LoaderRegistrar {
main.logger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\"");
throw e;
}
toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately.
}
public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException {
@ -155,7 +154,6 @@ public class ConfigPack implements LoaderRegistrar {
this.loader = new ZIPLoader(file);
this.main = main;
long l = System.nanoTime();
this.samplerCache = new SamplerCache(main);
floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(main);
@ -192,9 +190,11 @@ public class ConfigPack implements LoaderRegistrar {
main.logger().severe("Failed to load config pack from ZIP archive \"" + file.getName() + "\"");
throw e;
}
toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately.
}
public static <C extends AbstractableTemplate, O> void buildAll(TerraFactory<C, O> factory, OpenRegistry<O> registry, List<C> configTemplates, TerraPlugin main) throws LoadException {
public static <C extends AbstractableTemplate, O> void buildAll(ConfigFactory<C, O> factory, OpenRegistry<O> registry, List<C> configTemplates, TerraPlugin main) throws LoadException {
for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main));
}
@ -207,10 +207,10 @@ public class ConfigPack implements LoaderRegistrar {
loader.open("structures/data", ".tesf").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) {
try {
StructureScript structureScript = new StructureScript(entry.getValue(), main, scriptRegistry, lootRegistry, samplerCache, functionRegistry);
try(InputStream stream = entry.getValue()) {
StructureScript structureScript = new StructureScript(stream, main, scriptRegistry, lootRegistry, functionRegistry);
scriptRegistry.add(structureScript.getId(), structureScript);
} catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException e) {
} catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException | IOException e) {
throw new LoadException("Unable to load script \"" + entry.getKey() + "\"", e);
}
}
@ -237,14 +237,6 @@ public class ConfigPack implements LoaderRegistrar {
main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms.");
}
public TerraBiome getBiome(String id) {
return biomeRegistry.get(id);
}
public List<String> getBiomeIDs() {
return biomeRegistry.entries().stream().map(TerraBiome::getID).collect(Collectors.toList());
}
public TerraStructure getStructure(String id) {
return structureRegistry.get(id);
}
@ -270,7 +262,7 @@ public class ConfigPack implements LoaderRegistrar {
public void register(TypeRegistry registry) {
registry
.registerLoader(Palette.class, paletteRegistry)
.registerLoader(TerraBiome.class, biomeRegistry)
.registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(Flora.class, floraRegistry)
.registerLoader(Ore.class, oreRegistry)
.registerLoader(Tree.class, treeRegistry)
@ -280,15 +272,11 @@ public class ConfigPack implements LoaderRegistrar {
.registerLoader(UserDefinedCarver.class, carverRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry))
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry))
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, main))
.registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(main))
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
}
public SamplerCache getSamplerCache() {
return samplerCache;
}
public Set<UserDefinedCarver> getCarvers() {
return carverRegistry.entries();
}
@ -301,7 +289,7 @@ public class ConfigPack implements LoaderRegistrar {
return new CheckedRegistry<>(scriptRegistry);
}
public CheckedRegistry<TerraBiome> getBiomeRegistry() {
public CheckedRegistry<BiomeBuilder> getBiomeRegistry() {
return new CheckedRegistry<>(biomeRegistry);
}
@ -340,4 +328,8 @@ public class ConfigPack implements LoaderRegistrar {
public CheckedRegistry<TerraStructure> getStructureRegistry() {
return new CheckedRegistry<>(structureRegistry);
}
public WorldConfig toWorldConfig(TerraWorld world){
return new WorldConfig(world, this, main);
}
}

View File

@ -0,0 +1,124 @@
package com.dfsek.terra.config.pack;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.registry.OpenRegistry;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.population.items.TerraStructure;
import com.dfsek.terra.world.population.items.ores.Ore;
import java.util.Set;
import java.util.function.Supplier;
public class WorldConfig {
private final LockedRegistry<StructureScript> scriptRegistry;
private final LockedRegistry<TerraBiome> biomeRegistry;
private final SamplerCache samplerCache;
private final LockedRegistry<UserDefinedCarver> carverRegistry;
private final LockedRegistry<Tree> treeRegistry;
private final LockedRegistry<Flora> floraRegistry;
private final LockedRegistry<LootTable> lootRegistry;
private final LockedRegistry<Ore> oreRegistry;
private final LockedRegistry<Palette<BlockData>> paletteRegistry;
private final LockedRegistry<TerraStructure> structureRegistry;
private final BiomeProvider provider;
private final TerraWorld world;
private final ConfigPack pack;
public WorldConfig(TerraWorld world, ConfigPack pack, TerraPlugin main) {
this.world = world;
this.pack = pack;
this.samplerCache = new SamplerCache(main, world);
this.scriptRegistry = new LockedRegistry<>(pack.getScriptRegistry());
OpenRegistry<TerraBiome> biomeOpenRegistry = new OpenRegistry<>();
pack.getBiomeRegistry().forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed())));
this.biomeRegistry = new LockedRegistry<>(biomeOpenRegistry);
this.carverRegistry = new LockedRegistry<>(pack.getCarverRegistry());
this.treeRegistry = new LockedRegistry<>(pack.getTreeRegistry());
this.floraRegistry = new LockedRegistry<>(pack.getFloraRegistry());
this.lootRegistry = new LockedRegistry<>(pack.getLootRegistry());
this.oreRegistry = new LockedRegistry<>(pack.getOreRegistry());
this.paletteRegistry = new LockedRegistry<>(pack.getPaletteRegistry());
this.structureRegistry = new LockedRegistry<>(pack.getStructureRegistry());
this.provider = pack.getBiomeProviderBuilder().build(world.getWorld().getSeed());
}
public TerraWorld getWorld() {
return world;
}
public SamplerCache getSamplerCache() {
return samplerCache;
}
public Set<UserDefinedCarver> getCarvers() {
return carverRegistry.entries();
}
public LockedRegistry<StructureScript> getScriptRegistry() {
return scriptRegistry;
}
public LockedRegistry<TerraBiome> getBiomeRegistry() {
return biomeRegistry;
}
public LockedRegistry<Tree> getTreeRegistry() {
return treeRegistry;
}
public LockedRegistry<UserDefinedCarver> getCarverRegistry() {
return carverRegistry;
}
public LockedRegistry<Flora> getFloraRegistry() {
return floraRegistry;
}
public LockedRegistry<LootTable> getLootRegistry() {
return lootRegistry;
}
public LockedRegistry<Ore> getOreRegistry() {
return oreRegistry;
}
public LockedRegistry<Palette<BlockData>> getPaletteRegistry() {
return paletteRegistry;
}
public LockedRegistry<TerraStructure> getStructureRegistry() {
return structureRegistry;
}
public BiomeProvider getProvider() {
return provider;
}
public Set<TerraStructure> getStructures() {
return structureRegistry.entries();
}
public ConfigPackTemplate getTemplate() {
return pack.getTemplate();
}
}

View File

@ -31,6 +31,7 @@ import com.dfsek.terra.world.population.items.ores.OreHolder;
import com.dfsek.terra.world.population.items.tree.TreeLayer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -182,7 +183,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Value("tags")
@Default
@Abstractable
private Set<String> tags;
private Set<String> tags = new HashSet<>();
@Value("carving")
@Abstractable

View File

@ -17,7 +17,7 @@ import java.util.function.Consumer;
* Registry implementation with read/write access. For internal use only.
* @param <T>
*/
public abstract class OpenRegistry<T> implements Registry<T> {
public class OpenRegistry<T> implements Registry<T> {
private final Map<String, T> objects = new HashMap<>();
@Override

View File

@ -2,16 +2,16 @@ package com.dfsek.terra.registry.config;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.registry.OpenRegistry;
import java.lang.reflect.Type;
public class BiomeRegistry extends OpenRegistry<TerraBiome> {
public class BiomeRegistry extends OpenRegistry<BiomeBuilder> {
@Override
public TerraBiome load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
public BiomeBuilder load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
if(o.equals("SELF")) return null;
TerraBiome biome = get((String) o);
BiomeBuilder biome = get((String) o);
if(biome == null)
throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry.");
return biome;

View File

@ -12,13 +12,14 @@ import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.profiler.WorldProfiler;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import net.jafama.FastMath;
public class TerraWorld {
private final BiomeProvider provider;
private final ConfigPack config;
private final WorldConfig config;
private final boolean safe;
private final WorldProfiler profiler;
private final World world;
@ -27,11 +28,10 @@ public class TerraWorld {
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
if(!isTerraWorld(w)) throw new IllegalArgumentException("World " + w + " is not a Terra World!");
c.getBiomeRegistry().forEach(biome -> biome.getGenerator(w)); // Load all gens to cache
config = c;
profiler = new WorldProfiler(w);
this.provider = config.getBiomeProviderBuilder().build(w.getSeed());
this.world = w;
config = c.toWorldConfig(this);
this.provider = config.getProvider();
profiler = new WorldProfiler(w);
air = main.getWorldHandle().createBlockData("minecraft:air");
main.getEventManager().callEvent(new TerraWorldLoadEvent(this));
safe = true;
@ -53,7 +53,7 @@ public class TerraWorld {
return provider;
}
public ConfigPack getConfig() {
public WorldConfig getConfig() {
return config;
}
@ -76,7 +76,7 @@ public class TerraWorld {
public BlockData getUngeneratedBlock(int x, int y, int z) {
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(x, z);
Palette<BlockData> palette = biome.getGenerator(world).getPalette(y);
Sampler sampler = config.getSamplerCache().get(world, x, z);
Sampler sampler = config.getSamplerCache().get(x, z);
int fdX = FastMath.floorMod(x, 16);
int fdZ = FastMath.floorMod(z, 16);
double noise = sampler.sample(fdX, y, fdZ);

View File

@ -86,7 +86,7 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
Sampler sampler = cache.getChunk(world, chunkX, chunkZ);
Sampler sampler = cache.getChunk(chunkX, chunkZ);
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
@ -121,11 +121,6 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
DefaultChunkGenerator3D.biomes(world, chunkX, chunkZ, biome, main);
}
@Override
public SamplerCache getCache() {
return cache;
}
@Override
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth);

View File

@ -26,7 +26,6 @@ import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.world.Carver;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.carving.NoiseCarver;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.generation.math.samplers.Sampler3D;
import org.jetbrains.annotations.NotNull;
@ -42,16 +41,14 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
private final Carver carver;
private final SamplerCache cache;
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main, SamplerCache cache) {
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) {
this.configPack = c;
this.main = main;
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
water = main.getWorldHandle().createBlockData("minecraft:water").getBlockType();
blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air"));
this.cache = cache;
}
@Override
@ -99,7 +96,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
Sampler sampler = cache.getChunk(world, chunkX, chunkZ);
Sampler sampler = tw.getConfig().getSamplerCache().getChunk(chunkX, chunkZ);
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
@ -235,11 +232,6 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
biomes(world, chunkX, chunkZ, biome, main);
}
@Override
public SamplerCache getCache() {
return cache;
}
@Override
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth);

View File

@ -16,45 +16,18 @@ import java.util.HashMap;
import java.util.Map;
public class SamplerCache {
private final Map<Long, Container> containerMap;
private final TerraPlugin main;
public SamplerCache(TerraPlugin main) {
containerMap = Collections.synchronizedMap(new HashMap<>());
this.main = main;
}
public Sampler get(World world, int x, int z) {
synchronized(containerMap) {
return containerMap.computeIfAbsent(world.getSeed(), seed -> new Container(world)).get(x, z);
}
}
public Sampler getChunk(World world, int chunkX, int chunkZ) {
synchronized(containerMap) {
return containerMap.computeIfAbsent(world.getSeed(), seed -> new Container(world)).getChunk(chunkX, chunkZ);
}
}
public void clear() {
containerMap.clear();
}
private final class Container {
private final TerraWorld terraWorld;
private final LoadingCache<Long, Sampler> cache;
private Container(World world) {
public SamplerCache(TerraPlugin main, TerraWorld world) {
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache())
.build(new CacheLoader<Long, Sampler>() {
@Override
public Sampler load(@NotNull Long key) {
int cx = (int) (key >> 32);
int cz = (int) key.longValue();
return terraWorld.getGenerator().createSampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getElevationBlend());
return world.getGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend());
}
});
terraWorld = main.getWorld(world);
}
public Sampler get(int x, int z) {
@ -67,5 +40,9 @@ public class SamplerCache {
long key = MathUtil.squash(cx, cz);
return cache.getUnchecked(key);
}
public void clear() {
cache.invalidateAll();
cache.cleanUp();
}
}

View File

@ -12,6 +12,7 @@ import com.dfsek.terra.api.util.world.PopulationUtil;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.config.templates.CarverTemplate;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.world.TerraWorld;
@ -40,7 +41,7 @@ public class CavePopulator implements TerraBlockPopulator {
try(ProfileFuture ignored = tw.getProfiler().measure("CaveTime")) {
Random random = PopulationUtil.getRandom(chunk);
if(!tw.isSafe()) return;
ConfigPack config = tw.getConfig();
WorldConfig config = tw.getConfig();
for(UserDefinedCarver c : config.getCarvers()) {
CarverTemplate template = c.getConfig();

View File

@ -11,6 +11,7 @@ import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.TerraStructure;
@ -35,7 +36,7 @@ public class StructurePopulator implements TerraBlockPopulator {
int cz = (chunk.getZ() << 4);
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
ConfigPack config = tw.getConfig();
WorldConfig config = tw.getConfig();
for(TerraStructure conf : config.getStructures()) {
Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world);

View File

@ -27,14 +27,15 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
@ -144,11 +145,11 @@ public class DistributionTest {
private static BiomeProvider getProvider(long seed) throws ConfigException, IOException {
System.out.println(seed);
File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/betterend/");
File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/");
FolderLoader folderLoader = new FolderLoader(pack.toPath());
AbstractConfigLoader loader = new AbstractConfigLoader();
new GenericLoaders(null).register(loader);
new GenericLoaders(MAIN).register(loader);
BiomeRegistry biomeRegistry = new BiomeRegistry();
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), MAIN));
@ -157,12 +158,12 @@ public class DistributionTest {
ConfigLoader pipeLoader = new ConfigLoader()
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
.registerLoader(TerraBiome.class, biomeRegistry)
.registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader))
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry))
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, MAIN))
.registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(MAIN))
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
new GenericLoaders(null).register(pipeLoader);
new GenericLoaders(MAIN).register(pipeLoader);
pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NoiseRegistry()));
@ -285,7 +286,7 @@ public class DistributionTest {
}
}
private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate {
private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate, BiomeBuilder {
@Value("color")
@Default
@ -336,5 +337,10 @@ public class DistributionTest {
public String toString() {
return id;
}
@Override
public TestBiome apply(Long aLong) {
return this;
}
}
}

View File

@ -48,7 +48,7 @@ public class ImageTest {
};
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), null));
return new ImageBiomeProvider(biomeRegistry, ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
}
@Test

View File

@ -92,7 +92,7 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
boolean succeed = registry.loadAll(this);
Map<World, TerraWorld> newMap = new HashMap<>();
worldMap.forEach((world, tw) -> {
((BukkitChunkGeneratorWrapper) world.getGenerator().getHandle()).getHandle().getCache().clear();
tw.getConfig().getSamplerCache().clear();
String packID = tw.getConfig().getTemplate().getID();
newMap.put(world, new TerraWorld(world, registry.get(packID), this));
});
@ -218,7 +218,7 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
if(!registry.contains(id)) throw new IllegalArgumentException("No such config pack \"" + id + "\"");
ConfigPack pack = registry.get(id);
worlds.put(worldName, pack);
return new DefaultChunkGenerator3D(registry.get(id), this, pack.getSamplerCache());
return new DefaultChunkGenerator3D(registry.get(id), this);
}));
}

View File

@ -6,6 +6,7 @@ import com.dfsek.terra.bukkit.command.WorldCommand;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.TerraStructure;
@ -15,6 +16,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -27,10 +29,10 @@ public class BiomeInfoCommand extends WorldCommand {
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
String id = args[0];
ConfigPack cfg = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig();
WorldConfig cfg = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig();
UserDefinedBiome b;
try {
b = (UserDefinedBiome) cfg.getBiome(id);
b = (UserDefinedBiome) cfg.getBiomeRegistry().get(id);
} catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.biome.invalid", new BukkitCommandSender(sender), id);
return true;
@ -74,7 +76,9 @@ public class BiomeInfoCommand extends WorldCommand {
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld())))
return Collections.emptyList();
List<String> ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeIDs();
List<String> ids = new ArrayList<>();
getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeRegistry().forEach((id, biome) -> ids.add(id));
if(args.length == 1)
return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());
return Collections.emptyList();

View File

@ -21,6 +21,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -44,7 +45,7 @@ public class BiomeLocateCommand extends WorldCommand {
}
TerraBiome b;
try {
b = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getBiome(id);
b = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getBiomeRegistry().get(id);
} catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.biome.invalid", BukkitAdapter.adapt(sender), id);
return true;
@ -84,7 +85,9 @@ public class BiomeLocateCommand extends WorldCommand {
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld())))
return Collections.emptyList();
List<String> ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeIDs();
List<String> ids = new ArrayList<>();
getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getBiomeRegistry().forEach((id, biome) -> ids.add(id));
if(args.length == 1)
return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());
return Collections.emptyList();

View File

@ -21,6 +21,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@ -46,7 +47,7 @@ public class LocateCommand extends WorldCommand {
}
TerraStructure s;
try {
s = Objects.requireNonNull(getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getStructure(id));
s = Objects.requireNonNull(getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getStructureRegistry().get(id));
} catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.structure.invalid", BukkitAdapter.adapt(sender), id);
return true;
@ -90,7 +91,9 @@ public class LocateCommand extends WorldCommand {
if(!(sender instanceof Player) || !(TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld()))))
return Collections.emptyList();
List<String> ids = getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getStructureIDs();
List<String> ids = new ArrayList<>();
getMain().getWorld(BukkitAdapter.adapt(((Player) sender).getWorld())).getConfig().getStructureRegistry().forEach((id, struct) -> ids.add(id));
if(args.length == 1)
return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());

View File

@ -34,7 +34,7 @@ public class SpawnCommand extends WorldCommand implements DebugCommand {
int z = p.getBlockZ();
Position dummy = new Position(0, 0);
com.dfsek.terra.api.platform.world.World w = BukkitAdapter.adapt(world);
String check = new CheckFunction(getMain(), new NumericConstant(0, dummy), new NumericConstant(0, dummy), new NumericConstant(0, dummy), getMain().getWorld(w).getConfig().getSamplerCache(), dummy).apply(new TerraImplementationArguments(new StructureBuffer(
String check = new CheckFunction(getMain(), new NumericConstant(0, dummy), new NumericConstant(0, dummy), new NumericConstant(0, dummy), dummy).apply(new TerraImplementationArguments(new StructureBuffer(
new com.dfsek.terra.api.math.vector.Location(w, x, y, z)
), Rotation.NONE, new FastRandom(), 0), new HashMap<>());

View File

@ -9,6 +9,7 @@ import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.world.TerraWorld;
import org.bukkit.Material;
import org.bukkit.TreeType;
@ -46,7 +47,7 @@ public class CommonListener implements Listener {
World bukkit = BukkitAdapter.adapt(e.getWorld());
if(!TerraWorld.isTerraWorld(bukkit)) return;
TerraWorld tw = main.getWorld(bukkit);
ConfigPack c = tw.getConfig();
WorldConfig c = tw.getConfig();
if(c.getTemplate().isDisableSaplings()) return;
e.setCancelled(true);
Block block = e.getLocation().getBlock();

View File

@ -23,7 +23,7 @@ public class PaperListener implements Listener {
String name = "minecraft:" + e.getType().getName();
main.getDebugLogger().info("Overriding structure location for \"" + name + "\"");
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getWorld()));
TerraStructure config = tw.getConfig().getStructure(tw.getConfig().getTemplate().getLocatable().get(name));
TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get(name));
if(config != null) {
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getOrigin()), 0, 500, location -> {
if(location != null)

View File

@ -37,7 +37,7 @@ public class SpigotListener implements Listener {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld()));
EnderSignal signal = (EnderSignal) entity;
TerraStructure config = tw.getConfig().getStructure(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD"));
TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD"));
if(config != null) {
main.getDebugLogger().info("Overriding Ender Signal...");
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> {

View File

@ -22,10 +22,10 @@ import com.dfsek.terra.api.transform.NotNullValidator;
import com.dfsek.terra.api.transform.Transformer;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.Logger;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
@ -75,6 +75,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@ -218,11 +219,11 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
.registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new FabricBiome(biomeFixer.translate((String) o)));
}
public static String createBiomeID(ConfigPack pack, TerraBiome biome) {
return pack.getTemplate().getID().toLowerCase() + "/" + biome.getID().toLowerCase();
public static String createBiomeID(ConfigPack pack, String biomeID) {
return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT);
}
private Biome createBiome(TerraBiome biome) {
private Biome createBiome(BiomeBuilder biome) {
SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder();
DefaultBiomeFeatures.addFarmAnimals(spawnSettings);
DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100);
@ -282,14 +283,12 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
RegistryKey<ConfiguredFeature<?, ?>> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_WORLDGEN, new Identifier("terra", "flora_populator"));
Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE);
registry.forEach(pack -> pack.getBiomeRegistry().forEach(biome -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", createBiomeID(pack, biome)), createBiome(biome)))); // Register all Terra biomes.
registry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", createBiomeID(pack, id)), createBiome(biome)))); // Register all Terra biomes.
Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC);
Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC);
if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
registry.forEach(pack -> {
System.out.println(pack.getTemplate().getID());
pack.getBiomeRegistry().forEach(b -> System.out.println(b.getID()));
final GeneratorType generatorType = new GeneratorType("terra." + pack.getTemplate().getID()) {
@Override
protected ChunkGenerator getChunkGenerator(Registry<Biome> biomeRegistry, Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry, long seed) {

View File

@ -50,8 +50,8 @@ public class TerraBiomeSource extends BiomeSource {
@Override
public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) {
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX * 4, biomeZ * 4);
return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome)));
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2);
return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome.getID())));
}

View File

@ -78,7 +78,7 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements com.d
super(biomeSource, new StructuresConfig(false));
this.pack = configPack;
this.delegate = new DefaultChunkGenerator3D(pack, TerraFabricPlugin.getInstance(), pack.getSamplerCache());
this.delegate = new DefaultChunkGenerator3D(pack, TerraFabricPlugin.getInstance());
delegate.getMain().logger().info("Loading world with config pack " + pack.getTemplate().getID());
this.biomeSource = biomeSource;

View File

@ -1,6 +1,7 @@
package com.dfsek.terra.region;
import com.dfsek.terra.StandalonePlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.platform.DirectChunkData;
import com.dfsek.terra.platform.DirectWorld;
import com.dfsek.terra.platform.GenWrapper;
@ -31,7 +32,7 @@ public class Generator {
structurePopulator = new StructurePopulator(plugin);
treePopulator = new TreePopulator(plugin);
orePopulator = new OrePopulator(plugin);
generator = new DefaultChunkGenerator3D(plugin.getConfigRegistry().get("DEFAULT"), plugin, new SamplerCache(plugin));
generator = new DefaultChunkGenerator3D(plugin.getConfigRegistry().get("DEFAULT"), plugin);
this.seed = seed;
}