diff --git a/common/socket/ServerEvent.go b/common/socket/ServerEvent.go index 9c01acf1c..753cb117a 100644 --- a/common/socket/ServerEvent.go +++ b/common/socket/ServerEvent.go @@ -65,11 +65,7 @@ func (s *Server) OnClose(c gnet.Conn, err error) (action gnet.Action) { v, _ := c.Context().(*player.ClientData) v.LF.Close() if v.Player != nil { - v.SaveL.Do(func() { //使用保存锁,确保在踢人和掉线的时候只保存一次 - - v.Player.Save() //保存玩家数据 - - }) + v.Player.Save() //保存玩家数据 } @@ -110,7 +106,7 @@ func (s *Server) OnTraffic(c gnet.Conn) (action gnet.Action) { if err := recover(); err != nil { // 恢复 panic,err 为 panic 错误值 // 1. 打印错误信息 - fmt.Println(context.TODO(), "panic 错误:", err) + cool.Logger.Error(context.TODO(), "panic 错误:", err) } }() diff --git a/common/socket/kick.go b/common/socket/kick.go index c36ca0f9e..9a1eeb5e6 100644 --- a/common/socket/kick.go +++ b/common/socket/kick.go @@ -4,7 +4,6 @@ import ( "blazing/common/socket/errorcode" "blazing/logic/service/common" "blazing/logic/service/player" - "blazing/modules/base/service" "fmt" "time" ) @@ -34,25 +33,7 @@ func (s *Server) KickPerson(a int) error { return nil } - // 1. 创建结果通道 - resultChan := make(chan error, 1) - - // 2. 启动 goroutine 执行踢人操作 - go func() { - err := player.KickPlayer(uint32(a)) - resultChan <- err - }() - - // 3. 用 select 监听结果和超时信号 - select { - case err := <-resultChan: - // 正常完成 - return err - case <-time.After(kickTimeout): - service.NewBaseSysLogService().RecordKick(uint32(a), fmt.Errorf("踢人操作超时(超时时间:%v)", kickTimeout).Error()) - // 超时触发,返回自定义或内置超时错误 - return fmt.Errorf("踢人操作超时(超时时间:%v)", kickTimeout) - } + return player.KickPlayer(uint32(a)) } // 参数不为0是强制踢出 diff --git a/logic/controller/item_use.go b/logic/controller/item_use.go index c5cf77da0..25d6289c3 100644 --- a/logic/controller/item_use.go +++ b/logic/controller/item_use.go @@ -67,7 +67,7 @@ func (h Controller) UsePetItemOutOfFight(data *item.C2S_USE_PET_ITEM_OUT_OF_FIGH result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{} currentPet.CalculatePetPane(false) copier.Copy(&result, currentPet) - + defer c.Service.Info.Save(*c.Info) return result, 0 } diff --git a/logic/main.go b/logic/main.go index 31802e5b2..e664e38ba 100644 --- a/logic/main.go +++ b/logic/main.go @@ -18,7 +18,6 @@ import ( "github.com/shirou/gopsutil/v4/mem" - "blazing/modules/base/service" blservice "blazing/modules/player/service" "net/http" @@ -80,6 +79,7 @@ func main() { // if cool.Config.PortBL == 1 || cool.Config.PortBL == 2 { //只分析1服务器的 // go PprofWeb() // } + go PprofWeb() go monitorMemAndQuit() fmt.Println("Process start, pid:", os.Getpid()) diff --git a/logic/service/player/pack.go b/logic/service/player/pack.go index 0ebb546c6..3178f3674 100644 --- a/logic/service/player/pack.go +++ b/logic/service/player/pack.go @@ -133,8 +133,8 @@ type ClientData struct { ERROR_CONNUT int Wsmsg *WsCodec Conn gnet.Conn - SaveL sync.Once //保存锁 - LF *lockfree.Lockfree[[]byte] + //SaveL sync.Once //保存锁 + LF *lockfree.Lockfree[[]byte] //SaveDone chan struct{} } diff --git a/logic/service/player/player.go b/logic/service/player/player.go index e501043dc..0951d45ee 100644 --- a/logic/service/player/player.go +++ b/logic/service/player/player.go @@ -7,7 +7,9 @@ import ( "blazing/logic/service/common" "blazing/logic/service/fight/info" "blazing/logic/service/space" + "fmt" "sync/atomic" + "time" "blazing/modules/base/service" @@ -224,27 +226,35 @@ func (p *Player) ItemAdd(ItemId, ItemCnt uint32) (result bool) { } func (player1 *Player) Kick(qtype int) { - - //取成功,否则创建 - //player1.Save() //先保存数据再返回 + // 取成功,否则创建 + // player1.Save() //先保存数据再返回 head := common.NewTomeeHeader(1001, player1.Info.UserID) head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere) if qtype == 1 { head.Result = uint32(errorcode.ErrorCodes.ErrXinPlanSleepMode) } - //实际上这里有个问题,会造成重复保存问题 + // 实际上这里有个问题,会造成重复保存问题 player1.SendPack(head.Pack(nil)) CloseChan := make(chan struct{}) player1.MainConn.CloseWithCallback(func(c gnet.Conn, err error) error { - close(CloseChan) return nil }) - <-CloseChan + // --- 新增超时机制核心代码 --- + // 设定超时时间(可根据业务需求调整,这里以3秒为例) + const kickTimeout = 3 * time.Second + select { + case <-CloseChan: + // 正常流程:连接关闭回调已执行,CloseChan 被关闭 + case <-time.After(kickTimeout): + service.NewBaseSysLogService().RecordKick(uint32(player1.Info.UserID), fmt.Errorf("踢人操作超时(超时时间:%v)", kickTimeout).Error()) + // 超时处理:避免永久阻塞,可添加日志便于排查问题 + // 注意:这里不会中断 CloseWithCallback 的执行,仅解除当前协程的阻塞 + } } func (p *Player) Cheak(b error) { diff --git a/logic/service/player/save.go b/logic/service/player/save.go index 08e3ea896..6c1f2cfa3 100644 --- a/logic/service/player/save.go +++ b/logic/service/player/save.go @@ -22,30 +22,6 @@ func (p *Player) Save() { return } - // if p.FightC != nil { - - // //ov := make(chan struct{}) - // go func() { - - // defer func() { - // if err := recover(); err != nil { // 恢复 panic,err 为 panic 错误值 - // // 1. 打印错误信息 - - // cool.Logger.Error(context.TODO(), "panic 错误:", err) - - // } - // }() - // p.FightC.Over(p, info.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程 - // }() - // //<-ov - // select { - // case <-p.FightC.GetOverChan(): //等待结束 - // case <-time.After(time.Second * 5): //等待5秒 - // cool.Logger.Error(context.TODO(), "战斗崩溃", p.Info.UserID) - - // } - - // } newtime := uint32(time.Now().Unix()) p.Info.TimeToday = p.Info.TimeToday + newtime - uint32(p.Logintime) //保存电池时间 diff --git a/modules/config/service/pet_fusion_material_service.go b/modules/config/service/pet_fusion_material_service.go index 1101c8bee..cd4306c7c 100644 --- a/modules/config/service/pet_fusion_material_service.go +++ b/modules/config/service/pet_fusion_material_service.go @@ -54,26 +54,20 @@ func (s *PetFusionMaterialService) Data(Material1 [4]uint32) int32 { "is_enable": 1, } m.Where(condition).Scan(&effect) - //这时候有可能效果是空的,那么这时候就再次查询默认的特性,保证每次必会生成一个数据库有的特性 - //也许这个时候的特性配方就是随机从数据库中查找一个特性 + if effect != nil { - // if effect == nil { - // effect2s := service.NewDictInfoService().GetData("effect") - // for _, v := range effect2s { - // return gconv.Uint32(v.Value) - // } - - // } - r := grand.Intn(4) - switch r { - case 0: - return int32(effect.Trait1Idx) - case 1: - return int32(effect.Trait2Idx) - case 2: - return int32(effect.Trait3Idx) - case 3: - return int32(effect.Trait4Idx) + r := grand.Intn(4) + switch r { + case 0: + return int32(effect.Trait1Idx) + case 1: + return int32(effect.Trait2Idx) + case 2: + return int32(effect.Trait3Idx) + case 3: + return int32(effect.Trait4Idx) + } } + return -1 }