Initial commit

This commit is contained in:
dfsek 2021-10-17 15:05:52 -07:00
commit 41e6b7f243
23 changed files with 635 additions and 0 deletions

View File

@ -0,0 +1,2 @@
dependencies {
}

View File

@ -0,0 +1,76 @@
package com.dfsek.terra.addons.feature.locator;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import java.util.function.Supplier;
import com.dfsek.terra.addons.feature.locator.config.AndLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.Noise3DLocatorTemplate;
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;
import com.dfsek.terra.addons.feature.locator.config.pattern.AirMatchPatternTemplate;
import com.dfsek.terra.addons.feature.locator.config.pattern.AndPatternTemplate;
import com.dfsek.terra.addons.feature.locator.config.pattern.BlockSetMatchPatternTemplate;
import com.dfsek.terra.addons.feature.locator.config.pattern.NotPatternTemplate;
import com.dfsek.terra.addons.feature.locator.config.pattern.OrPatternTemplate;
import com.dfsek.terra.addons.feature.locator.config.pattern.SingleBlockMatchPatternTemplate;
import com.dfsek.terra.addons.feature.locator.config.pattern.SolidMatchPatternTemplate;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.Platform;
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.inject.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.reflection.TypeKey;
@Addon("config-locators")
@Version("1.0.0")
@Author("Terra")
public class LocatorAddon extends TerraAddon {
public static final TypeKey<Supplier<ObjectTemplate<Locator>>> LOCATOR_TOKEN = new TypeKey<>() {
};
public static final TypeKey<Supplier<ObjectTemplate<Pattern>>> PATTERN_TOKEN = new TypeKey<>() {
};
@Inject
private Platform platform;
@Override
public void initialize() {
platform.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Locator>>> locatorRegistry = event.getPack().getOrCreateRegistry(LOCATOR_TOKEN);
locatorRegistry.register("SURFACE", () -> new SurfaceLocatorTemplate(platform));
locatorRegistry.register("RANDOM", RandomLocatorTemplate::new);
locatorRegistry.register("PATTERN", PatternLocatorTemplate::new);
locatorRegistry.register("NOISE", NoiseLocatorTemplate::new);
locatorRegistry.register("NOISE_3D", Noise3DLocatorTemplate::new);
locatorRegistry.register("AND", AndLocatorTemplate::new);
locatorRegistry.register("OR", OrLocatorTemplate::new);
})
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<Pattern>>> patternRegistry = event.getPack().getOrCreateRegistry(PATTERN_TOKEN);
patternRegistry.register("MATCH_AIR", AirMatchPatternTemplate::new);
patternRegistry.register("MATCH_SOLID", SolidMatchPatternTemplate::new);
patternRegistry.register("MATCH", SingleBlockMatchPatternTemplate::new);
patternRegistry.register("MATCH_SET", BlockSetMatchPatternTemplate::new);
patternRegistry.register("AND", AndPatternTemplate::new);
patternRegistry.register("OR", OrPatternTemplate::new);
patternRegistry.register("NOT", NotPatternTemplate::new);
})
.failThrough();
}
}

View File

@ -0,0 +1,32 @@
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 java.util.List;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
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.Noise3DLocator;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.structure.feature.Locator;
public class Noise3DLocatorTemplate implements ObjectTemplate<Locator> {
@Value("sampler")
private @Meta NoiseSampler sampler;
@Override
public Locator get() {
return new Noise3DLocator(sampler);
}
}

View File

@ -0,0 +1,22 @@
package com.dfsek.terra.addons.feature.locator.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import java.util.List;
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;
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,32 @@
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 java.util.List;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
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

@ -0,0 +1,24 @@
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.PatternLocator;
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 com.dfsek.terra.api.util.Range;
public class PatternLocatorTemplate implements ObjectTemplate<Locator> {
@Value("range")
private @Meta Range range;
@Value("pattern")
private @Meta Pattern pattern;
@Override
public Locator get() {
return new PatternLocator(pattern, range);
}
}

View File

@ -0,0 +1,23 @@
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.RandomLocator;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
public class RandomLocatorTemplate implements ObjectTemplate<Locator> {
@Value("height")
private @Meta Range height;
@Value("amount")
private @Meta Range amount;
@Override
public Locator get() {
return new RandomLocator(height, amount);
}
}

View File

@ -0,0 +1,27 @@
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.SurfaceLocator;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
public class SurfaceLocatorTemplate implements ObjectTemplate<Locator> {
private final Platform platform;
@Value("range")
private @Meta Range range;
public SurfaceLocatorTemplate(Platform platform) {
this.platform = platform;
}
@Override
public Locator get() {
return new SurfaceLocator(range, platform);
}
}

View File

@ -0,0 +1,22 @@
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.MatchPattern;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.Range;
public class AirMatchPatternTemplate implements ObjectTemplate<Pattern> {
@Value("offset")
private @Meta Range offset;
@Override
public Pattern get() {
return new MatchPattern(offset, BlockState::isAir);
}
}

View File

