[Cleanup] Apply/handle SonarCloud warnings and some other cleanups

This commit is contained in:
hartie95 2023-07-29 20:44:10 +02:00
parent 9fec81914f
commit bd8063b867
18 changed files with 330 additions and 488 deletions

View File

@ -790,7 +790,7 @@ public class SceneScriptManager {
return BooleanLuaValue.FALSE;
}
val context = script.getEngine().getGroupEventLuaContext(group, params, this);
val context = script.getGroupEventLuaContext(group, params, this);
try{
return script.callMethod(funcName, context, params);
} catch (RuntimeException | ScriptException | NoSuchMethodException error){

View File

@ -29,7 +29,6 @@ import emu.grasscutter.scripts.lua_engine.ControllerLuaContext;
import emu.grasscutter.scripts.lua_engine.GroupEventLuaContext;
import emu.grasscutter.scripts.lua_engine.LuaContext;
import emu.grasscutter.scripts.lua_engine.LuaTable;
import emu.grasscutter.scripts.lua_engine.luaj.GroupEventLuaJContext;
import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.utils.Position;
import lombok.val;
@ -641,7 +640,7 @@ public class ScriptLib {
return 0;
}
public static int CreateMonster(GroupEventLuaJContext context, Object rawTable){
public static int CreateMonster(GroupEventLuaContext context, Object rawTable){
val table = context.getEngine().getTable(rawTable);
logger.debug("[LUA] Call CreateMonster with {}",
printTable(table));
@ -1510,19 +1509,23 @@ public class ScriptLib {
private static int killGroupEntityWithTable(SceneScriptManager sceneScriptManager, SceneGroup group, LuaTable lists){
// get targets
var monsterList = lists.getTable("monsters");
var gadgetList = lists.getTable("gadgets");
val monsterList = lists.getTable("monsters");
val gadgetList = lists.getTable("gadgets");
val monsterSize = monsterList != null ? monsterList.getSize() : 0;
val gadgetSize = gadgetList != null ? gadgetList.getSize() : 0;
int[] targets = new int[monsterSize + gadgetSize];
int targetsIndex = 0;
if(monsterList != null) {
for (int i = 1; i <= monsterSize; i++, targetsIndex++) {
targets[targetsIndex] = monsterList.optInt(i, -1);
}
}
if(gadgetList != null) {
for (int i = 1; i <= gadgetSize; i++, targetsIndex++) {
targets[targetsIndex] = gadgetList.optInt(i, -1);
}
}
// kill targets if exists
for(int cfgId : targets){

View File

@ -12,6 +12,7 @@ import emu.grasscutter.scripts.lua_engine.mock_results.IntLuaValue;
import javax.annotation.Nonnull;
import javax.script.ScriptException;
import java.util.Arrays;
public class EntityController {
private transient LuaScript entityController;
@ -47,18 +48,19 @@ public class EntityController {
if (entityController.hasMethod(funcName)) {
try {
//ScriptLoader.getScriptLib().setCurrentEntity(entity);
ControllerLuaContext context = entityController.getEngine().getControllerLuaContext((EntityGadget) entity);
ControllerLuaContext context = entityController.getControllerLuaContext((EntityGadget) entity);
Object[] newArgs = new Object[args.length + 1];
newArgs[0] = context;
System.arraycopy(args, 0, newArgs, 1, args.length);
return entityController.callMethod(funcName, newArgs);
} catch (RuntimeException | ScriptException | NoSuchMethodException error) {
ScriptLib.logger.error("[LUA] call function failed in gadget {} with {} ,{}", entity.getEntityTypeId(), funcName, args.toString(), error);
ScriptLib.logger.error("[LUA] call function failed in gadget {} with {} ,{}",
entity.getEntityTypeId(), funcName, Arrays.toString(args), error);
ret = IntLuaValue.N_ONE;
}
} else if (!funcName.equals("OnTimer")) {
ScriptLib.logger.error("[LUA] unknown func in gadget {} with {} {}", entity.getEntityTypeId(), funcName, args.toString());
ScriptLib.logger.error("[LUA] unknown func in gadget {} with {} {}",
entity.getEntityTypeId(), funcName, Arrays.toString(args));
}
return ret;
}

View File

@ -1,7 +1,21 @@
package emu.grasscutter.scripts.lua_engine;
import emu.grasscutter.game.entity.EntityGadget;
import lombok.Getter;
public interface ControllerLuaContext extends LuaContext {
EntityGadget getEntity();
public class ControllerLuaContext implements LuaContext {
@Getter
final private EntityGadget gadget;
@Getter(onMethod = @__(@Override))
final private LuaEngine engine;
public ControllerLuaContext(LuaEngine engine, EntityGadget gadget) {
this.gadget = gadget;
this.engine = engine;
}
public EntityGadget getEntity() {
return gadget;
}
}

View File

@ -3,11 +3,31 @@ package emu.grasscutter.scripts.lua_engine;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.ScriptArgs;
import lombok.Getter;
public interface GroupEventLuaContext extends LuaContext {
SceneGroup getCurrentGroup();
public class GroupEventLuaContext implements LuaContext {
@Getter
final private SceneGroup groupInstance;
@Getter
final private ScriptArgs args;
ScriptArgs getArgs();
final private SceneScriptManager scriptManager;
SceneScriptManager getSceneScriptManager();
@Getter(onMethod = @__(@Override))
final private LuaEngine engine;
public GroupEventLuaContext(LuaEngine engine, SceneGroup groupInstance, ScriptArgs args, SceneScriptManager scriptManager) {
this.groupInstance = groupInstance;
this.args = args;
this.scriptManager = scriptManager;
this.engine = engine;
}
public SceneGroup getCurrentGroup() {
return groupInstance;
}
public SceneScriptManager getSceneScriptManager() {
return scriptManager;
}
}

View File

@ -24,10 +24,6 @@ public interface LuaEngine {
@Nullable
LuaScript getScript(String scriptName, ScriptType scriptType);
ControllerLuaContext getControllerLuaContext(EntityGadget gadget);
GroupEventLuaContext getGroupEventLuaContext(SceneGroup sceneGroupInstance, ScriptArgs args, SceneScriptManager scriptManager);
LuaTable getTable(Object table);
LuaTable createTable();

View File

@ -1,5 +1,10 @@
package emu.grasscutter.scripts.lua_engine;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.ScriptArgs;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.script.ScriptException;
@ -21,4 +26,12 @@ public interface LuaScript {
<T> Map<String, T> getGlobalVariableMap(String name, Class<T> type);
LuaEngine getEngine();
default ControllerLuaContext getControllerLuaContext(EntityGadget gadget){
return new ControllerLuaContext(getEngine(), gadget);
}
default GroupEventLuaContext getGroupEventLuaContext(SceneGroup sceneGroupInstance, ScriptArgs args, SceneScriptManager scriptManager){
return new GroupEventLuaContext(getEngine(), sceneGroupInstance, args, scriptManager);
}
}

View File

@ -1,14 +1,83 @@
package emu.grasscutter.scripts.lua_engine;
import java.util.List;
import java.util.Map;
import com.esotericsoftware.reflectasm.ConstructorAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public interface Serializer {
public abstract class Serializer {
public <T> List<T> toList(Class<T> type, Object obj);
protected static final Map<Class<?>, MethodAccess> methodAccessCache = new ConcurrentHashMap<>();
protected static final Map<Class<?>, ConstructorAccess<?>> constructorCache = new ConcurrentHashMap<>();
protected static final Map<Class<?>, Map<String, FieldMeta>> fieldMetaCache = new ConcurrentHashMap<>();
public abstract <T> List<T> toList(Class<T> type, Object obj);
public <T> T toObject(Class<T> type, Object obj);
public abstract <T> T toObject(Class<T> type, Object obj);
public <T> Map<String,T> toMap(Class<T> type, Object obj);
public abstract <T> Map<String,T> toMap(Class<T> type, Object obj);
protected String getSetterName(String fieldName) {
if (fieldName == null || fieldName.length() == 0) {
return null;
}
if (fieldName.length() == 1) {
return "set" + fieldName.toUpperCase();
}
return "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
}
protected <T> Map<String, FieldMeta> cacheType(Class<T> type) {
if (fieldMetaCache.containsKey(type)) {
return fieldMetaCache.get(type);
}
if (!constructorCache.containsKey(type)) {
constructorCache.putIfAbsent(type, ConstructorAccess.get(type));
}
var methodAccess = Optional.ofNullable(methodAccessCache.get(type)).orElse(MethodAccess.get(type));
methodAccessCache.putIfAbsent(type, methodAccess);
var fieldMetaMap = new HashMap<String, FieldMeta>();
var methodNameSet = new HashSet<>(Arrays.stream(methodAccess.getMethodNames()).toList());
Arrays.stream(type.getDeclaredFields())
.filter(field -> methodNameSet.contains(getSetterName(field.getName())))
.forEach(field -> {
var setter = getSetterName(field.getName());
var index = methodAccess.getIndex(setter);
fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType(), field));
});
Arrays.stream(type.getFields())
.filter(field -> !fieldMetaMap.containsKey(field.getName()))
.filter(field -> methodNameSet.contains(getSetterName(field.getName())))
.forEach(field -> {
var setter = getSetterName(field.getName());
var index = methodAccess.getIndex(setter);
fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType(), field));
});
fieldMetaCache.put(type, fieldMetaMap);
return fieldMetaMap;
}
@Data
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
protected class FieldMeta {
String name;
String setter;
int index;
Class<?> type;
@Nullable
Field field;
}
}

View File

@ -1,25 +1,19 @@
package emu.grasscutter.scripts.lua_engine.jnlua;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.constants.IntValueEnum;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.scripts.lua_engine.*;
import emu.grasscutter.scripts.lua_engine.LuaEngine;
import emu.grasscutter.scripts.lua_engine.LuaScript;
import emu.grasscutter.scripts.lua_engine.ScriptType;
import emu.grasscutter.scripts.lua_engine.Serializer;
import emu.grasscutter.scripts.lua_engine.luaj.ControllerLuaJContext;
import emu.grasscutter.scripts.lua_engine.luaj.GroupEventLuaJContext;
import emu.grasscutter.scripts.lua_engine.luaj.LuaJScript;
import emu.grasscutter.utils.FileUtils;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
import org.luaj.vm2.LuaTable;
import org.terasology.jnlua.JavaFunction;
import org.terasology.jnlua.LuaState;
import org.terasology.jnlua.script.LuaBindings;
import javax.script.*;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
@ -30,12 +24,12 @@ import java.util.HashMap;
import java.util.Map;
public class JNLuaEngine implements LuaEngine {
@Getter private final ScriptEngineManager manager;
@Getter
private final ScriptEngineManager manager;
@Getter(onMethod = @__(@Override))
private final Serializer serializer;
//@Getter(onMethod = @__(@Override))
//private final ScriptEngine engine;
@Getter private final SimpleBindings bindings;
@Getter
private final SimpleBindings bindings;
public JNLuaEngine() {
manager = new ScriptEngineManager();
@ -57,7 +51,6 @@ public class JNLuaEngine implements LuaEngine {
table.put(e.name().toUpperCase(), e.ordinal());
});
bindings.put(name, table);
//ScriptBinding.coerce(engine, name, table);
return true;
}
@ -69,7 +62,6 @@ public class JNLuaEngine implements LuaEngine {
table.put(e.name().toUpperCase(), e.getValue());
});
bindings.put(name, table);
//ScriptBinding.coerce(engine, name, table);
return true;
}
@ -77,7 +69,6 @@ public class JNLuaEngine implements LuaEngine {
public boolean addGlobalStaticClass(String name, Class<?> staticClass) {
try {
bindings.put(name, staticClass.getConstructor().newInstance());
//ScriptBinding.coerce(engine, name, staticClass.getConstructor().newInstance());
return true;
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchMethodException e) {
@ -89,9 +80,9 @@ public class JNLuaEngine implements LuaEngine {
@Override
public boolean addObject(String name, Object object) {
bindings.put(name, object);
//ScriptBinding.coerce(engine, name, object);
return false;
}
@Nullable
@Override
public LuaScript getScript(String scriptName, ScriptType scriptType) {
@ -100,23 +91,11 @@ public class JNLuaEngine implements LuaEngine {
try {
return new JNLuaScript(this, scriptPath);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ScriptException e) {
} catch (IOException | ScriptException e) {
throw new RuntimeException(e);
}
}
@Override
public ControllerLuaContext getControllerLuaContext(EntityGadget gadget) {
return new ControllerLuaJContext(this, gadget);
}
@Override
public GroupEventLuaContext getGroupEventLuaContext(SceneGroup sceneGroupInstance, ScriptArgs args, SceneScriptManager scriptManager) {
return new GroupEventLuaJContext(this, sceneGroupInstance, args, scriptManager);
}
@Override
public emu.grasscutter.scripts.lua_engine.LuaTable getTable(Object table) {
return new JNLuaTable((AbstractMap<?, ?>) table);
@ -124,6 +103,6 @@ public class JNLuaEngine implements LuaEngine {
@Override
public emu.grasscutter.scripts.lua_engine.LuaTable createTable() {
return new JNLuaTable((AbstractMap<?, ?>) new HashMap<>());
return new JNLuaTable(new HashMap<>());
}
}

View File

@ -2,7 +2,6 @@ package emu.grasscutter.scripts.lua_engine.jnlua;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.ScriptLib;
import emu.grasscutter.scripts.lua_engine.LuaContext;
import emu.grasscutter.scripts.lua_engine.LuaEngine;
import emu.grasscutter.scripts.lua_engine.LuaScript;
import emu.grasscutter.scripts.lua_engine.LuaValue;
@ -61,8 +60,7 @@ public class JNLuaScript implements LuaScript {
@Override
public void convertJavaObject(LuaState luaState, Object o) {
if(o instanceof Map<?,?>){
val fields = (Map<?, ?>) o;
if (o instanceof Map<?, ?> fields) {
val first = fields.entrySet().stream().findFirst();
if (first.isPresent() && first.get().getKey() instanceof String && first.get().getValue() instanceof Integer) {
luaState.newTable();
@ -72,9 +70,8 @@ public class JNLuaScript implements LuaScript {
}
return;
}
} else if (o instanceof ScriptLib){
} else if (o instanceof ScriptLib lib) {
luaState.newTable();
val lib = (ScriptLib) o;
val methods = lib.getClass().getMethods();
Arrays.stream(methods).forEach(m -> {
val isStatic = Modifier.isStatic(m.getModifiers());
@ -141,6 +138,7 @@ public class JNLuaScript implements LuaScript {
return 0;
});
}
@Override
public boolean hasMethod(@NotNull String methodName) {
return binding.containsKey(methodName);

View File

@ -1,39 +1,16 @@
package emu.grasscutter.scripts.lua_engine.jnlua;
import com.esotericsoftware.reflectasm.ConstructorAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import emu.grasscutter.scripts.ScriptUtils;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.lua_engine.Serializer;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import org.terasology.jnlua.LuaValueProxy;
import org.terasology.jnlua.util.AbstractTableMap;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
public class JNLuaSerializer implements Serializer {
private final static Map<Class<?>, MethodAccess> methodAccessCache = new ConcurrentHashMap<>();
private final static Map<Class<?>, ConstructorAccess<?>> constructorCache = new ConcurrentHashMap<>();
private final static Map<Class<?>, Map<String, FieldMeta>> fieldMetaCache = new ConcurrentHashMap<>();
public class JNLuaSerializer extends Serializer {
private final ReentrantLock lock = new ReentrantLock();
// ...
@Override
public <T> List<T> toList(Class<T> type, Object obj) {
return serializeList(type, (LuaValueProxy) obj);
}
@Override
public <T> T toObject(Class<T> type, Object obj) {
return serialize(type, (LuaValueProxy) obj);
}
@Override
public <T> Map<String,T> toMap(Class<T> type, Object obj) {return serializeMap(type ,(LuaValueProxy) obj);}
public static Integer getInt(Object value) {
if (value instanceof Integer l) {
@ -53,6 +30,39 @@ public class JNLuaSerializer implements Serializer {
return 0f;
}
// ...
@Override
public <T> List<T> toList(Class<T> type, Object obj) {
return serializeList(type, (LuaValueProxy) obj);
}
@Override
public <T> T toObject(Class<T> type, Object obj) {
return serialize(type, (LuaValueProxy) obj);
}
@Override
public <T> Map<String, T> toMap(Class<T> type, Object obj) {
return serializeMap(type, (LuaValueProxy) obj);
}
private <T> T objectToClass(Class<T> type, Object value) {
T object = null;
if (value instanceof Integer) {
object = (T) getInt(value);
} else if (value instanceof Double) {
object = (T) getFloat(value);
} else if (value instanceof String) {
object = (T) value;
} else if (value instanceof Boolean) {
object = (T) value;
} else {
object = serialize(type, (LuaValueProxy) value);
}
return object;
}
public <T> List<T> serializeList(Class<T> type, LuaValueProxy table) {
List<T> list = new ArrayList<>();
@ -66,19 +76,7 @@ public class JNLuaSerializer implements Serializer {
try {
var keyValue = k.getValue();
T object = null;
if (keyValue instanceof Integer) {
object = (T) getInt(keyValue);
} else if (keyValue instanceof Double) {
object = (T) getFloat(keyValue);
} else if (keyValue instanceof String) {
object = (T) keyValue;
} else if (keyValue instanceof Boolean) {
object = (T) keyValue;
} else {
object = serialize(type, (LuaValueProxy) keyValue);
}
T object = objectToClass(type, keyValue);
if (object != null) {
list.add(object);
@ -88,7 +86,7 @@ public class JNLuaSerializer implements Serializer {
}
}
} catch (Exception e) {
e.printStackTrace();
Grasscutter.getLogger().error("Exception serializing list", e);
}
return list;
@ -102,7 +100,7 @@ public class JNLuaSerializer implements Serializer {
Class<T> listType = (Class<T>) type.getTypeParameters()[0].getClass();
return (T) serializeList(listType, table);
} catch (Exception e) {
e.printStackTrace();
Grasscutter.getLogger().error("Exception serializing", e);
return null;
}
}
@ -125,7 +123,7 @@ public class JNLuaSerializer implements Serializer {
var tableObj = (AbstractTableMap<String>) table;
for (var k : tableObj.entrySet()) {
try {
var keyName = k.getKey().toString();
var keyName = k.getKey();
if (!fieldMetaMap.containsKey(keyName)) {
continue;
}
@ -133,30 +131,28 @@ public class JNLuaSerializer implements Serializer {
var fieldMeta = fieldMetaMap.get(keyName);
var keyValue = k.getValue();
if (fieldMeta.getType().equals(float.class)) {
methodAccess.invoke(object, fieldMeta.index, getFloat(keyValue));
methodAccess.invoke(object, fieldMeta.getIndex(), getFloat(keyValue));
} else if (fieldMeta.getType().equals(double.class)) {
methodAccess.invoke(object, fieldMeta.index, (keyValue));
methodAccess.invoke(object, fieldMeta.getIndex(), (keyValue));
} else if (fieldMeta.getType().equals(int.class)) {
methodAccess.invoke(object, fieldMeta.index, getInt(keyValue));
methodAccess.invoke(object, fieldMeta.getIndex(), getInt(keyValue));
} else if (fieldMeta.getType().equals(String.class)) {
methodAccess.invoke(object, fieldMeta.index, keyValue);
methodAccess.invoke(object, fieldMeta.getIndex(), keyValue);
} else if (fieldMeta.getType().equals(boolean.class)) {
methodAccess.invoke(object, fieldMeta.index, keyValue);
methodAccess.invoke(object, fieldMeta.getIndex(), keyValue);
} else if (fieldMeta.getType().equals(List.class)) {
List<T> listObj = tableObj.get(k.getKey(), List.class);
methodAccess.invoke(object, fieldMeta.index, listObj);
methodAccess.invoke(object, fieldMeta.getIndex(), listObj);
} else {
methodAccess.invoke(object, fieldMeta.index, serialize(fieldMeta.getType(), (LuaValueProxy) keyValue));
methodAccess.invoke(object, fieldMeta.getIndex(), serialize(fieldMeta.getType(), (LuaValueProxy) keyValue));
//methodAccess.invoke(object, fieldMeta.index, keyValue);
}
} catch (Exception ex) {
ex.printStackTrace();
continue;
Grasscutter.getLogger().error("Exception serializing", ex);
}
}
} catch (Exception e) {
//Grasscutter.getLogger().info(ScriptSys.ScriptUtils.toMap(table).toString());
e.printStackTrace();
Grasscutter.getLogger().error("Exception serializing", e);
}
return object;
@ -176,19 +172,7 @@ public class JNLuaSerializer implements Serializer {
try {
var keyValue = k.getValue();
T object = null;
if (keyValue instanceof Integer) {
object = (T) getInt(keyValue);
} else if (keyValue instanceof Double) {
object = (T) getFloat(keyValue);
} else if (keyValue instanceof String) {
object = (T) keyValue;
} else if (keyValue instanceof Boolean) {
object = (T) keyValue;
} else {
object = serialize(type, (LuaValueProxy) keyValue);
}
T object = objectToClass(type, keyValue);
if (object != null) {
map.put(k.getKey(), object);
@ -198,73 +182,9 @@ public class JNLuaSerializer implements Serializer {
}
}
} catch (Exception e) {
e.printStackTrace();
Grasscutter.getLogger().error("Exception serializing map", e);
}
return map;
}
public <T> Map<String, FieldMeta> cacheType(Class<T> type) {
if (fieldMetaCache.containsKey(type)) {
return fieldMetaCache.get(type);
}
if (!constructorCache.containsKey(type)) {
constructorCache.putIfAbsent(type, ConstructorAccess.get(type));
}
var methodAccess = Optional.ofNullable(methodAccessCache.get(type)).orElse(MethodAccess.get(type));
methodAccessCache.putIfAbsent(type, methodAccess);
var fieldMetaMap = new HashMap<String, FieldMeta>();
var methodNameSet = new HashSet<>(Arrays.stream(methodAccess.getMethodNames()).toList());
Arrays.stream(type.getDeclaredFields())
.filter(field -> methodNameSet.contains(getSetterName(field.getName())))
.forEach(field -> {
var setter = getSetterName(field.getName());
var index = methodAccess.getIndex(setter);
fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType()));
});
Arrays.stream(type.getFields())
.filter(field -> !fieldMetaMap.containsKey(field.getName()))
.filter(field -> methodNameSet.contains(getSetterName(field.getName())))
.forEach(field -> {
var setter = getSetterName(field.getName());
var index = methodAccess.getIndex(setter);
fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType()));
});
fieldMetaCache.put(type, fieldMetaMap);
return fieldMetaMap;
}
public String getSetterName(String fieldName) {
if (fieldName == null || fieldName.length() == 0) {
return null;
}
if (fieldName.length() == 1) {
return "set" + fieldName.toUpperCase();
}
return "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
}
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
static class FieldMeta {
String name;
String setter;
int index;
Class<?> type;
public FieldMeta(String name, String setter, int index, Class<?> type) {
this.name = name;
this.setter = setter;
this.index = index;
this.type = type;
}
Class<?> getType() {
return type;
}
}
}

View File

@ -1,25 +0,0 @@
package emu.grasscutter.scripts.lua_engine.luaj;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.scripts.lua_engine.ControllerLuaContext;
import emu.grasscutter.scripts.lua_engine.LuaEngine;
import lombok.Getter;
public class ControllerLuaJContext implements ControllerLuaContext {
@Getter
final private EntityGadget gadget;
@Getter(onMethod = @__(@Override))
final private LuaEngine engine;
public ControllerLuaJContext(LuaEngine engine, EntityGadget gadget) {
this.gadget = gadget;
this.engine = engine;
}
@Override
public EntityGadget getEntity() {
return gadget;
}
}

View File

@ -1,39 +0,0 @@
package emu.grasscutter.scripts.lua_engine.luaj;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.scripts.lua_engine.GroupEventLuaContext;
import emu.grasscutter.scripts.lua_engine.LuaEngine;
import lombok.Getter;
public class GroupEventLuaJContext implements GroupEventLuaContext {
@Getter
final private SceneGroup groupInstance;
@Getter(onMethod = @__(@Override))
final private ScriptArgs args;
final private SceneScriptManager scriptManager;
@Getter(onMethod = @__(@Override))
final private LuaEngine engine;
public GroupEventLuaJContext(LuaEngine engine, SceneGroup groupInstance, ScriptArgs args, SceneScriptManager scriptManager) {
this.groupInstance = groupInstance;
this.args = args;
this.scriptManager = scriptManager;
this.engine = engine;
}
@Override
public SceneGroup getCurrentGroup() {
return groupInstance;
}
@Override
public SceneScriptManager getSceneScriptManager() {
return scriptManager;
}
}

View File

@ -1,12 +1,10 @@
package emu.grasscutter.scripts.lua_engine.luaj;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.constants.IntValueEnum;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.scripts.lua_engine.*;
import emu.grasscutter.scripts.lua_engine.LuaEngine;
import emu.grasscutter.scripts.lua_engine.LuaScript;
import emu.grasscutter.scripts.lua_engine.ScriptType;
import emu.grasscutter.utils.FileUtils;
import lombok.Getter;
import lombok.val;
@ -17,7 +15,6 @@ import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import org.luaj.vm2.script.LuajContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.*;
@ -28,17 +25,16 @@ import java.util.Arrays;
public class LuaJEngine implements LuaEngine {
private final ScriptEngineManager manager;
private final ScriptEngineFactory factory;
private final LuajContext context;
@Getter private final ScriptEngine engine;
@Getter
private final ScriptEngine engine;
@Getter(onMethod = @__(@Override))
private final LuaJSerializer serializer;
public LuaJEngine() {
manager = new ScriptEngineManager();
engine = manager.getEngineByName("luaj");
factory = getEngine().getFactory();
serializer = new LuaJSerializer();
context = (LuajContext) engine.getContext();
@ -115,23 +111,11 @@ public class LuaJEngine implements LuaEngine {
try {
return new LuaJScript(this, scriptPath);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ScriptException e) {
} catch (IOException | ScriptException e) {
throw new RuntimeException(e);
}
}
@Override
public ControllerLuaContext getControllerLuaContext(EntityGadget gadget) {
return new ControllerLuaJContext(this, gadget);
}
@Override
public GroupEventLuaContext getGroupEventLuaContext(SceneGroup sceneGroupInstance, ScriptArgs args, SceneScriptManager scriptManager) {
return new GroupEventLuaJContext(this, sceneGroupInstance, args, scriptManager);
}
@Override
public emu.grasscutter.scripts.lua_engine.LuaTable getTable(Object table) {
if (table instanceof LuaTable)

View File

@ -1,14 +1,8 @@
package emu.grasscutter.scripts.lua_engine.luaj;
import com.esotericsoftware.reflectasm.ConstructorAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.ScriptUtils;
import emu.grasscutter.scripts.lua_engine.Serializer;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
@ -17,13 +11,9 @@ import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class LuaJSerializer implements Serializer {
public class LuaJSerializer extends Serializer {
private final static Map<Class<?>, MethodAccess> methodAccessCache = new ConcurrentHashMap<>();
private final static Map<Class<?>, ConstructorAccess<?>> constructorCache = new ConcurrentHashMap<>();
private final static Map<Class<?>, Map<String, FieldMeta>> fieldMetaCache = new ConcurrentHashMap<>();
@Override
public <T> List<T> toList(Class<T> type, Object obj) {
@ -40,19 +30,8 @@ public class LuaJSerializer implements Serializer {
return serializeMap(type, (LuaTable) obj);
}
private <T> Map<String,T> serializeMap(Class<T> type, LuaTable table) {
Map<String,T> map = new HashMap<>();
if (table == null) {
return map;
}
try {
LuaValue[] keys = table.keys();
for (LuaValue k : keys) {
try {
LuaValue keyValue = table.get(k);
@Nullable
private <T> T valueToType(Class<T> type, LuaValue keyValue) {
T object = null;
if (keyValue.istable()) {
@ -68,6 +47,25 @@ public class LuaJSerializer implements Serializer {
} else {
object = (T) keyValue;
}
if (object == null) {
Grasscutter.getLogger().warn("Can't serialize value: {} to type: {}", keyValue, type);
}
return object;
}
private <T> Map<String, T> serializeMap(Class<T> type, LuaTable table) {
Map<String, T> map = new HashMap<>();
if (table == null) {
return map;
}
try {
LuaValue[] keys = table.keys();
for (LuaValue k : keys) {
try {
LuaValue keyValue = table.get(k);
T object = valueToType(type, keyValue);
if (object != null) {
map.put(String.valueOf(k), object);
@ -77,7 +75,7 @@ public class LuaJSerializer implements Serializer {
}
}
} catch (Exception e) {
e.printStackTrace();
Grasscutter.getLogger().error("Exception while serializing map", e);
}
return map;
@ -96,21 +94,7 @@ public class LuaJSerializer implements Serializer {
try {
LuaValue keyValue = table.get(k);
T object = null;
if (keyValue.istable()) {
object = serialize(type, null, keyValue.checktable());
} else if (keyValue.isint()) {
object = (T) (Integer) keyValue.toint();
} else if (keyValue.isnumber()) {
object = (T) (Float) keyValue.tofloat(); // terrible...
} else if (keyValue.isstring()) {
object = (T) keyValue.tojstring();
} else if (keyValue.isboolean()) {
object = (T) (Boolean) keyValue.toboolean();
} else {
object = (T) keyValue;
}
T object = valueToType(type, keyValue);
if (object != null) {
list.add(object);
@ -120,7 +104,7 @@ public class LuaJSerializer implements Serializer {
}
}
} catch (Exception e) {
e.printStackTrace();
Grasscutter.getLogger().error("Exception while serializing list", e);
}
return list;
@ -146,7 +130,7 @@ public class LuaJSerializer implements Serializer {
Class<?> listType = getListType(type, field);
return (T) serializeList(listType, table);
} catch (Exception e) {
e.printStackTrace();
Grasscutter.getLogger().error("Exception while serializing {}", type.getName(), e);
return null;
}
}
@ -175,83 +159,27 @@ public class LuaJSerializer implements Serializer {
LuaValue keyValue = table.get(k);
if (keyValue.istable()) {
methodAccess.invoke(object, fieldMeta.index, serialize(fieldMeta.getType(), fieldMeta.getField(), keyValue.checktable()));
methodAccess.invoke(object, fieldMeta.getIndex(), serialize(fieldMeta.getType(), fieldMeta.getField(), keyValue.checktable()));
} else if (fieldMeta.getType().equals(float.class)) {
methodAccess.invoke(object, fieldMeta.index, keyValue.tofloat());
methodAccess.invoke(object, fieldMeta.getIndex(), keyValue.tofloat());
} else if (fieldMeta.getType().equals(int.class)) {
methodAccess.invoke(object, fieldMeta.index, keyValue.toint());
methodAccess.invoke(object, fieldMeta.getIndex(), keyValue.toint());
} else if (fieldMeta.getType().equals(String.class)) {
methodAccess.invoke(object, fieldMeta.index, keyValue.tojstring());
methodAccess.invoke(object, fieldMeta.getIndex(), keyValue.tojstring());
} else if (fieldMeta.getType().equals(boolean.class)) {
methodAccess.invoke(object, fieldMeta.index, keyValue.toboolean());
methodAccess.invoke(object, fieldMeta.getIndex(), keyValue.toboolean());
} else {
methodAccess.invoke(object, fieldMeta.index, keyValue.tojstring());
methodAccess.invoke(object, fieldMeta.getIndex(), keyValue.tojstring());
}
} catch (Exception ex) {
//ex.printStackTrace();
continue;
Grasscutter.getLogger().error("Exception serializing", ex);
}
}
} catch (Exception e) {
Grasscutter.getLogger().info(ScriptUtils.toMap(table).toString());
e.printStackTrace();
Grasscutter.getLogger().error("Exception while serializing {}", type.getName(), e);
}
return object;
}
public <T> Map<String, FieldMeta> cacheType(Class<T> type) {
if (fieldMetaCache.containsKey(type)) {
return fieldMetaCache.get(type);
}
if (!constructorCache.containsKey(type)) {
constructorCache.putIfAbsent(type, ConstructorAccess.get(type));
}
var methodAccess = Optional.ofNullable(methodAccessCache.get(type)).orElse(MethodAccess.get(type));
methodAccessCache.putIfAbsent(type, methodAccess);
var fieldMetaMap = new HashMap<String, FieldMeta>();
var methodNameSet = new HashSet<>(Arrays.stream(methodAccess.getMethodNames()).toList());
Arrays.stream(type.getDeclaredFields())
.filter(field -> methodNameSet.contains(getSetterName(field.getName())))
.forEach(field -> {
var setter = getSetterName(field.getName());
var index = methodAccess.getIndex(setter);
fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType(), field));
});
Arrays.stream(type.getFields())
.filter(field -> !fieldMetaMap.containsKey(field.getName()))
.filter(field -> methodNameSet.contains(getSetterName(field.getName())))
.forEach(field -> {
var setter = getSetterName(field.getName());
var index = methodAccess.getIndex(setter);
fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType(), field));
});
fieldMetaCache.put(type, fieldMetaMap);
return fieldMetaMap;
}
public String getSetterName(String fieldName) {
if (fieldName == null || fieldName.length() == 0) {
return null;
}
if (fieldName.length() == 1) {
return "set" + fieldName.toUpperCase();
}
return "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
}
@Data
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
static class FieldMeta{
String name;
String setter;
int index;
Class<?> type;
@Nullable Field field;
}
}

View File

@ -2,53 +2,19 @@ package emu.grasscutter.scripts.lua_engine.mock_results;
import emu.grasscutter.scripts.lua_engine.LuaValue;
public class BooleanLuaValue implements LuaValue {
public class BooleanLuaValue extends MockLuaValue {
public static final BooleanLuaValue TRUE = new BooleanLuaValue(true);
public static final BooleanLuaValue FALSE = new BooleanLuaValue(false);
private final boolean value;
public BooleanLuaValue(boolean value){
this.value = value;
}
@Override
public boolean isNull() {
return false;
}
@Override
public boolean isBoolean() {
return true;
}
@Override
public boolean isInteger() {
return false;
}
@Override
public boolean isLong() {
return false;
}
@Override
public boolean isDouble() {
return false;
}
@Override
public boolean isFloat() {
return false;
}
@Override
public boolean isString() {
return false;
}
@Override
public boolean isTable() {
return false;
}
@Override
public boolean asBoolean() {
return value;
@ -81,6 +47,8 @@ public class BooleanLuaValue implements LuaValue {
@Override
public <T> T asObject(Class<T> type) {
if(type == Boolean.class)
return type.cast(value);
return null;
}
}

View File

@ -2,7 +2,7 @@ package emu.grasscutter.scripts.lua_engine.mock_results;
import emu.grasscutter.scripts.lua_engine.LuaValue;
public class IntLuaValue implements LuaValue {
public class IntLuaValue extends MockLuaValue {
public static final IntLuaValue ZERO = new IntLuaValue(0);
public static final IntLuaValue ONE = new IntLuaValue(1);
public static final IntLuaValue N_ONE = new IntLuaValue(-1);
@ -14,46 +14,11 @@ public class IntLuaValue implements LuaValue {
this.value = value;
}
@Override
public boolean isNull() {
return false;
}
@Override
public boolean isBoolean() {
return false;
}
@Override
public boolean isInteger() {
return true;
}
@Override
public boolean isLong() {
return false;
}
@Override
public boolean isDouble() {
return false;
}
@Override
public boolean isFloat() {
return false;
}
@Override
public boolean isString() {
return false;
}
@Override
public boolean isTable() {
return false;
}
@Override
public boolean asBoolean() {
return value != 0;
@ -86,6 +51,8 @@ public class IntLuaValue implements LuaValue {
@Override
public <T> T asObject(Class<T> type) {
if(type == Number.class)
return type.cast(value);
return null;
}
}

View File

@ -0,0 +1,45 @@
package emu.grasscutter.scripts.lua_engine.mock_results;
import emu.grasscutter.scripts.lua_engine.LuaValue;
public abstract class MockLuaValue implements LuaValue {
@Override
public boolean isNull() {
return false;
}
@Override
public boolean isBoolean() {
return false;
}
@Override
public boolean isInteger() {
return false;
}
@Override
public boolean isLong() {
return false;
}
@Override
public boolean isDouble() {
return false;
}
@Override
public boolean isFloat() {
return false;
}
@Override
public boolean isString() {
return false;
}
@Override
public boolean isTable() {
return false;
}
}