Fix Instanced Abilities Reloading per Usage

This commit is contained in:
Kam committed 2026-03-03 22:15:49 -05:00
1 parent 2ba2372bde
commit 54e0ca6510
8 files changed
+144 -18

No files matched your search

@@ -11,6 +11,7 @@ import noppes.npcs.controllers.data.IScriptHandler;
import noppes.npcs.controllers.data.IScriptUnit;
import noppes.npcs.scripted.NpcAPI;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
@@ -52,10 +53,39 @@ public class ScriptContainer implements IScriptUnit {
*/
private String language = null;
/**
* Per-instance bindings for variable isolation. When non-null, this container
* is an instance scope sharing a template's engine. All eval/lookup uses these
* bindings instead of the engine's default ENGINE_SCOPE.
*/
private Bindings instanceBindings = null;
public ScriptContainer(IScriptHandler handler) {
this.handler = handler;
}
/**
* Create a lightweight instance scope that shares this container's engine
* but has its own isolated Bindings for variable state.
* The template's engine is initialized if needed.
*
* @param instanceHandler the script handler for the instance
*/
public ScriptContainer createInstanceScope(IScriptHandler instanceHandler) {
if (this.engine == null) {
this.setEngine(this.getLanguage());
}
ScriptContainer instance = new ScriptContainer(instanceHandler);
instance.script = this.script;
instance.scripts = new ArrayList<>(this.scripts);
instance.console = this.console;
instance.language = this.language;
instance.engine = this.engine;
instance.currentScriptLanguage = this.currentScriptLanguage;
instance.instanceBindings = this.engine.createBindings();
return instance;
}
public void readFromNBT(NBTTagCompound compound) {
String prevScript = this.script;
this.script = compound.getString("Script");
@@ -205,20 +235,33 @@ public class ScriptContainer implements IScriptUnit {
engine.getContext().setWriter(pw);
engine.getContext().setErrorWriter(pw);
engine.put("API", NpcAPI.Instance());
HashMap<String, Object> engineEntries = new HashMap<>(NpcAPI.engineObjects);
for (Map.Entry<String, Object> objectEntry : engineEntries.entrySet()) {
engine.put(objectEntry.getKey(), objectEntry.getValue());
// Populate bindings with API objects
if (instanceBindings != null) {
instanceBindings.put("API", NpcAPI.Instance());
HashMap<String, Object> engineEntries = new HashMap<>(NpcAPI.engineObjects);
for (Map.Entry<String, Object> objectEntry : engineEntries.entrySet()) {
instanceBindings.put(objectEntry.getKey(), objectEntry.getValue());
}
} else {
engine.put("API", NpcAPI.Instance());
HashMap<String, Object> engineEntries = new HashMap<>(NpcAPI.engineObjects);
for (Map.Entry<String, Object> objectEntry : engineEntries.entrySet()) {
engine.put(objectEntry.getKey(), objectEntry.getValue());
}
}
try {
if (!evaluated) {
this.cachedFunctions.clear();
engine.eval(getFullCode());
if (instanceBindings != null) {
engine.eval(getFullCode(), instanceBindings);
} else {
engine.eval(getFullCode());
}
evaluated = true;
}
if (engine.getFactory().getLanguageName().equals("lua")) {
Object ob = engine.get(type);
Object ob = instanceBindings != null ? instanceBindings.get(type) : engine.get(type);
if (ob != null) {
if (luaCoerce == null) {
luaCoerce = Class.forName("org.luaj.vm2.lib.jse.CoerceJavaToLua").getMethod("coerce", Object.class);
@@ -230,8 +273,14 @@ public class ScriptContainer implements IScriptUnit {
}
} else {
if (!this.cachedFunctions.containsKey(type)) {
ScriptObjectMirror global = (ScriptObjectMirror) engine.getBindings(ScriptContext.ENGINE_SCOPE);
ScriptObjectMirror func = (ScriptObjectMirror) global.get(type);
ScriptObjectMirror func;
if (instanceBindings != null) {
Object val = instanceBindings.get(type);
func = val instanceof ScriptObjectMirror ? (ScriptObjectMirror) val : null;
} else {
ScriptObjectMirror global = (ScriptObjectMirror) engine.getBindings(ScriptContext.ENGINE_SCOPE);
func = (ScriptObjectMirror) global.get(type);
}
this.cachedFunctions.put(type, func);
}
ScriptObjectMirror func = this.cachedFunctions.get(type);
@@ -280,6 +329,8 @@ public class ScriptContainer implements IScriptUnit {
public void setEngine(String scriptLanguage) {
if (!Objects.equals(scriptLanguage, this.currentScriptLanguage)) {
// Instance scopes share the template's engine — never create a new one
if (instanceBindings != null) return;
this.currentScriptLanguage = scriptLanguage;
if (ConfigScript.ScriptingECMA6 && scriptLanguage.equals("ECMAScript")) {
System.setProperty("nashorn.args", "--language=es6");