Merge pull request #254 from PolyhedralDev/dev/addon-splits

Implement other biome provider types, streamline pipeline config syntax, implement more locators
This commit is contained in:
dfsek
2021-07-29 08:11:03 -07:00
committed by GitHub
32 changed files with 360 additions and 177 deletions

View File

@@ -0,0 +1,39 @@
package com.dfsek.terra.addons.biome.image;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import java.util.function.Supplier;
@Addon("biome-provider-image")
@Author("Terra")
@Version("1.0.0")
public class ImageBiomeProviderAddon extends TerraAddon {
public static final TypeKey<Supplier<ObjectTemplate<BiomeProvider>>> PROVIDER_REGISTRY_KEY = new TypeKey<>() {};
@Inject
private TerraPlugin main;
@Override
public void initialize() {
main.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry(PROVIDER_REGISTRY_KEY);
providerRegistry.register("IMAGE", () -> new ImageProviderTemplate(event.getPack().getRegistry(TerraBiome.class)));
})
.failThrough();
}
}

View File

@@ -1,6 +1,8 @@
package com.dfsek.terra.addons.biome.image;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
@@ -8,7 +10,7 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import java.awt.image.BufferedImage;
import java.util.HashSet;
public class ImageProviderTemplate /*extends BiomeProviderTemplate */ {
public class ImageProviderTemplate implements ObjectTemplate<BiomeProvider> {
private final Registry<TerraBiome> biomes;
@Value("image.name")
private BufferedImage image;
@@ -16,14 +18,16 @@ public class ImageProviderTemplate /*extends BiomeProviderTemplate */ {
@Value("image.align")
private ImageBiomeProvider.Align align;
private int resolution;
@Value("resolution")
@Default
private int resolution = 1;
public ImageProviderTemplate(Registry<TerraBiome> set) {
this.biomes = set;
}
//@Override
public BiomeProvider build() {
@Override
public BiomeProvider get() {
return new ImageBiomeProvider(new HashSet<>(biomes.entries()), image, resolution, align);
}
}

View File

@@ -1,25 +1,16 @@
package com.dfsek.terra.addons.biome.pipeline;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.BiomePipelineTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.BiomeProviderLoader;
import com.dfsek.terra.addons.biome.pipeline.config.NoiseSourceTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.SourceLoader;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageLoader;
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.addons.biome.pipeline.source.NoiseSource;
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
@@ -28,39 +19,47 @@ import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource;
import java.util.function.Supplier;
@Addon("biome-provider-pipeline")
@Author("Terra")
@Version("1.0.0")
public class BiomePipelineAddon extends TerraAddon {
public static final TypeKey<Supplier<ObjectTemplate<BiomeSource>>> SOURCE_REGISTRY_KEY = new TypeKey<>() {};
public static final TypeKey<Supplier<ObjectTemplate<Stage>>> STAGE_REGISTRY_KEY = new TypeKey<>() {};
public static final TypeKey<Supplier<ObjectTemplate<BiomeProvider>>> PROVIDER_REGISTRY_KEY = new TypeKey<>() {};
@Inject
private TerraPlugin main;
public static final TypeKey<BiomeProvider> BIOME_PROVIDER_BUILDER_TOKEN = new TypeKey<>(){};
public static final TypeKey<BiomeSource> BIOME_SOURCE_BUILDER_TOKEN = new TypeKey<>(){};
@Override
public void initialize() {
main.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().applyLoader(BIOME_SOURCE_BUILDER_TOKEN.getType(), new SourceLoader())
.applyLoader(Stage.class, new StageLoader())
.applyLoader(ExpanderStage.Type.class, (c, o, l) -> ExpanderStage.Type.valueOf((String) o))
.applyLoader(MutatorStage.Type.class, (c, o, l) -> MutatorStage.Type.valueOf((String) o))
.applyLoader(NoiseSource.class, NoiseSourceTemplate::new)
.applyLoader(ReplaceMutator.class, ReplaceMutatorTemplate::new)
.applyLoader(BorderMutator.class, BorderMutatorTemplate::new)
.applyLoader(BorderListMutator.class, BorderListMutatorTemplate::new)
.applyLoader(ReplaceListMutator.class, ReplaceListMutatorTemplate::new)
.applyLoader(SmoothMutator.class, SmoothMutatorTemplate::new)
.applyLoader(ExpanderStage.class, ExpanderStageTemplate::new)
.applyLoader(BiomePipelineProvider.class, () -> new BiomePipelineTemplate(main))
.applyLoader(BIOME_PROVIDER_BUILDER_TOKEN.getType(), new BiomeProviderLoader())
.applyLoader(BiomeSource.Type.class, (t, object, cf) -> BiomeSource.Type.valueOf((String) object)))
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry(PROVIDER_REGISTRY_KEY);
providerRegistry.register("PIPELINE", () -> new BiomePipelineTemplate(main));
})
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeSource>>> sourceRegistry = event.getPack().getOrCreateRegistry(SOURCE_REGISTRY_KEY);
sourceRegistry.register("NOISE", NoiseSourceTemplate::new);
})
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Stage>>> stageRegistry = event.getPack().getOrCreateRegistry(STAGE_REGISTRY_KEY);
stageRegistry.register("FRACTAL_EXPAND", ExpanderStageTemplate::new);
stageRegistry.register("SMOOTH", SmoothMutatorTemplate::new);
stageRegistry.register("REPLACE", ReplaceMutatorTemplate::new);
stageRegistry.register("REPLACE_LIST", ReplaceListMutatorTemplate::new);
stageRegistry.register("BORDER", BorderMutatorTemplate::new);
stageRegistry.register("BORDER_LIST", BorderListMutatorTemplate::new);
})
.failThrough();
}
}

