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

Boolean distributors, pattern matching locator
This commit is contained in:
dfsek
2021-07-27 20:50:08 -07:00
committed by GitHub
19 changed files with 373 additions and 54 deletions

View File

@@ -1,40 +0,0 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Java CI with Gradle
on:
push:
tags:
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build Terra
run: gradle shadowJar
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: Package
path: build/libs
- name: Publish release
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
prerelease: false
files: |
build/libs/Terra-*.jar
LICENSE

View File

@@ -1,7 +1,9 @@
package com.dfsek.terra.addons.feature.distributor;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.distributor.config.AndDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.NoiseDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.OrDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.PointSetDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.util.Point;
import com.dfsek.terra.addons.feature.distributor.util.PointTemplate;
@@ -36,6 +38,8 @@ public class DistributorAddon extends TerraAddon {
CheckedRegistry<Supplier<ObjectTemplate<Distributor>>> distributorRegistry = event.getPack().getOrCreateRegistry(DISTRIBUTOR_TOKEN);
distributorRegistry.register("NOISE", NoiseDistributorTemplate::new);
distributorRegistry.register("POINTS", PointSetDistributorTemplate::new);
distributorRegistry.register("AND", AndDistributorTemplate::new);
distributorRegistry.register("OR", OrDistributorTemplate::new);
event.getPack()
.applyLoader(Point.class, PointTemplate::new);

View File

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

View File

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

View File

@@ -1,8 +1,17 @@
package com.dfsek.terra.addons.feature.locator;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
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.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
@@ -23,6 +32,7 @@ import java.util.function.Supplier;
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 TerraPlugin main;
@@ -35,6 +45,18 @@ public class LocatorAddon extends TerraAddon {
CheckedRegistry<Supplier<ObjectTemplate<Locator>>> locatorRegistry = event.getPack().getOrCreateRegistry(LOCATOR_TOKEN);
locatorRegistry.register("SURFACE", () -> new SurfaceLocatorTemplate(main));
locatorRegistry.register("RANDOM", RandomLocatorTemplate::new);
locatorRegistry.register("PATTERN", PatternLocatorTemplate::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,22 @@
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,21 @@
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.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,30 @@
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 com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.config.meta.Meta;
import java.util.List;
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,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.Pattern;
import com.dfsek.terra.addons.feature.locator.patterns.match.MatchPattern;
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,16 @@
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,30 @@
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 com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.config.meta.Meta;
import java.util.List;
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,23 @@
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.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,17 @@
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.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,30 @@
package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.Column;
import java.util.ArrayList;
import java.util.List;
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 List<Integer> getSuitableCoordinates(Column column) {
List<Integer> locations = new ArrayList<>();
for(int y : search) {
if(pattern.matches(y, column)) locations.add(y);
}
return locations;
}
}

View File

@@ -0,0 +1,19 @@
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);
}
}

View File

@@ -0,0 +1,26 @@
package com.dfsek.terra.addons.feature.locator.patterns.match;
import com.dfsek.terra.addons.feature.locator.patterns.Pattern;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.Column;
import java.util.function.Predicate;
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

@@ -68,25 +68,25 @@ public class NoiseAddon extends TerraAddon {
noiseRegistry.register("IMAGE", ImageSamplerTemplate::new);
noiseRegistry.register("DOMAINWARP", DomainWarpTemplate::new);
noiseRegistry.register("DOMAIN_WARP", DomainWarpTemplate::new);
noiseRegistry.register("FBM", BrownianMotionTemplate::new);
noiseRegistry.register("PINGPONG", PingPongTemplate::new);
noiseRegistry.register("PING_PONG", PingPongTemplate::new);
noiseRegistry.register("RIDGED", RidgedFractalTemplate::new);
noiseRegistry.register("OPENSIMPLEX2", () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new));
noiseRegistry.register("OPENSIMPLEX2S", () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new));
noiseRegistry.register("OPEN_SIMPLEX_2", () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new));
noiseRegistry.register("OPEN_SIMPLEX_2S", () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new));
noiseRegistry.register("PERLIN", () -> new SimpleNoiseTemplate(PerlinSampler::new));
noiseRegistry.register("SIMPLEX", () -> new SimpleNoiseTemplate(SimplexSampler::new));
noiseRegistry.register("GABOR", GaborNoiseTemplate::new);
noiseRegistry.register("VALUE", () -> new SimpleNoiseTemplate(ValueSampler::new));
noiseRegistry.register("VALUECUBIC", () -> new SimpleNoiseTemplate(ValueCubicSampler::new));
noiseRegistry.register("VALUE_CUBIC", () -> new SimpleNoiseTemplate(ValueCubicSampler::new));
noiseRegistry.register("CELLULAR", CellularNoiseTemplate::new);
noiseRegistry.register("WHITENOISE", () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new));
noiseRegistry.register("WHITE_NOISE", () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new));
noiseRegistry.register("GAUSSIAN", () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new));
noiseRegistry.register("CONSTANT", ConstantNoiseTemplate::new);

