From c597c55c2cc90dfb6d713a584a1b76e8b070ee07 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Wed, 23 Apr 2025 14:21:09 +0200 Subject: [PATCH 01/31] replace rhino scripting engine with kotlin scripting --- build.gradle | 2 - core/src/main/java/com/volmit/iris/Iris.java | 2 + .../com/volmit/iris/core/loader/IrisData.java | 4 +- .../core/loader/ScriptResourceLoader.java | 12 +- .../volmit/iris/core/project/IrisProject.java | 2 + .../core/scripting/ExecutionEnvironment.java | 160 ++++++++++++++++++ .../iris/core/scripting/func/BiomeLookup.java | 10 ++ .../com/volmit/iris/engine/IrisEngine.java | 6 +- .../iris/engine/IrisExecutionEnvironment.java | 84 --------- .../volmit/iris/engine/framework/Engine.java | 4 +- .../volmit/iris/engine/object/IrisEntity.java | 8 +- .../scripting/EngineExecutionEnvironment.java | 38 ----- .../engine/scripting/IrisScriptingAPI.java | 96 ----------- core/src/main/resources/plugin.yml | 2 - 14 files changed, 188 insertions(+), 242 deletions(-) create mode 100644 core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java create mode 100644 core/src/main/java/com/volmit/iris/core/scripting/func/BiomeLookup.java delete mode 100644 core/src/main/java/com/volmit/iris/engine/IrisExecutionEnvironment.java delete mode 100644 core/src/main/java/com/volmit/iris/engine/scripting/EngineExecutionEnvironment.java delete mode 100644 core/src/main/java/com/volmit/iris/engine/scripting/IrisScriptingAPI.java diff --git a/build.gradle b/build.gradle index ebe09d7d8..12a0751b8 100644 --- a/build.gradle +++ b/build.gradle @@ -168,8 +168,6 @@ allprojects { compileOnly 'com.google.code.gson:gson:2.10.1' compileOnly 'org.ow2.asm:asm:9.2' compileOnly 'com.google.guava:guava:33.0.0-jre' - compileOnly 'bsf:bsf:2.4.0' - compileOnly 'rhino:js:1.7R2' compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6' compileOnly 'org.apache.commons:commons-lang3:3.12.0' compileOnly 'com.github.oshi:oshi-core:6.6.5' diff --git a/core/src/main/java/com/volmit/iris/Iris.java b/core/src/main/java/com/volmit/iris/Iris.java index 64fa8d4d3..0801c7a36 100644 --- a/core/src/main/java/com/volmit/iris/Iris.java +++ b/core/src/main/java/com/volmit/iris/Iris.java @@ -30,6 +30,7 @@ import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.nms.INMS; import com.volmit.iris.core.nms.v1X.NMSBinding1X; import com.volmit.iris.core.pregenerator.LazyPregenerator; +import com.volmit.iris.core.scripting.ExecutionEnvironment; import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisWorldCreator; @@ -462,6 +463,7 @@ public class Iris extends VolmitPlugin implements Listener { compat = IrisCompat.configured(getDataFile("compat.json")); ServerConfigurator.configure(); new IrisContextInjector(); + ExecutionEnvironment.createSimple(); IrisSafeguard.IrisSafeguardSystem(); getSender().setTag(getTag()); IrisSafeguard.earlySplash(); 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 e51c93176..4215c9c30 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 @@ -252,10 +252,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { if (engine != null && t.getPreprocessors().isNotEmpty()) { synchronized (this) { - engine.getExecution().getAPI().setPreprocessorObject(t); - for (String i : t.getPreprocessors()) { - engine.getExecution().execute(i); + 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); } } 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/project/IrisProject.java b/core/src/main/java/com/volmit/iris/core/project/IrisProject.java index d094c82ff..aa4ed4900 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.ExecutionEnvironment; import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.object.annotations.Snippet; @@ -274,6 +275,7 @@ public class IrisProject { PrecisionStopwatch p = PrecisionStopwatch.start(); JSONObject j = createCodeWorkspaceConfig(); IO.writeAll(ws, j.toString(4)); + ExecutionEnvironment.createPack(IrisData.get(path)).buildProject(); p.end(); return true; } catch (Throwable e) { diff --git a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java new file mode 100644 index 000000000..8389c8598 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -0,0 +1,160 @@ +package com.volmit.iris.core.scripting; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.core.loader.IrisRegistrant; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.io.IO; +import lombok.NonNull; +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.*; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; + +@UtilityClass +public class ExecutionEnvironment { + private static final String BASE_URL = "https://jitpack.io/com/github/VolmitSoftware/Iris-Scripts/%s/Iris-Scripts-%s-all.jar"; + private static final Provider PROVIDER = ServiceLoader.load(Provider.class, buildLoader()) + .findFirst() + .orElseThrow(); + + @NonNull + public static Engine createEngine(@NonNull com.volmit.iris.engine.framework.Engine engine) { + return PROVIDER.createEngine(engine); + } + + @NonNull + public static Pack createPack(@NonNull IrisData data) { + return PROVIDER.createPack(data); + } + + @NonNull + public static Simple createSimple() { + return PROVIDER.createSimple(); + } + + @SneakyThrows + private static URLClassLoader buildLoader() { + String version = "ac94c94427"; + String url = BASE_URL.formatted(version, version); + String hash = IO.hash("Iris-Scripts.jar@" + version); + var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash); + var libsDir = new File(file.getParentFile(), "libs"); + + KList libs = null; + if (!file.exists()) { + libsDir.mkdirs(); + + Iris.info("Downloading Script Engine..."); + var tempFile = Iris.getNonCachedFile(UUID.randomUUID().toString(), url); + try (var jar = new JarFile(tempFile); var out = new JarOutputStream(new FileOutputStream(file)) ) { + libs = getLibraries(jar); + for (var it = jar.entries().asIterator(); it.hasNext(); ) { + var entry = it.next(); + if (entry.isDirectory()) { + out.putNextEntry(entry); + out.closeEntry(); + continue; + } + + try (var in = jar.getInputStream(entry)) { + if (libs.contains(entry.getName())) { + var target = new File(libsDir, entry.getName()); + target.getParentFile().mkdirs(); + Files.copy(in, target.toPath()); + continue; + } + out.putNextEntry(entry); + IO.copy(in, out); + out.closeEntry(); + } + } + } + IO.deleteUp(tempFile); + Iris.info("Downloaded Script Engine!"); + } + + if (libs == null) { + try (var jar = new JarFile(file)) { + libs = getLibraries(jar); + } + } + var urls = new URL[libs.size() + 1]; + urls[0] = file.toURI().toURL(); + for (int i = 0; i < libs.size(); i++) { + File lib = new File(libsDir, libs.get(i)); + if (!lib.exists()) { + Iris.warn("Missing library: " + lib.getAbsolutePath()); + continue; + } + + urls[i + 1] = lib.toURI().toURL(); + } + return new URLClassLoader(urls, Provider.class.getClassLoader()); + } + + private static KList getLibraries(JarFile jar) throws IOException { + return new KList<>(jar.getManifest() + .getMainAttributes() + .getValue("Libraries") + .split(";")); + } + + public interface Provider { + @NonNull + Engine createEngine(@NonNull com.volmit.iris.engine.framework.Engine engine); + + @NonNull + Pack createPack(@NonNull IrisData data); + + @NonNull + Simple createSimple(); + } + + + public interface Simple { + 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() { + + } + } + + public interface Pack extends Simple { + @NonNull + IrisData getData(); + + void buildProject(); + } + + public interface Engine extends Pack { + @NonNull + com.volmit.iris.engine.framework.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); + } +} 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 88c5fdc14..fc6d657c3 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.ExecutionEnvironment; 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; @@ -93,7 +93,7 @@ public class IrisEngine implements Engine { private CompletableFuture hash32; private EngineMode mode; private EngineEffects effects; - private EngineExecutionEnvironment execution; + private ExecutionEnvironment.Engine execution; private EngineWorldManager worldManager; private volatile int parallelism; private volatile int minHeight; @@ -171,7 +171,7 @@ public class IrisEngine implements Engine { cacheId = RNG.r.nextInt(); worldManager = new IrisWorldManager(this); complex = new IrisComplex(this); - execution = new IrisExecutionEnvironment(this); + execution = ExecutionEnvironment.createEngine(this); effects = new IrisEngineEffects(this); hash32 = new CompletableFuture<>(); setupMode(); 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/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index fe99a322d..e150636a3 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.ExecutionEnvironment; 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; @@ -111,7 +111,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat IrisContext getContext(); - EngineExecutionEnvironment getExecution(); + ExecutionEnvironment.Engine getExecution(); double getMaxBiomeObjectDensity(); 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 dfb2508d0..206291892 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 @@ -211,9 +211,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(); @@ -353,11 +352,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/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/resources/plugin.yml b/core/src/main/resources/plugin.yml index 7ff73ff7e..cedb75c1e 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -16,8 +16,6 @@ libraries: - org.zeroturnaround:zt-zip:1.14 - it.unimi.dsi:fastutil:8.5.6 - org.ow2.asm:asm:9.2 - - rhino:js:1.7R2 - - bsf:bsf:2.4.0 - org.lz4:lz4-java:1.8.0 - com.github.oshi:oshi-core:6.6.5 commands: From 0a2f35dd8d31968d78c8d51535892380dc40072a Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Wed, 23 Apr 2025 21:24:14 +0200 Subject: [PATCH 02/31] update the scripting engine and fix cached file extension --- .../com/volmit/iris/core/scripting/ExecutionEnvironment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index 8389c8598..c01655449 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -46,10 +46,10 @@ public class ExecutionEnvironment { @SneakyThrows private static URLClassLoader buildLoader() { - String version = "ac94c94427"; + String version = "46d271c6ce"; String url = BASE_URL.formatted(version, version); String hash = IO.hash("Iris-Scripts.jar@" + version); - var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash); + var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); var libsDir = new File(file.getParentFile(), "libs"); KList libs = null; From e72abc8c394a383ac8df8d339655ca512d82c32e Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Thu, 24 Apr 2025 16:00:23 +0200 Subject: [PATCH 03/31] generate json schemas for intelij --- build.gradle | 1 + .../volmit/iris/core/project/IrisProject.java | 70 ++++++++++++++++++- .../iris/core/project/SchemaBuilder.java | 49 ++++++++----- .../core/scripting/ExecutionEnvironment.java | 15 +++- .../main/java/com/volmit/iris/util/io/IO.java | 24 +++++++ core/src/main/resources/plugin.yml | 2 + 6 files changed, 139 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index 12a0751b8..02c63f997 100644 --- a/build.gradle +++ b/build.gradle @@ -171,6 +171,7 @@ allprojects { compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6' compileOnly 'org.apache.commons:commons-lang3:3.12.0' compileOnly 'com.github.oshi:oshi-core:6.6.5' + compileOnly 'org.dom4j:dom4j:2.1.4' } /** 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 aa4ed4900..803057318 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 @@ -50,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.*; @@ -275,7 +277,6 @@ public class IrisProject { PrecisionStopwatch p = PrecisionStopwatch.start(); JSONObject j = createCodeWorkspaceConfig(); IO.writeAll(ws, j.toString(4)); - ExecutionEnvironment.createPack(IrisData.get(path)).buildProject(); p.end(); return true; } catch (Throwable e) { @@ -361,6 +362,73 @@ public class IrisProject { settings.put("json.schemas", schemas); ws.put("settings", settings); + ExecutionEnvironment.createSimple().configureProject(path); + 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); + } + 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 398d1630b..6f69bf223 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 @@ -108,7 +108,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(); @@ -506,16 +508,18 @@ 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); if (k.getType().isAnnotationPresent(Snippet.class)) { String sm = k.getType().getDeclaredAnnotation(Snippet.class).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 { @@ -523,15 +527,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()) && !OldEnum.isOldEnum(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) { @@ -539,8 +541,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); if (k.getType().isAnnotationPresent(Snippet.class)) { JSONObject anyOf = new JSONObject(); @@ -560,10 +568,13 @@ public class SchemaBuilder { arr.put(prop); arr.put(str); - prop.put("description", d.toString("\n")); - str.put("description", d.toString("\n")); + prop.put("description", desc); + prop.put("x-intellij-html-description", hDesc); + str.put("description", desc); + str.put("x-intellij-html-description", hDesc); anyOf.put("anyOf", arr); - anyOf.put("description", d.toString("\n")); + anyOf.put("description", desc); + anyOf.put("x-intellij-html-description", hDesc); anyOf.put("!required", k.isAnnotationPresent(Required.class)); return anyOf; @@ -592,7 +603,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/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index c01655449..21ee80219 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -10,6 +10,7 @@ import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import org.bukkit.Location; import org.bukkit.entity.Entity; +import org.dom4j.Document; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -46,7 +47,7 @@ public class ExecutionEnvironment { @SneakyThrows private static URLClassLoader buildLoader() { - String version = "46d271c6ce"; + String version = "868b3b9910"; String url = BASE_URL.formatted(version, version); String hash = IO.hash("Iris-Scripts.jar@" + version); var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); @@ -124,6 +125,16 @@ public class ExecutionEnvironment { public interface Simple { + default void configureProject(@NonNull File projectDir) { + var workspaceFile = new File(projectDir, ".idea" + File.separator + "workspace.xml"); + var workspaceDoc = IO.read(workspaceFile); + if (configureProject(projectDir, workspaceDoc)) { + IO.write(workspaceFile, workspaceDoc); + } + } + + boolean configureProject(@NonNull File projectDir, @NonNull Document workspace); + void execute(@NonNull String script); void execute(@NonNull String script, @NonNull Class type, @Nullable Map<@NonNull String, Object> vars); @@ -142,8 +153,6 @@ public class ExecutionEnvironment { public interface Pack extends Simple { @NonNull IrisData getData(); - - void buildProject(); } public interface Engine extends Pack { 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 a8f718885..f18b157fd 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 @@ -20,6 +20,12 @@ package com.volmit.iris.util.io; import com.volmit.iris.Iris; import com.volmit.iris.util.format.Form; +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.charset.StandardCharsets; @@ -1602,4 +1608,22 @@ public class IO { int ch2 = input2.read(); 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; + } } diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index cedb75c1e..f3b1cfa8c 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -18,6 +18,8 @@ libraries: - org.ow2.asm:asm:9.2 - org.lz4:lz4-java:1.8.0 - com.github.oshi:oshi-core:6.6.5 + - org.dom4j:dom4j:2.1.4 + - jaxen:jaxen:1.1.6 commands: iris: aliases: [ ir, irs ] From 8eb35aa8be13974f5abe3968e47e359bf7c14295 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Mon, 28 Apr 2025 21:24:54 +0200 Subject: [PATCH 04/31] update Script Engine to b5e2cc6e --- .../core/scripting/ExecutionEnvironment.java | 76 ++----------------- 1 file changed, 6 insertions(+), 70 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index 21ee80219..fe96cd995 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -3,25 +3,20 @@ package com.volmit.iris.core.scripting; import com.volmit.iris.Iris; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisRegistrant; -import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.io.IO; import lombok.NonNull; import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import org.bukkit.Location; import org.bukkit.entity.Entity; -import org.dom4j.Document; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; +import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; import java.util.*; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; @UtilityClass public class ExecutionEnvironment { @@ -47,69 +42,18 @@ public class ExecutionEnvironment { @SneakyThrows private static URLClassLoader buildLoader() { - String version = "868b3b9910"; + String version = "b5e2cc6e"; String url = BASE_URL.formatted(version, version); String hash = IO.hash("Iris-Scripts.jar@" + version); var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); - var libsDir = new File(file.getParentFile(), "libs"); - - KList libs = null; if (!file.exists()) { - libsDir.mkdirs(); - Iris.info("Downloading Script Engine..."); - var tempFile = Iris.getNonCachedFile(UUID.randomUUID().toString(), url); - try (var jar = new JarFile(tempFile); var out = new JarOutputStream(new FileOutputStream(file)) ) { - libs = getLibraries(jar); - for (var it = jar.entries().asIterator(); it.hasNext(); ) { - var entry = it.next(); - if (entry.isDirectory()) { - out.putNextEntry(entry); - out.closeEntry(); - continue; - } - - try (var in = jar.getInputStream(entry)) { - if (libs.contains(entry.getName())) { - var target = new File(libsDir, entry.getName()); - target.getParentFile().mkdirs(); - Files.copy(in, target.toPath()); - continue; - } - out.putNextEntry(entry); - IO.copy(in, out); - out.closeEntry(); - } - } + try (var stream = URI.create(url).toURL().openStream()) { + Files.copy(stream, file.toPath()); } - IO.deleteUp(tempFile); Iris.info("Downloaded Script Engine!"); } - - if (libs == null) { - try (var jar = new JarFile(file)) { - libs = getLibraries(jar); - } - } - var urls = new URL[libs.size() + 1]; - urls[0] = file.toURI().toURL(); - for (int i = 0; i < libs.size(); i++) { - File lib = new File(libsDir, libs.get(i)); - if (!lib.exists()) { - Iris.warn("Missing library: " + lib.getAbsolutePath()); - continue; - } - - urls[i + 1] = lib.toURI().toURL(); - } - return new URLClassLoader(urls, Provider.class.getClassLoader()); - } - - private static KList getLibraries(JarFile jar) throws IOException { - return new KList<>(jar.getManifest() - .getMainAttributes() - .getValue("Libraries") - .split(";")); + return new URLClassLoader(new URL[]{file.toURI().toURL()}, Provider.class.getClassLoader()); } public interface Provider { @@ -125,15 +69,7 @@ public class ExecutionEnvironment { public interface Simple { - default void configureProject(@NonNull File projectDir) { - var workspaceFile = new File(projectDir, ".idea" + File.separator + "workspace.xml"); - var workspaceDoc = IO.read(workspaceFile); - if (configureProject(projectDir, workspaceDoc)) { - IO.write(workspaceFile, workspaceDoc); - } - } - - boolean configureProject(@NonNull File projectDir, @NonNull Document workspace); + void configureProject(@NonNull File projectDir); void execute(@NonNull String script); From 5958bcb22e47f022878fe8fa34051e776341da22 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Mon, 28 Apr 2025 21:40:44 +0200 Subject: [PATCH 05/31] update Script Engine to 41396a77d5 --- .../com/volmit/iris/core/scripting/ExecutionEnvironment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index fe96cd995..5b9dd6022 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -42,7 +42,7 @@ public class ExecutionEnvironment { @SneakyThrows private static URLClassLoader buildLoader() { - String version = "b5e2cc6e"; + String version = "41396a77d5"; String url = BASE_URL.formatted(version, version); String hash = IO.hash("Iris-Scripts.jar@" + version); var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); From b6f9f68b9ffa22dc44c096e0b5a16cc6604b72cc Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Mon, 16 Jun 2025 22:43:26 +0200 Subject: [PATCH 06/31] add global preprocessor setting --- .../com/volmit/iris/core/loader/IrisData.java | 14 ++++++++-- .../iris/engine/object/IrisDimension.java | 17 +++++++++++ .../iris/engine/object/IrisPreProcessors.java | 25 +++++++++++++++++ .../functions/ResourceLoadersFunction.java | 28 +++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/com/volmit/iris/engine/object/IrisPreProcessors.java create mode 100644 core/src/main/java/com/volmit/iris/engine/object/annotations/functions/ResourceLoadersFunction.java 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 404958e79..87a45076b 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 @@ -250,9 +250,19 @@ 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) { - for (String i : t.getPreprocessors()) { + 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 : 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); } 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 f2c5b724c..a765e167a 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 @@ -28,6 +28,7 @@ import com.volmit.iris.core.nms.datapack.IDataFixer; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.object.annotations.*; 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; @@ -66,6 +67,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") @@ -244,6 +246,10 @@ public class IrisDimension extends IrisRegistrant { @MaxNumber(318) @Desc("The Subterrain Fluid Layer Height") private int caveLavaHeight = 8; + @MinNumber(1) + @Desc("A list of globally applied pre-processors") + @ArrayType(type = IrisPreProcessors.class) + private KList globalPreProcessors = new KList<>(); public int getMaxHeight() { return (int) getDimensionHeight().getMax(); @@ -362,6 +368,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/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/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()); + } +} From 2929a1f0a771df7f5198de6bbabbd36e500f26a2 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Mon, 16 Jun 2025 22:44:15 +0200 Subject: [PATCH 07/31] update Script Engine to e08b6f893e --- .../com/volmit/iris/core/scripting/ExecutionEnvironment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index 5b9dd6022..6620880db 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -42,7 +42,7 @@ public class ExecutionEnvironment { @SneakyThrows private static URLClassLoader buildLoader() { - String version = "41396a77d5"; + String version = "e08b6f893e"; String url = BASE_URL.formatted(version, version); String hash = IO.hash("Iris-Scripts.jar@" + version); var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); From c35c858eee697ff0d5cdef85e3b21b093f894c46 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Mon, 7 Jul 2025 21:06:36 +0200 Subject: [PATCH 08/31] add scripts for engine setup --- core/src/main/java/com/volmit/iris/engine/IrisEngine.java | 1 + .../java/com/volmit/iris/engine/object/IrisDimension.java | 4 ++++ 2 files changed, 5 insertions(+) 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 00232dcc1..9839a7ff6 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngine.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngine.java @@ -173,6 +173,7 @@ public class IrisEngine implements Engine { effects = new IrisEngineEffects(this); hash32 = new CompletableFuture<>(); setupMode(); + getDimension().getSetupScripts().forEach(execution::execute); J.a(this::computeBiomeMaxes); J.a(() -> { File[] roots = getData().getLoaders() 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 a765e167a..e2ac178b9 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 @@ -250,6 +250,10 @@ public class IrisDimension extends IrisRegistrant { @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 setupScripts = new KList<>(); public int getMaxHeight() { return (int) getDimensionHeight().getMax(); From 50db1d11a7750b474d01117e0d638db4cdea7b6d Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Tue, 8 Jul 2025 12:30:21 +0200 Subject: [PATCH 09/31] move script engine libraries into the iris plugin folder --- build.gradle.kts | 4 ++- .../core/scripting/ExecutionEnvironment.java | 34 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d3cfd5fee..4ae285a40 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -63,7 +63,8 @@ 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 scriptVersion = findProperty("scriptVersion") as String? ?: "master-SNAPSHOT" val nmsBindings = mapOf( "v1_21_R5" to "1.21.7-R0.1-SNAPSHOT", @@ -110,6 +111,7 @@ nmsBindings.forEach { key, value -> systemProperty("net.kyori.ansi.colorLevel", color) systemProperty("com.mojang.eula.agree", true) systemProperty("iris.suppressReporting", !errorReporting) + systemProperty("iris.scriptVersion", scriptVersion) jvmArgs("-javaagent:${project(":core:agent").tasks.jar.flatMap { it.archiveFile }.get().asFile.absolutePath}") } } diff --git a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index 6620880db..2b6ab34b6 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -15,15 +15,20 @@ import java.io.File; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; -import java.nio.file.Files; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Path; import java.util.*; @UtilityClass public class ExecutionEnvironment { - private static final String BASE_URL = "https://jitpack.io/com/github/VolmitSoftware/Iris-Scripts/%s/Iris-Scripts-%s-all.jar"; + private static final String VERSION = System.getProperty("iris.scriptVersion", "e08b6f893e"); + private static final String BASE_URL = "https://jitpack.io/com/github/VolmitSoftware/Iris-Scripts/" + VERSION + "/Iris-Scripts-" + VERSION + "-all.jar"; private static final Provider PROVIDER = ServiceLoader.load(Provider.class, buildLoader()) .findFirst() - .orElseThrow(); + .orElseThrow() + .init(Iris.instance.getDataFolder("cache", "libraries").toPath()); @NonNull public static Engine createEngine(@NonNull com.volmit.iris.engine.framework.Engine engine) { @@ -42,21 +47,24 @@ public class ExecutionEnvironment { @SneakyThrows private static URLClassLoader buildLoader() { - String version = "e08b6f893e"; - String url = BASE_URL.formatted(version, version); - String hash = IO.hash("Iris-Scripts.jar@" + version); - var file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); - if (!file.exists()) { - Iris.info("Downloading Script Engine..."); - try (var stream = URI.create(url).toURL().openStream()) { - Files.copy(stream, file.toPath()); + try (HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build()) { + var resolved = client.send(HttpRequest.newBuilder(URI.create(BASE_URL)).build(), HttpResponse.BodyHandlers.discarding()) + .request(); + String hash = IO.hash(resolved.uri().getPath()); + File file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); + if (!file.exists()) { + file.getParentFile().mkdirs(); + Iris.info("Downloading Script Engine..."); + client.send(resolved, HttpResponse.BodyHandlers.ofFile(file.toPath())); + Iris.info("Downloaded Script Engine!"); } - Iris.info("Downloaded Script Engine!"); + return new URLClassLoader(new URL[]{file.toURI().toURL()}, Provider.class.getClassLoader()); } - return new URLClassLoader(new URL[]{file.toURI().toURL()}, Provider.class.getClassLoader()); } public interface Provider { + Provider init(Path localRepository); + @NonNull Engine createEngine(@NonNull com.volmit.iris.engine.framework.Engine engine); From c01a7def5d831ca77421063a2afeac8b7c62e342 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Tue, 8 Jul 2025 15:37:14 +0200 Subject: [PATCH 10/31] add iris data setup hook --- .../main/java/com/volmit/iris/core/loader/IrisData.java | 8 ++++++++ .../java/com/volmit/iris/core/loader/ResourceLoader.java | 6 +++++- .../volmit/iris/core/scripting/ExecutionEnvironment.java | 2 +- core/src/main/java/com/volmit/iris/engine/IrisEngine.java | 2 +- .../java/com/volmit/iris/engine/object/IrisDimension.java | 6 +++++- 5 files changed, 20 insertions(+), 4 deletions(-) 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 34d67ec83..10dc795a6 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.ExecutionEnvironment; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.object.*; @@ -54,6 +55,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { private static final KMap dataLoaders = new KMap<>(); private final File dataFolder; private final int id; + private final ExecutionEnvironment.Pack environment; private boolean closed = false; private ResourceLoader biomeLoader; private ResourceLoader lootLoader; @@ -87,6 +89,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { this.engine = null; this.dataFolder = dataFolder; this.id = RNG.r.imax(); + this.environment = ExecutionEnvironment.createPack(this); hotloaded(); } @@ -319,6 +322,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { } public synchronized void hotloaded() { + environment.close(); possibleSnippets = new KMap<>(); builder = new GsonBuilder() .addDeserializationExclusionStrategy(this) @@ -359,6 +363,10 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory { } 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 a9b468e57..0f804e4e2 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 @@ -44,8 +44,8 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import java.io.*; +import java.util.Arrays; import java.util.Locale; -import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -216,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/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index 2b6ab34b6..b484242bf 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -23,7 +23,7 @@ import java.util.*; @UtilityClass public class ExecutionEnvironment { - private static final String VERSION = System.getProperty("iris.scriptVersion", "e08b6f893e"); + private static final String VERSION = System.getProperty("iris.scriptVersion", "master-ffbf167eba-1"); private static final String BASE_URL = "https://jitpack.io/com/github/VolmitSoftware/Iris-Scripts/" + VERSION + "/Iris-Scripts-" + VERSION + "-all.jar"; private static final Provider PROVIDER = ServiceLoader.load(Provider.class, buildLoader()) .findFirst() 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 9839a7ff6..3289c64d8 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngine.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngine.java @@ -173,7 +173,7 @@ public class IrisEngine implements Engine { effects = new IrisEngineEffects(this); hash32 = new CompletableFuture<>(); setupMode(); - getDimension().getSetupScripts().forEach(execution::execute); + getDimension().getEngineScripts().forEach(execution::execute); J.a(this::computeBiomeMaxes); J.a(() -> { File[] roots = getData().getLoaders() 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 c82a175ea..791a602e1 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 @@ -247,7 +247,11 @@ public class IrisDimension extends IrisRegistrant { @Desc("A list of scripts executed on engine setup") @RegistryListResource(IrisScript.class) @ArrayType(type = String.class, min = 1) - private KList setupScripts = new KList<>(); + 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(); From 0a30881f87e284aff00eb1cc97cf9805274d6aab Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Tue, 8 Jul 2025 16:08:30 +0200 Subject: [PATCH 11/31] add jaxen to runtime dependencies --- core/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 912dfbaba..f375accfb 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -85,6 +85,7 @@ dependencies { dynamic("net.bytebuddy:byte-buddy:1.17.5") dynamic("net.bytebuddy:byte-buddy-agent:1.17.5") dynamic("org.dom4j:dom4j:2.1.4") + dynamic("jaxen:jaxen:1.1.6") } java { From 4b0766c097dd3649682018f8e513247d98bb1808 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Wed, 9 Jul 2025 14:24:24 +0200 Subject: [PATCH 12/31] remove bfs --- gradle/libs.versions.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a474aec14..5ac9ac2c0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,8 +32,6 @@ lru = "1.4.2" # https://central.sonatype.com/artifact/com.googlecode.concurrentl zip = "1.17" # https://central.sonatype.com/artifact/org.zeroturnaround/zt-zip gson = "2.13.1" # https://central.sonatype.com/artifact/com.google.code.gson/gson asm = "9.8" # https://central.sonatype.com/artifact/org.ow2.asm/asm -bsf = "2.4.0" # https://central.sonatype.com/artifact/bsf/bsf -rhino = "1.7R2" # https://central.sonatype.com/artifact/rhino/js caffeine = "3.2.1" # https://central.sonatype.com/artifact/com.github.ben-manes.caffeine/caffeine byte-buddy = "1.17.6" # https://central.sonatype.com/artifact/net.bytebuddy/byte-buddy dom4j = "2.2.0" # https://central.sonatype.com/artifact/org.dom4j/dom4j From 1bc6192c8b41d8065956afa9eb2429cdfd33736e Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Wed, 9 Jul 2025 15:16:11 +0200 Subject: [PATCH 13/31] merge kts engine into this codebase --- core/build.gradle.kts | 13 ++ core/src/main/java/com/volmit/iris/Iris.java | 9 +- .../core/scripting/ExecutionEnvironment.java | 56 +------- .../com/volmit/iris/util/misc/SlimJar.java | 37 +++++ .../core/scripting/kotlin/base/DataScript.kt | 15 ++ .../scripting/kotlin/base/EngineScript.kt | 25 ++++ .../kotlin/base/MobSpawningScript.kt | 15 ++ .../kotlin/base/PostMobSpawningScript.kt | 15 ++ .../kotlin/base/PreprocessorScript.kt | 15 ++ .../scripting/kotlin/base/SimpleScript.kt | 40 ++++++ .../environment/IrisExecutionEnvironment.kt | 45 ++++++ .../IrisPackExecutionEnvironment.kt | 35 +++++ .../IrisSimpleExecutionEnvironment.kt | 135 ++++++++++++++++++ .../scripting/kotlin/runner/CachedScript.kt | 64 +++++++++ .../core/scripting/kotlin/runner/Script.kt | 8 ++ .../scripting/kotlin/runner/ScriptRunner.kt | 53 +++++++ .../core/scripting/kotlin/runner/Utils.kt | 54 +++++++ ...iris.core.scripting.kotlin.base.DataScript | 0 ...is.core.scripting.kotlin.base.EngineScript | 0 ...re.scripting.kotlin.base.MobSpawningScript | 0 ...cripting.kotlin.base.PostMobSpawningScript | 0 ...e.scripting.kotlin.base.PreprocessorScript | 0 ...is.core.scripting.kotlin.base.SimpleScript | 0 gradle/libs.versions.toml | 14 ++ 24 files changed, 591 insertions(+), 57 deletions(-) create mode 100644 core/src/main/java/com/volmit/iris/util/misc/SlimJar.java create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/DataScript.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/EngineScript.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/MobSpawningScript.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PostMobSpawningScript.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/PreprocessorScript.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/SimpleScript.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisExecutionEnvironment.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisPackExecutionEnvironment.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisSimpleExecutionEnvironment.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/runner/CachedScript.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/runner/Script.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/runner/ScriptRunner.kt create mode 100644 core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/runner/Utils.kt create mode 100644 core/src/main/resources/META-INF/kotlin/script/templates/com.volmit.iris.core.scripting.kotlin.base.DataScript create mode 100644 core/src/main/resources/META-INF/kotlin/script/templates/com.volmit.iris.core.scripting.kotlin.base.EngineScript create mode 100644 core/src/main/resources/META-INF/kotlin/script/templates/com.volmit.iris.core.scripting.kotlin.base.MobSpawningScript create mode 100644 core/src/main/resources/META-INF/kotlin/script/templates/com.volmit.iris.core.scripting.kotlin.base.PostMobSpawningScript create mode 100644 core/src/main/resources/META-INF/kotlin/script/templates/com.volmit.iris.core.scripting.kotlin.base.PreprocessorScript create mode 100644 core/src/main/resources/META-INF/kotlin/script/templates/com.volmit.iris.core.scripting.kotlin.base.SimpleScript diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 0abad7812..da7b101bd 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -26,6 +26,8 @@ plugins { alias(libs.plugins.shadow) alias(libs.plugins.sentry) alias(libs.plugins.slimjar) + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.lombok) } val apiVersion = "1.19" @@ -91,6 +93,14 @@ dependencies { 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) } java { @@ -117,6 +127,9 @@ 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") } tasks { diff --git a/core/src/main/java/com/volmit/iris/Iris.java b/core/src/main/java/com/volmit/iris/Iris.java index cfd03f730..8da92f0c4 100644 --- a/core/src/main/java/com/volmit/iris/Iris.java +++ b/core/src/main/java/com/volmit/iris/Iris.java @@ -53,6 +53,7 @@ import com.volmit.iris.util.io.JarScanner; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.misc.Bindings; +import com.volmit.iris.util.misc.SlimJar; import com.volmit.iris.util.misc.getHardware; import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.plugin.IrisService; @@ -438,13 +439,7 @@ public class Iris extends VolmitPlugin implements Listener { } public Iris() { - ApplicationBuilder.appending("Iris") - .downloadDirectoryPath(getDataFolder("cache", "libraries").toPath()) - .logger((message, args) -> { - if (!message.startsWith("Loaded library ")) return; - getLogger().info(message.formatted(args)); - }) - .build(); + SlimJar.load(getDataFolder("cache", "libraries")); } private void enable() { diff --git a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java index b484242bf..7e903a218 100644 --- a/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java +++ b/core/src/main/java/com/volmit/iris/core/scripting/ExecutionEnvironment.java @@ -1,81 +1,37 @@ package com.volmit.iris.core.scripting; -import com.volmit.iris.Iris; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisRegistrant; -import com.volmit.iris.util.io.IO; +import com.volmit.iris.core.scripting.kotlin.environment.IrisExecutionEnvironment; +import com.volmit.iris.core.scripting.kotlin.environment.IrisPackExecutionEnvironment; +import com.volmit.iris.core.scripting.kotlin.environment.IrisSimpleExecutionEnvironment; import lombok.NonNull; -import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.file.Path; import java.util.*; @UtilityClass public class ExecutionEnvironment { - private static final String VERSION = System.getProperty("iris.scriptVersion", "master-ffbf167eba-1"); - private static final String BASE_URL = "https://jitpack.io/com/github/VolmitSoftware/Iris-Scripts/" + VERSION + "/Iris-Scripts-" + VERSION + "-all.jar"; - private static final Provider PROVIDER = ServiceLoader.load(Provider.class, buildLoader()) - .findFirst() - .orElseThrow() - .init(Iris.instance.getDataFolder("cache", "libraries").toPath()); @NonNull public static Engine createEngine(@NonNull com.volmit.iris.engine.framework.Engine engine) { - return PROVIDER.createEngine(engine); + return new IrisExecutionEnvironment(engine); } @NonNull public static Pack createPack(@NonNull IrisData data) { - return PROVIDER.createPack(data); + return new IrisPackExecutionEnvironment(data); } @NonNull public static Simple createSimple() { - return PROVIDER.createSimple(); + return new IrisSimpleExecutionEnvironment(); } - @SneakyThrows - private static URLClassLoader buildLoader() { - try (HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build()) { - var resolved = client.send(HttpRequest.newBuilder(URI.create(BASE_URL)).build(), HttpResponse.BodyHandlers.discarding()) - .request(); - String hash = IO.hash(resolved.uri().getPath()); - File file = Iris.instance.getDataFile("cache", hash.substring(0, 2), hash.substring(3, 5), hash + ".jar"); - if (!file.exists()) { - file.getParentFile().mkdirs(); - Iris.info("Downloading Script Engine..."); - client.send(resolved, HttpResponse.BodyHandlers.ofFile(file.toPath())); - Iris.info("Downloaded Script Engine!"); - } - return new URLClassLoader(new URL[]{file.toURI().toURL()}, Provider.class.getClassLoader()); - } - } - - public interface Provider { - Provider init(Path localRepository); - - @NonNull - Engine createEngine(@NonNull com.volmit.iris.engine.framework.Engine engine); - - @NonNull - Pack createPack(@NonNull IrisData data); - - @NonNull - Simple createSimple(); - } - - public interface Simple { void configureProject(@NonNull File projectDir); diff --git a/core/src/main/java/com/volmit/iris/util/misc/SlimJar.java b/core/src/main/java/com/volmit/iris/util/misc/SlimJar.java new file mode 100644 index 000000000..bbd5ee878 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/misc/SlimJar.java @@ -0,0 +1,37 @@ +package com.volmit.iris.util.misc; + +import io.github.slimjar.app.builder.ApplicationBuilder; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Logger; + +public class SlimJar { + private static final Logger LOGGER = Logger.getLogger("Iris"); + private static final ReentrantLock lock = new ReentrantLock(); + private static final AtomicBoolean loaded = new AtomicBoolean(); + + public static void load(@Nullable File localRepository) { + if (loaded.get()) return; + lock.lock(); + + try { + if (loaded.getAndSet(true)) return; + if (localRepository == null) { + localRepository = new File(".iris/libraries"); + } + + ApplicationBuilder.appending("Iris") + .downloadDirectoryPath(localRepository.toPath()) + .logger((message, args) -> { + if (!message.startsWith("Loaded library ")) return; + LOGGER.info(message.formatted(args)); + }) + .build(); + } finally { + lock.unlock(); + } + } +} 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/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..5adbbaf8c --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/base/SimpleScript.kt @@ -0,0 +1,40 @@ +package com.volmit.iris.core.scripting.kotlin.base + +import com.volmit.iris.core.scripting.kotlin.runner.configureMavenDepsOnAnnotations +import com.volmit.iris.util.misc.SlimJar +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.defaultImports +import kotlin.script.experimental.api.isStandalone +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({ + SlimJar.load(null) + + isStandalone(false) + defaultImports( + "kotlin.script.experimental.dependencies.DependsOn", + "kotlin.script.experimental.dependencies.Repository", + "com.volmit.iris.Iris.info", + "com.volmit.iris.Iris.debug", + "com.volmit.iris.Iris.warn", + "com.volmit.iris.Iris.error" + ) + + jvm { + 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..df13c7ad4 --- /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.ExecutionEnvironment +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), ExecutionEnvironment.Engine { + 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..a69b9ea6a --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisPackExecutionEnvironment.kt @@ -0,0 +1,35 @@ +package com.volmit.iris.core.scripting.kotlin.environment + +import com.volmit.iris.core.loader.IrisData +import com.volmit.iris.core.scripting.ExecutionEnvironment +import com.volmit.iris.core.scripting.kotlin.base.DataScript +import com.volmit.iris.core.scripting.kotlin.runner.Script +import kotlin.reflect.KClass +import kotlin.script.experimental.api.valueOrThrow + +open class IrisPackExecutionEnvironment( + private val data: IrisData +) : IrisSimpleExecutionEnvironment(), ExecutionEnvironment.Pack { + + 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.compileText(type, loaded.source, script) } + .valueOrThrow() + } + + override fun execute(script: String) = + execute(script, DataScript::class.java, data.parameters()) + + override fun evaluate(script: String) = + evaluate(script, DataScript::class.java, data.parameters()) + + 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..014d440f4 --- /dev/null +++ b/core/src/main/kotlin/com/volmit/iris/core/scripting/kotlin/environment/IrisSimpleExecutionEnvironment.kt @@ -0,0 +1,135 @@ +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.ExecutionEnvironment +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.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.api.ResultWithDiagnostics +import kotlin.script.experimental.api.valueOrThrow +import kotlin.text.split + +open class IrisSimpleExecutionEnvironment : ExecutionEnvironment.Simple { + protected val compileCache = KCache, ResultWithDiagnostics