refactor(common): 重构 common 模块

- 移除 global.go 文件
- 更新 player.go 中的玩家数据存储方式
- 删除 session.go 文件
- 调整 rpc.go 中的 RPC 客户端方法
- 更新 ServerEvent.go 中的会话管理
- 调整 controller 中的 Maincontroller 结构
- 更新 login.go 中的用户登录逻辑
- 调整 service 中的玩家数据获取方式
- 更新 admin/login.go 和 login.go 中的会话管理
This commit is contained in:
2025-07-15 12:14:17 +08:00
parent 43a726006c
commit 7a87bfa089
13 changed files with 208 additions and 80 deletions

View File

@@ -1,16 +1,17 @@
package core
package cool
import (
"fmt"
"context"
"sync"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/util/gconv"
"github.com/yitter/idgenerator-go/idgen"
)
var (
Mainplayer sync.Map //玩家数据
Maincmdcache sync.Map //命令缓存
Mainplayer sync.Map //玩家数据
CmdCache sync.Map //命令缓存
)
func init() {
@@ -25,7 +26,6 @@ func init() {
// 保存参数(务必调用,否则参数设置不生效):
idgen.SetIdGenerator(options)
newId := idgen.NextId()
fmt.Println(newId, "初始化雪花算法")
glog.Debug(context.Background(), "初始化雪花算法", newId)
}

181
common/data/cache/cache.go vendored Normal file
View File

@@ -0,0 +1,181 @@
package cache
import (
"blazing/cool"
"context"
"fmt"
"strings"
"time"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/util/gconv"
)
var (
// ErrCacheMiss 表示缓存未命中
ErrCacheMiss = gerror.New("缓存未找到")
// ErrTypeConvert 表示类型转换失败
ErrTypeConvert = gerror.New("缓存值类型转换失败")
)
// CacheStore 泛型缓存存储
type CacheStore[T any] struct {
manager *gcache.Cache // 缓存管理器
prefix string // 缓存键前缀
}
// NewSessionStore 创建会话缓存实例
func NewSessionStore() *CacheStore[uint32] {
return &CacheStore[uint32]{
manager: cool.CacheManager,
prefix: "blazing:session:",
}
}
// NewUserOnlineStore 创建用户在线状态缓存实例
func NewUserOnlineStore() *CacheStore[uint32] {
return &CacheStore[uint32]{
manager: cool.CacheManager,
prefix: "blazing:useronline:",
}
}
// 生成带前缀的缓存键
func (s *CacheStore[T]) formatKey(key string) string {
return s.prefix + strings.TrimSpace(key)
}
// Get 通过键获取缓存值
func (s *CacheStore[T]) Get(ctx context.Context, key string) (T, error) {
var zero T
result, err := s.manager.Get(ctx, s.formatKey(key))
if err != nil {
return zero, gerror.Wrapf(err, "获取缓存失败,键: %s", key)
}
if result.IsEmpty() {
return zero, ErrCacheMiss
}
// 使用 ConvertWithRefer 进行类型转换
value := gconv.ConvertWithRefer(result.Val(), zero)
// 类型断言检查转换结果
converted, ok := value.(T)
if !ok {
return zero, gerror.Wrapf(
ErrTypeConvert,
"键: %s缓存值实际类型: %T期望类型: %T",
key, result.Val(), zero,
)
}
return converted, nil
}
// Set 设置缓存值并带有效期
func (s *CacheStore[T]) Set(ctx context.Context, key string, value T, duration time.Duration) error {
err := s.manager.Set(ctx, s.formatKey(key), value, duration)
if err != nil {
return gerror.Wrapf(err, "设置缓存失败,键: %s值: %v", key, value)
}
fmt.Printf("[INFO] 缓存操作 [%s] 键: %s 值: %v 有效期: %v\n",
s.prefix, key, value, duration)
return nil
}
// Del 删除缓存
func (s *CacheStore[T]) Del(ctx context.Context, key string) error {
_, err := s.manager.Remove(ctx, s.formatKey(key))
if err != nil {
return gerror.Wrapf(err, "删除缓存失败,键: %s", key)
}
fmt.Printf("[INFO] 删除缓存 [%s] 键: %s 成功\n", s.prefix, key)
return nil
}
// Contains 检查缓存是否存在
func (s *CacheStore[T]) Contains(ctx context.Context, key string) (bool, error) {
exists, err := s.manager.Contains(ctx, s.formatKey(key))
if err != nil {
return false, gerror.Wrapf(err, "检查缓存是否存在失败,键: %s", key)
}
return exists, nil
}
// GetOrSet 获取缓存值,如果不存在则设置默认值
func (s *CacheStore[T]) GetOrSet(ctx context.Context, key string, defaultValue T, duration time.Duration) (T, error) {
var zero T
result, err := s.manager.GetOrSet(ctx, s.formatKey(key), defaultValue, duration)
if err != nil {
return zero, gerror.Wrapf(err, "获取或设置缓存失败,键: %s", key)
}
// 类型转换
value := gconv.ConvertWithRefer(result.Val(), zero)
converted, ok := value.(T)
if !ok {
return zero, gerror.Wrapf(
ErrTypeConvert,
"键: %s缓存值实际类型: %T期望类型: %T",
key, result.Val(), zero,
)
}
return converted, nil
}
// SessionManager 会话管理器
type SessionManager struct {
sessionStore *CacheStore[uint32] // 会话缓存
userOnlineStore *CacheStore[uint32] // 用户在线状态缓存
}
// NewSessionManager 创建会话管理器
func NewSessionManager() *SessionManager {
return &SessionManager{
sessionStore: NewSessionStore(),
userOnlineStore: NewUserOnlineStore(),
}
}
// GetSession 通过会话ID获取用户ID
func (m *SessionManager) GetSession(sessionID string) (uint32, error) {
return m.sessionStore.Get(context.Background(), sessionID)
}
// SaveSession 保存会话信息
func (m *SessionManager) SaveSession(sessionID string, userID uint32) error {
return m.sessionStore.Set(gctx.New(), sessionID, userID, time.Hour*24)
}
// DeleteSession 删除会话
func (m *SessionManager) DeleteSession(sessionID string) error {
return m.sessionStore.Del(gctx.New(), sessionID)
}
// SessionExists 检查会话是否存在
func (m *SessionManager) SessionExists(sessionID string) (bool, error) {
return m.sessionStore.Contains(context.Background(), sessionID)
}
// SetUserOnline 设置用户在线状态
func (m *SessionManager) SetUserOnline(userID uint32, serverID uint32) error {
return m.userOnlineStore.Set(gctx.New(), gconv.String(userID), serverID, 0)
}
// GetUserOnline 获取用户在线状态
func (m *SessionManager) GetUserOnline(userID uint32) (uint32, error) {
return m.userOnlineStore.Get(context.Background(), gconv.String(userID))
}
// DeleteUserOnline 删除用户在线状态
func (m *SessionManager) DeleteUserOnline(userID uint32) error {
return m.userOnlineStore.Del(gctx.New(), gconv.String(userID))
}
// UserOnlineExists 检查用户在线状态是否存在
func (m *SessionManager) UserOnlineExists(userID uint32) (bool, error) {
return m.userOnlineStore.Contains(context.Background(), gconv.String(userID))
}

View File

@@ -1,7 +1,7 @@
package entity
import (
"blazing/common/core"
"blazing/cool"
"github.com/panjf2000/gnet/v2"
)
@@ -48,10 +48,8 @@ func (p *Player) SendPack(b []byte) error {
func ConutPlayer() int {
// v := reflect.ValueOf(&core.Mainplayer).Elem().FieldByName("m").Elem()
// return int(v.FieldByName("count").Int())
count := 0
core.Mainplayer.Range(func(key, value interface{}) bool {
cool.Mainplayer.Range(func(key, value interface{}) bool {
count++
return true // 继续遍历
})

View File

@@ -1,45 +0,0 @@
package session
import (
"blazing/cool"
"context"
"fmt"
"strings"
"time"
"github.com/gogf/gf/v2/os/gctx"
)
var sessionprx = "blazing:session:"
// GetSession 通过给定的键从缓存中获取会话数据。
// 该函数主要执行以下操作:
// 1. 使用 strings.Trim 移除输入字符串 t1 两端的空格,得到 t2。
// 2. 调用 cool.CacheManager.Get 方法,在上下文为 context.Background() 的情况下,使用 t2 作为键从缓存中获取数据。
// 参数:
//
// t1 - 用于获取会话数据的键字符串。
func GetSession(t1 string) (userid uint32, err error) {
// 移除输入键两端的空格,以确保键的格式一致性。
t2 := strings.Trim(t1, " ")
// 从缓存中获取与键 t2 关联的数据。这里假设 cool.CacheManager 已经初始化,并且 Get 方法可用。
// 此处不处理 err可能是因为上层调用者期望处理这个错误或者在特定上下文中错误被视为可接受。
t, err := cool.CacheManager.Get(context.Background(), sessionprx+t2)
userid = t.Uint32()
return
}
func SaveSession(session string, userid string) error {
err := cool.CacheManager.Set(gctx.New(), sessionprx+strings.Trim(session, " "), userid, time.Hour*24)
// gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))
//t, err := cool.CacheManager.Contains(context.Background(), strings.Trim(session, " "))
fmt.Println("前端获取", session, err)
// if t {
// return nil
// }
return err
}

View File

@@ -108,8 +108,6 @@ func StartClient(port uint16, callback any) *struct {
Kick func(int32) error
RegisterLogic func(int32) error
UserLogin func(int32, int32) error
UserLogout func(int32, int32) error
} {
closer1, err := jsonrpc.NewMergeClient(context.Background(), "ws://"+rpcaddr, "", []interface{}{
@@ -141,6 +139,6 @@ var RPCClient struct {
RegisterLogic func(int32) error //注册服务器消息
UserLogin func(int32, int32) error //用户登录事件
UserLogout func(int32, int32) error //用户登出事件
// UserLogin func(int32, int32) error //用户登录事件
// UserLogout func(int32, int32) error //用户登出事件
}

View File

@@ -6,6 +6,7 @@ import (
"sync/atomic"
"time"
"blazing/common/data/cache"
"blazing/common/data/entity"
"github.com/gogf/gf/v2/os/glog"
@@ -48,7 +49,7 @@ func (s *Server) OnClose(c gnet.Conn, _ error) (action gnet.Action) {
t := v.GetPlayer()
if t != nil {
glog.Debug(context.Background(), t.UserID, "断开连接")
cache.NewSessionManager().DeleteUserOnline(t.UserID) //设置用户登录服务器
}
//}

View File

@@ -1,7 +1,6 @@
package controller
import (
"blazing/common/core"
"blazing/common/data/entity"
"blazing/common/socket/handler"
"blazing/cool"
@@ -23,14 +22,11 @@ import (
var Maincontroller = NewController() //注入service
// 分发cmd逻辑实现Controller
type Controller struct {
//connected int64 //统计连接数
Port uint32
RPCClient struct {
Kick func(int32) error
RegisterLogic func(int32) error
UserLogin func(int32, int32) error
UserLogout func(int32, int32) error
}
}
@@ -110,7 +106,7 @@ func init() { //默认初始化扫描
}
glog.Debug(context.Background(), "注册方法", func_cmd, method.Name)
// fmt.Println(methodValue.Interface().(func(gnet.Conn, handler.TomeeHeader)))
_, ok := core.Maincmdcache.LoadOrStore(func_cmd, methodValue) //TODO 待实现对不同用户初始化方法以取消全局cmdcache
_, ok := cool.CmdCache.LoadOrStore(func_cmd, methodValue) //TODO 待实现对不同用户初始化方法以取消全局cmdcache
if ok { //方法已存在init
glog.Error(context.Background(), "方法已存在init,不会初始化后面的方法", func_cmd)
@@ -163,7 +159,7 @@ func getcmd(t reflect.Type) uint32 {
// 遍历结构体方法并执行RECV_cmd
func Recv(c gnet.Conn, data handler.TomeeHeader) {
tt, ok := core.Maincmdcache.Load(data.CMD)
tt, ok := cool.CmdCache.Load(data.CMD)
if !ok {
glog.Error(context.Background(), data.CMD, "cmd未注册")

View File

@@ -1,6 +1,7 @@
package controller
import (
"blazing/common/data/cache"
"blazing/logic/service"
"blazing/logic/service/login"
"encoding/hex"
@@ -15,9 +16,9 @@ func (h *Controller) Login(data login.LoginSidInfo, c gnet.Conn) []byte { //这
if tt := data.CheakSession(); tt { //说明sid正确
h.RPCClient.Kick(int32(data.Head.UserID)) //先踢人
h.RPCClient.UserLogin(int32(h.Port), int32(data.Head.UserID)) //初始化用户登录
// h.RPCClient.UserLogin(int32(h.Port), int32(data.Head.UserID)) //初始化用户登录
service.SetPlayer(c, data.Head.UserID)
cache.NewSessionManager().SetUserOnline(data.Head.UserID, h.Port) //设置用户登录服务器
}
t1, _ := hex.DecodeString("0000045D37000003E9000186A600000000000186A6683F89CF6E69656F0000000000000000000000000008000F00000000000000000000000000000000000000000000000000000001000001DB0000018B000000000000A8C000000000000000000000000000000000000000080001388000000001000000017FFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000000000000000000000000000000000064000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001FFFFFFFF000000004E4F4E4F0000000000000000000000000000000000000001000000010000000100000001000000010000000100000001000000000003030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000100000064000000000000000000000000000000000000001F000000000000006400000000000093F4000093F4000000D5000000F7000000AD00000088000000920000008C0000009C00000000000000000000000000000000000000000000000000000004000027900000001B00004E6200000014000028380000002800004E3E0000002368493DC60000000000000000000000000000000000000000000100000000000000A937000007D1000186A600000000000186A66E69656F00000000000000000000000000000000000000000000000F0000000000000000000001DB0000018B0000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000")

View File

@@ -72,8 +72,8 @@ func Start(serverid uint32) {
}
// go func() {
t := rpc.StartClient(uint16(serverid), controller.Maincontroller)
t := rpc.StartClient(uint16(port), controller.Maincontroller)
//TODO 待实现掉线重新连接login
controller.Maincontroller.RPCClient = *t //将RPC赋值Start
controller.Maincontroller.Port = serverid //赋值服务器ID
//}()

View File

@@ -1,7 +1,7 @@
package login
import (
"blazing/common/data/session"
"blazing/common/data/cache"
"blazing/common/socket/handler"
"encoding/hex"
"fmt"
@@ -21,7 +21,7 @@ func (l *LoginSidInfo) CheakSession() bool {
//g.Dump(tt)
t1 := hex.EncodeToString(l.Sid)
t, err := session.GetSession(t1)
t, err := cache.NewSessionManager().GetSession(t1)
if err != nil {
return false
}

View File

@@ -1,10 +1,10 @@
package service
import (
"blazing/common/core"
"blazing/common/data/entity"
"blazing/common/socket/errorcode"
"blazing/common/socket/handler"
"blazing/cool"
"github.com/panjf2000/gnet/v2"
)
@@ -18,7 +18,7 @@ func GetPlayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优
return clientdata.GetPlayer()
}
var player *entity.Player
if player1, ok := core.Mainplayer.Load((userid)); ok {
if player1, ok := cool.Mainplayer.Load((userid)); ok {
player = player1.(*entity.Player) //取成功,否则创建
clientdata.SetPlayer(player)
}
@@ -29,7 +29,7 @@ func GetPlayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优
func KickPlayer(userid uint32) { //踢出玩家
//TODO 返回错误码
//var player *entity.Player
if player1, ok := core.Mainplayer.Load((userid)); ok {
if player1, ok := cool.Mainplayer.Load((userid)); ok {
player := player1.(*entity.Player) //取成功,否则创建
head := handler.NewTomeeHeader()
head.Result = uint32(errorcode.ErrorCodes.ErrAlreadyLoggedIn)
@@ -52,7 +52,7 @@ func SetPlayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优
entity.WithUserID(userid), //注入ID
entity.WithConn(c), //注入conn
)
core.Mainplayer.Store(userid, player)
cool.Mainplayer.Store(userid, player)
clientdata.SetPlayer(player) //= player

View File

@@ -1,7 +1,7 @@
package admin
import (
"blazing/common/data/session"
"blazing/common/data/cache"
"blazing/cool"
baseservice "blazing/modules/base/service"
"blazing/modules/blazing/service"
@@ -77,7 +77,7 @@ func (c *BlazingController) GetSession(ctx context.Context, req *SessionReq) (re
res.Session = retsid
if err := session.SaveSession(sid, gconv.String(accountID)); err != nil {
if err := cache.NewSessionManager().SaveSession(sid, gconv.String(accountID)); err != nil {
res.Code = 400
res.Msg = err.Error()
}

View File

@@ -54,8 +54,6 @@ func (s *LoginService) SetServerID(OnlineID uint32, Port uint16, t *struct {
Kick func(int32) error
RegisterLogic func(int32) error
UserLogin func(int32, int32) error
UserLogout func(int32, int32) error
}) error {
m := cool.DBM(s.Model).Where("online_id", OnlineID)