refactor(socket): 更新广播和退出逻辑中的类型引用

更新socket服务器中广播功能和退出功能的代码,
将player.Player类型替换为player.ClientData类型,
并相应调整方法调用以适应新的数据结构。

feat(map): 添加LoadOrStore方法支持

在并发安全的swiss map中新增LoadOrStore方法,
提供原子性的加载或存储功能,增强map的操作能力。

refactor(login): 优化登录逻辑中的玩家获取方式

重构登录控制器中获取玩家对象的方式,
直接从
This commit is contained in:
昔念
2026-03-16 22:30:12 +08:00
parent 30dba8fee3
commit d74652373c
9 changed files with 32 additions and 50 deletions

View File

@@ -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)

View File

@@ -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
})

View File

@@ -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

View File

@@ -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

View File

@@ -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 的执行,仅解除当前协程的阻塞

View File

@@ -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

View File

@@ -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)
}