commit 5714e799cdc42f1e4954eb4b8747bd7fa5db11cc Author: hartie95 Date: Sat Oct 7 18:48:22 2023 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b63da45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..5c4606b --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..f8467b4 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..87a20fc --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BaseLua/build.gradle.kts b/BaseLua/build.gradle.kts new file mode 100644 index 0000000..923f2b7 --- /dev/null +++ b/BaseLua/build.gradle.kts @@ -0,0 +1,44 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("java-library") + kotlin("jvm") version "1.9.10" +} + +group = "org.anime_game_servers" +version = "0.1" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(platform("org.junit:junit-bom:5.9.1")) + testImplementation("org.junit.jupiter:junit-jupiter") + implementation("com.google.code.findbugs:jsr305:3.0.2") + implementation("com.esotericsoftware:reflectasm:1.11.9") + implementation(kotlin("stdlib-jdk8")) +} + +tasks.test { + useJUnitPlatform() +} +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "17" +} +val compileTestKotlin: KotlinCompile by tasks +compileTestKotlin.kotlinOptions { + jvmTarget = "17" +} + + + +publishing { + publications { + create("maven") { + from(components["kotlin"]) + artifactId = "BaseLua" + } + } +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaEngine.java b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaEngine.java new file mode 100644 index 0000000..6ebe67a --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaEngine.java @@ -0,0 +1,27 @@ +package org.anime_game_servers.lua.engine; + +import org.anime_game_servers.lua.models.IntValueEnum; +import org.anime_game_servers.lua.models.ScriptType; +import org.anime_game_servers.lua.serialize.Serializer; + +public interface LuaEngine { + //TODO move to a better place + static ScriptFinder scriptFinder = null; + + > boolean addGlobalEnumByOrdinal(String name, T[] enumArray); + + & IntValueEnum> boolean addGlobalEnumByIntValue(String name, T[] enumArray); + + boolean addGlobalStaticClass(String name, Class staticClass); + + boolean addObject(String name, Object object); + + Serializer getSerializer(); + + LuaScript getScript(String scriptName, ScriptType scriptType); + + LuaTable getTable(Object table); + + LuaTable createTable(); + +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaScript.java b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaScript.java new file mode 100644 index 0000000..7743208 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaScript.java @@ -0,0 +1,24 @@ +package org.anime_game_servers.lua.engine; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.script.ScriptException; +import java.util.List; +import java.util.Map; + +public interface LuaScript { + boolean hasMethod(@Nonnull String methodName); + + @Nullable + LuaValue callMethod(@Nonnull String methodName, Object... args) throws ScriptException, NoSuchMethodException; + + void evaluate() throws ScriptException; + + T getGlobalVariable(String name, Class type); + + List getGlobalVariableList(String name, Class type); + + Map getGlobalVariableMap(String name, Class type); + + LuaEngine getEngine(); +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaTable.java b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaTable.java new file mode 100644 index 0000000..aa51d27 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaTable.java @@ -0,0 +1,88 @@ +package org.anime_game_servers.lua.engine; + +import javax.annotation.Nullable; +import java.util.Set; + +public interface LuaTable { + boolean has(String key); + + @Nullable + Object get(String key); + + @Nullable + Object get(int key); + + int getInt(String key); + + int optInt(String key, int defaultValue); + + int getInt(int key); + + int optInt(int key, int defaultValue); + + void set(int key, int value); + + void set(String key, int value); + + double getDouble(String key); + + double optDouble(String key, double defaultValue); + + double getDouble(int key); + + double optDouble(int key, double defaultValue); + + float getFloat(String key); + + float optFloat(String key, float defaultValue); + + float getFloat(int key); + + float optFloat(int key, float defaultValue); + + void set(int key, double value); + + void set(String key, double value); + + boolean getBoolean(String key); + + boolean optBoolean(String key, boolean defaultValue); + + boolean getBoolean(int key); + + boolean optBoolean(int key, boolean defaultValue); + + void set(int key, boolean value); + + void set(String key, boolean value); + + String getString(String key); + + String optString(String key, String defaultValue); + + String getString(int key); + + String optString(int key, String defaultValue); + + void set(int key, String value); + + void set(String key, String value); + + @Nullable + LuaTable getTable(String key); + + @Nullable + LuaTable getTable(int key); + + void set(int key, LuaTable value); + + void set(String key, LuaTable value); + + Set getKeys(); + + int[] getAsIntArray(); + + int getSize(); + + Object getRawTable(); +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaValue.java b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaValue.java new file mode 100644 index 0000000..3a7670f --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/LuaValue.java @@ -0,0 +1,33 @@ +package org.anime_game_servers.lua.engine; + +public interface LuaValue { + boolean isNull(); + + boolean isBoolean(); + + boolean isInteger(); + + boolean isLong(); + + boolean isDouble(); + + boolean isFloat(); + + boolean isString(); + + boolean isTable(); + + boolean asBoolean(); + + int asInteger(); + + long asLong(); + + double asDouble(); + + float asFloat(); + + String asString(); + + T asObject(Class type); +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/engine/ScriptFinder.java b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/ScriptFinder.java new file mode 100644 index 0000000..ea27600 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/engine/ScriptFinder.java @@ -0,0 +1,9 @@ +package org.anime_game_servers.lua.engine; + +import java.io.InputStream; +import java.nio.file.Path; + +public interface ScriptFinder { + InputStream openScript(String scriptName); + Path getScriptPath(String scriptName); +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/models/BooleanLuaValue.java b/BaseLua/src/main/java/org/anime_game_servers/lua/models/BooleanLuaValue.java new file mode 100644 index 0000000..b0ec309 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/models/BooleanLuaValue.java @@ -0,0 +1,52 @@ +package org.anime_game_servers.lua.models; + +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 isBoolean() { + return true; + } + + @Override + public boolean asBoolean() { + return value; + } + + @Override + public int asInteger() { + return value ? 1 : 0; + } + + @Override + public long asLong() { + return value ? 1 : 0; + } + + @Override + public double asDouble() { + return value ? 1 : 0; + } + + @Override + public float asFloat() { + return value ? 1 : 0; + } + + @Override + public String asString() { + return value ? "true" : "false"; + } + + @Override + public T asObject(Class type) { + if(type == Boolean.class) + return type.cast(value); + return null; + } +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/models/IntLuaValue.java b/BaseLua/src/main/java/org/anime_game_servers/lua/models/IntLuaValue.java new file mode 100644 index 0000000..a2e5996 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/models/IntLuaValue.java @@ -0,0 +1,56 @@ +package org.anime_game_servers.lua.models; + +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); + + + private final int value; + + public IntLuaValue(int value) { + this.value = value; + } + + @Override + public boolean isInteger() { + return true; + } + + @Override + public boolean asBoolean() { + return value != 0; + } + + @Override + public int asInteger() { + return value; + } + + @Override + public long asLong() { + return value; + } + + @Override + public double asDouble() { + return value; + } + + @Override + public float asFloat() { + return value; + } + + @Override + public String asString() { + return Integer.toString(value); + } + + @Override + public T asObject(Class type) { + if(type == Number.class) + return type.cast(value); + return null; + } +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/models/IntValueEnum.java b/BaseLua/src/main/java/org/anime_game_servers/lua/models/IntValueEnum.java new file mode 100644 index 0000000..910bef2 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/models/IntValueEnum.java @@ -0,0 +1,5 @@ +package org.anime_game_servers.lua.models; + +public interface IntValueEnum { + int getValue(); +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/models/MockLuaValue.java b/BaseLua/src/main/java/org/anime_game_servers/lua/models/MockLuaValue.java new file mode 100644 index 0000000..3c5d928 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/models/MockLuaValue.java @@ -0,0 +1,46 @@ +package org.anime_game_servers.lua.models; + + +import org.anime_game_servers.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; + } +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/models/ScriptType.kt b/BaseLua/src/main/java/org/anime_game_servers/lua/models/ScriptType.kt new file mode 100644 index 0000000..10a797b --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/models/ScriptType.kt @@ -0,0 +1,12 @@ +package org.anime_game_servers.lua.models + +enum class ScriptType( + val addDefaultGlobals: Boolean, + val precompile: Boolean +) { + DATA_STORAGE(false, false), + STATIC_EXECUTABLE(false, true), + EXECUTABLE(true, true), + ONE_TIME_EXECUTABLE(true, false), + INCLUDE(true, true); +} \ No newline at end of file diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/BaseSerializer.java b/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/BaseSerializer.java new file mode 100644 index 0000000..48a5a86 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/BaseSerializer.java @@ -0,0 +1,142 @@ +package org.anime_game_servers.lua.serialize; + + +import com.esotericsoftware.reflectasm.ConstructorAccess; +import com.esotericsoftware.reflectasm.MethodAccess; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class BaseSerializer implements Serializer { + + protected static final Map, MethodAccess> methodAccessCache = new ConcurrentHashMap<>(); + protected static final Map, ConstructorAccess> constructorCache = new ConcurrentHashMap<>(); + protected static final Map, Map> fieldMetaCache = new ConcurrentHashMap<>(); + public abstract List toList(Class type, Object obj); + + public abstract T toObject(Class type, Object obj); + + public abstract Map toMap(Class 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 Map cacheType(Class 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(); + var methodNameSet = new HashSet<>(Arrays.stream(methodAccess.getMethodNames()).toList()); + + Class classtype = type; + while(classtype!=null){ + Arrays.stream(classtype.getDeclaredFields()) + .forEach(field -> { + if(methodNameSet.contains(getSetterName(field.getName()))) { + var setter = getSetterName(field.getName()); + var index = methodAccess.getIndex(setter); + fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), setter, index, field.getType(), field)); + } else { + field.setAccessible(true); + fieldMetaMap.put(field.getName(), new FieldMeta(field.getName(), null, -1, field.getType(), field)); + } + }); + classtype = classtype.getSuperclass(); + } + + 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; + } + + protected void set(Object object, @Nonnull FieldMeta fieldMeta, @Nullable MethodAccess methodAccess, int value){ + try { + if (methodAccess != null && fieldMeta.getSetter() != null) { + methodAccess.invoke(object, fieldMeta.getIndex(), value); + } else if(fieldMeta.getField() != null){ + fieldMeta.getField().setInt(object, value); + } + } catch (Exception ex){ + //Grasscutter.getLogger().warn("Failed to set field {} of type {} to value {}", fieldMeta.getName(), fieldMeta.getType(), value, ex); + } + } + protected void set(Object object, @Nonnull FieldMeta fieldMeta, @Nullable MethodAccess methodAccess, double value){ + try { + if (methodAccess != null && fieldMeta.getSetter() != null) { + methodAccess.invoke(object, fieldMeta.getIndex(), value); + } else if(fieldMeta.getField() != null) { + fieldMeta.getField().setDouble(object, value); + } + } catch (Exception ex){ + //Grasscutter.getLogger().warn("Failed to set field {} of type {} to value {}", fieldMeta.getName(), fieldMeta.getType(), value, ex); + } + } + protected void set(Object object, @Nonnull FieldMeta fieldMeta, @Nullable MethodAccess methodAccess, float value){ + try { + if (methodAccess != null && fieldMeta.getSetter() != null) { + methodAccess.invoke(object, fieldMeta.getIndex(), value); + } else if(fieldMeta.getField() != null) { + fieldMeta.getField().setFloat(object, value); + } + } catch (Exception ex){ + //Grasscutter.getLogger().warn("Failed to set field {} of type {} to value {}", fieldMeta.getName(), fieldMeta.getType(), value, ex); + } + } + protected void set(Object object, @Nonnull FieldMeta fieldMeta, @Nullable MethodAccess methodAccess, long value){ + try { + if (methodAccess != null && fieldMeta.getSetter() != null) { + methodAccess.invoke(object, fieldMeta.getIndex(), value); + } else if(fieldMeta.getField() != null) { + fieldMeta.getField().setLong(object, value); + } + } catch (Exception ex){ + //Grasscutter.getLogger().warn("Failed to set field {} of type {} to value {}", fieldMeta.getName(), fieldMeta.getType(), value, ex); + } + } + protected void set(Object object, @Nonnull FieldMeta fieldMeta, @Nullable MethodAccess methodAccess, boolean value){ + try { + if (methodAccess != null && fieldMeta.getSetter() != null) { + methodAccess.invoke(object, fieldMeta.getIndex(), value); + } else if(fieldMeta.getField() != null) { + fieldMeta.getField().setBoolean(object, value); + } + } catch (Exception ex){ + //Grasscutter.getLogger().warn("Failed to set field {} of type {} to value {}", fieldMeta.getName(), fieldMeta.getType(), value, ex); + } + } + protected void set(Object object, @Nonnull FieldMeta fieldMeta, @Nullable MethodAccess methodAccess, Object value){ + try { + if (methodAccess != null && fieldMeta.getSetter() != null) { + methodAccess.invoke(object, fieldMeta.getIndex(), value); + } else if(fieldMeta.getField() != null) { + fieldMeta.getField().set(object, value); + } + } catch (Exception ex){ + //Grasscutter.getLogger().warn("Failed to set field {} of type {} to value {}", fieldMeta.getName(), fieldMeta.getType(), value, ex); + } + } +} diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/FieldMeta.kt b/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/FieldMeta.kt new file mode 100644 index 0000000..fbc9c3b --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/FieldMeta.kt @@ -0,0 +1,11 @@ +package org.anime_game_servers.lua.serialize + +import java.lang.reflect.Field + +data class FieldMeta( + val name: String? = null, + val setter: String? = null, + val index: Int = 0, + val type: Class<*>? = null, + val field: Field? = null +) diff --git a/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/Serializer.java b/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/Serializer.java new file mode 100644 index 0000000..6cf5531 --- /dev/null +++ b/BaseLua/src/main/java/org/anime_game_servers/lua/serialize/Serializer.java @@ -0,0 +1,4 @@ +package org.anime_game_servers.lua.serialize; + +public interface Serializer { +} diff --git a/GILua/build.gradle.kts b/GILua/build.gradle.kts new file mode 100644 index 0000000..4bc8d48 --- /dev/null +++ b/GILua/build.gradle.kts @@ -0,0 +1,46 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("java-library") + kotlin("jvm") version "1.9.10" +} + +group = "org.anime_game_servers" +version = "0.1" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(platform("org.junit:junit-bom:5.9.1")) + testImplementation("org.junit.jupiter:junit-jupiter") + api(project(":BaseLua")) + implementation("com.google.code.findbugs:jsr305:3.0.2") + implementation(kotlin("stdlib-jdk8")) + compileOnly("org.projectlombok:lombok:1.18.30") + annotationProcessor("org.projectlombok:lombok:1.18.30") + implementation("com.github.davidmoten:rtree-multi:0.1") +} + +tasks.test { + useJUnitPlatform() +} +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "17" +} +val compileTestKotlin: KotlinCompile by tasks +compileTestKotlin.kotlinOptions { + jvmTarget = "17" +} + +publishing { + publications { + create("maven") { + from(components["kotlin"]) + groupId = "org.anime_game_servers" + artifactId = "GIlua" + } + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/SceneIndexManager.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/SceneIndexManager.java new file mode 100644 index 0000000..78e0b58 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/SceneIndexManager.java @@ -0,0 +1,33 @@ +package org.anime_game_servers.gi_lua; + +import com.github.davidmoten.rtreemulti.Entry; +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import com.github.davidmoten.rtreemulti.geometry.Rectangle; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +public class SceneIndexManager { + + public static RTree buildIndex(int dimensions, Collection elements, Function extractor){ + RTree rtree = RTree.dimensions(dimensions).create(); + return rtree.add(elements.stream().map(e -> Entry.entry(e, extractor.apply(e))).toList()); + } + public static List queryNeighbors(RTree tree, double[] position, int range){ + var result = new ArrayList(); + Rectangle rectangle = Rectangle.create(calRange(position, -range), calRange(position, range)); + var queryResult = tree.search(rectangle); + queryResult.forEach(q -> result.add(q.value())); + return result; + } + private static double[] calRange(double[] position, int range){ + var newPos = position.clone(); + for(int i=0;i xyz) { + switch (xyz.size()) { + default: // Might want to error on excess elements, but maybe we want to extend to 3+3 representation later. + case 3: + this.z = xyz.get(2); // Fall-through + case 2: + this.y = xyz.get(1); // Fall-through + case 1: + this.x = xyz.get(0); // pointless fall-through + case 0: + break; + } + } + + public Point toPoint() { + return Point.create(x,y,z); + } + + /** + * To XYZ array for Spatial Index + */ + public double[] toDoubleArray() { + return new double[]{ x, y, z}; + } + /** + * To XZ array for Spatial Index (Blocks) + */ + public double[] toXZDoubleArray() { + return new double[]{x, z}; + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBlock.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBlock.java new file mode 100644 index 0000000..28641c7 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBlock.java @@ -0,0 +1,66 @@ +package org.anime_game_servers.gi_lua.models; + +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import com.github.davidmoten.rtreemulti.geometry.Rectangle; +import lombok.*; +import org.anime_game_servers.gi_lua.SceneIndexManager; +import org.anime_game_servers.gi_lua.utils.GIScriptLoader; +import org.anime_game_servers.lua.models.ScriptType; + +import javax.script.ScriptException; +import java.util.Map; +import java.util.stream.Collectors; + +@ToString +@Getter +public class SceneBlock { + @Setter(AccessLevel.PACKAGE) + private int id; + private Position max; + private Position min; + + private int sceneId; + private Map groups; + private RTree sceneGroupIndex; + + private transient boolean loaded; // Not an actual variable in the scripts either + + public void setLoaded(boolean loaded) { + this.loaded = loaded; + } + + public SceneBlock load(int sceneId, GIScriptLoader scriptLoader) { + if (this.loaded) { + return this; + } + this.sceneId = sceneId; + this.setLoaded(true); + + val cs = scriptLoader.getSceneScript(sceneId, "scene" + sceneId + "_block" + this.id + ".lua", ScriptType.DATA_STORAGE); + + if (cs == null) { + return null; + } + + // Eval script + try { + cs.evaluate(); + + // Set groups + this.groups = cs.getGlobalVariableList("groups", SceneGroup.class).stream() + .collect(Collectors.toMap(x -> x.getId(), y -> y, (a, b) -> a)); + + this.groups.values().forEach(g -> g.block_id = this.id); + this.sceneGroupIndex = SceneIndexManager.buildIndex(3, this.groups.values(), g -> g.getPos().toPoint()); + } catch (ScriptException exception) { + //Grasscutter.getLogger().error("An error occurred while loading block " + this.id + " in scene " + sceneId, exception); + } + //Grasscutter.getLogger().debug("Successfully loaded block {} in scene {}.", this.id, sceneId); + return this; + } + + public Rectangle toRectangle() { + return Rectangle.create(this.min.toXZDoubleArray(), this.max.toXZDoubleArray()); + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBossChest.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBossChest.java new file mode 100644 index 0000000..33e51b4 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBossChest.java @@ -0,0 +1,13 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString +public class SceneBossChest { + private int life_time; + private int monster_config_id; + private int resin; + private int take_num; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBusiness.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBusiness.java new file mode 100644 index 0000000..d639654 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneBusiness.java @@ -0,0 +1,10 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; + +@ToString +@Getter +public class SceneBusiness { + private int type; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneConfig.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneConfig.java new file mode 100644 index 0000000..825c916 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneConfig.java @@ -0,0 +1,15 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; + +@ToString +@Getter +public class SceneConfig { + private Position vision_anchor; + private Position born_pos; + private Position born_rot; + private Position begin_pos; + private Position size; + private float die_y; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGadget.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGadget.java new file mode 100644 index 0000000..06c45ec --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGadget.java @@ -0,0 +1,32 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; +import org.anime_game_servers.gi_lua.models.constants.EntityType; + +import java.util.List; + +@ToString +@Getter +public class SceneGadget extends SceneObject{ + private int gadget_id; + private int state; + private int point_type; + private SceneBossChest boss_chest; + private int chest_drop_id; + private int interact_id; + private boolean isOneoff; + private int draft_id; + private int route_id; + private boolean start_route = true; + private boolean is_use_point_array = false; + private boolean persistent = false; + private boolean showcutscene; + private Explore explore; + private List arguments; + + @Override + public EntityType getType() { + return EntityType.GADGET; + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGarbage.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGarbage.java new file mode 100644 index 0000000..ef8c600 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGarbage.java @@ -0,0 +1,12 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; + +import java.util.List; + +@ToString +@Getter +public class SceneGarbage { + private List gadgets; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGroup.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGroup.java new file mode 100644 index 0000000..66eadec --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneGroup.java @@ -0,0 +1,186 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.val; +import org.anime_game_servers.gi_lua.utils.GIScriptLoader; +import org.anime_game_servers.lua.engine.LuaScript; +import org.anime_game_servers.lua.models.ScriptType; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.stream.Collectors; + +@ToString +@Getter +public class SceneGroup { + public transient int block_id; // Not an actual variable in the scripts but we will keep it here for reference + + @Setter + private int id; + private int refresh_id; + @Nullable + private Position pos; + + @Nullable + private Map monsters; // + @Nullable + private Map npcs; // + @Nullable + private Map gadgets; // + @Nullable + private Map triggers; + @Nullable + private Map regions; + @Nullable + private List suites; + @Nullable + private List variables; + + @Nullable + private SceneBusiness business; + @Nullable + private SceneGarbage garbages; + @Nullable + private SceneInitConfig init_config; + private final boolean dynamic_load = false; + + @Nullable + private SceneReplaceable is_replaceable; + + private transient boolean loaded; // Not an actual variable in the scripts either + private transient LuaScript script; + + public static SceneGroup of(int groupId) { + var group = new SceneGroup(); + group.id = groupId; + return group; + } + + public int getBusinessType() { + return this.business == null ? 0 : this.business.getType(); + } + + public List getGarbageGadgets() { + return this.garbages == null ? null : this.garbages.getGadgets(); + } + + public boolean isReplaceable() { + return this.is_replaceable != null ? this.is_replaceable.isValue() : false; + } + + public SceneSuite getSuiteByIndex(int index) { + if (index < 1 || index > suites.size()) { + return null; + } + return this.suites.get(index - 1); + } + + public synchronized SceneGroup load(int sceneId, GIScriptLoader scriptLoader) { + if (this.loaded) { + return this; + } + // Set flag here so if there is no script, we don't call this function over and over again. + this.loaded = true; + + val cs = scriptLoader.getSceneScript(sceneId, "scene" + sceneId + "_group" + this.id + ".lua", ScriptType.EXECUTABLE); + + if (cs == null) { + return this; + } + + this.script = cs; + + // Eval script + try { + cs.evaluate(); + + // Set + this.monsters = cs.getGlobalVariableList("monsters", SceneMonster.class).stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); + this.monsters.values().forEach(m -> m.group = this); + + this.npcs = cs.getGlobalVariableList("npcs", SceneNPC.class).stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); + this.npcs.values().forEach(m -> m.group = this); + + this.gadgets = cs.getGlobalVariableList("gadgets", SceneGadget.class).stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); + this.gadgets.values().forEach(m -> m.group = this); + + this.triggers = cs.getGlobalVariableList("triggers", SceneTrigger.class).stream() + .collect(Collectors.toMap(SceneTrigger::getName, y -> y, (a, b) -> a)); + this.triggers.values().forEach(t -> t.setCurrentGroup(this)); + + this.suites = cs.getGlobalVariableList("suites", SceneSuite.class); + this.regions = cs.getGlobalVariableList("regions", SceneRegion.class).stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); + this.regions.values().forEach(m -> m.group = this); + + this.init_config = cs.getGlobalVariable("init_config", SceneInitConfig.class); + + // Garbages // TODO: fix properly later + /*Object garbagesValue = this.bindings.get("garbages"); + if (garbagesValue instanceof LuaValue garbagesTable) { + this.garbages = new SceneGarbage(); + if (garbagesTable.checktable().get("gadgets") != LuaValue.NIL) { + this.garbages.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, garbagesTable.checktable().get("gadgets").checktable()); + this.garbages.gadgets.forEach(m -> m.group = this); + } + }*/ + + // Add variables to suite + this.variables = cs.getGlobalVariableList("variables", SceneVar.class); + + // Add monsters and gadgets to suite + this.suites.forEach(i -> i.init(this)); + + } catch (Exception e) { + //Grasscutter.getLogger().error("An error occurred while loading group " + this.id + " in scene " + sceneId + ".", e); + } + + //Grasscutter.getLogger().debug("Successfully loaded group {} in scene {}.", this.id, sceneId); + return this; + } + + public int findInitSuiteIndex(int exclude_index) { //TODO: Investigate end index + if (init_config == null) return 1; + if (init_config.getIo_type() == 1) return init_config.getSuite(); //IO TYPE FLOW + if (init_config.isRand_suite()) { + if (suites.size() == 1) { + return init_config.getSuite(); + } else { + List randSuiteList = new ArrayList<>(); + for (int i = 0; i < suites.size(); i++) { + if (i == exclude_index) continue; + + var suite = suites.get(i); + for (int j = 0; j < suite.getRand_weight(); j++) randSuiteList.add(Integer.valueOf(i + 1)); + } + return randSuiteList.get(new Random().nextInt(randSuiteList.size())); + } + } + return init_config.getSuite(); + } + + public Optional searchBossChestInGroup() { + return this.gadgets.values().stream().map(g -> g.getBoss_chest()).filter(Objects::nonNull) + .filter(bossChest -> bossChest.getMonster_config_id() > 0) + .findFirst(); + } + + /*public List getReplaceableGroups(Collection loadedGroups) { + return this.is_replaceable == null ? List.of() : + Optional.ofNullable(GameData.getGroupReplacements().get(this.id)).stream() + .map(GroupReplacementData::getReplace_groups) + .flatMap(List::stream) + .map(replacementId -> loadedGroups.stream().filter(g -> g.id == replacementId).findFirst()) + .filter(Optional::isPresent).map(Optional::get) + .filter(replacementGroup -> replacementGroup.is_replaceable != null) + .filter(replacementGroup -> (replacementGroup.is_replaceable.isValue() + && replacementGroup.is_replaceable.getVersion() <= this.is_replaceable.getVersion()) + || replacementGroup.is_replaceable.isNew_bin_only()) + .toList(); + }*/ +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneInitConfig.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneInitConfig.java new file mode 100644 index 0000000..22f44b6 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneInitConfig.java @@ -0,0 +1,13 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; + +@ToString +@Getter +public class SceneInitConfig { + private int suite; + private int end_suite; + private int io_type ; + private boolean rand_suite; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneMeta.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneMeta.java new file mode 100644 index 0000000..0597466 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneMeta.java @@ -0,0 +1,68 @@ +package org.anime_game_servers.gi_lua.models; + +import com.github.davidmoten.rtreemulti.RTree; +import com.github.davidmoten.rtreemulti.geometry.Geometry; +import lombok.Getter; +import lombok.ToString; +import lombok.val; +import org.anime_game_servers.gi_lua.SceneIndexManager; +import org.anime_game_servers.gi_lua.utils.GIScriptLoader; +import org.anime_game_servers.lua.engine.LuaScript; +import org.anime_game_servers.lua.models.ScriptType; + +import javax.script.ScriptException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@ToString +@Getter +public class SceneMeta { + + private SceneConfig config; + private Map blocks; + + private LuaScript context; + + private RTree sceneBlockIndex; + + public static SceneMeta of(int sceneId, GIScriptLoader scriptLoader) { + return new SceneMeta().load(sceneId, scriptLoader); + } + + public SceneMeta load(int sceneId, GIScriptLoader scriptLoader) { + // Get compiled script if cached + val cs = scriptLoader.getSceneScript(sceneId, "scene"+sceneId+".lua", ScriptType.DATA_STORAGE); + + if (cs == null) { + //Grasscutter.getLogger().warn("No script found for scene " + sceneId); + return null; + } + + // Eval script + try { + cs.evaluate(); + + this.config = cs.getGlobalVariable("scene_config", SceneConfig.class); + + // TODO optimize later + // Create blocks + List blockIds = cs.getGlobalVariableList("blocks", Integer.class); + List blocks = cs.getGlobalVariableList("block_rects", SceneBlock.class); + + for (int i = 0; i < blocks.size(); i++) { + SceneBlock block = blocks.get(i); + block.setId(blockIds.get(i)); + } + + this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.getId(), b -> b, (a, b) -> a)); + this.sceneBlockIndex = SceneIndexManager.buildIndex(2, blocks, SceneBlock::toRectangle); + + } catch (ScriptException exception) { + //Grasscutter.getLogger().error("An error occurred while running a script.", exception); + return null; + } + //Grasscutter.getLogger().debug("Successfully loaded metadata in scene {}.", sceneId); + return this; + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneMonster.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneMonster.java new file mode 100644 index 0000000..0964089 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneMonster.java @@ -0,0 +1,32 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; +import org.anime_game_servers.gi_lua.models.constants.EntityType; + +import java.util.List; + +@ToString +@Getter +public class SceneMonster extends SceneObject{ + private int monster_id; + private int pose_id; + private String pose_logic_state; + private int drop_id; + private boolean disableWander; + private int title_id; + private int special_name_id; + private List affix; + private boolean isElite; + private int climate_area_id; + private int ai_config_id; + private int kill_score; + private int speed_level; + private long tag; + private boolean is_light_config; + + @Override + public EntityType getType() { + return EntityType.MONSTER; + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneNPC.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneNPC.java new file mode 100644 index 0000000..52fc114 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneNPC.java @@ -0,0 +1,16 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; +import org.anime_game_servers.gi_lua.models.constants.EntityType; + +@ToString +@Getter +public class SceneNPC extends SceneObject{ + private int npc_id; + + @Override + public EntityType getType() { + return EntityType.NPC; + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneObject.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneObject.java new file mode 100644 index 0000000..7988da8 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneObject.java @@ -0,0 +1,29 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; +import org.anime_game_servers.gi_lua.models.constants.EntityType; + +@ToString +@Getter +public abstract class SceneObject { + protected int level; + protected int config_id; + protected int area_id; + protected int vision_level = 0; + protected int mark_flag; + protected String drop_tag; + protected int guest_ban_drop; + protected int oneoff_reset_version; + protected int sight_group_index; + // server_global_value_config, might be group only + + protected Position pos; + protected Position rot; + /** + * not set by lua + */ + protected transient SceneGroup group; + + public abstract EntityType getType(); +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneRegion.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneRegion.java new file mode 100644 index 0000000..25094bc --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneRegion.java @@ -0,0 +1,47 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import org.anime_game_servers.gi_lua.models.constants.EntityType; +import org.anime_game_servers.gi_lua.models.constants.ScriptRegionShape; + +import java.util.List; + + +@Getter +public class SceneRegion extends SceneObject{ + private int shape; + // for CUBIC + private Position size; + // for SPHERE AND CYLINDER + private int radius; + // for CYLINDER and POLYGON + private float height; + private List point_array; + private List team_ability_group; + private boolean is_trigger_reload_group; + + public boolean contains(Position position) { + switch (shape) { + case ScriptRegionShape.CUBIC: + return (Math.abs(pos.getX() - position.getX()) <= size.getX()/2f) && + (Math.abs(pos.getY() - position.getY()) <= size.getY()/2f) && + (Math.abs(pos.getZ() - position.getZ()) <= size.getZ()/2f); + case ScriptRegionShape.SPHERE: + var x = Math.pow(pos.getX() - position.getX(), 2); + var y = Math.pow(pos.getY() - position.getY(), 2); + var z = Math.pow(pos.getZ() - position.getZ(), 2); + // ^ means XOR in java! + return x + y + z <= (radius*radius); + } + return false; + } + + public int getGroupId() { + return group.getId(); + } + + @Override + public EntityType getType() { + return EntityType.REGION; + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneReplaceable.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneReplaceable.java new file mode 100644 index 0000000..cb0f30e --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneReplaceable.java @@ -0,0 +1,15 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@ToString +@Getter +public class SceneReplaceable { + // TODO move to modifiable value in SceneGroupInstance + @Setter + private boolean value; + private int version; + private boolean new_bin_only; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneSuite.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneSuite.java new file mode 100644 index 0000000..ef4ce55 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneSuite.java @@ -0,0 +1,68 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; +import lombok.val; + +import java.util.ArrayList; +import java.util.List; + +@ToString +@Getter +public class SceneSuite { + // make it refer the default empty list to avoid NPE caused by some group + private List monsters = List.of(); + private List gadgets = List.of(); + private List triggers = List.of(); + private List regions = List.of(); + private int rand_weight; + + private boolean ban_refresh = false; + + private transient List sceneMonsters = List.of(); + private transient List sceneGadgets = List.of(); + private transient List sceneTriggers = List.of(); + private transient List sceneRegions = List.of(); + + public void init(SceneGroup sceneGroup) { + val monsters = sceneGroup.getMonsters(); + if(monsters != null){ + this.sceneMonsters = new ArrayList<>( + this.monsters.stream() + .filter(monsters::containsKey) + .map(monsters::get) + .toList() + ); + } + + val gadgets = sceneGroup.getGadgets(); + if(gadgets != null){ + this.sceneGadgets = new ArrayList<>( + this.gadgets.stream() + .filter(gadgets::containsKey) + .map(gadgets::get) + .toList() + ); + } + + val triggers = sceneGroup.getTriggers(); + if(triggers != null) { + this.sceneTriggers = new ArrayList<>( + this.triggers.stream() + .filter(triggers::containsKey) + .map(triggers::get) + .toList() + ); + } + val regions = sceneGroup.getRegions(); + if(regions != null) { + this.sceneRegions = new ArrayList<>( + this.regions.stream() + .filter(regions::containsKey) + .map(regions::get) + .toList() + ); + } + + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneTrigger.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneTrigger.java new file mode 100644 index 0000000..484e186 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneTrigger.java @@ -0,0 +1,27 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +// todo find way to deserialize from lua with final fields, maybe with the help of Builder? +public class SceneTrigger { + /** + * When the trigger count is set to this, it only gets unregistered on a return of != 0 from the trigger function. + */ + public static final int INF_TRIGGERS = 0; + + private String name; + private int config_id; + private int event; + private int trigger_count = 1; + private String source; + private String condition; + private String action; + private String tag; + private String tlog_tag; + private boolean forbid_guest; + + private transient SceneGroup currentGroup; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneVar.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneVar.java new file mode 100644 index 0000000..2a281ed --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/SceneVar.java @@ -0,0 +1,13 @@ +package org.anime_game_servers.gi_lua.models; + +import lombok.Getter; +import lombok.ToString; + +@ToString +@Getter +public class SceneVar { + private int configId; + private String name; + private int value; + private boolean no_refresh; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/ScriptArgs.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/ScriptArgs.java new file mode 100644 index 0000000..1cd2cef --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/ScriptArgs.java @@ -0,0 +1,94 @@ +package org.anime_game_servers.gi_lua.models; + +public class ScriptArgs { + public int param1; + public int param2; + public int param3; + public int source_eid; // Source entity + public int target_eid; + public int group_id; + public String source; // source string, used for timers + public int type; // lua event type, used by scripts and the ScriptManager + + public ScriptArgs(int groupId, int eventType) { + this(groupId, eventType, 0,0); + } + + public ScriptArgs(int groupId, int eventType, int param1) { + this(groupId, eventType, param1,0); + } + + public ScriptArgs(int groupId, int eventType, int param1, int param2) { + this.type = eventType; + this.param1 = param1; + this.param2 = param2; + this.group_id = groupId; + } + + public int getParam1() { + return param1; + } + + public ScriptArgs setParam1(int param1) { + this.param1 = param1; + return this; + } + + public int getParam2() { + return param2; + } + + public ScriptArgs setParam2(int param2) { + this.param2 = param2; + return this; + } + + public int getParam3() { + return param3; + } + + public ScriptArgs setParam3(int param3) { + this.param3 = param3; + return this; + } + + public int getSourceEntityId() { + return source_eid; + } + + public ScriptArgs setSourceEntityId(int source_eid) { + this.source_eid = source_eid; + return this; + } + + public int getTargetEntityId() { + return target_eid; + } + + public ScriptArgs setTargetEntityId(int target_eid) { + this.target_eid = target_eid; + return this; + } + + public String getEventSource() { + return source; + } + + public ScriptArgs setEventSource(String source) { + this.source = source; + return this; + } + + public ScriptArgs setEventSource(int source) { + return setEventSource(Integer.toString(source)); + } + + public int getGroupId() { + return group_id; + } + + public ScriptArgs setGroupId(int group_id) { + this.group_id = group_id; + return this; + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/EntityType.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/EntityType.java new file mode 100644 index 0000000..9fffab3 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/EntityType.java @@ -0,0 +1,18 @@ +package org.anime_game_servers.gi_lua.models.constants; + +public enum EntityType { + NONE, + AVATAR, + MONSTER, + NPC, + GADGET, + REGION, + WEAPON, + WEATHER, + SCENE, + TEAM, + MASSIVE_ENTITY , + MPLEVEL, + PLAY_TEAM_ENTITY, + EYE_POINT; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/EventType.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/EventType.java new file mode 100644 index 0000000..1a37b26 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/EventType.java @@ -0,0 +1,127 @@ +package org.anime_game_servers.gi_lua.models.constants; + +public class EventType { + public static final int EVENT_NONE = 0; + /** + * param1: monster.configId + */ + public static final int EVENT_ANY_MONSTER_DIE = 1; + public static final int EVENT_ANY_GADGET_DIE = 2; + public static final int EVENT_VARIABLE_CHANGE = 3; + public static final int EVENT_ENTER_REGION = 4; + public static final int EVENT_LEAVE_REGION = 5; + public static final int EVENT_GADGET_CREATE = 6; + public static final int EVENT_GADGET_STATE_CHANGE = 7; + public static final int EVENT_DUNGEON_SETTLE = 8; + public static final int EVENT_SELECT_OPTION = 9; + public static final int EVENT_CLIENT_EXECUTE = 10; + public static final int EVENT_ANY_MONSTER_LIVE = 11; + public static final int EVENT_SPECIFIC_MONSTER_HP_CHANGE = 12; + public static final int EVENT_CITY_LEVELUP_UNLOCK_DUNGEON_ENTRY = 13; + public static final int EVENT_DUNGEON_BROADCAST_ONTIMER = 14; + public static final int EVENT_TIMER_EVENT = 15; + public static final int EVENT_CHALLENGE_SUCCESS = 16; + public static final int EVENT_CHALLENGE_FAIL = 17; + public static final int EVENT_SEAL_BATTLE_BEGIN = 18; + public static final int EVENT_SEAL_BATTLE_END = 19; + public static final int EVENT_GATHER = 20; + public static final int EVENT_QUEST_FINISH = 21; + public static final int EVENT_MONSTER_BATTLE = 22; + public static final int EVENT_CITY_LEVELUP = 23; + public static final int EVENT_CUTSCENE_END = 24; + public static final int EVENT_AVATAR_NEAR_PLATFORM = 25; // also send by the client + public static final int EVENT_PLATFORM_REACH_POINT = 26; + public static final int EVENT_UNLOCK_TRANS_POINT = 27; + public static final int EVENT_QUEST_START = 28; + public static final int EVENT_GROUP_LOAD = 29; + public static final int EVENT_GROUP_WILL_UNLOAD = 30; + public static final int EVENT_GROUP_WILL_REFRESH = 31; + public static final int EVENT_GROUP_REFRESH = 32; + public static final int EVENT_DUNGEON_REWARD_GET = 33; + public static final int EVENT_SPECIFIC_GADGET_HP_CHANGE = 34; + public static final int EVENT_MONSTER_TIDE_OVER = 35; + public static final int EVENT_MONSTER_TIDE_CREATE = 36; + public static final int EVENT_MONSTER_TIDE_DIE = 37; + public static final int EVENT_SEALAMP_PHASE_CHANGE = 38; + public static final int EVENT_BLOSSOM_PROGRESS_FINISH = 39; + public static final int EVENT_BLOSSOM_CHEST_DIE = 40; + public static final int EVENT_GADGET_PLAY_START = 41; + public static final int EVENT_GADGET_PLAY_START_CD = 42; + public static final int EVENT_GADGET_PLAY_STOP = 43; + public static final int EVENT_GADGET_LUA_NOTIFY = 44; + public static final int EVENT_MP_PLAY_PREPARE = 45; + public static final int EVENT_MP_PLAY_BATTLE = 46; + public static final int EVENT_MP_PLAY_PREPARE_INTERRUPT = 47; + public static final int EVENT_SELECT_DIFFICULTY = 48; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_STATE = 49; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_STAGE_CHANGE = 50; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_RESULT = 51; + public static final int EVENT_SEAL_BATTLE_PROGRESS_DECREASE = 52; + public static final int EVENT_GENERAL_REWARD_DIE = 53; + public static final int EVENT_SCENE_MP_PLAY_BATTLE_INTERRUPT = 54; + public static final int EVENT_MONSTER_DIE_BEFORE_LEAVE_SCENE = 55; + public static final int EVENT_SCENE_MP_PLAY_OPEN = 56; + public static final int EVENT_OFFERING_LEVELUP = 57; + public static final int EVENT_DUNGEON_REVIVE = 58; + public static final int EVENT_SCENE_MP_PLAY_ALL_AVATAR_DIE = 59; + public static final int EVENT_DUNGEON_ALL_AVATAR_DIE = 60; + public static final int EVENT_GENERAL_REWARD_TAKEN = 61; + public static final int EVENT_PLATFORM_REACH_ARRAYPOINT = 62; + public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_END = 63; + public static final int EVENT_SCENE_MULTISTAGE_PLAY_END_STAGE_REQ = 64; + public static final int EVENT_MECHANICUS_PICKED_CARD = 65; + public static final int EVENT_POOL_MONSTER_TIDE_OVER = 66; + public static final int EVENT_POOL_MONSTER_TIDE_CREATE = 67; + public static final int EVENT_POOL_MONSTER_TIDE_DIE = 68; + public static final int EVENT_DUNGEON_AVATAR_SLIP_DIE = 69; + public static final int EVENT_GALLERY_START = 70; + public static final int EVENT_GALLERY_STOP = 71; + public static final int EVENT_TIME_AXIS_PASS = 72; + public static final int EVENT_FLEUR_FAIR_DUNGEON_ALL_PLAYER_ENTER = 73; + public static final int EVENT_GADGETTALK_DONE = 74; + public static final int EVENT_SET_GAME_TIME = 75; + public static final int EVENT_HIDE_AND_SEEK_PLAYER_QUIT = 76; + public static final int EVENT_AVATAR_DIE = 77; + public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_START = 78; + public static final int EVENT_GALLERY_PROGRESS_PASS = 79; + public static final int EVENT_GALLERY_PROGRESS_EMPTY = 80; + public static final int EVENT_GALLERY_PROGRESS_FULL = 81; + public static final int EVENT_HUNTING_FINISH_FINAL = 82; + public static final int EVENT_USE_WIDGET_TOY_FOX_CAMERA = 83; + public static final int EVENT_LUNA_RITE_SACRIFICE = 84; + public static final int EVENT_SUMO_SWITCH_TEAM_EVENT = 85; + public static final int EVENT_FISHING_START = 86; + public static final int EVENT_FISHING_STOP = 87; + public static final int EVENT_FISHING_QTE_FINISH = 88; + public static final int EVENT_FISHING_TIMEOUT_FLEE = 89; + public static final int EVENT_ROGUE_CELL_STATE_CHANGE = 90; + public static final int EVENT_ROGUE_CELL_CONSTRUCT = 91; + public static final int EVENT_ROGUE_CELL_FINISH_SELECT_CARD = 92; + public static final int EVENT_ANY_MONSTER_CAPTURE = 93; + public static final int EVENT_ACTIVITY_INTERACT_GADGET = 94; + public static final int EVENT_CHALLENGE_PAUSE = 95; + public static final int EVENT_LEVEL_TAG_CHANGE = 96; + public static final int EVENT_CUSTOM_DUNGEON_START = 97; + public static final int EVENT_CUSTOM_DUNGEON_RESTART = 98; + public static final int EVENT_CUSTOM_DUNGEON_REACTIVE = 99; + public static final int EVENT_CUSTOM_DUNGEON_OUT_STUCK = 100; + public static final int EVENT_CUSTOM_DUNGEON_EXIT_TRY = 101; + public static final int EVENT_CUSTOM_DUNGEON_OFFICIAL_RESTART = 102; + public static final int EVENT_ANY_MONSTER_CAPTURE_AND_DISAPPEAR = 103; + public static final int EVENT_MICHIAE_INTERACT = 104; + public static final int EVENT_SELECT_UIINTERACT = 105; + public static final int EVENT_LUA_NOTIFY = 106; + public static final int EVENT_PHOTO_FINISH = 107; + public static final int EVENT_IRODORI_MASTER_READY = 108; + public static final int EVENT_ROGUE_START_FIGHT = 109; + public static final int EVENT_ROGUE_CREAGE_FIGHT_GADGET = 110; + public static final int EVENT_ROGUE_CREAGE_REPAIR_GADGET = 111; + public static final int EVENT_ROGUE_OPEN_ACCESS = 112; + public static final int EVENT_GADGET_GIVING_FINISHED = 113; + public static final int EVENT_OBSERVATION_POINT_NOTIFY = 114; + public static final int EVENT_GADGET_GIVING_TAKEBACK = 115; + public static final int EVENT_ECHO_SHELL_INTERACT = 116; + public static final int EVENT_PLATFORM_ARRIVAL = 2701; + public static final int EVENT_PLAYER_BACK_GALLERY_REVIVE_POINT = 2800; + public static final int EVENT_GALLERY_CANNOT_START_AFTER_COUNTDOWN = 2801; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/GroupKillPolicy.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/GroupKillPolicy.java new file mode 100644 index 0000000..d916514 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/GroupKillPolicy.java @@ -0,0 +1,9 @@ +package org.anime_game_servers.gi_lua.models.constants; + +public enum GroupKillPolicy { + GROUP_KILL_NONE, + GROUP_KILL_ALL, + GROUP_KILL_MONSTER, + GROUP_KILL_GADGET, + GROUP_KILL_NPC +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/ScriptGadgetState.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/ScriptGadgetState.java new file mode 100644 index 0000000..d37548d --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/ScriptGadgetState.java @@ -0,0 +1,24 @@ +package org.anime_game_servers.gi_lua.models.constants; + +public class ScriptGadgetState { + public static final int Default = 0; + public static final int GatherDrop = 1; + public static final int ChestLocked = 101; + public static final int ChestOpened = 102; + public static final int ChestTrap = 103; + public static final int ChestBramble = 104; + public static final int ChestFrozen = 105; + public static final int ChestRock = 106; + public static final int GearStart = 201; + public static final int GearStop = 202; + public static final int GearAction1 = 203; + public static final int GearAction2 = 204; + public static final int CrystalResonate1 = 301; + public static final int CrystalResonate2 = 302; + public static final int CrystalExplode = 303; + public static final int CrystalDrain = 304; + public static final int StatueActive = 401; + public static final int Action01 = 901; + public static final int Action02 = 902; + public static final int Action03 = 903; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/ScriptRegionShape.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/ScriptRegionShape.java new file mode 100644 index 0000000..f6cb714 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/ScriptRegionShape.java @@ -0,0 +1,9 @@ +package org.anime_game_servers.gi_lua.models.constants; + +public class ScriptRegionShape { + public static final int NONE = 0; + public static final int SPHERE = 1; + public static final int CUBIC = 2; + public static final int CYLINDER = 3; + public static final int POLYGON = 4; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/SealBattleType.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/SealBattleType.java new file mode 100644 index 0000000..f706463 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/SealBattleType.java @@ -0,0 +1,7 @@ +package org.anime_game_servers.gi_lua.models.constants; + +public enum SealBattleType { + NONE, + ENERGY_CHARGE, + KILL_MONSTER +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/VisionLevelType.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/VisionLevelType.java new file mode 100644 index 0000000..45616bf --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/VisionLevelType.java @@ -0,0 +1,12 @@ +package org.anime_game_servers.gi_lua.models.constants; + +public enum VisionLevelType { + VISION_LEVEL_NORMAL, + VISION_LEVEL_LITTLE_REMOTE, + VISION_LEVEL_REMOTE, + VISION_LEVEL_SUPER, + VISION_LEVEL_NEARBY, + VISION_LEVEL_SUPER_NEARBY, + VISION_LEVEL_SUPER_NUM, + +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/ExhibitionPlayType.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/ExhibitionPlayType.java new file mode 100644 index 0000000..0d0faad --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/ExhibitionPlayType.java @@ -0,0 +1,6 @@ +package org.anime_game_servers.gi_lua.models.constants.temporary; + +public enum ExhibitionPlayType { + Challenge, + Gallery, +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/FlowSuiteOperatePolicy.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/FlowSuiteOperatePolicy.java new file mode 100644 index 0000000..ea636fb --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/FlowSuiteOperatePolicy.java @@ -0,0 +1,6 @@ +package org.anime_game_servers.gi_lua.models.constants.temporary; + +public enum FlowSuiteOperatePolicy { + DEFAULT, + COMPLETE +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/GalleryProgressScoreType.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/GalleryProgressScoreType.java new file mode 100644 index 0000000..73f9b89 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/GalleryProgressScoreType.java @@ -0,0 +1,6 @@ +package org.anime_game_servers.gi_lua.models.constants.temporary; + +public enum GalleryProgressScoreType { + GALLERY_PROGRESS_SCORE_NONE, + GALLERY_PROGRESS_SCORE_NO_DEGRADE +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/GalleryProgressScoreUIType.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/GalleryProgressScoreUIType.java new file mode 100644 index 0000000..ca8a1a2 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/models/constants/temporary/GalleryProgressScoreUIType.java @@ -0,0 +1,10 @@ +package org.anime_game_servers.gi_lua.models.constants.temporary; + +public enum GalleryProgressScoreUIType { + GALLERY_PROGRESS_SCORE_UI_TYPE_NONE, + GALLERY_PROGRESS_SCORE_UI_TYPE_BUOYANT_COMBAT, + GALLERY_PROGRESS_SCORE_UI_TYPE_SUMO_STAGE, + GALLERY_PROGRESS_SCORE_UI_TYPE_DIG, + GALLERY_PROGRESS_SCORE_UI_TYPE_CRYSTAL_LINK, + GALLERY_PROGRESS_SCORE_UI_TYPE_TREASURE; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ActivityOpenAndCloseTime.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ActivityOpenAndCloseTime.java new file mode 100644 index 0000000..98dd984 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ActivityOpenAndCloseTime.java @@ -0,0 +1,11 @@ +package org.anime_game_servers.gi_lua.script_lib; + +import lombok.Data; + +import java.util.Date; + +@Data +public class ActivityOpenAndCloseTime { + private Date openTime; + private Date closeTime; +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ControllerLuaContext.kt b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ControllerLuaContext.kt new file mode 100644 index 0000000..6bf66dc --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ControllerLuaContext.kt @@ -0,0 +1,5 @@ +package org.anime_game_servers.gi_lua.script_lib + +interface ControllerLuaContext : LuaContext { + val gadget:GadgetEntity +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/GroupEventLuaContext.kt b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/GroupEventLuaContext.kt new file mode 100644 index 0000000..e7ae8b5 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/GroupEventLuaContext.kt @@ -0,0 +1,10 @@ +package org.anime_game_servers.gi_lua.script_lib + +import org.anime_game_servers.gi_lua.models.SceneGroup +import org.anime_game_servers.gi_lua.models.ScriptArgs +import org.anime_game_servers.lua.engine.LuaEngine + +interface GroupEventLuaContext: LuaContext { + fun getGroupInstance(): SceneGroup + fun getArgs(): ScriptArgs +} \ No newline at end of file diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/LuaContext.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/LuaContext.java new file mode 100644 index 0000000..6d1d083 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/LuaContext.java @@ -0,0 +1,8 @@ +package org.anime_game_servers.gi_lua.script_lib; + +import org.anime_game_servers.lua.engine.LuaEngine; + +public interface LuaContext { + LuaEngine getEngine(); + ScriptLibHandler getScriptLibHandler(); +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLib.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLib.java new file mode 100644 index 0000000..360d0ed --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLib.java @@ -0,0 +1,866 @@ +package org.anime_game_servers.gi_lua.script_lib; + +import lombok.val; + +import static org.anime_game_servers.gi_lua.utils.ScriptUtils.posToLua; + +public class ScriptLib { + + /** + * Context free functions + */ + + public static ScriptLibStaticHandler staticHandler; + public static void PrintLog(String msg) { + staticHandler.PrintLog(msg); + } + + public static int GetEntityType(int entityId){ + return staticHandler.GetEntityType(entityId); + } + + + /** + * Context independent functions + */ + public static void PrintContextLog(LuaContext context, String msg) { + context.getScriptLibHandler().PrintContextLog(context, msg); + } + + + /** + * GroupEventLuaContext functions + */ + + public static int SetGadgetStateByConfigId(GroupEventLuaContext context, int configId, int gadgetState) { + return context.getScriptLibHandler().SetGadgetStateByConfigId(context, configId, gadgetState); + } + + public static int SetGroupGadgetStateByConfigId(GroupEventLuaContext context, int groupId, int configId, int gadgetState) { + return context.getScriptLibHandler().SetGroupGadgetStateByConfigId(context, groupId, configId, gadgetState); + } + + public static int SetWorktopOptionsByGroupId(GroupEventLuaContext context, int groupId, int configId, Object optionsTable) { + val options = context.getEngine().getTable(optionsTable); + return context.getScriptLibHandler().SetWorktopOptionsByGroupId(context, groupId, configId, options); + } + + public static int SetWorktopOptions(GroupEventLuaContext context, Object rawTable){ + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().SetWorktopOptions(context, table); + } + + public static int DelWorktopOptionByGroupId(GroupEventLuaContext context, int groupId, int configId, int option) { + return context.getScriptLibHandler().DelWorktopOptionByGroupId(context, groupId, configId, option); + } + public static int DelWorktopOption(GroupEventLuaContext context, int var1){ + return context.getScriptLibHandler().DelWorktopOption(context, var1); + } + + // Some fields are guessed + public static int AutoMonsterTide(GroupEventLuaContext context, int challengeIndex, int groupId, Integer[] ordersConfigId, int tideCount, int sceneLimit, int param6) { + return context.getScriptLibHandler().AutoMonsterTide(context, challengeIndex, groupId, ordersConfigId, tideCount, sceneLimit, param6); + } + + public static int GoToGroupSuite(GroupEventLuaContext context, int groupId, int suite) { + return context.getScriptLibHandler().GoToGroupSuite(context, groupId, suite); + } + + public static int AddExtraGroupSuite(GroupEventLuaContext context, int groupId, int suite) { + return context.getScriptLibHandler().AddExtraGroupSuite(context, groupId, suite); + } + public static int RemoveExtraGroupSuite(GroupEventLuaContext context, int groupId, int suite) { + return context.getScriptLibHandler().RemoveExtraGroupSuite(context, groupId, suite); + } + public static int KillExtraGroupSuite(GroupEventLuaContext context, int groupId, int suite) { + return context.getScriptLibHandler().KillExtraGroupSuite(context, groupId, suite); + } + + public static int AddExtraFlowSuite(GroupEventLuaContext context, int groupId, int suiteId, int flowSuitePolicy){ + return context.getScriptLibHandler().AddExtraFlowSuite(context, groupId, suiteId, flowSuitePolicy); + } + public static int RemoveExtraFlowSuite(GroupEventLuaContext context, int groupId, int suiteId, int flowSuitePolicy){ + return context.getScriptLibHandler().RemoveExtraFlowSuite(context, groupId, suiteId, flowSuitePolicy); + } + public static int KillExtraFlowSuite(GroupEventLuaContext context, int groupId, int suiteId, int flowSuitePolicy){ + return context.getScriptLibHandler().KillExtraFlowSuite(context, groupId, suiteId, flowSuitePolicy); + } + + public static int ActiveChallenge(GroupEventLuaContext context, int challengeIndex, int challengeId, int timeLimitOrGroupId, int groupId, int objectiveKills, int param5) { + return context.getScriptLibHandler().ActiveChallenge(context, challengeIndex, challengeId, timeLimitOrGroupId, groupId, objectiveKills, param5); + } + + public static int StartChallenge(GroupEventLuaContext context, int challengeIndex, int challengeId, Object challengeParams) { + val conditionParamTable = context.getEngine().getTable(challengeParams); + return context.getScriptLibHandler().StartChallenge(context, challengeIndex, challengeId, conditionParamTable); + } + + public static int StopChallenge(GroupEventLuaContext context, int challengeIndex, int result) { + return context.getScriptLibHandler().StopChallenge(context, challengeIndex, result); + } + + /** + * Adds or removed time from the challenge + * TODO verify and implement + * @param context + * @param challengeId The active target challenges id + * @param duration The duration to add or remove + * @return 0 if success, 1 if no challenge is active, 2 if the challenge id doesn't match the active challenge, + * 3 if modifying the duration failed + */ + public static int AddChallengeDuration(GroupEventLuaContext context, int challengeId, int duration) { + return context.getScriptLibHandler().AddChallengeDuration(context, challengeId, duration); + } + + public static int GetGroupMonsterCountByGroupId(GroupEventLuaContext context, int groupId) { + return context.getScriptLibHandler().GetGroupMonsterCountByGroupId(context, groupId); + } + + // TODO check existence + public static int CreateVariable(GroupEventLuaContext context, String type, Object value) { + //TODO implement + switch (type){ + case "int": + default: + } + return 0; + } + // TODO check existence + public static int SetVariableValue(GroupEventLuaContext context, int var1) { + //TODO implement var1 type + return 0; + } + public static int GetVariableValue(GroupEventLuaContext context, int var1) { + //TODO implement var1 type + return 0; + } + + public static int GetGroupVariableValue(GroupEventLuaContext context, String var) { + return context.getScriptLibHandler().GetGroupVariableValue(context, var); + } + + public static int GetGroupVariableValueByGroup(GroupEventLuaContext context, String name, int groupId){ + return context.getScriptLibHandler().GetGroupVariableValueByGroup(context, name, groupId); + } + + public static int SetGroupVariableValue(GroupEventLuaContext context, String varName, int value) { + return context.getScriptLibHandler().SetGroupVariableValue(context, varName, value); + } + + public static int SetGroupVariableValueByGroup(GroupEventLuaContext context, String key, int value, int groupId){ + return context.getScriptLibHandler().SetGroupVariableValueByGroup(context, key, value, groupId); + } + + public static int ChangeGroupVariableValue(GroupEventLuaContext context, String varName, int value) { + return context.getScriptLibHandler().ChangeGroupVariableValue(context, varName, value); + } + + public static int ChangeGroupVariableValueByGroup(GroupEventLuaContext context, String name, int value, int groupId){ + return context.getScriptLibHandler().ChangeGroupVariableValueByGroup(context, name, value, groupId); + } + + + /** + * Set the actions and triggers to designated group + */ + public static int RefreshGroup(GroupEventLuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().RefreshGroup(context, table); + } + + public static int GetRegionEntityCount(GroupEventLuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().GetRegionEntityCount(context, table); + } + + public int GetRegionConfigId(GroupEventLuaContext context, Object rawTable){ + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().GetRegionConfigId(context, table); + } + + public static int TowerCountTimeStatus(GroupEventLuaContext context, int isDone, int var2){ + return context.getScriptLibHandler().TowerCountTimeStatus(context, isDone, var2); + } + public static int GetGroupMonsterCount(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetGroupMonsterCount(context); + } + + public static int SetMonsterBattleByGroup(GroupEventLuaContext context, int configId, int groupId) { + return context.getScriptLibHandler().SetMonsterBattleByGroup(context, configId, groupId); + } + + public static int CauseDungeonFail(GroupEventLuaContext context){ + return context.getScriptLibHandler().CauseDungeonFail(context); + } + + public static int SetEntityServerGlobalValueByConfigId(GroupEventLuaContext context, int cfgId, String sgvName, int value){ + return context.getScriptLibHandler().SetEntityServerGlobalValueByConfigId(context, cfgId, sgvName, value); + } + + public static int SetGroupLogicStateValue(GroupEventLuaContext context, String sgvName, int value){ + return context.getScriptLibHandler().SetGroupLogicStateValue(context, sgvName, value); + } + + public static int SetIsAllowUseSkill(GroupEventLuaContext context, int canUse){ + return context.getScriptLibHandler().SetIsAllowUseSkill(context, canUse); + } + + public static int KillEntityByConfigId(LuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().KillEntityByConfigId(context, table); + } + + public static int CreateMonster(GroupEventLuaContext context, Object rawTable){ + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().CreateMonster(context, table); + } + + public static int TowerMirrorTeamSetUp(GroupEventLuaContext context, int team, int var1) { + return context.getScriptLibHandler().TowerMirrorTeamSetUp(context, team, var1); + } + + public static int CreateGadget(GroupEventLuaContext context, Object rawTable){ + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().CreateGadget(context, table); + } + + public static int CheckRemainGadgetCountByGroupId(GroupEventLuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().CheckRemainGadgetCountByGroupId(context, table); + } + + public static int GetGadgetStateByConfigId(GroupEventLuaContext context, int groupId, int configId){ + return context.getScriptLibHandler().GetGadgetStateByConfigId(context, groupId, configId); + } + + public static int MarkPlayerAction(GroupEventLuaContext context, int var1, int var2, int var3){ + return context.getScriptLibHandler().MarkPlayerAction(context, var1, var2, var3); + } + + public static int AddQuestProgress(GroupEventLuaContext context, String eventNotifyName){ + return context.getScriptLibHandler().AddQuestProgress(context, eventNotifyName); + } + + /** + * change the state of gadget + */ + public static int ChangeGroupGadget(GroupEventLuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().ChangeGroupGadget(context, table); + } + + public static int GetSceneOwnerUid(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetSceneOwnerUid(context); + } + + public static int GetHostQuestState(GroupEventLuaContext context, int questId){ + return context.getScriptLibHandler().GetHostQuestState(context, questId); + } + + public static int GetQuestState(GroupEventLuaContext context, int entityId, int questId){ + return context.getScriptLibHandler().GetQuestState(context, entityId, questId); + } + + public static int ShowReminder(GroupEventLuaContext context, int reminderId){ + return context.getScriptLibHandler().ShowReminder(context, reminderId); + } + + public static int RemoveEntityByConfigId(GroupEventLuaContext context, int groupId, int entityType, int configId){ + return context.getScriptLibHandler().RemoveEntityByConfigId(context, groupId, entityType, configId); + } + + public static int CreateGroupTimerEvent(GroupEventLuaContext context, int groupID, String source, double time) { + return context.getScriptLibHandler().CreateGroupTimerEvent(context, groupID, source, time); + } + + public static int CancelGroupTimerEvent(GroupEventLuaContext context, int groupID, String source) { + return context.getScriptLibHandler().CancelGroupTimerEvent(context, groupID, source); + } + + public static int GetGroupSuite(GroupEventLuaContext context, int groupId) { + return context.getScriptLibHandler().GetGroupSuite(context, groupId); + } + public static int SetGroupReplaceable(GroupEventLuaContext context, int groupId, boolean value) { + return context.getScriptLibHandler().SetGroupReplaceable(context, groupId, value); + } + + public static Object GetSceneUidList(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetSceneUidList(context); + } + + public static int GetSeaLampActivityPhase(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetSeaLampActivityPhase(context); + } + public static int GadgetPlayUidOp(GroupEventLuaContext context, int groupId, int gadget_crucible, int var3, int var4, String var5, int var6 ){ + return context.getScriptLibHandler().GadgetPlayUidOp(context, groupId, gadget_crucible, var3, var4, var5, var6); + } + public static long GetServerTime(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetServerTime(context); + } + public static long GetServerTimeByWeek(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetServerTimeByWeek(context); + } + public static int GetCurTriggerCount(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetCurTriggerCount(context); + } + public static int GetChannellerSlabLoopDungeonLimitTime(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetChannellerSlabLoopDungeonLimitTime(context); + } + public static boolean IsPlayerAllAvatarDie(GroupEventLuaContext context, int sceneUid){ + return context.getScriptLibHandler().IsPlayerAllAvatarDie(context, sceneUid); + } + + public static int sendShowCommonTipsToClient(GroupEventLuaContext context, String title, String content, int closeTime) { + return context.getScriptLibHandler().sendShowCommonTipsToClient(context, title, content, closeTime); + } + + public static int sendCloseCommonTipsToClient(GroupEventLuaContext context){ + return context.getScriptLibHandler().sendCloseCommonTipsToClient(context); + } + + public static int CreateFatherChallenge(GroupEventLuaContext context, int challengeIndex, int challengeId, int timeLimit, Object conditionTable){ + val conditionLuaTable = context.getEngine().getTable(conditionTable); + return context.getScriptLibHandler().CreateFatherChallenge(context, challengeIndex, challengeId, timeLimit, conditionLuaTable); + } + public static int StartFatherChallenge(GroupEventLuaContext context, int challengeIndex){ + return context.getScriptLibHandler().StartFatherChallenge(context, challengeIndex); + } + public static int ModifyFatherChallengeProperty(GroupEventLuaContext context, int challengeId, int propertyTypeIndex, int value){ + return context.getScriptLibHandler().ModifyFatherChallengeProperty(context, challengeId, propertyTypeIndex, value); + } + public static int AttachChildChallenge(GroupEventLuaContext context, int fatherChallengeIndex, int childChallengeIndex, + int childChallengeId, Object var4Table, Object var5Table, Object var6Table){ + val conditionArray = context.getEngine().getTable(var4Table); + val var5 = context.getEngine().getTable(var5Table); + val conditionTable = context.getEngine().getTable(var6Table); + return context.getScriptLibHandler().AttachChildChallenge(context, fatherChallengeIndex, childChallengeIndex, + childChallengeId, conditionArray, var5, conditionTable); + } + public static int CreateEffigyChallengeMonster(GroupEventLuaContext context, int var1, Object var2Table){ + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().CreateEffigyChallengeMonster(context, var1, var2); + } + public static int GetEffigyChallengeMonsterLevel(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetEffigyChallengeMonsterLevel(context); + } + public static int AddTeamEntityGlobalFloatValue(GroupEventLuaContext context, Object sceneUidListTable, String var2, int var3){ + val sceneUidList = context.getEngine().getTable(sceneUidListTable); + return context.getScriptLibHandler().AddTeamEntityGlobalFloatValue(context, sceneUidList, var2, var3); + } + public static int CreateBlossomChestByGroupId(GroupEventLuaContext context, int groupId, int chestConfigId){ + return context.getScriptLibHandler().CreateBlossomChestByGroupId(context, groupId, chestConfigId); + } + public static int GetBlossomScheduleStateByGroupId(GroupEventLuaContext context, int groupId){ + return context.getScriptLibHandler().GetBlossomScheduleStateByGroupId(context, groupId); + } + public static int SetBlossomScheduleStateByGroupId(GroupEventLuaContext context, int groupId, int state){ + return context.getScriptLibHandler().SetBlossomScheduleStateByGroupId(context, groupId, state); + } + public static int RefreshBlossomGroup(GroupEventLuaContext context, Object rawTable) { + val configTable = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().RefreshBlossomGroup(context, configTable); + } + public static int RefreshBlossomDropRewardByGroupId(GroupEventLuaContext context, int groupId){ + return context.getScriptLibHandler().RefreshBlossomDropRewardByGroupId(context, groupId); + } + public static int AddBlossomScheduleProgressByGroupId(GroupEventLuaContext context, int groupId){ + return context.getScriptLibHandler().AddBlossomScheduleProgressByGroupId(context, groupId); + } + public static int GetBlossomRefreshTypeByGroupId(GroupEventLuaContext context, int groupId){ + return context.getScriptLibHandler().GetBlossomRefreshTypeByGroupId(context, groupId); + } + public static int RefreshHuntingClueGroup(GroupEventLuaContext context){ + return context.getScriptLibHandler().RefreshHuntingClueGroup(context); + } + public static int GetHuntingMonsterExtraSuiteIndexVec(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetHuntingMonsterExtraSuiteIndexVec(context); + } + public static int SetGroupTempValue(GroupEventLuaContext context, String name, int value, Object var3Table) { + val var3 = context.getEngine().getTable(var3Table); + return context.getScriptLibHandler().SetGroupTempValue(context, name, value, var3); + } + public static int GetGroupTempValue(GroupEventLuaContext context, String name, Object var2Table) { + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().GetGroupTempValue(context, name, var2); + } + + public static int FinishExpeditionChallenge(GroupEventLuaContext context){ + return context.getScriptLibHandler().FinishExpeditionChallenge(context); + } + public static int ExpeditionChallengeEnterRegion(GroupEventLuaContext context, boolean var1){ + return context.getScriptLibHandler().ExpeditionChallengeEnterRegion(context, var1); + } + + public static int StartSealBattle(GroupEventLuaContext context, int gadgetId, Object var2Table) { + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().StartSealBattle(context, gadgetId, var2); + } + + public static int InitTimeAxis(GroupEventLuaContext context, String var1, Object var2Table, boolean var3){ + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().InitTimeAxis(context, var1, var2, var3); + } + public static int EndTimeAxis(GroupEventLuaContext context, String var1){ + return context.getScriptLibHandler().EndTimeAxis(context, var1); + } + + public static int SetTeamEntityGlobalFloatValue(GroupEventLuaContext context, Object sceneUidListTable, String var2, int var3){ + val sceneUidList = context.getEngine().getTable(sceneUidListTable); + return context.getScriptLibHandler().SetTeamEntityGlobalFloatValue(context, sceneUidList, var2, var3); + } + + public static int SetTeamServerGlobalValue(GroupEventLuaContext context, int sceneUid, String var2, int var3){ + return context.getScriptLibHandler().SetTeamServerGlobalValue(context, sceneUid, var2, var3); + } + + public static int AddTeamServerGlobalValue(GroupEventLuaContext context, int ownerId, String sgvName, int value){ + return context.getScriptLibHandler().AddTeamServerGlobalValue(context, ownerId, sgvName, value); + } + + public static int GetTeamServerGlobalValue(GroupEventLuaContext context, int ownerId, String sgvName, int value){ + return context.getScriptLibHandler().GetTeamServerGlobalValue(context, ownerId, sgvName, value); + } + + public static int GetLanternRiteValue(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetLanternRiteValue(context); + } + + public static int CreateMonsterFaceAvatar(GroupEventLuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().CreateMonsterFaceAvatar(context, table); + } + + public static int ChangeToTargetLevelTag(GroupEventLuaContext context, int var1){ + return context.getScriptLibHandler().ChangeToTargetLevelTag(context, var1); + } + + public static int AddSceneTag(GroupEventLuaContext context, int sceneId, int sceneTagId){ + return context.getScriptLibHandler().AddSceneTag(context, sceneId, sceneTagId); + } + + public static int DelSceneTag(GroupEventLuaContext context, int sceneId, int sceneTagId){ + return context.getScriptLibHandler().DelSceneTag(context, sceneId, sceneTagId); + } + + public static boolean CheckSceneTag(GroupEventLuaContext context, int sceneId, int sceneTagId){ + return context.getScriptLibHandler().CheckSceneTag(context, sceneId, sceneTagId); + } + public static int StartHomeGallery(GroupEventLuaContext context, int galleryId, int uid){ + return context.getScriptLibHandler().StartHomeGallery(context, galleryId, uid); + } + + public static int StartGallery(GroupEventLuaContext context, int galleryId){ + return context.getScriptLibHandler().StartGallery(context, galleryId); + } + + public static int StopGallery(GroupEventLuaContext context, int galleryId, boolean var2){ + return context.getScriptLibHandler().StopGallery(context, galleryId, var2); + } + + public static int UpdatePlayerGalleryScore(GroupEventLuaContext context, int galleryId, Object var2Table) { + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().UpdatePlayerGalleryScore(context, galleryId, var2); + } + public static int InitGalleryProgressScore(GroupEventLuaContext context, String name, int galleryId, Object progressTable, + int scoreUiTypeIndex, int scoreTypeIndex) { + val progress = context.getEngine().getTable(progressTable); + return context.getScriptLibHandler().InitGalleryProgressScore(context, name, galleryId, progress, scoreUiTypeIndex, scoreTypeIndex); + } + public static int InitGalleryProgressWithScore(GroupEventLuaContext context, String name, int galleryId, Object progressTable, + int maxProgress, int scoreUiTypeIndex, int scoreTypeIndex) { + val progress = context.getEngine().getTable(progressTable); + return context.getScriptLibHandler().InitGalleryProgressWithScore(context, name, galleryId, progress, maxProgress, scoreUiTypeIndex, scoreTypeIndex); + } + public static int AddGalleryProgressScore(GroupEventLuaContext context, String name, int galleryId, int score) { + return context.getScriptLibHandler().AddGalleryProgressScore(context, name, galleryId, score); + } + public static int GetGalleryProgressScore(GroupEventLuaContext context, String name, int galleryId) { + return context.getScriptLibHandler().GetGalleryProgressScore(context, name, galleryId); + } + public static int SetHandballGalleryBallPosAndRot(GroupEventLuaContext context, int galleryId, Object positionTable, Object rotationTable){ + val position = context.getEngine().getTable(positionTable); + val rotation = context.getEngine().getTable(rotationTable); + return context.getScriptLibHandler().SetHandballGalleryBallPosAndRot(context, galleryId, position, rotation); + } + + public static int UnlockFloatSignal(GroupEventLuaContext context, int groupId, int gadgetSignalId){ + return context.getScriptLibHandler().UnlockFloatSignal(context, groupId, gadgetSignalId); + } + + public static int SendServerMessageByLuaKey(GroupEventLuaContext context, String var1, Object var2Table){ + var var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().SendServerMessageByLuaKey(context, var1, var2); + } + + public static int TryReallocateEntityAuthority(GroupEventLuaContext context, int uid, int endConfig, int var3){ + return context.getScriptLibHandler().TryReallocateEntityAuthority(context, uid, endConfig, var3); + } + + public static int ForceRefreshAuthorityByConfigId(GroupEventLuaContext context, int var1, int uid){ + return context.getScriptLibHandler().ForceRefreshAuthorityByConfigId(context, var1, uid); + } + + public static int AddPlayerGroupVisionType(GroupEventLuaContext context, Object uidsTable, Object var2Table){ + val uids = context.getEngine().getTable(uidsTable); + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().AddPlayerGroupVisionType(context, uids, var2); + } + + public static int DelPlayerGroupVisionType(GroupEventLuaContext context, Object uidsTable, Object var2Table){ + val uids = context.getEngine().getTable(uidsTable); + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().DelPlayerGroupVisionType(context, uids, var2); + } + + public static int MoveAvatarByPointArray(GroupEventLuaContext context, int uid, int targetId, Object var3Table, String var4){ + val var3 = context.getEngine().getTable(var3Table); + return context.getScriptLibHandler().MoveAvatarByPointArray(context, uid, targetId, var3, var4); + } + + public static int MovePlayerToPos(GroupEventLuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().MovePlayerToPos(context, table); + } + + public static int TransPlayerToPos(GroupEventLuaContext context, Object rawTable) { + val var1 = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().TransPlayerToPos(context, var1); + } + + public static int PlayCutScene(GroupEventLuaContext context, int cutsceneId, int var2){ + return context.getScriptLibHandler().PlayCutScene(context, cutsceneId, var2); + } + + public static int PlayCutSceneWithParam(GroupEventLuaContext context, int cutsceneId, int var2, Object var3Table){ + val var3 = context.getEngine().getTable(var3Table); + return context.getScriptLibHandler().PlayCutSceneWithParam(context, cutsceneId, var2, var3); + } + + public static int ScenePlaySound(GroupEventLuaContext context, Object soundInfoTable) { + val soundInfo = context.getEngine().getTable(soundInfoTable); + return context.getScriptLibHandler().ScenePlaySound(context, soundInfo); + } + + public static int BeginCameraSceneLook(GroupEventLuaContext context, Object sceneLookParamsTable){ + val sceneLookParams = context.getEngine().getTable(sceneLookParamsTable); + return context.getScriptLibHandler().BeginCameraSceneLook(context, sceneLookParams); + } + + public int ClearPlayerEyePoint(GroupEventLuaContext context, int var1){ + return context.getScriptLibHandler().ClearPlayerEyePoint(context, var1); + } + + public static int ShowReminderRadius(GroupEventLuaContext context, int var1, Object var2Table, int var3){ + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().ShowReminderRadius(context, var1, var2, var3); + } + public static int ShowClientGuide(GroupEventLuaContext context, String guideName){ + return context.getScriptLibHandler().ShowClientGuide(context, guideName); + } + + /** + * Activates a dungeon checkpoint. + * @param context a group event lua context + * @param pointId the scene point id of the dungeon checkpoint + * @return 0 if successful, 1 if dungeon manager is null, 2 if dungeon manager failed to activate the checkpoint + */ + public static int ActivateDungeonCheckPoint(GroupEventLuaContext context, int pointId){ + return context.getScriptLibHandler().ActivateDungeonCheckPoint(context, pointId); + } + + public static int SetWeatherAreaState(GroupEventLuaContext context, int var1, int var2){ + return context.getScriptLibHandler().SetWeatherAreaState(context, var1, var2); + } + + public static int EnterWeatherArea(GroupEventLuaContext context, int weatherAreaId){ + return context.getScriptLibHandler().EnterWeatherArea(context, weatherAreaId); + } + + public static boolean CheckIsInMpMode(GroupEventLuaContext context){ + return context.getScriptLibHandler().CheckIsInMpMode(context); + } + + /** + * TODO properly implement + * var3 might contain the next point, sometimes is a single int, sometimes multiple ints as array + * var4 has RouteType route_type, bool turn_mode + */ + public static int SetPlatformPointArray(GroupEventLuaContext context, int entityConfigId, int pointArrayId, Object var3Table, Object var4Table){ + val var3 = context.getEngine().getTable(var3Table); + val var4 = context.getEngine().getTable(var4Table); + return context.getScriptLibHandler().SetPlatformPointArray(context, entityConfigId, pointArrayId, var3, var4); + } + + //TODO check + public static int SetPlatformRouteId(GroupEventLuaContext context, int entityConfigId, int routeId){ + return context.getScriptLibHandler().SetPlatformRouteId(context, entityConfigId, routeId); + } + + //TODO check + public static int StartPlatform(GroupEventLuaContext context, int configId){ + return context.getScriptLibHandler().StartPlatform(context, configId); + } + + //TODO check + public static int StopPlatform(GroupEventLuaContext context, int configId){ + return context.getScriptLibHandler().StopPlatform(context, configId); + } + + public static int CreateChannellerSlabCampRewardGadget(GroupEventLuaContext context, int configId){ + return context.getScriptLibHandler().CreateChannellerSlabCampRewardGadget(context, configId); + } + + public static int AssignPlayerShowTemplateReminder(GroupEventLuaContext context, int var1, Object var2Table){ + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().AssignPlayerShowTemplateReminder(context, var1, var2); + } + + public static int RevokePlayerShowTemplateReminder(GroupEventLuaContext context, int var1, Object var2Table){ + val var2 = context.getEngine().getTable(var2Table); + return context.getScriptLibHandler().RevokePlayerShowTemplateReminder(context, var1, var2); + } + + public static int UnlockForce(GroupEventLuaContext context, int force){ + return context.getScriptLibHandler().UnlockForce(context, force); + } + + public static int LockForce(GroupEventLuaContext context, int force){ + return context.getScriptLibHandler().LockForce(context, force); + } + + public static int KillGroupEntity(GroupEventLuaContext context, Object rawTable) { + val table = context.getEngine().getTable(rawTable); + return context.getScriptLibHandler().KillGroupEntity(context, table); + } + + public static int GetGadgetIdByEntityId(GroupEventLuaContext context, int entityId){ + return context.getScriptLibHandler().GetGadgetIdByEntityId(context, entityId); + } + public static int GetMonsterIdByEntityId(GroupEventLuaContext context, int entityId){ + return context.getScriptLibHandler().GetMonsterIdByEntityId(context, entityId); + } + public static int GetMonsterConfigId(GroupEventLuaContext context, int entityId){ + return context.getScriptLibHandler().GetMonsterConfigId(context, entityId); + } + public static int GetMonsterID(GroupEventLuaContext context, int var1){ + return context.getScriptLibHandler().GetMonsterID(context, var1); + } + public static int GetEntityIdByConfigId(GroupEventLuaContext context, int configId){ + return context.getScriptLibHandler().GetEntityIdByConfigId(context, configId); + } + public static int GetAvatarEntityIdByUid(GroupEventLuaContext context, int uid){ + return context.getScriptLibHandler().GetAvatarEntityIdByUid(context, uid); + } + + + + public static Object GetPosByEntityId(GroupEventLuaContext context, int entityId){ + val pos = context.getScriptLibHandler().GetPosByEntityId(context, entityId); + return posToLua(pos, context.getEngine()).getRawTable(); + } + + public static Object GetRotationByEntityId(GroupEventLuaContext context, int entityId){ + val rot = context.getScriptLibHandler().GetPosByEntityId(context, entityId); + return posToLua(rot, context.getEngine()).getRawTable(); + } + + public static Object GetActivityOpenAndCloseTimeByScheduleId(GroupEventLuaContext context, int scheduleId){ + var result = context.getEngine().createTable(); + var activityConfig = context.getScriptLibHandler().GetActivityOpenAndCloseTimeByScheduleId(context, scheduleId); + + if(activityConfig != null){ + result.set(1, activityConfig.getOpenTime().getTime()); + result.set(2, activityConfig.getCloseTime().getTime()); + } + + return result.getRawTable(); + } + + public static int GetGameHour(GroupEventLuaContext context){ + return context.getScriptLibHandler().GetGameHour(context); + } + + public static int ActivateGroupLinkBundle(GroupEventLuaContext context, int groupId){ + return context.getScriptLibHandler().ActivateGroupLinkBundle(context, groupId); + } + public static int ActivateGroupLinkBundleByBundleId(GroupEventLuaContext context, int bundleId){ + return context.getScriptLibHandler().ActivateGroupLinkBundleByBundleId(context, bundleId); + } + + /** + * TODO implement + * @param context + * @param givingId The id if the giving element found in [GivingData] + * @param groupId The groupdId of the group containing the gadget + * @param gadgetCfgId The gadgets target configId + * @return 0 if success, something else if failed + */ + public static int ActiveGadgetItemGiving(GroupEventLuaContext context, int givingId, int groupId, int gadgetCfgId){ + return context.getScriptLibHandler().ActiveGadgetItemGiving(context, givingId, groupId, gadgetCfgId); + } + + public static int AddChessBuildingPoints(GroupEventLuaContext context, int groupId, int param2, int uid, int pointsToAdd){ + return context.getScriptLibHandler().AddChessBuildingPoints(context, groupId, param2, uid, pointsToAdd); + } + + public static int AddEntityGlobalFloatValueByConfigId(GroupEventLuaContext context, Object param1Table, String param2, int param3){ + val param1 = context.getEngine().getTable(param1Table); + return context.getScriptLibHandler().AddEntityGlobalFloatValueByConfigId(context, param1, param2, param3); + } + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @return + */ + public static int AddExhibitionAccumulableData(GroupEventLuaContext context, int uid, String param2, int param3){ + return context.getScriptLibHandler().AddExhibitionAccumulableData(context, uid, param2, param3); + } + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @param param4Table contains the fields "play_type" is part of the enum [ExhibitionPlayType] and "gallery_id" + * @return + */ + public static int AddExhibitionAccumulableDataAfterSuccess(GroupEventLuaContext context, int uid, String param2, int param3, Object param4Table){ + val param4 = context.getEngine().getTable(param4Table); + return context.getScriptLibHandler().AddExhibitionAccumulableDataAfterSuccess(context, uid, param2, param3, param4); + } + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @return + */ + public static int AddExhibitionReplaceableData(GroupEventLuaContext context, int uid, String param2, int param3){ + return context.getScriptLibHandler().AddExhibitionReplaceableData(context, uid, param2, param3); + } + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @param param4Table contains the fields "play_type" is part of the enum [ExhibitionPlayType] and "gallery_id" + * @return + */ + public static int AddExhibitionReplaceableDataAfterSuccess(GroupEventLuaContext context, int uid, String param2, int param3, Object param4Table){ + val param4 = context.getEngine().getTable(param4Table); + return context.getScriptLibHandler().AddExhibitionReplaceableDataAfterSuccess(context, uid, param2, param3, param4); + } + + public static int AddFleurFairMultistagePlayBuffEnergy(GroupEventLuaContext context, int groupId, int param2, int uid, int bonusId){ + return context.getScriptLibHandler().AddFleurFairMultistagePlayBuffEnergy(context, groupId, param2, uid, bonusId); + } + + public static int AddGadgetPlayProgress(GroupEventLuaContext context, int param1, int param2, int progressChange){ + return context.getScriptLibHandler().AddGadgetPlayProgress(context, param1, param2, progressChange); + } + + public static int AddIrodoriChessBuildingPoints(GroupEventLuaContext context, int groupId, int param2, int points){ + return context.getScriptLibHandler().AddIrodoriChessBuildingPoints(context, groupId, param2, points); + } + public static int AddIrodoriChessTowerServerGlobalValue(GroupEventLuaContext context, int groupId, int param2, int param3, int delta){ + return context.getScriptLibHandler().AddIrodoriChessTowerServerGlobalValue(context, groupId, param2, param3, delta); + } + public static int AddMechanicusBuildingPoints(GroupEventLuaContext context, int groupId, int param2, int uid, int delta){ + return context.getScriptLibHandler().AddMechanicusBuildingPoints(context, groupId, param2, uid, delta); + } + + public static int AddRegionRecycleProgress(GroupEventLuaContext context, int regionId, int delta){ + return context.getScriptLibHandler().AddRegionRecycleProgress(context, regionId, delta); + } + public static int AddRegionSearchProgress(GroupEventLuaContext context, int regionId, int delta){ + return context.getScriptLibHandler().AddRegionSearchProgress(context, regionId, delta); + } + public static int AddRegionalPlayVarValue(GroupEventLuaContext context, int uid, int regionId, int delta){ + return context.getScriptLibHandler().AddRegionalPlayVarValue(context, uid, regionId, delta); + } + public static int AddSceneMultiStagePlayUidValue(GroupEventLuaContext context, int groupId, int param2, String param3, int uid, int param5){ + return context.getScriptLibHandler().AddSceneMultiStagePlayUidValue(context, groupId, param2, param3, uid, param5); + } + public static int AddScenePlayBattleProgress(GroupEventLuaContext context, int groupId, int progress){ + return context.getScriptLibHandler().AddScenePlayBattleProgress(context, groupId, progress); + } + + /** + * TODO implement + * @param context + * @param param1Table contains the following fields: param_index:int, param_list:Table, param_uid_list:Table, + * duration:int, target_uid_list:Table + * @return + */ + public static int AssignPlayerUidOpNotify(GroupEventLuaContext context, Object param1Table){ + val param1 = context.getEngine().getTable(param1Table); + return context.getScriptLibHandler().AssignPlayerUidOpNotify(context, param1); + } + + + /** + * Methods used in EntityControllers/using ControllerLuaContext + */ + + public static int SetGadgetState(ControllerLuaContext context, int gadgetState) { + return context.getScriptLibHandler().SetGadgetState(context, gadgetState); + } + + public static int GetGadgetState(ControllerLuaContext context) { + return context.getScriptLibHandler().GetGadgetState(context); + } + + public static int ResetGadgetState(ControllerLuaContext context, int gadgetState) { + return context.getScriptLibHandler().ResetGadgetState(context, gadgetState); + } + + public static int SetGearStartValue(ControllerLuaContext context, int startValue) { + return context.getScriptLibHandler().SetGearStartValue(context, startValue); + } + + public static int GetGearStartValue(ControllerLuaContext context) { + return context.getScriptLibHandler().GetGearStartValue(context); + } + + public static int SetGearStopValue(ControllerLuaContext context, int startValue) { + return context.getScriptLibHandler().SetGearStopValue(context, startValue); + } + + public static int GetGearStopValue(ControllerLuaContext context) { + return context.getScriptLibHandler().GetGearStopValue(context); + } + + public static int GetGadgetStateBeginTime(ControllerLuaContext context) { + return context.getScriptLibHandler().GetGadgetStateBeginTime(context); + } + + public static int GetContextGadgetConfigId(ControllerLuaContext context) { + return context.getScriptLibHandler().GetContextGadgetConfigId(context); + } + + public static int GetContextGroupId(ControllerLuaContext context) { + return context.getScriptLibHandler().GetContextGroupId(context); + } + + public static int SetGadgetEnableInteract(ControllerLuaContext context, int groupId, int configId, boolean enable) { + return context.getScriptLibHandler().SetGadgetEnableInteract(context, groupId, configId, enable); + } + + public static int DropSubfield(ControllerLuaContext context, Object paramsTable) { + val params = context.getEngine().getTable(paramsTable); + return context.getScriptLibHandler().DropSubfield(context, params); + } + + public static int[] GetGatherConfigIdList(ControllerLuaContext context) { + return context.getScriptLibHandler().GetGatherConfigIdList(context); + } +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLibHandler.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLibHandler.java new file mode 100644 index 0000000..a352c06 --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLibHandler.java @@ -0,0 +1,402 @@ +package org.anime_game_servers.gi_lua.script_lib; + +import org.anime_game_servers.gi_lua.models.Position; +import org.anime_game_servers.lua.engine.LuaTable; + +@SuppressWarnings("unused") +public interface ScriptLibHandler { + + /** + * Context independent functions + */ + void PrintContextLog(LuaContext context, String msg); + + + /** + * GroupEventLuaContext functions + */ + + int SetGadgetStateByConfigId(GroupEventLuaContext context, int configId, int gadgetState); + int SetGroupGadgetStateByConfigId(GroupEventLuaContext context, int groupId, int configId, int gadgetState); + int SetWorktopOptionsByGroupId(GroupEventLuaContext context, int groupId, int configId, LuaTable options); + int SetWorktopOptions(GroupEventLuaContext context, LuaTable table); + + int DelWorktopOptionByGroupId(GroupEventLuaContext context, int groupId, int configId, int option); + int DelWorktopOption(GroupEventLuaContext context, int var1); + + // Some fields are guessed + int AutoMonsterTide(GroupEventLuaContext context, int challengeIndex, int groupId, Integer[] ordersConfigId, int tideCount, int sceneLimit, int param6); + int GoToGroupSuite(GroupEventLuaContext context, int groupId, int suite); + + int AddExtraGroupSuite(GroupEventLuaContext context, int groupId, int suite); + int RemoveExtraGroupSuite(GroupEventLuaContext context, int groupId, int suite); + int KillExtraGroupSuite(GroupEventLuaContext context, int groupId, int suite); + + int AddExtraFlowSuite(GroupEventLuaContext context, int groupId, int suiteId, int flowSuitePolicy); + int RemoveExtraFlowSuite(GroupEventLuaContext context, int groupId, int suiteId, int flowSuitePolicy); + int KillExtraFlowSuite(GroupEventLuaContext context, int groupId, int suiteId, int flowSuitePolicy); + + int ActiveChallenge(GroupEventLuaContext context, int challengeIndex, int challengeId, int timeLimitOrGroupId, int groupId, int objectiveKills, int param5); + + int StartChallenge(GroupEventLuaContext context, int challengeIndex, int challengeId, LuaTable challengeParams); + + int StopChallenge(GroupEventLuaContext context, int challengeIndex, int result); + + /** + * Adds or removed time from the challenge + * TODO verify and implement + * @param context + * @param challengeId The active target challenges id + * @param duration The duration to add or remove + * @return 0 if success, 1 if no challenge is active, 2 if the challenge id doesn't match the active challenge, + * 3 if modifying the duration failed + */ + int AddChallengeDuration(GroupEventLuaContext context, int challengeId, int duration); + + int GetGroupMonsterCountByGroupId(GroupEventLuaContext context, int groupId); + + int CreateVariable(GroupEventLuaContext context, String type, LuaTable value); + int SetVariableValue(GroupEventLuaContext context, int var1); + int GetVariableValue(GroupEventLuaContext context, int var1); + + int GetGroupVariableValue(GroupEventLuaContext context, String var); + + int GetGroupVariableValueByGroup(GroupEventLuaContext context, String name, int groupId); + + int SetGroupVariableValue(GroupEventLuaContext context, String varName, int value); + + int SetGroupVariableValueByGroup(GroupEventLuaContext context, String key, int value, int groupId); + + int ChangeGroupVariableValue(GroupEventLuaContext context, String varName, int value); + + int ChangeGroupVariableValueByGroup(GroupEventLuaContext context, String name, int value, int groupId); + + + /** + * Set the actions and triggers to designated group + */ + int RefreshGroup(GroupEventLuaContext context, LuaTable table); + + int GetRegionEntityCount(GroupEventLuaContext context, LuaTable table); + + int GetRegionConfigId(GroupEventLuaContext context, LuaTable table); + + int TowerCountTimeStatus(GroupEventLuaContext context, int isDone, int var2); + int GetGroupMonsterCount(GroupEventLuaContext context); + + int SetMonsterBattleByGroup(GroupEventLuaContext context, int configId, int groupId); + + int CauseDungeonFail(GroupEventLuaContext context); + + int SetEntityServerGlobalValueByConfigId(GroupEventLuaContext context, int cfgId, String sgvName, int value); + + int SetGroupLogicStateValue(GroupEventLuaContext context, String sgvName, int value); + + int SetIsAllowUseSkill(GroupEventLuaContext context, int canUse); + + int KillEntityByConfigId(LuaContext context, LuaTable table); + + int CreateMonster(GroupEventLuaContext context, LuaTable table); + + int TowerMirrorTeamSetUp(GroupEventLuaContext context, int team, int var1) ; + + int CreateGadget(GroupEventLuaContext context, LuaTable table); + + int CheckRemainGadgetCountByGroupId(GroupEventLuaContext context, LuaTable table); + + int GetGadgetStateByConfigId(GroupEventLuaContext context, int groupId, int configId); + + int MarkPlayerAction(GroupEventLuaContext context, int var1, int var2, int var3); + int AddQuestProgress(GroupEventLuaContext context, String eventNotifyName); + + /** + * change the state of gadget + */ + int ChangeGroupGadget(GroupEventLuaContext context, LuaTable table) ; + + int GetSceneOwnerUid(GroupEventLuaContext context); + int GetHostQuestState(GroupEventLuaContext context, int questId); + int GetQuestState(GroupEventLuaContext context, int entityId, int questId); + int ShowReminder(GroupEventLuaContext context, int reminderId); + int RemoveEntityByConfigId(GroupEventLuaContext context, int groupId, int entityType, int configId); + int CreateGroupTimerEvent(GroupEventLuaContext context, int groupID, String source, double time); + int CancelGroupTimerEvent(GroupEventLuaContext context, int groupID, String source); + + int GetGroupSuite(GroupEventLuaContext context, int groupId); + int SetGroupReplaceable(GroupEventLuaContext context, int groupId, boolean value) ; + Object GetSceneUidList(GroupEventLuaContext context); + int GetSeaLampActivityPhase(GroupEventLuaContext context); + int GadgetPlayUidOp(GroupEventLuaContext context, int groupId, int gadget_crucible, int var3, int var4, String var5, int var6 ); + long GetServerTime(GroupEventLuaContext context); + long GetServerTimeByWeek(GroupEventLuaContext context); + int GetCurTriggerCount(GroupEventLuaContext context); + int GetChannellerSlabLoopDungeonLimitTime(GroupEventLuaContext context); + boolean IsPlayerAllAvatarDie(GroupEventLuaContext context, int sceneUid); + + int sendShowCommonTipsToClient(GroupEventLuaContext context, String title, String content, int closeTime); + + int sendCloseCommonTipsToClient(GroupEventLuaContext context); + int CreateFatherChallenge(GroupEventLuaContext context, int challengeIndex, int challengeId, int timeLimit, LuaTable conditionTable); + int StartFatherChallenge(GroupEventLuaContext context, int challengeIndex); + int ModifyFatherChallengeProperty(GroupEventLuaContext context, int challengeId, int propertyTypeIndex, int value); + int AttachChildChallenge(GroupEventLuaContext context, int fatherChallengeIndex, int childChallengeIndex, + int childChallengeId, LuaTable var4, LuaTable var5, LuaTable var6); + int CreateEffigyChallengeMonster(GroupEventLuaContext context, int var1, LuaTable var2Table); + int GetEffigyChallengeMonsterLevel(GroupEventLuaContext context); + int AddTeamEntityGlobalFloatValue(GroupEventLuaContext context, LuaTable sceneUidListTable, String var2, int var3); + int CreateBlossomChestByGroupId(GroupEventLuaContext context, int groupId, int chestConfigId); + int GetBlossomScheduleStateByGroupId(GroupEventLuaContext context, int groupId); + int SetBlossomScheduleStateByGroupId(GroupEventLuaContext context, int groupId, int state); + int RefreshBlossomGroup(GroupEventLuaContext context, LuaTable table); + int RefreshBlossomDropRewardByGroupId(GroupEventLuaContext context, int groupId); + int AddBlossomScheduleProgressByGroupId(GroupEventLuaContext context, int groupId); + int GetBlossomRefreshTypeByGroupId(GroupEventLuaContext context, int groupId); + int RefreshHuntingClueGroup(GroupEventLuaContext context); + int GetHuntingMonsterExtraSuiteIndexVec(GroupEventLuaContext context); + int SetGroupTempValue(GroupEventLuaContext context, String name, int value, LuaTable var3Table); + int GetGroupTempValue(GroupEventLuaContext context, String name, LuaTable var2); + + int FinishExpeditionChallenge(GroupEventLuaContext context); + int ExpeditionChallengeEnterRegion(GroupEventLuaContext context, boolean var1); + int StartSealBattle(GroupEventLuaContext context, int gadgetId, LuaTable var2); + + int InitTimeAxis(GroupEventLuaContext context, String var1, LuaTable var2, boolean var3); + int EndTimeAxis(GroupEventLuaContext context, String var1); + + int SetTeamEntityGlobalFloatValue(GroupEventLuaContext context, LuaTable sceneUidListTable, String var2, int var3); + + int SetTeamServerGlobalValue(GroupEventLuaContext context, int sceneUid, String var2, int var3); + + int AddTeamServerGlobalValue(GroupEventLuaContext context, int ownerId, String sgvName, int value); + + int GetTeamServerGlobalValue(GroupEventLuaContext context, int ownerId, String sgvName, int value); + + int GetLanternRiteValue(GroupEventLuaContext context); + + int CreateMonsterFaceAvatar(GroupEventLuaContext context, LuaTable table); + + int ChangeToTargetLevelTag(GroupEventLuaContext context, int var1); + + int AddSceneTag(GroupEventLuaContext context, int sceneId, int sceneTagId); + + int DelSceneTag(GroupEventLuaContext context, int sceneId, int sceneTagId); + + boolean CheckSceneTag(GroupEventLuaContext context, int sceneId, int sceneTagId); + int StartHomeGallery(GroupEventLuaContext context, int galleryId, int uid); + + int StartGallery(GroupEventLuaContext context, int galleryId); + + int StopGallery(GroupEventLuaContext context, int galleryId, boolean var2); + + int UpdatePlayerGalleryScore(GroupEventLuaContext context, int galleryId, LuaTable var2); + int InitGalleryProgressScore(GroupEventLuaContext context, String name, int galleryId, LuaTable progressTable, + int scoreUiTypeIndex, int scoreTypeIndex); + int InitGalleryProgressWithScore(GroupEventLuaContext context, String name, int galleryId, LuaTable progress, + int maxProgress, int scoreUiTypeIndex, int scoreTypeIndex); + int AddGalleryProgressScore(GroupEventLuaContext context, String name, int galleryId, int score); + int GetGalleryProgressScore(GroupEventLuaContext context, String name, int galleryId) ; + int SetHandballGalleryBallPosAndRot(GroupEventLuaContext context, int galleryId, LuaTable positionTable, LuaTable rotationTable); + + int UnlockFloatSignal(GroupEventLuaContext context, int groupId, int gadgetSignalId); + + int SendServerMessageByLuaKey(GroupEventLuaContext context, String var1, LuaTable var2); + + int TryReallocateEntityAuthority(GroupEventLuaContext context, int uid, int endConfig, int var3); + + int ForceRefreshAuthorityByConfigId(GroupEventLuaContext context, int var1, int uid); + + int AddPlayerGroupVisionType(GroupEventLuaContext context, LuaTable uidsTable, LuaTable var2); + + int DelPlayerGroupVisionType(GroupEventLuaContext context, LuaTable uidsTable, LuaTable var2); + + int MoveAvatarByPointArray(GroupEventLuaContext context, int uid, int targetId, LuaTable var3, String var4); + + int MovePlayerToPos(GroupEventLuaContext context, LuaTable table); + + int TransPlayerToPos(GroupEventLuaContext context, LuaTable table); + + int PlayCutScene(GroupEventLuaContext context, int cutsceneId, int var2); + + int PlayCutSceneWithParam(GroupEventLuaContext context, int cutsceneId, int var2, LuaTable var3); + + int ScenePlaySound(GroupEventLuaContext context, LuaTable soundInfoTable); + + int BeginCameraSceneLook(GroupEventLuaContext context, LuaTable sceneLookParamsTable); + + public int ClearPlayerEyePoint(GroupEventLuaContext context, int var1); + + int ShowReminderRadius(GroupEventLuaContext context, int var1, LuaTable var2, int var3); + int ShowClientGuide(GroupEventLuaContext context, String guideName); + + /** + * Activates a dungeon checkpoint. + * @param context a group event lua context + * @param pointId the scene point id of the dungeon checkpoint + * @return 0 if successful, 1 if dungeon manager is null, 2 if dungeon manager failed to activate the checkpoint + */ + int ActivateDungeonCheckPoint(GroupEventLuaContext context, int pointId); + + //TODO check + int SetWeatherAreaState(GroupEventLuaContext context, int var1, int var2); + + int EnterWeatherArea(GroupEventLuaContext context, int weatherAreaId); + + //TODO check + boolean CheckIsInMpMode(GroupEventLuaContext context); + + /** + * TODO properly implement + * var3 might contain the next point, sometimes is a single int, sometimes multiple ints as array + * var4 has RouteType route_type, bool turn_mode + */ + int SetPlatformPointArray(GroupEventLuaContext context, int entityConfigId, int pointArrayId, LuaTable var3, LuaTable var4); + + //TODO check + int SetPlatformRouteId(GroupEventLuaContext context, int entityConfigId, int routeId); + + //TODO check + int StartPlatform(GroupEventLuaContext context, int configId); + + //TODO check + int StopPlatform(GroupEventLuaContext context, int configId); + + int CreateChannellerSlabCampRewardGadget(GroupEventLuaContext context, int configId); + + int AssignPlayerShowTemplateReminder(GroupEventLuaContext context, int var1, LuaTable var2); + + int RevokePlayerShowTemplateReminder(GroupEventLuaContext context, int var1, LuaTable var2); + + int UnlockForce(GroupEventLuaContext context, int force); + + int LockForce(GroupEventLuaContext context, int force); + + int KillGroupEntity(GroupEventLuaContext context, LuaTable table); + int GetGadgetIdByEntityId(GroupEventLuaContext context, int entityId); + int GetMonsterIdByEntityId(GroupEventLuaContext context, int entityId); + int GetMonsterConfigId(GroupEventLuaContext context, int entityId); + int GetMonsterID(GroupEventLuaContext context, int var1); + int GetEntityIdByConfigId(GroupEventLuaContext context, int configId); + int GetAvatarEntityIdByUid(GroupEventLuaContext context, int uid); + + + Position GetPosByEntityId(GroupEventLuaContext context, int entityId); + + Position GetRotationByEntityId(GroupEventLuaContext context, int entityId); + + ActivityOpenAndCloseTime GetActivityOpenAndCloseTimeByScheduleId(GroupEventLuaContext context, int scheduleId); + + int GetGameHour(GroupEventLuaContext context); + + int ActivateGroupLinkBundle(GroupEventLuaContext context, int groupId); + int ActivateGroupLinkBundleByBundleId(GroupEventLuaContext context, int bundleId); + + /** + * TODO implement + * @param context + * @param givingId The id if the giving element found in [GivingData] + * @param groupId The groupdId of the group containing the gadget + * @param gadgetCfgId The gadgets target configId + * @return 0 if success, something else if failed + */ + int ActiveGadgetItemGiving(GroupEventLuaContext context, int givingId, int groupId, int gadgetCfgId); + + int AddChessBuildingPoints(GroupEventLuaContext context, int groupId, int param2, int uid, int pointsToAdd); + + int AddEntityGlobalFloatValueByConfigId(GroupEventLuaContext context, Object param1Table, String param2, int param3); + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @return + */ + int AddExhibitionAccumulableData(GroupEventLuaContext context, int uid, String param2, int param3); + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @param param4 contains the fields "play_type" is part of the enum [ExhibitionPlayType] and "gallery_id" + * @return + */ + int AddExhibitionAccumulableDataAfterSuccess(GroupEventLuaContext context, int uid, String param2, int param3, LuaTable param4); + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @return + */ + int AddExhibitionReplaceableData(GroupEventLuaContext context, int uid, String param2, int param3); + + /** + * TODO implement + * @param context + * @param uid + * @param param2 probably the name of the data field + * @param param3 + * @param param4 contains the fields "play_type" is part of the enum [ExhibitionPlayType] and "gallery_id" + * @return + */ + int AddExhibitionReplaceableDataAfterSuccess(GroupEventLuaContext context, int uid, String param2, int param3, LuaTable param4); + + int AddFleurFairMultistagePlayBuffEnergy(GroupEventLuaContext context, int groupId, int param2, int uid, int bonusId); + + int AddGadgetPlayProgress(GroupEventLuaContext context, int param1, int param2, int progressChange); + + int AddIrodoriChessBuildingPoints(GroupEventLuaContext context, int groupId, int param2, int points); + int AddIrodoriChessTowerServerGlobalValue(GroupEventLuaContext context, int groupId, int param2, int param3, int delta); + int AddMechanicusBuildingPoints(GroupEventLuaContext context, int groupId, int param2, int uid, int delta); + + int AddRegionRecycleProgress(GroupEventLuaContext context, int regionId, int delta); + int AddRegionSearchProgress(GroupEventLuaContext context, int regionId, int delta); + int AddRegionalPlayVarValue(GroupEventLuaContext context, int uid, int regionId, int delta); + int AddSceneMultiStagePlayUidValue(GroupEventLuaContext context, int groupId, int param2, String param3, int uid, int param5); + int AddScenePlayBattleProgress(GroupEventLuaContext context, int groupId, int progress); + + /** + * TODO implement + * @param context + * @param param1Table contains the following fields: param_index:int, param_list:Table, param_uid_list:Table, + * duration:int, target_uid_list:Table + * @return + */ + int AssignPlayerUidOpNotify(GroupEventLuaContext context, LuaTable param1Table); + + + /** + * Methods used in EntityControllers/using ControllerLuaContext + */ + + int SetGadgetState(ControllerLuaContext context, int gadgetState); + + int GetGadgetState(ControllerLuaContext context); + + int ResetGadgetState(ControllerLuaContext context, int gadgetState) ; + + int SetGearStartValue(ControllerLuaContext context, int startValue); + + int GetGearStartValue(ControllerLuaContext context); + + int SetGearStopValue(ControllerLuaContext context, int startValue); + + int GetGearStopValue(ControllerLuaContext context) ; + + int GetGadgetStateBeginTime(ControllerLuaContext context); + + int GetContextGadgetConfigId(ControllerLuaContext context) ; + + int GetContextGroupId(ControllerLuaContext context); + + int SetGadgetEnableInteract(ControllerLuaContext context, int groupId, int configId, boolean enable); + + int DropSubfield(ControllerLuaContext context, LuaTable paramsTable); + + int[] GetGatherConfigIdList(ControllerLuaContext context); +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLibStaticHandler.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLibStaticHandler.java new file mode 100644 index 0000000..f005b3c --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/script_lib/ScriptLibStaticHandler.java @@ -0,0 +1,6 @@ +package org.anime_game_servers.gi_lua.script_lib; + +public interface ScriptLibStaticHandler { + void PrintLog(String msg); + int GetEntityType(int entityId); +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/utils/GIScriptLoader.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/utils/GIScriptLoader.java new file mode 100644 index 0000000..e9e905f --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/utils/GIScriptLoader.java @@ -0,0 +1,8 @@ +package org.anime_game_servers.gi_lua.utils; + +import org.anime_game_servers.lua.engine.LuaScript; +import org.anime_game_servers.lua.models.ScriptType; + +public interface GIScriptLoader { + LuaScript getSceneScript(int sceneId, String scriptName, ScriptType scriptType); +} diff --git a/GILua/src/main/java/org/anime_game_servers/gi_lua/utils/ScriptUtils.java b/GILua/src/main/java/org/anime_game_servers/gi_lua/utils/ScriptUtils.java new file mode 100644 index 0000000..2f051cb --- /dev/null +++ b/GILua/src/main/java/org/anime_game_servers/gi_lua/utils/ScriptUtils.java @@ -0,0 +1,37 @@ +package org.anime_game_servers.gi_lua.utils; + +import lombok.val; +import org.anime_game_servers.gi_lua.models.Position; +import org.anime_game_servers.lua.engine.LuaEngine; +import org.anime_game_servers.lua.engine.LuaTable; + +import java.util.HashMap; + +public class ScriptUtils { + + public static LuaTable posToLua(Position position, LuaEngine engine){ + var result = engine.createTable(); + if(position != null){ + result.set("x", position.getX()); + result.set("y", position.getY()); + result.set("z", position.getZ()); + } else { + result.set("x", 0); + result.set("y", 0); + result.set("z", 0); + } + + return result; + } + + public static Position luaToPos(LuaTable position){ + val result = new Position(); + if(position != null){ + result.setX(position.optInt("x", 0)); + result.setY(position.optInt("y", 0)); + result.setZ(position.optInt("z", 0)); + } + + return result; + } +} diff --git a/JNLuaEngine/build.gradle.kts b/JNLuaEngine/build.gradle.kts new file mode 100644 index 0000000..ddfc36e --- /dev/null +++ b/JNLuaEngine/build.gradle.kts @@ -0,0 +1,37 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("java-library") + kotlin("jvm") version "1.9.10" +} + +group = "org.anime_game_servers" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(platform("org.junit:junit-bom:5.9.1")) + testImplementation("org.junit.jupiter:junit-jupiter") + implementation(project(":BaseLua")) + implementation("com.google.code.findbugs:jsr305:3.0.2") + implementation("org.anime_game_servers:JNLua_GC:0.1.0") + implementation(kotlin("stdlib-jdk8")) + compileOnly("org.projectlombok:lombok:1.18.30") + annotationProcessor("org.projectlombok:lombok:1.18.30") + implementation("com.esotericsoftware:reflectasm:1.11.9") +} + +tasks.test { + useJUnitPlatform() +} +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "1.8" +} +val compileTestKotlin: KotlinCompile by tasks +compileTestKotlin.kotlinOptions { + jvmTarget = "1.8" +} \ No newline at end of file diff --git a/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaConverter.java b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaConverter.java new file mode 100644 index 0000000..b2d4968 --- /dev/null +++ b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaConverter.java @@ -0,0 +1,76 @@ +package org.anime_game_servers.jnlua_engine; + +import lombok.Getter; +import lombok.val; +import org.terasology.jnlua.Converter; +import org.terasology.jnlua.DefaultConverter; +import org.terasology.jnlua.LuaState; + +import java.util.Map; + +public class JNLuaConverter implements Converter { + @Getter private static final JNLuaConverter INSTANCE = new JNLuaConverter(); + final Converter defaultConverter = DefaultConverter.getInstance(); + @Override + public int getTypeDistance(LuaState luaState, int i, Class aClass) { + return defaultConverter.getTypeDistance(luaState, i, aClass); + } + + @Override + public T convertLuaValue(LuaState luaState, int i, Class aClass) { + return defaultConverter.convertLuaValue(luaState, i, aClass); + } + + @Override + public void convertJavaObject(LuaState luaState, Object 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(); + for (var entry : fields.entrySet()) { + luaState.pushInteger((Integer) entry.getValue()); + luaState.setField(-2, (String) entry.getKey()); + } + return; + } + } /*else if (o instanceof ScriptLib lib) { + luaState.newTable(); + val methods = lib.getClass().getMethods(); + Arrays.stream(methods).forEach(m -> { + val isStatic = Modifier.isStatic(m.getModifiers()); + class TempFunc implements NamedJavaFunction { + @Override + public String getName() { + return m.getName(); + } + + @SneakyThrows + @Override + public int invoke(LuaState luaState) { + var argSize = luaState.getTop(); + List args = new ArrayList<>(); + for (int i = 0; i < argSize; ++i) { + args.add(luaState.checkJavaObject(i + 1, Object.class)); + } + try { + Object caller = isStatic ? null : o; + Object ret = m.invoke(caller, args.toArray()); + luaState.pushJavaObject(ret); + } catch (Exception e) { + //LuaEngine.logger.error("Error on invoking binding function. ", e); + throw e; + } + return 1; + } + } + val func = new TempFunc(); + luaState.pushJavaFunction(func); + luaState.setField(-2, func.getName()); + } + ); + + return; + }*/ + defaultConverter.convertJavaObject(luaState, o); + } +} diff --git a/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaEngine.java b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaEngine.java new file mode 100644 index 0000000..f35f919 --- /dev/null +++ b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaEngine.java @@ -0,0 +1,107 @@ +package org.anime_game_servers.jnlua_engine; + +import lombok.Getter; +import org.anime_game_servers.lua.engine.LuaEngine; +import org.anime_game_servers.lua.engine.LuaScript; +import org.anime_game_servers.lua.engine.LuaTable; +import org.anime_game_servers.lua.models.IntValueEnum; +import org.anime_game_servers.lua.models.ScriptType; +import org.anime_game_servers.lua.serialize.Serializer; +import org.jetbrains.annotations.Nullable; +import org.terasology.jnlua.JavaFunction; + +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; +import java.nio.file.Path; +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class JNLuaEngine implements LuaEngine { + @Getter + private final ScriptEngineManager manager; + @Getter(onMethod = @__(@Override)) + private final JNLuaSerializer serializer; + @Getter + private final SimpleBindings bindings; + + public JNLuaEngine() { + manager = new ScriptEngineManager(); + bindings = new SimpleBindings(); + this.serializer = new JNLuaSerializer(); + + bindings.put("print", (JavaFunction) luaState -> { + //logger.debug("[LUA] print {} ", luaState.checkString(1)); + return 1; + }); + + } + + @Override + public > boolean addGlobalEnumByOrdinal(String name, T[] enumArray) { + Map table = new HashMap<>(); + Arrays.stream(enumArray).forEach(e -> { + table.put(e.name(), e.ordinal()); + table.put(e.name().toUpperCase(), e.ordinal()); + }); + bindings.put(name, table); + return true; + } + + @Override + public & IntValueEnum> boolean addGlobalEnumByIntValue(String name, T[] enumArray) { + Map table = new HashMap<>(); + Arrays.stream(enumArray).forEach(e -> { + table.put(e.name(), e.getValue()); + table.put(e.name().toUpperCase(), e.getValue()); + }); + bindings.put(name, table); + return true; + } + + @Override + public boolean addGlobalStaticClass(String name, Class staticClass) { + try { + bindings.put(name, staticClass.getConstructor().newInstance()); + return true; + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + //logger.error("Failed to add static class to lua engine: " + name, e); + } + return false; + } + + @Override + public boolean addObject(String name, Object object) { + bindings.put(name, object); + return false; + } + + @Nullable + @Override + public LuaScript getScript(String scriptName, ScriptType scriptType) { + final Path scriptPath = scriptFinder.getScriptPath(scriptName); + if (!Files.exists(scriptPath)) return null; + + try { + return new JNLuaScript(this, scriptPath, scriptType); + } catch (IOException | ScriptException e) { + throw new RuntimeException(e); + } + } + + @Override + public LuaTable getTable(Object table) { + return new JNLuaTable((AbstractMap) table); + } + + @Override + public LuaTable createTable() { + return new JNLuaTable(new HashMap<>()); + } +} diff --git a/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaRequireCommonFunction.java b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaRequireCommonFunction.java new file mode 100644 index 0000000..1bb788c --- /dev/null +++ b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaRequireCommonFunction.java @@ -0,0 +1,39 @@ +package org.anime_game_servers.jnlua_engine; + +import lombok.val; +import org.terasology.jnlua.LuaState; +import org.terasology.jnlua.NamedJavaFunction; + +import java.io.IOException; +import java.nio.file.Files; + +import static org.anime_game_servers.lua.engine.LuaEngine.scriptFinder; + +public class JNLuaRequireCommonFunction implements NamedJavaFunction { + public static final JNLuaRequireCommonFunction INSTANCE = new JNLuaRequireCommonFunction(); + @Override + public int invoke(LuaState luaState) { + val requiredName = luaState.checkString(1); + luaState.remove(1); + val path = "Common/" + requiredName + ".lua"; + val includePath = scriptFinder.getScriptPath(path); + if (!Files.exists(includePath)) { + //LuaEngine.logger.error("Require script not found. {}", path); + return 1; + } + try { + val includeScript = Files.newInputStream(includePath); + luaState.load(includeScript, requiredName, "t"); + luaState.call(0, 0); + } catch (IOException e) { + //LuaEngine.logger.error("Error on loading require script. {}", path, e); + return 2; + } + return 0; + } + + @Override + public String getName() { + return "require"; + } +} diff --git a/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaScript.java b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaScript.java new file mode 100644 index 0000000..910ce00 --- /dev/null +++ b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaScript.java @@ -0,0 +1,101 @@ +package org.anime_game_servers.jnlua_engine; + +import lombok.val; +import org.anime_game_servers.lua.engine.LuaEngine; +import org.anime_game_servers.lua.engine.LuaScript; +import org.anime_game_servers.lua.engine.LuaValue; +import org.anime_game_servers.lua.models.BooleanLuaValue; +import org.anime_game_servers.lua.models.IntLuaValue; +import org.anime_game_servers.lua.models.ScriptType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.terasology.jnlua.script.CompiledLuaScript; +import org.terasology.jnlua.script.LuaBindings; +import org.terasology.jnlua.script.LuaScriptEngine; + +import javax.script.*; +import java.io.IOException; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +public class JNLuaScript implements LuaScript { + + final Reader scriptReader; + @Nullable + private final CompiledLuaScript compiledScript; + private final LuaBindings binding; + private final JNLuaEngine engine; + private final LuaScriptEngine scriptEngine; + SimpleScriptContext context = new SimpleScriptContext(); + + JNLuaScript(JNLuaEngine engine, Path scriptPath, ScriptType scriptType) throws ScriptException, IOException { + this.engine = engine; + this.scriptEngine = (LuaScriptEngine) engine.getManager().getEngineByName("jnlua"); + if(scriptType.getAddDefaultGlobals()) { + context.setBindings(engine.getBindings(), ScriptContext.GLOBAL_SCOPE); + } + this.binding = (LuaBindings) scriptEngine.createBindings(); + context.setBindings(binding, ScriptContext.ENGINE_SCOPE); + val luaState = binding.getLuaState(); + luaState.setConverter(JNLuaConverter.getINSTANCE()); + + val requireFunction = JNLuaRequireCommonFunction.INSTANCE; + binding.put(requireFunction.getName(), requireFunction); + scriptReader = Files.newBufferedReader(scriptPath); + if(scriptType.getPrecompile()) { + this.compiledScript = (CompiledLuaScript) ((Compilable) scriptEngine).compile(scriptReader); + } else { + this.compiledScript = null; + } + } + + @Override + public boolean hasMethod(@NotNull String methodName) { + return binding.containsKey(methodName); + } + + @Nullable + @Override + public LuaValue callMethod(@NotNull String methodName, Object... args) throws ScriptException, NoSuchMethodException { + val result = ((Invocable) scriptEngine).invokeFunction(methodName, args); + if (result instanceof Boolean) { + return ((Boolean) result) ? BooleanLuaValue.TRUE : BooleanLuaValue.FALSE; + } else if (result instanceof Integer) { + return new IntLuaValue((Integer) result); + } + //TODO + return null; + } + + @Override + public void evaluate() throws ScriptException { + if(compiledScript != null) { + compiledScript.eval(context); + } else { + scriptEngine.eval(scriptReader, context); + } + } + + @Override + public T getGlobalVariable(String name, Class type) { + return engine.getSerializer().toObject(type, binding.get(name)); + } + + @Override + public List getGlobalVariableList(String name, Class type) { + return engine.getSerializer().toList(type, binding.get(name)); + } + + @Override + public Map getGlobalVariableMap(String name, Class type) { + return engine.getSerializer().toMap(type, binding.get(name)); + } + + @Override + public LuaEngine getEngine() { + return engine; + } +} diff --git a/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaSerializer.java b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaSerializer.java new file mode 100644 index 0000000..1c2bb1d --- /dev/null +++ b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaSerializer.java @@ -0,0 +1,208 @@ +package org.anime_game_servers.jnlua_engine; + +import org.anime_game_servers.lua.serialize.BaseSerializer; +import org.terasology.jnlua.LuaValueProxy; +import org.terasology.jnlua.util.AbstractTableMap; + +import javax.annotation.Nullable; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; + +public class JNLuaSerializer extends BaseSerializer { + + private final ReentrantLock lock = new ReentrantLock(); + + public static Integer getInt(Object value) { + if (value instanceof Integer l) { + return l.intValue(); + } else if (value instanceof Double d) { + return d.intValue(); + } + return 0; + } + + public static Float getFloat(Object value) { + if (value instanceof Double l) { + return l.floatValue(); + } else if (value instanceof Integer l) { + return l.floatValue(); + } + return 0f; + } + + // ... + @Override + public List toList(Class type, Object obj) { + return serializeList(type, (LuaValueProxy) obj); + } + + @Override + public T toObject(Class type, Object obj) { + return serialize(type, null, (LuaValueProxy) obj); + } + + @Override + public Map toMap(Class type, Object obj) { + return serializeMap(type, (LuaValueProxy) obj); + } + + private T objectToClass(Class 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, null, (LuaValueProxy) value); + } + return object; + } + + public List serializeList(Class type, LuaValueProxy table) { + List list = new ArrayList<>(); + + if (table == null) { + return list; + } + + var tableObj = (Map) table; + try { + for (var k : tableObj.entrySet()) { + try { + var keyValue = k.getValue(); + + T object = objectToClass(type, keyValue); + + if (object != null) { + list.add(object); + } + } catch (Exception ex) { + + } + } + } catch (Exception e) { + //LuaEngine.logger.error("Exception serializing list", e); + } + + return list; + } + + private Class getListType(Class type, @Nullable Field field){ + if(field == null){ + return type.getTypeParameters()[0].getClass(); + } + Type fieldType = field.getGenericType(); + if(fieldType instanceof ParameterizedType){ + return (Class) ((ParameterizedType) fieldType).getActualTypeArguments()[0]; + } + + return null; + } + + public T serialize(Class type, @Nullable Field field, LuaValueProxy table) { + T object = null; + + if (type == List.class) { + try { + Class listType = getListType(type, field); + return (T) serializeList(listType, table); + } catch (Exception e) { + //LuaEngine.logger.error("Exception serializing", e); + return null; + } + } + + try { + if (!fieldMetaCache.containsKey(type)) { + cacheType(type); + } + var methodAccess = methodAccessCache.get(type); + var fieldMetaMap = fieldMetaCache.get(type); + + object = (T) constructorCache.get(type).newInstance(); + + if (table == null) { + return object; + } + + var tableObj = (AbstractTableMap) table; + for (var k : tableObj.entrySet()) { + try { + var keyName = k.getKey(); + if (!fieldMetaMap.containsKey(keyName)) { + continue; + } + + var fieldMeta = fieldMetaMap.get(keyName); + var keyValue = k.getValue(); + if (fieldMeta.getType().equals(float.class)) { + set(object, fieldMeta, methodAccess, getFloat(keyValue)); + } else if (fieldMeta.getType().equals(double.class)) { + set(object, fieldMeta, methodAccess, (double) keyValue); + } else if (fieldMeta.getType().equals(int.class)) { + set(object, fieldMeta, methodAccess, getInt(keyValue)); + } else if (fieldMeta.getType().equals(String.class)) { + set(object, fieldMeta, methodAccess, keyValue); + } else if (fieldMeta.getType().equals(boolean.class)) { + set(object, fieldMeta, methodAccess, (boolean) keyValue); + } else if (fieldMeta.getType().equals(List.class)) { + LuaValueProxy objTable = (LuaValueProxy) tableObj.get(k.getKey()); + Class listType = getListType(type, fieldMeta.getField()); + List listObj = serializeList(listType, objTable); + set(object, fieldMeta, methodAccess, listObj); + } else { + set(object, fieldMeta, methodAccess, serialize(fieldMeta.getType(), fieldMeta.getField(), (LuaValueProxy) keyValue)); + //methodAccess.invoke(object, fieldMeta.index, keyValue); + } + } catch (Exception ex) { + // LuaEngine.logger.error("Exception serializing", ex); + } + } + } catch (Exception e) { + //LuaEngine.logger.error("Exception serializing", e); + } + + return object; + } + + public Map serializeMap(Class type, LuaValueProxy table) { + Map map = new HashMap<>(); + + if (table == null) { + return map; + } + + var tableObj = (Map) table; + + try { + for (var k : tableObj.entrySet()) { + try { + var keyValue = k.getValue(); + + T object = objectToClass(type, keyValue); + + if (object != null) { + map.put(k.getKey(), object); + } + } catch (Exception ex) { + + } + } + } catch (Exception e) { + //LuaEngine.logger.error("Exception serializing map", e); + } + + return map; + } +} diff --git a/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaTable.java b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaTable.java new file mode 100644 index 0000000..2b7fd17 --- /dev/null +++ b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/JNLuaTable.java @@ -0,0 +1,255 @@ +package org.anime_game_servers.jnlua_engine; + +import lombok.val; +import org.anime_game_servers.lua.engine.LuaTable; +import org.jetbrains.annotations.Nullable; + +import java.util.AbstractMap; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class JNLuaTable implements LuaTable { + + AbstractMap table; + + JNLuaTable(AbstractMap table) { + this.table = (AbstractMap) table; + } + + @Override + public boolean has(String key) { + return table.containsKey(key); + } + + @Override + public Object get(String key) { + return table.get(key); + } + + @Override + public Object get(int key) { + return table.get(key); + } + + @Override + public int getInt(String key) { + return ((Number) table.get(key)).intValue(); + } + + @Override + public int optInt(String key, int defaultValue) { + val value = table.get(key); + if (value instanceof Number) + return ((Number) value).intValue(); + return defaultValue; + } + + @Override + public int getInt(int key) { + return ((Number) table.get(key)).intValue(); + } + + @Override + public int optInt(int key, int defaultValue) { + val value = table.get(key); + if (value instanceof Number) + return ((Number) value).intValue(); + return defaultValue; + } + + @Override + public void set(int key, int value) { + table.put(key, value); + } + + @Override + public void set(String key, int value) { + table.put(key, value); + } + + @Override + public double getDouble(String key) { + return ((Number) table.get(key)).doubleValue(); + } + + @Override + public double optDouble(String key, double defaultValue) { + val value = table.get(key); + if (value instanceof Number) + return ((Number) value).doubleValue(); + return defaultValue; + } + + @Override + public double getDouble(int key) { + return ((Number) table.get(key)).doubleValue(); + } + + @Override + public double optDouble(int key, double defaultValue) { + val value = table.get(key); + if (value instanceof Number) + return ((Number) value).doubleValue(); + return defaultValue; + } + + @Override + public float getFloat(String key) { + return ((Number) table.get(key)).floatValue(); + } + + @Override + public float optFloat(String key, float defaultValue) { + val value = table.get(key); + if (value instanceof Number) + return ((Number) value).floatValue(); + return defaultValue; + } + + @Override + public float getFloat(int key) { + return ((Number) table.get(key)).floatValue(); + } + + @Override + public float optFloat(int key, float defaultValue) { + val value = table.get(key); + if (value instanceof Number) + return ((Number) value).floatValue(); + return defaultValue; + } + + @Override + public void set(int key, double value) { + table.put(key, value); + } + + @Override + public void set(String key, double value) { + table.put(key, value); + } + + @Override + public boolean getBoolean(String key) { + return (Boolean) table.get(key); + } + + @Override + public boolean optBoolean(String key, boolean defaultValue) { + val value = table.get(key); + if (value instanceof Boolean) + return (boolean) value; + return defaultValue; + } + + @Override + public boolean getBoolean(int key) { + return (Boolean) table.get(key); + } + + @Override + public boolean optBoolean(int key, boolean defaultValue) { + val value = table.get(key); + if (value instanceof Boolean) + return (boolean) value; + return defaultValue; + } + + @Override + public void set(int key, boolean value) { + table.put(key, value); + } + + @Override + public void set(String key, boolean value) { + table.put(key, value); + } + + @Override + public String getString(String key) { + return (String) table.get(key); + } + + @Override + public String optString(String key, String defaultValue) { + val value = table.get(key); + if (value instanceof String) + return (String) value; + return defaultValue; + } + + @Override + public String getString(int key) { + return (String) table.get(key); + } + + @Override + public String optString(int key, String defaultValue) { + val value = table.get(key); + if (value instanceof String) + return (String) value; + return defaultValue; + } + + @Override + public void set(int key, String value) { + table.put(key, value); + } + + @Override + public void set(String key, String value) { + table.put(key, value); + } + + @Nullable + @Override + public LuaTable getTable(String key) { + return new JNLuaTable((AbstractMap) table.get(key)); + } + + @Nullable + @Override + public LuaTable getTable(int key) { + return new JNLuaTable((AbstractMap) table.get(key)); + } + + @Override + public void set(int key, LuaTable value) { + table.put(key, value.getRawTable()); + } + + @Override + public void set(String key, LuaTable value) { + table.put(key, value.getRawTable()); + } + + @Override + public Set getKeys() { + //TODO check if this is correct + val keys = table.keySet(); + if (keys != null) { + return (Set) (Set) keys; + } + return IntStream.rangeClosed(1, table.size()).mapToObj(String::valueOf).collect(Collectors.toSet()); + } + + @Override + public int[] getAsIntArray() { + int[] result = new int[table.size()]; + for (int i = 0; i < table.size(); i++) { + result[i] = (Integer) table.get(i + 1); + } + return result; + } + + @Override + public int getSize() { + return table.size(); + } + + @Override + public Object getRawTable() { + return table; + } +} diff --git a/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/ScriptBinding.java b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/ScriptBinding.java new file mode 100644 index 0000000..a271900 --- /dev/null +++ b/JNLuaEngine/src/main/java/org/anime_game_servers/jnlua_engine/ScriptBinding.java @@ -0,0 +1,102 @@ +package org.anime_game_servers.jnlua_engine; + +import com.esotericsoftware.reflectasm.MethodAccess; +import org.terasology.jnlua.LuaState; +import org.terasology.jnlua.LuaState53; +import org.terasology.jnlua.NamedJavaFunction; +import org.terasology.jnlua.script.LuaBindings; + +import javax.script.ScriptEngine; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * TODO remove? + */ +public class ScriptBinding { + final static Map, MethodAccess> methodAccessCache = new ConcurrentHashMap<>(); + + public static MethodAccess getMethodAccessByClazz(Class type) { + if (!methodAccessCache.containsKey(type)) { + methodAccessCache.putIfAbsent(type, MethodAccess.get(type)); + } + return methodAccessCache.get(type); + } + + public static void coerce(ScriptEngine engine, String bindName, Object o) { + if (o == null) { + return; + } + List bindings = new ArrayList<>(); + LuaState53 L = (LuaState53) ((LuaBindings) engine.createBindings()).getLuaState(); + + //Bind Enum. + if (o instanceof Map) { + var fields = (Map) o; + for (var enumField : fields.entrySet()) { + L.pushJavaObject(enumField.getValue()); + L.setField(-2, enumField.getKey()); + } + } else { + var methods = getMethodAccessByClazz(o.getClass()); + Arrays.stream(methods.getMethodNames()).forEach(m -> { + class TempFunc implements NamedJavaFunction { + @Override + public String getName() { + return m; + } + + @Override + public int invoke(LuaState luaState) { + var argSize = luaState.getTop(); + List args = new ArrayList<>(); + for (int i = 0; i < argSize; ++i) { + args.add(luaState.checkJavaObject(i + 1, Object.class)); + } + try { + Object ret = methods.invoke(o, m, args.toArray()); + luaState.pushJavaObject(ret); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Error on invoking binding function. " + e); + throw e; + } + return 1; + } + } + bindings.add(new TempFunc()); + } + ); + + var fields = o.getClass().getFields(); + L.newTable(); + Arrays.stream(fields).forEach(f -> { + try { + L.pushJavaObject(f.get(o)); + L.setField(-2, f.getName()); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + }); + } + + for (var func : bindings) { + String name = func.getName(); + + L.pushJavaFunction(func); + L.setField(-2, name); + } + + L.luaGetsubtable(L.REGISTRYINDEX, "_LOADED"); + L.pushValue(-2); + L.setField(-2, bindName); + L.pop(1); + L.rawGet(L.REGISTRYINDEX, 2); + L.pushValue(-2); + L.setField(-2, bindName); + L.pop(1); + } +} diff --git a/LuaJEngine/build.gradle.kts b/LuaJEngine/build.gradle.kts new file mode 100644 index 0000000..a93c4d2 --- /dev/null +++ b/LuaJEngine/build.gradle.kts @@ -0,0 +1,27 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("java-library") +} + +group = "org.anime_game_servers" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(platform("org.junit:junit-bom:5.9.1")) + testImplementation("org.junit.jupiter:junit-jupiter") + implementation(project(":BaseLua")) + implementation("com.google.code.findbugs:jsr305:3.0.2") + implementation("org.anime_game_servers:luaj:3.0.3") + compileOnly("org.projectlombok:lombok:1.18.30") + annotationProcessor("org.projectlombok:lombok:1.18.30") + implementation("com.esotericsoftware:reflectasm:1.11.9") +} + +tasks.test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJEngine.java b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJEngine.java new file mode 100644 index 0000000..044e7b8 --- /dev/null +++ b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJEngine.java @@ -0,0 +1,121 @@ +package org.anime_game_servers.luaj_engine; + +import lombok.Getter; +import lombok.val; +import org.anime_game_servers.lua.engine.LuaEngine; +import org.anime_game_servers.lua.engine.LuaScript; +import org.anime_game_servers.lua.models.IntValueEnum; +import org.anime_game_servers.lua.models.ScriptType; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.lib.ResourceFinder; +import org.luaj.vm2.lib.jse.CoerceJavaToLua; +import org.luaj.vm2.script.LuajContext; + +import javax.annotation.Nullable; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; + +public class LuaJEngine implements LuaEngine { + private final ScriptEngineManager manager; + private final LuajContext context; + + @Getter + private final ScriptEngine engine; + @Getter(onMethod = @__(@Override)) + private final LuaJSerializer serializer; + + public LuaJEngine() { + manager = new ScriptEngineManager(); + engine = manager.getEngineByName("luaj"); + + serializer = new LuaJSerializer(); + context = (LuajContext) engine.getContext(); + + // Set engine to replace require as a temporary fix to missing scripts + context.globals.finder = new ResourceFinder() { + @Override + public InputStream findResource(String filename) { + val stream = scriptFinder.openScript(filename); + return stream!=null ? stream : new ByteArrayInputStream(new byte[0]); + } + + @Override + public boolean useRawParamString() { + return true; + } + }; + } + + @Override + public > boolean addGlobalEnumByOrdinal(String name, T[] enumArray) { + LuaTable table = new LuaTable(); + Arrays.stream(enumArray).forEach(e -> { + table.set(e.name(), e.ordinal()); + table.set(e.name().toUpperCase(), e.ordinal()); + }); + context.globals.set(name, table); + return true; + } + + @Override + public & IntValueEnum> boolean addGlobalEnumByIntValue(String name, T[] enumArray) { + LuaTable table = new LuaTable(); + Arrays.stream(enumArray).forEach(e -> { + table.set(e.name(), e.getValue()); + table.set(e.name().toUpperCase(), e.getValue()); + }); + context.globals.set(name, table); + return true; + } + + @Override + public boolean addGlobalStaticClass(String name, Class staticClass) { + try { + context.globals.set(name, CoerceJavaToLua.coerce(staticClass.getConstructor().newInstance())); + return true; + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + //logger.error("Failed to add static class to lua engine: " + name, e); + } + return false; + } + + @Override + public boolean addObject(String name, Object object) { + context.globals.set(name, CoerceJavaToLua.coerce(object)); + return true; + } + + @Nullable + @Override + public LuaScript getScript(String scriptName, ScriptType scriptType) { + final Path scriptPath = scriptFinder.getScriptPath(scriptName); + if (!Files.exists(scriptPath)) return null; + + try { + return new LuaJScript(this, scriptPath); + } catch (IOException | ScriptException e) { + throw new RuntimeException(e); + } + } + + @Override + public org.anime_game_servers.lua.engine.LuaTable getTable(Object table) { + if (table instanceof LuaTable) + return new LuaJTable(this, (LuaTable) table); + throw new IllegalArgumentException("Table must be a LuaTable"); + } + + @Override + public org.anime_game_servers.lua.engine.LuaTable createTable() { + return new LuaJTable(this, new LuaTable()); + } +} diff --git a/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJScript.java b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJScript.java new file mode 100644 index 0000000..b33e0ef --- /dev/null +++ b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJScript.java @@ -0,0 +1,78 @@ +package org.anime_game_servers.luaj_engine; + +import lombok.val; +import org.anime_game_servers.lua.engine.LuaEngine; +import org.anime_game_servers.lua.engine.LuaScript; +import org.anime_game_servers.lua.engine.LuaValue; +import org.anime_game_servers.lua.models.BooleanLuaValue; +import org.luaj.vm2.lib.jse.CoerceJavaToLua; + +import javax.annotation.Nonnull; +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +public class LuaJScript implements LuaScript { + private final CompiledScript compiledScript; + private final Bindings binding; + private final LuaJEngine engine; + + public LuaJScript(LuaJEngine engine, Path scriptPath) throws IOException, ScriptException { + this.engine = engine; + this.compiledScript = ((Compilable) engine.getEngine()).compile(Files.newBufferedReader(scriptPath)); + this.binding = engine.getEngine().createBindings(); + } + + @Override + public boolean hasMethod(@Nonnull String methodName) { + return binding.containsKey(methodName) && ((org.luaj.vm2.LuaValue) binding.get(methodName)).isfunction(); + } + + @Override + public LuaValue callMethod(@Nonnull String methodName, Object... args) { + val function = (org.luaj.vm2.LuaValue) binding.get(methodName); + if (function == null || !function.isfunction()) { + //LuaEngine.logger.warn("Attempted to call method {} on script {} but it does not exist or is not a function", methodName, this); + return BooleanLuaValue.FALSE; + } + + org.luaj.vm2.LuaValue[] luaArgs; + + luaArgs = new org.luaj.vm2.LuaValue[args.length]; + for (int i = 0; i < args.length; i++) + luaArgs[i] = CoerceJavaToLua.coerce(args[i]); + + return new LuaJValue(engine, function.invoke(luaArgs).arg1()); + } + + @Override + public void evaluate() throws ScriptException { + this.compiledScript.eval(this.binding); + } + + @Override + public T getGlobalVariable(String name, Class type) { + return engine.getSerializer().toObject(type, binding.get(name)); + } + + @Override + public List getGlobalVariableList(String name, Class type) { + return engine.getSerializer().toList(type, binding.get(name)); + } + + @Override + public Map getGlobalVariableMap(String name, Class type) { + return engine.getSerializer().toMap(type, binding.get(name)); + } + + @Override + public LuaEngine getEngine() { + return engine; + } +} diff --git a/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJSerializer.java b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJSerializer.java new file mode 100644 index 0000000..8f9cb89 --- /dev/null +++ b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJSerializer.java @@ -0,0 +1,186 @@ +package org.anime_game_servers.luaj_engine; + +import org.anime_game_servers.lua.serialize.BaseSerializer; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; + +import javax.annotation.Nullable; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class LuaJSerializer extends BaseSerializer { + + + @Override + public List toList(Class type, Object obj) { + return serializeList(type, (LuaTable) obj); + } + + @Override + public T toObject(Class type, Object obj) { + return serialize(type, null, (LuaTable) obj); + } + + @Override + public Map toMap(Class type, Object obj) { + return serializeMap(type, (LuaTable) obj); + } + + @Nullable + private T valueToType(Class type, LuaValue keyValue) { + 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; + } + if (object == null) { + //LuaEngine.logger.warn("Can't serialize value: {} to type: {}", keyValue, type); + } + return object; + } + + private Map serializeMap(Class type, LuaTable table) { + Map 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); + } + } catch (Exception ex) { + + } + } + } catch (Exception e) { + //LuaEngine.logger.error("Exception while serializing map", e); + } + + return map; + } + + public List serializeList(Class type, LuaTable table) { + List list = new ArrayList<>(); + + if (table == null) { + return list; + } + + try { + LuaValue[] keys = table.keys(); + for (LuaValue k : keys) { + try { + LuaValue keyValue = table.get(k); + + T object = valueToType(type, keyValue); + + if (object != null) { + list.add(object); + } + } catch (Exception ex) { + + } + } + } catch (Exception e) { + //LuaEngine.logger.error("Exception while serializing list", e); + } + + return list; + } + + private Class getListType(Class type, @Nullable Field field) { + if (field == null) { + return type.getTypeParameters()[0].getClass(); + } + Type fieldType = field.getGenericType(); + if (fieldType instanceof ParameterizedType) { + return (Class) ((ParameterizedType) fieldType).getActualTypeArguments()[0]; + } + + return null; + } + + public T serialize(Class type, @Nullable Field field, LuaTable table) { + T object = null; + + if (type == List.class) { + try { + Class listType = getListType(type, field); + return (T) serializeList(listType, table); + } catch (Exception e) { + //LuaEngine.logger.error("Exception while serializing {}", type.getName(), e); + return null; + } + } + + try { + if (!fieldMetaCache.containsKey(type)) { + cacheType(type); + } + var methodAccess = methodAccessCache.get(type); + var fieldMetaMap = fieldMetaCache.get(type); + + object = (T) constructorCache.get(type).newInstance(); + + if (table == null) { + return object; + } + + LuaValue[] keys = table.keys(); + for (LuaValue k : keys) { + try { + var keyName = k.checkjstring(); + if (!fieldMetaMap.containsKey(keyName)) { + continue; + } + var fieldMeta = fieldMetaMap.get(keyName); + LuaValue keyValue = table.get(k); + + if (keyValue.istable()) { + set(object, fieldMeta, methodAccess, serialize(fieldMeta.getType(), fieldMeta.getField(), keyValue.checktable())); + } else if (fieldMeta.getType().equals(float.class)) { + set(object, fieldMeta, methodAccess, keyValue.tofloat()); + } else if (fieldMeta.getType().equals(int.class)) { + set(object, fieldMeta, methodAccess, keyValue.toint()); + } else if (fieldMeta.getType().equals(String.class)) { + set(object, fieldMeta, methodAccess, keyValue.tojstring()); + } else if (fieldMeta.getType().equals(boolean.class)) { + set(object, fieldMeta, methodAccess, keyValue.toboolean()); + } else { + set(object, fieldMeta, methodAccess, keyValue.tojstring()); + } + } catch (Exception ex) { + //LuaEngine.logger.error("Exception serializing", ex); + } + } + } catch (Exception e) { + //LuaEngine.logger.info(ScriptUtils.toMap(table).toString()); + //LuaEngine.logger.error("Exception while serializing {}", type.getName(), e); + } + + return object; + } +} diff --git a/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJTable.java b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJTable.java new file mode 100644 index 0000000..3f3311d --- /dev/null +++ b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJTable.java @@ -0,0 +1,228 @@ +package org.anime_game_servers.luaj_engine; + +import lombok.val; +import org.anime_game_servers.lua.engine.LuaTable; + +import java.util.Arrays; +import java.util.Set; + +public class LuaJTable implements LuaTable { + private final org.luaj.vm2.LuaTable table; + private final LuaJEngine engine; + + LuaJTable(LuaJEngine engine, org.luaj.vm2.LuaTable table) { + this.table = table; + this.engine = engine; + } + + @Override + public boolean has(String key) { + return !table.get(key).isnil(); + } + + @Override + public Object get(String key) { + return new LuaJValue(engine, table.get(key)); + } + + @Override + public Object get(int key) { + return new LuaJValue(engine, table.get(key)); + } + + @Override + public int getInt(String key) { + return table.get(key).checkint(); + } + + @Override + public int optInt(String key, int defaultValue) { + return table.get(key).optint(defaultValue); + } + + @Override + public int getInt(int key) { + return table.get(key).checkint(); + } + + @Override + public int optInt(int key, int defaultValue) { + return table.get(key).optint(defaultValue); + } + + @Override + public void set(int key, int value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public void set(String key, int value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public double getDouble(String key) { + return table.get(key).checkdouble(); + } + + @Override + public double optDouble(String key, double defaultValue) { + return table.get(key).optdouble(defaultValue); + } + + @Override + public double getDouble(int key) { + return table.get(key).checkdouble(); + } + + @Override + public double optDouble(int key, double defaultValue) { + return table.get(key).optdouble(defaultValue); + } + + @Override + public float getFloat(String key) { + return table.get(key).tofloat(); + } + + @Override + public float optFloat(String key, float defaultValue) { + return (float) table.get(key).optdouble(defaultValue); + } + + @Override + public float getFloat(int key) { + return table.get(key).tofloat(); + } + + @Override + public float optFloat(int key, float defaultValue) { + return (float) table.get(key).optdouble(defaultValue); + } + + @Override + public void set(int key, double value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public void set(String key, double value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public boolean getBoolean(String key) { + return table.get(key).toboolean(); + } + + @Override + public boolean optBoolean(String key, boolean defaultValue) { + return table.get(key).optboolean(defaultValue); + } + + @Override + public boolean getBoolean(int key) { + return table.get(key).toboolean(); + } + + @Override + public boolean optBoolean(int key, boolean defaultValue) { + return table.get(key).optboolean(defaultValue); + } + + @Override + public void set(int key, boolean value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public void set(String key, boolean value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public String getString(String key) { + return table.get(key).tojstring(); + } + + @Override + public String optString(String key, String defaultValue) { + return table.get(key).optjstring(defaultValue); + } + + @Override + public String getString(int key) { + return table.get(key).toString(); + } + + @Override + public String optString(int key, String defaultValue) { + return table.get(key).optjstring(defaultValue); + } + + @Override + public void set(int key, String value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public void set(String key, String value) { + table.set(key, org.luaj.vm2.LuaValue.valueOf(value)); + } + + @Override + public LuaTable getTable(String key) { + val variable = table.get(key); + if (!variable.istable()) { + return null; + } + return new LuaJTable(engine, variable.checktable()); + } + + @Override + public LuaTable getTable(int key) { + val variable = table.get(key); + if (!variable.istable()) { + return null; + } + return new LuaJTable(engine, variable.checktable()); + } + + @Override + public void set(int key, LuaTable value) { + val rawTable = value.getRawTable(); + if (rawTable instanceof org.luaj.vm2.LuaTable) + table.set(key, (org.luaj.vm2.LuaTable) rawTable); + } + + @Override + public void set(String key, LuaTable value) { + val rawTable = value.getRawTable(); + if (rawTable instanceof org.luaj.vm2.LuaTable) + table.set(key, (org.luaj.vm2.LuaTable) rawTable); + } + + @Override + public Set getKeys() { + return Arrays.stream(table.keys()).map(org.luaj.vm2.LuaValue::tojstring).collect(java.util.stream.Collectors.toSet()); + } + + @Override + public int[] getAsIntArray() { + val array = new int[table.length()]; + for (int i = 0; i < array.length; i++) { + array[i] = table.get(i + 1).optint(0); + } + return array; + } + + @Override + public int getSize() { + return table.length(); + } + + @Override + public Object getRawTable() { + return table; + } +} diff --git a/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJValue.java b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJValue.java new file mode 100644 index 0000000..d62d052 --- /dev/null +++ b/LuaJEngine/src/main/java/org/anime_game_servers/luaj_engine/LuaJValue.java @@ -0,0 +1,92 @@ +package org.anime_game_servers.luaj_engine; + +import org.anime_game_servers.lua.engine.LuaValue; + +public class LuaJValue implements LuaValue { + private final org.luaj.vm2.LuaValue value; + private final LuaJEngine engine; + + LuaJValue(LuaJEngine engine, org.luaj.vm2.LuaValue value) { + this.engine = engine; + this.value = value; + } + + @Override + public boolean isNull() { + return value.isnil(); + } + + @Override + public boolean isBoolean() { + return value.isboolean(); + } + + @Override + public boolean isInteger() { + return value.isint(); + } + + @Override + public boolean isLong() { + return value.islong(); + } + + @Override + public boolean isDouble() { + return value.isnumber(); + } + + @Override + public boolean isFloat() { + return value.isnumber(); + } + + @Override + public boolean isString() { + return value.isstring(); + } + + @Override + public boolean isTable() { + return value.istable(); + } + + @Override + public boolean asBoolean() { + return value.toboolean(); + } + + @Override + public int asInteger() { + return value.toint(); + } + + @Override + public long asLong() { + return value.tolong(); + } + + @Override + public double asDouble() { + return value.todouble(); + } + + @Override + public float asFloat() { + return value.tofloat(); + } + + @Override + public String asString() { + return value.toString(); + } + + @Override + public T asObject(Class type) { + if (!value.istable()) { + return null; + } + + return engine.getSerializer().toObject(type, value.checktable()); + } +} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..5c0297d --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,63 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("java") + id("maven-publish") + kotlin("jvm") version "1.9.10" +} + +group = "org.anime_game_servers" +version = "0.1" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation(platform("org.junit:junit-bom:5.9.1")) + testImplementation("org.junit.jupiter:junit-jupiter") + implementation(kotlin("stdlib-jdk8")) +} + +tasks.test { + useJUnitPlatform() +} + +allprojects { + apply(plugin ="maven-publish") + + repositories { + mavenLocal() + mavenCentral() + maven { + name = "ags-mvn-Releases" + url = uri("https://mvn.animegameservers.org/releases") + } + } + + dependencies { + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } + + publishing { + repositories { + maven { + name = "agsmvnrelease" + url = uri("https://mvn.animegameservers.org/releases") + credentials(PasswordCredentials::class) + authentication { + create("basic") + } + } + } + } +} +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "1.8" +} +val compileTestKotlin: KotlinCompile by tasks +compileTestKotlin.kotlinOptions { + jvmTarget = "1.8" +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..298d6a6 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Oct 06 21:24:40 CEST 2023 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..1b6c787 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..c2769bd --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,5 @@ +rootProject.name = "AnimeGameLua" +include("LuaJEngine") +include("JNLuaEngine") +include("GILua") +include("BaseLua")