diff --git a/gate/forward/forward.go b/gate/forward/forward.go index d1ec01c2..966a92e0 100644 --- a/gate/forward/forward.go +++ b/gate/forward/forward.go @@ -194,7 +194,8 @@ func (f *ForwardManager) Start() { go f.recvNetMsgFromGameServer() // 接收客户端消息 cpuCoreNum := runtime.NumCPU() - for i := 0; i < cpuCoreNum*10; i++ { + _ = cpuCoreNum * 10 + for i := 0; i < 1; i++ { go f.sendNetMsgToGameServer() } } diff --git a/gate/forward/login_hk4e.go b/gate/forward/login_hk4e.go index 42f84a8d..a7ec345e 100644 --- a/gate/forward/login_hk4e.go +++ b/gate/forward/login_hk4e.go @@ -70,19 +70,19 @@ func (f *ForwardManager) getPlayerToken(convId uint64, req *proto.GetPlayerToken // 返回响应 rsp = new(proto.GetPlayerTokenRsp) rsp.Uid = tokenVerifyRsp.PlayerID - // TODO 不同的token - rsp.Token = "xxx" + rsp.AccountUid = req.AccountUid + rsp.Token = req.AccountToken data := make([]byte, 16+32) rand.Read(data) rsp.SecurityCmdBuffer = data[16:] rsp.ClientVersionRandomKey = fmt.Sprintf("%03x-%012x", data[:3], data[4:16]) - // TODO 要确定一下新注册的号这个值该返回什么 rsp.AccountType = 1 rsp.IsProficientPlayer = true rsp.PlatformType = 3 rsp.ChannelId = 1 - rsp.CountryCode = "US" - rsp.RegPlatform = 3 + rsp.SubChannelId = 1 + rsp.RegPlatform = 2 + rsp.Birthday = "2000-01-01" addr, exist := f.getAddrByConvId(convId) if !exist { logger.LOG.Error("can not find addr by convId") @@ -146,6 +146,7 @@ func (f *ForwardManager) getPlayerToken(convId uint64, req *proto.GetPlayerToken logger.LOG.Error("rsa sign error: %v", err) return rsp } + rsp.KeyId = req.KeyId rsp.ServerRandKey = base64.StdEncoding.EncodeToString(seedEnc) rsp.Sign = base64.StdEncoding.EncodeToString(seedSign) // 开启发包监听 @@ -159,11 +160,7 @@ func (f *ForwardManager) getPlayerToken(convId uint64, req *proto.GetPlayerToken } func (f *ForwardManager) playerLogin(convId uint64, req *proto.PlayerLoginReq) (rsp *proto.PlayerLoginRsp) { - tokenValid := false - // TODO 不同的token - if req.Token == "xxx" { - tokenValid = true - } + tokenValid := true if !tokenValid { logger.LOG.Error("token error") return nil @@ -173,8 +170,13 @@ func (f *ForwardManager) playerLogin(convId uint64, req *proto.PlayerLoginReq) ( // 返回响应 rsp = new(proto.PlayerLoginRsp) rsp.IsUseAbilityHash = true - rsp.AbilityHashCode = 1844674 - rsp.GameBiz = "hk4e_global" + rsp.AbilityHashCode = -228935105 + rsp.GameBiz = "hk4e_cn" + rsp.IsScOpen = false + rsp.RegisterCps = "taptap" + rsp.CountryCode = "CN" + rsp.Birthday = "2000-01-01" + rsp.TotalTickTime = 1185941.871788 rsp.ClientDataVersion = f.regionCurr.RegionInfo.ClientDataVersion rsp.ClientSilenceDataVersion = f.regionCurr.RegionInfo.ClientSilenceDataVersion @@ -184,8 +186,5 @@ func (f *ForwardManager) playerLogin(convId uint64, req *proto.PlayerLoginReq) ( rsp.ClientVersionSuffix = f.regionCurr.RegionInfo.ClientVersionSuffix rsp.ClientSilenceVersionSuffix = f.regionCurr.RegionInfo.ClientSilenceVersionSuffix - rsp.IsScOpen = false - rsp.RegisterCps = "mihoyo" - rsp.CountryCode = "US" return rsp } diff --git a/gate/net/proto_endecode.go b/gate/net/proto_endecode.go index a6305969..868768e5 100644 --- a/gate/net/proto_endecode.go +++ b/gate/net/proto_endecode.go @@ -61,11 +61,6 @@ func (p *ProtoEnDecode) protoDecode(kcpMsg *KcpMsg) (protoMsgList []*ProtoMsg) { msg.CmdId = protoMessage.cmdId msg.HeadMessage = protoMsg.HeadMessage msg.PayloadMessage = protoMessage.message - if protoMessage.cmdId == cmd.UnionCmdNotify { - // 聚合消息自身不再往后发送 - logger.LOG.Debug("[recv union], cmdId: %v, convId: %v, headMsg: %v", msg.CmdId, msg.ConvId, msg.HeadMessage) - continue - } protoMsgList = append(protoMsgList, msg) } } else { diff --git a/gs/game/route_manager.go b/gs/game/route_manager.go index 97878266..8f6c9c57 100644 --- a/gs/game/route_manager.go +++ b/gs/game/route_manager.go @@ -47,6 +47,8 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa } func (r *RouteManager) InitRoute() { + r.registerRouter(cmd.UnionCmdNotify, r.gameManager.UnionCmdNotify) + r.registerRouter(cmd.MassiveEntityElementOpBatchNotify, r.gameManager.MassiveEntityElementOpBatchNotify) r.registerRouter(cmd.PlayerSetPauseReq, r.gameManager.PlayerSetPauseReq) r.registerRouter(cmd.EnterSceneReadyReq, r.gameManager.EnterSceneReadyReq) r.registerRouter(cmd.PathfindingEnterSceneReq, r.gameManager.PathfindingEnterSceneReq) diff --git a/gs/game/tick_manager.go b/gs/game/tick_manager.go index 5bde2680..e5c1a88b 100644 --- a/gs/game/tick_manager.go +++ b/gs/game/tick_manager.go @@ -235,12 +235,12 @@ func (t *TickManager) onTick200MilliSecond(now int64) { } func (t *TickManager) onTick100MilliSecond(now int64) { - // 伤害处理和转发 - for _, world := range t.gameManager.worldManager.worldMap { - for _, scene := range world.sceneMap { - scene.AttackHandler(t.gameManager) - } - } + //// 伤害处理和转发 + //for _, world := range t.gameManager.worldManager.worldMap { + // for _, scene := range world.sceneMap { + // scene.AttackHandler(t.gameManager) + // } + //} // 服务器控制的模拟AI移动 diff --git a/gs/game/user_ability.go b/gs/game/user_ability.go index acadd252..a9640b07 100644 --- a/gs/game/user_ability.go +++ b/gs/game/user_ability.go @@ -2,13 +2,12 @@ package game import ( "hk4e/gs/model" - "hk4e/pkg/logger" "hk4e/protocol/proto" ) // HandleAbilityInvoke 处理能力调用 func (g *GameManager) HandleAbilityInvoke(player *model.Player, entry *proto.AbilityInvokeEntry) { - logger.LOG.Debug("ability invoke handle, entry: %v", entry.ArgumentType) + //logger.LOG.Debug("ability invoke handle, entry: %v", entry.ArgumentType) switch entry.ArgumentType { case proto.AbilityInvokeArgument_ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA: diff --git a/gs/game/user_combat.go b/gs/game/user_combat.go index f0a67eea..0bba32cc 100644 --- a/gs/game/user_combat.go +++ b/gs/game/user_combat.go @@ -9,6 +9,140 @@ import ( pb "google.golang.org/protobuf/proto" ) +func (g *GameManager) UnionCmdNotify(player *model.Player, payloadMsg pb.Message) { + //logger.LOG.Debug("user send union cmd, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.UnionCmdNotify) + _ = req + + world := g.worldManager.GetWorldByID(player.WorldId) + if world == nil { + return + } + scene := world.GetSceneById(player.SceneId) + + // 只给附近aoi区域的玩家广播消息 + surrPlayerList := make([]*model.Player, 0) + entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) + for _, entityId := range entityIdList { + entity := scene.GetEntity(entityId) + if entity == nil { + continue + } + if entity.avatarEntity != nil { + otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) + surrPlayerList = append(surrPlayerList, otherPlayer) + } + } + + // CombatInvocationsNotify转发 + // PacketCombatInvocationsNotify + if player.CombatInvokeHandler.AllLen() > 0 { + combatInvocationsNotify := new(proto.CombatInvocationsNotify) + combatInvocationsNotify.InvokeList = player.CombatInvokeHandler.EntryListForwardAll + for _, v := range surrPlayerList { + g.SendMsg(cmd.CombatInvocationsNotify, v.PlayerID, player.ClientSeq, combatInvocationsNotify) + } + } + if player.CombatInvokeHandler.AllExceptCurLen() > 0 { + combatInvocationsNotify := new(proto.CombatInvocationsNotify) + combatInvocationsNotify.InvokeList = player.CombatInvokeHandler.EntryListForwardAllExceptCur + for _, v := range surrPlayerList { + if player.PlayerID == v.PlayerID { + continue + } + g.SendMsg(cmd.CombatInvocationsNotify, v.PlayerID, player.ClientSeq, combatInvocationsNotify) + } + } + if player.CombatInvokeHandler.HostLen() > 0 { + combatInvocationsNotify := new(proto.CombatInvocationsNotify) + combatInvocationsNotify.InvokeList = player.CombatInvokeHandler.EntryListForwardHost + g.SendMsg(cmd.CombatInvocationsNotify, world.owner.PlayerID, player.ClientSeq, combatInvocationsNotify) + } + + // AbilityInvocationsNotify转发 + // PacketAbilityInvocationsNotify + if player.AbilityInvokeHandler.AllLen() > 0 { + abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) + abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardAll + for _, v := range surrPlayerList { + g.SendMsg(cmd.AbilityInvocationsNotify, v.PlayerID, player.ClientSeq, abilityInvocationsNotify) + } + } + if player.AbilityInvokeHandler.AllExceptCurLen() > 0 { + abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) + abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardAllExceptCur + for _, v := range surrPlayerList { + if player.PlayerID == v.PlayerID { + continue + } + g.SendMsg(cmd.AbilityInvocationsNotify, v.PlayerID, player.ClientSeq, abilityInvocationsNotify) + } + } + if player.AbilityInvokeHandler.HostLen() > 0 { + abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) + abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardHost + g.SendMsg(cmd.AbilityInvocationsNotify, world.owner.PlayerID, player.ClientSeq, abilityInvocationsNotify) + } + + // ClientAbilityInitFinishNotify转发 + // PacketClientAbilityInitFinishNotify + if player.ClientAbilityInvokeHandler.AllLen() > 0 { + clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) + clientAbilityInitFinishNotify.Invokes = player.ClientAbilityInvokeHandler.EntryListForwardAll + for _, v := range surrPlayerList { + g.SendMsg(cmd.ClientAbilityInitFinishNotify, v.PlayerID, player.ClientSeq, clientAbilityInitFinishNotify) + } + } + if player.ClientAbilityInvokeHandler.AllExceptCurLen() > 0 { + clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) + clientAbilityInitFinishNotify.Invokes = player.ClientAbilityInvokeHandler.EntryListForwardAllExceptCur + for _, v := range surrPlayerList { + if player.PlayerID == v.PlayerID { + continue + } + g.SendMsg(cmd.ClientAbilityInitFinishNotify, v.PlayerID, player.ClientSeq, clientAbilityInitFinishNotify) + } + } + if player.ClientAbilityInvokeHandler.HostLen() > 0 { + clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) + clientAbilityInitFinishNotify.Invokes = player.ClientAbilityInvokeHandler.EntryListForwardHost + g.SendMsg(cmd.ClientAbilityInitFinishNotify, world.owner.PlayerID, player.ClientSeq, clientAbilityInitFinishNotify) + } + + player.CombatInvokeHandler.Clear() + player.AbilityInvokeHandler.Clear() + player.ClientAbilityInvokeHandler.Clear() +} + +func (g *GameManager) MassiveEntityElementOpBatchNotify(player *model.Player, payloadMsg pb.Message) { + //logger.LOG.Debug("user meeo sync, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.MassiveEntityElementOpBatchNotify) + ntf := req + world := g.worldManager.GetWorldByID(player.WorldId) + if world == nil { + return + } + scene := world.GetSceneById(player.SceneId) + ntf.OpIdx = scene.meeoIndex + scene.meeoIndex++ + // 只给附近aoi区域的玩家广播消息 + surrPlayerList := make([]*model.Player, 0) + entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) + for _, entityId := range entityIdList { + entity := scene.GetEntity(entityId) + if entity == nil { + continue + } + if entity.avatarEntity != nil { + otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) + surrPlayerList = append(surrPlayerList, otherPlayer) + } + } + for _, v := range surrPlayerList { + g.SendMsg(cmd.MassiveEntityElementOpBatchNotify, v.PlayerID, player.ClientSeq, ntf) + } +} + func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user combat invocations, uid: %v", player.PlayerID) req := payloadMsg.(*proto.CombatInvocationsNotify) @@ -17,15 +151,14 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p return } scene := world.GetSceneById(player.SceneId) - invokeHandler := model.NewInvokeHandler[proto.CombatInvokeEntry]() for _, entry := range req.InvokeList { //logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) switch entry.ArgumentType { - case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT: - scene.AddAttack(&Attack{ - combatInvokeEntry: entry, - uid: player.PlayerID, - }) + //case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT: + // scene.AddAttack(&Attack{ + // combatInvokeEntry: entry, + // uid: player.PlayerID, + // }) case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ENTITY_MOVE: entityMoveInfo := new(proto.EntityMoveInfo) err := pb.Unmarshal(entry.CombatData, entityMoveInfo) @@ -205,60 +338,16 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p // 处理耐力消耗 g.HandleStamina(player, motionInfo.State) - invokeHandler.AddEntry(entry.ForwardType, entry) + player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) default: - invokeHandler.AddEntry(entry.ForwardType, entry) + player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) } } - - // 只给附近aoi区域的玩家广播消息 - surrPlayerList := make([]*model.Player, 0) - entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) - for _, entityId := range entityIdList { - entity := scene.GetEntity(entityId) - if entity == nil { - continue - } - if entity.avatarEntity != nil { - otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) - surrPlayerList = append(surrPlayerList, otherPlayer) - } - } - - // 处理转发 - // PacketCombatInvocationsNotify - if invokeHandler.AllLen() > 0 { - combatInvocationsNotify := new(proto.CombatInvocationsNotify) - combatInvocationsNotify.InvokeList = invokeHandler.EntryListForwardAll - for _, v := range surrPlayerList { - g.SendMsg(cmd.CombatInvocationsNotify, v.PlayerID, v.ClientSeq, combatInvocationsNotify) - } - } - if invokeHandler.AllExceptCurLen() > 0 { - combatInvocationsNotify := new(proto.CombatInvocationsNotify) - combatInvocationsNotify.InvokeList = invokeHandler.EntryListForwardAllExceptCur - for _, v := range surrPlayerList { - if player.PlayerID == v.PlayerID { - continue - } - g.SendMsg(cmd.CombatInvocationsNotify, v.PlayerID, v.ClientSeq, combatInvocationsNotify) - } - } - if invokeHandler.HostLen() > 0 { - combatInvocationsNotify := new(proto.CombatInvocationsNotify) - combatInvocationsNotify.InvokeList = invokeHandler.EntryListForwardHost - g.SendMsg(cmd.CombatInvocationsNotify, world.owner.PlayerID, world.owner.ClientSeq, combatInvocationsNotify) - } } func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user ability invocations, uid: %v", player.PlayerID) req := payloadMsg.(*proto.AbilityInvocationsNotify) - - if player.AbilityInvokeHandler == nil { - player.AbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]() - } - for _, entry := range req.Invokes { //logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) @@ -272,86 +361,13 @@ func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg func (g *GameManager) ClientAbilityInitFinishNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user client ability init finish, uid: %v", player.PlayerID) req := payloadMsg.(*proto.ClientAbilityInitFinishNotify) - world := g.worldManager.GetWorldByID(player.WorldId) - if world == nil { - return - } - scene := world.GetSceneById(player.SceneId) - invokeHandler := model.NewInvokeHandler[proto.AbilityInvokeEntry]() for _, entry := range req.Invokes { //logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) // 处理能力调用 g.HandleAbilityInvoke(player, entry) - invokeHandler.AddEntry(entry.ForwardType, entry) - } - - // 只给附近aoi区域的玩家广播消息 - surrPlayerList := make([]*model.Player, 0) - entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) - for _, entityId := range entityIdList { - entity := scene.GetEntity(entityId) - if entity == nil { - continue - } - if entity.avatarEntity != nil { - otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) - surrPlayerList = append(surrPlayerList, otherPlayer) - } - } - - // AbilityInvocationsNotify转发 - if player.AbilityInvokeHandler == nil { - player.AbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]() - } - // PacketAbilityInvocationsNotify - if player.AbilityInvokeHandler.AllLen() > 0 { - abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) - abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardAll - for _, v := range surrPlayerList { - g.SendMsg(cmd.AbilityInvocationsNotify, v.PlayerID, v.ClientSeq, abilityInvocationsNotify) - } - } - if player.AbilityInvokeHandler.AllExceptCurLen() > 0 { - abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) - abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardAllExceptCur - for _, v := range surrPlayerList { - if player.PlayerID == v.PlayerID { - continue - } - g.SendMsg(cmd.AbilityInvocationsNotify, v.PlayerID, v.ClientSeq, abilityInvocationsNotify) - } - } - if player.AbilityInvokeHandler.HostLen() > 0 { - abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) - abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardHost - g.SendMsg(cmd.AbilityInvocationsNotify, world.owner.PlayerID, world.owner.ClientSeq, abilityInvocationsNotify) - } - - // ClientAbilityInitFinishNotify转发 - // PacketClientAbilityInitFinishNotify - if invokeHandler.AllLen() > 0 { - clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) - clientAbilityInitFinishNotify.Invokes = invokeHandler.EntryListForwardAll - for _, v := range surrPlayerList { - g.SendMsg(cmd.ClientAbilityInitFinishNotify, v.PlayerID, v.ClientSeq, clientAbilityInitFinishNotify) - } - } - if invokeHandler.AllExceptCurLen() > 0 { - clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) - clientAbilityInitFinishNotify.Invokes = invokeHandler.EntryListForwardAllExceptCur - for _, v := range surrPlayerList { - if player.PlayerID == v.PlayerID { - continue - } - g.SendMsg(cmd.ClientAbilityInitFinishNotify, v.PlayerID, v.ClientSeq, clientAbilityInitFinishNotify) - } - } - if invokeHandler.HostLen() > 0 { - clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) - clientAbilityInitFinishNotify.Invokes = invokeHandler.EntryListForwardHost - g.SendMsg(cmd.ClientAbilityInitFinishNotify, world.owner.PlayerID, world.owner.ClientSeq, clientAbilityInitFinishNotify) + player.ClientAbilityInvokeHandler.AddEntry(entry.ForwardType, entry) } } diff --git a/gs/game/user_common_handler.go b/gs/game/user_common_handler.go index 381f915f..b4289a29 100644 --- a/gs/game/user_common_handler.go +++ b/gs/game/user_common_handler.go @@ -45,10 +45,6 @@ func (g *GameManager) EntityAiSyncNotify(player *model.Player, payloadMsg pb.Mes logger.LOG.Debug("user entity ai sync, uid: %v", player.PlayerID) req := payloadMsg.(*proto.EntityAiSyncNotify) - if len(req.LocalAvatarAlertedMonsterList) == 0 { - return - } - // PacketEntityAiSyncNotify entityAiSyncNotify := new(proto.EntityAiSyncNotify) entityAiSyncNotify.InfoList = make([]*proto.AiSyncInfo, 0) diff --git a/gs/game/user_login.go b/gs/game/user_login.go index 40b29975..f09c34d9 100644 --- a/gs/game/user_login.go +++ b/gs/game/user_login.go @@ -38,6 +38,10 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u world.AddPlayer(player, player.SceneId) player.WorldId = world.id + player.CombatInvokeHandler = model.NewInvokeHandler[proto.CombatInvokeEntry]() + player.AbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]() + player.ClientAbilityInvokeHandler = model.NewInvokeHandler[proto.AbilityInvokeEntry]() + //// TODO 薄荷标记 //if world.IsBigWorld() { // bigWorld := world.GetSceneById(3) diff --git a/gs/game/user_stamina.go b/gs/game/user_stamina.go index 93ad4a71..1d2b540b 100644 --- a/gs/game/user_stamina.go +++ b/gs/game/user_stamina.go @@ -19,29 +19,29 @@ func (g *GameManager) SceneAvatarStaminaStepReq(player *model.Player, payloadMsg switch player.StaminaInfo.State { case proto.MotionState_MOTION_STATE_CLIMB: // 缓慢攀爬 - - // 缓慢攀爬的耐力将根据角度不同而改变 - // rotX ∈ [0,180) x = rotX - // rotX ∈ [180,360) x = rotX - 360.0 - // x >= 0 y = -x + 10 - // x < 0 y = -2x + 10 - // rotX req.Rot.X - // y 消耗的耐力修正值 - // base(-100) + y 消耗的耐力 - var x int32 - var costRevise int32 // 攀爬耐力修正值 - if req.Rot.X >= 0 && req.Rot.X < 180 { - x = int32(req.Rot.X) - } else if req.Rot.X >= 180 && req.Rot.X < 360 { - x = int32(req.Rot.X - 360.0) - } - if x >= 0 { - costRevise = -x + 10 + var angleRevise int32 // 角度修正值 归一化为-90到+90范围内的角 + // rotX ∈ [0,90) angle = rotX + // rotX ∈ (270,360) angle = rotX - 360.0 + if req.Rot.X >= 0 && req.Rot.X < 90 { + angleRevise = int32(req.Rot.X) + } else if req.Rot.X > 270 && req.Rot.X < 360 { + angleRevise = int32(req.Rot.X - 360.0) } else { - costRevise = -(x * 2) + 10 + logger.LOG.Error("invalid rot x angle: %v", req.Rot.X) } - //logger.LOG.Debug("stamina climbing, rotX: %v, costRevise: %v, cost: %v", req.Rot.X, costRevise, constant.StaminaCostConst.CLIMBING_BASE+costRevise) - g.UpdateStamina(player, constant.StaminaCostConst.CLIMBING_BASE+costRevise) + // 攀爬耐力修正曲线 + // angle >= 0 cost = -x + 10 + // angle < 0 cost = -2x + 10 + var costRevise int32 // 攀爬耐力修正值 在基础消耗值的水平上增加或减少 + if angleRevise >= 0 { + // 普通或垂直斜坡 + costRevise = -angleRevise + 10 + } else { + // 倒三角 非常消耗体力 + costRevise = -(angleRevise * 2) + 10 + } + logger.LOG.Debug("stamina climbing, rotX: %v, costRevise: %v, cost: %v", req.Rot.X, costRevise, constant.StaminaCostConst.CLIMBING_BASE-costRevise) + g.UpdateStamina(player, constant.StaminaCostConst.CLIMBING_BASE-costRevise) case proto.MotionState_MOTION_STATE_SWIM_MOVE: // 缓慢游泳 g.UpdateStamina(player, constant.StaminaCostConst.SWIMMING) diff --git a/gs/game/world_manager.go b/gs/game/world_manager.go index e802c56a..91d5e5dd 100644 --- a/gs/game/world_manager.go +++ b/gs/game/world_manager.go @@ -135,6 +135,7 @@ func (w *World) CreateScene(sceneId uint32) *Scene { gameTime: 18 * 60, attackQueue: alg.NewRAQueue[*Attack](1000), createTime: time.Now().UnixMilli(), + meeoIndex: 0, } w.sceneMap[sceneId] = scene return scene @@ -169,6 +170,7 @@ type Scene struct { gameTime uint32 attackQueue *alg.RAQueue[*Attack] createTime int64 + meeoIndex uint32 } type AvatarEntity struct { diff --git a/gs/model/invoke_handler.go b/gs/model/invoke_handler.go index e1ce3bfa..1edf94ed 100644 --- a/gs/model/invoke_handler.go +++ b/gs/model/invoke_handler.go @@ -8,13 +8,14 @@ import ( // 泛型通用转发器 type InvokeType interface { - proto.AbilityInvokeEntry | proto.CombatInvokeEntry + proto.CombatInvokeEntry | proto.AbilityInvokeEntry } type InvokeHandler[T InvokeType] struct { EntryListForwardAll []*T EntryListForwardAllExceptCur []*T EntryListForwardHost []*T + EntryListForwardServer []*T } func NewInvokeHandler[T InvokeType]() (r *InvokeHandler[T]) { @@ -27,6 +28,7 @@ func (i *InvokeHandler[T]) InitInvokeHandler() { i.EntryListForwardAll = make([]*T, 0) i.EntryListForwardAllExceptCur = make([]*T, 0) i.EntryListForwardHost = make([]*T, 0) + i.EntryListForwardServer = make([]*T, 0) } func (i *InvokeHandler[T]) AddEntry(forward proto.ForwardType, entry *T) { @@ -39,10 +41,11 @@ func (i *InvokeHandler[T]) AddEntry(forward proto.ForwardType, entry *T) { i.EntryListForwardAllExceptCur = append(i.EntryListForwardAllExceptCur, entry) case proto.ForwardType_FORWARD_TYPE_TO_HOST: i.EntryListForwardHost = append(i.EntryListForwardHost, entry) + case proto.ForwardType_FORWARD_TYPE_ONLY_SERVER: + i.EntryListForwardServer = append(i.EntryListForwardServer, entry) + logger.LOG.Error("fwd server entry: %v", entry) default: - if forward != proto.ForwardType_FORWARD_TYPE_ONLY_SERVER { - logger.LOG.Error("forward: %v, entry: %v", forward, entry) - } + logger.LOG.Error("forward: %v, entry: %v", forward, entry) } } @@ -57,3 +60,14 @@ func (i *InvokeHandler[T]) AllExceptCurLen() int { func (i *InvokeHandler[T]) HostLen() int { return len(i.EntryListForwardHost) } + +func (i *InvokeHandler[T]) ServerLen() int { + return len(i.EntryListForwardServer) +} + +func (i *InvokeHandler[T]) Clear() { + i.EntryListForwardAll = make([]*T, 0) + i.EntryListForwardAllExceptCur = make([]*T, 0) + i.EntryListForwardHost = make([]*T, 0) + i.EntryListForwardServer = make([]*T, 0) +} diff --git a/gs/model/player.go b/gs/model/player.go index eaad586e..966f84a6 100644 --- a/gs/model/player.go +++ b/gs/model/player.go @@ -53,21 +53,23 @@ type Player struct { ChatMsgMap map[uint32][]*ChatMsg `bson:"chatMsgMap"` // 聊天信息 IsGM uint8 `bson:"isGM"` // 管理员权限等级 // 在线数据 - EnterSceneToken uint32 `bson:"-"` // 玩家的世界进入令牌 - DbState int `bson:"-"` // 数据库存档状态 - WorldId uint32 `bson:"-"` // 所在的世界id - PeerId uint32 `bson:"-"` // 多人世界的玩家编号 - GameObjectGuidCounter uint64 `bson:"-"` // 游戏对象guid计数器 - ClientTime uint32 `bson:"-"` // 玩家客户端的本地时钟 - ClientRTT uint32 `bson:"-"` // 玩家客户端往返时延 - GameObjectGuidMap map[uint64]GameObject `bson:"-"` // 游戏对象guid映射表 - Online bool `bson:"-"` // 在线状态 - Pause bool `bson:"-"` // 暂停状态 - SceneLoadState int `bson:"-"` // 场景加载状态 - CoopApplyMap map[uint32]int64 `bson:"-"` // 敲门申请的玩家uid及时间 - StaminaInfo *StaminaInfo `bson:"-"` // 耐力临时数据 - ClientSeq uint32 `bson:"-"` // 客户端发包请求的序号 - AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] + EnterSceneToken uint32 `bson:"-"` // 玩家的世界进入令牌 + DbState int `bson:"-"` // 数据库存档状态 + WorldId uint32 `bson:"-"` // 所在的世界id + PeerId uint32 `bson:"-"` // 多人世界的玩家编号 + GameObjectGuidCounter uint64 `bson:"-"` // 游戏对象guid计数器 + ClientTime uint32 `bson:"-"` // 玩家客户端的本地时钟 + ClientRTT uint32 `bson:"-"` // 玩家客户端往返时延 + GameObjectGuidMap map[uint64]GameObject `bson:"-"` // 游戏对象guid映射表 + Online bool `bson:"-"` // 在线状态 + Pause bool `bson:"-"` // 暂停状态 + SceneLoadState int `bson:"-"` // 场景加载状态 + CoopApplyMap map[uint32]int64 `bson:"-"` // 敲门申请的玩家uid及时间 + StaminaInfo *StaminaInfo `bson:"-"` // 耐力临时数据 + ClientSeq uint32 `bson:"-"` // 客户端发包请求的序号 + CombatInvokeHandler *InvokeHandler[proto.CombatInvokeEntry] + AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] + ClientAbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] } func (p *Player) GetNextGameObjectGuid() uint64 { diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 4a58246f..4e850b2a 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -100,8 +100,13 @@ func (l *Logger) doLog() { "goroutine:" + logInfo.GoroutineId + "]" + RESET + " " } - logStr := logHeader + fmt.Sprintf(logInfo.Msg, logInfo.Param...) + "\n" + logStr := logHeader if logInfo.Level == ERROR { + logStr += RED + fmt.Sprintf(logInfo.Msg, logInfo.Param...) + RESET + "\n" + } else { + logStr += fmt.Sprintf(logInfo.Msg, logInfo.Param...) + "\n" + } + if logInfo.Stack != "" { logStr += logInfo.Stack } if l.Method == CONSOLE { @@ -126,7 +131,6 @@ func (l *Logger) Debug(msg string, param ...any) { if l.TrackLine { logInfo.FileName, logInfo.Line, logInfo.FuncName = l.getLineFunc() logInfo.GoroutineId = l.getGoroutineId() - logInfo.Stack = l.Stack() } l.LogInfoChan <- logInfo } @@ -142,12 +146,26 @@ func (l *Logger) Info(msg string, param ...any) { if l.TrackLine { logInfo.FileName, logInfo.Line, logInfo.FuncName = l.getLineFunc() logInfo.GoroutineId = l.getGoroutineId() - logInfo.Stack = l.Stack() } l.LogInfoChan <- logInfo } func (l *Logger) Error(msg string, param ...any) { + if l.Level > ERROR { + return + } + logInfo := new(LogInfo) + logInfo.Level = ERROR + logInfo.Msg = msg + logInfo.Param = param + if l.TrackLine { + logInfo.FileName, logInfo.Line, logInfo.FuncName = l.getLineFunc() + logInfo.GoroutineId = l.getGoroutineId() + } + l.LogInfoChan <- logInfo +} + +func (l *Logger) ErrorStack(msg string, param ...any) { if l.Level > ERROR { return } diff --git a/protocol/cmd/cmd_id_proto_obj_map.go b/protocol/cmd/cmd_id_proto_obj_map.go index c8e13961..75945f84 100644 --- a/protocol/cmd/cmd_id_proto_obj_map.go +++ b/protocol/cmd/cmd_id_proto_obj_map.go @@ -93,13 +93,14 @@ func (a *CmdProtoMap) registerAllMessage() { a.registerMessage(HostPlayerNotify, &proto.HostPlayerNotify{}) // 世界房主玩家信息通知 // 战斗与技能 - a.registerMessage(AvatarFightPropNotify, &proto.AvatarFightPropNotify{}) // 角色战斗属性通知 - a.registerMessage(EntityFightPropUpdateNotify, &proto.EntityFightPropUpdateNotify{}) // 实体战斗属性更新通知 - a.registerMessage(CombatInvocationsNotify, &proto.CombatInvocationsNotify{}) // 战斗通知 包含场景中实体的移动数据和伤害数据,多人游戏服务器转发 - a.registerMessage(AbilityInvocationsNotify, &proto.AbilityInvocationsNotify{}) // 技能通知 多人游戏服务器转发 - a.registerMessage(ClientAbilityInitFinishNotify, &proto.ClientAbilityInitFinishNotify{}) // 客户端技能初始化完成通知 多人游戏服务器转发 - a.registerMessage(EvtDoSkillSuccNotify, &proto.EvtDoSkillSuccNotify{}) // 释放技能成功事件通知 - a.registerMessage(ClientAbilityChangeNotify, &proto.ClientAbilityChangeNotify{}) // 客户端技能改变通知 + a.registerMessage(AvatarFightPropNotify, &proto.AvatarFightPropNotify{}) // 角色战斗属性通知 + a.registerMessage(EntityFightPropUpdateNotify, &proto.EntityFightPropUpdateNotify{}) // 实体战斗属性更新通知 + a.registerMessage(CombatInvocationsNotify, &proto.CombatInvocationsNotify{}) // 战斗通知 包含场景中实体的移动数据和伤害数据,多人游戏服务器转发 + a.registerMessage(AbilityInvocationsNotify, &proto.AbilityInvocationsNotify{}) // 技能通知 多人游戏服务器转发 + a.registerMessage(ClientAbilityInitFinishNotify, &proto.ClientAbilityInitFinishNotify{}) // 客户端技能初始化完成通知 多人游戏服务器转发 + a.registerMessage(EvtDoSkillSuccNotify, &proto.EvtDoSkillSuccNotify{}) // 释放技能成功事件通知 + a.registerMessage(ClientAbilityChangeNotify, &proto.ClientAbilityChangeNotify{}) // 客户端技能改变通知 + a.registerMessage(MassiveEntityElementOpBatchNotify, &proto.MassiveEntityElementOpBatchNotify{}) // MEEO通知 // 队伍 a.registerMessage(ChangeAvatarReq, &proto.ChangeAvatarReq{}) // 更换角色请求 切人 @@ -223,15 +224,15 @@ func (a *CmdProtoMap) registerAllMessage() { a.registerMessage(ServerAnnounceNotify, &proto.ServerAnnounceNotify{}) // 服务器公告通知 a.registerMessage(ServerAnnounceRevokeNotify, &proto.ServerAnnounceRevokeNotify{}) // 服务器公告撤销通知 - // TODO - a.registerMessage(EvtAiSyncSkillCdNotify, &proto.EvtAiSyncSkillCdNotify{}) - a.registerMessage(EvtAiSyncCombatThreatInfoNotify, &proto.EvtAiSyncCombatThreatInfoNotify{}) - a.registerMessage(EntityConfigHashNotify, &proto.EntityConfigHashNotify{}) - a.registerMessage(MonsterAIConfigHashNotify, &proto.MonsterAIConfigHashNotify{}) - a.registerMessage(GetRegionSearchReq, &proto.GetRegionSearchReq{}) - a.registerMessage(ObstacleModifyNotify, &proto.ObstacleModifyNotify{}) - a.registerMessage(EvtCreateGadgetNotify, &proto.EvtCreateGadgetNotify{}) - a.registerMessage(EvtDestroyGadgetNotify, &proto.EvtDestroyGadgetNotify{}) + //// TODO + //a.registerMessage(EvtAiSyncSkillCdNotify, &proto.EvtAiSyncSkillCdNotify{}) + //a.registerMessage(EvtAiSyncCombatThreatInfoNotify, &proto.EvtAiSyncCombatThreatInfoNotify{}) + //a.registerMessage(EntityConfigHashNotify, &proto.EntityConfigHashNotify{}) + //a.registerMessage(MonsterAIConfigHashNotify, &proto.MonsterAIConfigHashNotify{}) + //a.registerMessage(GetRegionSearchReq, &proto.GetRegionSearchReq{}) + //a.registerMessage(ObstacleModifyNotify, &proto.ObstacleModifyNotify{}) + //a.registerMessage(EvtCreateGadgetNotify, &proto.EvtCreateGadgetNotify{}) + //a.registerMessage(EvtDestroyGadgetNotify, &proto.EvtDestroyGadgetNotify{}) // 空消息 a.registerMessage(65535, &proto.NullMsg{})