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.googlecode.json-simple:json-simple:1.1")
"compileOnly"("com.google.guava:guava:30.0-jre") "compileOnly"("com.google.guava:guava:30.0-jre")
"testImplementation"("com.google.guava:guava:30.0-jre")
} }
publishing { publishing {

View File

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

View File

@ -15,9 +15,9 @@ import java.util.function.Consumer;
* @param <T> Type in registry * @param <T> Type in registry
*/ */
public class LockedRegistry<T> implements Registry<T> { 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; 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.FunctionRegistry;
import com.dfsek.terra.registry.config.LootRegistry; import com.dfsek.terra.registry.config.LootRegistry;
import com.dfsek.terra.registry.config.ScriptRegistry; 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.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import net.jafama.FastMath; import net.jafama.FastMath;
@ -49,7 +48,7 @@ public class StructureScript {
private final TerraPlugin main; private final TerraPlugin main;
private String tempID; 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; Parser parser;
try { try {
parser = new Parser(IOUtils.toString(inputStream)); parser = new Parser(IOUtils.toString(inputStream));
@ -60,7 +59,7 @@ public class StructureScript {
functionRegistry.forEach(parser::registerFunction); // Register registry functions. functionRegistry.forEach(parser::registerFunction); // Register registry functions.
parser.registerFunction("block", new BlockFunctionBuilder(main)) parser.registerFunction("block", new BlockFunctionBuilder(main))
.registerFunction("check", new CheckFunctionBuilder(main, cache)) .registerFunction("check", new CheckFunctionBuilder(main))
.registerFunction("structure", new StructureFunctionBuilder(registry, main)) .registerFunction("structure", new StructureFunctionBuilder(registry, main))
.registerFunction("randomInt", new RandomFunctionBuilder()) .registerFunction("randomInt", new RandomFunctionBuilder())
.registerFunction("recursions", new RecursionsFunctionBuilder()) .registerFunction("recursions", new RecursionsFunctionBuilder())

View File

@ -12,17 +12,15 @@ import java.util.List;
public class CheckFunctionBuilder implements FunctionBuilder<CheckFunction> { public class CheckFunctionBuilder implements FunctionBuilder<CheckFunction> {
private final TerraPlugin main; private final TerraPlugin main;
private final SamplerCache cache;
public CheckFunctionBuilder(TerraPlugin main, SamplerCache cache) { public CheckFunctionBuilder(TerraPlugin main) {
this.main = main; this.main = main;
this.cache = cache;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public CheckFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException { 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 @Override

View File

@ -25,22 +25,23 @@ public class CheckFunction implements Function<String> {
private final TerraPlugin main; private final TerraPlugin main;
private final Returnable<Number> x, y, z; private final Returnable<Number> x, y, z;
private final Position position; 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.main = main;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
this.position = position; this.position = position;
this.cache = cache;
} }
@Override @Override
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) { public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation()); RotationUtil.rotateVector(xz, arguments.getRotation());
@ -52,7 +53,8 @@ public class CheckFunction implements Function<String> {
private String apply(Location vector, World world) { private String apply(Location vector, World world) {
TerraWorld tw = main.getWorld(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. 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 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 cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 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 @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.MathUtil;
import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.util.mutable.MutableInteger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class ProbabilityCollection<E> implements Collection<E> { 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 Object[] array = new Object[0];
private int size; private int size;
public ProbabilityCollection<E> add(E item, int probability) { public ProbabilityCollection<E> add(E item, int probability) {
if(!cont.contains(item)) size++; if(!cont.containsKey(item)) size++;
cont.add(item); cont.computeIfAbsent(item, i -> new MutableInteger(0)).increment();
int oldLength = array.length; int oldLength = array.length;
Object[] newArray = new Object[array.length + probability]; Object[] newArray = new Object[array.length + probability];
System.arraycopy(array, 0, newArray, 0, array.length); // Expand array. 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)]; 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() { public int getTotalProbability() {
return array.length; 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 @Override
public int size() { public int size() {
return size; return size;
@ -59,26 +88,26 @@ public class ProbabilityCollection<E> implements Collection<E> {
@Override @Override
public boolean contains(Object o) { public boolean contains(Object o) {
return cont.contains(o); return cont.containsKey(o);
} }
@NotNull @NotNull
@Override @Override
public Iterator<E> iterator() { public Iterator<E> iterator() {
return cont.iterator(); return cont.keySet().iterator();
} }
@NotNull @NotNull
@Override @Override
public Object[] toArray() { public Object[] toArray() {
return cont.toArray(); return cont.keySet().toArray();
} }
@SuppressWarnings("SuspiciousToArrayCall") @SuppressWarnings("SuspiciousToArrayCall")
@NotNull @NotNull
@Override @Override
public <T> T[] toArray(@NotNull T[] a) { 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 @Override
public boolean containsAll(@NotNull Collection<?> c) { public boolean containsAll(@NotNull Collection<?> c) {
return cont.containsAll(c); return cont.keySet().containsAll(c);
} }
@Override @Override
@ -123,7 +152,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
} }
public Set<E> getContents() { public Set<E> getContents() {
return new HashSet<>(cont); return new HashSet<>(cont.keySet());
} }
public static final class Singleton<T> extends ProbabilityCollection<T> { public static final class Singleton<T> extends ProbabilityCollection<T> {
@ -131,6 +160,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
public Singleton(T single) { public Singleton(T single) {
this.single = single; this.single = single;
cont.put(single, new MutableInteger(1));
} }
@Override @Override
@ -138,6 +168,12 @@ public class ProbabilityCollection<E> implements Collection<E> {
throw new UnsupportedOperationException(); 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 @Override
public T get(Random r) { public T get(Random r) {
return single; 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.Biome;
import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; 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.config.templates.BiomeTemplate;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
/** /**
* Class representing a config-defined biome * Class representing a config-defined biome
*/ */
public class UserDefinedBiome implements TerraBiome { public class UserDefinedBiome implements TerraBiome {
private final GeneratorBuilder gen; private final WorldGenerator gen;
private final ProbabilityCollection<Biome> vanilla; private final ProbabilityCollection<Biome> vanilla;
private final String id; private final String id;
private final BiomeTemplate config; private final BiomeTemplate config;
@ -21,13 +20,13 @@ public class UserDefinedBiome implements TerraBiome {
private final Set<String> tags; 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.vanilla = vanilla;
this.gen = gen; this.gen = gen;
this.id = config.getID(); this.id = config.getID();
this.config = config; this.config = config;
this.color = config.getColor(); this.color = config.getColor();
this.tags = config.getTags() == null ? new HashSet<>() : config.getTags(); this.tags = config.getTags();
tags.add("BIOME:" + id); tags.add("BIOME:" + id);
} }
@ -52,7 +51,7 @@ public class UserDefinedBiome implements TerraBiome {
@Override @Override
public Generator getGenerator(World w) { public Generator getGenerator(World w) {
return gen.build(w.getSeed()); return gen;
} }
@Override @Override
@ -64,4 +63,9 @@ public class UserDefinedBiome implements TerraBiome {
public Set<String> getTags() { public Set<String> getTags() {
return tags; 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 { public interface BiomeSource {
TerraBiome getBiome(double x, double z); TerraBiome getBiome(double x, double z);
enum Type {
NOISE
}
} }

View File

@ -1,5 +1,6 @@
package com.dfsek.terra.api.world.biome.provider; 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.api.world.biome.TerraBiome;
import com.dfsek.terra.registry.OpenRegistry; import com.dfsek.terra.registry.OpenRegistry;
import net.jafama.FastMath; import net.jafama.FastMath;
@ -8,6 +9,7 @@ import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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. 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<>(); 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 int resolution;
private final Align align; 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.image = image;
this.resolution = resolution; this.resolution = resolution;
this.align = align; this.align = align;

View File

@ -31,7 +31,5 @@ public interface TerraChunkGenerator {
TerraPlugin getMain(); TerraPlugin getMain();
SamplerCache getCache();
Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth); 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.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SourceSeeded; import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.util.seeded.StageSeeded; 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.ExpanderStage;
import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage; import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider; 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.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.SourceBuilderLoader; 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.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.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.BorderListMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate; 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(ReplaceListMutatorTemplate.class, ReplaceListMutatorTemplate::new)
.registerLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new) .registerLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new)
.registerLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new) .registerLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new)
.registerLoader(NoiseSourceTemplate.class, NoiseSourceTemplate::new)
.registerLoader(FunctionTemplate.class, FunctionTemplate::new) .registerLoader(FunctionTemplate.class, FunctionTemplate::new)
.registerLoader(LinkedHashMap.class, new LinkedHashMapLoader()) .registerLoader(LinkedHashMap.class, new LinkedHashMapLoader())
.registerLoader(CarverPalette.class, new CarverPaletteLoader()) .registerLoader(CarverPalette.class, new CarverPaletteLoader())
@ -97,6 +100,7 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object)) .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(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(ImageBiomeProvider.Align.class, (t, object, cf) -> ImageBiomeProvider.Align.valueOf((String) object))
.registerLoader(ExpanderStage.Type.class, (t, object, cf) -> ExpanderStage.Type.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)) .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; package com.dfsek.terra.config.factories;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.world.biome.TerraBiome; import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import com.dfsek.terra.config.builder.GeneratorBuilder;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.config.templates.BiomeTemplate;
import java.util.LinkedHashMap; public class BiomeFactory implements ConfigFactory<BiomeTemplate, BiomeBuilder> {
import java.util.Map;
public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
private final ConfigPack pack; private final ConfigPack pack;
public BiomeFactory(ConfigPack pack) { public BiomeFactory(ConfigPack pack) {
@ -20,32 +14,7 @@ public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
} }
@Override @Override
public UserDefinedBiome build(BiomeTemplate template, TerraPlugin main) { public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) {
GeneratorBuilder generatorBuilder = new GeneratorBuilder(); return new UserDefinedBiomeBuilder(template, pack);
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);
} }
} }

View File

@ -11,7 +11,7 @@ import com.dfsek.terra.config.templates.CarverTemplate;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public class CarverFactory implements TerraFactory<CarverTemplate, UserDefinedCarver> { public class CarverFactory implements ConfigFactory<CarverTemplate, UserDefinedCarver> {
private final ConfigPack pack; private final ConfigPack pack;
public CarverFactory(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.tectonic.exception.LoadException;
import com.dfsek.terra.api.TerraPlugin; 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; 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.config.templates.FloraTemplate;
import com.dfsek.terra.world.population.items.flora.TerraFlora; import com.dfsek.terra.world.population.items.flora.TerraFlora;
public class FloraFactory implements TerraFactory<FloraTemplate, Flora> { public class FloraFactory implements ConfigFactory<FloraTemplate, Flora> {
@Override @Override
public TerraFlora build(FloraTemplate config, TerraPlugin main) { public TerraFlora build(FloraTemplate config, TerraPlugin main) {
Palette<BlockData> palette = new NoisePalette<>(new WhiteNoiseSampler(2403), false); 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.Ore;
import com.dfsek.terra.world.population.items.ores.VanillaOre; import com.dfsek.terra.world.population.items.ores.VanillaOre;
public class OreFactory implements TerraFactory<OreTemplate, Ore> { public class OreFactory implements ConfigFactory<OreTemplate, Ore> {
@Override @Override
public Ore build(OreTemplate config, TerraPlugin main) { public Ore build(OreTemplate config, TerraPlugin main) {
BlockData m = config.getMaterial(); 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.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.config.templates.PaletteTemplate; import com.dfsek.terra.config.templates.PaletteTemplate;
public class PaletteFactory implements TerraFactory<PaletteTemplate, Palette<BlockData>> { public class PaletteFactory implements ConfigFactory<PaletteTemplate, Palette<BlockData>> {
@Override @Override
public Palette<BlockData> build(PaletteTemplate config, TerraPlugin main) { public Palette<BlockData> build(PaletteTemplate config, TerraPlugin main) {
NoisePalette<BlockData> palette = new NoisePalette<>(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2); 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.config.templates.StructureTemplate;
import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.TerraStructure;
public class StructureFactory implements TerraFactory<StructureTemplate, TerraStructure> { public class StructureFactory implements ConfigFactory<StructureTemplate, TerraStructure> {
@Override @Override
public TerraStructure build(StructureTemplate config, TerraPlugin main) { public TerraStructure build(StructureTemplate config, TerraPlugin main) {
return new TerraStructure(config.getStructures(), config.getY(), config.getSpawn(), config); 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.config.templates.TreeTemplate;
import com.dfsek.terra.world.population.items.tree.TerraTree; import com.dfsek.terra.world.population.items.tree.TerraTree;
public class TreeFactory implements TerraFactory<TreeTemplate, Tree> { public class TreeFactory implements ConfigFactory<TreeTemplate, Tree> {
@Override @Override
public Tree build(TreeTemplate config, TerraPlugin main) { public Tree build(TreeTemplate config, TerraPlugin main) {
return new TerraTree(config.getSpawnable(), config.getyOffset(), config.getStructures()); 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.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader; import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider; 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.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; 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.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SourceSeeded; import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome; 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.api.world.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.loaders.Types; 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.lang.reflect.Type;
import java.util.Map; 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 { public SourceSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> source = (Map<String, Object>) c; 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)) { if(type == BiomeSource.Type.NOISE) {
ProbabilityCollection<TerraBiome> sourceBiomes = (ProbabilityCollection<TerraBiome>) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes")); return loader.loadClass(NoiseSourceTemplate.class, source);
NoiseSeeded sourceNoise = loader.loadClass(NoiseSeeded.class, source.get("noise"));
return seed -> new RandomSource(sourceBiomes, sourceNoise.apply(seed));
} }
throw new LoadException("No such loader type: " + type); 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.Default;
import com.dfsek.tectonic.annotations.Value; 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.pipeline.BiomePipeline;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider; import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
import java.util.List; import java.util.List;
@ -25,8 +24,7 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate {
@Value("pipeline.source") @Value("pipeline.source")
private SourceSeeded source; private SourceSeeded source;
public BiomePipelineTemplate(BiomeRegistry registry, TerraPlugin main) { public BiomePipelineTemplate(TerraPlugin main) {
super(registry);
this.main = 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.Default;
import com.dfsek.tectonic.annotations.Value; 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.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider; 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 { public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvider.BiomeProviderBuilder>, BiomeProvider.BiomeProviderBuilder {
protected final BiomeRegistry registry;
@Value("resolution") @Value("resolution")
@Default @Default
protected int resolution = 1; protected int resolution = 1;
@ -33,10 +31,6 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvi
@Value("type") @Value("type")
BiomeProvider.Type type; BiomeProvider.Type type;
protected BiomeProviderTemplate(BiomeRegistry registry) {
this.registry = registry;
}
@Override @Override
public BiomeProvider.BiomeProviderBuilder get() { public BiomeProvider.BiomeProviderBuilder get() {
return this; 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.tectonic.annotations.Value;
import com.dfsek.terra.api.world.biome.TerraBiome; 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.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider; import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
public class SingleBiomeProviderTemplate extends BiomeProviderTemplate { public class SingleBiomeProviderTemplate extends BiomeProviderTemplate {
@Value("biome") @Value("biome")
private TerraBiome biome; private TerraBiome biome;
public SingleBiomeProviderTemplate(BiomeRegistry registry) { public SingleBiomeProviderTemplate() {
super(registry);
} }
@Override @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.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator; 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; import java.util.Map;
@SuppressWarnings("unused")
public class BorderListMutatorTemplate extends MutatorStageTemplate { public class BorderListMutatorTemplate extends MutatorStageTemplate {
@Value("from") @Value("from")
private String from; private String from;
@ -16,14 +19,18 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate {
private String defaultReplace; private String defaultReplace;
@Value("default-to") @Value("default-to")
private ProbabilityCollection<TerraBiome> defaultTo; private ProbabilityCollection<BiomeBuilder> defaultTo;
@Value("replace") @Value("replace")
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace; private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
@Override @Override
public BiomeMutator build(long seed) { 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.tectonic.annotations.Value;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; 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.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator; import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class BorderMutatorTemplate extends MutatorStageTemplate { public class BorderMutatorTemplate extends MutatorStageTemplate {
@ -15,10 +15,10 @@ public class BorderMutatorTemplate extends MutatorStageTemplate {
private String replace; private String replace;
@Value("to") @Value("to")
private ProbabilityCollection<TerraBiome> to; private ProbabilityCollection<BiomeBuilder> to;
@Override @Override
public BiomeMutator build(long seed) { 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.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceListMutator; 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; import java.util.Map;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -14,13 +16,17 @@ public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
private String defaultFrom; private String defaultFrom;
@Value("default-to") @Value("default-to")
private ProbabilityCollection<TerraBiome> defaultTo; private ProbabilityCollection<BiomeBuilder> defaultTo;
@Value("to") @Value("to")
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace; private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
@Override @Override
public BiomeMutator build(long seed) { 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.tectonic.annotations.Value;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; 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.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator; import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class ReplaceMutatorTemplate extends MutatorStageTemplate { public class ReplaceMutatorTemplate extends MutatorStageTemplate {
@ -12,10 +12,10 @@ public class ReplaceMutatorTemplate extends MutatorStageTemplate {
private String from; private String from;
@Value("to") @Value("to")
private ProbabilityCollection<TerraBiome> to; private ProbabilityCollection<BiomeBuilder> to;
@Override @Override
public BiomeMutator build(long seed) { 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.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.seeded.NoiseSeeded; 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.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.carving.UserDefinedCarver; 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.BiomeFactory;
import com.dfsek.terra.config.factories.CarverFactory; 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.FloraFactory;
import com.dfsek.terra.config.factories.OreFactory; import com.dfsek.terra.config.factories.OreFactory;
import com.dfsek.terra.config.factories.PaletteFactory; import com.dfsek.terra.config.factories.PaletteFactory;
import com.dfsek.terra.config.factories.StructureFactory; 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.factories.TreeFactory;
import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.Loader; import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.fileloaders.ZIPLoader; import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader; 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.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; 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.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate;
import com.dfsek.terra.config.templates.AbstractableTemplate; 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.ScriptRegistry;
import com.dfsek.terra.registry.config.StructureRegistry; import com.dfsek.terra.registry.config.StructureRegistry;
import com.dfsek.terra.registry.config.TreeRegistry; 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.TerraStructure;
import com.dfsek.terra.world.population.items.ores.Ore; import com.dfsek.terra.world.population.items.ores.Ore;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -106,8 +107,6 @@ public class ConfigPack implements LoaderRegistrar {
private final ConfigLoader selfLoader = new ConfigLoader(); private final ConfigLoader selfLoader = new ConfigLoader();
private final Scope varScope = new Scope(); private final Scope varScope = new Scope();
private final SamplerCache samplerCache;
private final TerraPlugin main; private final TerraPlugin main;
private final Loader loader; private final Loader loader;
@ -119,7 +118,6 @@ public class ConfigPack implements LoaderRegistrar {
this.loader = new FolderLoader(folder.toPath()); this.loader = new FolderLoader(folder.toPath());
this.main = main; this.main = main;
long l = System.nanoTime(); long l = System.nanoTime();
this.samplerCache = new SamplerCache(main);
floraRegistry = new FloraRegistry(main); floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main); paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(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() + "\""); main.logger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\"");
throw e; throw e;
} }
toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately.
} }
public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException { public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException {
@ -155,7 +154,6 @@ public class ConfigPack implements LoaderRegistrar {
this.loader = new ZIPLoader(file); this.loader = new ZIPLoader(file);
this.main = main; this.main = main;
long l = System.nanoTime(); long l = System.nanoTime();
this.samplerCache = new SamplerCache(main);
floraRegistry = new FloraRegistry(main); floraRegistry = new FloraRegistry(main);
paletteRegistry = new PaletteRegistry(main); paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(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() + "\""); main.logger().severe("Failed to load config pack from ZIP archive \"" + file.getName() + "\"");
throw e; 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)); 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 -> { loader.open("structures/data", ".tesf").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) { for(Map.Entry<String, InputStream> entry : entries) {
try { try(InputStream stream = entry.getValue()) {
StructureScript structureScript = new StructureScript(entry.getValue(), main, scriptRegistry, lootRegistry, samplerCache, functionRegistry); StructureScript structureScript = new StructureScript(stream, main, scriptRegistry, lootRegistry, functionRegistry);
scriptRegistry.add(structureScript.getId(), structureScript); 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); 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."); 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) { public TerraStructure getStructure(String id) {
return structureRegistry.get(id); return structureRegistry.get(id);
} }
@ -270,7 +262,7 @@ public class ConfigPack implements LoaderRegistrar {
public void register(TypeRegistry registry) { public void register(TypeRegistry registry) {
registry registry
.registerLoader(Palette.class, paletteRegistry) .registerLoader(Palette.class, paletteRegistry)
.registerLoader(TerraBiome.class, biomeRegistry) .registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(Flora.class, floraRegistry) .registerLoader(Flora.class, floraRegistry)
.registerLoader(Ore.class, oreRegistry) .registerLoader(Ore.class, oreRegistry)
.registerLoader(Tree.class, treeRegistry) .registerLoader(Tree.class, treeRegistry)
@ -280,15 +272,11 @@ public class ConfigPack implements LoaderRegistrar {
.registerLoader(UserDefinedCarver.class, carverRegistry) .registerLoader(UserDefinedCarver.class, carverRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader)) .registerLoader(BufferedImage.class, new BufferedImageLoader(loader))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry)) .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry))
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry)) .registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, main)) .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(main))
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); .registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
} }
public SamplerCache getSamplerCache() {
return samplerCache;
}
public Set<UserDefinedCarver> getCarvers() { public Set<UserDefinedCarver> getCarvers() {
return carverRegistry.entries(); return carverRegistry.entries();
} }
@ -301,7 +289,7 @@ public class ConfigPack implements LoaderRegistrar {
return new CheckedRegistry<>(scriptRegistry); return new CheckedRegistry<>(scriptRegistry);
} }
public CheckedRegistry<TerraBiome> getBiomeRegistry() { public CheckedRegistry<BiomeBuilder> getBiomeRegistry() {
return new CheckedRegistry<>(biomeRegistry); return new CheckedRegistry<>(biomeRegistry);
} }
@ -340,4 +328,8 @@ public class ConfigPack implements LoaderRegistrar {
public CheckedRegistry<TerraStructure> getStructureRegistry() { public CheckedRegistry<TerraStructure> getStructureRegistry() {
return new CheckedRegistry<>(structureRegistry); 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 com.dfsek.terra.world.population.items.tree.TreeLayer;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -182,7 +183,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Value("tags") @Value("tags")
@Default @Default
@Abstractable @Abstractable
private Set<String> tags; private Set<String> tags = new HashSet<>();
@Value("carving") @Value("carving")
@Abstractable @Abstractable

View File

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

View File

@ -2,16 +2,16 @@ package com.dfsek.terra.registry.config;
import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader; 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 com.dfsek.terra.registry.OpenRegistry;
import java.lang.reflect.Type; import java.lang.reflect.Type;
public class BiomeRegistry extends OpenRegistry<TerraBiome> { public class BiomeRegistry extends OpenRegistry<BiomeBuilder> {
@Override @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; if(o.equals("SELF")) return null;
TerraBiome biome = get((String) o); BiomeBuilder biome = get((String) o);
if(biome == null) if(biome == null)
throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry."); throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry.");
return biome; 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.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.profiler.WorldProfiler; import com.dfsek.terra.profiler.WorldProfiler;
import com.dfsek.terra.world.generation.math.samplers.Sampler; import com.dfsek.terra.world.generation.math.samplers.Sampler;
import net.jafama.FastMath; import net.jafama.FastMath;
public class TerraWorld { public class TerraWorld {
private final BiomeProvider provider; private final BiomeProvider provider;
private final ConfigPack config; private final WorldConfig config;
private final boolean safe; private final boolean safe;
private final WorldProfiler profiler; private final WorldProfiler profiler;
private final World world; private final World world;
@ -27,11 +28,10 @@ public class TerraWorld {
public TerraWorld(World w, ConfigPack c, TerraPlugin main) { public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
if(!isTerraWorld(w)) throw new IllegalArgumentException("World " + w + " is not a Terra World!"); 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; this.world = w;
config = c.toWorldConfig(this);
this.provider = config.getProvider();
profiler = new WorldProfiler(w);
air = main.getWorldHandle().createBlockData("minecraft:air"); air = main.getWorldHandle().createBlockData("minecraft:air");
main.getEventManager().callEvent(new TerraWorldLoadEvent(this)); main.getEventManager().callEvent(new TerraWorldLoadEvent(this));
safe = true; safe = true;
@ -53,7 +53,7 @@ public class TerraWorld {
return provider; return provider;
} }
public ConfigPack getConfig() { public WorldConfig getConfig() {
return config; return config;
} }
@ -76,7 +76,7 @@ public class TerraWorld {
public BlockData getUngeneratedBlock(int x, int y, int z) { public BlockData getUngeneratedBlock(int x, int y, int z) {
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(x, z); UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(x, z);
Palette<BlockData> palette = biome.getGenerator(world).getPalette(y); 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 fdX = FastMath.floorMod(x, 16);
int fdZ = FastMath.floorMod(z, 16); int fdZ = FastMath.floorMod(z, 16);
double noise = sampler.sample(fdX, y, fdZ); double noise = sampler.sample(fdX, y, fdZ);

View File

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

View File

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

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.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.pack.ConfigPack; 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.config.templates.CarverTemplate;
import com.dfsek.terra.profiler.ProfileFuture; import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.TerraWorld;
@ -40,7 +41,7 @@ public class CavePopulator implements TerraBlockPopulator {
try(ProfileFuture ignored = tw.getProfiler().measure("CaveTime")) { try(ProfileFuture ignored = tw.getProfiler().measure("CaveTime")) {
Random random = PopulationUtil.getRandom(chunk); Random random = PopulationUtil.getRandom(chunk);
if(!tw.isSafe()) return; if(!tw.isSafe()) return;
ConfigPack config = tw.getConfig(); WorldConfig config = tw.getConfig();
for(UserDefinedCarver c : config.getCarvers()) { for(UserDefinedCarver c : config.getCarvers()) {
CarverTemplate template = c.getConfig(); 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.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.profiler.ProfileFuture; import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.TerraStructure;
@ -35,7 +36,7 @@ public class StructurePopulator implements TerraBlockPopulator {
int cz = (chunk.getZ() << 4); int cz = (chunk.getZ() << 4);
if(!tw.isSafe()) return; if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider(); BiomeProvider provider = tw.getBiomeProvider();
ConfigPack config = tw.getConfig(); WorldConfig config = tw.getConfig();
for(TerraStructure conf : config.getStructures()) { for(TerraStructure conf : config.getStructures()) {
Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world); 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.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig; 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.fileloaders.FolderLoader;
import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader; 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.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; 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.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate; import com.dfsek.terra.config.templates.AbstractableTemplate;
@ -144,11 +145,11 @@ public class DistributionTest {
private static BiomeProvider getProvider(long seed) throws ConfigException, IOException { private static BiomeProvider getProvider(long seed) throws ConfigException, IOException {
System.out.println(seed); 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()); FolderLoader folderLoader = new FolderLoader(pack.toPath());
AbstractConfigLoader loader = new AbstractConfigLoader(); AbstractConfigLoader loader = new AbstractConfigLoader();
new GenericLoaders(null).register(loader); new GenericLoaders(MAIN).register(loader);
BiomeRegistry biomeRegistry = new BiomeRegistry(); BiomeRegistry biomeRegistry = new BiomeRegistry();
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), MAIN)); 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() ConfigLoader pipeLoader = new ConfigLoader()
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()) .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
.registerLoader(TerraBiome.class, biomeRegistry) .registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader)) .registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader))
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry)) .registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, MAIN)) .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(MAIN))
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); .registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
new GenericLoaders(null).register(pipeLoader); new GenericLoaders(MAIN).register(pipeLoader);
pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NoiseRegistry())); 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") @Value("color")
@Default @Default
@ -336,5 +337,10 @@ public class DistributionTest {
public String toString() { public String toString() {
return id; 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)); 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 @Test

View File

@ -92,7 +92,7 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
boolean succeed = registry.loadAll(this); boolean succeed = registry.loadAll(this);
Map<World, TerraWorld> newMap = new HashMap<>(); Map<World, TerraWorld> newMap = new HashMap<>();
worldMap.forEach((world, tw) -> { worldMap.forEach((world, tw) -> {
((BukkitChunkGeneratorWrapper) world.getGenerator().getHandle()).getHandle().getCache().clear(); tw.getConfig().getSamplerCache().clear();
String packID = tw.getConfig().getTemplate().getID(); String packID = tw.getConfig().getTemplate().getID();
newMap.put(world, new TerraWorld(world, registry.get(packID), this)); 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 + "\""); if(!registry.contains(id)) throw new IllegalArgumentException("No such config pack \"" + id + "\"");
ConfigPack pack = registry.get(id); ConfigPack pack = registry.get(id);
worlds.put(worldName, pack); 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.bukkit.world.BukkitAdapter;
import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.pack.ConfigPack; 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.config.templates.BiomeTemplate;
import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.TerraStructure;
@ -15,6 +16,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -27,10 +29,10 @@ public class BiomeInfoCommand extends WorldCommand {
@Override @Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) { public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
String id = args[0]; String id = args[0];
ConfigPack cfg = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig(); WorldConfig cfg = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig();
UserDefinedBiome b; UserDefinedBiome b;
try { try {
b = (UserDefinedBiome) cfg.getBiome(id); b = (UserDefinedBiome) cfg.getBiomeRegistry().get(id);
} catch(IllegalArgumentException | NullPointerException e) { } catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.biome.invalid", new BukkitCommandSender(sender), id); LangUtil.send("command.biome.invalid", new BukkitCommandSender(sender), id);
return true; return true;
@ -74,7 +76,9 @@ public class BiomeInfoCommand extends WorldCommand {
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) { public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld()))) if(!(sender instanceof Player) || !TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld())))
return Collections.emptyList(); 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) if(args.length == 1)
return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());
return Collections.emptyList(); return Collections.emptyList();

View File

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

View File

@ -21,6 +21,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -46,7 +47,7 @@ public class LocateCommand extends WorldCommand {
} }
TerraStructure s; TerraStructure s;
try { 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) { } catch(IllegalArgumentException | NullPointerException e) {
LangUtil.send("command.structure.invalid", BukkitAdapter.adapt(sender), id); LangUtil.send("command.structure.invalid", BukkitAdapter.adapt(sender), id);
return true; return true;
@ -90,7 +91,9 @@ public class LocateCommand extends WorldCommand {
if(!(sender instanceof Player) || !(TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld())))) if(!(sender instanceof Player) || !(TerraWorld.isTerraWorld(BukkitAdapter.adapt(((Player) sender).getWorld()))))
return Collections.emptyList(); 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) if(args.length == 1)
return ids.stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList()); 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(); int z = p.getBlockZ();
Position dummy = new Position(0, 0); Position dummy = new Position(0, 0);
com.dfsek.terra.api.platform.world.World w = BukkitAdapter.adapt(world); 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) new com.dfsek.terra.api.math.vector.Location(w, x, y, z)
), Rotation.NONE, new FastRandom(), 0), new HashMap<>()); ), 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.api.world.tree.Tree;
import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.TerraWorld;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.TreeType; import org.bukkit.TreeType;
@ -46,7 +47,7 @@ public class CommonListener implements Listener {
World bukkit = BukkitAdapter.adapt(e.getWorld()); World bukkit = BukkitAdapter.adapt(e.getWorld());
if(!TerraWorld.isTerraWorld(bukkit)) return; if(!TerraWorld.isTerraWorld(bukkit)) return;
TerraWorld tw = main.getWorld(bukkit); TerraWorld tw = main.getWorld(bukkit);
ConfigPack c = tw.getConfig(); WorldConfig c = tw.getConfig();
if(c.getTemplate().isDisableSaplings()) return; if(c.getTemplate().isDisableSaplings()) return;
e.setCancelled(true); e.setCancelled(true);
Block block = e.getLocation().getBlock(); Block block = e.getLocation().getBlock();

View File

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

View File

@ -37,7 +37,7 @@ public class SpigotListener implements Listener {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return; if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld())); TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld()));
EnderSignal signal = (EnderSignal) entity; 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) { if(config != null) {
main.getDebugLogger().info("Overriding Ender Signal..."); main.getDebugLogger().info("Overriding Ender Signal...");
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> { 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.transform.Transformer;
import com.dfsek.terra.api.util.logging.DebugLogger; import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.Logger; 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.api.world.tree.Tree;
import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig; 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.LangUtil;
import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.ConfigPack;
@ -75,6 +75,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; 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))); .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) { public static String createBiomeID(ConfigPack pack, String biomeID) {
return pack.getTemplate().getID().toLowerCase() + "/" + biome.getID().toLowerCase(); 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(); SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder();
DefaultBiomeFeatures.addFarmAnimals(spawnSettings); DefaultBiomeFeatures.addFarmAnimals(spawnSettings);
DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100); 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")); 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.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.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC);
Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC); Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC);
if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
registry.forEach(pack -> { 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()) { final GeneratorType generatorType = new GeneratorType("terra." + pack.getTemplate().getID()) {
@Override @Override
protected ChunkGenerator getChunkGenerator(Registry<Biome> biomeRegistry, Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry, long seed) { protected ChunkGenerator getChunkGenerator(Registry<Biome> biomeRegistry, Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry, long seed) {

View File

@ -50,8 +50,8 @@ public class TerraBiomeSource extends BiomeSource {
@Override @Override
public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) {
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX * 4, biomeZ * 4); UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2);
return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome))); 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)); super(biomeSource, new StructuresConfig(false));
this.pack = configPack; 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()); delegate.getMain().logger().info("Loading world with config pack " + pack.getTemplate().getID());
this.biomeSource = biomeSource; this.biomeSource = biomeSource;

View File

@ -1,6 +1,7 @@
package com.dfsek.terra.region; package com.dfsek.terra.region;
import com.dfsek.terra.StandalonePlugin; import com.dfsek.terra.StandalonePlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.platform.DirectChunkData; import com.dfsek.terra.platform.DirectChunkData;
import com.dfsek.terra.platform.DirectWorld; import com.dfsek.terra.platform.DirectWorld;
import com.dfsek.terra.platform.GenWrapper; import com.dfsek.terra.platform.GenWrapper;
@ -31,7 +32,7 @@ public class Generator {
structurePopulator = new StructurePopulator(plugin); structurePopulator = new StructurePopulator(plugin);
treePopulator = new TreePopulator(plugin); treePopulator = new TreePopulator(plugin);
orePopulator = new OrePopulator(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; this.seed = seed;
} }