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: