Merge pull request #57 from PolyhedralDev/biome

Biome Stuff
This commit is contained in:
dfsek
2021-02-07 15:40:45 -07:00
committed by GitHub
358 changed files with 5714 additions and 3985 deletions

View File

@@ -1,6 +1,6 @@
import com.dfsek.terra.getGitHash
val versionObj = Version("3", "1", "1", true)
val versionObj = Version("4", "0", "0", true)
allprojects {
version = versionObj

View File

@@ -7,7 +7,6 @@ import org.gradle.kotlin.dsl.repositories
fun Project.configureDependencies() {
repositories {
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
maven { url = uri("http://maven.enginehub.org/repo/") }
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
@@ -19,6 +18,8 @@ fun Project.configureDependencies() {
dependencies {
"testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0")
"testImplementation"("org.yaml:snakeyaml:1.27")
"testImplementation"("com.googlecode.json-simple:json-simple:1.1.1")
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
"compileOnly"("org.jetbrains:annotations:20.1.0")
}

View File

@@ -14,7 +14,7 @@ dependencies {
"shadedApi"("commons-io:commons-io:2.4")
"shadedApi"("com.scireum:parsii:1.2.1")
"shadedApi"("com.dfsek:Tectonic:1.1.0")
"shadedApi"("com.dfsek:Tectonic:1.2.3")
"shadedApi"("net.jafama:jafama:2.3.2")
"shadedApi"("org.yaml:snakeyaml:1.27")

View File

@@ -1,18 +0,0 @@
package com.dfsek.terra;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.profiler.DataType;
import com.dfsek.terra.api.profiler.Measurement;
import com.dfsek.terra.api.profiler.WorldProfiler;
public class TerraProfiler extends WorldProfiler {
public TerraProfiler(World w) {
super(w);
this
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime")
.addMeasurement(new Measurement(10000000, DataType.PERIOD_MILLISECONDS), "TreeTime")
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
.addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime")
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime");
}
}

View File

@@ -1,55 +0,0 @@
package com.dfsek.terra;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.generator.GeneratorWrapper;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.biome.BiomeZone;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.config.base.ConfigPack;
public class TerraWorld {
private final TerraBiomeGrid grid;
private final BiomeZone zone;
private final ConfigPack config;
private final boolean safe;
private final TerraProfiler profiler;
private final World world;
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
config = c;
profiler = new TerraProfiler(w);
this.grid = new TerraBiomeGrid.TerraBiomeGridBuilder(w.getSeed(), c, main).build();
this.zone = grid.getZone();
this.world = w;
safe = true;
}
public World getWorld() {
return world;
}
public static boolean isTerraWorld(World w) {
return w.getGenerator().getHandle() instanceof GeneratorWrapper;
}
public TerraBiomeGrid getGrid() {
return grid;
}
public ConfigPack getConfig() {
return config;
}
public BiomeZone getZone() {
return zone;
}
public boolean isSafe() {
return safe;
}
public TerraProfiler getProfiler() {
return profiler;
}
}

View File

@@ -1,8 +0,0 @@
package com.dfsek.terra.api;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.Handle;
public interface Entity extends Handle {
Location getLocation();
}

View File

@@ -1,65 +0,0 @@
package com.dfsek.terra.api;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.math.GridSpawn;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.math.noise.samplers.Normalizer;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.palette.PaletteHolder;
import com.dfsek.terra.biome.palette.PaletteLayer;
import com.dfsek.terra.carving.CarverPalette;
import com.dfsek.terra.config.loaders.ImageLoaderLoader;
import com.dfsek.terra.config.loaders.MaterialSetLoader;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.RangeLoader;
import com.dfsek.terra.config.loaders.config.FloraLayerLoader;
import com.dfsek.terra.config.loaders.config.GridSpawnLoader;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.config.loaders.config.OreConfigLoader;
import com.dfsek.terra.config.loaders.config.OreHolderLoader;
import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader;
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;
import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader;
import com.dfsek.terra.generation.config.NoiseBuilder;
import com.dfsek.terra.image.ImageLoader;
import com.dfsek.terra.population.items.flora.FloraLayer;
import com.dfsek.terra.population.items.flora.TerraFlora;
import com.dfsek.terra.population.items.ores.Ore;
import com.dfsek.terra.population.items.ores.OreConfig;
import com.dfsek.terra.population.items.ores.OreHolder;
import com.dfsek.terra.population.items.tree.TreeLayer;
import com.dfsek.terra.util.MaterialSet;
public class GenericLoaders implements LoaderRegistrar {
private final TerraPlugin main;
public GenericLoaders(TerraPlugin main) {
this.main = main;
}
@Override
public void register(TypeRegistry registry) {
registry.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
.registerLoader(Range.class, new RangeLoader())
.registerLoader(CarverPalette.class, new CarverPaletteLoader())
.registerLoader(GridSpawn.class, new GridSpawnLoader())
.registerLoader(PaletteHolder.class, new PaletteHolderLoader())
.registerLoader(PaletteLayer.class, new PaletteLayerLoader())
.registerLoader(FloraLayer.class, new FloraLayerLoader())
.registerLoader(Ore.Type.class, (t, o, l) -> Ore.Type.valueOf(o.toString()))
.registerLoader(OreConfig.class, new OreConfigLoader())
.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
.registerLoader(TreeLayer.class, new TreeLayerLoader())
.registerLoader(MaterialSet.class, new MaterialSetLoader())
.registerLoader(OreHolder.class, new OreHolderLoader())
.registerLoader(ImageLoader.class, new ImageLoaderLoader())
.registerLoader(TerraBiomeGrid.Type.class, (t, o, l) -> TerraBiomeGrid.Type.valueOf(o.toString()))
.registerLoader(ImageLoader.Channel.class, (t, o, l) -> ImageLoader.Channel.valueOf(o.toString()))
.registerLoader(ImageLoader.Align.class, (t, o, l) -> ImageLoader.Align.valueOf(o.toString()))
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf(o.toString()))
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()));
}
}

View File

@@ -1,4 +0,0 @@
package com.dfsek.terra.api;
public interface Player extends Entity {
}

View File

@@ -1,13 +1,15 @@
package com.dfsek.terra.api.platform;
package com.dfsek.terra.api.core;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.LoaderRegistrar;
import com.dfsek.terra.api.language.Language;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.config.base.PluginConfig;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.debug.DebugLogger;
import com.dfsek.terra.registry.ConfigRegistry;
import com.dfsek.terra.world.TerraWorld;
import java.io.File;
import java.util.logging.Logger;
@@ -38,4 +40,14 @@ public interface TerraPlugin extends LoaderRegistrar {
void saveDefaultConfig();
String platformName();
default void packPreLoadCallback(ConfigPack pack) {
}
default void packPostLoadCallback(ConfigPack pack) {
}
DebugLogger getDebugLogger();
}

View File

@@ -0,0 +1,4 @@
package com.dfsek.terra.api.core.event;
public interface Event {
}

View File

@@ -0,0 +1,4 @@
package com.dfsek.terra.api.core.event;
public interface EventListener {
}

View File