View File

@@ -14,7 +14,12 @@ import java.util.Map;
public class RangeLoader implements TypeLoader<Range> {
@Override
public Range load(AnnotatedType type, Object o, ConfigLoader configLoader) throws LoadException {
Map<String, Integer> map = (Map<String, Integer>) o;
return new ConstantRange(map.get("min"), map.get("max"));
if(o instanceof Map) {
Map<String, Integer> map = (Map<String, Integer>) o;
return new ConstantRange(map.get("min"), map.get("max"));
} else {
int h = configLoader.loadType(Integer.class, o);
return new ConstantRange(h, h+1);
}
}
}

View File

@@ -42,6 +42,8 @@ import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.preprocessor.MetaListLikePreprocessor;
import com.dfsek.terra.config.preprocessor.MetaMapPreprocessor;
import com.dfsek.terra.config.preprocessor.MetaNumberPreprocessor;
import com.dfsek.terra.config.preprocessor.MetaStringPreprocessor;
import com.dfsek.terra.config.preprocessor.MetaValuePreprocessor;
import com.dfsek.terra.config.prototype.ProtoConfig;
@@ -241,17 +243,25 @@ public class ConfigPackImpl implements ConfigPack {
main.getEventManager().callEvent(new ConfigurationDiscoveryEvent(this, loader, configurations::put)); // Create all the configs.
MetaValuePreprocessor valuePreprocessor = new MetaValuePreprocessor(configurations);
selfLoader.registerPreprocessor(Meta.class, valuePreprocessor);
abstractConfigLoader.registerPreprocessor(Meta.class, valuePreprocessor);
MetaStringPreprocessor stringPreprocessor = new MetaStringPreprocessor(configurations);
selfLoader.registerPreprocessor(Meta.class, stringPreprocessor);
abstractConfigLoader.registerPreprocessor(Meta.class, stringPreprocessor);
MetaListLikePreprocessor listPreprocessor = new MetaListLikePreprocessor(configurations);
selfLoader.registerPreprocessor(Meta.class, listPreprocessor);
abstractConfigLoader.registerPreprocessor(Meta.class, listPreprocessor);
MetaStringPreprocessor stringPreprocessor = new MetaStringPreprocessor(configurations);
selfLoader.registerPreprocessor(Meta.class, stringPreprocessor);
abstractConfigLoader.registerPreprocessor(Meta.class, stringPreprocessor);
MetaMapPreprocessor mapPreprocessor = new MetaMapPreprocessor(configurations);
selfLoader.registerPreprocessor(Meta.class, mapPreprocessor);
abstractConfigLoader.registerPreprocessor(Meta.class, mapPreprocessor);
MetaValuePreprocessor valuePreprocessor = new MetaValuePreprocessor(configurations);
selfLoader.registerPreprocessor(Meta.class, valuePreprocessor);
abstractConfigLoader.registerPreprocessor(Meta.class, valuePreprocessor);
MetaNumberPreprocessor numberPreprocessor = new MetaNumberPreprocessor(configurations);
selfLoader.registerPreprocessor(Meta.class, numberPreprocessor);
abstractConfigLoader.registerPreprocessor(Meta.class, numberPreprocessor);
Map<ConfigType<? extends ConfigTemplate, ?>, List<Configuration>> configs = new HashMap<>();