diff --git a/build.gradle b/build.gradle index 4e1252df97..226b21f891 100644 --- a/build.gradle +++ b/build.gradle @@ -254,6 +254,7 @@ project(":core"){ compileJava.dependsOn(preGen) compile "org.lz4:lz4-java:1.4.1" + compile "org.graalvm.js:js:19.3.0" compile arcModule("arc-core") compile arcModule("extensions:freetype") compile arcModule("extensions:arcnet") diff --git a/core/src/io/anuke/mindustry/mod/Mod.java b/core/src/io/anuke/mindustry/mod/Mod.java index 5ee0f699c4..aa4d8198f5 100644 --- a/core/src/io/anuke/mindustry/mod/Mod.java +++ b/core/src/io/anuke/mindustry/mod/Mod.java @@ -15,11 +15,6 @@ public class Mod{ } - /** Create any content needed here. */ - public void loadContent(){ - - } - /** Register any commands to be used on the server side, e.g. from the console. */ public void registerServerCommands(CommandHandler handler){ diff --git a/core/src/io/anuke/mindustry/mod/Mods.java b/core/src/io/anuke/mindustry/mod/Mods.java index 37a35e6f53..0107e5072f 100644 --- a/core/src/io/anuke/mindustry/mod/Mods.java +++ b/core/src/io/anuke/mindustry/mod/Mods.java @@ -30,6 +30,7 @@ import static io.anuke.mindustry.Vars.*; public class Mods implements Loadable{ private Json json = new Json(); + private Scripts scripts = new Scripts(); private ContentParser parser = new ContentParser(); private ObjectMap> bundles = new ObjectMap<>(); private ObjectSet specialFolders = ObjectSet.with("bundles", "sprites"); @@ -362,6 +363,31 @@ public class Mods implements Loadable{ /** Creates all the content found in mod files. */ public void loadContent(){ + + Time.mark(); + + for(LoadedMod mod : loaded){ + if(mod.root.child("scripts").exists()){ + mod.scripts = mod.root.child("scripts").findAll(f -> f.extension().equals("js")); + Log.info("[{0}] Found {1} scripts.", mod.meta.name, mod.scripts.size); + + for(FileHandle file : mod.scripts){ + try{ + scripts.run(file.readString()); + }catch(Throwable e){ + Core.app.post(() -> { + Log.err("Error loading script {0} for mod {1}.", file.name(), mod.meta.name); + e.printStackTrace(); + if(!headless) ui.showException(e); + }); + break; + } + } + } + } + + Log.info("Time to initialize modded scripts: {0}", Time.elapsed()); + class LoadRun implements Comparable{ final ContentType type; final FileHandle file; @@ -414,9 +440,6 @@ public class Mods implements Loadable{ //this finishes parsing content fields parser.finishParsing(); - - //load content for code mods - each(Mod::loadContent); } /** @return all loaded mods. */ @@ -582,6 +605,8 @@ public class Mods implements Loadable{ public Array dependencies = new Array<>(); /** All missing dependencies of this mod as strings. */ public Array missingDependencies = new Array<>(); + /** Script files to run. */ + public Array scripts = new Array<>(); public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){ this.root = root; diff --git a/core/src/io/anuke/mindustry/mod/Scripts.java b/core/src/io/anuke/mindustry/mod/Scripts.java new file mode 100644 index 0000000000..4de51215a0 --- /dev/null +++ b/core/src/io/anuke/mindustry/mod/Scripts.java @@ -0,0 +1,16 @@ +package io.anuke.mindustry.mod; + +import org.graalvm.polyglot.*; + +public class Scripts{ + //TODO allowHostAccess(...) is obviously insecure + private Context context = Context.newBuilder("js").allowHostClassLookup(s -> s.startsWith("io.anuke.mindustry")).allowHostAccess(HostAccess.ALL).build(); + + public Scripts(){ + context.eval("js", "console.log(\"Initialized JS context.\")"); + } + + public void run(String script){ + context.eval("js", script); + } +} diff --git a/gradle.properties b/gradle.properties index c5b304340a..8b7352fd6a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=ed17a2654951d1131bb6af71db6dea588df55b19 +archash=c7f3d8125c8d13c0a31c5f14fdabdb3d0efbd676