diff --git a/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java index 2ecdb518e..7174bac6e 100644 --- a/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java +++ b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java @@ -25,7 +25,6 @@ import noppes.npcs.api.IBlock; import noppes.npcs.api.block.ITextPlane; import noppes.npcs.client.renderer.blocks.BlockScriptedRenderer; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptBlockHandler; import noppes.npcs.controllers.data.IScriptUnit; @@ -369,9 +368,7 @@ public class TileScripted extends TileEntity implements IScriptBlockHandler { } for (IScriptUnit script : scripts) { - if (script instanceof ScriptContainer) { - ((ScriptContainer) script).run(type, event); - } + script.run(type, event); } } diff --git a/src/main/java/noppes/npcs/controllers/data/DataScript.java b/src/main/java/noppes/npcs/controllers/data/DataScript.java index 71921e60b..014959919 100644 --- a/src/main/java/noppes/npcs/controllers/data/DataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/DataScript.java @@ -153,9 +153,7 @@ public class DataScript implements IScriptHandler { } for (IScriptUnit script : this.eventScripts) { - if (script instanceof ScriptContainer) { - ((ScriptContainer) script).run(type, event); - } + script.run(type, event); } ScriptContainer script = scripts.get(type); diff --git a/src/main/java/noppes/npcs/controllers/data/EffectScript.java b/src/main/java/noppes/npcs/controllers/data/EffectScript.java index 5ca67697d..dcd497fc8 100644 --- a/src/main/java/noppes/npcs/controllers/data/EffectScript.java +++ b/src/main/java/noppes/npcs/controllers/data/EffectScript.java @@ -8,7 +8,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.Constants; import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.scripted.event.player.PlayerEvent; @@ -62,8 +61,9 @@ public class EffectScript implements IScriptHandler { if (!this.isEnabled()) { return; } - if (container instanceof ScriptContainer) - ((ScriptContainer) container).run(s, event); + if (container != null) { + container.run(s, event); + } } @Override diff --git a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java index 66563bf54..043e56efe 100644 --- a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java @@ -78,14 +78,9 @@ public class ForgeDataScript implements IScriptHandler { } for (IScriptUnit script : this.scripts) { - if (script == null || !script.hasCode()) + if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - if (container.errored) - continue; - container.run(type, event); - } + script.run(type, event); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java index 4bbb742ce..c4dc15913 100644 --- a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java @@ -94,14 +94,9 @@ public class GlobalNPCDataScript implements IScriptHandler { } for (IScriptUnit script : this.scripts) { - if (script == null || !script.hasCode()) + if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - if (container.errored) - continue; - container.run(hookName, event); - } + script.run(hookName, event); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java index fcd3fc6f8..392901ede 100644 --- a/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java +++ b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java @@ -1,8 +1,9 @@ package noppes.npcs.controllers.data; +import cpw.mods.fml.common.eventhandler.Event; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptContainer; -import noppes.npcs.janino.JaninoScript; import java.util.List; import java.util.Map; @@ -149,4 +150,26 @@ public interface IScriptUnit { * Set the error state of this script unit. */ void setErrored(boolean errored); + + // ==================== EXECUTION ==================== + + /** + * Execute this script unit for the given hook type and event. + * For ScriptContainer: calls run(EnumScriptType, Event) + * For JaninoScript: calls callByHookType(EnumScriptType, Event) + * + * @param type The script hook type + * @param event The event object + */ + void run(EnumScriptType type, Event event); + + /** + * Execute this script unit for the given hook name and event. + * For ScriptContainer: calls run(String, Event) + * For JaninoScript: converts hookName to EnumScriptType and calls callByHookType + * + * @param hookName The hook name (e.g., "init", "interact") + * @param event The event object + */ + void run(String hookName, Object event); } diff --git a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java index d13e64c50..a2f3a3025 100644 --- a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java +++ b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java @@ -8,7 +8,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.Constants; import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import java.io.IOException; @@ -56,8 +55,9 @@ public class LinkedItemScript implements IScriptHandler { if (!this.isEnabled()) { return; } - if (container instanceof ScriptContainer) - ((ScriptContainer) container).run(s, event); + if (container != null) { + container.run(s, event); + } } @Override diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java index 7fd2eb644..c8dd007f7 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java @@ -121,18 +121,15 @@ public class PlayerDataScript implements IScriptHandler { IScriptUnit script = scripts.get(i); if (errored.contains(i)) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - container.run(hookName, event); - if (container.errored) { - errored.add(i); - } - for (Entry entry : container.console.entrySet()) { - if (!console.containsKey(entry.getKey())) - console.put(entry.getKey(), " tab " + (i + 1) + ":\n" + entry.getValue()); - } - container.console.clear(); + script.run(hookName, event); + if (script.hasErrored()) { + errored.add(i); } + for (Entry entry : script.getConsole().entrySet()) { + if (!console.containsKey(entry.getKey())) + console.put(entry.getKey(), " tab " + (i + 1) + ":\n" + entry.getValue()); + } + script.clearConsole(); } } else { if (ScriptController.Instance.lastLoaded > this.lastInited || ScriptController.Instance.lastPlayerUpdate > this.lastPlayerUpdate) { @@ -151,12 +148,9 @@ public class PlayerDataScript implements IScriptHandler { } for (IScriptUnit script : this.scripts) { - if (script == null || script.hasErrored()|| !script.hasCode()) + if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - container.run(hookName, event); - } + script.run(hookName, event); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java index ff9f681ad..ee1b32c08 100644 --- a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java +++ b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java @@ -8,7 +8,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.Constants; import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import java.io.IOException; @@ -53,8 +52,9 @@ public class RecipeScript implements IScriptHandler { public void callScript(String s, Event event) { if (!this.isEnabled()) return; - if (container instanceof ScriptContainer) - ((ScriptContainer) container).run(s, event); + if (container != null) { + container.run(s, event); + } } @Override diff --git a/src/main/java/noppes/npcs/janino/JaninoScript.java b/src/main/java/noppes/npcs/janino/JaninoScript.java index 13a7a33c9..a5e1f3274 100644 --- a/src/main/java/noppes/npcs/janino/JaninoScript.java +++ b/src/main/java/noppes/npcs/janino/JaninoScript.java @@ -1,12 +1,14 @@ package noppes.npcs.janino; import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.Event; import io.github.somehussar.janinoloader.api.script.IScriptBodyBuilder; import io.github.somehussar.janinoloader.api.script.IScriptClassBody; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.CustomNpcs; import noppes.npcs.NBTTags; import noppes.npcs.config.ConfigScript; +import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptUnit; import org.codehaus.commons.compiler.InternalCompilerException; @@ -51,6 +53,8 @@ public abstract class JaninoScript implements IScriptUnit { private List hookList = new ArrayList<>(); // Map from display name (with parameters if overloaded) to Method private Map hookMap = new HashMap<>(); + // Map from EnumScriptType to Method for OLD tab-based script system + private Map hookTypeMap = new HashMap<>(); protected JaninoScript(Class type, Consumer> buildSettings) { this.type = type; @@ -63,6 +67,9 @@ public abstract class JaninoScript implements IScriptUnit { sandbox = new Sandbox(permissions); this.scriptBody = builder.build(); + + // Build hook type map from @ScriptHook annotations + initializeHookTypeMap(); } protected T getUnsafe() { @@ -195,9 +202,85 @@ public abstract class JaninoScript implements IScriptUnit { sb.append(code).append("\n"); } } - + + /** + * Scans the Functions interface for @ScriptHook annotations and builds the hookTypeMap. + * This allows direct method invocation by EnumScriptType without switch statements. + */ + private void initializeHookTypeMap() { + for (Method method : type.getDeclaredMethods()) { + ScriptHook annotation = method.getAnnotation(ScriptHook.class); + if (annotation != null) { + for (EnumScriptType hookType : annotation.value()) { + hookTypeMap.put(hookType, method); + } + } + } + } + + /** + * Call a hook method by its EnumScriptType. + * Used by the OLD tab-based script system to execute hooks directly. + * + * @param hookType The script type/hook to execute + * @param event The event object to pass to the hook method + */ + public void callByHookType(EnumScriptType hookType, Object event) { + Method method = hookTypeMap.get(hookType); + if (method == null) { + // Hook not implemented or not annotated + return; + } + + ensureCompiled(); + T t = getUnsafe(); + if (t == null) + return; + + try { + sandbox.confine((PrivilegedAction) () -> { + try { + method.invoke(t, event); + } catch (Exception e) { + appendConsole("Error calling hook " + hookType.name() + ": " + e.getMessage()); + } + return null; + }); + } catch (Exception e) { + appendConsole("Runtime Error in hook " + hookType.name() + ": " + e.getMessage()); + } + } + // ==================== IScriptUnit IMPLEMENTATION ==================== + /** + * Execute this script unit for the given hook type and event. + * Implementation of IScriptUnit.run(EnumScriptType, Event) + * + * @param type The script hook type + * @param event The event object + */ + @Override + public void run(EnumScriptType type, Event event) { + callByHookType(type, event); + } + + /** + * Execute this script unit for the given hook name and event. + * Implementation of IScriptUnit.run(String, Event) + * + * @param hookName The hook name (e.g., "init", "interact") + * @param event The event object + */ + @Override + public void run(String hookName, Object event) { + try { + EnumScriptType enumType = EnumScriptType.valueOfIgnoreCase(hookName); + callByHookType(enumType, event); + } catch (IllegalArgumentException ignored) { + // Hook name doesn't map to an EnumScriptType + } + } @Override public String getScript() { return this.script; diff --git a/src/main/java/noppes/npcs/janino/ScriptHook.java b/src/main/java/noppes/npcs/janino/ScriptHook.java new file mode 100644 index 000000000..1b1ba598b --- /dev/null +++ b/src/main/java/noppes/npcs/janino/ScriptHook.java @@ -0,0 +1,22 @@ +package noppes.npcs.janino; + +import noppes.npcs.constants.EnumScriptType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to mark script hook methods and associate them with their EnumScriptType. + * Used by JaninoScript to automatically build a map of hook types to methods. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ScriptHook { + /** + * The script type(s) this method handles. + * Multiple types can be specified for methods that handle multiple hooks. + */ + EnumScriptType[] value(); +} diff --git a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java index 87d233540..02f27b71c 100644 --- a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java +++ b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java @@ -8,7 +8,6 @@ import noppes.npcs.NBTTags; import noppes.npcs.api.item.IItemCustom; import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.data.IScriptUnit; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptHandler; import noppes.npcs.scripted.CustomNPCsException; @@ -101,9 +100,7 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ((ScriptContainer) script).run(hookName, event); - } + script.run(hookName, event); if (script.hasErrored()) { this.errored.add(i);