package game import ( "hk4e/common/constant" "hk4e/gdconf" "hk4e/gs/model" "hk4e/pkg/logger" "hk4e/pkg/object" "hk4e/protocol/cmd" "hk4e/protocol/proto" lua "github.com/yuin/gopher-lua" ) type LuaCtx struct { uid uint32 ownerUid uint32 sourceEntityId uint32 targetEntityId uint32 groupId uint32 } type LuaEvt struct { param1 int32 param2 int32 param3 int32 param4 int32 paramStr1 string evtType int32 uid uint32 sourceName string sourceEntityId uint32 targetEntityId uint32 } // CallLuaFunc 调用LUA方法 func CallLuaFunc(luaState *lua.LState, luaFuncName string, luaCtx *LuaCtx, luaEvt *LuaEvt) bool { ctx := luaState.NewTable() luaState.SetField(ctx, "uid", lua.LNumber(luaCtx.uid)) luaState.SetField(ctx, "owner_uid", lua.LNumber(luaCtx.ownerUid)) luaState.SetField(ctx, "source_entity_id", lua.LNumber(luaCtx.sourceEntityId)) luaState.SetField(ctx, "target_entity_id", lua.LNumber(luaCtx.targetEntityId)) luaState.SetField(ctx, "groupId", lua.LNumber(luaCtx.groupId)) evt := luaState.NewTable() luaState.SetField(evt, "param1", lua.LNumber(luaEvt.param1)) luaState.SetField(evt, "param2", lua.LNumber(luaEvt.param2)) luaState.SetField(evt, "param3", lua.LNumber(luaEvt.param3)) luaState.SetField(evt, "param4", lua.LNumber(luaEvt.param4)) luaState.SetField(evt, "param_str1", lua.LString(luaEvt.paramStr1)) luaState.SetField(evt, "type", lua.LNumber(luaEvt.evtType)) luaState.SetField(evt, "uid", lua.LNumber(luaEvt.uid)) luaState.SetField(evt, "source_name", lua.LString(luaEvt.sourceName)) luaState.SetField(evt, "source_eid", lua.LNumber(luaEvt.sourceEntityId)) luaState.SetField(evt, "target_eid", lua.LNumber(luaEvt.targetEntityId)) err := luaState.CallByParam(lua.P{ Fn: luaState.GetGlobal(luaFuncName), NRet: 1, Protect: true, }, ctx, evt) if err != nil { logger.Error("call lua error, func: %v, error: %v", luaFuncName, err) return false } luaRet := luaState.Get(-1) luaState.Pop(1) switch luaRet.(type) { case lua.LBool: return bool(luaRet.(lua.LBool)) case lua.LNumber: return object.ConvRetCodeToBool(int64(luaRet.(lua.LNumber))) default: return false } } // GetContextPlayer 获取上下文中的玩家对象 func GetContextPlayer(ctx *lua.LTable, luaState *lua.LState) *model.Player { uid, ok := luaState.GetField(ctx, "uid").(lua.LNumber) if !ok { return nil } player := USER_MANAGER.GetOnlineUser(uint32(uid)) return player } // GetContextGroup 获取上下文中的场景组对象 func GetContextGroup(player *model.Player, ctx *lua.LTable, luaState *lua.LState) *Group { world := WORLD_MANAGER.GetWorldByID(player.WorldId) if world == nil { return nil } groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber) if !ok { return nil } scene := world.GetSceneById(player.SceneId) group := scene.GetGroupById(uint32(groupId)) if group == nil { return nil } return group } func GetContextDbSceneGroup(player *model.Player, groupId uint32) *model.DbSceneGroup { world := WORLD_MANAGER.GetWorldByID(player.WorldId) if world == nil { return nil } owner := world.GetOwner() dbWorld := owner.GetDbWorld() dbScene := dbWorld.GetSceneById(player.SceneId) dbSceneGroup := dbScene.GetSceneGroupById(groupId) return dbSceneGroup } // RegLuaScriptLibFunc 注册LUA侧ScriptLib调用的Golang方法 func RegLuaScriptLibFunc() { gdconf.RegScriptLibFunc("GetEntityType", GetEntityType) gdconf.RegScriptLibFunc("GetQuestState", GetQuestState) gdconf.RegScriptLibFunc("PrintLog", PrintLog) gdconf.RegScriptLibFunc("PrintContextLog", PrintContextLog) gdconf.RegScriptLibFunc("BeginCameraSceneLook", BeginCameraSceneLook) gdconf.RegScriptLibFunc("GetGroupMonsterCount", GetGroupMonsterCount) gdconf.RegScriptLibFunc("ChangeGroupGadget", ChangeGroupGadget) gdconf.RegScriptLibFunc("GetGadgetStateByConfigId", GetGadgetStateByConfigId) gdconf.RegScriptLibFunc("SetGadgetStateByConfigId", SetGadgetStateByConfigId) gdconf.RegScriptLibFunc("MarkPlayerAction", MarkPlayerAction) gdconf.RegScriptLibFunc("AddQuestProgress", AddQuestProgress) gdconf.RegScriptLibFunc("CreateMonster", CreateMonster) gdconf.RegScriptLibFunc("CreateGadget", CreateGadget) gdconf.RegScriptLibFunc("KillEntityByConfigId", KillEntityByConfigId) gdconf.RegScriptLibFunc("AddExtraGroupSuite", AddExtraGroupSuite) gdconf.RegScriptLibFunc("GetGroupVariableValue", GetGroupVariableValue) gdconf.RegScriptLibFunc("GetGroupVariableValueByGroup", GetGroupVariableValueByGroup) gdconf.RegScriptLibFunc("SetGroupVariableValue", SetGroupVariableValue) gdconf.RegScriptLibFunc("SetGroupVariableValueByGroup", SetGroupVariableValueByGroup) gdconf.RegScriptLibFunc("ChangeGroupVariableValue", ChangeGroupVariableValue) gdconf.RegScriptLibFunc("ChangeGroupVariableValueByGroup", ChangeGroupVariableValueByGroup) } func GetEntityType(luaState *lua.LState) int { entityId := luaState.ToInt(1) luaState.Push(lua.LNumber(entityId >> 24)) return 1 } func GetQuestState(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(constant.QUEST_STATE_NONE)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(constant.QUEST_STATE_NONE)) return 1 } entityId := luaState.ToInt(2) _ = entityId questId := luaState.ToInt(3) dbQuest := player.GetDbQuest() quest := dbQuest.GetQuestById(uint32(questId)) if quest == nil { luaState.Push(lua.LNumber(constant.QUEST_STATE_NONE)) return 1 } luaState.Push(lua.LNumber(quest.State)) return 1 } func PrintLog(luaState *lua.LState) int { logInfo := luaState.ToString(1) logger.Info("[LUA LOG] %v", logInfo) return 0 } func PrintContextLog(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { return 0 } uid, ok := luaState.GetField(ctx, "uid").(lua.LNumber) if !ok { return 0 } logInfo := luaState.ToString(2) logger.Info("[LUA CTX LOG] %v [UID: %v]", logInfo, uid) return 0 } func BeginCameraSceneLook(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } cameraLockInfo, ok := luaState.Get(2).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } ntf := new(proto.BeginCameraSceneLookNotify) gdconf.ParseLuaTableToObject(cameraLockInfo, ntf) GAME.SendMsg(cmd.BeginCameraSceneLookNotify, player.PlayerID, player.ClientSeq, ntf) logger.Debug("BeginCameraSceneLook, ntf: %v, uid: %v", ntf, player.PlayerID) luaState.Push(lua.LNumber(0)) return 1 } func GetGroupMonsterCount(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } group := GetContextGroup(player, ctx, luaState) if group == nil { luaState.Push(lua.LNumber(-1)) return 1 } monsterCount := 0 for _, entity := range group.GetAllEntity() { if entity.GetEntityType() == constant.ENTITY_TYPE_MONSTER { monsterCount++ } } luaState.Push(lua.LNumber(monsterCount)) return 1 } func ChangeGroupGadget(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } group := GetContextGroup(player, ctx, luaState) if group == nil { luaState.Push(lua.LNumber(-1)) return 1 } gadgetInfo, ok := luaState.Get(2).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } gadgetStateInfo := new(gdconf.Gadget) gdconf.ParseLuaTableToObject(gadgetInfo, gadgetStateInfo) entity := group.GetEntityByConfigId(uint32(gadgetStateInfo.ConfigId)) GAME.ChangeGadgetState(player, entity.GetId(), uint32(gadgetStateInfo.State)) luaState.Push(lua.LNumber(0)) return 1 } func GetGadgetStateByConfigId(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId := luaState.ToInt(2) configId := luaState.ToInt(3) world := WORLD_MANAGER.GetWorldByID(player.WorldId) if world == nil { luaState.Push(lua.LNumber(-1)) return 1 } scene := world.GetSceneById(player.SceneId) group := scene.GetGroupById(uint32(groupId)) if group == nil { luaState.Push(lua.LNumber(-1)) return 1 } entity := group.GetEntityByConfigId(uint32(configId)) if entity == nil { luaState.Push(lua.LNumber(-1)) return 1 } if entity.GetEntityType() != constant.ENTITY_TYPE_GADGET { luaState.Push(lua.LNumber(-1)) return 1 } gadgetEntity := entity.GetGadgetEntity() luaState.Push(lua.LNumber(gadgetEntity.GetGadgetState())) return 1 } func SetGadgetStateByConfigId(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } group := GetContextGroup(player, ctx, luaState) if group == nil { luaState.Push(lua.LNumber(-1)) return 1 } configId := luaState.ToInt(2) state := luaState.ToInt(3) entity := group.GetEntityByConfigId(uint32(configId)) GAME.ChangeGadgetState(player, entity.GetId(), uint32(state)) luaState.Push(lua.LNumber(0)) return 1 } func MarkPlayerAction(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } param1 := luaState.ToInt(2) param2 := luaState.ToInt(3) param3 := luaState.ToInt(4) logger.Debug("[MarkPlayerAction] [%v %v %v] [UID: %v]", param1, param2, param3, player.PlayerID) luaState.Push(lua.LNumber(0)) return 1 } func AddQuestProgress(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } complexParam := luaState.ToString(2) GAME.TriggerQuest(player, constant.QUEST_FINISH_COND_TYPE_LUA_NOTIFY, complexParam) luaState.Push(lua.LNumber(0)) return 1 } type LuaTableParam struct { ConfigId int32 `json:"config_id"` DelayTime int32 `json:"delay_time"` } func CreateMonster(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } luaTable, ok := luaState.Get(2).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } luaTableParam := new(LuaTableParam) gdconf.ParseLuaTableToObject[*LuaTableParam](luaTable, luaTableParam) TICK_MANAGER.CreateUserTimer(player.PlayerID, UserTimerActionLuaCreateMonster, uint32(luaTableParam.DelayTime), uint32(groupId), uint32(luaTableParam.ConfigId)) luaState.Push(lua.LNumber(0)) return 1 } func CreateGadget(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } luaTable, ok := luaState.Get(2).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } luaTableParam := new(LuaTableParam) gdconf.ParseLuaTableToObject[*LuaTableParam](luaTable, luaTableParam) groupConfig := gdconf.GetSceneGroup(int32(groupId)) if groupConfig == nil { luaState.Push(lua.LNumber(-1)) return 1 } gadget := groupConfig.GadgetMap[luaTableParam.ConfigId] if gadget == nil { luaState.Push(lua.LNumber(-1)) return 1 } GAME.CreateGadget(player, &model.Vector{X: float64(gadget.Pos.X), Y: float64(gadget.Pos.Y), Z: float64(gadget.Pos.Z)}, uint32(gadget.GadgetId), nil) luaState.Push(lua.LNumber(0)) return 1 } func KillEntityByConfigId(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } luaTable, ok := luaState.Get(2).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } luaTableParam := new(LuaTableParam) gdconf.ParseLuaTableToObject[*LuaTableParam](luaTable, luaTableParam) world := WORLD_MANAGER.GetWorldByID(player.WorldId) if world == nil { luaState.Push(lua.LNumber(-1)) return 1 } scene := world.GetSceneById(player.SceneId) group := scene.GetGroupById(uint32(groupId)) entity := group.GetEntityByConfigId(uint32(luaTableParam.ConfigId)) GAME.KillEntity(player, scene, entity.GetId(), proto.PlayerDieType_PLAYER_DIE_NONE) luaState.Push(lua.LNumber(0)) return 1 } func AddExtraGroupSuite(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId := luaState.ToInt(2) suiteId := luaState.ToInt(3) GAME.AddSceneGroupSuite(player, uint32(groupId), uint8(suiteId)) luaState.Push(lua.LNumber(0)) return 1 } func GetGroupVariableValue(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } name := luaState.ToString(2) dbSceneGroup := GetContextDbSceneGroup(player, uint32(groupId)) if dbSceneGroup == nil { luaState.Push(lua.LNumber(-1)) return 1 } value := dbSceneGroup.GetVariableByName(name) luaState.Push(lua.LNumber(value)) return 1 } func GetGroupVariableValueByGroup(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } name := luaState.ToString(2) groupId := luaState.ToInt(3) dbSceneGroup := GetContextDbSceneGroup(player, uint32(groupId)) if dbSceneGroup == nil { luaState.Push(lua.LNumber(-1)) return 1 } value := dbSceneGroup.GetVariableByName(name) luaState.Push(lua.LNumber(value)) return 1 } func SetGroupVariableValue(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } name := luaState.ToString(2) value := luaState.ToInt(3) dbSceneGroup := GetContextDbSceneGroup(player, uint32(groupId)) if dbSceneGroup == nil { luaState.Push(lua.LNumber(-1)) return 1 } dbSceneGroup.SetVariable(name, int32(value)) luaState.Push(lua.LNumber(0)) return 1 } func SetGroupVariableValueByGroup(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } name := luaState.ToString(2) value := luaState.ToInt(3) groupId := luaState.ToInt(4) dbSceneGroup := GetContextDbSceneGroup(player, uint32(groupId)) if dbSceneGroup == nil { luaState.Push(lua.LNumber(-1)) return 1 } dbSceneGroup.SetVariable(name, int32(value)) luaState.Push(lua.LNumber(0)) return 1 } func ChangeGroupVariableValue(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } name := luaState.ToString(2) change := luaState.ToInt(3) dbSceneGroup := GetContextDbSceneGroup(player, uint32(groupId)) if dbSceneGroup == nil { luaState.Push(lua.LNumber(-1)) return 1 } value := dbSceneGroup.GetVariableByName(name) dbSceneGroup.SetVariable(name, value+int32(change)) luaState.Push(lua.LNumber(0)) return 1 } func ChangeGroupVariableValueByGroup(luaState *lua.LState) int { ctx, ok := luaState.Get(1).(*lua.LTable) if !ok { luaState.Push(lua.LNumber(-1)) return 1 } player := GetContextPlayer(ctx, luaState) if player == nil { luaState.Push(lua.LNumber(-1)) return 1 } name := luaState.ToString(2) change := luaState.ToInt(3) groupId := luaState.ToInt(4) dbSceneGroup := GetContextDbSceneGroup(player, uint32(groupId)) if dbSceneGroup == nil { luaState.Push(lua.LNumber(-1)) return 1 } value := dbSceneGroup.GetVariableByName(name) dbSceneGroup.SetVariable(name, value+int32(change)) luaState.Push(lua.LNumber(0)) return 1 }