@@ -0,0 +1,7 @@
package com.dfsek.terra.api.core.event;
public interface EventManager {
void callEvent(Event event);
void registerListener(EventListener listener);
}

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.math;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.generation.math.Sampler;
import com.dfsek.terra.world.generation.math.Sampler;
import net.jafama.FastMath;
import java.util.List;
@@ -91,7 +91,103 @@ public final class MathUtil {
return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1)));
}
public static int normalizeIndex(double val, int size) {
return FastMath.max(FastMath.min(FastMath.floorToInt(((val + 1D) / 2D) * size), size - 1), 0);
}
public static long squash(int first, int last) {
return (((long) first) << 32) | (last & 0xffffffffL);
}
/**
* Clamp value to range of [-1, 1]
*
* @param in Value to clamp
* @return Clamped value
*/
public static double clamp(double in) {
return FastMath.min(FastMath.max(in, -1), 1);
}
/**
* Compute the value in a normally distributed data set that has probability p.
*
* @param p Probability of value
* @param mu Mean of data
* @param sigma Standard deviation of data
* @return Value corresponding to input probability
*/
public static double normalInverse(double p, double mu, double sigma) {
if(p < 0 || p > 1)
throw new IllegalArgumentException("Probability must be in range [0, 1]");
if(sigma < 0)
throw new IllegalArgumentException("Standard deviation must be positive.");
if(p == 0)
return Double.NEGATIVE_INFINITY;
if(p == 1)
return Double.POSITIVE_INFINITY;
if(sigma == 0)
return mu;
double q, r, val;
q = p - 0.5;
if(FastMath.abs(q) <= .425) {
r = .180625 - q * q;
val =
q * (((((((r * 2509.0809287301226727 +
33430.575583588128105) * r + 67265.770927008700853) * r +
45921.953931549871457) * r + 13731.693765509461125) * r +
1971.5909503065514427) * r + 133.14166789178437745) * r +
3.387132872796366608)
/ (((((((r * 5226.495278852854561 +
28729.085735721942674) * r + 39307.89580009271061) * r +
21213.794301586595867) * r + 5394.1960214247511077) * r +
687.1870074920579083) * r + 42.313330701600911252) * r + 1);
} else {
if(q > 0) {
r = 1 - p;
} else {
r = p;
}
r = FastMath.sqrt(-FastMath.log(r));
if(r <= 5) {
r += -1.6;
val = (((((((r * 7.7454501427834140764e-4 +
.0227238449892691845833) * r + .24178072517745061177) *
r + 1.27045825245236838258) * r +
3.64784832476320460504) * r + 5.7694972214606914055) *
r + 4.6303378461565452959) * r +
1.42343711074968357734)
/ (((((((r *
1.05075007164441684324e-9 + 5.475938084995344946e-4) *
r + .0151986665636164571966) * r +
.14810397642748007459) * r + .68976733498510000455) *
r + 1.6763848301838038494) * r +
2.05319162663775882187) * r + 1);
} else {
r += -5;
val = (((((((r * 2.01033439929228813265e-7 +
2.71155556874348757815e-5) * r +
.0012426609473880784386) * r + .026532189526576123093) *
r + .29656057182850489123) * r +
1.7848265399172913358) * r + 5.4637849111641143699) *
r + 6.6579046435011037772)
/ (((((((r *
2.04426310338993978564e-15 + 1.4215117583164458887e-7) *
r + 1.8463183175100546818e-5) * r +
7.868691311456132591e-4) * r + .0148753612908506148525)
* r + .13692988092273580531) * r +
.59983220655588793769) * r + 1);
}
if(q < 0.0) {
val = -val;
}
}
return mu + sigma * val;
}
}

View File