@ -0,0 +1,32 @@
package com.dfsek.terra.addons.feature.locator.config.pattern;
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 java.util.List;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.config.meta.Meta;
public class AndPatternTemplate implements ObjectTemplate<Pattern>, ValidatedConfigTemplate {
@Value("patterns")
private @Meta List<@Meta Pattern> patterns;
@Override
public Pattern get() {
Pattern current = patterns.remove(0);
while(!patterns.isEmpty()) {
current = current.and(patterns.remove(0));
}
return current;
}
@Override
public boolean validate() throws ValidationException {
if(patterns.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern.");
return true;
}
}

View File

@ -0,0 +1,24 @@
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.MatchPattern;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.util.collection.MaterialSet;
public class BlockSetMatchPatternTemplate implements ObjectTemplate<Pattern> {
@Value("blocks")
private @Meta MaterialSet blocks;
@Value("offset")
private @Meta Range offset;
@Override
public Pattern get() {
return new MatchPattern(offset, blockState -> blocks.contains(blockState.getBlockType()));
}
}

View File

@ -0,0 +1,18 @@
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.api.config.meta.Meta;
public class NotPatternTemplate implements ObjectTemplate<Pattern> {
@Value("pattern")
private @Meta Pattern pattern;
@Override
public Pattern get() {
return pattern.not();
}
}

View File

@ -0,0 +1,32 @@
package com.dfsek.terra.addons.feature.locator.config.pattern;
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 java.util.List;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.config.meta.Meta;
public class OrPatternTemplate implements ObjectTemplate<Pattern>, ValidatedConfigTemplate {
@Value("patterns")
private @Meta List<@Meta Pattern> patterns;
@Override
public Pattern get() {
Pattern current = patterns.remove(0);
while(!patterns.isEmpty()) {
current = current.or(patterns.remove(0));
}
return current;
}
@Override
public boolean validate() throws ValidationException {
if(patterns.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern.");
return true;
}
}

View File

@ -0,0 +1,25 @@
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.MatchPattern;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.Range;
public class SingleBlockMatchPatternTemplate implements ObjectTemplate<Pattern> {
@Value("block")
private @Meta BlockState block;
@Value("offset")
private @Meta Range offset;
@Override
public Pattern get() {
return new MatchPattern(offset, block::matches);
}
}

View File

@ -0,0 +1,19 @@
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.MatchPattern;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.util.Range;
public class SolidMatchPatternTemplate implements ObjectTemplate<Pattern> {
@Value("offset")
private Range offset;
@Override
public Pattern get() {
return new MatchPattern(offset, blockState -> blockState.getBlockType().isSolid());
}
}

View File

@ -0,0 +1,27 @@
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;
public class Noise3DLocator implements Locator {
private final NoiseSampler sampler;
public Noise3DLocator(NoiseSampler sampler) {
this.sampler = sampler;
}
@Override
public BinaryColumn getSuitableCoordinates(Column column) {
BinaryColumn results = column.newBinaryColumn();
long seed = column.getWorld().getSeed();
int x = column.getX();
int z = column.getZ();
column.forEach(y -> {
if(sampler.getNoiseSeeded(seed, x, y, z) > 0) results.set(y);
});
return results;
}
}

View File

@ -0,0 +1,33 @@
package com.dfsek.terra.addons.feature.locator.locators;
import net.jafama.FastMath;
import java.util.List;
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;
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

@ -0,0 +1,29 @@
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;
public class PatternLocator implements Locator {
private final Pattern pattern;
private final Range search;
public PatternLocator(Pattern pattern, Range search) {
this.pattern = pattern;
this.search = search;
}
@Override
public BinaryColumn getSuitableCoordinates(Column column) {
BinaryColumn locations = new BinaryColumn(column.getMinY(), column.getMaxY());
for(int y : search) {
if(pattern.matches(y, column)) locations.set(y);
}
return locations;
}
}

View File

@ -0,0 +1,38 @@
package com.dfsek.terra.addons.feature.locator.locators;
import java.util.Random;
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;
public class RandomLocator implements Locator {
private final Range height;
private final Range points;
public RandomLocator(Range height, Range points) {
this.height = height;
this.points = points;
}
@Override
public BinaryColumn getSuitableCoordinates(Column column) {
long seed = column.getWorld().getSeed();
seed = 31 * seed + column.getX();
seed = 31 * seed + column.getZ();
Random r = new Random(seed);
int size = points.get(r);
BinaryColumn results = new BinaryColumn(column.getMinY(), column.getMaxY());
for(int i = 0; i < size; i++) {
results.set(height.get(r));
}
return results;
}
}

View File

@ -0,0 +1,32 @@
package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.api.Platform;
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.Range;
import com.dfsek.terra.api.world.Column;
public class SurfaceLocator implements Locator {
private final Range search;
private final BlockState air;
public SurfaceLocator(Range search, Platform platform) {
this.search = search;
this.air = platform.getWorldHandle().air();
}
@Override
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)) {
location.set(y);
return location;
}
}
return location;
}
}

View File

@ -0,0 +1,26 @@
package com.dfsek.terra.addons.feature.locator.patterns;
import java.util.function.Predicate;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.Column;
public class MatchPattern implements Pattern {
private final Range range;
private final Predicate<BlockState> matches;
public MatchPattern(Range range, Predicate<BlockState> matches) {
this.range = range;
this.matches = matches;
}
@Override
public boolean matches(int y, Column column) {
for(int i : range) {
if(!matches.test(column.getBlock(y + i))) return false;
}
return true;
}
}

View File

@ -0,0 +1,20 @@
package com.dfsek.terra.addons.feature.locator.patterns;
import com.dfsek.terra.api.world.Column;
public interface Pattern {
boolean matches(int y, Column column);
default Pattern and(Pattern that) {
return (y, column) -> this.matches(y, column) && that.matches(y, column);
}
default Pattern or(Pattern that) {
return (y, column) -> this.matches(y, column) || that.matches(y, column);
}
default Pattern not() {
return (y, column) -> !this.matches(y, column);
}
}