diff --git a/common/socket/ServerEvent.go b/common/socket/ServerEvent.go index 0cec9b71b..daafc3d98 100644 --- a/common/socket/ServerEvent.go +++ b/common/socket/ServerEvent.go @@ -63,7 +63,7 @@ func (s *Server) OnClose(c gnet.Conn, err error) (action gnet.Action) { //logging.Infof("conn[%v] disconnected", c.RemoteAddr().String()) v, _ := c.Context().(*player.ClientData) - v.LF.Close() + v.LF.Close() //关闭继续接受 if v.Player != nil { v.Player.Save() //保存玩家数据 @@ -153,7 +153,11 @@ func (s *Server) OnTraffic(c gnet.Conn) (action gnet.Action) { t := c.Context().(*player.ClientData) for _, msg := range messages { - t.LF.Producer().Write(msg.Payload) + + if t.LF.Running() { + t.LF.Producer().Write(msg.Payload) + } + //t.OnEvent(msg.Payload) } @@ -177,7 +181,10 @@ func (s *Server) handleTCP(conn gnet.Conn) (action gnet.Action) { } if t, ok := conn.Context().(*player.ClientData); ok { - t.LF.Producer().Write(data) + if t.LF.Running() { + t.LF.Producer().Write(data) + } + } if conn.InboundBuffered() > 0 { diff --git a/common/socket/kick.go b/common/socket/kick.go index 170a49e2b..e73c6b3e6 100644 --- a/common/socket/kick.go +++ b/common/socket/kick.go @@ -43,7 +43,7 @@ func (s *Server) QuitSelf(a int) error { if a != 0 { player.Mainplayer.Range(func(key uint32, value *player.Player) bool { if value != nil { - value.Kick() + value.Kick(true) } return false @@ -60,7 +60,7 @@ func (s *Server) QuitSelf(a int) error { <-time.After(10 * time.Minute) player.Mainplayer.Range(func(key uint32, value *player.Player) bool { if value != nil { - value.Kick() + value.Kick(true) } return false diff --git a/help/查询多余精灵.sql b/help/查询多余精灵.sql new file mode 100644 index 000000000..5fd2befd4 --- /dev/null +++ b/help/查询多余精灵.sql @@ -0,0 +1,11 @@ +SELECT + player_id, + COUNT(*) AS pet_count +FROM + "player_pet" +WHERE + (data->>'ID')::INT IN (273, 274) -- 适配JSONB的data字段取id并转整型 +GROUP BY + player_id +HAVING + COUNT(*) >= 2; -- 筛选出拥有273/274宠物的玩家,可根据需求调整为>=2(同时拥有两者) \ No newline at end of file diff --git a/logic/controller/fight_pvp_withplayer.go b/logic/controller/fight_pvp_withplayer.go index 305f9942b..cfd0e7985 100644 --- a/logic/controller/fight_pvp_withplayer.go +++ b/logic/controller/fight_pvp_withplayer.go @@ -55,6 +55,8 @@ func (h Controller) OnPlayerHandleFightInvite(data *fight.HandleFightInviteInbou _, err = fight.NewFight(v, c, func(foi info.FightOverInfo) { + //println("好友对战测试", foi.Reason) + }) if err <= 0 { //成功发起对战 diff --git a/logic/controller/login_main.go b/logic/controller/login_main.go index 4553f2b7c..1472ab9c6 100644 --- a/logic/controller/login_main.go +++ b/logic/controller/login_main.go @@ -49,6 +49,7 @@ func (h Controller) Login(data *user.MAIN_LOGIN_IN, c gnet.Conn) (result *user.L defer space.GetSpace(currentPlayer.Info.MapID).EnterMap(currentPlayer) + currentPlayer.IsLogin = true return result, 0 } diff --git a/logic/main.go b/logic/main.go index f4288c244..f4c268b93 100644 --- a/logic/main.go +++ b/logic/main.go @@ -38,7 +38,7 @@ func cleanup() { log.Println("执行优雅清理资源...") player.Mainplayer.Range(func(key uint32, value *player.Player) bool { - value.Kick() + value.Kick(true) return false }) diff --git a/logic/service/fight/action.go b/logic/service/fight/action.go index b7bb2243f..480738867 100644 --- a/logic/service/fight/action.go +++ b/logic/service/fight/action.go @@ -5,6 +5,7 @@ import ( "blazing/logic/service/fight/action" "blazing/logic/service/fight/info" "blazing/logic/service/fight/input" + "blazing/logic/service/player" "github.com/jinzhu/copier" ) @@ -168,6 +169,9 @@ func (f *FightC) startBattle(startInfo info.FightStartOutboundInfo) { // 通知双方玩家准备完成,即将开始战斗 ff.Player.SendPackCmd(2504, &startInfo) + if _, ok := ff.Player.(*player.AI_player); ok { + ff.GetAction() + } }) }) diff --git a/logic/service/fight/fightc.go b/logic/service/fight/fightc.go index af0c3e21f..abd5d7648 100644 --- a/logic/service/fight/fightc.go +++ b/logic/service/fight/fightc.go @@ -375,13 +375,10 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction) if f.closefight { return } - //println("回合结束") - if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC { - if f.Opp.CurrentPet.Info.Hp <= 0 { - f.Opp.GetAction() - //panic("AI自动技能") - } + if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC { + println("AI出手") + go f.Opp.GetAction() } diff --git a/logic/service/fight/input/ai.go b/logic/service/fight/input/ai.go index b062a1369..b0930a447 100644 --- a/logic/service/fight/input/ai.go +++ b/logic/service/fight/input/ai.go @@ -17,6 +17,7 @@ func (our *Input) GetAction() { if selfPet.Info.Hp <= 0 { for _, v := range our.AllPet { if v.Info.Hp > 0 { + println("AI出手,切换宠物") our.FightC.ChangePet(our.Player, v.Info.CatchTime) return } @@ -76,29 +77,4 @@ func (our *Input) GetAction() { our.FightC.UseSkill(our.Player, 0) } - // // 若存在能秒杀的技能,优先使用(选伤害最高的,避免浪费高伤害技能) - // if len(killableSkills) > 0 { - // bestKillSkill := killableSkills[0].SkillEntity - // maxDamage := killableSkills[0].damage - // for _, ks := range killableSkills[1:] { - // if ks.damage.Cmp(maxDamage) > 0 { // 使用decimal的比较方法比较伤害值 - // if ks.CanUse() { - // maxDamage = ks.damage - // bestKillSkill = ks.SkillEntity - // } - - // } - // } - // our.FightC.UseSkill(our.Player, uint32(bestKillSkill.ID)) - // return - // } - // if len(allSkills) <= 0 { - // our.FightC.UseSkill(our.Player, 0) - // return - // } - - // 优化随机选择技能的逻辑,直接使用随机索引 - // randomIdx := grand.Intn(len(allSkills)) - // our.FightC.UseSkill(our.Player, uint32(allSkills[randomIdx].ID)) - } diff --git a/logic/service/fight/loop.go b/logic/service/fight/loop.go index ffacd8b62..591bffe58 100644 --- a/logic/service/fight/loop.go +++ b/logic/service/fight/loop.go @@ -161,10 +161,10 @@ func (f *FightC) collectPlayerActions(ourID, oppID uint32) map[uint32]action.Bat if pid != ourID && pid != oppID { continue } - if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC && pid != 0 { - f.Opp.GetAction() + // if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC && pid != 0 { + // f.Opp.GetAction() - } + // } selfinput := f.GetInputByAction(paction, false) if ret, ok := paction.(*action.ActiveSwitchAction); ok { //正常结束可以切换,以及死切后还能再切一次 @@ -211,6 +211,8 @@ func (f *FightC) collectPlayerActions(ourID, oppID uint32) map[uint32]action.Bat if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC && pid == 0 { f.Switch = make(map[uint32]*action.ActiveSwitchAction) f.Our.Player.SendPackCmd(2407, &ret.Reason) + println("AI出手死切") + go f.Our.GetAction() //boss出手后获取出招 } continue diff --git a/logic/service/player/boss.go b/logic/service/player/boss.go index 7e2de866b..c121a3dc6 100644 --- a/logic/service/player/boss.go +++ b/logic/service/player/boss.go @@ -21,6 +21,9 @@ func (p *Player) getTaskGift(taskID int, ot int) *task.TaskResult { // SptCompletedTask 完成任务(单分支) // 优化点:仅当奖励存在时,才完成任务并发放奖励 func (p *Player) SptCompletedTask(taskID int, ot int) { + if !p.IsLogin { + return + } // 1. 检查任务当前状态:未接受才处理 if p.Info.GetTask(taskID) != model.Unaccepted { return @@ -40,6 +43,9 @@ func (p *Player) SptCompletedTask(taskID int, ot int) { // TawerCompletedTask 完成塔类任务(多分支) // 优化点:1. 默认分支仅奖励存在时才完成主任务 2. 指定分支仅奖励存在时才标记完成并发奖 func (p *Player) TawerCompletedTask(taskID int, ot int) { + if !p.IsLogin { + return + } // 处理默认分支(ot=-1):仅奖励存在时才完成主任务 if p.Info.GetTask(taskID) == model.Unaccepted { defaultGift := p.getTaskGift(taskID, -1) diff --git a/logic/service/player/player.go b/logic/service/player/player.go index d29b9a660..015c308b8 100644 --- a/logic/service/player/player.go +++ b/logic/service/player/player.go @@ -223,14 +223,19 @@ func (p *Player) ItemAdd(ItemId, ItemCnt uint32) (result bool) { return false } -func (player1 *Player) Kick() { + +// Kick 是否热更退出 +func (player1 *Player) Kick(isquit bool) { if player1.Info == nil { return } head := common.NewTomeeHeader(1001, player1.Info.UserID) - head.Result = uint32(errorcode.ErrorCodes.ErrXinPlanSleepMode) + head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere) + if isquit { + head.Result = uint32(errorcode.ErrorCodes.ErrXinPlanSleepMode) + } // 实际上这里有个问题,会造成重复保存问题 player1.SendPack(head.Pack(nil)) @@ -244,7 +249,7 @@ func (player1 *Player) Kick() { // --- 新增超时机制核心代码 --- // 设定超时时间(可根据业务需求调整,这里以3秒为例) - const kickTimeout = 3 * time.Second + const kickTimeout = 5 * time.Second select { case <-CloseChan: // 正常流程:连接关闭回调已执行,CloseChan 被关闭 diff --git a/logic/service/player/save.go b/logic/service/player/save.go index 1403b7d5e..ca37a10bb 100644 --- a/logic/service/player/save.go +++ b/logic/service/player/save.go @@ -5,6 +5,7 @@ import ( "blazing/cool" "fmt" + "blazing/logic/service/fight/info" "blazing/logic/service/space" "context" "time" @@ -26,7 +27,12 @@ func (p *Player) Save() { p.Info.TimeToday = p.Info.TimeToday + newtime - uint32(p.Logintime) //保存电池时间 p.Info.OnlineTime = p.Info.OnlineTime + (newtime-uint32(p.Logintime))/60 //每次退出时候保存已经在线的分钟数 + if p.FightC != nil { + go p.FightC.Over(p, info.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程 + + } + p.IsLogin = false p.Service.Info.Save(*p.Info) space.GetSpace(p.Info.MapID).LeaveMap(p) diff --git a/logic/service/player/server.go b/logic/service/player/server.go index 918250590..df8a84877 100644 --- a/logic/service/player/server.go +++ b/logic/service/player/server.go @@ -34,7 +34,7 @@ func KickPlayer(userid uint32) error { //踢出玩家 //TODO 返回错误码 //var player *entity.Player if player1, ok := Mainplayer.Load(userid); ok { - player1.Kick() + player1.Kick(false) }