@@ -1,15 +1,15 @@
package com.dfsek.terra.api.math;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import net.jafama.FastMath;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
@SuppressWarnings("unchecked")
public class ProbabilityCollection<E> {
private final Set<Object> cont = new HashSet<>();
private final Set<E> cont = new HashSet<>();
private Object[] array = new Object[0];
private int size;
@@ -29,24 +29,14 @@ public class ProbabilityCollection<E> {
return (E) array[r.nextInt(array.length)];
}
private static double getNoise(double x, double y, double z, NoiseSampler sampler) {
double n = sampler.getNoise(x, y, z);
return FastMath.min(FastMath.max(n, -1), 1);
}
private static double getNoise(double x, double z, NoiseSampler sampler) {
double n = sampler.getNoise(x, z);
return FastMath.min(FastMath.max(n, -1), 1);
}
public E get(NoiseSampler n, double x, double y, double z) {
if(array.length == 0) return null;
return (E) array[FastMath.min(FastMath.floorToInt(((getNoise(x, y, z, n) + 1D) / 2D) * array.length), array.length - 1)];
return (E) array[MathUtil.normalizeIndex(n.getNoise(x, y, z), array.length)];
}
public E get(NoiseSampler n, double x, double z) {
if(array.length == 0) return null;
return (E) array[FastMath.min(FastMath.floorToInt(((getNoise(x, z, n) + 1D) / 2D) * array.length), array.length - 1)];
return (E) array[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)];
}
public int getTotalProbability() {
@@ -56,4 +46,51 @@ public class ProbabilityCollection<E> {
public int size() {
return size;
}
public Set<E> getContents() {
return new HashSet<>(cont);
}
public static final class Singleton<T> extends ProbabilityCollection<T> {
private final T single;
public Singleton(T single) {
this.single = single;
}
@Override
public ProbabilityCollection<T> add(T item, int probability) {
throw new UnsupportedOperationException();
}
@Override
public T get(Random r) {
return single;
}
@Override
public T get(NoiseSampler n, double x, double y, double z) {
return single;
}
@Override
public T get(NoiseSampler n, double x, double z) {
return single;
}
@Override
public int getTotalProbability() {
return 1;
}
@Override
public int size() {
return 1;
}
@Override
public Set<T> getContents() {
return Collections.singleton(single);
}
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.api.math.noise.samplers;
package com.dfsek.terra.api.math.noise;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
@@ -9,14 +9,14 @@ public interface NoiseSampler {
* <p>
* Noise output bounded between -1...1
*/
double getNoise(/*FNLdouble*/ double x, /*FNLdouble*/ double y);
double getNoise(double x, double y);
/**
* 3D noise at given position using current settings
* <p>
* Noise output bounded between -1...1
*/
double getNoise(/*FNLdouble*/ double x, /*FNLdouble*/ double y, /*FNLdouble*/ double z);
double getNoise(double x, double y, double z);
default double getNoise(Vector3 vector3) {
return getNoise(vector3.getX(), vector3.getY(), vector3.getZ());
@@ -25,4 +25,8 @@ public interface NoiseSampler {
default double getNoise(Vector2 vector2) {
return getNoise(vector2.getX(), vector2.getZ());
}
double getNoiseSeeded(int seed, double x, double y);
double getNoiseSeeded(int seed, double x, double y, double z);
}

View File

@@ -1,5 +1,10 @@
package com.dfsek.terra.api.math.noise.samplers;
package com.dfsek.terra.api.math.noise.normalizer;
import com.dfsek.terra.api.math.noise.NoiseSampler;
/**
* Normalizer to linearly scale data's range.
*/
public class LinearNormalizer extends Normalizer {
private final double min;
private final double max;

View File

@@ -0,0 +1,45 @@
package com.dfsek.terra.api.math.noise.normalizer;
import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import net.jafama.FastMath;
/**
* Normalizer to redistribute normally distributed data to a continuous distribution via an automatically generated lookup table.
*/
public class NormalNormalizer extends Normalizer {
private final double[] lookup;
public NormalNormalizer(NoiseSampler sampler, int buckets, double mean, double standardDeviation) {
super(sampler);
this.lookup = new double[buckets];
for(int i = 0; i < buckets; i++) {
lookup[i] = MathUtil.normalInverse((double) i / buckets, mean, standardDeviation);
}
}
@Override
public double normalize(double in) {
int start = 0;
int end = lookup.length - 1;
while(start + 1 < end) {
int mid = start + (end - start) / 2;
if(lookup[mid] <= in) {
start = mid;
} else {
end = mid;
}
}
double left = FastMath.abs(lookup[start] - in);
double right = FastMath.abs(lookup[end] - in);
double fin;
if(left <= right) {
fin = (double) start / (lookup.length);
} else fin = (double) end / (lookup.length);
return (fin - 0.5) * 2;
}
}

View File

@@ -1,4 +1,6 @@
package com.dfsek.terra.api.math.noise.samplers;
package com.dfsek.terra.api.math.noise.normalizer;
import com.dfsek.terra.api.math.noise.NoiseSampler;
public abstract class Normalizer implements NoiseSampler {
private final NoiseSampler sampler;
@@ -19,7 +21,17 @@ public abstract class Normalizer implements NoiseSampler {
return normalize(sampler.getNoise(x, y, z));
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return normalize(sampler.getNoiseSeeded(seed, x, y));
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return normalize(sampler.getNoiseSeeded(seed, x, y, z));
}
public enum NormalType {
LINEAR, NONE
LINEAR, NORMAL
}
}

View File

@@ -0,0 +1,34 @@
package com.dfsek.terra.api.math.noise.samplers;
import com.dfsek.terra.api.math.noise.NoiseSampler;
/**
* Sampler implementation that returns a constant.
*/
public class ConstantSampler implements NoiseSampler {
private final double constant;
public ConstantSampler(double constant) {
this.constant = constant;
}
@Override
public double getNoise(double x, double y) {
return constant;
}
@Override
public double getNoise(double x, double y, double z) {
return constant;
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return constant;
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return constant;
}
}

View File

@@ -0,0 +1,44 @@
package com.dfsek.terra.api.math.noise.samplers;
import com.dfsek.terra.api.math.noise.NoiseSampler;
public class DomainWarpedSampler implements NoiseSampler {
private final NoiseSampler function;
private final NoiseSampler warp;
private final int seed;
private final double amplitude;
public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, int seed, double amplitude) {
this.function = function;
this.warp = warp;
this.seed = seed;
this.amplitude = amplitude;
}
@Override
public double getNoise(double x, double y) {
return getNoiseSeeded(seed, x, y);
}
@Override
public double getNoise(double x, double y, double z) {
return getNoiseSeeded(seed, x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return function.getNoise(
x + warp.getNoiseSeeded(seed, x, y) * amplitude,
y + warp.getNoiseSeeded(seed + 1, x, y) * amplitude
);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return function.getNoise(
x + warp.getNoiseSeeded(seed, x, y, z) * amplitude,
y + warp.getNoiseSeeded(seed + 1, x, y, z) * amplitude,
z + warp.getNoiseSeeded(seed + 2, x, y, z) * amplitude
);
}
}

View File

@@ -0,0 +1,82 @@
package com.dfsek.terra.api.math.noise.samplers;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.parsii.defined.UserDefinedFunction;
import com.dfsek.terra.api.math.parsii.noise.NoiseFunction2;
import com.dfsek.terra.api.math.parsii.noise.NoiseFunction3;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
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.Map;
import java.util.stream.Collectors;
/**
* Sampler implementation using parsii expression
*/
public class ExpressionSampler implements NoiseSampler {
private final Expression expression;
private final Variable x;
private final Variable y;
private final Variable z;
public ExpressionSampler(String equation, Scope parent, long seed, Map<String, NoiseSeeded> functions, Map<String, FunctionTemplate> definedFunctions) throws ParseException {
Parser parser = new Parser();
Scope scope = new Scope().withParent(parent);
this.x = scope.create("x");
this.y = scope.create("y");
this.z = scope.create("z");
functions.forEach((id, noise) -> {
switch(noise.getDimensions()) {
case 2:
parser.registerFunction(id, new NoiseFunction2(seed, noise));
break;
case 3:
parser.registerFunction(id, new NoiseFunction3(seed, noise));
break;
}
});
for(Map.Entry<String, FunctionTemplate> entry : definedFunctions.entrySet()) {
String id = entry.getKey();
FunctionTemplate fun = entry.getValue();
Scope functionScope = new Scope().withParent(parent);
List<Variable> variables = fun.getArgs().stream().map(functionScope::create).collect(Collectors.toList());
parser.registerFunction(id, new UserDefinedFunction(parser.parse(fun.getFunction(), functionScope), variables));
}
this.expression = parser.parse(equation, scope);
}
@Override
public synchronized double getNoise(double x, double y) {
return getNoise(x, 0, y);
}
@Override
public synchronized double getNoise(double x, double y, double z) {
this.x.setValue(x);
this.y.setValue(y);
this.z.setValue(z);
return expression.evaluate();
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return getNoise(x, y, z);
}
}

View File

@@ -0,0 +1,70 @@
package com.dfsek.terra.api.math.noise.samplers;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import net.jafama.FastMath;
import java.awt.image.BufferedImage;
public class ImageSampler implements NoiseSampler {
private final BufferedImage image;
private final Channel channel;
private final double frequency;
public ImageSampler(BufferedImage image, Channel channel, double frequency) {
this.image = image;
this.channel = channel;
this.frequency = frequency;
}
@Override
public double getNoise(double x, double y) {
return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * 2;
}
@Override
public double getNoise(double x, double y, double z) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return getNoise(x, y, z);
}
public enum Channel {
RED {
@Override
public int getChannel(int mashed) {
return (mashed >> 16) & 0xff;
}
}, GREEN {
@Override
public int getChannel(int mashed) {
return (mashed >> 8) & 0xff;
}
}, BLUE {
@Override
public int getChannel(int mashed) {
return mashed & 0xff;
}
}, GRAYSCALE {
@Override
public int getChannel(int mashed) {
return (RED.getChannel(mashed) + GREEN.getChannel(mashed) + BLUE.getChannel(mashed)) / 3;
}
}, ALPHA {
@Override
public int getChannel(int mashed) {
return (mashed >> 24) & 0xff;
}
};
public abstract int getChannel(int mashed);
}
}

View File

@@ -1,30 +0,0 @@
package com.dfsek.terra.api.math.parsii;
import com.dfsek.terra.api.util.FastRandom;
import parsii.eval.Expression;
import parsii.eval.Function;
import java.util.List;
/**
* Provides access to a PRNG ({@link com.dfsek.terra.api.util.FastRandom})
* <p>
* Takes 1 argument, which sets the seed
*/
public class RandomFunction implements Function {
@Override
public int getNumberOfArguments() {
return 1;
}
@Override
public double eval(List<Expression> list) {
long seed = (long) list.get(0).evaluate();
return new FastRandom(seed).nextDouble();
}
@Override
public boolean isNaturalFunction() {
return true;
}
}

View File

@@ -0,0 +1,35 @@
package com.dfsek.terra.api.math.parsii.defined;
import parsii.eval.Expression;
import parsii.eval.Function;
import parsii.eval.Variable;
import java.util.List;
public class UserDefinedFunction implements Function {
private final Expression expression;
private final List<Variable> variables;
public UserDefinedFunction(Expression expression, List<Variable> variables) {
this.expression = expression;
this.variables = variables;
}
@Override
public int getNumberOfArguments() {
return variables.size();
}
@Override
public synchronized double eval(List<Expression> args) {
for(int i = 0; i < variables.size(); i++) {
variables.get(i).setValue(args.get(i).evaluate());
}
return expression.evaluate();
}
@Override
public boolean isNaturalFunction() {
return true;
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.api.math.noise;
package com.dfsek.terra.api.math.parsii.noise;
import parsii.eval.Function;

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.math.noise;
package com.dfsek.terra.api.math.parsii.noise;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.generation.config.NoiseBuilder;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.util.hash.HashMapDoubleDouble;
import parsii.eval.Expression;
@@ -11,8 +11,8 @@ public class NoiseFunction2 implements NoiseFunction {
private final NoiseSampler gen;
private final Cache cache = new Cache();
public NoiseFunction2(long seed, NoiseBuilder builder) {
this.gen = builder.build((int) seed);
public NoiseFunction2(long seed, NoiseSeeded builder) {
this.gen = builder.apply(seed);
}
@Override

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.math.noise;
package com.dfsek.terra.api.math.parsii.noise;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.generation.config.NoiseBuilder;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import parsii.eval.Expression;
import java.util.List;
@@ -9,8 +9,8 @@ import java.util.List;
public class NoiseFunction3 implements NoiseFunction {
private final NoiseSampler gen;
public NoiseFunction3(long seed, NoiseBuilder builder) {
this.gen = builder.build((int) seed);
public NoiseFunction3(long seed, NoiseSeeded builder) {
this.gen = builder.apply(seed);
}
@Override

View File

@@ -178,6 +178,14 @@ public class Vector2 implements Cloneable {
return this;
}
public int getBlockX() {
return FastMath.floorToInt(x);
}
public int getBlockZ() {
return FastMath.floorToInt(z);
}
@Override
public String toString() {
return "(" + x + ", " + z + ")";

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.math.voxel;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.vector.Vector3;
public class DeformedSphere extends VoxelGeometry {

View File

@@ -4,5 +4,10 @@ package com.dfsek.terra.api.platform;
* An interface that contains a platform delegate.
*/
public interface Handle {
/**
* Gets the delegate object.
*
* @return Delegate
*/
Object getHandle();
}

View File

@@ -0,0 +1,6 @@
package com.dfsek.terra.api.platform;
import com.dfsek.terra.api.platform.entity.Entity;
public interface Player extends Entity {
}

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.platform.block.state;
import com.dfsek.terra.api.platform.world.entity.EntityType;
import com.dfsek.terra.api.platform.entity.EntityType;
import org.jetbrains.annotations.NotNull;
public interface MobSpawner extends BlockState {

View File

@@ -0,0 +1,9 @@
package com.dfsek.terra.api.platform.entity;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.Handle;
public interface Entity extends Handle, CommandSender {
Location getLocation();
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.api.platform.world.entity;
package com.dfsek.terra.api.platform.entity;
import com.dfsek.terra.api.platform.Handle;

View File

@@ -1,69 +0,0 @@
package com.dfsek.terra.api.platform.generator;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.BiomeGrid;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Random;
public interface ChunkGenerator extends Handle {
boolean isParallelCapable();
boolean shouldGenerateCaves();
boolean shouldGenerateDecorations();
boolean shouldGenerateMobs();
boolean shouldGenerateStructures();
ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome);
List<BlockPopulator> getDefaultPopulators(World world);
@Nullable
TerraChunkGenerator getTerraGenerator();
interface ChunkData extends Handle {
/**
* Get the maximum height for the chunk.
* <p>
* Setting blocks at or above this height will do nothing.
*
* @return the maximum height
*/
int getMaxHeight();
/**
* Set the block at x,y,z in the chunk data to material.
* <p>
* Setting blocks outside the chunk's bounds does nothing.
*
* @param x the x location in the chunk from 0-15 inclusive
* @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive)
* @param z the z location in the chunk from 0-15 inclusive
* @param blockData the type to set the block to
*/
void setBlock(int x, int y, int z, @NotNull BlockData blockData);
/**
* Get the type and data of the block at x, y, z.
* <p>
* Getting blocks outside the chunk's bounds returns air.
*
* @param x the x location in the chunk from 0-15 inclusive
* @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive)
* @param z the z location in the chunk from 0-15 inclusive
* @return the data of the block or the BlockData for air if x, y or z are outside the chunk's bounds
*/
@NotNull BlockData getBlockData(int x, int y, int z);
}
}

View File

@@ -3,8 +3,7 @@ package com.dfsek.terra.api.platform.handle;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.MaterialData;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.platform.world.entity.EntityType;
import com.dfsek.terra.api.platform.entity.EntityType;
/**
* Interface to be implemented for world manipulation.
@@ -20,7 +19,5 @@ public interface WorldHandle {
MaterialData createMaterialData(String data);
Tree getTree(String id);
EntityType getEntity(String id);
}

View File

@@ -1,9 +1,8 @@
package com.dfsek.terra.api.platform.world;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.block.Block;
public interface Chunk extends Handle {
public interface Chunk extends ChunkAccess {
int getX();
int getZ();

View File

@@ -0,0 +1,31 @@
package com.dfsek.terra.api.platform.world;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.block.BlockData;
import org.jetbrains.annotations.NotNull;
public interface ChunkAccess extends Handle {
/**
* Set the block at x,y,z in the chunk data to material.
* <p>
* Setting blocks outside the chunk's bounds does nothing.
*
* @param x the x location in the chunk from 0-15 inclusive
* @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive)
* @param z the z location in the chunk from 0-15 inclusive
* @param blockData the type to set the block to
*/
void setBlock(int x, int y, int z, @NotNull BlockData blockData);
/**
* Get the type and data of the block at x, y, z.
* <p>
* Getting blocks outside the chunk's bounds returns air.
*
* @param x the x location in the chunk from 0-15 inclusive
* @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive)
* @param z the z location in the chunk from 0-15 inclusive
* @return the data of the block or the BlockData for air if x, y or z are outside the chunk's bounds
*/
@NotNull BlockData getBlockData(int x, int y, int z);
}

View File

@@ -1,6 +0,0 @@
package com.dfsek.terra.api.platform.world;
import com.dfsek.terra.api.platform.Handle;
public interface Tree extends Handle, com.dfsek.terra.api.world.tree.Tree {
}

View File

@@ -3,9 +3,9 @@ package com.dfsek.terra.api.platform.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.entity.Entity;
import com.dfsek.terra.api.platform.world.entity.EntityType;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import java.io.File;
import java.util.UUID;
@@ -31,7 +31,5 @@ public interface World extends Handle {
Block getBlockAt(Location l);
boolean generateTree(Location l, Tree vanillaTreeType);
Entity spawnEntity(Location location, EntityType entityType);
}

View File

@@ -1,6 +0,0 @@
package com.dfsek.terra.api.platform.world.entity;
import com.dfsek.terra.api.platform.Handle;
public interface Entity extends Handle {
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.api.platform.generator;
package com.dfsek.terra.api.platform.world.generator;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.world.Chunk;

View File

@@ -0,0 +1,43 @@
package com.dfsek.terra.api.platform.world.generator;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.world.BiomeGrid;
import com.dfsek.terra.api.platform.world.ChunkAccess;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Random;
public interface ChunkGenerator extends Handle {
boolean isParallelCapable();
boolean shouldGenerateCaves();
boolean shouldGenerateDecorations();
boolean shouldGenerateMobs();
boolean shouldGenerateStructures();
ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome);
List<BlockPopulator> getDefaultPopulators(World world);
@Nullable
TerraChunkGenerator getTerraGenerator();
interface ChunkData extends ChunkAccess {
/**
* Get the maximum height for the chunk.
* <p>
* Setting blocks at or above this height will do nothing.
*
* @return the maximum height
*/
int getMaxHeight();
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.api.platform.generator;
package com.dfsek.terra.api.platform.world.generator;
import com.dfsek.terra.api.platform.Handle;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.loot;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.platform.block.MaterialData;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.api.structures.loot.functions.AmountFunction;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.loot;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.platform.inventory.Inventory;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.api.util.GlueList;

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.structures.loot;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.api.util.GlueList;
import net.jafama.FastMath;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.loot.functions;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;

View File

@@ -36,11 +36,8 @@ import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThan
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanStatement;
import com.dfsek.terra.api.structures.parser.lang.operations.statements.NotEqualsStatement;
import com.dfsek.terra.api.structures.parser.lang.variables.Assignment;
import com.dfsek.terra.api.structures.parser.lang.variables.BooleanVariable;
import com.dfsek.terra.api.structures.parser.lang.variables.Declaration;
import com.dfsek.terra.api.structures.parser.lang.variables.Getter;
import com.dfsek.terra.api.structures.parser.lang.variables.NumberVariable;
import com.dfsek.terra.api.structures.parser.lang.variables.StringVariable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.api.structures.tokenizer.Token;
import com.dfsek.terra.api.structures.tokenizer.Tokenizer;
@@ -92,7 +89,7 @@ public class Parser {
}
private Keyword<?> parseLoopLike(Tokenizer tokens, Map<String, Variable<?>> variableMap, boolean loop) throws ParseException {
private Keyword<?> parseLoopLike(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
Token identifier = tokens.consume();
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP);
@@ -111,7 +108,7 @@ public class Parser {
}
}
private WhileKeyword parseWhileLoop(Tokenizer tokens, Map<String, Variable<?>> variableMap, Position start) throws ParseException {
private WhileKeyword parseWhileLoop(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start) throws ParseException {
Returnable<?> first = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(first, Returnable.ReturnType.BOOLEAN);
@@ -120,7 +117,7 @@ public class Parser {
return new WhileKeyword(parseStatementBlock(tokens, variableMap, true), (Returnable<Boolean>) first, start); // While loop
}
private IfKeyword parseIfStatement(Tokenizer tokens, Map<String, Variable<?>> variableMap, Position start, boolean loop) throws ParseException {
private IfKeyword parseIfStatement(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start, boolean loop) throws ParseException {
Returnable<?> condition = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN);
@@ -147,7 +144,7 @@ public class Parser {
return new IfKeyword(statement, (Returnable<Boolean>) condition, elseIf, elseBlock, start); // If statement
}
private Block parseStatementBlock(Tokenizer tokens, Map<String, Variable<?>> variableMap, boolean loop) throws ParseException {
private Block parseStatementBlock(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) {
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN);
@@ -162,21 +159,17 @@ public class Parser {
}
}
private ForKeyword parseForLoop(Tokenizer tokens, Map<String, Variable<?>> old, Position start) throws ParseException {
Map<String, Variable<?>> variableMap = new HashMap<>(old); // New scope
private ForKeyword parseForLoop(Tokenizer tokens, Map<String, Returnable.ReturnType> old, Position start) throws ParseException {
Map<String, Returnable.ReturnType> variableMap = new HashMap<>(old); // New scope
Token f = tokens.get();
ParserUtil.checkType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER);
Item<?> initializer;
if(f.isVariableDeclaration()) {
Variable<?> forVar = parseVariableDeclaration(tokens, ParserUtil.getVariableReturnType(f));
ParserUtil.checkType(tokens.consume(), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
Declaration<?> forVar = parseVariableDeclaration(tokens, variableMap);
Token name = tokens.get();
if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent()))
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
initializer = parseAssignment(forVar, tokens, variableMap);
variableMap.put(name.getContent(), forVar);
initializer = forVar;
} else initializer = parseExpression(tokens, true, variableMap);
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
Returnable<?> conditional = parseExpression(tokens, true, variableMap);
@@ -186,8 +179,7 @@ public class Parser {
Item<?> incrementer;
Token token = tokens.get();
if(variableMap.containsKey(token.getContent())) { // Assume variable assignment
Variable<?> variable = variableMap.get(token.getContent());
incrementer = parseAssignment(variable, tokens, variableMap);
incrementer = parseAssignment(tokens, variableMap);
} else incrementer = parseFunction(tokens, true, variableMap);
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
@@ -195,7 +187,7 @@ public class Parser {
return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable<Boolean>) conditional, incrementer, start);
}
private Returnable<?> parseExpression(Tokenizer tokens, boolean full, Map<String, Variable<?>> variableMap) throws ParseException {
private Returnable<?> parseExpression(Tokenizer tokens, boolean full, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
boolean booleanInverted = false; // Check for boolean not operator
boolean negate = false;
if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) {
@@ -220,7 +212,7 @@ public class Parser {
expression = parseFunction(tokens, false, variableMap);
else if(variableMap.containsKey(id.getContent())) {
ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER);
expression = new Getter(variableMap.get(id.getContent()));
expression = new Getter(id.getContent(), id.getPosition(), variableMap.get(id.getContent()));
} else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition());
}
@@ -254,7 +246,7 @@ public class Parser {
}
}
private Returnable<?> parseGroup(Tokenizer tokens, Map<String, Variable<?>> variableMap) throws ParseException {
private Returnable<?> parseGroup(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
Returnable<?> expression = parseExpression(tokens, true, variableMap); // Parse inside of group as a separate expression
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
@@ -262,7 +254,7 @@ public class Parser {
}
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, Tokenizer tokens, Map<String, Variable<?>> variableMap) throws ParseException {
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
Token binaryOperator = tokens.consume();
ParserUtil.checkBinaryOperator(binaryOperator);
@@ -316,23 +308,31 @@ public class Parser {
}
}
private Variable<?> parseVariableDeclaration(Tokenizer tokens, Returnable.ReturnType type) throws ParseException {
ParserUtil.checkVarType(tokens.get(), type); // Check for type mismatch
switch(type) {
case NUMBER:
return new NumberVariable(0d, tokens.get().getPosition());
case STRING:
return new StringVariable("", tokens.get().getPosition());
case BOOLEAN:
return new BooleanVariable(false, tokens.get().getPosition());
}
throw new UnsupportedOperationException("Unsupported variable type: " + type);
private Declaration<?> parseVariableDeclaration(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
Token type = tokens.consume();
ParserUtil.checkType(type, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
Returnable.ReturnType returnType = ParserUtil.getVariableReturnType(type);
ParserUtil.checkVarType(type, returnType); // Check for type mismatch
Token identifier = tokens.consume();
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
if(functions.containsKey(identifier.getContent()) || variableMap.containsKey(identifier.getContent()))
throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition());
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
Returnable<?> value = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(value, returnType);
variableMap.put(identifier.getContent(), returnType);
return new Declaration<>(tokens.get().getPosition(), identifier.getContent(), value, returnType);
}
private Block parseBlock(Tokenizer tokens, Map<String, Variable<?>> superVars, boolean loop) throws ParseException {
private Block parseBlock(Tokenizer tokens, Map<String, Returnable.ReturnType> superVars, boolean loop) throws ParseException {
List<Item<?>> parsedItems = new GlueList<>();
Map<String, Variable<?>> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
Map<String, Returnable.ReturnType> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
Token first = tokens.get();
@@ -345,7 +345,7 @@ public class Parser {
return new Block(parsedItems, first.getPosition());
}
private Item<?> parseItem(Tokenizer tokens, Map<String, Variable<?>> variableMap, boolean loop) throws ParseException {
private Item<?> parseItem(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
Token token = tokens.get();
if(loop) ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL);
@@ -356,23 +356,12 @@ public class Parser {
return parseLoopLike(tokens, variableMap, loop);
} else if(token.isIdentifier()) { // Parse identifiers
if(variableMap.containsKey(token.getContent())) { // Assume variable assignment
Variable<?> variable = variableMap.get(token.getContent());
return parseAssignment(variable, tokens, variableMap);
return parseAssignment(tokens, variableMap);
} else return parseFunction(tokens, true, variableMap);
} else if(token.isVariableDeclaration()) {
Variable<?> temp = parseVariableDeclaration(tokens, ParserUtil.getVariableReturnType(token));
ParserUtil.checkType(tokens.consume(), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
Token name = tokens.get();
ParserUtil.checkType(name, Token.Type.IDENTIFIER); // Name must be an identifier.
return parseVariableDeclaration(tokens, variableMap);
if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent()))
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
variableMap.put(name.getContent(), temp);
return parseAssignment(temp, tokens, variableMap);
} else if(token.getType().equals(Token.Type.RETURN)) return new ReturnKeyword(tokens.consume().getPosition());
else if(token.getType().equals(Token.Type.BREAK)) return new BreakKeyword(tokens.consume().getPosition());
else if(token.getType().equals(Token.Type.CONTINUE)) return new ContinueKeyword(tokens.consume().getPosition());
@@ -380,21 +369,21 @@ public class Parser {
else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition());
}
private Assignment<?> parseAssignment(Variable<?> variable, Tokenizer tokens, Map<String, Variable<?>> variableMap) throws ParseException {
Token name = tokens.get();
private Assignment<?> parseAssignment(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
Token identifier = tokens.consume();
ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER);
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
Returnable<?> expression = parseExpression(tokens, true, variableMap);
Returnable<?> value = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(expression, variable.getType());
ParserUtil.checkReturnType(value, variableMap.get(identifier.getContent()));
return new Assignment<>((Variable<Object>) variable, (Returnable<Object>) expression, name.getPosition());
return new Assignment<>(value, identifier.getContent(), identifier.getPosition());
}
private Function<?> parseFunction(Tokenizer tokens, boolean fullStatement, Map<String, Variable<?>> variableMap) throws ParseException {
private Function<?> parseFunction(Tokenizer tokens, boolean fullStatement, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
Token identifier = tokens.consume();
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
@@ -428,7 +417,7 @@ public class Parser {
}
private List<Returnable<?>> getArgs(Tokenizer tokens, Map<String, Variable<?>> variableMap) throws ParseException {
private List<Returnable<?>> getArgs(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
List<Returnable<?>> args = new GlueList<>();
while(!tokens.get().getType().equals(Token.Type.GROUP_END)) {

View File

@@ -1,8 +1,11 @@
package com.dfsek.terra.api.structures.parser.lang;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Block implements Item<Block.ReturnInfo<?>> {
private final List<Item<?>> items;
@@ -17,10 +20,15 @@ public class Block implements Item<Block.ReturnInfo<?>> {
return items;
}
public ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
return apply(implementationArguments, new HashMap<>());
}
@Override
public synchronized ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
public ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
Map<String, Variable<?>> scope = new HashMap<>(variableMap);
for(Item<?> item : items) {
Object result = item.apply(implementationArguments);
Object result = item.apply(implementationArguments, scope);
if(result instanceof ReturnInfo) {
ReturnInfo<?> level = (ReturnInfo<?>) result;
if(!level.getLevel().equals(ReturnLevel.NONE)) return level;

View File

@@ -1,9 +1,12 @@
package com.dfsek.terra.api.structures.parser.lang;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public interface Item<T> {
T apply(ImplementationArguments implementationArguments);
T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap);
Position getPosition();
}

View File

@@ -2,8 +2,11 @@ package com.dfsek.terra.api.structures.parser.lang.constants;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public abstract class ConstantExpression<T> implements Returnable<T> {
private final T constant;
private final Position position;
@@ -14,7 +17,7 @@ public abstract class ConstantExpression<T> implements Returnable<T> {
}
@Override
public T apply(ImplementationArguments implementationArguments) {
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return constant;
}

View File

@@ -1,27 +0,0 @@
package com.dfsek.terra.api.structures.parser.lang.functions.def;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.tokenizer.Position;
public abstract class DefinedFunction<T> implements Function<T> {
private final FunctionBlock<T> block;
private final String name;
private final Position position;
protected DefinedFunction(FunctionBlock<T> block, String name, Position position) {
this.block = block;
this.name = name;
this.position = position;
}
@Override
public T apply(ImplementationArguments implementationArguments) {
return block.apply(implementationArguments);
}
@Override
public Position getPosition() {
return position;
}
}

View File

@@ -3,9 +3,12 @@ package com.dfsek.terra.api.structures.parser.lang.functions.def;
import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Item;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FunctionBlock<T> implements Item<T> {
private final List<Item<?>> items;
@@ -24,9 +27,10 @@ public class FunctionBlock<T> implements Item<T> {
@SuppressWarnings("unchecked")
@Override
public synchronized T apply(ImplementationArguments implementationArguments) {
public synchronized T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
Map<String, Variable<?>> scope = new HashMap<>(variableMap);
for(Item<?> item : items) {
Object result = item.apply(implementationArguments);
Object result = item.apply(implementationArguments, variableMap);
if(result instanceof Block.ReturnInfo) {
Block.ReturnInfo<T> level = (Block.ReturnInfo<T>) result;
if(level.getLevel().equals(Block.ReturnLevel.RETURN)) return level.getData();

View File

@@ -3,8 +3,11 @@ package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Keyword;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class BreakKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
@@ -13,7 +16,7 @@ public class BreakKeyword implements Keyword<Block.ReturnInfo<?>> {
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null);
}

View File

@@ -3,8 +3,11 @@ package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Keyword;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class ContinueKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
@@ -13,7 +16,7 @@ public class ContinueKeyword implements Keyword<Block.ReturnInfo<?>> {
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null);
}

View File

@@ -3,8 +3,11 @@ package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Keyword;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class FailKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
@@ -13,7 +16,7 @@ public class FailKeyword implements Keyword<Block.ReturnInfo<?>> {
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null);
}

View File

@@ -3,8 +3,11 @@ package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Keyword;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class ReturnKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
@@ -13,7 +16,7 @@ public class ReturnKeyword implements Keyword<Block.ReturnInfo<?>> {
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null);
}

View File

@@ -5,8 +5,11 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Item;
import com.dfsek.terra.api.structures.parser.lang.Keyword;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Block conditional;
private final Item<?> initializer;
@@ -23,9 +26,9 @@ public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
for(initializer.apply(implementationArguments); statement.apply(implementationArguments); incrementer.apply(implementationArguments)) {
Block.ReturnInfo<?> level = conditional.apply(implementationArguments);
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
for(initializer.apply(implementationArguments, variableMap); statement.apply(implementationArguments, variableMap); incrementer.apply(implementationArguments, variableMap)) {
Block.ReturnInfo<?> level = conditional.apply(implementationArguments, variableMap);
if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break;
if(level.getLevel().isReturnFast()) return level;
}

View File

@@ -4,10 +4,12 @@ import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Keyword;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Block conditional;
@@ -25,15 +27,15 @@ public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
if(statement.apply(implementationArguments)) return conditional.apply(implementationArguments);
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
if(statement.apply(implementationArguments, variableMap)) return conditional.apply(implementationArguments, variableMap);
else {
for(Pair<Returnable<Boolean>, Block> pair : elseIf) {
if(pair.getLeft().apply(implementationArguments)) {
return pair.getRight().apply(implementationArguments);
if(pair.getLeft().apply(implementationArguments, variableMap)) {
return pair.getRight().apply(implementationArguments, variableMap);
}
}
if(elseBlock != null) return elseBlock.apply(implementationArguments);
if(elseBlock != null) return elseBlock.apply(implementationArguments, variableMap);
}
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
}

View File

@@ -4,8 +4,11 @@ import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Keyword;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Block conditional;
private final Returnable<Boolean> statement;
@@ -18,9 +21,9 @@ public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
while(statement.apply(implementationArguments)) {
Block.ReturnInfo<?> level = conditional.apply(implementationArguments);
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
while(statement.apply(implementationArguments, variableMap)) {
Block.ReturnInfo<?> level = conditional.apply(implementationArguments, variableMap);
if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break;
if(level.getLevel().isReturnFast()) return level;
}

View File

@@ -2,8 +2,11 @@ package com.dfsek.terra.api.structures.parser.lang.operations;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public abstract class BinaryOperation<I, O> implements Returnable<O> {
private final Returnable<I> left;
private final Returnable<I> right;
@@ -23,7 +26,7 @@ public abstract class BinaryOperation<I, O> implements Returnable<O> {
}
@Override
public O apply(ImplementationArguments implementationArguments) {
return apply(left.apply(implementationArguments), right.apply(implementationArguments));
public O apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return apply(left.apply(implementationArguments, variableMap), right.apply(implementationArguments, variableMap));
}
}

View File

@@ -2,8 +2,11 @@ package com.dfsek.terra.api.structures.parser.lang.operations;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public abstract class UnaryOperation<T> implements Returnable<T> {
private final Returnable<T> input;
private final Position position;
@@ -16,8 +19,8 @@ public abstract class UnaryOperation<T> implements Returnable<T> {
public abstract T apply(T input);
@Override
public T apply(ImplementationArguments implementationArguments) {
return apply(input.apply(implementationArguments));
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return apply(input.apply(implementationArguments, variableMap));
}
@Override

View File

@@ -5,21 +5,24 @@ import com.dfsek.terra.api.structures.parser.lang.Item;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class Assignment<T> implements Item<T> {
private final Variable<T> delegate;
private final Returnable<T> value;
private final Position position;
private final String identifier;
public Assignment(Variable<T> delegate, Returnable<T> value, Position position) {
this.delegate = delegate;
public Assignment(Returnable<T> value, String identifier, Position position) {
this.value = value;
this.identifier = identifier;
this.position = position;
}
@SuppressWarnings("unchecked")
@Override
public synchronized T apply(ImplementationArguments implementationArguments) {
T val = value.apply(implementationArguments);
delegate.setValue(val);
public synchronized T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
T val = value.apply(implementationArguments, variableMap);
((Variable<T>) variableMap.get(identifier)).setValue(val);
return val;
}

View File

@@ -0,0 +1,60 @@
package com.dfsek.terra.api.structures.parser.lang.variables;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Item;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class Declaration<T> implements Item<T> {
private final Position position;
private final String identifier;
private final Returnable<T> value;
private final Returnable.ReturnType type;
public Declaration(Position position, String identifier, Returnable<T> value, Returnable.ReturnType type) {
switch(type) {
case STRING:
case BOOLEAN:
case NUMBER:
break;
default:
throw new IllegalArgumentException("Invalid variable type: " + type);
}
this.position = position;
this.identifier = identifier;
this.value = value;
this.type = type;
}
@Override
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
T result = value.apply(implementationArguments, variableMap);
switch(type) {
case NUMBER:
variableMap.put(identifier, new NumberVariable((Number) result, position));
break;
case BOOLEAN:
variableMap.put(identifier, new BooleanVariable((Boolean) result, position));
break;
case STRING:
variableMap.put(identifier, new StringVariable((String) result, position));
break;
}
return result;
}
@Override
public Position getPosition() {
return position;
}
public Returnable.ReturnType getType() {
return type;
}
public String getIdentifier() {
return identifier;
}
}

View File

@@ -4,25 +4,31 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class Getter implements Returnable<Object> {
private final Variable<?> delegate;
import java.util.Map;
public Getter(Variable<?> delegate) {
this.delegate = delegate;
public class Getter implements Returnable<Object> {
private final String identifier;
private final Position position;
private final ReturnType type;
public Getter(String identifier, Position position, ReturnType type) {
this.identifier = identifier;
this.position = position;
this.type = type;
}
@Override
public ReturnType returnType() {
return delegate.getType();
return type;
}
@Override
public synchronized Object apply(ImplementationArguments implementationArguments) {
return delegate.getValue();
public synchronized Object apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return variableMap.get(identifier).getValue();
}
@Override
public Position getPosition() {
return delegate.getPosition();
return position;
}
}

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.structures.script;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.structures.parser.Parser;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
@@ -28,26 +28,25 @@ import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.structures.structure.buffer.Buffer;
import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer;
import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer;
import com.dfsek.terra.debug.Debug;
import com.dfsek.terra.generation.math.SamplerCache;
import com.dfsek.terra.registry.LootRegistry;
import com.dfsek.terra.registry.ScriptRegistry;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.jafama.FastMath;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;
public class StructureScript {
private final Block block;
private final String id;
String tempID;
private final Map<Location, StructureBuffer> cache;
private final Cache<Location, StructureBuffer> cache;
private final TerraPlugin main;
String tempID;
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException {
Parser parser;
@@ -73,7 +72,9 @@ public class StructureScript {
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getX(), Returnable.ReturnType.NUMBER))
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getY(), Returnable.ReturnType.NUMBER))
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getZ(), Returnable.ReturnType.NUMBER))
.registerFunction("print", new UnaryStringFunctionBuilder(string -> Debug.info("[" + tempID + "] " + string)))
.registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(), Returnable.ReturnType.STRING))
.registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(), Returnable.ReturnType.NUMBER))
.registerFunction("print", new UnaryStringFunctionBuilder(string -> main.getDebugLogger().info("[" + tempID + "] " + string)))
.registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue())))
.registerFunction("pow", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue())))
.registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue())))
@@ -88,12 +89,7 @@ public class StructureScript {
this.id = parser.getID();
tempID = id;
this.main = main;
this.cache = Collections.synchronizedMap(new LinkedHashMap<Location, StructureBuffer>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Location, StructureBuffer> eldest) {
return this.size() > main.getTerraConfig().getStructureCache();
}
});
this.cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getStructureCache()).build();
}
/**
@@ -122,12 +118,14 @@ public class StructureScript {
}
private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) {
synchronized(cache) {
return cache.computeIfAbsent(location, loc -> {
StructureBuffer buf = new StructureBuffer(loc);
try {
return cache.get(location, () -> {
StructureBuffer buf = new StructureBuffer(location);
buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, 0)));
return buf;
});
} catch(ExecutionException e) {
throw new RuntimeException(e);
}
}
@@ -149,6 +147,7 @@ public class StructureScript {
return !block.apply(arguments).getLevel().equals(Block.ReturnLevel.FAIL);
} catch(RuntimeException e) {
main.getLogger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage());
main.getDebugLogger().stack(e);
return false;
}
}

View File

@@ -4,9 +4,11 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
@@ -27,8 +29,8 @@ public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Num
@SuppressWarnings("unchecked")
@Override
public Number apply(ImplementationArguments implementationArguments) {
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments), ((Returnable<Number>) argumentList.get(1)).apply(implementationArguments));
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, variableMap), ((Returnable<Number>) argumentList.get(1)).apply(implementationArguments, variableMap));
}
@Override

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.functions.BiomeFunction;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant;

View File

@@ -1,12 +1,12 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.functions.CheckFunction;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.generation.math.SamplerCache;
import com.dfsek.terra.world.generation.math.SamplerCache;
import java.util.List;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.functions.LootFunction;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;

View File

@@ -4,9 +4,11 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.List;
import java.util.Map;
public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
@@ -26,8 +28,8 @@ public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Numb
@SuppressWarnings("unchecked")
@Override
public Number apply(ImplementationArguments implementationArguments) {
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments));
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, variableMap));
}
@Override

View File

@@ -4,9 +4,11 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.List;
import java.util.Map;
public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void>> {
@@ -26,8 +28,8 @@ public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void
@SuppressWarnings("unchecked")
@Override
public Void apply(ImplementationArguments implementationArguments) {
function.accept(((Returnable<String>) argumentList.get(0)).apply(implementationArguments));
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
function.accept(((Returnable<String>) argumentList.get(0)).apply(implementationArguments, variableMap));
return null;
}

View File

@@ -4,10 +4,12 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.List;
import java.util.Map;
public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
private final java.util.function.Function<TerraImplementationArguments, T> function;
@@ -27,7 +29,7 @@ public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
}
@Override
public T apply(ImplementationArguments implementationArguments) {
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return function.apply((TerraImplementationArguments) implementationArguments);
}

View File

@@ -1,18 +1,21 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.provider.BiomeProvider;
import net.jafama.FastMath;
import java.util.Map;
public class BiomeFunction implements Function<String> {
private final TerraPlugin main;
private final Returnable<Number> x, y, z;
@@ -29,16 +32,16 @@ public class BiomeFunction implements Function<String> {
@Override
public String apply(ImplementationArguments implementationArguments) {
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
TerraBiomeGrid grid = main.getWorld(arguments.getBuffer().getOrigin().getWorld()).getGrid();
BiomeProvider grid = main.getWorld(arguments.getBuffer().getOrigin().getWorld()).getBiomeProvider();
return ((UserDefinedBiome) grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ()))))).getID();
return ((UserDefinedBiome) grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ()))))).getID();
}

View File

@@ -1,20 +1,23 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedBlock;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map;
public class BlockFunction implements Function<Void> {
private final BlockData data;
private final Returnable<Number> x, y, z;
@@ -37,16 +40,16 @@ public class BlockFunction implements Function<Void> {
}
@Override
public Void apply(ImplementationArguments implementationArguments) {
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
BlockData rot = data.clone();
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}

View File

@@ -5,11 +5,14 @@ import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map;
public class CheckBlockFunction implements Function<String> {
private final Returnable<Number> x, y, z;
private final Position position;
@@ -23,14 +26,14 @@ public class CheckBlockFunction implements Function<String> {
@Override
public String apply(ImplementationArguments implementationArguments) {
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String data = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ()))).getBlock().getBlockData().getAsString();
String data = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ()))).getBlock().getBlockData().getAsString();
if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties
else return data;
}

View File

@@ -1,24 +1,26 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.generation.math.SamplerCache;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.math.SamplerCache;
import net.jafama.FastMath;
import java.util.Map;
public class CheckFunction implements Function<String> {
private final TerraPlugin main;
private final Returnable<Number> x, y, z;
@@ -36,14 +38,14 @@ public class CheckFunction implements Function<String> {
@Override
public String apply(ImplementationArguments implementationArguments) {
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
Location location = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ())));
Location location = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())));
return apply(location, arguments.getBuffer().getOrigin().getWorld());
}
@@ -54,8 +56,8 @@ public class CheckFunction implements Function<String> {
if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land.
TerraBiomeGrid grid = tw.getGrid();
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(vector.getBlockX(), vector.getBlockZ(), GenerationPhase.POPULATE);
BiomeProvider provider = tw.getBiomeProvider();
UserDefinedBiome b = (UserDefinedBiome) provider.getBiome(vector.getBlockX(), vector.getBlockZ());
BiomeTemplate c = b.getConfig();
if(vector.getY() > c.getSeaLevel()) return "AIR"; // Above sea level

View File

@@ -1,19 +1,22 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.entity.EntityType;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class EntityFunction implements Function<Void> {
private final EntityType data;
private final Returnable<Number> x, y, z;
@@ -30,13 +33,13 @@ public class EntityFunction implements Function<Void> {
}
@Override
public Void apply(ImplementationArguments implementationArguments) {
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().addItem(new BufferedEntity(data), new Vector3(xz.getX(), y.apply(implementationArguments).doubleValue(), xz.getZ()).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().addItem(new BufferedEntity(data), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}

View File

@@ -5,11 +5,14 @@ import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map;
public class GetMarkFunction implements Function<String> {
private final Returnable<Number> x, y, z;
private final Position position;
@@ -22,12 +25,12 @@ public class GetMarkFunction implements Function<String> {
}
@Override
public String apply(ImplementationArguments implementationArguments) {
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String mark = arguments.getBuffer().getMark(new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
String mark = arguments.getBuffer().getMark(new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return mark == null ? "" : mark;
}

View File

@@ -1,12 +1,13 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication;
@@ -14,6 +15,8 @@ import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.registry.LootRegistry;
import net.jafama.FastMath;
import java.util.Map;
public class LootFunction implements Function<Void> {
private final LootRegistry registry;
private final Returnable<String> data;
@@ -32,13 +35,13 @@ public class LootFunction implements Function<Void> {
}
@Override
public Void apply(ImplementationArguments implementationArguments) {
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String id = data.apply(implementationArguments);
String id = data.apply(implementationArguments, variableMap);
LootTable table = registry.get(id);
if(table == null) {
@@ -46,7 +49,7 @@ public class LootFunction implements Function<Void> {
return null;
}
arguments.getBuffer().addItem(new BufferedLootApplication(table, main), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().addItem(new BufferedLootApplication(table, main), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}

View File

@@ -1,20 +1,23 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedPulledBlock;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map;
public class PullFunction implements Function<Void> {
private final BlockData data;
private final Returnable<Number> x, y, z;
@@ -31,14 +34,14 @@ public class PullFunction implements Function<Void> {
}
@Override
public Void apply(ImplementationArguments implementationArguments) {
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
BlockData rot = data.clone();
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
arguments.getBuffer().addItem(new BufferedPulledBlock(rot), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().addItem(new BufferedPulledBlock(rot), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}

View File

@@ -3,9 +3,12 @@ package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class RandomFunction implements Function<Integer> {
private final Returnable<Number> numberReturnable;
private final Position position;
@@ -22,8 +25,8 @@ public class RandomFunction implements Function<Integer> {
}
@Override
public Integer apply(ImplementationArguments implementationArguments) {
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(numberReturnable.apply(implementationArguments).intValue());
public Integer apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(numberReturnable.apply(implementationArguments, variableMap).intValue());
}
@Override

View File

@@ -2,9 +2,12 @@ package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.tokenizer.Position;
import java.util.Map;
public class RecursionsFunction implements Function<Number> {
private final Position position;
@@ -18,7 +21,7 @@ public class RecursionsFunction implements Function<Number> {
}
@Override
public Number apply(ImplementationArguments implementationArguments) {
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return ((TerraImplementationArguments) implementationArguments).getRecursions();
}

View File

@@ -5,11 +5,14 @@ import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map;
public class SetMarkFunction implements Function<Void> {
private final Returnable<Number> x, y, z;
private final Position position;
@@ -24,13 +27,13 @@ public class SetMarkFunction implements Function<Void> {
}
@Override
public Void apply(ImplementationArguments implementationArguments) {
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().setMark(mark.apply(implementationArguments), new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().setMark(mark.apply(implementationArguments, variableMap), new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}

View File

@@ -1,17 +1,20 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedStateManipulator;
import com.dfsek.terra.api.structures.tokenizer.Position;
import net.jafama.FastMath;
import java.util.Map;
public class StateFunction implements Function<Void> {
private final Returnable<String> data;
private final Returnable<Number> x, y, z;
@@ -28,12 +31,12 @@ public class StateFunction implements Function<Void> {
}
@Override
public Void apply(ImplementationArguments implementationArguments) {
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments, variableMap)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}

View File

@@ -1,11 +1,12 @@
package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.Rotation;
@@ -16,6 +17,7 @@ import com.dfsek.terra.registry.ScriptRegistry;
import net.jafama.FastMath;
import java.util.List;
import java.util.Map;
public class StructureFunction implements Function<Boolean> {
private final ScriptRegistry registry;
@@ -42,17 +44,17 @@ public class StructureFunction implements Function<Boolean> {
}
@Override
public Boolean apply(ImplementationArguments implementationArguments) {
public Boolean apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
if(arguments.getRecursions() > main.getTerraConfig().getMaxRecursion())
throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions());
Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String app = id.apply(implementationArguments);
String app = id.apply(implementationArguments, variableMap);
StructureScript script = registry.get(app);
if(script == null) {
main.getLogger().severe("No such structure " + app);
@@ -60,7 +62,7 @@ public class StructureFunction implements Function<Boolean> {
}
Rotation rotation1;
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments);
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, variableMap);
try {
rotation1 = Rotation.valueOf(rotString);
} catch(IllegalArgumentException e) {
@@ -68,7 +70,7 @@ public class StructureFunction implements Function<Boolean> {
return null;
}
Vector3 offset = new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).doubleValue(), FastMath.roundToInt(xz.getZ()));
Vector3 offset = new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ()));
return script.executeInBuffer(new IntermediateBuffer(arguments.getBuffer(), offset), arguments.getRandom(), arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
}

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.structures.structure.buffer.items;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.entity.EntityType;
import com.dfsek.terra.api.platform.entity.EntityType;
public class BufferedEntity implements BufferedItem {

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.structures.structure.buffer.items;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.api.platform.block.state.Container;
import com.dfsek.terra.api.structures.loot.LootTable;

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.api.structures.structure.buffer.items;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.block.state.BlockState;
public class BufferedStateManipulator implements BufferedItem {

View File

@@ -1,7 +1,5 @@
package com.dfsek.terra.api.util;
import com.dfsek.terra.debug.Debug;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -21,7 +19,6 @@ public class JarUtil {
if(parent != null) {
parent.mkdirs();
}
Debug.info("Output does not already exist. Creating... ");
try(FileOutputStream out = new FileOutputStream(dest); InputStream in = fromJar.getInputStream(entry)) {
byte[] buffer = new byte[(8192)];

View File

@@ -0,0 +1,20 @@
package com.dfsek.terra.api.util.mutable;
public class MutableBoolean implements MutablePrimitive<Boolean> {
private boolean value;
@Override
public Boolean get() {
return value;
}
@Override
public void set(Boolean value) {
this.value = value;
}
public boolean invert() {
value = !value;
return value;
}
}

View File

@@ -0,0 +1,37 @@
package com.dfsek.terra.api.util.mutable;
public class MutableDouble extends MutableNumber<Double> {
public MutableDouble(Double value) {
super(value);
}
@Override
public void increment() {
add(1d);
}
@Override
public void decrement() {
subtract(1d);
}
@Override
public void add(Double add) {
value += add;
}
@Override
public void multiply(Double mul) {
value *= mul;
}
@Override
public void subtract(Double sub) {
value -= sub;
}
@Override
public void divide(Double divide) {
value /= divide;
}
}

View File

@@ -0,0 +1,39 @@
package com.dfsek.terra.api.util.mutable;
public class MutableInteger extends MutableNumber<Integer> {
public MutableInteger(Integer value) {
super(value);
}
public void increment() {
add(1);
}
public void decrement() {
subtract(1);
}
@Override
public void add(Integer add) {
value += add;
}
@Override
public void multiply(Integer mul) {
value *= mul;
}
@Override
public void subtract(Integer sub) {
value -= sub;
}
@Override
public void divide(Integer divide) {
value /= divide;
}
public void add(int add) {
value += add;
}
}

Some files were not shown because too many files have changed in this diff Show More