diff --git a/common/src/main/java/cn/zbx1425/mtrsteamloco/gui/ScriptDebugOverlay.java b/common/src/main/java/cn/zbx1425/mtrsteamloco/gui/ScriptDebugOverlay.java index 4d417fd0..10bd362d 100644 --- a/common/src/main/java/cn/zbx1425/mtrsteamloco/gui/ScriptDebugOverlay.java +++ b/common/src/main/java/cn/zbx1425/mtrsteamloco/gui/ScriptDebugOverlay.java @@ -60,7 +60,7 @@ public static void render(PoseStack vdStuff) { } for (AbstractScriptContext context : entry.getValue()) { drawText(vdStuff, font, - String.format("#%08X (%.2f ms)", context.hashCode(), context.lastExecuteDuration / 1000f), + String.format("#%08X (%.2f ms)", context.hashCode(), context.lastExecuteDuration / 1000.0), 10, y, 0xFFCCCCFF); y += lineHeight; for (Map.Entry debugInfo : context.debugInfo.entrySet()) { diff --git a/common/src/main/java/cn/zbx1425/mtrsteamloco/render/scripting/ScriptHolder.java b/common/src/main/java/cn/zbx1425/mtrsteamloco/render/scripting/ScriptHolder.java index 2ad8fb53..b3981655 100644 --- a/common/src/main/java/cn/zbx1425/mtrsteamloco/render/scripting/ScriptHolder.java +++ b/common/src/main/java/cn/zbx1425/mtrsteamloco/render/scripting/ScriptHolder.java @@ -17,6 +17,8 @@ import vendor.cn.zbx1425.mtrsteamloco.org.mozilla.javascript.*; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -27,6 +29,9 @@ public class ScriptHolder { private static ExecutorService SCRIPT_THREAD = Executors.newSingleThreadExecutor(); private Scriptable scope; + private final List createFunctions = new ArrayList<>(); + private final List renderFunctions = new ArrayList<>(); + private final List disposeFunctions = new ArrayList<>(); public long failTime = 0; public Exception failException = null; @@ -42,6 +47,7 @@ public void load(String name, ResourceManager resourceManager, Map entry : scripts.entrySet()) { String scriptStr = entry.getValue() == null ? ResourceUtil.readResource(resourceManager, entry.getKey()) : entry.getValue(); ScriptResourceUtil.executeScript(rhinoCtx, scope, entry.getKey(), scriptStr); + acquireFunction("create", createFunctions); + acquireFunction("render", renderFunctions); + acquireFunction("dispose", disposeFunctions); } ScriptResourceUtil.activeContext = null; ScriptResourceUtil.activeScope = null; @@ -109,7 +119,17 @@ public void reload(ResourceManager resourceManager) throws Exception { load(name, resourceManager, scripts); } - public Future callFunctionAsync(String function, AbstractScriptContext scriptCtx, Runnable finishCallback) { + private void acquireFunction(String functionName, List target) { + Object jsFunction = scope.get(functionName, scope); + if (jsFunction != Scriptable.NOT_FOUND) { + if (jsFunction instanceof Function) { + target.add((Function)jsFunction); + } + scope.delete(functionName); + } + } + + public Future callFunctionAsync(List functions, AbstractScriptContext scriptCtx, Runnable finishCallback) { if (duringFailTimeout()) return null; failTime = 0; return SCRIPT_THREAD.submit(() -> { @@ -118,15 +138,12 @@ public Future callFunctionAsync(String function, AbstractScriptContext script if (scriptCtx.state == null) scriptCtx.state = rhinoCtx.newObject(scope); try { long startTime = System.nanoTime(); - Object jsFunction = scope.get(function, scope); - if (!(jsFunction instanceof Function && jsFunction != Scriptable.NOT_FOUND)) { - jsFunction = scope.get(function + scriptCtx.getContextTypeName(), scope); - } - if (!(jsFunction instanceof Function && jsFunction != Scriptable.NOT_FOUND)) return; TimingUtil.prepareForScript(scriptCtx); Object[] functionParam = { scriptCtx, scriptCtx.state, scriptCtx.getWrapperObject() }; - ((Function)jsFunction).call(rhinoCtx, scope, scope, functionParam); + for (Function function : functions) { + function.call(rhinoCtx, scope, scope, functionParam); + } if (finishCallback != null) finishCallback.run(); scriptCtx.lastExecuteDuration = System.nanoTime() - startTime; } catch (Exception ex) { @@ -144,12 +161,13 @@ public void tryCallRenderFunctionAsync(AbstractScriptContext scriptCtx) { if (scriptCtx.disposed) return; if (!scriptCtx.created) { ScriptContextManager.trackContext(scriptCtx, this); - scriptCtx.scriptStatus = callFunctionAsync("create", scriptCtx, () -> { + scriptCtx.scriptStatus = callFunctionAsync(createFunctions, scriptCtx, () -> { scriptCtx.created = true; }); + return; } if (scriptCtx.scriptStatus == null || scriptCtx.scriptStatus.isDone()) { - scriptCtx.scriptStatus = callFunctionAsync("render", scriptCtx, scriptCtx::renderFunctionFinished); + scriptCtx.scriptStatus = callFunctionAsync(renderFunctions, scriptCtx, scriptCtx::renderFunctionFinished); } } @@ -157,7 +175,7 @@ public void tryCallDisposeFunctionAsync(AbstractScriptContext scriptCtx) { if (!(scriptCtx.scriptStatus == null || scriptCtx.scriptStatus.isDone())) return; scriptCtx.disposed = true; if (scriptCtx.created) { - scriptCtx.scriptStatus = callFunctionAsync("dispose", scriptCtx, () -> { + scriptCtx.scriptStatus = callFunctionAsync(disposeFunctions, scriptCtx, () -> { scriptCtx.created = false; }); }