diff --git a/build.gradle.kts b/build.gradle.kts index 28b72c0ee..682335c2a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -62,7 +62,7 @@ val serverMinHeap = "2G" val serverMaxHeap = "8G" //Valid values are: none, truecolor, indexed256, indexed16, indexed8 val color = "truecolor" -val errorReporting = false +val errorReporting = findProperty("errorReporting") as Boolean? ?: false val nmsBindings = mapOf( "v1_21_R5" to "1.21.7-R0.1-SNAPSHOT", diff --git a/core/build.gradle.kts b/core/build.gradle.kts index fcaed71f4..e192e784a 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -28,6 +28,8 @@ plugins { alias(libs.plugins.sentry) alias(libs.plugins.slimjar) alias(libs.plugins.grgit) + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.lombok) } val apiVersion = "1.19" @@ -88,11 +90,23 @@ dependencies { slim(libs.zip) slim(libs.gson) slim(libs.asm) - slim(libs.bsf) - slim(libs.rhino) slim(libs.caffeine) slim(libs.byteBuddy.core) slim(libs.byteBuddy.agent) + slim(libs.dom4j) + slim(libs.jaxen) + + // Script Engine + slim(libs.kotlin.stdlib) + slim(libs.kotlin.coroutines) + slim(libs.kotlin.scripting.common) + slim(libs.kotlin.scripting.jvm) + slim(libs.kotlin.scripting.jvm.host) + slim(libs.kotlin.scripting.dependencies.maven) { + constraints { + slim(libs.mavenCore) + } + } } java { @@ -120,6 +134,11 @@ slimJar { relocate("net.kyori", "$lib.kyori") relocate("org.bstats", "$lib.metrics") relocate("io.sentry", "$lib.sentry") + relocate("org.apache.maven", "$lib.maven") + relocate("org.codehaus.plexus", "$lib.plexus") + relocate("org.eclipse.sisu", "$lib.sisu") + relocate("org.eclipse.aether", "$lib.aether") + relocate("com.google.inject", "$lib.guice") } tasks { diff --git a/core/src/main/java/com/volmit/iris/Iris.java b/core/src/main/java/com/volmit/iris/Iris.java index 69afb8353..615d40d89 100644 --- a/core/src/main/java/com/volmit/iris/Iris.java +++ b/core/src/main/java/com/volmit/iris/Iris.java @@ -742,7 +742,7 @@ public class Iris extends VolmitPlugin implements Listener { String padd2 = Form.repeat(" ", 4); String[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion()}; if (unstablemode) { - info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + getDescription().getVersion()}; + info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + getDescription().getVersion()}; } if (warningmode) { info = new String[]{"", "", "", "", "", padd2 + C.GOLD + " Iris", padd2 + C.GRAY + " by " + C.GOLD + "Volmit Software", padd2 + C.GRAY + " v" + C.GOLD + getDescription().getVersion()}; diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java index 2adb48780..452b41a1d 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java @@ -47,7 +47,6 @@ import com.volmit.iris.util.io.IO; import com.volmit.iris.util.json.JSONArray; import com.volmit.iris.util.json.JSONObject; import com.volmit.iris.util.mantle.MantleChunk; -import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; @@ -233,9 +232,7 @@ public class CommandStudio implements DecreeExecutor { chunkMap.forEach((pos, chunk) -> { var c = mantle.getChunk(pos.getX(), pos.getZ()).use(); try { - for (MantleFlag flag : MantleFlag.values()) { - c.flag(flag, chunk.isFlagged(flag)); - } + c.copyFlags(chunk); c.clear(); for (int y = 0; y < sections; y++) { var slice = chunk.get(y); @@ -370,7 +367,7 @@ public class CommandStudio implements DecreeExecutor { var sender = sender(); int d = radius * 2; KMap> data = new KMap<>(); - var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY); + var multiBurst = new MultiBurst("Distance Sampler"); var executor = multiBurst.burst(radius * radius); sender.sendMessage(C.GRAY + "Generating data..."); diff --git a/core/src/main/java/com/volmit/iris/core/link/data/MythicMobsDataProvider.java b/core/src/main/java/com/volmit/iris/core/link/data/MythicMobsDataProvider.java index 7c08b8e6a..c43e0e282 100644 --- a/core/src/main/java/com/volmit/iris/core/link/data/MythicMobsDataProvider.java +++ b/core/src/main/java/com/volmit/iris/core/link/data/MythicMobsDataProvider.java @@ -17,6 +17,7 @@ import org.bukkit.entity.Entity; import org.bukkit.event.EventHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.ConcurrentHashMap; diff --git a/core/src/main/java/com/volmit/iris/core/loader/IrisData.java b/core/src/main/java/com/volmit/iris/core/loader/IrisData.java index 7628f7da7..1bfcd1ba2 100644 --- a/core/src/main/java/com/volmit/iris/core/loader/IrisData.java +++ b/core/src/main/java/com/volmit/iris/core/loader/IrisData.java @@ -24,6 +24,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import com.volmit.iris.Iris; +import com.volmit.iris.core.scripting.environment.PackEnvironment; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.object.*; @@ -33,6 +34,8 @@ import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.context.IrisContext; import com.volmit.iris.util.format.C; +import com.volmit.iris.util.mantle.flag.MantleFlagAdapter; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; @@ -54,6 +57,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { private static final KMap dataLoaders = new KMap<>(); private final File dataFolder; private final int id; + private final PackEnvironment environment; private boolean closed = false; private ResourceLoader biomeLoader; private ResourceLoader lootLoader; @@ -87,6 +91,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { this.engine = null; this.dataFolder = dataFolder; this.id = RNG.r.imax(); + this.environment = PackEnvironment.create(this); hotloaded(); } @@ -252,12 +257,20 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { } } - if (engine != null && t.getPreprocessors().isNotEmpty()) { + if (engine == null) return; + var global = engine.getDimension().getPreProcessors(t.getFolderName()); + var local = t.getPreprocessors(); + if ((global != null && global.isNotEmpty()) || local.isNotEmpty()) { synchronized (this) { - engine.getExecution().getAPI().setPreprocessorObject(t); + if (global != null) { + for (String i : global) { + engine.getExecution().preprocessObject(i, t); + Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in " + i); + } + } - for (String i : t.getPreprocessors()) { - engine.getExecution().execute(i); + for (String i : local) { + engine.getExecution().preprocessObject(i, t); Iris.debug("Loader<" + C.GREEN + t.getTypeName() + C.LIGHT_PURPLE + "> iprocess " + C.YELLOW + t.getLoadKey() + C.LIGHT_PURPLE + " in " + i); } } @@ -271,6 +284,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { public void close() { closed = true; dump(); + dataLoaders.remove(dataFolder); } public IrisData copy() { @@ -311,12 +325,14 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { } public synchronized void hotloaded() { + environment.close(); possibleSnippets = new KMap<>(); builder = new GsonBuilder() .addDeserializationExclusionStrategy(this) .addSerializationExclusionStrategy(this) .setLenient() .registerTypeAdapterFactory(this) + .registerTypeAdapter(MantleFlag.class, new MantleFlagAdapter()) .setPrettyPrinting(); loaders.clear(); File packs = dataFolder; @@ -344,6 +360,10 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { builder.registerTypeAdapterFactory(KeyedType::createTypeAdapter); gson = builder.create(); + dimensionLoader.streamAll() + .map(IrisDimension::getDataScripts) + .flatMap(KList::stream) + .forEach(environment::execute); } public void dump() { diff --git a/core/src/main/java/com/volmit/iris/core/loader/ResourceLoader.java b/core/src/main/java/com/volmit/iris/core/loader/ResourceLoader.java index 83822ff86..25d37642d 100644 --- a/core/src/main/java/com/volmit/iris/core/loader/ResourceLoader.java +++ b/core/src/main/java/com/volmit/iris/core/loader/ResourceLoader.java @@ -45,6 +45,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import java.io.*; +import java.util.Arrays; import java.util.Locale; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -215,6 +216,10 @@ public class ResourceLoader implements MeteredCache { return j; } + public Stream streamAll() { + return streamAll(Arrays.stream(getPossibleKeys())); + } + public Stream streamAll(Stream s) { return s.map(this::load); } diff --git a/core/src/main/java/com/volmit/iris/core/loader/ScriptResourceLoader.java b/core/src/main/java/com/volmit/iris/core/loader/ScriptResourceLoader.java index 4c0a6a1de..793a0aa1b 100644 --- a/core/src/main/java/com/volmit/iris/core/loader/ScriptResourceLoader.java +++ b/core/src/main/java/com/volmit/iris/core/loader/ScriptResourceLoader.java @@ -82,8 +82,8 @@ public class ScriptResourceLoader extends ResourceLoader { private Set getKeysInDirectory(File directory) { Set keys = new HashSet<>(); for (File file : directory.listFiles()) { - if (file.isFile() && file.getName().endsWith(".js")) { - keys.add(file.getName().replaceAll("\\Q.js\\E", "")); + if (file.isFile() && file.getName().endsWith(".kts")) { + keys.add(file.getName().replaceAll("\\Q.kts\\E", "")); } else if (file.isDirectory()) { keys.addAll(getKeysInDirectory(file)); } @@ -127,12 +127,12 @@ public class ScriptResourceLoader extends ResourceLoader { public File findFile(String name) { for (File i : getFolders(name)) { for (File j : i.listFiles()) { - if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) { + if (j.isFile() && j.getName().endsWith(".kts") && j.getName().split("\\Q.\\E")[0].equals(name)) { return j; } } - File file = new File(i, name + ".js"); + File file = new File(i, name + ".kts"); if (file.exists()) { return file; @@ -147,12 +147,12 @@ public class ScriptResourceLoader extends ResourceLoader { private IrisScript loadRaw(String name) { for (File i : getFolders(name)) { for (File j : i.listFiles()) { - if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) { + if (j.isFile() && j.getName().endsWith(".kts") && j.getName().split("\\Q.\\E")[0].equals(name)) { return loadFile(j, name); } } - File file = new File(i, name + ".js"); + File file = new File(i, name + ".kts"); if (file.exists()) { return loadFile(file, name); diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java index 0dba60111..bce79233c 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java @@ -8,7 +8,7 @@ import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.format.Form; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RollingSequence; diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCacheImpl.java b/core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCacheImpl.java index b9a3de943..f1e065fa2 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCacheImpl.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/cache/PregenCacheImpl.java @@ -14,12 +14,10 @@ import net.jpountz.lz4.LZ4BlockInputStream; import net.jpountz.lz4.LZ4BlockOutputStream; import org.jetbrains.annotations.Nullable; -import javax.annotation.concurrent.NotThreadSafe; import java.io.*; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; -@NotThreadSafe @RequiredArgsConstructor class PregenCacheImpl implements PregenCache { private static final int SIZE = 32; diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java index 0dcfffcfc..7e92807bf 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java @@ -192,7 +192,7 @@ public class AsyncPregenMethod implements PregeneratorMethod { private class ServiceExecutor implements Executor { private final ExecutorService service = IrisSettings.get().getPregen().isUseVirtualThreads() ? Executors.newVirtualThreadPerTaskExecutor() : - new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY); + new MultiBurst("Iris Async Pregen"); public void generate(int x, int z, PregenListener listener) { service.submit(() -> { diff --git a/core/src/main/java/com/volmit/iris/core/project/Gradle.java b/core/src/main/java/com/volmit/iris/core/project/Gradle.java new file mode 100644 index 000000000..c28b28ca4 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/project/Gradle.java @@ -0,0 +1,104 @@ +package com.volmit.iris.core.project; + +import com.volmit.iris.Iris; +import com.volmit.iris.util.io.IO; +import org.zeroturnaround.zip.ZipUtil; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.HashMap; +import java.util.Optional; +import java.util.Scanner; + +public class Gradle { + private static final boolean WINDOWS = System.getProperty("os.name").toLowerCase().contains("win"); + private static final String[] ENVIRONMENT = createEnvironment(); + private static final String VERSION = "8.14.2"; + private static final String DISTRIBUTION_URL = "https://services.gradle.org/distributions/gradle-" + VERSION + "-bin.zip"; + private static final String HASH = IO.hash(DISTRIBUTION_URL); + + public static synchronized void wrapper(File projectDir) { + try { + File settings = new File(projectDir, "settings.gradle.kts"); + if (!settings.exists()) settings.createNewFile(); + runGradle(projectDir, "wrapper"); + } catch (Throwable e) { + Iris.error("Failed to install gradle wrapper!"); + e.printStackTrace(); + Iris.reportError(e); + } + } + + public static void runGradle(File projectDir, String... args) throws IOException, InterruptedException { + File gradle = downloadGradle(false); + String[] cmd = new String[args.length + 1]; + cmd[0] = gradle.getAbsolutePath(); + System.arraycopy(args, 0, cmd, 1, args.length); + var process = Runtime.getRuntime().exec(cmd, ENVIRONMENT, projectDir); + attach(process.getInputStream()); + attach(process.getErrorStream()); + var code = process.waitFor(); + if (code == 0) return; + throw new RuntimeException("Gradle exited with code " + code); + } + + private static synchronized File downloadGradle(boolean force) { + var folder = Iris.instance.getDataFolder("cache", HASH.substring(0, 2), HASH); + if (force) { + IO.delete(folder); + folder.mkdirs(); + } + + var bin = new File(folder, "gradle-" + VERSION + "/bin/gradle" + (WINDOWS ? ".bat" : "")); + if (bin.exists()) { + bin.setExecutable(true); + return bin; + } + + try (var input = new BufferedInputStream(URI.create(DISTRIBUTION_URL).toURL().openStream())) { + ZipUtil.unpack(input, folder); + } catch (Throwable e) { + throw new RuntimeException("Failed to download gradle", e); + } + + bin.setExecutable(true); + return bin; + } + + private static String[] createEnvironment() { + var env = new HashMap<>(System.getenv()); + env.put("JAVA_HOME", findJavaHome()); + return env.entrySet() + .stream() + .map(e -> e.getKey() + "=" + e.getValue()) + .toArray(String[]::new); + } + + private static String findJavaHome() { + String javaHome = System.getProperty("java.home"); + if (javaHome != null && new File(javaHome + "/bin/java" + (WINDOWS ? ".exe" : "")).exists()) { + return javaHome; + } + + return ProcessHandle.current() + .info() + .command() + .map(s -> new File(s).getAbsoluteFile().getParentFile().getParentFile()) + .flatMap(f -> f.exists() ? Optional.of(f.getAbsolutePath()) : Optional.empty()) + .orElseThrow(() -> new RuntimeException("Failed to find java home, please set java.home system property")); + } + + private static void attach(InputStream stream) { + Thread.ofVirtual().start(() -> { + try (var in = new Scanner(stream)) { + while (in.hasNextLine()) { + String line = in.nextLine(); + Iris.debug("[GRADLE] " + line); + } + } + }); + } +} diff --git a/core/src/main/java/com/volmit/iris/core/project/IrisProject.java b/core/src/main/java/com/volmit/iris/core/project/IrisProject.java index c0f327b6f..716173bd6 100644 --- a/core/src/main/java/com/volmit/iris/core/project/IrisProject.java +++ b/core/src/main/java/com/volmit/iris/core/project/IrisProject.java @@ -24,6 +24,7 @@ import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisRegistrant; import com.volmit.iris.core.loader.ResourceLoader; +import com.volmit.iris.core.scripting.environment.SimpleEnvironment; import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.object.annotations.Snippet; @@ -49,6 +50,8 @@ import lombok.Data; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.World; +import org.dom4j.Document; +import org.dom4j.Element; import org.zeroturnaround.zip.ZipUtil; import java.awt.*; @@ -217,24 +220,15 @@ public class IrisProject { close(); } - boolean hasError = false; - - if (hasError) { - return; - } - - IrisDimension d = IrisData.loadAnyDimension(getName()); - if (d == null) { - sender.sendMessage("Can't find dimension: " + getName()); - return; - } else if (sender.isPlayer()) { - sender.player().setGameMode(GameMode.SPECTATOR); - } - - openVSCode(sender); - - J.a(() -> { + IrisDimension d = IrisData.loadAnyDimension(getName()); + if (d == null) { + sender.sendMessage("Can't find dimension: " + getName()); + return; + } else if (sender.isPlayer()) { + sender.player().setGameMode(GameMode.SPECTATOR); + } + try { activeProvider = (PlatformChunkGenerator) IrisToolbelt.createWorld() .seed(seed) @@ -247,6 +241,8 @@ public class IrisProject { } catch (IrisException e) { e.printStackTrace(); } + + openVSCode(sender); }); } @@ -359,6 +355,74 @@ public class IrisProject { settings.put("json.schemas", schemas); ws.put("settings", settings); + dm.getEnvironment().configureProject(); + File schemasFile = new File(path, ".idea" + File.separator + "jsonSchemas.xml"); + Document doc = IO.read(schemasFile); + Element mappings = (Element) doc.selectSingleNode("//component[@name='JsonSchemaMappingsProjectConfiguration']"); + if (mappings == null) { + mappings = doc.getRootElement() + .addElement("component") + .addAttribute("name", "JsonSchemaMappingsProjectConfiguration"); + } + + Element state = (Element) mappings.selectSingleNode("state"); + if (state == null) state = mappings.addElement("state"); + + Element map = (Element) state.selectSingleNode("map"); + if (map == null) map = state.addElement("map"); + var schemaMap = new KMap(); + schemas.forEach(element -> { + if (!(element instanceof JSONObject obj)) + return; + + String url = obj.getString("url"); + String dir = obj.getJSONArray("fileMatch").getString(0); + schemaMap.put(url, dir.substring(1, dir.indexOf("/*"))); + }); + + map.selectNodes("entry/value/SchemaInfo/option[@name='relativePathToSchema']") + .stream() + .map(node -> node.valueOf("@value")) + .forEach(schemaMap::remove); + + var ideaSchemas = map; + schemaMap.forEach((url, dir) -> { + var genName = UUID.randomUUID().toString(); + + var info = ideaSchemas.addElement("entry") + .addAttribute("key", genName) + .addElement("value") + .addElement("SchemaInfo"); + info.addElement("option") + .addAttribute("name", "generatedName") + .addAttribute("value", genName); + info.addElement("option") + .addAttribute("name", "name") + .addAttribute("value", dir); + info.addElement("option") + .addAttribute("name", "relativePathToSchema") + .addAttribute("value", url); + + + var item = info.addElement("option") + .addAttribute("name", "patterns") + .addElement("list") + .addElement("Item"); + item.addElement("option") + .addAttribute("name", "directory") + .addAttribute("value", "true"); + item.addElement("option") + .addAttribute("name", "path") + .addAttribute("value", dir); + item.addElement("option") + .addAttribute("name", "mappingKind") + .addAttribute("value", "Directory"); + }); + if (!schemaMap.isEmpty()) { + IO.write(schemasFile, doc); + } + Gradle.wrapper(path); + return ws; } diff --git a/core/src/main/java/com/volmit/iris/core/project/SchemaBuilder.java b/core/src/main/java/com/volmit/iris/core/project/SchemaBuilder.java index f5fe814c3..1570ca6d8 100644 --- a/core/src/main/java/com/volmit/iris/core/project/SchemaBuilder.java +++ b/core/src/main/java/com/volmit/iris/core/project/SchemaBuilder.java @@ -110,7 +110,9 @@ public class SchemaBuilder { private JSONObject buildProperties(Class c) { JSONObject o = new JSONObject(); JSONObject properties = new JSONObject(); - o.put("description", getDescription(c)); + String desc = getDescription(c); + o.put("description", desc); + o.put("x-intellij-html-description", desc.replace("\n", "
")); o.put("type", getType(c)); JSONArray required = new JSONArray(); @@ -520,11 +522,12 @@ public class SchemaBuilder { } KList d = new KList<>(); - d.add(k.getName()); - d.add(getFieldDescription(k)); - d.add(" "); - d.add(fancyType); - d.add(getDescription(k.getType())); + d.add("" + k.getName() + ""); + d.add(getFieldDescription(k) + "
"); + d.add("" + fancyType + ""); + String typeDesc = getDescription(k.getType()); + boolean present = !typeDesc.isBlank(); + if (present) d.add(typeDesc); Snippet snippet = k.getType().getDeclaredAnnotation(Snippet.class); if (snippet == null) { @@ -536,8 +539,9 @@ public class SchemaBuilder { if (snippet != null) { String sm = snippet.value(); - d.add(" "); + if (present) d.add(" "); d.add("You can instead specify \"snippet/" + sm + "/some-name.json\" to use a snippet file instead of specifying it here."); + present = false; } try { @@ -545,15 +549,13 @@ public class SchemaBuilder { Object value = k.get(cl.newInstance()); if (value != null) { + if (present) d.add(" "); if (value instanceof List) { - d.add(" "); - d.add("* Default Value is an empty list"); + d.add(SYMBOL_LIMIT__N + " Default Value is an empty list"); } else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()) && !KeyedType.isKeyed(cl)) { - d.add(" "); - d.add("* Default Value is a default object (create this object to see default properties)"); + d.add(SYMBOL_LIMIT__N + " Default Value is a default object (create this object to see default properties)"); } else { - d.add(" "); - d.add("* Default Value is " + value); + d.add(SYMBOL_LIMIT__N + " Default Value is " + value); } } } catch (Throwable ignored) { @@ -561,8 +563,14 @@ public class SchemaBuilder { } description.forEach((g) -> d.add(g.trim())); + String desc = d.toString("\n") + .replace("
", "\n") + .replace("", "") + .replace("", ""); + String hDesc = d.toString("
"); prop.put("type", type); - prop.put("description", d.toString("\n")); + prop.put("description", desc); + prop.put("x-intellij-html-description", hDesc); return buildSnippet(prop, k.getType()); } @@ -588,8 +596,10 @@ public class SchemaBuilder { arr.put(prop); arr.put(str); str.put("description", prop.getString("description")); + str.put("x-intellij-html-description", prop.getString("x-intellij-html-description")); anyOf.put("anyOf", arr); anyOf.put("description", prop.getString("description")); + anyOf.put("x-intellij-html-description", prop.getString("x-intellij-html-description")); anyOf.put("!required", type.isAnnotationPresent(Required.class)); return anyOf; @@ -615,7 +625,9 @@ public class SchemaBuilder { String name = function.apply(gg); j.put("const", name); Desc dd = type.getField(name).getAnnotation(Desc.class); - j.put("description", dd == null ? ("No Description for " + name) : dd.value()); + String desc = dd == null ? ("No Description for " + name) : dd.value(); + j.put("description", desc); + j.put("x-intellij-html-description", desc.replace("\n", "
")); a.put(j); } catch (Throwable e) { Iris.reportError(e); diff --git a/core/src/main/java/com/volmit/iris/core/scripting/environment/EngineEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/environment/EngineEnvironment.java new file mode 100644 index 000000000..64507eeb8 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/scripting/environment/EngineEnvironment.java @@ -0,0 +1,25 @@ +package com.volmit.iris.core.scripting.environment; + +import com.volmit.iris.core.loader.IrisRegistrant; +import com.volmit.iris.core.scripting.kotlin.environment.IrisExecutionEnvironment; +import com.volmit.iris.engine.framework.Engine; +import lombok.NonNull; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.Nullable; + +public interface EngineEnvironment extends PackEnvironment { + static EngineEnvironment create(@NonNull Engine engine) { + return new IrisExecutionEnvironment(engine); + } + + @NonNull + Engine getEngine(); + + @Nullable + Object spawnMob(@NonNull String script, @NonNull Location location); + + void postSpawnMob(@NonNull String script, @NonNull Location location, @NonNull Entity mob); + + void preprocessObject(@NonNull String script, @NonNull IrisRegistrant object); +} \ No newline at end of file diff --git a/core/src/main/java/com/volmit/iris/core/scripting/environment/PackEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/environment/PackEnvironment.java new file mode 100644 index 000000000..c5dbccf22 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/scripting/environment/PackEnvironment.java @@ -0,0 +1,19 @@ +package com.volmit.iris.core.scripting.environment; + +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.core.scripting.kotlin.environment.IrisPackExecutionEnvironment; +import com.volmit.iris.util.math.RNG; +import lombok.NonNull; +import org.jetbrains.annotations.Nullable; + +public interface PackEnvironment extends SimpleEnvironment { + static PackEnvironment create(@NonNull IrisData data) { + return new IrisPackExecutionEnvironment(data); + } + + @NonNull + IrisData getData(); + + @Nullable + Object createNoise(@NonNull String script, @NonNull RNG rng); +} \ No newline at end of file diff --git a/core/src/main/java/com/volmit/iris/core/scripting/environment/SimpleEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/environment/SimpleEnvironment.java new file mode 100644 index 000000000..4eb7e0ce8 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/scripting/environment/SimpleEnvironment.java @@ -0,0 +1,34 @@ +package com.volmit.iris.core.scripting.environment; + +import com.volmit.iris.core.scripting.kotlin.environment.IrisSimpleExecutionEnvironment; +import lombok.NonNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.Map; + +public interface SimpleEnvironment { + static SimpleEnvironment create() { + return new IrisSimpleExecutionEnvironment(); + } + + static SimpleEnvironment create(@NonNull File projectDir) { + return new IrisSimpleExecutionEnvironment(projectDir); + } + + void configureProject(); + + void execute(@NonNull String script); + + void execute(@NonNull String script, @NonNull Class type, @Nullable Map<@NonNull String, Object> vars); + + @Nullable + Object evaluate(@NonNull String script); + + @Nullable + Object evaluate(@NonNull String script, @NonNull Class type, @Nullable Map<@NonNull String, Object> vars); + + default void close() { + + } +} \ No newline at end of file diff --git a/core/src/main/java/com/volmit/iris/core/scripting/func/BiomeLookup.java b/core/src/main/java/com/volmit/iris/core/scripting/func/BiomeLookup.java new file mode 100644 index 000000000..d27247b1a --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/scripting/func/BiomeLookup.java @@ -0,0 +1,10 @@ +package com.volmit.iris.core.scripting.func; + +import com.volmit.iris.engine.object.IrisBiome; +import com.volmit.iris.util.documentation.BlockCoordinates; + +@FunctionalInterface +public interface BiomeLookup { + @BlockCoordinates + IrisBiome at(int x, int z); +} diff --git a/core/src/main/java/com/volmit/iris/engine/IrisEngine.java b/core/src/main/java/com/volmit/iris/engine/IrisEngine.java index e5db0d978..d35dd3311 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngine.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngine.java @@ -28,12 +28,12 @@ import com.volmit.iris.core.loader.ResourceLoader; import com.volmit.iris.core.nms.container.BlockPos; import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.core.project.IrisProject; +import com.volmit.iris.core.scripting.environment.EngineEnvironment; import com.volmit.iris.core.service.PreservationSVC; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.framework.*; import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.object.*; -import com.volmit.iris.engine.scripting.EngineExecutionEnvironment; import com.volmit.iris.util.atomics.AtomicRollingSequence; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.context.ChunkContext; @@ -43,7 +43,7 @@ import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.io.IO; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.MatterStructurePOI; @@ -94,7 +94,7 @@ public class IrisEngine implements Engine { private CompletableFuture hash32; private EngineMode mode; private EngineEffects effects; - private EngineExecutionEnvironment execution; + private EngineEnvironment execution; private EngineWorldManager worldManager; private volatile int parallelism; private boolean failing; @@ -170,10 +170,11 @@ public class IrisEngine implements Engine { cacheId = RNG.r.nextInt(); worldManager = new IrisWorldManager(this); complex = new IrisComplex(this); - execution = new IrisExecutionEnvironment(this); + execution = EngineEnvironment.create(this); effects = new IrisEngineEffects(this); hash32 = new CompletableFuture<>(); setupMode(); + getDimension().getEngineScripts().forEach(execution::execute); J.a(this::computeBiomeMaxes); J.a(() -> { File[] roots = getData().getLoaders() @@ -199,7 +200,7 @@ public class IrisEngine implements Engine { mode.close(); } - mode = getDimension().getMode().getType().create(this); + mode = getDimension().getMode().create(this); } @Override diff --git a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java index e58324ad7..10d12aa9d 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java @@ -31,7 +31,7 @@ import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.mantle.Mantle; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import lombok.*; import java.io.File; diff --git a/core/src/main/java/com/volmit/iris/engine/IrisExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/engine/IrisExecutionEnvironment.java deleted file mode 100644 index 51ca6d1f9..000000000 --- a/core/src/main/java/com/volmit/iris/engine/IrisExecutionEnvironment.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2022 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.volmit.iris.engine; - -import com.volmit.iris.Iris; -import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.engine.object.IrisScript; -import com.volmit.iris.engine.scripting.EngineExecutionEnvironment; -import com.volmit.iris.engine.scripting.IrisScriptingAPI; -import com.volmit.iris.util.format.C; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.apache.bsf.BSFException; -import org.apache.bsf.BSFManager; -import org.apache.bsf.engines.javascript.JavaScriptEngine; - -@Data -@EqualsAndHashCode(exclude = "engine") -@ToString(exclude = "engine") -public class IrisExecutionEnvironment implements EngineExecutionEnvironment { - private final BSFManager manager; - private final Engine engine; - private final IrisScriptingAPI api; - private JavaScriptEngine javaScriptEngine; - - public IrisExecutionEnvironment(Engine engine) { - this.engine = engine; - this.api = new IrisScriptingAPI(engine); - this.manager = new BSFManager(); - this.manager.setClassLoader(Iris.class.getClassLoader()); - try { - this.manager.declareBean("Iris", api, api.getClass()); - this.javaScriptEngine = (JavaScriptEngine) this.manager.loadScriptingEngine("javascript"); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - @Override - public IrisScriptingAPI getAPI() { - return api; - } - - public void execute(String script) { - execute(getEngine().getData().getScriptLoader().load(script)); - } - - public void execute(IrisScript script) { - Iris.debug("Execute Script (void) " + C.DARK_GREEN + script.getLoadKey()); - try { - javaScriptEngine.exec("", 0, 0, script); - } catch (BSFException e) { - e.printStackTrace(); - } - } - - public Object evaluate(String script) { - Iris.debug("Execute Script (for result) " + C.DARK_GREEN + script); - try { - return javaScriptEngine.eval("", 0, 0, getEngine().getData().getScriptLoader().load(script)); - } catch (BSFException e) { - e.printStackTrace(); - } - - return null; - } -} diff --git a/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java b/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java index 95ba698c9..e44ac8700 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java @@ -29,7 +29,7 @@ import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.mantle.Mantle; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 348d0b122..9026729e9 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -29,13 +29,13 @@ import com.volmit.iris.core.loader.IrisRegistrant; import com.volmit.iris.core.nms.container.BlockPos; import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.core.pregenerator.ChunkUpdater; +import com.volmit.iris.core.scripting.environment.EngineEnvironment; import com.volmit.iris.core.service.ExternalDataSVC; import com.volmit.iris.engine.IrisComplex; import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.data.chunk.TerrainChunk; import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.object.*; -import com.volmit.iris.engine.scripting.EngineExecutionEnvironment; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.context.ChunkContext; @@ -48,7 +48,7 @@ import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.format.C; import com.volmit.iris.util.function.Function2; import com.volmit.iris.util.hunk.Hunk; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.BlockPosition; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.Position2; @@ -110,7 +110,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat IrisContext getContext(); - EngineExecutionEnvironment getExecution(); + EngineEnvironment getExecution(); double getMaxBiomeObjectDensity(); diff --git a/core/src/main/java/com/volmit/iris/engine/framework/PlacedObject.java b/core/src/main/java/com/volmit/iris/engine/framework/PlacedObject.java index e96155572..31cdf1b59 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/PlacedObject.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/PlacedObject.java @@ -22,8 +22,7 @@ import com.volmit.iris.engine.object.IrisObject; import com.volmit.iris.engine.object.IrisObjectPlacement; import lombok.AllArgsConstructor; import lombok.Data; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; @Data @AllArgsConstructor diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/ComponentFlag.java b/core/src/main/java/com/volmit/iris/engine/mantle/ComponentFlag.java index 1c7fe20b2..0ed617a7d 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/ComponentFlag.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/ComponentFlag.java @@ -1,6 +1,6 @@ package com.volmit.iris.engine.mantle; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.ReservedFlag; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -10,5 +10,5 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ComponentFlag { - MantleFlag value(); + ReservedFlag value(); } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java index b2c87fe4f..c31478b15 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java @@ -37,7 +37,7 @@ import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.MantleChunk; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.matter.*; import com.volmit.iris.util.matter.slices.UpdateMatter; diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java index cfe72ae39..ec99fd32c 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java @@ -18,7 +18,7 @@ package com.volmit.iris.engine.mantle; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java index 64c69d5c6..43a61c65c 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java @@ -24,7 +24,7 @@ import com.volmit.iris.engine.object.IrisDimension; import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.mantle.Mantle; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.parallel.BurstExecutor; import org.jetbrains.annotations.NotNull; diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java index eca862c79..19bd89b32 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java @@ -28,17 +28,17 @@ import com.volmit.iris.engine.object.IrisCarving; import com.volmit.iris.engine.object.IrisRegion; import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.documentation.ChunkCoordinates; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.ReservedFlag; import com.volmit.iris.util.math.RNG; import lombok.Getter; @Getter -@ComponentFlag(MantleFlag.CARVED) +@ComponentFlag(ReservedFlag.CARVED) public class MantleCarvingComponent extends IrisMantleComponent { private final int radius = computeRadius(); public MantleCarvingComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.CARVED, 0); + super(engineMantle, ReservedFlag.CARVED, 0); } @Override diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java index 15389715e..dcfe9653d 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java @@ -28,17 +28,17 @@ import com.volmit.iris.engine.object.IrisFluidBodies; import com.volmit.iris.engine.object.IrisRegion; import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.documentation.ChunkCoordinates; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.ReservedFlag; import com.volmit.iris.util.math.RNG; import lombok.Getter; @Getter -@ComponentFlag(MantleFlag.FLUID_BODIES) +@ComponentFlag(ReservedFlag.FLUID_BODIES) public class MantleFluidBodyComponent extends IrisMantleComponent { private final int radius = computeRadius(); public MantleFluidBodyComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.FLUID_BODIES, 0); + super(engineMantle, ReservedFlag.FLUID_BODIES, 0); } @Override diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java index 376560289..8f59ae93d 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java @@ -30,7 +30,7 @@ import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.documentation.BlockCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.ReservedFlag; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer; @@ -40,14 +40,14 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -@ComponentFlag(MantleFlag.JIGSAW) +@ComponentFlag(ReservedFlag.JIGSAW) public class MantleJigsawComponent extends IrisMantleComponent { @Getter private final int radius = computeRadius(); private final CNG cng; public MantleJigsawComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.JIGSAW, 2); + super(engineMantle, ReservedFlag.JIGSAW, 2); cng = NoiseStyle.STATIC.create(new RNG(jigsaw())); } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java index a4ca6dd7a..bc48a9969 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java @@ -33,7 +33,7 @@ import com.volmit.iris.util.data.B; import com.volmit.iris.util.documentation.BlockCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.format.Form; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.ReservedFlag; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.MatterStructurePOI; import com.volmit.iris.util.noise.CNG; @@ -48,12 +48,12 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @Getter -@ComponentFlag(MantleFlag.OBJECT) +@ComponentFlag(ReservedFlag.OBJECT) public class MantleObjectComponent extends IrisMantleComponent { private final int radius = computeRadius(); public MantleObjectComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.OBJECT, 1); + super(engineMantle, ReservedFlag.OBJECT, 1); } @Override diff --git a/core/src/main/java/com/volmit/iris/engine/modifier/IrisCustomModifier.java b/core/src/main/java/com/volmit/iris/engine/modifier/IrisCustomModifier.java index 161600101..eca550cd2 100644 --- a/core/src/main/java/com/volmit/iris/engine/modifier/IrisCustomModifier.java +++ b/core/src/main/java/com/volmit/iris/engine/modifier/IrisCustomModifier.java @@ -5,7 +5,7 @@ import com.volmit.iris.engine.framework.EngineAssignedModifier; import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.data.IrisCustomData; import com.volmit.iris.util.hunk.Hunk; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; import org.bukkit.block.data.BlockData; diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java b/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java index ef76eac9f..704d0b014 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java @@ -30,11 +30,12 @@ import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.object.annotations.*; import com.volmit.iris.engine.object.annotations.functions.ComponentFlagFunction; import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.data.DataProvider; import com.volmit.iris.util.io.IO; import com.volmit.iris.util.json.JSONObject; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.noise.CNG; @@ -68,6 +69,7 @@ public class IrisDimension extends IrisRegistrant { private final transient AtomicCache rad = new AtomicCache<>(); private final transient AtomicCache featuresUsed = new AtomicCache<>(); private final transient AtomicCache> strongholdsCache = new AtomicCache<>(); + private final transient AtomicCache>> cachedPreProcessors = new AtomicCache<>(); @MinNumber(2) @Required @Desc("The human readable name of this dimension") @@ -241,9 +243,20 @@ public class IrisDimension extends IrisRegistrant { @Desc("The Subterrain Fluid Layer Height") private int caveLavaHeight = 8; @RegistryListFunction(ComponentFlagFunction.class) - @ArrayType(type = MantleFlag.class) + @ArrayType(type = String.class) @Desc("Collection of disabled components") private KList disabledComponents = new KList<>(); + @Desc("A list of globally applied pre-processors") + @ArrayType(type = IrisPreProcessors.class) + private KList globalPreProcessors = new KList<>(); + @Desc("A list of scripts executed on engine setup") + @RegistryListResource(IrisScript.class) + @ArrayType(type = String.class, min = 1) + private KList engineScripts = new KList<>(); + @Desc("A list of scripts executed on data setup") + @RegistryListResource(IrisScript.class) + @ArrayType(type = String.class, min = 1) + private KList dataScripts = new KList<>(); public int getMaxHeight() { return (int) getDimensionHeight().getMax(); @@ -364,6 +377,17 @@ public class IrisDimension extends IrisRegistrant { return r; } + public KList getPreProcessors(String type) { + return cachedPreProcessors.aquire(() -> { + KMap> preProcessors = new KMap<>(); + for (var entry : globalPreProcessors) { + preProcessors.computeIfAbsent(entry.getType(), k -> new KList<>()) + .addAll(entry.getScripts()); + } + return preProcessors; + }).get(type); + } + public IrisGeneratorStyle getBiomeStyle(InferredType type) { switch (type) { case CAVE: diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisDimensionMode.java b/core/src/main/java/com/volmit/iris/engine/object/IrisDimensionMode.java index ccf3c49b1..07b0e252b 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisDimensionMode.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisDimensionMode.java @@ -18,7 +18,10 @@ package com.volmit.iris.engine.object; +import com.volmit.iris.engine.framework.Engine; +import com.volmit.iris.engine.framework.EngineMode; import com.volmit.iris.engine.object.annotations.Desc; +import com.volmit.iris.engine.object.annotations.RegistryListResource; import com.volmit.iris.engine.object.annotations.Snippet; import lombok.AllArgsConstructor; import lombok.Data; @@ -35,4 +38,19 @@ public class IrisDimensionMode { @Desc("The dimension type") private IrisDimensionModeType type = IrisDimensionModeType.OVERWORLD; + @RegistryListResource(IrisScript.class) + @Desc("The script to create the dimension mode instead of using provided types") + private String script; + + public EngineMode create(Engine engine) { + if (script == null) { + return type.create(engine); + } + Object result = engine.getExecution().evaluate(script); + if (result instanceof EngineMode) { + return (EngineMode) result; + } + + throw new IllegalStateException("The script '" + script + "' did not return an engine mode!"); + } } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java index a87c319d0..a1f51863f 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java @@ -213,9 +213,8 @@ public class IrisEntity extends IrisRegistrant { if (!spawnerScript.isEmpty() && ee == null) { synchronized (this) { - gen.getExecution().getAPI().setLocation(at); try { - ee = (Entity) gen.getExecution().evaluate(spawnerScript); + ee = (Entity) gen.getExecution().spawnMob(spawnerScript, at); } catch (Throwable ex) { Iris.error("You must return an Entity in your scripts to use entity scripts!"); ex.printStackTrace(); @@ -355,11 +354,8 @@ public class IrisEntity extends IrisRegistrant { if (postSpawnScripts.isNotEmpty()) { synchronized (this) { - gen.getExecution().getAPI().setLocation(at); - gen.getExecution().getAPI().setEntity(ee); - for (String i : postSpawnScripts) { - gen.getExecution().execute(i); + gen.getExecution().postSpawnMob(i, at, ee); } } } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java b/core/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java index 1c1da694b..7f7ae9f47 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java @@ -18,6 +18,7 @@ package com.volmit.iris.engine.object; +import com.volmit.iris.Iris; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.object.annotations.*; @@ -25,6 +26,7 @@ import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.noise.CNG; import com.volmit.iris.util.noise.ExpressionNoise; import com.volmit.iris.util.noise.ImageNoise; +import com.volmit.iris.util.noise.NoiseGenerator; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -56,6 +58,9 @@ public class IrisGeneratorStyle { private String expression = null; @Desc("Use an Image map instead of a generated value") private IrisImageMap imageMap = null; + @Desc("Instead of using the style property, use a custom noise generator to represent this style.") + @RegistryListResource(IrisScript.class) + private String script = null; @MinNumber(0.00001) @Desc("The Output multiplier. Only used if parent is fracture.") private double multiplier = 1; @@ -93,40 +98,27 @@ public class IrisGeneratorStyle { public CNG createNoCache(RNG rng, IrisData data, boolean actuallyCached) { String cacheKey = hash() + ""; + CNG cng = null; if (getExpression() != null) { IrisExpression e = data.getExpressionLoader().load(getExpression()); - if (e != null) { - CNG cng = new CNG(rng, new ExpressionNoise(rng, e), 1D, 1) - .bake().scale(1D / zoom).pow(exponent).bake(); - cng.setTrueFracturing(axialFracturing); - - if (fracture != null) { - cng.fractureWith(fracture.create(rng.nextParallelRNG(2934), data), fracture.getMultiplier()); - } - - if (cellularFrequency > 0) { - return cng.cellularize(rng.nextParallelRNG(884466), cellularFrequency).scale(1D / cellularZoom).bake(); - } - - return cng; + cng = new CNG(rng, new ExpressionNoise(rng, e), 1D, 1).bake(); } } else if (getImageMap() != null) { - CNG cng = new CNG(rng, new ImageNoise(data, getImageMap()), 1D, 1).bake().scale(1D / zoom).pow(exponent).bake(); - cng.setTrueFracturing(axialFracturing); - - if (fracture != null) { - cng.fractureWith(fracture.create(rng.nextParallelRNG(2934), data), fracture.getMultiplier()); + cng = new CNG(rng, new ImageNoise(data, getImageMap()), 1D, 1).bake(); + } else if (getScript() != null) { + Object result = data.getEnvironment().createNoise(getScript(), rng); + if (result == null) Iris.warn("Failed to create noise from script: " + getScript()); + if (result instanceof NoiseGenerator generator) { + cng = new CNG(rng, generator, 1D, 1).bake(); } - - if (cellularFrequency > 0) { - return cng.cellularize(rng.nextParallelRNG(884466), cellularFrequency).scale(1D / cellularZoom).bake(); - } - - return cng; } - CNG cng = style.create(rng).bake().scale(1D / zoom).pow(exponent).bake(); + if (cng == null) { + cng = style.create(rng).bake(); + } + + cng = cng.scale(1D / zoom).pow(exponent).bake(); cng.setTrueFracturing(axialFracturing); if (fracture != null) { diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisPreProcessors.java b/core/src/main/java/com/volmit/iris/engine/object/IrisPreProcessors.java new file mode 100644 index 000000000..fb62a9d78 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisPreProcessors.java @@ -0,0 +1,25 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.engine.object.annotations.*; +import com.volmit.iris.engine.object.annotations.functions.ResourceLoadersFunction; +import com.volmit.iris.util.collection.KList; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Desc("Represents global preprocessors") +public class IrisPreProcessors { + @Required + @Desc("The preprocessor type") + @RegistryListFunction(ResourceLoadersFunction.class) + private String type = "dimension"; + + @Required + @Desc("The preprocessor scripts") + @RegistryListResource(IrisScript.class) + @ArrayType(type = String.class, min = 1) + private KList scripts = new KList<>(); +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ComponentFlagFunction.java b/core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ComponentFlagFunction.java index 7a0c01755..fb8738ffe 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ComponentFlagFunction.java +++ b/core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ComponentFlagFunction.java @@ -6,7 +6,7 @@ import com.volmit.iris.engine.framework.ListFunction; import com.volmit.iris.engine.mantle.ComponentFlag; import com.volmit.iris.engine.mantle.MantleComponent; import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.mantle.flag.MantleFlag; import java.util.Objects; diff --git a/core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ResourceLoadersFunction.java b/core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ResourceLoadersFunction.java new file mode 100644 index 000000000..943a96113 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ResourceLoadersFunction.java @@ -0,0 +1,28 @@ +package com.volmit.iris.engine.object.annotations.functions; + +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.core.loader.ResourceLoader; +import com.volmit.iris.engine.framework.ListFunction; +import com.volmit.iris.util.collection.KList; + +public class ResourceLoadersFunction implements ListFunction> { + @Override + public String key() { + return "resource-loader"; + } + + @Override + public String fancyName() { + return "Resource Loader"; + } + + @Override + public KList apply(IrisData data) { + return data.getLoaders() + .values() + .stream() + .filter(rl -> ResourceLoader.class.equals(rl.getClass())) + .map(ResourceLoader::getFolderName) + .collect(KList.collector()); + } +} diff --git a/core/src/main/java/com/volmit/iris/engine/scripting/EngineExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/engine/scripting/EngineExecutionEnvironment.java deleted file mode 100644 index 464feb77a..000000000 --- a/core/src/main/java/com/volmit/iris/engine/scripting/EngineExecutionEnvironment.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2022 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.volmit.iris.engine.scripting; - -import com.volmit.iris.engine.framework.Engine; -import org.apache.bsf.BSFManager; - -public interface EngineExecutionEnvironment { - Engine getEngine(); - - IrisScriptingAPI getAPI(); - - BSFManager getManager(); - - void execute(String script); - - Object evaluate(String script); - - default void close() { - - } -} diff --git a/core/src/main/java/com/volmit/iris/engine/scripting/IrisScriptingAPI.java b/core/src/main/java/com/volmit/iris/engine/scripting/IrisScriptingAPI.java deleted file mode 100644 index ae613c48f..000000000 --- a/core/src/main/java/com/volmit/iris/engine/scripting/IrisScriptingAPI.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2022 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.volmit.iris.engine.scripting; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.loader.IrisData; -import com.volmit.iris.core.loader.IrisRegistrant; -import com.volmit.iris.engine.IrisComplex; -import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.engine.object.IrisBiome; -import com.volmit.iris.engine.object.IrisDimension; -import com.volmit.iris.engine.object.IrisExpression; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.bukkit.Location; -import org.bukkit.entity.Entity; - -@Data -@EqualsAndHashCode(exclude = "engine") -@ToString(exclude = "engine") -public class IrisScriptingAPI { - private final Engine engine; - private IrisRegistrant preprocessorObject; - private double x = 0; - private double y = 0; - private double z = 0; - private Location location; - private Entity entity; - - public IrisScriptingAPI(Engine engine) { - this.engine = engine; - } - - public IrisData getData() { - return getEngine().getData(); - } - - public IrisComplex getComplex() { - return getEngine().getComplex(); - } - - public long getSeed() { - return getEngine().getSeedManager().getScript(); - } - - public double expression(String expressionName, double x, double y, double z) { - IrisExpression expression = getData().getExpressionLoader().load(expressionName); - return expression.evaluate(getComplex().getRng(), x, y, z); - } - - public double expression(String expressionName, double x, double z) { - IrisExpression expression = getData().getExpressionLoader().load(expressionName); - return expression.evaluate(getComplex().getRng(), x, z); - } - - public IrisBiome getBiomeAt(int x, int z) { - return getEngine().getSurfaceBiome(x, z); - } - - public IrisDimension getDimension() { - return getEngine().getDimension(); - } - - public void info(String log) { - Iris.info(log); - } - - public void debug(String log) { - Iris.debug(log); - } - - public void warn(String log) { - Iris.warn(log); - } - - public void error(String log) { - Iris.error(log); - } -} diff --git a/core/src/main/java/com/volmit/iris/util/io/IO.java b/core/src/main/java/com/volmit/iris/util/io/IO.java index a848d13a0..7506c5651 100644 --- a/core/src/main/java/com/volmit/iris/util/io/IO.java +++ b/core/src/main/java/com/volmit/iris/util/io/IO.java @@ -27,6 +27,12 @@ import com.volmit.iris.util.format.Form; import com.volmit.iris.util.scheduling.J; import org.apache.commons.io.function.IOConsumer; import org.apache.commons.io.function.IOFunction; +import lombok.SneakyThrows; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.SAXReader; +import org.dom4j.io.XMLWriter; import java.io.*; import java.nio.channels.Channels; @@ -1669,6 +1675,24 @@ public class IO { return (ch2 == -1); } + @SneakyThrows + public static void write(File file, Document doc) { + file.getParentFile().mkdirs(); + try (var writer = new FileWriter(file)) { + new XMLWriter(writer, OutputFormat.createPrettyPrint()) + .write(doc); + } + } + + @SneakyThrows + public static Document read(File file) { + if (file.exists()) return new SAXReader().read(file); + var doc = DocumentHelper.createDocument(); + doc.addElement("project") + .addAttribute("version", "4"); + return doc; + } + public static void write(File file, IOFunction builder, IOConsumer action) throws IOException { File dir = new File(file.getParentFile(), ".tmp"); dir.mkdirs(); diff --git a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java index a5e070b1d..f795d4f14 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -36,6 +36,7 @@ import com.volmit.iris.util.format.Form; import com.volmit.iris.util.function.Consumer4; import com.volmit.iris.util.io.IO; import com.volmit.iris.util.mantle.io.IOWorker; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.math.M; import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.MatterSlice; diff --git a/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java b/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java index f451acb18..01153403c 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java @@ -24,9 +24,11 @@ import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.ChunkRelativeBlockCoordinates; import com.volmit.iris.util.function.Consumer4; import com.volmit.iris.util.io.CountingDataInputStream; +import com.volmit.iris.util.mantle.flag.MantleFlag; import com.volmit.iris.util.matter.IrisMatter; import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.MatterSlice; +import com.volmit.iris.util.parallel.AtomicBooleanArray; import lombok.Getter; import lombok.SneakyThrows; import org.jetbrains.annotations.Nullable; @@ -36,7 +38,6 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicReferenceArray; /** @@ -48,7 +49,7 @@ public class MantleChunk { private final int x; @Getter private final int z; - private final AtomicIntegerArray flags; + private final AtomicBooleanArray flags; private final Object[] flagLocks; private final AtomicReferenceArray sections; private final Semaphore ref = new Semaphore(Integer.MAX_VALUE, true); @@ -62,13 +63,12 @@ public class MantleChunk { @ChunkCoordinates public MantleChunk(int sectionHeight, int x, int z) { sections = new AtomicReferenceArray<>(sectionHeight); - flags = new AtomicIntegerArray(MantleFlag.values().length); - flagLocks = new Object[MantleFlag.values().length]; + flags = new AtomicBooleanArray(MantleFlag.MAX_ORDINAL + 1); + flagLocks = new Object[flags.length()]; this.x = x; this.z = z; for (int i = 0; i < flags.length(); i++) { - flags.set(i, 0); flagLocks[i] = new Object(); } } @@ -84,10 +84,19 @@ public class MantleChunk { public MantleChunk(int version, int sectionHeight, CountingDataInputStream din) throws IOException { this(sectionHeight, din.readByte(), din.readByte()); int s = din.readByte(); - int l = version < 0 ? flags.length() : Varint.readUnsignedVarInt(din); + int l = version < 0 ? MantleFlag.RESERVED_FLAGS : Varint.readUnsignedVarInt(din); - for (int i = 0; i < flags.length() && i < l; i++) { - flags.set(i, din.readBoolean() ? 1 : 0); + if (version >= 1) { + for (int i = 0; i < l;) { + byte f = din.readByte(); + for (int j = 0; j < Byte.SIZE && i < flags.length(); j++, i++) { + flags.set(i, (f & (1 << j)) != 0); + } + } + } else { + for (int i = 0; i < flags.length() && i < l; i++) { + flags.set(i, din.readBoolean()); + } } for (int i = 0; i < s; i++) { @@ -145,9 +154,17 @@ public class MantleChunk { ref.release(); } + public void copyFlags(MantleChunk chunk) { + use(); + for (int i = 0; i < flags.length(); i++) { + flags.set(i, chunk.flags.get(i)); + } + release(); + } + public void flag(MantleFlag flag, boolean f) { if (closed.get()) throw new IllegalStateException("Chunk is closed!"); - flags.set(flag.ordinal(), f ? 1 : 0); + flags.set(flag.ordinal(), f); } public void raiseFlag(MantleFlag flag, Runnable r) { @@ -158,14 +175,14 @@ public class MantleChunk { if (closed.get()) throw new IllegalStateException("Chunk is closed!"); if (guard != null && isFlagged(guard)) return; synchronized (flagLocks[flag.ordinal()]) { - if (flags.getAndSet(flag.ordinal(), 1) == 0) { + if (flags.compareAndSet(flag.ordinal(), false, true)) { r.run(); } } } public boolean isFlagged(MantleFlag flag) { - return flags.get(flag.ordinal()) == 1; + return flags.get(flag.ordinal()); } /** @@ -249,10 +266,15 @@ public class MantleChunk { dos.writeByte(x); dos.writeByte(z); dos.writeByte(sections.length()); - Varint.writeUnsignedVarInt(flags.length(), dos); + Varint.writeUnsignedVarInt(Math.ceilDiv(flags.length(), Byte.SIZE), dos); - for (int i = 0; i < flags.length(); i++) { - dos.writeBoolean(flags.get(i) == 1); + int count = flags.length(); + for (int i = 0; i < count;) { + int f = 0; + for (int j = 0; j < Byte.SIZE && i < flags.length(); j++, i++) { + f |= flags.get(i) ? (1 << j) : 0; + } + dos.write(f); } var bytes = new ByteArrayOutputStream(8192); diff --git a/core/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java b/core/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java deleted file mode 100644 index 81c4a8504..000000000 --- a/core/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2022 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.volmit.iris.util.mantle; - -import com.volmit.iris.util.collection.StateList; - -public enum MantleFlag { - OBJECT, - UPDATE, - JIGSAW, - FEATURE, - INITIAL_SPAWNED, - REAL, - CARVED, - FLUID_BODIES, - INITIAL_SPAWNED_MARKER, - CLEANED, - PLANNED, - ETCHED, - TILE, - CUSTOM, - DISCOVERED, - CUSTOM_ACTIVE; - - static StateList getStateList() { - return new StateList(MantleFlag.values()); - } -} diff --git a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java index a10bfbc26..1b9ea817e 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java @@ -37,7 +37,7 @@ import java.util.concurrent.atomic.AtomicReferenceArray; public class TectonicPlate { private static final ThreadLocal errors = ThreadLocal.withInitial(() -> false); public static final int MISSING = -1; - public static final int CURRENT = 0; + public static final int CURRENT = 1; private final int sectionHeight; private final AtomicReferenceArray chunks; diff --git a/core/src/main/java/com/volmit/iris/util/mantle/flag/CustomFlag.java b/core/src/main/java/com/volmit/iris/util/mantle/flag/CustomFlag.java new file mode 100644 index 000000000..5b239e1a1 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/mantle/flag/CustomFlag.java @@ -0,0 +1,28 @@ +package com.volmit.iris.util.mantle.flag; + +import org.jetbrains.annotations.NotNull; + +record CustomFlag(String name, int ordinal) implements MantleFlag { + + @Override + public @NotNull String toString() { + return name; + } + + @Override + public boolean isCustom() { + return false; + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof CustomFlag that)) + return false; + return ordinal == that.ordinal; + } + + @Override + public int hashCode() { + return ordinal; + } +} diff --git a/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlag.java b/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlag.java new file mode 100644 index 000000000..965bf6780 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlag.java @@ -0,0 +1,57 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.mantle.flag; + +import org.jetbrains.annotations.Contract; + +public sealed interface MantleFlag permits CustomFlag, ReservedFlag { + int MIN_ORDINAL = 64; + int MAX_ORDINAL = 255; + + MantleFlag OBJECT = ReservedFlag.OBJECT; + MantleFlag UPDATE = ReservedFlag.UPDATE; + MantleFlag JIGSAW = ReservedFlag.JIGSAW; + MantleFlag FEATURE = ReservedFlag.FEATURE; + MantleFlag INITIAL_SPAWNED = ReservedFlag.INITIAL_SPAWNED; + MantleFlag REAL = ReservedFlag.REAL; + MantleFlag CARVED = ReservedFlag.CARVED; + MantleFlag FLUID_BODIES = ReservedFlag.FLUID_BODIES; + MantleFlag INITIAL_SPAWNED_MARKER = ReservedFlag.INITIAL_SPAWNED_MARKER; + MantleFlag CLEANED = ReservedFlag.CLEANED; + MantleFlag PLANNED = ReservedFlag.PLANNED; + MantleFlag ETCHED = ReservedFlag.ETCHED; + MantleFlag TILE = ReservedFlag.TILE; + MantleFlag CUSTOM = ReservedFlag.CUSTOM; + MantleFlag DISCOVERED = ReservedFlag.DISCOVERED; + MantleFlag CUSTOM_ACTIVE = ReservedFlag.CUSTOM_ACTIVE; + + int RESERVED_FLAGS = ReservedFlag.values().length; + + String name(); + int ordinal(); + + boolean isCustom(); + + @Contract(value = "_ -> new", pure = true) + static MantleFlag of(int ordinal) { + if (ordinal < MIN_ORDINAL || ordinal > MAX_ORDINAL) + throw new IllegalArgumentException("Ordinal must be between " + MIN_ORDINAL + " and " + MAX_ORDINAL); + return new CustomFlag("CUSTOM:"+ordinal, ordinal); + } +} diff --git a/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlagAdapter.java b/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlagAdapter.java new file mode 100644 index 000000000..c56916df8 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/mantle/flag/MantleFlagAdapter.java @@ -0,0 +1,31 @@ +package com.volmit.iris.util.mantle.flag; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; + +public class MantleFlagAdapter extends TypeAdapter { + private static final String CUSTOM = "CUSTOM:"; + private static final int CUSTOM_LENGTH = CUSTOM.length(); + + @Override + public void write(JsonWriter out, MantleFlag value) throws IOException { + if (value == null) out.nullValue(); + else out.value(value.toString()); + } + + @Override + public MantleFlag read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + String s = in.nextString(); + if (s.startsWith(CUSTOM) && s.length() > CUSTOM_LENGTH) + return MantleFlag.of(Integer.parseInt(s.substring(CUSTOM_LENGTH))); + return ReservedFlag.valueOf(s); + } +} diff --git a/core/src/main/java/com/volmit/iris/util/mantle/flag/ReservedFlag.java b/core/src/main/java/com/volmit/iris/util/mantle/flag/ReservedFlag.java new file mode 100644 index 000000000..c6ea07b64 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/mantle/flag/ReservedFlag.java @@ -0,0 +1,25 @@ +package com.volmit.iris.util.mantle.flag; + +public enum ReservedFlag implements MantleFlag { + OBJECT, + UPDATE, + JIGSAW, + FEATURE, + INITIAL_SPAWNED, + REAL, + CARVED, + FLUID_BODIES, + INITIAL_SPAWNED_MARKER, + CLEANED, + PLANNED, + ETCHED, + TILE, + CUSTOM, + DISCOVERED, + CUSTOM_ACTIVE; + + @Override + public boolean isCustom() { + return false; + } +} diff --git a/core/src/main/java/com/volmit/iris/util/parallel/AtomicBooleanArray.java b/core/src/main/java/com/volmit/iris/util/parallel/AtomicBooleanArray.java new file mode 100644 index 000000000..5d2603a85 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/parallel/AtomicBooleanArray.java @@ -0,0 +1,46 @@ +package com.volmit.iris.util.parallel; + +import java.io.Serializable; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; + +public class AtomicBooleanArray implements Serializable { + private static final VarHandle AA = MethodHandles.arrayElementVarHandle(boolean[].class); + private final boolean[] array; + + public AtomicBooleanArray(int length) { + array = new boolean[length]; + } + + public final int length() { + return array.length; + } + + public final boolean get(int index) { + return (boolean) AA.getVolatile(array, index); + } + + public final void set(int index, boolean newValue) { + AA.setVolatile(array, index, newValue); + } + + public final boolean compareAndSet(int index, boolean expectedValue, boolean newValue) { + return (boolean) AA.compareAndSet(array, index, expectedValue, newValue); + } + + @Override + public String toString() { + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(get(i)); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } + } +} diff --git a/core/src/main/java/com/volmit/iris/util/parallel/MultiBurst.java b/core/src/main/java/com/volmit/iris/util/parallel/MultiBurst.java index 3762d9ecd..32ab14103 100644 --- a/core/src/main/java/com/volmit/iris/util/parallel/MultiBurst.java +++ b/core/src/main/java/com/volmit/iris/util/parallel/MultiBurst.java @@ -42,7 +42,11 @@ public class MultiBurst implements ExecutorService { private ExecutorService service; public MultiBurst() { - this("Iris", Thread.MIN_PRIORITY, () -> IrisSettings.get().getConcurrency().getParallelism()); + this("Iris"); + } + + public MultiBurst(String name) { + this(name, Thread.MIN_PRIORITY, () -> IrisSettings.get().getConcurrency().getParallelism()); } public MultiBurst(String name, IntSupplier parallelism) { diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/DataScript.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/DataScript.kt new file mode 100644 index 000000000..1a180701c --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/DataScript.kt @@ -0,0 +1,15 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import com.volmit.iris.core.loader.IrisData +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.providedProperties + +@KotlinScript(fileExtension = "data.kts", compilationConfiguration = DataScriptDefinition::class) +abstract class DataScript + +object DataScriptDefinition : ScriptCompilationConfiguration(listOf(SimpleScriptDefinition), { + providedProperties("data" to IrisData::class) +}) { + private fun readResolve(): Any = DataScriptDefinition +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/EngineScript.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/EngineScript.kt new file mode 100644 index 000000000..768f2a9d3 --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/EngineScript.kt @@ -0,0 +1,25 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import com.volmit.iris.core.scripting.func.BiomeLookup +import com.volmit.iris.engine.IrisComplex +import com.volmit.iris.engine.framework.Engine +import com.volmit.iris.engine.`object`.IrisDimension +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.providedProperties + +@KotlinScript(fileExtension = "engine.kts", compilationConfiguration = EngineScriptDefinition::class) +abstract class EngineScript + +object EngineScriptDefinition : ScriptCompilationConfiguration(listOf(DataScriptDefinition), { + providedProperties( + "engine" to Engine::class, + "complex" to IrisComplex::class, + "seed" to Long::class, + "dimension" to IrisDimension::class, + "biome" to BiomeLookup::class, + ) +}) { + + private fun readResolve(): Any = EngineScriptDefinition +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/MobSpawningScript.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/MobSpawningScript.kt new file mode 100644 index 000000000..f9add58dc --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/MobSpawningScript.kt @@ -0,0 +1,15 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import org.bukkit.Location +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.providedProperties + +@KotlinScript(fileExtension = "spawn.kts", compilationConfiguration = MobSpawningScriptDefinition::class) +abstract class MobSpawningScript + +object MobSpawningScriptDefinition : ScriptCompilationConfiguration(listOf(EngineScriptDefinition), { + providedProperties("location" to Location::class) +}) { + private fun readResolve(): Any = MobSpawningScriptDefinition +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/NoiseScript.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/NoiseScript.kt new file mode 100644 index 000000000..c8a7056fa --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/NoiseScript.kt @@ -0,0 +1,16 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import com.volmit.iris.util.math.RNG +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.providedProperties + +@KotlinScript(fileExtension = "noise.kts", compilationConfiguration = NoiseScriptDefinition::class) +abstract class NoiseScript + +object NoiseScriptDefinition : ScriptCompilationConfiguration(listOf(DataScriptDefinition), { + providedProperties("rng" to RNG::class) +}) { + + private fun readResolve(): Any = NoiseScriptDefinition +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PostMobSpawningScript.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PostMobSpawningScript.kt new file mode 100644 index 000000000..02b485bed --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PostMobSpawningScript.kt @@ -0,0 +1,15 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import org.bukkit.entity.Entity +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.providedProperties + +@KotlinScript(fileExtension = "postspawn.kts", compilationConfiguration = PostMobSpawningScriptDefinition::class) +abstract class PostMobSpawningScript + +object PostMobSpawningScriptDefinition : ScriptCompilationConfiguration(listOf(MobSpawningScriptDefinition), { + providedProperties("entity" to Entity::class) +}) { + private fun readResolve(): Any = PostMobSpawningScriptDefinition +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PreprocessorScript.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PreprocessorScript.kt new file mode 100644 index 000000000..f594649e1 --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PreprocessorScript.kt @@ -0,0 +1,15 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import com.volmit.iris.core.loader.IrisRegistrant +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.providedProperties + +@KotlinScript(fileExtension = "proc.kts", compilationConfiguration = PreprocessorScriptDefinition::class) +abstract class PreprocessorScript + +object PreprocessorScriptDefinition : ScriptCompilationConfiguration(listOf(EngineScriptDefinition), { + providedProperties("object" to IrisRegistrant::class) +}) { + private fun readResolve(): Any = PreprocessorScriptDefinition +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/SimpleScript.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/SimpleScript.kt new file mode 100644 index 000000000..d97732c31 --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/SimpleScript.kt @@ -0,0 +1,36 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import com.volmit.iris.core.scripting.kotlin.runner.configureMavenDepsOnAnnotations +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.defaultImports +import kotlin.script.experimental.api.refineConfiguration +import kotlin.script.experimental.dependencies.DependsOn +import kotlin.script.experimental.dependencies.Repository +import kotlin.script.experimental.jvm.dependenciesFromClassContext +import kotlin.script.experimental.jvm.jvm + +@KotlinScript(fileExtension = "simple.kts", compilationConfiguration = SimpleScriptDefinition::class) +abstract class SimpleScript + +object SimpleScriptDefinition : ScriptCompilationConfiguration({ + defaultImports( + DependsOn::class.qualifiedName!!, + Repository::class.qualifiedName!!, + "com.volmit.iris.Iris.info", + "com.volmit.iris.Iris.debug", + "com.volmit.iris.Iris.warn", + "com.volmit.iris.Iris.error" + ) + + jvm { + dependenciesFromClassContext(KotlinScript::class, wholeClasspath = true) + dependenciesFromClassContext(SimpleScript::class, wholeClasspath = true) + } + + refineConfiguration { + onAnnotations(DependsOn::class, Repository::class, handler = ::configureMavenDepsOnAnnotations) + } +}) { + private fun readResolve(): Any = SimpleScriptDefinition +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisExecutionEnvironment.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisExecutionEnvironment.kt new file mode 100644 index 000000000..edaba44e5 --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisExecutionEnvironment.kt @@ -0,0 +1,45 @@ +package com.volmit.iris.core.scripting.kotlin.environment + +import com.volmit.iris.core.loader.IrisRegistrant +import com.volmit.iris.core.scripting.environment.EngineEnvironment +import com.volmit.iris.core.scripting.func.BiomeLookup +import com.volmit.iris.core.scripting.kotlin.base.EngineScript +import com.volmit.iris.core.scripting.kotlin.base.MobSpawningScript +import com.volmit.iris.core.scripting.kotlin.base.PostMobSpawningScript +import com.volmit.iris.core.scripting.kotlin.base.PreprocessorScript +import com.volmit.iris.engine.framework.Engine +import org.bukkit.Location +import org.bukkit.entity.Entity + +data class IrisExecutionEnvironment( + private val engine: Engine +) : IrisPackExecutionEnvironment(engine.data), EngineEnvironment { + override fun getEngine() = engine + + override fun execute(script: String) = + execute(script, EngineScript::class.java, engine.parameters()) + + override fun evaluate(script: String) = + evaluate(script, EngineScript::class.java, engine.parameters()) + + override fun spawnMob(script: String, location: Location) = + evaluate(script, MobSpawningScript::class.java, engine.parameters("location" to location)) + + override fun postSpawnMob(script: String, location: Location, mob: Entity) = + execute(script, PostMobSpawningScript::class.java, engine.parameters("location" to location, "entity" to mob)) + + override fun preprocessObject(script: String, `object`: IrisRegistrant) = + execute(script, PreprocessorScript::class.java, engine.parameters("object" to `object`)) + + private fun Engine.parameters(vararg values: Pair): Map { + return mapOf( + "data" to data, + "engine" to this, + "complex" to complex, + "seed" to seedManager.seed, + "dimension" to dimension, + "biome" to BiomeLookup(::getSurfaceBiome), + *values, + ) + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisPackExecutionEnvironment.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisPackExecutionEnvironment.kt new file mode 100644 index 000000000..86832c963 --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisPackExecutionEnvironment.kt @@ -0,0 +1,40 @@ +package com.volmit.iris.core.scripting.kotlin.environment + +import com.volmit.iris.core.loader.IrisData +import com.volmit.iris.core.scripting.environment.PackEnvironment +import com.volmit.iris.core.scripting.kotlin.base.DataScript +import com.volmit.iris.core.scripting.kotlin.base.NoiseScript +import com.volmit.iris.core.scripting.kotlin.runner.Script +import com.volmit.iris.core.scripting.kotlin.runner.valueOrThrow +import com.volmit.iris.util.math.RNG +import kotlin.reflect.KClass + +open class IrisPackExecutionEnvironment( + private val data: IrisData +) : IrisSimpleExecutionEnvironment(data.dataFolder), PackEnvironment { + + override fun getData() = data + + override fun compile(script: String, type: KClass<*>): Script { + val loaded = data.scriptLoader.load(script) + return compileCache.get(script) + .computeIfAbsent(type) { _ -> runner.compile(type, loaded.loadFile, loaded.source) } + .valueOrThrow("Failed to compile script $script") + } + + override fun execute(script: String) = + execute(script, DataScript::class.java, data.parameters()) + + override fun evaluate(script: String) = + evaluate(script, DataScript::class.java, data.parameters()) + + override fun createNoise(script: String, rng: RNG) = + evaluate(script, NoiseScript::class.java, data.parameters("rng" to rng)) + + private fun IrisData.parameters(vararg values: Pair): Map { + return mapOf( + "data" to this, + *values, + ) + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisSimpleExecutionEnvironment.kt b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisSimpleExecutionEnvironment.kt new file mode 100644 index 000000000..bcc955954 --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisSimpleExecutionEnvironment.kt @@ -0,0 +1,136 @@ +package com.volmit.iris.core.scripting.kotlin.environment + +import com.volmit.iris.Iris +import com.volmit.iris.core.IrisSettings +import com.volmit.iris.core.scripting.environment.SimpleEnvironment +import com.volmit.iris.core.scripting.kotlin.base.* +import com.volmit.iris.core.scripting.kotlin.runner.Script +import com.volmit.iris.core.scripting.kotlin.runner.ScriptRunner +import com.volmit.iris.core.scripting.kotlin.runner.classpath +import com.volmit.iris.core.scripting.kotlin.runner.valueOrNull +import com.volmit.iris.core.scripting.kotlin.runner.valueOrThrow +import com.volmit.iris.util.collection.KMap +import com.volmit.iris.util.data.KCache +import com.volmit.iris.util.format.C +import java.io.File +import kotlin.reflect.KClass +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ResultWithDiagnostics +import kotlin.text.split + +open class IrisSimpleExecutionEnvironment( + baseDir: File = File(".").absoluteFile +) : SimpleEnvironment { + protected val compileCache = KCache, ResultWithDiagnostics