mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-14 01:24:09 +00:00
Add Script Optimizations / Caching
This commit is contained in:
1 parent
b231f65bfb
commit
8119515705
6 files changed
+74
-15
No files matched your search
@@ -92,6 +92,7 @@ import noppes.npcs.scripted.item.ScriptItemStack;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class EventHooks {
|
||||
public EventHooks() {
|
||||
@@ -1053,12 +1054,24 @@ public class EventHooks {
|
||||
NpcAPI.EVENT_BUS.post(event);
|
||||
}
|
||||
|
||||
private static final HashMap<Class<?>, String> forgeEventNameCache = new HashMap<>();
|
||||
|
||||
private static String getForgeEventName(Event event) {
|
||||
Class<?> clazz = event.getClass();
|
||||
String cached = forgeEventNameCache.get(clazz);
|
||||
if (cached != null)
|
||||
return cached;
|
||||
String eventName = clazz.getName();
|
||||
int i = eventName.lastIndexOf(".");
|
||||
eventName = StringUtils.uncapitalize(eventName.substring(i + 1).replace("$", ""));
|
||||
forgeEventNameCache.put(clazz, eventName);
|
||||
return eventName;
|
||||
}
|
||||
|
||||
public static void onForgeEvent(ForgeEvent ev, Event event) {
|
||||
ForgeDataScript handler = ScriptController.Instance.forgeScripts;
|
||||
if (handler.isEnabled()) {
|
||||
String eventName = event.getClass().getName();
|
||||
int i = eventName.lastIndexOf(".");
|
||||
eventName = StringUtils.uncapitalize(eventName.substring(i + 1).replace("$", ""));
|
||||
String eventName = getForgeEventName(event);
|
||||
if (event.isCancelable()) {
|
||||
ev.setCanceled(event.isCanceled());
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ public class ScriptContainer implements IScriptUnit {
|
||||
private static Method luaCall;
|
||||
private CompiledScript compScript = null;
|
||||
private final HashMap<String, ScriptObjectMirror> cachedFunctions = new HashMap<>();
|
||||
private long lastGlobalsVersion = -1;
|
||||
|
||||
/**
|
||||
* Persisted per-container language. Null means inherit from handler default.
|
||||
@@ -224,6 +225,7 @@ public class ScriptContainer implements IScriptUnit {
|
||||
if (ScriptController.Instance.lastLoaded > this.lastCreated) {
|
||||
this.lastCreated = ScriptController.Instance.lastLoaded;
|
||||
evaluated = false;
|
||||
lastGlobalsVersion = -1;
|
||||
}
|
||||
|
||||
synchronized (lock) {
|
||||
@@ -236,18 +238,24 @@ public class ScriptContainer implements IScriptUnit {
|
||||
engine.getContext().setWriter(pw);
|
||||
engine.getContext().setErrorWriter(pw);
|
||||
|
||||
// Populate bindings with API objects
|
||||
// Populate bindings with API objects (skip if globals unchanged)
|
||||
long currentGlobalsVersion = NpcAPI.engineObjectsVersion;
|
||||
boolean globalsChanged = lastGlobalsVersion != currentGlobalsVersion;
|
||||
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());
|
||||
if (globalsChanged) {
|
||||
instanceBindings.put("API", NpcAPI.Instance());
|
||||
for (Map.Entry<String, Object> objectEntry : NpcAPI.engineObjects.entrySet()) {
|
||||
instanceBindings.put(objectEntry.getKey(), objectEntry.getValue());
|
||||
}
|
||||
lastGlobalsVersion = currentGlobalsVersion;
|
||||
}
|
||||
} 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());
|
||||
if (globalsChanged) {
|
||||
engine.put("API", NpcAPI.Instance());
|
||||
for (Map.Entry<String, Object> objectEntry : NpcAPI.engineObjects.entrySet()) {
|
||||
engine.put(objectEntry.getKey(), objectEntry.getValue());
|
||||
}
|
||||
lastGlobalsVersion = currentGlobalsVersion;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,6 +336,11 @@ public class ScriptContainer implements IScriptUnit {
|
||||
return !this.getFullCode().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnknownFunction(String type) {
|
||||
return unknownFunctions.contains(type);
|
||||
}
|
||||
|
||||
public void setEngine(String scriptLanguage) {
|
||||
if (!Objects.equals(scriptLanguage, this.currentScriptLanguage)) {
|
||||
// Instance scopes share the template's engine — never create a new one
|
||||
|
||||
@@ -45,6 +45,7 @@ public class DataScript implements IScriptHandlerPacket {
|
||||
public String scriptLanguage = "ECMAScript";
|
||||
private EntityNPCInterface npc;
|
||||
public boolean enabled = false;
|
||||
private long lastGlobalsVersion = -1;
|
||||
|
||||
public ICustomNpc dummyNpc;
|
||||
public IWorld dummyWorld;
|
||||
@@ -271,9 +272,13 @@ public class DataScript implements IScriptHandlerPacket {
|
||||
engine.put(entry.getKey(), entry.getValue().value);
|
||||
}
|
||||
|
||||
engine.put("API", NpcAPI.Instance());
|
||||
for (Map.Entry<String, Object> engineObjects : NpcAPI.engineObjects.entrySet()) {
|
||||
engine.put(engineObjects.getKey(), engineObjects.getValue());
|
||||
long currentGlobalsVersion = NpcAPI.engineObjectsVersion;
|
||||
if (lastGlobalsVersion != currentGlobalsVersion) {
|
||||
engine.put("API", NpcAPI.Instance());
|
||||
for (Map.Entry<String, Object> engineObjects : NpcAPI.engineObjects.entrySet()) {
|
||||
engine.put(engineObjects.getKey(), engineObjects.getValue());
|
||||
}
|
||||
lastGlobalsVersion = currentGlobalsVersion;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class ForgeDataScript extends MultiScriptHandler {
|
||||
@@ -32,6 +33,7 @@ public class ForgeDataScript extends MultiScriptHandler {
|
||||
private static List<String> cachedHooks;
|
||||
|
||||
private long lastForgeUpdate = -1L;
|
||||
private final HashSet<String> globalUnknownEvents = new HashSet<>();
|
||||
|
||||
public ForgeDataScript() {
|
||||
}
|
||||
@@ -59,6 +61,7 @@ public class ForgeDataScript extends MultiScriptHandler {
|
||||
protected void reInitScripts() {
|
||||
lastInited = ScriptController.Instance.lastLoaded;
|
||||
lastForgeUpdate = ScriptController.Instance.lastForgeUpdate;
|
||||
globalUnknownEvents.clear();
|
||||
|
||||
for (IScriptUnit script : this.scripts) {
|
||||
if (script instanceof ScriptContainer)
|
||||
@@ -79,10 +82,25 @@ public class ForgeDataScript extends MultiScriptHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Skip events that no script tab handles
|
||||
if (globalUnknownEvents.contains(type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean anyHandled = false;
|
||||
for (IScriptUnit script : this.scripts) {
|
||||
if (script == null || script.hasErrored() || !script.hasCode())
|
||||
continue;
|
||||
boolean wasUnknown = script.isUnknownFunction(type);
|
||||
script.run(type, event);
|
||||
if (!wasUnknown || !script.isUnknownFunction(type)) {
|
||||
anyHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If no script tab handled this event type, cache it globally
|
||||
if (!anyHandled) {
|
||||
globalUnknownEvents.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,13 @@ public interface IScriptUnit {
|
||||
*/
|
||||
IScriptUnit createInstanceScope(IScriptHandler instanceHandler);
|
||||
|
||||
/**
|
||||
* Check if the given function name is known to be absent from this script unit.
|
||||
*/
|
||||
default boolean isUnknownFunction(String type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ==================== EXECUTION ====================
|
||||
|
||||
/**
|
||||
|
||||
@@ -160,6 +160,7 @@ public class NpcAPI extends AbstractNpcAPI {
|
||||
private static final Map<Integer, ScriptWorld> worldCache = new LRUHashMap<>(10);
|
||||
private static final CacheHashMap<ItemStack, CacheHashMap.CachedObject<ScriptItemStack>> scriptItemCache = new CacheHashMap<>(60 * 1000);
|
||||
public static final HashMap<String, Object> engineObjects = new HashMap<>();
|
||||
public static volatile long engineObjectsVersion = 0;
|
||||
public static final EventBus EVENT_BUS = new EventBus();
|
||||
private static AbstractNpcAPI instance = null;
|
||||
|
||||
@@ -255,10 +256,12 @@ public class NpcAPI extends AbstractNpcAPI {
|
||||
|
||||
public void addGlobalObject(String key, Object obj) {
|
||||
NpcAPI.engineObjects.put(key, obj);
|
||||
NpcAPI.engineObjectsVersion++;
|
||||
}
|
||||
|
||||
public void removeGlobalObject(String key) {
|
||||
NpcAPI.engineObjects.remove(key);
|
||||
NpcAPI.engineObjectsVersion++;
|
||||
}
|
||||
|
||||
public boolean hasGlobalObject(String key) {
|
||||
|
||||
Reference in new issue
Block a user