Compare commits

...

99 Commits

Author SHA1 Message Date
dfsek 213182e2ab re-implement noise carvers 2021-02-06 19:14:07 -07:00
dfsek 76eb0f3fe0 respect function loading order 2021-02-05 23:30:46 -07:00
dfsek 4aebb83b0c improve biome mutation noise functions 2021-02-05 11:07:12 -07:00
dfsek 1863ba29fc implement UserDefinedFunction 2021-01-31 01:41:05 -07:00
dfsek e600b50a11 refactor biome templates 2021-01-30 21:34:55 -07:00
dfsek 762c3064d9 use fancy new tectonic stuff for biome stage loading 2021-01-30 15:23:29 -07:00
dfsek b99fabcf1d redo noise config loading with new tectonic object goodies 2021-01-30 12:02:06 -07:00
dfsek af248ee14a begin refactoring with Tectonic Object Templates 2021-01-30 03:22:13 -07:00
dfsek c834d80206 refactor NoiseSampler 2021-01-30 00:16:16 -07:00
dfsek 66fb481ac2 cleanup 2021-01-29 10:54:04 -07:00
dfsek 7858cc34c2 add DomainWarpedSampler 2021-01-29 10:30:03 -07:00
dfsek e306a0fd09 ImageSampler implementation 2021-01-29 10:09:19 -07:00
dfsek 02d61d0764 completely redo noise config loading (mostly keeps parity with old configs) 2021-01-29 01:52:12 -07:00
dfsek dddf644c34 Remove 2d base eq options. Closes #70. 2021-01-29 00:46:55 -07:00
dfsek a8266f99b1 implement NormalNormalizer 2021-01-28 15:26:17 -07:00
dfsek 2fb30322ff actually register overridden vars 2021-01-27 20:06:40 -07:00
dfsek dfec463765 add biome specific vars 2021-01-27 00:37:30 -07:00
dfsek f6967be95f biome cleanup 2021-01-26 21:50:56 -07:00
dfsek 82fa9abe15 more refactoring 2021-01-25 23:29:15 -07:00
dfsek 1d6cdf9eaa refactor 2021-01-25 19:34:29 -07:00
dfsek 89f52a22c8 fix domain warp frequency issue 2021-01-25 11:12:20 -07:00
dfsek dca0891e00 basic noise carver implementation 2021-01-24 21:14:21 -07:00
dfsek bd4812ef2b clean up noise eqs 2021-01-24 02:56:50 -07:00
dfsek ce62f1d7ac implement ChunkAccess 2021-01-24 01:58:51 -07:00
dfsek da5d3fe0ce refactor API 2021-01-24 01:46:01 -07:00
dfsek 3318161c44 cleanup biome config loading 2021-01-21 22:20:40 -07:00
dfsek 25acda4410 add rotation and rotationDegrees functions 2021-01-21 20:35:52 -07:00
dfsek 115bb414c0 configurable blend weight 2021-01-21 20:29:25 -07:00
dfsek 708ef16a1c reduce pipeline boilerplate 2021-01-21 20:00:51 -07:00
dfsek 8b501ddcde redo biome blending 2021-01-21 18:18:43 -07:00
dfsek 5b8beebaa3 fix fabric stuff 2021-01-20 18:49:45 -07:00
dfsek 7b6d195615 fix BiomeTest 2021-01-19 23:38:23 -07:00
dfsek 9e830abb90 image to biome stuff 2021-01-18 23:56:46 -07:00
dfsek 4b21fcd80a add elevation weight, add "self" biome opt 2021-01-17 21:55:08 -07:00
dfsek af5b316326 fix minor biome issues 2021-01-17 04:05:30 -07:00
dfsek beb18c6e2c Merge branch 'structurelocate' into biome
# Conflicts:
#	build.gradle.kts
2021-01-17 01:25:28 -07:00
dfsek 09c1957ab6 StructureLocateEvent implementation 2021-01-16 17:30:11 -07:00
dfsek b2c3498a32 create DistributionTest 2021-01-16 14:37:00 -07:00
dfsek 20de531c8f custom noise functions per palette layer 2021-01-15 15:08:59 -07:00
dfsek 6d1dd3acbf terrascript should be thread safe now 2021-01-15 00:59:04 -07:00
dfsek 346a8826aa add domain warp controls to FastNoiseLite 2021-01-15 00:03:01 -07:00
dfsek 25f6f3dbe1 debug log structure exception 2021-01-14 21:26:05 -07:00
dfsek 87f7af1e1b fix tree determinism issues 2021-01-14 20:48:07 -07:00
dfsek 764344b4ef synchronize maps 2021-01-14 20:40:57 -07:00
dfsek d327909389 implement multiple vanilla biomes per custom biome 2021-01-14 20:28:52 -07:00
dfsek c1fdfa94f1 improve elevation interp (TEMP DISABLE CARVING) 2021-01-14 18:40:03 -07:00
dfsek cbc2885c16 replace dumb caches with guava caches 2021-01-14 00:34:23 -07:00
dfsek 8fd3530653 configurable cache sizes 2021-01-13 23:51:23 -07:00
dfsek 244f0fba11 protect against biome cell overflow 2021-01-13 22:12:18 -07:00
dfsek 56a0d5d15b Revert "use getUngeneratedBlock for trees"
This reverts commit ca8cc8bc
2021-01-13 20:03:01 -07:00
dfsek ca8cc8bc66 use getUngeneratedBlock for trees 2021-01-13 20:02:34 -07:00
dfsek 627f1b75d6 add BorderMutator to config 2021-01-13 19:02:51 -07:00
dfsek 18731a5aa0 remove unused biome opts 2021-01-13 19:02:38 -07:00
dfsek 4bd943ae7b implement getUngeneratedBlock 2021-01-13 17:48:30 -07:00
dfsek e04d363123 fix minor issues 2021-01-13 17:10:29 -07:00
dfsek d1c018690d minor perf improvements 2021-01-13 14:03:52 -07:00
dfsek 54f732176d implement biome pipeline config loader 2021-01-13 10:48:45 -07:00
dfsek fb32531584 implementation of BiomePipeline 2021-01-13 00:19:57 -07:00
dfsek 5c9a9c7dfa implement BiomePipeline 2021-01-12 22:36:16 -07:00
dfsek fc46c8bd4d fix border issues 2021-01-12 21:10:46 -07:00
dfsek f28759d07a add BorderMutator 2021-01-12 19:25:01 -07:00
dfsek 93c33ca455 refactor TerraBiome 2021-01-12 17:39:26 -07:00
dfsek 9c50dc2ef9 smoothing stuff 2021-01-12 17:22:49 -07:00
dfsek 883124d8ab basic framework 2021-01-12 16:32:21 -07:00
dfsek 1ee2b180d4 bump version 2021-01-12 11:10:17 -07:00
dfsek e6e2c62474 Merge pull request #50 from PolyhedralDev/palette
Noise config additions
2021-01-12 10:34:42 -07:00
dfsek 5df511a940 white noise micro opt 2021-01-11 22:00:10 -07:00
dfsek 462b0af225 normalization options 2021-01-11 20:23:41 -07:00
dfsek 5c469ed378 noise function flora and tree dist 2021-01-11 17:07:25 -07:00
dfsek c59ab5d917 fix lookup issue 2021-01-11 16:28:53 -07:00
dfsek 8a10a9807d allow configuration of 2d/3d noise in palettes 2021-01-11 14:37:56 -07:00
dfsek 623a4dea4f allow configuration of cellular lookup function 2021-01-11 13:34:53 -07:00
dfsek 18d7408f53 customizable palette noise 2021-01-11 13:31:19 -07:00
dfsek 462b6f4198 add publishing stuff 2021-01-10 20:44:56 -07:00
dfsek 1049bb901d complain about tstructure files 2021-01-10 18:08:41 -07:00
dfsek 999c9b565d fix biomegrid wackiness 2021-01-10 17:20:21 -07:00
dfsek 27aeb73157 fix minor version issues 2021-01-10 16:55:49 -07:00
dfsek 12ff9cc146 give gradle more memory 2021-01-10 16:19:16 -07:00
dfsek f114baebd6 better tab completion, fix testWithPaper task 2021-01-10 14:37:44 -07:00
dfsek 11a6546064 oops 2021-01-10 00:01:53 -07:00
dfsek 771e42d1a8 Add Terra name classifier to Jars 2021-01-09 23:58:46 -07:00
dfsek 5e3c12298b oops forgot nether trees 2021-01-09 23:14:16 -07:00
dfsek a5dd4a63d1 minor fixes/improvements 2021-01-09 22:26:39 -07:00
dfsek 9fbe117f78 fix fabric stuff 2021-01-09 12:00:18 -07:00
dfsek 3429165aca Merge pull request #43 from PolyhedralDev/agnostic
Platform-agnostic engine & TerraScript structures
2021-01-09 11:30:34 -07:00
dfsek 9310114c0e cleanup 2021-01-09 02:58:02 -07:00
dfsek 141b4f86ae cleanup 2021-01-09 02:25:48 -07:00
dfsek 67ffd91641 add enchantment to loot tables 2021-01-09 02:25:36 -07:00
dfsek 9a94485c91 add white noise to FastNoiseLite 2021-01-08 11:51:07 -07:00
dfsek 28b6fe49bb rework image stuff 2021-01-07 22:04:35 -07:00
dfsek 308ba887a3 add getOrigin functions 2021-01-07 17:18:38 -07:00
dfsek d2a1901f44 add max structure recursion depth 2021-01-07 16:38:07 -07:00
dfsek 64391f3abc remove unused random parameter from populators 2021-01-07 10:33:23 -07:00
dfsek e47b3f0397 add message to export command, more cleanup 2021-01-07 09:45:40 -07:00
dfsek c6ff808cce fix //regen and cleanup 2021-01-06 21:07:57 -07:00
dfsek e9d0c14eee cleanup biomegrids 2021-01-06 13:32:46 -07:00
dfsek 23d8a0aeeb skip over buffer when pasting trees 2021-01-06 11:56:17 -07:00
dfsek 512edae9c6 Multi-version support for 1.13-1.16 2021-01-06 10:57:34 -07:00
Haurum d21d448947 Create da.yml (#42) 2020-12-30 13:33:31 -07:00
398 changed files with 7538 additions and 5113 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
import com.dfsek.terra.getGitHash
val versionObj = Version("3", "0", "0", true)
val versionObj = Version("4", "0", "0", true)
allprojects {
version = versionObj
@@ -7,7 +7,7 @@ import org.gradle.kotlin.dsl.repositories
fun Project.configureDependencies() {
repositories {
maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") }
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 +19,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")
}
@@ -45,12 +45,13 @@ fun Project.configureDistribution() {
}
tasks["processResources"].dependsOn(downloadDefaultPacks)
tasks.register<Jar>("sourcesJar") {
archiveClassifier.set("sources")
tasks.withType<Jar> {
archiveBaseName.set("Terra-${archiveBaseName.get()}")
from("../LICENSE", "../../LICENSE")
}
tasks.withType<Jar> {
from("../LICENSE", "../../LICENSE")
tasks.register<Jar>("sourcesJar") {
archiveClassifier.set("sources")
}
tasks.register<Jar>("javadocJar") {
+4
View File
@@ -0,0 +1,4 @@
colors:
- 0x000000: 20
- 0xffffff: 3
enable: false
+27 -1
View File
@@ -2,6 +2,7 @@ import com.dfsek.terra.configureCommon
plugins {
`java-library`
`maven-publish`
}
configureCommon()
@@ -13,11 +14,36 @@ 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")
"compileOnly"("com.googlecode.json-simple:json-simple:1.1")
"shadedApi"("com.google.guava:guava:30.0-jre")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
artifact(tasks["sourcesJar"])
artifact(tasks["jar"])
}
}
repositories {
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/"
maven(mavenUrl) {
val mavenUsername: String? by project
val mavenPassword: String? by project
if (mavenUsername != null && mavenPassword != null) {
credentials {
username = mavenUsername
password = mavenPassword
}
}
}
}
}
@@ -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");
}
}
@@ -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;
}
}
@@ -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();
}
@@ -1,63 +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.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((String) o))
.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((String) o))
.registerLoader(ImageLoader.Channel.class, (t, o, l) -> ImageLoader.Channel.valueOf((String) o))
.registerLoader(ImageLoader.Align.class, (t, o, l) -> ImageLoader.Align.valueOf((String) o))
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf((String) o));
}
}
@@ -1,4 +0,0 @@
package com.dfsek.terra.api;
public interface Player extends Entity {
}
@@ -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();
}
@@ -0,0 +1,4 @@
package com.dfsek.terra.api.core.event;
public interface Event {
}
@@ -0,0 +1,4 @@
package com.dfsek.terra.api.core.event;
public interface EventListener {
}
@@ -0,0 +1,7 @@
package com.dfsek.terra.api.core.event;
public interface EventManager {
void callEvent(Event event);
void registerListener(EventListener listener);
}
@@ -1,9 +1,10 @@
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;
import java.util.Random;
/**
@@ -25,18 +26,18 @@ public final class MathUtil {
* @param numArray The array of numbers to calculate the standard deviation of.
* @return double - The standard deviation.
*/
public static double standardDeviation(double[] numArray) {
public static double standardDeviation(List<Number> numArray) {
double sum = 0.0, standardDeviation = 0.0;
int length = numArray.length;
int length = numArray.size();
for(double num : numArray) {
sum += num;
for(Number num : numArray) {
sum += num.doubleValue();
}
double mean = sum / length;
for(double num : numArray) {
standardDeviation += FastMath.pow(num - mean, 2);
for(Number num : numArray) {
standardDeviation += FastMath.pow2(num.doubleValue() - mean);
}
return FastMath.sqrt(standardDeviation / length);
@@ -89,4 +90,104 @@ 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;
}
}
@@ -1,16 +1,15 @@
package com.dfsek.terra.api.math;
import com.dfsek.terra.api.math.noise.FastNoiseLite;
import com.dfsek.terra.api.world.biome.NormalizationUtil;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
@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;
@@ -25,19 +24,19 @@ public class ProbabilityCollection<E> {
return this;
}
public E get() {
if(array.length == 0) return null;
return (E) array[ThreadLocalRandom.current().nextInt(array.length)];
}
public E get(Random r) {
if(array.length == 0) return null;
return (E) array[r.nextInt(array.length)];
}
public E get(FastNoiseLite n, double x, double z) {
public E get(NoiseSampler n, double x, double y, double z) {
if(array.length == 0) return null;
return (E) array[NormalizationUtil.normalize(n.getNoise(x, z), 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[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)];
}
public int getTotalProbability() {
@@ -47,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);
}
}
}
@@ -0,0 +1,32 @@
package com.dfsek.terra.api.math.noise;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
public interface NoiseSampler {
/**
* 2D noise at given position using current settings
* <p>
* Noise output bounded between -1...1
*/
double getNoise(double x, double y);
/**
* 3D noise at given position using current settings
* <p>
* Noise output bounded between -1...1
*/
double getNoise(double x, double y, double z);
default double getNoise(Vector3 vector3) {
return getNoise(vector3.getX(), vector3.getY(), vector3.getZ());
}
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);
}
@@ -0,0 +1,22 @@
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;
public LinearNormalizer(NoiseSampler sampler, double min, double max) {
super(sampler);
this.min = min;
this.max = max;
}
@Override
public double normalize(double in) {
return (in - min) * (2 / (max - min)) - 1;
}
}
@@ -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;
}
}
@@ -0,0 +1,37 @@
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;
public Normalizer(NoiseSampler sampler) {
this.sampler = sampler;
}
public abstract double normalize(double in);
@Override
public double getNoise(double x, double y) {
return normalize(sampler.getNoise(x, y));
}
@Override
public double getNoise(double x, double y, double z) {
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, NORMAL
}
}
@@ -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;
}
}
@@ -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
);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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;
}
}
@@ -0,0 +1,10 @@
package com.dfsek.terra.api.math.parsii.defined;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
public class DefinedFunctionTemplate implements SeededBuilder<UserDefinedFunction> {
@Override
public UserDefinedFunction apply(Long aLong) {
return null;
}
}
@@ -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;
}
}
@@ -1,4 +1,4 @@
package com.dfsek.terra.api.math.noise;
package com.dfsek.terra.api.math.parsii.noise;
import parsii.eval.Function;
@@ -1,17 +1,18 @@
package com.dfsek.terra.api.math.noise;
package com.dfsek.terra.api.math.parsii.noise;
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;
import java.util.List;
public class NoiseFunction2 implements NoiseFunction {
private final FastNoiseLite gen;
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
@@ -43,7 +44,7 @@ public class NoiseFunction2 implements NoiseFunction {
private static final long serialVersionUID = 8915092734723467010L;
private static final int cacheSize = 384;
public double get(FastNoiseLite noise, double x, double z) {
public double get(NoiseSampler noise, double x, double z) {
double xx = x >= 0 ? x * 2 : x * -2 - 1;
double zz = z >= 0 ? z * 2 : z * -2 - 1;
double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx);
@@ -1,15 +1,16 @@
package com.dfsek.terra.api.math.noise;
package com.dfsek.terra.api.math.parsii.noise;
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;
public class NoiseFunction3 implements NoiseFunction {
private final FastNoiseLite gen;
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
@@ -65,7 +65,7 @@ public class Vector2 implements Cloneable {
/**
* Add this vector to another.
*
* @param other Vector to add
* @param other Vector to increment
* @return Mutated vector, for chaining.
*/
public Vector2 add(Vector2 other) {
@@ -172,6 +172,20 @@ public class Vector2 implements Cloneable {
}
}
public Vector2 add(double x, double z) {
this.x += x;
this.z += z;
return this;
}
public int getBlockX() {
return FastMath.floorToInt(x);
}
public int getBlockZ() {
return FastMath.floorToInt(z);
}
@Override
public String toString() {
return "(" + x + ", " + z + ")";
@@ -101,6 +101,10 @@ public class Vector3 implements Cloneable {
return FastMath.sqrt(lengthSquared());
}
public double inverseLength() {
return FastMath.invSqrtQuick(lengthSquared());
}
/**
* Returns if a vector is normalized
*
@@ -280,7 +284,7 @@ public class Vector3 implements Cloneable {
}
public Vector3 normalize() {
return this.multiply(1D / this.length());
return this.multiply(this.inverseLength());
}
public Vector3 subtract(int x, int y, int z) {
@@ -1,10 +1,10 @@
package com.dfsek.terra.api.math.voxel;
import com.dfsek.terra.api.math.noise.FastNoiseLite;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.vector.Vector3;
public class DeformedSphere extends VoxelGeometry {
public DeformedSphere(Vector3 start, int rad, double deform, FastNoiseLite noise) {
public DeformedSphere(Vector3 start, int rad, double deform, NoiseSampler noise) {
for(int x = -rad; x <= rad; x++) {
for(int y = -rad; y <= rad; y++) {
for(int z = -rad; z <= rad; z++) {
@@ -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();
}
@@ -0,0 +1,6 @@
package com.dfsek.terra.api.platform;
import com.dfsek.terra.api.platform.entity.Entity;
public interface Player extends Entity {
}
@@ -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 {
@@ -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();
}
@@ -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;
@@ -1,71 +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 {
Object getHandle();
/**
* 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);
}
}
@@ -2,7 +2,14 @@ package com.dfsek.terra.api.platform.handle;
import com.dfsek.terra.api.platform.block.MaterialData;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import java.util.Set;
public interface ItemHandle {
ItemStack newItemStack(MaterialData material, int amount);
Enchantment getEnchantment(String id);
Set<Enchantment> getEnchantments();
}
@@ -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);
}
@@ -0,0 +1,14 @@
package com.dfsek.terra.api.platform.inventory.item;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.inventory.ItemStack;
public interface Enchantment extends Handle {
boolean canEnchantItem(ItemStack itemStack);
String getID();
boolean conflictsWith(Enchantment other);
int getMaxLevel();
}
@@ -2,5 +2,10 @@ package com.dfsek.terra.api.platform.inventory.item;
import com.dfsek.terra.api.platform.Handle;
import java.util.Map;
public interface ItemMeta extends Handle {
Map<Enchantment, Integer> getEnchantments();
void addEnchantment(Enchantment enchantment, int level);
}
@@ -9,7 +9,7 @@ public interface BiomeGrid extends Handle {
*
* @param x - 0-15
* @param z - 0-15
* @return Biome value
* @return TerraBiome value
*/
@NotNull
Biome getBiome(int x, int z);
@@ -20,7 +20,7 @@ public interface BiomeGrid extends Handle {
* @param x - 0-15
* @param y - 0-255
* @param z - 0-15
* @return Biome value
* @return TerraBiome value
*/
@NotNull
Biome getBiome(int x, int y, int z);
@@ -30,7 +30,7 @@ public interface BiomeGrid extends Handle {
*
* @param x - 0-15
* @param z - 0-15
* @param bio - Biome value
* @param bio - TerraBiome value
*/
void setBiome(int x, int z, @NotNull Biome bio);
@@ -40,7 +40,7 @@ public interface BiomeGrid extends Handle {
* @param x - 0-15
* @param y - 0-255
* @param z - 0-15
* @param bio - Biome value
* @param bio - TerraBiome value
*/
void setBiome(int x, int y, int z, @NotNull Biome bio);
}
@@ -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();
@@ -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);
}
@@ -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 {
}
@@ -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);
}
@@ -1,6 +0,0 @@
package com.dfsek.terra.api.platform.world.entity;
import com.dfsek.terra.api.platform.Handle;
public interface Entity extends Handle {
}
@@ -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;
@@ -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();
}
}
@@ -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;
@@ -1,11 +1,12 @@
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;
import com.dfsek.terra.api.structures.loot.functions.DamageFunction;
import com.dfsek.terra.api.structures.loot.functions.Function;
import com.dfsek.terra.api.structures.loot.functions.EnchantFunction;
import com.dfsek.terra.api.structures.loot.functions.LootFunction;
import com.dfsek.terra.api.util.GlueList;
import net.jafama.FastMath;
import org.json.simple.JSONArray;
@@ -20,7 +21,7 @@ import java.util.Random;
public class Entry {
private final MaterialData item;
private final long weight;
private final List<Function> functions = new GlueList<>();
private final List<LootFunction> functions = new GlueList<>();
private final TerraPlugin main;
/**
@@ -63,6 +64,15 @@ public class Entry {
long minDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("min");
functions.add(new DamageFunction(FastMath.toIntExact(minDamage), FastMath.toIntExact(maxDamage)));
break;
case "minecraft:enchant_with_levels":
case "enchant_with_levels":
long maxEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("max");
long minEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("min");
JSONArray disabled = null;
if(((JSONObject) function).containsKey("disabled_enchants"))
disabled = (JSONArray) ((JSONObject) function).get("disabled_enchants");
functions.add(new EnchantFunction(FastMath.toIntExact(minEnchant), FastMath.toIntExact(maxEnchant), disabled, main));
break;
}
}
}
@@ -76,7 +86,7 @@ public class Entry {
*/
public ItemStack getItem(Random r) {
ItemStack item = main.getItemHandle().newItemStack(this.item, 1);
for(Function f : functions) {
for(LootFunction f : functions) {
item = f.apply(item, r);
}
return item;
@@ -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;
@@ -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;
@@ -6,9 +6,9 @@ import com.dfsek.terra.api.platform.inventory.ItemStack;
import java.util.Random;
/**
* Loot Function fot setting the amount of an item.
* Loot LootFunction fot setting the amount of an item.
*/
public class AmountFunction implements Function {
public class AmountFunction implements LootFunction {
private final int max;
private final int min;
@@ -7,9 +7,9 @@ import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
import java.util.Random;
/**
* Loot Function for setting the damage on items in Loot Tables
* Loot LootFunction for setting the damage on items in Loot Tables
*/
public class DamageFunction implements Function {
public class DamageFunction implements LootFunction {
private final int max;
private final int min;
@@ -0,0 +1,64 @@
package com.dfsek.terra.api.structures.loot.functions;
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;
import com.dfsek.terra.api.util.GlueList;
import net.jafama.FastMath;
import org.json.simple.JSONArray;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class EnchantFunction implements LootFunction {
private final int min;
private final int max;
private final JSONArray disabled;
private final TerraPlugin main;
public EnchantFunction(int min, int max, JSONArray disabled, TerraPlugin main) {
this.max = max;
this.min = min;
this.disabled = disabled;
this.main = main;
}
/**
* Applies the function to an ItemStack.
*
* @param original The ItemStack on which to apply the function.
* @param r The Random instance to use.
* @return - ItemStack - The mutated ItemStack.
*/
@Override
public ItemStack apply(ItemStack original, Random r) {
double enchant = (r.nextDouble() * (max - min)) + min;
List<Enchantment> possible = new GlueList<>();
for(Enchantment ench : main.getItemHandle().getEnchantments()) {
if(ench.canEnchantItem(original) && (disabled == null || !this.disabled.contains(ench.getID()))) {
possible.add(ench);
}
}
int numEnchant = (r.nextInt((int) FastMath.abs(enchant)) / 10 + 1);
Collections.shuffle(possible);
ItemMeta meta = original.getItemMeta();
iter:
for(int i = 0; i < numEnchant && i < possible.size(); i++) {
Enchantment chosen = possible.get(i);
for(Enchantment ench : meta.getEnchantments().keySet()) {
if(chosen.conflictsWith(ench)) continue iter;
}
int lvl = r.nextInt(1 + (int) (((enchant / 40 > 1) ? 1 : enchant / 40) * (chosen.getMaxLevel())));
try {
meta.addEnchantment(chosen, FastMath.max(lvl, 1));
} catch(IllegalArgumentException e) {
main.getLogger().warning("Attempted to enchant " + original.getType() + " with " + chosen + " at level " + FastMath.max(lvl, 1) + ", but an unexpected exception occurred! Usually this is caused by a misbehaving enchantment plugin.");
}
}
original.setItemMeta(meta);
return original;
}
}
@@ -8,7 +8,7 @@ import java.util.Random;
/**
* Interface for mutating items in Loot Tables.
*/
public interface Function {
public interface LootFunction {
/**
* Applies the function to an ItemStack.
*
@@ -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)) {
@@ -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;
@@ -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();
}
@@ -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;
}
@@ -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;
}
}
@@ -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();
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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);
}
@@ -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;
}
@@ -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));
}
}
@@ -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
@@ -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;
}
@@ -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;
}
}
@@ -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;
}
}
@@ -1,11 +1,12 @@
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;
import com.dfsek.terra.api.structures.parser.lang.Block;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.script.builders.BinaryNumberFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.BiomeFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.BlockFunctionBuilder;
@@ -22,28 +23,30 @@ import com.dfsek.terra.api.structures.script.builders.StateFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.StructureFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.UnaryNumberFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.UnaryStringFunctionBuilder;
import com.dfsek.terra.api.structures.script.builders.ZeroArgFunctionBuilder;
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;
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException {
Parser parser;
@@ -66,7 +69,12 @@ public class StructureScript {
.registerFunction("getBiome", new BiomeFunctionBuilder(main))
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
.registerFunction("state", new StateFunctionBuilder(main))
.registerFunction("print", new UnaryStringFunctionBuilder(string -> Debug.info("[" + tempID + "] " + string)))
.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("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())))
@@ -80,12 +88,8 @@ public class StructureScript {
block = parser.parse();
this.id = parser.getID();
tempID = id;
this.cache = Collections.synchronizedMap(new LinkedHashMap<Location, StructureBuffer>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Location, StructureBuffer> eldest) {
return this.size() > main.getTerraConfig().getStructureCache();
}
});
this.main = main;
this.cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getStructureCache()).build();
}
/**
@@ -97,9 +101,9 @@ public class StructureScript {
*/
public boolean execute(Location location, Random random, Rotation rotation) {
StructureBuffer buffer = new StructureBuffer(location);
Block.ReturnInfo<?> level = block.apply(new TerraImplementationArguments(buffer, rotation, random, 0));
boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
buffer.paste();
return !level.getLevel().equals(Block.ReturnLevel.FAIL);
return level;
}
public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) {
@@ -114,21 +118,39 @@ public class StructureScript {
}
private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) {
synchronized(cache) {
return cache.computeIfAbsent(location, loc -> {
StructureBuffer buf = new StructureBuffer(loc);
Block.ReturnInfo<?> level = block.apply(new TerraImplementationArguments(buf, rotation, random, 0));
buf.setSucceeded(!level.getLevel().equals(Block.ReturnLevel.FAIL));
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);
}
}
public boolean executeInBuffer(Buffer buffer, Random random, Rotation rotation, int recursions) {
return !block.apply(new TerraImplementationArguments(buffer, rotation, random, recursions)).getLevel().equals(Block.ReturnLevel.FAIL);
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions));
}
public boolean executeDirect(Location location, Random random, Rotation rotation) {
DirectBuffer buffer = new DirectBuffer(location);
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
}
public String getId() {
return id;
}
private boolean applyBlock(TerraImplementationArguments arguments) {
synchronized(block) {
try {
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;
}
}
}
}
@@ -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
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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
@@ -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;
}
@@ -0,0 +1,53 @@
package com.dfsek.terra.api.structures.script.builders;
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;
private final Returnable.ReturnType type;
public ZeroArgFunctionBuilder(java.util.function.Function<TerraImplementationArguments, T> function, Returnable.ReturnType type) {
this.function = function;
this.type = type;
}
@Override
public Function<T> build(List<Returnable<?>> argumentList, Position position) {
return new Function<T>() {
@Override
public ReturnType returnType() {
return type;
}
@Override
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return function.apply((TerraImplementationArguments) implementationArguments);
}
@Override
public Position getPosition() {
return position;
}
};
}
@Override
public int argNumber() {
return 1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return type;
return null;
}
}
@@ -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();
}
@@ -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;
@@ -25,7 +28,11 @@ public class BlockFunction implements Function<Void> {
this.position = position;
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant());
try {
this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant());
} catch(IllegalArgumentException e) {
throw new ParseException("Could not parse block data", data.getPosition(), e);
}
this.x = x;
this.y = y;
this.z = z;
@@ -33,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;
}
@@ -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;
}
@@ -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
@@ -1,19 +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.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 net.jafama.FastMath;
import java.util.Map;
public class EntityFunction implements Function<Void> {
private final EntityType data;
@@ -31,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(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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

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