diff --git a/build.gradle b/build.gradle index 40efad1..f11d5e2 100644 --- a/build.gradle +++ b/build.gradle @@ -91,11 +91,24 @@ repositories { name 'CurseMaven' url 'https://curse.cleanroommc.com' } + maven { + name 'BlameJared Maven' + url 'https://maven.blamejared.com' + } + maven { + name 'GTNH Maven' + url 'https://nexus.gtnewhorizons.com/repository/public/' + } + maven { + name 'GTCEu Maven' + url 'https://maven.gtceu.com' + } } dependencies { implementation 'curse.maven:resource-mod-loader-945917:5768125+5768126' + implementation 'com.cleanroommc:groovyscript:1.2.3' if (propertyBool('use_asset_mover')) { implementation "com.cleanroommc:assetmover:${propertyString('asset_mover_version')}" } diff --git a/src/main/java/mods/Hileb/shotaasm/ScriptLoader.java b/src/main/java/mods/Hileb/shotaasm/ScriptLoader.java index 8fda95c..19286da 100644 --- a/src/main/java/mods/Hileb/shotaasm/ScriptLoader.java +++ b/src/main/java/mods/Hileb/shotaasm/ScriptLoader.java @@ -15,8 +15,8 @@ import java.util.stream.Collectors; public class ScriptLoader { - private static Collection locators; - private static HashMap compilers = new HashMap<>(); + public static Collection locators; + public static HashMap compilers = new HashMap<>(); public static void initialize() { locators = loadServices(IScriptLocator.class).stream().map( aClass -> { diff --git a/src/main/java/mods/Hileb/shotaasm/ShotaASM.java b/src/main/java/mods/Hileb/shotaasm/ShotaASM.java index 4bd648b..ce8c9f1 100644 --- a/src/main/java/mods/Hileb/shotaasm/ShotaASM.java +++ b/src/main/java/mods/Hileb/shotaasm/ShotaASM.java @@ -4,6 +4,7 @@ import com.google.common.eventbus.Subscribe; import mods.Hileb.shotaasm.api.ShotaContext; import mods.Hileb.shotaasm.impl.ShotaCompiler; +import mods.Hileb.shotaasm.impl.EventHandler; import net.minecraftforge.fml.common.LoadController; import net.minecraftforge.fml.common.ModMetadata; import net.minecraftforge.fml.common.event.FMLStateEvent; @@ -71,7 +72,7 @@ public File getSource() { @Subscribe public void onFMLState(FMLStateEvent event) { - ShotaCompiler.executeEvent(event.getEventType()); + EventHandler.executeEvent(event.getEventType()); } } diff --git a/src/main/java/mods/Hileb/shotaasm/api/ShotaContext.java b/src/main/java/mods/Hileb/shotaasm/api/ShotaContext.java index b1845e6..e5bf12a 100644 --- a/src/main/java/mods/Hileb/shotaasm/api/ShotaContext.java +++ b/src/main/java/mods/Hileb/shotaasm/api/ShotaContext.java @@ -6,4 +6,8 @@ public static void initialize() {} public static boolean isClassExist(String name) { return net.minecraft.launchwrapper.Launch.classLoader.isClassExist(name); } + + public static java.util.Set supportedCompilers() { + return mods.Hileb.shotaasm.ScriptLoader.compilers.keySet(); + } } diff --git a/src/main/java/mods/Hileb/shotaasm/impl/EventHandler.java b/src/main/java/mods/Hileb/shotaasm/impl/EventHandler.java new file mode 100644 index 0000000..2fc7fc2 --- /dev/null +++ b/src/main/java/mods/Hileb/shotaasm/impl/EventHandler.java @@ -0,0 +1,16 @@ +package mods.Hileb.shotaasm.impl; + +import com.google.common.collect.HashMultimap; + +public class EventHandler { + private static final HashMultimap eventTasks = HashMultimap.create(); + + public static void executeEvent(String evt) { + eventTasks.get(evt).forEach(Runnable::run); + eventTasks.removeAll(evt); + } + + public static void addEvent(String evt, Runnable r) { + eventTasks.put(evt, r); + } +} \ No newline at end of file diff --git a/src/main/java/mods/Hileb/shotaasm/impl/ShotaCompiler.java b/src/main/java/mods/Hileb/shotaasm/impl/ShotaCompiler.java index 10c8a5d..cc0f348 100644 --- a/src/main/java/mods/Hileb/shotaasm/impl/ShotaCompiler.java +++ b/src/main/java/mods/Hileb/shotaasm/impl/ShotaCompiler.java @@ -16,12 +16,6 @@ import java.lang.reflect.InvocationTargetException; public class ShotaCompiler implements IScriptCompiler { - private static final HashMultimap eventTasks = HashMultimap.create(); - - public static void executeEvent(String evt) { - eventTasks.get(evt).forEach(Runnable::run); - eventTasks.removeAll(evt); - } @Override public String name() { @@ -35,7 +29,7 @@ public Runnable compile(final ScriptFile file) { if (file.property().containsKey("event")) { String event = Iterables.getFirst(file.property().get("event"), null); if (event != null) { - eventTasks.put(event, () -> ShotaCompiler.this.compile(file)); + EventHandler.addEvent(event, () -> ShotaCompiler.this.compile(file)); return () -> {}; } else return null; } else { diff --git a/src/main/java/mods/Hileb/shotaasm/impl/groovy/GroovyShotaCompiler.java b/src/main/java/mods/Hileb/shotaasm/impl/groovy/GroovyShotaCompiler.java new file mode 100644 index 0000000..b579622 --- /dev/null +++ b/src/main/java/mods/Hileb/shotaasm/impl/groovy/GroovyShotaCompiler.java @@ -0,0 +1,45 @@ +package mods.Hileb.shotaasm.impl.groovy; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Iterables; + +import mods.Hileb.shotaasm.api.ShotaContext; +import mods.Hileb.shotaasm.api.IScriptCompiler; +import mods.Hileb.shotaasm.api.ScriptFile; +import mods.Hileb.shotaasm.impl.EventHandler; + +public class GroovyShotaCompiler implements IScriptCompiler { + + @Override + public String name() { + return "groovyShota"; + } + + @Override + public Runnable compile(final ScriptFile file) { + if (ShotaContext.isClassExist("groovy.lang.GroovyClassLoader")) { + if (file.property().containsKey("event")) { + String event = Iterables.getFirst(file.property().get("event"), null); + if (event != null) { + EventHandler.addEvent(event, () -> GroovyShotaCompiler.this.compile(file)); + return () -> {}; + } else throw new RuntimeException("Could not understand the first event property is null. At " + file.name()); + } else { + String singleName = file.name().substring(0, file.name().lastIndexOf('.')).replace('.', '_') + file.hashCode(); + String name = "mods.Hileb.shotaasm.dynamic.groovy" + singleName; + StringBuilder builder = new StringBuilder(); + for (String s : file.property().get("import")) { + builder.append("import ").append(s).append(";\n"); + } + builder.append("\n").append(file.text()); + try { + return ShotaGroovySandbox.compileScript(name, builder.toString()); + } catch (Throwable e) { + throw new RuntimeException("Unable to compile for " + file.name(), e); + } + } + } else { + throw new RuntimeException("Groovy Support not found. But " + file.name() + " required the compiler of groovyShota."); + } + } +} diff --git a/src/main/java/mods/Hileb/shotaasm/impl/groovy/ShotaGroovySandbox.java b/src/main/java/mods/Hileb/shotaasm/impl/groovy/ShotaGroovySandbox.java new file mode 100644 index 0000000..93aa329 --- /dev/null +++ b/src/main/java/mods/Hileb/shotaasm/impl/groovy/ShotaGroovySandbox.java @@ -0,0 +1,57 @@ +package mods.Hileb.shotaasm.impl.groovy; + +import org.codehaus.groovy.control.customizers.ImportCustomizer; +import org.codehaus.groovy.control.CompilerConfiguration; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import groovy.lang.Binding; +import groovy.lang.GroovyClassLoader; +import groovy.lang.Script; +import org.codehaus.groovy.runtime.InvokerHelper; +import mods.Hileb.shotaasm.api.ScriptFile; +import net.minecraft.launchwrapper.Launch; + +import java.util.*; + +public class ShotaGroovySandbox { + + ImportCustomizer importCustomizer = new ImportCustomizer(); + CompilerConfiguration config = new CompilerConfiguration(); + Map bindings = new Object2ObjectOpenHashMap<>(); + Binding binding = new Binding(this.bindings); + GroovyClassLoader classLoader; + + public ShotaGroovySandbox() { + importCustomizer = new ImportCustomizer(); + config = new CompilerConfiguration(); + + importCustomizer.addImports( + "mods.Hileb.shotaasm.api.TransformerRegistry", + "mods.Hileb.shotaasm.api.ShotaContext" + ); + importCustomizer.addStarImports( + "org.objectweb.asm", + "org.objectweb.asm.tree", + "org.objectweb.asm.util", + "org.objectweb.asm.commons", + "org.objectweb.asm.signature" + ); + importCustomizer.addStaticStars("org.objectweb.asm.Opcodes"); + config.addCompilationCustomizers(importCustomizer); + classLoader = new GroovyClassLoader(Launch.classLoader, config, false); + } + + public Class compile(String name, String text) { + return classLoader.parseClass(text, name); + } + + public Runnable makeScript(Class cls){ + final Script script = InvokerHelper.createScript(cls, binding); + return script::run ; + } + + static ShotaGroovySandbox box = null; + public static Runnable compileScript(String name, String file){ + if (box == null) box = new ShotaGroovySandbox(); + return box.makeScript(box.compile(name, file)); + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/services/mods.Hileb.shotaasm.api.IScriptCompiler b/src/main/resources/META-INF/services/mods.Hileb.shotaasm.api.IScriptCompiler index a194455..04a42a7 100644 --- a/src/main/resources/META-INF/services/mods.Hileb.shotaasm.api.IScriptCompiler +++ b/src/main/resources/META-INF/services/mods.Hileb.shotaasm.api.IScriptCompiler @@ -1 +1,2 @@ -mods.Hileb.shotaasm.impl.ShotaCompiler \ No newline at end of file +mods.Hileb.shotaasm.impl.ShotaCompiler +mods.Hileb.shotaasm.impl.groovy.GroovyShotaCompiler \ No newline at end of file