mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-27 08:36:38 +00:00
optimized the Lua func binding so that the script will not eval again
This commit is contained in:
parent
1fef837a97
commit
8faf8decec
@ -138,7 +138,9 @@ public class DungeonChallenge {
|
||||
getScene().getDungeonSettleObservers().forEach(o -> o.onDungeonSettle(getScene()));
|
||||
|
||||
if(!stage){
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0));
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE,
|
||||
// TODO record the time in PARAM2 and used in action
|
||||
new ScriptArgs(this.isSuccess() ? 1 : 0, 100));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public class WorldDataManager {
|
||||
}
|
||||
|
||||
public synchronized void load(){
|
||||
try(InputStream is = DataLoader.load("ChestReward.json", false); InputStreamReader isr = new InputStreamReader(is)) {
|
||||
try(InputStream is = DataLoader.load("ChestReward.json"); InputStreamReader isr = new InputStreamReader(is)) {
|
||||
List<ChestReward> chestReward = Grasscutter.getGsonFactory().fromJson(
|
||||
isr,
|
||||
TypeToken.getParameterized(List.class, ChestReward.class).getType());
|
||||
|
@ -20,16 +20,11 @@ import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptException;
|
||||
import java.util.*;
|
||||
|
||||
public class SceneScriptManager {
|
||||
private final Scene scene;
|
||||
private final ScriptLib scriptLib;
|
||||
private final LuaValue scriptLibLua;
|
||||
private final Map<String, Integer> variables;
|
||||
private Bindings bindings;
|
||||
private SceneMeta meta;
|
||||
private boolean isInit;
|
||||
/**
|
||||
@ -50,8 +45,6 @@ public class SceneScriptManager {
|
||||
private Int2ObjectMap<Set<SceneGroup>> loadedGroupSetPerBlock;
|
||||
public SceneScriptManager(Scene scene) {
|
||||
this.scene = scene;
|
||||
this.scriptLib = new ScriptLib(this);
|
||||
this.scriptLibLua = CoerceJavaToLua.coerce(this.scriptLib);
|
||||
this.triggers = new HashMap<>();
|
||||
this.currentTriggers = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@ -74,18 +67,6 @@ public class SceneScriptManager {
|
||||
return scene;
|
||||
}
|
||||
|
||||
public ScriptLib getScriptLib() {
|
||||
return scriptLib;
|
||||
}
|
||||
|
||||
public LuaValue getScriptLibLua() {
|
||||
return scriptLibLua;
|
||||
}
|
||||
|
||||
public Bindings getBindings() {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public SceneConfig getConfig() {
|
||||
if(!isInit){
|
||||
return null;
|
||||
@ -162,11 +143,6 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
// Create bindings
|
||||
bindings = ScriptLoader.getEngine().createBindings();
|
||||
// Set variables
|
||||
bindings.put("ScriptLib", getScriptLib());
|
||||
|
||||
var meta = ScriptLoader.getSceneMeta(getScene().getId());
|
||||
if (meta == null){
|
||||
return;
|
||||
@ -186,14 +162,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
public void loadGroupFromScript(SceneGroup group) {
|
||||
group.load(getScene().getId(), meta.context);
|
||||
|
||||
try {
|
||||
// build the trigger for this scene
|
||||
group.getScript().eval(getBindings());
|
||||
} catch (ScriptException e) {
|
||||
Grasscutter.getLogger().error("Could not build the trigger for this scene", e);
|
||||
}
|
||||
group.load(getScene().getId());
|
||||
|
||||
group.variables.forEach(var -> this.getVariables().put(var.name, var.value));
|
||||
this.sceneGroups.put(group.id, group);
|
||||
@ -284,47 +253,55 @@ public class SceneScriptManager {
|
||||
// Events
|
||||
|
||||
public void callEvent(int eventType, ScriptArgs params) {
|
||||
for (SceneTrigger trigger : this.getTriggersByEvent(eventType)) {
|
||||
scriptLib.setCurrentGroup(trigger.currentGroup);
|
||||
LuaValue condition = null;
|
||||
|
||||
if (trigger.condition != null && !trigger.condition.isEmpty()) {
|
||||
condition = (LuaValue) this.getBindings().get(trigger.condition);
|
||||
}
|
||||
|
||||
LuaValue ret = LuaValue.TRUE;
|
||||
|
||||
if (condition != null) {
|
||||
LuaValue args = LuaValue.NIL;
|
||||
|
||||
if (params != null) {
|
||||
args = CoerceJavaToLua.coerce(params);
|
||||
}
|
||||
try{
|
||||
ScriptLoader.getScriptLib().setSceneScriptManager(this);
|
||||
for (SceneTrigger trigger : this.getTriggersByEvent(eventType)) {
|
||||
try{
|
||||
ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup);
|
||||
|
||||
ScriptLib.logger.trace("Call Condition Trigger {}", trigger);
|
||||
ret = safetyCall(trigger.condition, condition, args);
|
||||
}
|
||||
|
||||
if (ret.isboolean() && ret.checkboolean()) {
|
||||
if(trigger.action == null || trigger.action.isEmpty()){
|
||||
return;
|
||||
LuaValue ret = callScriptFunc(trigger.condition, trigger.currentGroup, params);
|
||||
Grasscutter.getLogger().trace("Call Condition Trigger {}", trigger.condition);
|
||||
|
||||
if (ret.isboolean() && ret.checkboolean()) {
|
||||
// the SetGroupVariableValueByGroup in tower need the param to record the first stage time
|
||||
callScriptFunc(trigger.action, trigger.currentGroup, params);
|
||||
Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action);
|
||||
}
|
||||
//TODO some ret may not bool
|
||||
|
||||
}finally {
|
||||
ScriptLoader.getScriptLib().removeCurrentGroup();
|
||||
}
|
||||
ScriptLib.logger.trace("Call Action Trigger {}", trigger);
|
||||
LuaValue action = (LuaValue) this.getBindings().get(trigger.action);
|
||||
// TODO impl the param of SetGroupVariableValueByGroup
|
||||
var arg = new ScriptArgs();
|
||||
arg.param2 = 100;
|
||||
var args = CoerceJavaToLua.coerce(arg);
|
||||
safetyCall(trigger.action, action, args);
|
||||
}
|
||||
//TODO some ret may not bool
|
||||
scriptLib.removeCurrentGroup();
|
||||
}finally {
|
||||
// make sure it is removed
|
||||
ScriptLoader.getScriptLib().removeSceneScriptManager();
|
||||
}
|
||||
}
|
||||
|
||||
public LuaValue callScriptFunc(String funcName, SceneGroup group, ScriptArgs params){
|
||||
LuaValue funcLua = null;
|
||||
if (funcName != null && !funcName.isEmpty()) {
|
||||
funcLua = (LuaValue) group.getBindings().get(funcName);
|
||||
}
|
||||
|
||||
LuaValue ret = LuaValue.TRUE;
|
||||
|
||||
if (funcLua != null) {
|
||||
LuaValue args = LuaValue.NIL;
|
||||
|
||||
if (params != null) {
|
||||
args = CoerceJavaToLua.coerce(params);
|
||||
}
|
||||
|
||||
ret = safetyCall(funcName, funcLua, args);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public LuaValue safetyCall(String name, LuaValue func, LuaValue args){
|
||||
try{
|
||||
return func.call(this.getScriptLibLua(), args);
|
||||
return func.call(ScriptLoader.getScriptLibLua(), args);
|
||||
}catch (LuaError error){
|
||||
ScriptLib.logger.error("[LUA] call trigger failed {},{},{}",name,args,error.getMessage());
|
||||
return LuaValue.valueOf(-1);
|
||||
|
@ -10,6 +10,7 @@ import emu.grasscutter.scripts.data.SceneRegion;
|
||||
import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetStateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify;
|
||||
import io.netty.util.concurrent.FastThreadLocal;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.slf4j.Logger;
|
||||
@ -20,15 +21,24 @@ import java.util.Optional;
|
||||
|
||||
public class ScriptLib {
|
||||
public static final Logger logger = LoggerFactory.getLogger(ScriptLib.class);
|
||||
private final SceneScriptManager sceneScriptManager;
|
||||
|
||||
public ScriptLib(SceneScriptManager sceneScriptManager) {
|
||||
this.sceneScriptManager = sceneScriptManager;
|
||||
this.currentGroup = new ThreadLocal<>();
|
||||
private final FastThreadLocal<SceneScriptManager> sceneScriptManager;
|
||||
private final FastThreadLocal<SceneGroup> currentGroup;
|
||||
public ScriptLib() {
|
||||
this.sceneScriptManager = new FastThreadLocal<>();
|
||||
this.currentGroup = new FastThreadLocal<>();
|
||||
}
|
||||
|
||||
public void setSceneScriptManager(SceneScriptManager sceneScriptManager){
|
||||
this.sceneScriptManager.set(sceneScriptManager);
|
||||
}
|
||||
|
||||
public void removeSceneScriptManager(){
|
||||
this.sceneScriptManager.remove();
|
||||
}
|
||||
|
||||
public SceneScriptManager getSceneScriptManager() {
|
||||
return sceneScriptManager;
|
||||
// normally not null
|
||||
return Optional.of(sceneScriptManager.get()).get();
|
||||
}
|
||||
|
||||
private String printTable(LuaTable table){
|
||||
@ -40,13 +50,11 @@ public class ScriptLib {
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
private final ThreadLocal<SceneGroup> currentGroup;
|
||||
public void setCurrentGroup(SceneGroup currentGroup){
|
||||
logger.debug("current {}", currentGroup);
|
||||
this.currentGroup.set(currentGroup);
|
||||
}
|
||||
public Optional<SceneGroup> getCurrentGroup(){
|
||||
return Optional.ofNullable(this.currentGroup.get());
|
||||
return Optional.of(this.currentGroup.get());
|
||||
}
|
||||
public void removeCurrentGroup(){
|
||||
this.currentGroup.remove();
|
||||
|
@ -29,6 +29,8 @@ public class ScriptLoader {
|
||||
private static ScriptEngineFactory factory;
|
||||
private static String fileType;
|
||||
private static Serializer serializer;
|
||||
private static ScriptLib scriptLib;
|
||||
private static LuaValue scriptLibLua;
|
||||
/**
|
||||
* suggest GC to remove it if the memory is less
|
||||
*/
|
||||
@ -68,6 +70,10 @@ public class ScriptLoader {
|
||||
ctx.globals.set("EventType", CoerceJavaToLua.coerce(new EventType())); // TODO - make static class to avoid instantiating a new class every scene
|
||||
ctx.globals.set("GadgetState", CoerceJavaToLua.coerce(new ScriptGadgetState()));
|
||||
ctx.globals.set("RegionShape", CoerceJavaToLua.coerce(new ScriptRegionShape()));
|
||||
|
||||
scriptLib = new ScriptLib();
|
||||
scriptLibLua = CoerceJavaToLua.coerce(scriptLib);
|
||||
ctx.globals.set("ScriptLib", scriptLibLua);
|
||||
}
|
||||
|
||||
public static ScriptEngine getEngine() {
|
||||
@ -82,6 +88,14 @@ public class ScriptLoader {
|
||||
return serializer;
|
||||
}
|
||||
|
||||
public static ScriptLib getScriptLib() {
|
||||
return scriptLib;
|
||||
}
|
||||
|
||||
public static LuaValue getScriptLibLua() {
|
||||
return scriptLibLua;
|
||||
}
|
||||
|
||||
public static <T> Optional<T> tryGet(SoftReference<T> softReference){
|
||||
try{
|
||||
return Optional.ofNullable(softReference.get());
|
||||
|
@ -10,12 +10,11 @@ import javax.script.Bindings;
|
||||
import javax.script.CompiledScript;
|
||||
import javax.script.ScriptException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static emu.grasscutter.Configuration.*;
|
||||
import static emu.grasscutter.Configuration.SCRIPT;
|
||||
|
||||
@ToString
|
||||
@Setter
|
||||
@ -40,6 +39,7 @@ public class SceneGroup {
|
||||
|
||||
private transient boolean loaded; // Not an actual variable in the scripts either
|
||||
private transient CompiledScript script;
|
||||
private transient Bindings bindings;
|
||||
|
||||
public boolean isLoaded() {
|
||||
return loaded;
|
||||
@ -65,13 +65,19 @@ public class SceneGroup {
|
||||
return suites.get(index - 1);
|
||||
}
|
||||
|
||||
public SceneGroup load(int sceneId, Bindings bindings){
|
||||
public Bindings getBindings() {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public SceneGroup load(int sceneId){
|
||||
if(loaded){
|
||||
return this;
|
||||
}
|
||||
// Set flag here so if there is no script, we dont call this function over and over again.
|
||||
setLoaded(true);
|
||||
|
||||
this.bindings = ScriptLoader.getEngine().createBindings();
|
||||
|
||||
CompiledScript cs = ScriptLoader.getScriptByPath(
|
||||
SCRIPT("Scene/" + sceneId + "/scene" + sceneId + "_group" + id + "." + ScriptLoader.getScriptType()));
|
||||
|
||||
|
@ -87,6 +87,9 @@ public class LuaSerializer implements Serializer {
|
||||
|
||||
object = (T) constructorCache.get(type).newInstance();
|
||||
|
||||
if(table == null){
|
||||
return object;
|
||||
}
|
||||
LuaValue[] keys = table.keys();
|
||||
for (LuaValue k : keys) {
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user