From 12ac5b32d370abf6248b1dc56edb0c025976755c Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Sun, 13 Aug 2023 19:12:39 -0400 Subject: [PATCH] Implement `ServerLuaCall` --- .../data/binout/AbilityModifier.java | 17 ++++- .../ability/actions/ActionServerLuaCall.java | 66 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/main/java/emu/grasscutter/game/ability/actions/ActionServerLuaCall.java diff --git a/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java b/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java index c63332ae3..75472b854 100644 --- a/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java +++ b/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java @@ -3,9 +3,10 @@ package emu.grasscutter.data.binout; import com.google.gson.annotations.SerializedName; import emu.grasscutter.data.common.DynamicFloat; import emu.grasscutter.game.props.ElementType; -import java.io.Serializable; import lombok.ToString; +import java.io.Serializable; + public class AbilityModifier implements Serializable { private static final long serialVersionUID = -2001232313615923575L; @@ -340,6 +341,20 @@ public class AbilityModifier implements Serializable { public int param2; public int param3; + public LuaCallType luaCallType; + @SerializedName("CallParamList") + public int[] callParamList; + public String funcName; + + public enum LuaCallType { + FromGroup, + CurGalleryControlGroup, + CurChallengeGroup, + SpecificGroup, + AbilityGroupSourceGroup, + CurScenePlay + } + public enum DropType { LevelControl, BigWorldOnly, diff --git a/src/main/java/emu/grasscutter/game/ability/actions/ActionServerLuaCall.java b/src/main/java/emu/grasscutter/game/ability/actions/ActionServerLuaCall.java new file mode 100644 index 000000000..a6aee3097 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/ability/actions/ActionServerLuaCall.java @@ -0,0 +1,66 @@ +package emu.grasscutter.game.ability.actions; + +import com.google.protobuf.ByteString; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; +import emu.grasscutter.game.ability.Ability; +import emu.grasscutter.game.entity.GameEntity; +import org.luaj.vm2.LuaFunction; + +import javax.script.Bindings; + +@AbilityAction(AbilityModifierAction.Type.ServerLuaCall) +public final class ActionServerLuaCall extends AbilityActionHandler { + @Override + public boolean execute( + Ability ability, AbilityModifierAction action, + ByteString abilityData, GameEntity target + ) { + var scene = target.getScene(); + var scriptManager = scene.getScriptManager(); + var functionName = action.funcName; + + return switch (action.luaCallType) { + default -> false; + case FromGroup -> { + var groupId = target.getGroupId(); + var group = scriptManager.getGroupById(groupId); + var script = group.getBindings(); + + yield ActionServerLuaCall.callFunction(script, functionName); + } + case SpecificGroup -> { + var groupId = action.callParamList[0]; + var group = scriptManager.getGroupById(groupId); + var script = group.getBindings(); + + yield ActionServerLuaCall.callFunction(script, functionName); + } + }; + } + + /** + * Handles fetching and calling a function. + * + * @param bindings The bindings to fetch the function from. + * @param functionName The name of the function to call. + * @return Whether the function was called successfully. + */ + private static boolean callFunction(Bindings bindings, String functionName) { + try { + // Resolve the function from the script. + var function = bindings.get(functionName); + if (!(function instanceof LuaFunction luaFunction)) + throw new Exception("Function is not a LuaFunction."); + + // Attempt to invoke the function. + luaFunction.call(); + + return true; + } catch (Exception exception) { + Grasscutter.getLogger().warn("Unable to invoke {}.", + functionName, exception); + return false; + } + } +}