diff --git a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java index 89e4178e6..7f8d69850 100644 --- a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -12,15 +12,19 @@ import org.polydev.gaea.math.Range; import org.polydev.gaea.util.FastRandom; import org.polydev.gaea.world.carving.Carver; import org.polydev.gaea.world.carving.Worm; +import parsii.eval.Expression; +import parsii.eval.Parser; +import parsii.eval.Scope; +import parsii.eval.Variable; +import parsii.tokenizer.ParseException; +import java.util.List; import java.util.Random; public class UserDefinedCarver extends Carver { private final double[] start; // 0, 1, 2 = x, y, z. private final double[] mutate; // 0, 1, 2 = x, y, z. 3 = radius. - private final double[] radiusMultiplier; private final Range length; - private final Range radius; private final int hash; private final int topCut; private final int bottomCut; @@ -28,24 +32,38 @@ public class UserDefinedCarver extends Carver { private Range recalc = new Range(8, 10); private double recalcMagnitude = 3; private final CarverTemplate config; + private final Expression xRad; + private final Expression yRad; + private final Expression zRad; + private final Variable lengthVar; + private final Variable position; - public UserDefinedCarver(Range height, Range radius, Range length, double[] start, double[] mutate, double[] radiusMultiplier, int hash, int topCut, int bottomCut, CarverTemplate config) { + public UserDefinedCarver(Range height, Range length, double[] start, double[] mutate, List radii, Scope parent, int hash, int topCut, int bottomCut, CarverTemplate config) throws ParseException { super(height.getMin(), height.getMax()); - this.radius = radius; this.length = length; this.start = start; this.mutate = mutate; - this.radiusMultiplier = radiusMultiplier; this.hash = hash; this.topCut = topCut; this.bottomCut = bottomCut; this.config = config; + + Parser p = new Parser(); + Scope s = new Scope().withParent(parent); + + lengthVar = s.create("length"); + position = s.create("position"); + + xRad = p.parse(radii.get(0), s); + yRad = p.parse(radii.get(1), s); + zRad = p.parse(radii.get(2), s); + } @Override public Worm getWorm(long l, Vector vector) { Random r = new FastRandom(l + hash); - return new UserDefinedWorm(length.get(r) / 2, r, vector, radius.getMax(), topCut, bottomCut); + return new UserDefinedWorm(length.get(r) / 2, r, vector, topCut, bottomCut); } public void setStep(double step) { @@ -75,19 +93,18 @@ public class UserDefinedCarver extends Carver { private class UserDefinedWorm extends Worm { private final Vector direction; - private final int maxRad; - private double runningRadius; private int steps; private int nextDirection = 0; private double[] currentRotation = new double[3]; - public UserDefinedWorm(int length, Random r, Vector origin, int maxRad, int topCut, int bottomCut) { + public UserDefinedWorm(int length, Random r, Vector origin, int topCut, int bottomCut) { super(length, r, origin); super.setTopCut(topCut); super.setBottomCut(bottomCut); - runningRadius = radius.get(r); - this.maxRad = maxRad; direction = new Vector((r.nextDouble() - 0.5D) * start[0], (r.nextDouble() - 0.5D) * start[1], (r.nextDouble() - 0.5D) * start[2]).normalize().multiply(step); + position.setValue(0); + lengthVar.setValue(length); + setRadius(new int[] {(int) (xRad.evaluate()), (int) (yRad.evaluate()), (int) (zRad.evaluate())}); } @Override @@ -102,9 +119,8 @@ public class UserDefinedCarver extends Carver { nextDirection += recalc.get(getRandom()); } steps++; - setRadius(new int[] {(int) (runningRadius * radiusMultiplier[0]), (int) (runningRadius * radiusMultiplier[1]), (int) (runningRadius * radiusMultiplier[2])}); - runningRadius += (getRandom().nextDouble() - 0.5) * mutate[3]; - runningRadius = FastMath.max(FastMath.min(runningRadius, maxRad), 1); + position.setValue(steps); + setRadius(new int[] {(int) (xRad.evaluate()), (int) (yRad.evaluate()), (int) (zRad.evaluate())}); direction.rotateAroundX(FastMath.toRadians(currentRotation[0] * mutate[0])); direction.rotateAroundY(FastMath.toRadians(currentRotation[1] * mutate[1])); direction.rotateAroundZ(FastMath.toRadians(currentRotation[2] * mutate[2])); diff --git a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java b/src/main/java/com/dfsek/terra/config/base/ConfigPack.java index be91c9b17..2b574245f 100644 --- a/src/main/java/com/dfsek/terra/config/base/ConfigPack.java +++ b/src/main/java/com/dfsek/terra/config/base/ConfigPack.java @@ -2,6 +2,7 @@ package com.dfsek.terra.config.base; import com.dfsek.tectonic.abstraction.AbstractConfigLoader; import com.dfsek.tectonic.exception.ConfigException; +import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.terra.Debug; import com.dfsek.terra.biome.UserDefinedBiome; @@ -145,9 +146,13 @@ public class ConfigPack { .then(streams -> carverTemplates.addAll(abstractConfigLoader.load(streams, CarverTemplate::new))) .close(); - CarverFactory carverFactory = new CarverFactory(); + CarverFactory carverFactory = new CarverFactory(this); carverTemplates.forEach(carver -> { - carverRegistry.add(carver.getID(), carverFactory.build(carver)); + try { + carverRegistry.add(carver.getID(), carverFactory.build(carver)); + } catch(LoadException e) { + throw new RuntimeException(e); + } Debug.info("Loaded carver " + carver.getID()); }); diff --git a/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java b/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java index 7658a8062..fb08f65b0 100644 --- a/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java +++ b/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java @@ -1,15 +1,35 @@ package com.dfsek.terra.config.factories; +import com.dfsek.tectonic.exception.LoadException; import com.dfsek.terra.carving.UserDefinedCarver; +import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.templates.CarverTemplate; +import parsii.tokenizer.ParseException; + +import java.util.Arrays; +import java.util.List; public class CarverFactory implements TerraFactory { + private final ConfigPack pack; + + public CarverFactory(ConfigPack pack) { + this.pack = pack; + } + @Override - public UserDefinedCarver build(CarverTemplate config) { + public UserDefinedCarver build(CarverTemplate config) throws LoadException { double[] start = new double[] {config.getStartX(), config.getStartY(), config.getStartZ()}; - double[] mutate = new double[] {config.getMutateX(), config.getMutateY(), config.getMutateZ(), config.getMutateRadius()}; - double[] radius = new double[] {config.getRadMX(), config.getRadMY(), config.getRadMZ()}; + double[] mutate = new double[] {config.getMutateX(), config.getMutateY(), config.getMutateZ()}; + List radius = Arrays.asList(config.getRadMX(), config.getRadMY(), config.getRadMZ()); int hash = config.getID().hashCode(); - return new UserDefinedCarver(config.getHeight(), config.getRadius(), config.getLength(), start, mutate, radius, hash, config.getCutTop(), config.getCutBottom(), config); + UserDefinedCarver carver; + try { + carver = new UserDefinedCarver(config.getHeight(), config.getLength(), start, mutate, radius, pack.getVarScope(), hash, config.getCutTop(), config.getCutBottom(), config); + } catch(ParseException e) { + throw new LoadException("Unable to parse radius equations", e); + } + carver.setRecalc(config.getRecalc()); + carver.setRecalcMagnitude(config.getRecaclulateMagnitude()); + return carver; } } diff --git a/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java b/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java index 79e05350b..6c868d7c8 100644 --- a/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java +++ b/src/main/java/com/dfsek/terra/config/factories/TerraFactory.java @@ -1,7 +1,8 @@ package com.dfsek.terra.config.factories; import com.dfsek.tectonic.config.ConfigTemplate; +import com.dfsek.tectonic.exception.LoadException; public interface TerraFactory { - O build(C config); + O build(C config) throws LoadException; } diff --git a/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java b/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java index 906726da9..aba3f7c79 100644 --- a/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java +++ b/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java @@ -23,6 +23,16 @@ public class CarverTemplate implements ConfigTemplate { @Default private int step = 2; + @Value("recalculate-magnitude") + @Default + @Abstractable + private double recaclulateMagnitude = 4; + + @Value("recalculate-direction") + @Abstractable + @Default + private Range recalc = new Range(8, 10); + @Value("length") @Abstractable private Range length; @@ -39,21 +49,17 @@ public class CarverTemplate implements ConfigTemplate { @Abstractable private double startZ; - @Value("start.radius.multiply.x") + @Value("start.radius.x") @Abstractable - private double radMX; + private String radMX; - @Value("start.radius.multiply.y") + @Value("start.radius.y") @Abstractable - private double radMY; + private String radMY; - @Value("start.radius.multiply.z") + @Value("start.radius.z") @Abstractable - private double radMZ; - - @Value("start.radius") - @Abstractable - private Range radius; + private String radMZ; @Value("start.height") @Abstractable @@ -81,10 +87,6 @@ public class CarverTemplate implements ConfigTemplate { @Abstractable private double mutateZ; - @Value("mutate.radius") - @Abstractable - private double mutateRadius; - @Value("palette.top") @Abstractable private CarverPalette top; @@ -135,22 +137,18 @@ public class CarverTemplate implements ConfigTemplate { return startZ; } - public double getRadMX() { + public String getRadMX() { return radMX; } - public double getRadMY() { + public String getRadMY() { return radMY; } - public double getRadMZ() { + public String getRadMZ() { return radMZ; } - public Range getRadius() { - return radius; - } - public Range getHeight() { return height; } @@ -175,10 +173,6 @@ public class CarverTemplate implements ConfigTemplate { return mutateZ; } - public double getMutateRadius() { - return mutateRadius; - } - public CarverPalette getTop() { return top; } @@ -202,4 +196,12 @@ public class CarverTemplate implements ConfigTemplate { public Set getUpdate() { return update; } + + public Range getRecalc() { + return recalc; + } + + public double getRecaclulateMagnitude() { + return recaclulateMagnitude; + } }