From d74652373cf35c4cc1b7fd70d65d69c9132c64f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Mon, 16 Mar 2026 22:30:12 +0800 Subject: [PATCH] =?UTF-8?q?```=20refactor(socket):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=B9=BF=E6=92=AD=E5=92=8C=E9=80=80=E5=87=BA=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E7=B1=BB=E5=9E=8B=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新socket服务器中广播功能和退出功能的代码, 将player.Player类型替换为player.ClientData类型, 并相应调整方法调用以适应新的数据结构。 feat(map): 添加LoadOrStore方法支持 在并发安全的swiss map中新增LoadOrStore方法, 提供原子性的加载或存储功能,增强map的操作能力。 refactor(login): 优化登录逻辑中的玩家获取方式 重构登录控制器中获取玩家对象的方式, 直接从 --- common/socket/kick.go | 22 +++++++------- .../concurrent_swiss_map.go | 4 +++ logic/controller/login_main.go | 2 +- logic/main.go | 4 +-- logic/service/player/new.go | 4 +-- logic/service/player/pack.go | 10 +++++++ logic/service/player/player.go | 4 +-- logic/service/player/save.go | 3 -- logic/service/player/server.go | 29 +------------------ 9 files changed, 32 insertions(+), 50 deletions(-) diff --git a/common/socket/kick.go b/common/socket/kick.go index 6883ee27e..adfe104bd 100644 --- a/common/socket/kick.go +++ b/common/socket/kick.go @@ -13,9 +13,9 @@ type Broadcast struct { func (s *Server) Broadcast(t string) int { - player.Mainplayer.Range(func(key uint32, value *player.Player) bool { + player.Mainplayer.Range(func(key uint32, value *player.ClientData) bool { - value.SendPackCmd(50003, &Broadcast{ + value.Player.SendPackCmd(50003, &Broadcast{ Name: t, }) return true @@ -42,32 +42,32 @@ func (s *Server) QuitSelf(a int) error { s.quit = true if a != 0 { - player.Mainplayer.Range(func(key uint32, value *player.Player) bool { + player.Mainplayer.Range(func(key uint32, value *player.ClientData) bool { if value != nil { - value.Kick(true) + value.Player.Kick(true) } return false }) } else { - + go func() { - player.Mainplayer.Range(func(key uint32, value *player.Player) bool { + player.Mainplayer.Range(func(key uint32, value *player.ClientData) bool { if value != nil { - value.KickMessage() + value.Player.KickMessage() } return false }) <-time.After(10 * time.Minute) - player.Mainplayer.Range(func(key uint32, value *player.Player) bool { + player.Mainplayer.Range(func(key uint32, value *player.ClientData) bool { if value != nil { - value.Kick(true) + value.Player.Kick(true) } - + return false }) - os.Exit(0) + os.Exit(0) }() } diff --git a/common/utils/concurrent-swiss-map/concurrent_swiss_map.go b/common/utils/concurrent-swiss-map/concurrent_swiss_map.go index 62e7358cd..8d6660449 100644 --- a/common/utils/concurrent-swiss-map/concurrent_swiss_map.go +++ b/common/utils/concurrent-swiss-map/concurrent_swiss_map.go @@ -43,6 +43,10 @@ func WithSize[K comparable, V any](size uint64) func(csMap *CsMap[K, V]) { func (m *CsMap[K, V]) Store(key K, value V) { m.inner.Store(key, value) } +func (m *CsMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { + T, OK := m.inner.LoadOrStore(key, value) + return T.(V), OK +} // Delete 删除指定键,返回是否删除成功 func (m *CsMap[K, V]) Delete(key K) bool { diff --git a/logic/controller/login_main.go b/logic/controller/login_main.go index 886da8a05..e5148d268 100644 --- a/logic/controller/login_main.go +++ b/logic/controller/login_main.go @@ -41,7 +41,7 @@ func (h Controller) Login(data *user.MAIN_LOGIN_IN, c gnet.Conn) (result *user.L } } - currentPlayer := player.GetPlayer(c, data.Head.UserID) + currentPlayer := c.Context().(*player.ClientData).GetPlayer(data.Head.UserID) if currentPlayer == nil { cool.Logger.Error(context.Background(), "获取玩家失败", data.Head.UserID) diff --git a/logic/main.go b/logic/main.go index e29a40b0c..1aa0bbb42 100644 --- a/logic/main.go +++ b/logic/main.go @@ -60,8 +60,8 @@ func PprofWeb() { func cleanup() { fmt.Println("执行优雅清理资源...") - player.Mainplayer.Range(func(key uint32, value *player.Player) bool { - value.Kick(true) + player.Mainplayer.Range(func(key uint32, value *player.ClientData) bool { + value.Player.Kick(true) return false }) diff --git a/logic/service/player/new.go b/logic/service/player/new.go index 2d7b39c24..c8ddf8159 100644 --- a/logic/service/player/new.go +++ b/logic/service/player/new.go @@ -27,9 +27,7 @@ func NewPlayer(opts gnet.Conn) *Player { p.monsters = generateThreeUniqueNumbers() p.Done = NewDone(p) //发布订阅事件 - p.MapNPC = time.AfterFunc(10*time.Second, func() { - p.GenMonster() //生成野怪 - }) + p.MapNPC = time.AfterFunc(10*time.Second, p.GenMonster) p.MainConn = opts return p diff --git a/logic/service/player/pack.go b/logic/service/player/pack.go index 6c72adc90..f054c7b2b 100644 --- a/logic/service/player/pack.go +++ b/logic/service/player/pack.go @@ -219,6 +219,16 @@ type ClientData struct { //SaveDone chan struct{} } +func (p *ClientData) GetPlayer(userid uint32) *Player { //TODO 这里待优化,可能存在内存泄漏问题 + + _, ok := Mainplayer.LoadOrStore(userid, p) + if !ok { + p.Player = NewPlayer(p.Conn) + } + + return p.Player + // return nil +} func NewClientData(c gnet.Conn) *ClientData { // 创建事件处理器 // 创建消费端串行处理的Lockfree diff --git a/logic/service/player/player.go b/logic/service/player/player.go index 9dfe6d49d..35ebe95d8 100644 --- a/logic/service/player/player.go +++ b/logic/service/player/player.go @@ -27,7 +27,7 @@ import ( ) // Mainplayer 全局玩家数据存储映射 -var Mainplayer = csmap.New[uint32, *Player]() +var Mainplayer = csmap.New[uint32, *ClientData]() type OgrePetInfo struct { ID uint32 @@ -284,7 +284,7 @@ func (player1 *Player) Kick(isquit bool) { case <-CloseChan: // 正常流程:连接关闭回调已执行,CloseChan 被关闭 case <-time.After(kickTimeout): - player1.Service.Info.Save(*player1.Info) + player1.Save() service.NewBaseSysLogService().RecordKick(uint32(player1.Info.UserID), fmt.Errorf("踢人操作超时(超时时间:%v)", kickTimeout).Error()) // 超时处理:避免永久阻塞,可添加日志便于排查问题 // 注意:这里不会中断 CloseWithCallback 的执行,仅解除当前协程的阻塞 diff --git a/logic/service/player/save.go b/logic/service/player/save.go index 11bc942db..45c3a91e9 100644 --- a/logic/service/player/save.go +++ b/logic/service/player/save.go @@ -16,10 +16,7 @@ import ( // Save 保存玩家数据 func (p *Player) Save() { cool.CacheManager.Remove(context.TODO(), fmt.Sprintf("player:%d", p.Info.UserID)) - if cool.Config.ServerInfo.IsVip != 0 { - return - } if p.Info == nil { return diff --git a/logic/service/player/server.go b/logic/service/player/server.go index 8bce21cbc..3e8e5e4ab 100644 --- a/logic/service/player/server.go +++ b/logic/service/player/server.go @@ -1,37 +1,10 @@ package player -import ( - "github.com/panjf2000/gnet/v2" -) - -func GetPlayer(c gnet.Conn, userid uint32) *Player { //TODO 这里待优化,可能存在内存泄漏问题 - - //检查player初始化,是否为conn初始后取map,防止二次连接后存在两个player - - clientdata, ok := c.Context().(*ClientData) - if !ok { - return nil - } - if clientdata.Player == nil { - - clientdata.Player = NewPlayer(c) - - } - - // gff := socket.NewClientData() - - // gff.Player = clientdata.Player - // c.MainConn.SetContext(gff) - Mainplayer.Store(userid, clientdata.Player) - - return clientdata.Player - // return nil -} func KickPlayer(userid uint32) error { //踢出玩家 //TODO 返回错误码 //var player *entity.Player if player1, ok := Mainplayer.Load(userid); ok { - player1.Kick(false) + player1.Player.Kick(false) }