View File

@@ -1,25 +0,0 @@
package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.addons.biome.pipeline.source.NoiseSource;
import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource;
import java.lang.reflect.AnnotatedType;
import java.util.Map;
@SuppressWarnings("unchecked")
public class SourceLoader implements TypeLoader<BiomeSource> {
@Override
public BiomeSource load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> source = (Map<String, Object>) c;
BiomeSource.Type type = loader.loadType(BiomeSource.Type.class, source.get("type"));
if(type == BiomeSource.Type.NOISE) {
return loader.loadType(NoiseSource.class, source);
}
throw new LoadException("No such loader type: " + type);
}
}

View File

@@ -1,63 +0,0 @@
package com.dfsek.terra.addons.biome.pipeline.config.stage;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import java.lang.reflect.AnnotatedType;
import java.util.Map;
@SuppressWarnings("unchecked")
public class StageLoader implements TypeLoader<Stage> {
@Override
public Stage load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> raw = (Map<String, Object>) c;
if(raw.size() != 1) throw new LoadException("Illegal stage map size: " + raw.size());
Map.Entry<String, Object> entry = null;
for(Map.Entry<String, Object> e : raw.entrySet()) {
entry = e;
}
Map<String, Object> mutator = (Map<String, Object>) entry.getValue();
if(entry.getKey().equals("expand")) {
ExpanderStage.Type stageType = loader.loadType(ExpanderStage.Type.class, mutator.get("type"));
if(stageType.equals(ExpanderStage.Type.FRACTAL)) {
return loader.loadType(ExpanderStage.class, mutator);
} else throw new LoadException("No such expander \"" + stageType + "\"");
} else if(entry.getKey().equals("mutate")) {
switch(loader.loadType(MutatorStage.Type.class, mutator.get("type"))) {
case SMOOTH:
return new MutatorStage(loader.loadType(SmoothMutator.class, mutator));
case REPLACE:
return new MutatorStage(loader.loadType(ReplaceMutator.class, mutator));
case REPLACE_LIST:
return new MutatorStage(loader.loadType(ReplaceListMutator.class, mutator));
case BORDER:
return new MutatorStage(loader.loadType(BorderMutator.class, mutator));
case BORDER_LIST:
return new MutatorStage(loader.loadType(BorderListMutator.class, mutator));
default:
throw new LoadException("No such mutator type \"" + mutator.get("type"));
}
}
throw new LoadException("No such mutator \"" + entry.getKey() + "\"");
}
}

View File

@@ -2,7 +2,9 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.noise.NoiseSampler;

View File

@@ -1,8 +1,10 @@
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
@@ -10,7 +12,7 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.Map;
@SuppressWarnings("unused")
public class BorderListMutatorTemplate extends MutatorStageTemplate {
public class BorderListMutatorTemplate extends StageTemplate {
@Value("from")
private @Meta String from;
@@ -25,7 +27,7 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate {
@Override
public BiomeMutator get() {
return new BorderListMutator(replace, from, defaultReplace, noise, defaultTo);
public Stage get() {
return new MutatorStage(new BorderListMutator(replace, from, defaultReplace, noise, defaultTo));
}
}

View File

@@ -2,13 +2,16 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
@SuppressWarnings("unused")
public class BorderMutatorTemplate extends MutatorStageTemplate {
public class BorderMutatorTemplate extends StageTemplate {
@Value("from")
private @Meta String from;
@@ -19,7 +22,7 @@ public class BorderMutatorTemplate extends MutatorStageTemplate {
private @Meta ProbabilityCollection<@Meta TerraBiome> to;
@Override
public BiomeMutator get() {
return new BorderMutator(from, replace, noise, to);
public Stage get() {
return new MutatorStage(new BorderMutator(from, replace, noise, to));
}
}

View File

@@ -1,16 +0,0 @@
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.noise.NoiseSampler;
public abstract class MutatorStageTemplate implements ObjectTemplate<BiomeMutator> {
@Value("noise")
protected @Meta NoiseSampler noise;
@Override
public abstract BiomeMutator get();
}

View File

@@ -2,7 +2,10 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
@@ -10,7 +13,7 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.Map;
@SuppressWarnings("unused")
public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
public class ReplaceListMutatorTemplate extends StageTemplate {
@Value("default-from")
private @Meta String defaultFrom;
@@ -21,7 +24,7 @@ public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
private @Meta Map<@Meta TerraBiome, @Meta ProbabilityCollection<@Meta TerraBiome>> replace;
@Override
public BiomeMutator get() {
return new ReplaceListMutator(replace, defaultFrom, defaultTo, noise);
public Stage get() {
return new MutatorStage(new ReplaceListMutator(replace, defaultFrom, defaultTo, noise));
}
}

View File

@@ -2,13 +2,16 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
@SuppressWarnings("unused")
public class ReplaceMutatorTemplate extends MutatorStageTemplate {
public class ReplaceMutatorTemplate extends StageTemplate {
@Value("from")
private @Meta String from;
@@ -16,7 +19,7 @@ public class ReplaceMutatorTemplate extends MutatorStageTemplate {
private @Meta ProbabilityCollection<@Meta TerraBiome> to;
@Override
public BiomeMutator get() {
return new ReplaceMutator(from, to, noise);
public Stage get() {
return new MutatorStage(new ReplaceMutator(from, to, noise));
}
}

View File

@@ -1,11 +1,14 @@
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
public class SmoothMutatorTemplate extends MutatorStageTemplate {
public class SmoothMutatorTemplate extends StageTemplate {
@Override
public BiomeMutator get() {
return new SmoothMutator(noise);
public Stage get() {
return new MutatorStage(new SmoothMutator(noise));
}
}

View File

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

View File

@@ -0,0 +1,38 @@
package com.dfsek.terra.addons.biome.single;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import java.util.function.Supplier;
@Addon("biome-provider-single")
@Author("Terra")
@Version("1.0.0")
public class SingleBiomeProviderAddon extends TerraAddon {
public static final TypeKey<Supplier<ObjectTemplate<BiomeProvider>>> PROVIDER_REGISTRY_KEY = new TypeKey<>() {};
@Inject
private TerraPlugin main;
@Override
public void initialize() {
main.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry = event.getPack().getOrCreateRegistry(PROVIDER_REGISTRY_KEY);
providerRegistry.register("SINGLE", SingleBiomeProviderTemplate::new);
})
.failThrough();
}
}

View File

@@ -1,6 +1,9 @@
package com.dfsek.terra.addons.feature.locator;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.config.AndLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.NoiseLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.OrLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.PatternLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.RandomLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.SurfaceLocatorTemplate;
@@ -46,6 +49,10 @@ public class LocatorAddon extends TerraAddon {
locatorRegistry.register("SURFACE", () -> new SurfaceLocatorTemplate(main));
locatorRegistry.register("RANDOM", RandomLocatorTemplate::new);
locatorRegistry.register("PATTERN", PatternLocatorTemplate::new);
locatorRegistry.register("NOISE", NoiseLocatorTemplate::new);
locatorRegistry.register("AND", AndLocatorTemplate::new);
locatorRegistry.register("OR", OrLocatorTemplate::new);
})
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Pattern>>> patternRegistry = event.getPack().getOrCreateRegistry(PATTERN_TOKEN);

View File

@@ -0,0 +1,31 @@
package com.dfsek.terra.addons.feature.locator.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
import java.util.List;
public class AndLocatorTemplate implements ObjectTemplate<Locator>, ValidatedConfigTemplate {
@Value("locators")
private @Meta List<@Meta Locator> locators;
@Override
public Locator get() {
Locator current = locators.remove(0);
while(!locators.isEmpty()) {
current = current.and(locators.remove(0));
}
return current;
}
@Override
public boolean validate() throws ValidationException {
if(locators.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern.");
return true;
}
}

View File

@@ -0,0 +1,20 @@
package com.dfsek.terra.addons.feature.locator.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.locators.NoiseLocator;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.structure.feature.Locator;
import java.util.List;
public class NoiseLocatorTemplate implements ObjectTemplate<Locator> {
@Value("samplers")
private @Meta List<@Meta NoiseSampler> samplers;
@Override
public Locator get() {
return new NoiseLocator(samplers);
}
}

View File

@@ -0,0 +1,30 @@
package com.dfsek.terra.addons.feature.locator.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
import java.util.List;
public class OrLocatorTemplate implements ObjectTemplate<Locator>, ValidatedConfigTemplate {
@Value("locators")
private @Meta List<@Meta Locator> locators;
@Override
public Locator get() {
Locator current = locators.remove(0);
while(!locators.isEmpty()) {
current = current.or(locators.remove(0));
}
return current;
}
@Override
public boolean validate() throws ValidationException {
if(locators.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern.");
return true;
}
}

View File

@@ -3,8 +3,7 @@ package com.dfsek.terra.addons.feature.locator.config.pattern;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.addons.feature.locator.patterns.match.MatchPattern;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.Range;

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.addons.feature.locator.config.pattern;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.addons.feature.locator.patterns.match.MatchPattern;
import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.util.collection.MaterialSet;

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.addons.feature.locator.config.pattern;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.addons.feature.locator.patterns.match.MatchPattern;
import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.Range;

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.addons.feature.locator.config.pattern;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.addons.feature.locator.patterns.match.MatchPattern;
import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern;
import com.dfsek.terra.api.util.Range;
public class SolidMatchPatternTemplate implements ObjectTemplate<Pattern> {

View File

@@ -0,0 +1,31 @@
package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.structure.feature.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.world.Column;
import net.jafama.FastMath;
import java.util.List;
public class NoiseLocator implements Locator {
private final List<NoiseSampler> samplers;
public NoiseLocator(List<NoiseSampler> samplers) {
this.samplers = samplers;
}
@Override
public BinaryColumn getSuitableCoordinates(Column column) {
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
long seed = column.getWorld().getSeed();
samplers.forEach(sampler -> {
int y = FastMath.floorToInt(sampler.getNoiseSeeded(seed, column.getX(), column.getX()));
if(y >= column.getMaxY() || y < column.getMinY()) return;
results.set(y);
});
return results;
}
}

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.structure.feature.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.Column;
@@ -18,11 +19,11 @@ public class PatternLocator implements Locator {
}
@Override
public List<Integer> getSuitableCoordinates(Column column) {
List<Integer> locations = new ArrayList<>();
public BinaryColumn getSuitableCoordinates(Column column) {
BinaryColumn locations = new BinaryColumn(column.getMinY(), column.getMaxY());
for(int y : search) {
if(pattern.matches(y, column)) locations.add(y);
if(pattern.matches(y, column)) locations.set(y);
}
return locations;

View File

@@ -1,5 +1,6 @@
package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.api.structure.feature.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.Column;
@@ -19,7 +20,7 @@ public class RandomLocator implements Locator {
}
@Override
public List<Integer> getSuitableCoordinates(Column column) {
public BinaryColumn getSuitableCoordinates(Column column) {
long seed = column.getWorld().getSeed();
seed = 31 * seed + column.getX();
seed = 31 * seed + column.getZ();
@@ -28,9 +29,9 @@ public class RandomLocator implements Locator {
int size = points.get(r);
List<Integer> results = new ArrayList<>(size);
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
for(int i = 0; i < size; i++) {
results.set(i, height.get(r));
results.set(height.get(r));
}
return results;

View File

@@ -2,13 +2,12 @@ package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.structure.feature.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.ConstantRange;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.Column;
import java.util.Collections;
import java.util.List;
public class SurfaceLocator implements Locator {
private final Range search;
@@ -21,12 +20,14 @@ public class SurfaceLocator implements Locator {
}
@Override
public List<Integer> getSuitableCoordinates(Column column) {
public BinaryColumn getSuitableCoordinates(Column column) {
BinaryColumn location = new BinaryColumn(column.getMinY(), column.getMaxY());
for(int y : search) {
if(column.getBlock(y).matches(air) && !column.getBlock(y-1).matches(air)) {
return Collections.singletonList(y);
location.set(y);
return location;
}
}
return Collections.emptyList();
return location;
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.addons.feature.locator.patterns.match;
package com.dfsek.terra.addons.feature.locator.patterns;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.block.state.BlockState;

View File

@@ -30,14 +30,14 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
@Default
private @Meta Map<String, @Meta Double> vars = new HashMap<>();
@Value("equation")
@Value("expression")
private @Meta String equation;
@Value("functions")
@Default
private @Meta LinkedHashMap<String, @Meta DimensionApplicableNoiseSampler> functions = new LinkedHashMap<>();
@Value("expressions")
@Value("functions")
@Default
private @Meta LinkedHashMap<String, @Meta FunctionTemplate> expressions = new LinkedHashMap<>();

View File

@@ -34,4 +34,14 @@ public class ColumnImpl implements Column {
public World getWorld() {
return world;
}
@Override
public int getMinY() {
return world.getMinHeight();
}
@Override
public int getMaxY() {
return world.getMaxHeight();
}
}

View File

@@ -0,0 +1,54 @@
package com.dfsek.terra.api.structure.feature;
import java.util.function.IntConsumer;
public class BinaryColumn {
private final boolean[] data;
private final int minY;
public BinaryColumn(int minY, int maxY) {
this.minY = minY;
if(maxY <= minY) throw new IllegalArgumentException("Max y must be greater than min y");
this.data = new boolean[maxY-minY];
}
public void set(int y) {
data[y - minY] = true;
}
public boolean get(int y) {
return data[y - minY];
}
public void forEach(IntConsumer consumer) {
for(int y = 0; y < data.length; y++) {
if(data[y]) {
consumer.accept(y - minY);
}
}
}
public BinaryColumn and(BinaryColumn that) {
if(that.minY != this.minY) throw new IllegalArgumentException("Must share same min Y");
if(that.data.length != this.data.length) throw new IllegalArgumentException("Must share same max Y");
BinaryColumn next = new BinaryColumn(minY, data.length - minY);
for(int i = 0; i < this.data.length; i++) {
next.data[i] = this.data[i] && that.data[i];
}
return next;
}
public BinaryColumn or(BinaryColumn that) {
if(that.minY != this.minY) throw new IllegalArgumentException("Must share same min Y");
if(that.data.length != this.data.length) throw new IllegalArgumentException("Must share same max Y");
BinaryColumn next = new BinaryColumn(minY, data.length - minY);
for(int i = 0; i < this.data.length; i++) {
next.data[i] = this.data[i] || that.data[i];
}
return next;
}
}

View File

@@ -2,8 +2,14 @@ package com.dfsek.terra.api.structure.feature;
import com.dfsek.terra.api.world.Column;
import java.util.List;
public interface Locator {
List<Integer> getSuitableCoordinates(Column column);
BinaryColumn getSuitableCoordinates(Column column);
default Locator and(Locator that) {
return column -> this.getSuitableCoordinates(column).and(that.getSuitableCoordinates(column));
}
default Locator or(Locator that) {
return column -> this.getSuitableCoordinates(column).or(that.getSuitableCoordinates(column));
}
}

View File

@@ -13,4 +13,8 @@ public interface Column {
BlockState getBlock(int y);
World getWorld();
int getMinY();
int getMaxY();
}