From 12323c35b2b6ab0c86d1bfcc4a2c41f64448e078 Mon Sep 17 00:00:00 2001 From: tangmingyou Date: Tue, 28 Mar 2023 11:53:12 +0800 Subject: [PATCH] =?UTF-8?q?=E7=89=8C=E5=B1=80=E7=BB=93=E6=9D=9F,=E6=B8=85?= =?UTF-8?q?=E7=90=86=E7=A6=BB=E7=BA=BF=E7=8E=A9=E5=AE=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/game/actions.go | 2 +- internal/game/{game.go => dealer.go} | 0 internal/game/delayer/delayer.go | 30 ++++++ internal/game/event/game_round_end.go | 62 ++++++++++++ internal/game/store.go | 22 +++++ internal/game/table.go | 19 ++-- internal/{service => logic}/auth.go | 6 +- .../event => logic/delayer}/auto_betting.go | 4 +- internal/logic/delayer/offline_clean.go | 25 +++++ .../{service => logic}/event/event_type.go | 0 internal/{service => logic}/event/offline.go | 20 +--- internal/{service => logic}/event/online.go | 2 +- internal/{service => logic}/service.go | 2 +- internal/logic/store/store.go | 38 ++++++++ internal/{service => logic}/table.go | 41 ++++---- internal/server/route.go | 10 +- internal/server/ws.go | 2 +- internal/server/wsroute.go | 26 ++--- internal/service/store/store.go | 94 ------------------- tool/cache/kvcache.go | 59 ++++++++++++ tool/collect/collect.go | 4 + 21 files changed, 305 insertions(+), 163 deletions(-) rename internal/game/{game.go => dealer.go} (100%) create mode 100644 internal/game/delayer/delayer.go create mode 100644 internal/game/event/game_round_end.go create mode 100644 internal/game/store.go rename internal/{service => logic}/auth.go (98%) rename internal/{service/event => logic/delayer}/auto_betting.go (94%) create mode 100644 internal/logic/delayer/offline_clean.go rename internal/{service => logic}/event/event_type.go (100%) rename internal/{service => logic}/event/offline.go (63%) rename internal/{service => logic}/event/online.go (94%) rename internal/{service => logic}/service.go (98%) create mode 100644 internal/logic/store/store.go rename internal/{service => logic}/table.go (95%) delete mode 100644 internal/service/store/store.go create mode 100644 tool/cache/kvcache.go diff --git a/internal/game/actions.go b/internal/game/actions.go index 8f890ac..982c5e8 100644 --- a/internal/game/actions.go +++ b/internal/game/actions.go @@ -124,7 +124,7 @@ func Fold4Limited(player *Player, betChip int32) proto.Message { player.SetStatus(7) betNotice.Line2 = "弃牌" - // 剩余玩家数为1则结束, 在 service 中判断 + // 剩余玩家数为1则结束, 在 logic 中判断 //leftPlayers := collect.Filter(player.GameTable.Players, func(i int, p *Player) bool { // return p != nil && p.Status != 7 //}) diff --git a/internal/game/game.go b/internal/game/dealer.go similarity index 100% rename from internal/game/game.go rename to internal/game/dealer.go diff --git a/internal/game/delayer/delayer.go b/internal/game/delayer/delayer.go new file mode 100644 index 0000000..e0bfa12 --- /dev/null +++ b/internal/game/delayer/delayer.go @@ -0,0 +1,30 @@ +package delayer + +import ( + "fmt" + "runtime/debug" + "texas-poker-bk/tool/async" + "time" +) + +var ( + GameDelayer *async.DelayQueue[func()] +) + +func init() { + GameDelayer = async.NewDelayQueue(time.Second, 128, handleDelayTask) +} + +func handleDelayTask(task func(), _ time.Time) { + if task == nil { + return + } + defer func() { + if err := recover(); err != nil { + fmt.Printf("consumer handler error: %v \n", err) + // 输出堆栈信息 + fmt.Println(string(debug.Stack())) + } + }() + task() +} diff --git a/internal/game/event/game_round_end.go b/internal/game/event/game_round_end.go new file mode 100644 index 0000000..fd02ad3 --- /dev/null +++ b/internal/game/event/game_round_end.go @@ -0,0 +1,62 @@ +package event + +import ( + "texas-poker-bk/internal/game" + "texas-poker-bk/internal/logic/store" + "texas-poker-bk/tool/collect" + "texas-poker-bk/tool/watcher" +) + +// 回合结束时,自动清除离线玩家 + +var ( + GameRoundEndWatcher *watcher.Watcher[int32, bool] +) + +func init() { + GameRoundEndWatcher = watcher.NewWatcher(32, handleGameRoundEnd) + go GameRoundEndWatcher.Run() +} + +func handleGameRoundEnd(e *watcher.Event[int32, bool]) { + table := game.LobbyTables.Get(e.Publisher) + if table == nil || collect.NotIn(table.Stage, 1, 7) { + return + } + table.Lock.Lock() + defer table.Lock.Unlock() + table.PlayersLock.Lock() + defer table.PlayersLock.Unlock() + + notice := true + for i, player := range table.Players { + if player == nil { + continue + } + if !player.Client.IsOnline() { + // 踢了 + table.Players[i] = nil + // 结算玩家金额 + store.NetAccounts.Get(player.Id).SettlePlayerChip() + // 被踢玩家消息 + // player.Client.Write(&api.ResKickOutTable{}) + + // 该离线玩家是房主, 房主给到下个位置玩家 + if table.MasterId == player.Id { + nextMasterPos := table.NextPlayerPos(i) + if nextMasterPos == i { + // 没有玩家了, 解散牌桌 + notice = false + table.Stage = 9 + game.LobbyTables.Delete(player.GameTable.TableNo) + return + } + table.MasterId = table.Players[nextMasterPos].Id + } + } + } + // 通知牌桌所有玩家 + if notice { + table.NoticeGameFullStatus() + } +} diff --git a/internal/game/store.go b/internal/game/store.go new file mode 100644 index 0000000..d9a40d4 --- /dev/null +++ b/internal/game/store.go @@ -0,0 +1,22 @@ +package game + +import ( + "strconv" + "sync/atomic" + "texas-poker-bk/tool/cache" +) + +// LobbyTables 存储当前进行中的牌桌 +var ( + TableNo = &atomic.Int32{} // 牌桌编号计数器 + LobbyTables *cache.KVCache[int32, *Table] +) + +func init() { + TableNo = &atomic.Int32{} // 牌桌编号计数器 + + var tableZeroValue *Table = nil + LobbyTables = cache.NewKVCache(tableZeroValue, func(k int32) string { + return strconv.Itoa(int(k)) + }) +} diff --git a/internal/game/table.go b/internal/game/table.go index fb6dc8c..4b7dbc2 100644 --- a/internal/game/table.go +++ b/internal/game/table.go @@ -135,14 +135,13 @@ func (t *Table) PlayerCount() int32 { func (t *Table) NextPlayerPos(current int) int { // 当前位置往后 for i := current + 1; i < len(t.Players); i++ { - if t.Players[i] == nil { - continue + if t.Players[i] != nil { + return i } - return i } // 从头找 - for i, p := range t.Players { - if p != nil { + for i := 0; i < current && i < len(t.Players); i++ { + if t.Players[i] != nil { return i } } @@ -438,14 +437,14 @@ func (t *Table) SetNextPlayer(current int) { } // RoundOver 当前回合结束 -func (t *Table) RoundOver() error { +func (t *Table) RoundOver() (finished bool, err error) { // TODO 记录 t.RoundBetLogs[] // 游戏结束,开牌结算 if t.Stage == 5 || 1 == len(collect.Filter(t.Players, func(i int, p *Player) bool { return p != nil && p.Status != 7 })) { - return t.cardFightAndSettle() + return true, t.cardFightAndSettle() } // 开启下一回合, 根据回合发公共牌 @@ -480,7 +479,7 @@ func (t *Table) RoundOver() error { t.PlayerBetting.SetNextPlayer(true, t, nil) // t.SetNextPlayerWithRoundStart() - return nil + return false, nil } // cardFightAndSettle 斗牌并结算 @@ -511,9 +510,9 @@ func (t *Table) cardFightAndSettle() error { if winners == nil { winners = []*Player{p} } else { - if p.Hand.point > winners[0].Hand.point { + if p.Hand.GetPoint() > winners[0].Hand.GetPoint() { winners = []*Player{p} - } else if p.Hand.point == winners[0].Hand.point { + } else if p.Hand.GetPoint() == winners[0].Hand.GetPoint() { // 手牌相同 winners = append(winners, p) } diff --git a/internal/service/auth.go b/internal/logic/auth.go similarity index 98% rename from internal/service/auth.go rename to internal/logic/auth.go index 1e456a7..2fc46c3 100644 --- a/internal/service/auth.go +++ b/internal/logic/auth.go @@ -1,4 +1,4 @@ -package service +package logic import ( "encoding/base64" @@ -15,9 +15,9 @@ import ( "texas-poker-bk/api" "texas-poker-bk/internal/conf" "texas-poker-bk/internal/dao" + "texas-poker-bk/internal/logic/event" + "texas-poker-bk/internal/logic/store" "texas-poker-bk/internal/model/entity" - "texas-poker-bk/internal/service/event" - "texas-poker-bk/internal/service/store" "texas-poker-bk/internal/session" "texas-poker-bk/tool/collect" "texas-poker-bk/tool/security" diff --git a/internal/service/event/auto_betting.go b/internal/logic/delayer/auto_betting.go similarity index 94% rename from internal/service/event/auto_betting.go rename to internal/logic/delayer/auto_betting.go index 8215fe0..d9a35ff 100644 --- a/internal/service/event/auto_betting.go +++ b/internal/logic/delayer/auto_betting.go @@ -1,11 +1,11 @@ -package event +package delayer import ( "fmt" "github.com/golang/protobuf/proto" "texas-poker-bk/api" "texas-poker-bk/internal/game" - "texas-poker-bk/internal/service/store" + "texas-poker-bk/internal/logic/store" "texas-poker-bk/tool/async" "time" ) diff --git a/internal/logic/delayer/offline_clean.go b/internal/logic/delayer/offline_clean.go new file mode 100644 index 0000000..a99b0ce --- /dev/null +++ b/internal/logic/delayer/offline_clean.go @@ -0,0 +1,25 @@ +package delayer + +import ( + "texas-poker-bk/internal/logic/store" + "texas-poker-bk/tool/async" + "time" +) + +// 清理离线用户 + +var ( + OfflineCleanDelayer *async.DelayQueue[int64] +) + +func init() { + OfflineCleanDelayer = async.NewDelayQueue(time.Second, 128, removeMemoryAccount) +} + +// func removeMemoryAccount(account *session.NetAccount) { +func removeMemoryAccount(accountId int64, now time.Time) { + _ = store.NetAccounts.Get(accountId) + store.NetAccounts.Delete(accountId) + store.TokenVersions.Delete(accountId) + // TODO 持久化账户金额 +} diff --git a/internal/service/event/event_type.go b/internal/logic/event/event_type.go similarity index 100% rename from internal/service/event/event_type.go rename to internal/logic/event/event_type.go diff --git a/internal/service/event/offline.go b/internal/logic/event/offline.go similarity index 63% rename from internal/service/event/offline.go rename to internal/logic/event/offline.go index 662842e..dadfb9a 100644 --- a/internal/service/event/offline.go +++ b/internal/logic/event/offline.go @@ -2,8 +2,8 @@ package event import ( "fmt" - "texas-poker-bk/internal/service/store" - "texas-poker-bk/tool/async" + "texas-poker-bk/internal/logic/delayer" + "texas-poker-bk/internal/logic/store" "texas-poker-bk/tool/collect" "texas-poker-bk/tool/watcher" "time" @@ -12,15 +12,11 @@ import ( var ( // OfflineWatcher 离线动作 OfflineWatcher *watcher.Watcher[int64, bool] - - offlineCleanDelayer *async.DelayQueue[int64] ) func init() { OfflineWatcher = watcher.NewWatcher(128, handleOffline) go OfflineWatcher.Run() - - offlineCleanDelayer = async.NewDelayQueue(time.Second, 128, removeMemoryAccount) } func handleOffline(e *watcher.Event[int64, bool]) { @@ -34,14 +30,14 @@ func handleOffline(e *watcher.Event[int64, bool]) { } if account.Player == nil { // 不在游戏中,n秒后移除 - account.OfflineCleanCanceler = offlineCleanDelayer.Delay(10*time.Second, account.Id) + account.OfflineCleanCanceler = delayer.OfflineCleanDelayer.Delay(10*time.Second, account.Id) return } if collect.In(account.Player.GameTable.Stage, 1, 9) { // 牌局未在进行中直接移除玩家并下线 account.Player.GameTable.RemovePlayer(account.Id) account.SettlePlayerChip() - account.OfflineCleanCanceler = offlineCleanDelayer.Delay(10*time.Second, account.Id) + account.OfflineCleanCanceler = delayer.OfflineCleanDelayer.Delay(10*time.Second, account.Id) return } // 判断当前是玩家回合(60s自动过牌/弃牌) @@ -50,11 +46,3 @@ func handleOffline(e *watcher.Event[int64, bool]) { } // 待玩家回合时还是offline(自动过牌/弃牌) } - -// func removeMemoryAccount(account *session.NetAccount) { -func removeMemoryAccount(accountId int64, now time.Time) { - _ = store.NetAccounts.Get(accountId) - store.NetAccounts.Delete(accountId) - store.TokenVersions.Delete(accountId) - // TODO 持久化账户金额 -} diff --git a/internal/service/event/online.go b/internal/logic/event/online.go similarity index 94% rename from internal/service/event/online.go rename to internal/logic/event/online.go index 7a9bbd4..49d8693 100644 --- a/internal/service/event/online.go +++ b/internal/logic/event/online.go @@ -1,7 +1,7 @@ package event import ( - "texas-poker-bk/internal/service/store" + "texas-poker-bk/internal/logic/store" "texas-poker-bk/tool/watcher" ) diff --git a/internal/service/service.go b/internal/logic/service.go similarity index 98% rename from internal/service/service.go rename to internal/logic/service.go index 27ebc14..a746ac8 100644 --- a/internal/service/service.go +++ b/internal/logic/service.go @@ -1,4 +1,4 @@ -package service +package logic import ( "bytes" diff --git a/internal/logic/store/store.go b/internal/logic/store/store.go new file mode 100644 index 0000000..dbe72e5 --- /dev/null +++ b/internal/logic/store/store.go @@ -0,0 +1,38 @@ +package store + +import ( + "strconv" + "texas-poker-bk/internal/session" + "texas-poker-bk/tool/cache" +) + +var ( + //TableNo *atomic.Int32 + + // LobbyTables 存储当前进行中的牌桌 + //LobbyTables *cache.KVCache[int32, *game.Table] + + // NetAccounts 存储一下在线用户, TODO 连接终端,未在牌局或牌局未开始中回收账号,机器人代打后回收账号 + NetAccounts *cache.KVCache[int64, *session.NetAccount] + + // TokenVersions 存储token版本号,登录时+1,一个账户同一时间只允许一个token有效 + TokenVersions *cache.KVCache[int64, int32] +) + +func init() { + //TableNo = &atomic.Int32{} // 牌桌编号计数器 + + //var tableZeroValue *game.Table = nil + //LobbyTables = cache.NewKVCache(tableZeroValue, func(k int32) string { + // return strconv.Itoa(int(k)) + //}) + + var accountZeroValue *session.NetAccount = nil + NetAccounts = cache.NewKVCache(accountZeroValue, func(k int64) string { + return strconv.FormatInt(k, 10) + }) + + TokenVersions = cache.NewKVCache(int32(-1), func(k int64) string { + return strconv.FormatInt(k, 10) + }) +} diff --git a/internal/service/table.go b/internal/logic/table.go similarity index 95% rename from internal/service/table.go rename to internal/logic/table.go index 57815cb..304c068 100644 --- a/internal/service/table.go +++ b/internal/logic/table.go @@ -1,4 +1,4 @@ -package service +package logic import ( "fmt" @@ -7,15 +7,18 @@ import ( "sort" "texas-poker-bk/api" "texas-poker-bk/internal/game" - "texas-poker-bk/internal/service/event" - "texas-poker-bk/internal/service/store" + "texas-poker-bk/internal/game/delayer" + "texas-poker-bk/internal/game/event" + delayer2 "texas-poker-bk/internal/logic/delayer" + "texas-poker-bk/internal/logic/store" "texas-poker-bk/internal/session" "texas-poker-bk/tool/collect" + "time" ) func init() { // TODO 循环依赖 ioc 参考 - event.HandleReqBetting = HandleReqBetting + delayer2.HandleReqBetting = HandleReqBetting } // HandleReqCreateTable 创建桌面 @@ -40,7 +43,7 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable) } // 初始化一个牌桌 table := &game.Table{ - TableNo: store.TableNo.Add(1), + TableNo: game.TableNo.Add(1), MasterId: account.Id, PlayerNum: playerNum + 1, @@ -51,7 +54,7 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable) SmallBlindChip: msg.BigBlind / 2, LimitInAmount: msg.BigBlind * 100, TexasType: msg.TexasType, - RefAutoBettingDelayQueue: event.AutoBettingDelayQueue, + RefAutoBettingDelayQueue: delayer2.AutoBettingDelayQueue, } // 游戏类型 对应 下注处理流程 switch msg.TexasType { @@ -87,7 +90,7 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable) for i := 0; i < int(robotNum); i++ { table.Robots[i] = &game.Robot{} } - store.LobbyTables.SetDefault(table.TableNo, table) + game.LobbyTables.SetDefault(table.TableNo, table) //err := store.SaveNewTable(table) //if err != nil { // return &api.ResFail{Msg: err.Error()}, nil @@ -98,10 +101,10 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable) // HandleReqLobbyView 返回当前所有桌面和玩家数量 func HandleReqLobbyView(account *session.NetAccount, _ *api.ReqLobbyView) (proto.Message, error) { res := &api.ResLobbyView{} - if store.LobbyTables.Count() == 0 { + if game.LobbyTables.Count() == 0 { return res, nil } - tables := make([]*api.LobbyTable, store.LobbyTables.Count()) + tables := make([]*api.LobbyTable, game.LobbyTables.Count()) if account.Player != nil { res.CurTableNo = account.Player.GameTable.TableNo } @@ -109,7 +112,7 @@ func HandleReqLobbyView(account *session.NetAccount, _ *api.ReqLobbyView) (proto // 遍历 store tables 转换为视图层结构体 idx := 0 - store.LobbyTables.ForEach(func(k string, t *game.Table) { + game.LobbyTables.ForEach(func(k string, t *game.Table) { table := &api.LobbyTable{TableNo: t.TableNo, PlayerNum: t.PlayerNum, RobotNum: t.RobotNum} table.Players = make([]*api.LobbyPlayer, t.PlayerNum+t.RobotNum) @@ -150,7 +153,7 @@ func HandleReqJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (pro if account.Player != nil { return &api.ResFail{Msg: fmt.Sprintf("当前已加入#%d牌桌", account.Player.GameTable.TableNo)}, nil } - table := store.LobbyTables.Get(msg.TableNo) + table := game.LobbyTables.Get(msg.TableNo) if table == nil { return &api.ResFail{Msg: "牌桌不存在"}, nil } @@ -314,19 +317,19 @@ func HandleReqCancelReady(player *game.Player, _ *api.ReqCancelReady) (proto.Mes func HandleReqDismissGameTable(player *game.Player, _ *api.ReqDismissGameTable) (proto.Message, error) { player.GameTable.Lock.Lock() defer player.GameTable.Lock.Unlock() - if !collect.In(player.GameTable.Stage, 1, 7) { + if collect.NotIn(player.GameTable.Stage, 1, 7) { return &api.ResFail{Msg: fmt.Sprintf("#%d,牌局进行中", player.GameTable.Stage)}, nil } player.GameTable.Stage = 9 - store.LobbyTables.Delete(player.GameTable.TableNo) + game.LobbyTables.Delete(player.GameTable.TableNo) // 通知所有玩家,解除账号绑定,结算玩家金额 for i, p := range player.GameTable.Players { if p == nil { continue } account := store.NetAccounts.Get(p.Id) - account.IncrementBalance(p.Chip) - account.Player = nil + account.SettlePlayerChip() + player.GameTable.Players[i] = nil if p.Id != player.Id { p.Client.Write(&api.ResDismissGameTable{}) @@ -463,10 +466,16 @@ func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message, // 判断回合是否结束 if table.PlayerBetting.IsRoundOver(player, table.LastPosBetOp) { // 开启下一轮 - err := table.RoundOver() + finished, err := table.RoundOver() if err != nil { return &api.ResFail{Code: 500, Msg: err.Error()}, nil } + if finished { + delayer.GameDelayer.Delay(time.Second*5, func() { + // 该局牌结束事件 + event.GameRoundEndWatcher.Publish(table.TableNo, true) + }) + } return res, nil } diff --git a/internal/server/route.go b/internal/server/route.go index 980758d..bca2e92 100644 --- a/internal/server/route.go +++ b/internal/server/route.go @@ -5,13 +5,13 @@ import ( "net/http" "texas-poker-bk/api" "texas-poker-bk/internal/dao" - "texas-poker-bk/internal/service" + "texas-poker-bk/internal/logic" ) func NewServer() *gin.Engine { server := gin.Default() // token认证过滤器 - server.Use(service.SubjectAuthFilter) + server.Use(logic.SubjectAuthFilter) // session storage server.Use(SessionStore("golang-tech-stack")) @@ -27,13 +27,13 @@ func NewServer() *gin.Engine { conn.GET("/route_ws", RouteWs) auth := base.Group("/auth") - auth.GET("/captcha", service.Captcha) // 验证码 - auth.POST("/authorize", service.Authorize) // 登录或注册认证 + auth.GET("/captcha", logic.Captcha) // 验证码 + auth.POST("/authorize", logic.Authorize) // 登录或注册认证 user := base.Group("/user") user.GET("/findByName", dao.FindUserByName) gm := base.Group("/gm") - gm.GET("/avatar/:avatar", service.Avatar) + gm.GET("/avatar/:avatar", logic.Avatar) return server } diff --git a/internal/server/ws.go b/internal/server/ws.go index f310926..bf2cd27 100644 --- a/internal/server/ws.go +++ b/internal/server/ws.go @@ -9,7 +9,7 @@ import ( "net/http" "texas-poker-bk/api" "texas-poker-bk/internal/conf" - "texas-poker-bk/internal/service/event" + "texas-poker-bk/internal/logic/event" "texas-poker-bk/internal/session" "texas-poker-bk/tool/ip" "time" diff --git a/internal/server/wsroute.go b/internal/server/wsroute.go index fe81400..30c540b 100644 --- a/internal/server/wsroute.go +++ b/internal/server/wsroute.go @@ -5,7 +5,7 @@ import ( "reflect" "texas-poker-bk/api" "texas-poker-bk/internal/game" - "texas-poker-bk/internal/service" + "texas-poker-bk/internal/logic" "texas-poker-bk/internal/session" ) @@ -19,30 +19,30 @@ func init() { return &api.Pong{PingMs: ping.Ms}, nil }) // 连接token认证 - HandleNetClientMsg(&api.ReqIdentity{}, service.HandleReqIdentity) + HandleNetClientMsg(&api.ReqIdentity{}, logic.HandleReqIdentity) // 创建桌面 - HandleNetAccountMsg(&api.ReqCreateTable{}, service.HandleReqCreateTable) + HandleNetAccountMsg(&api.ReqCreateTable{}, logic.HandleReqCreateTable) // 查询所有游戏桌面 - HandleNetAccountMsg(&api.ReqLobbyView{}, service.HandleReqLobbyView) + HandleNetAccountMsg(&api.ReqLobbyView{}, logic.HandleReqLobbyView) // 获取牌桌当前所有状态 - HandleNetPlayerMsg(&api.ReqGameFullStatus{}, service.HandleReqGameFullStatus) + HandleNetPlayerMsg(&api.ReqGameFullStatus{}, logic.HandleReqGameFullStatus) // 加入桌面 - HandleNetAccountMsg(&api.ReqJoinTable{}, service.HandleReqJoinTable) + HandleNetAccountMsg(&api.ReqJoinTable{}, logic.HandleReqJoinTable) // 踢人 - HandleNetPlayerMsg(&api.ReqKickOutTable{}, service.HandleReqKickOutTable) + HandleNetPlayerMsg(&api.ReqKickOutTable{}, logic.HandleReqKickOutTable) // 离开房间 - HandleNetPlayerMsg(&api.ReqLeaveTable{}, service.HandleReqLeaveTable) + HandleNetPlayerMsg(&api.ReqLeaveTable{}, logic.HandleReqLeaveTable) // 解散房间 - HandleNetPlayerMsg(&api.ReqDismissGameTable{}, service.HandleReqDismissGameTable) + HandleNetPlayerMsg(&api.ReqDismissGameTable{}, logic.HandleReqDismissGameTable) // 玩家准备 - HandleNetPlayerMsg(&api.ReqReadyStart{}, service.HandleReqReadyStart) + HandleNetPlayerMsg(&api.ReqReadyStart{}, logic.HandleReqReadyStart) // 玩家取消准备 - HandleNetPlayerMsg(&api.ReqCancelReady{}, service.HandleReqCancelReady) + HandleNetPlayerMsg(&api.ReqCancelReady{}, logic.HandleReqCancelReady) // 开始游戏 - HandleNetPlayerMsg(&api.ReqGameStart{}, service.HandleReqGameStart) + HandleNetPlayerMsg(&api.ReqGameStart{}, logic.HandleReqGameStart) // 筹码下注 - HandleNetPlayerMsg(&api.ReqBetting{}, service.HandleReqBetting) + HandleNetPlayerMsg(&api.ReqBetting{}, logic.HandleReqBetting) } func checkExistsTypeHandler(op int32, err error) { diff --git a/internal/service/store/store.go b/internal/service/store/store.go deleted file mode 100644 index b0e9e64..0000000 --- a/internal/service/store/store.go +++ /dev/null @@ -1,94 +0,0 @@ -package store - -import ( - "github.com/patrickmn/go-cache" - "strconv" - "sync/atomic" - "texas-poker-bk/internal/game" - "texas-poker-bk/internal/session" - "time" -) - -var ( - TableNo *atomic.Int32 - - // LobbyTables 存储当前进行中的牌桌 - LobbyTables *Store[int32, *game.Table] - - // NetAccounts 存储一下在线用户, TODO 连接终端,未在牌局或牌局未开始中回收账号,机器人代打后回收账号 - NetAccounts *Store[int64, *session.NetAccount] - - // TokenVersions 存储token版本号,登录时+1,一个账户同一时间只允许一个token有效 - TokenVersions *Store[int64, int32] -) - -const ( - NoExpiration time.Duration = cache.NoExpiration - DefaultExpiration time.Duration = cache.DefaultExpiration -) - -func init() { - TableNo = &atomic.Int32{} // 牌桌编号计数器 - - var tableZeroValue *game.Table = nil - LobbyTables = NewStore(tableZeroValue, func(k int32) string { - return strconv.Itoa(int(k)) - }) - - var accountZeroValue *session.NetAccount = nil - NetAccounts = NewStore(accountZeroValue, func(k int64) string { - return strconv.FormatInt(k, 10) - }) - - TokenVersions = NewStore(int32(-1), func(k int64) string { - return strconv.FormatInt(k, 10) - }) -} - -type Store[K any, V any] struct { - c *cache.Cache - zeroValue V // 默认值 - k2str func(K) string -} - -func NewStore[K any, V any](zeroValue V, k2str func(K) string) *Store[K, V] { - return NewExpireStore(cache.NoExpiration, cache.NoExpiration, zeroValue, k2str) -} - -func NewExpireStore[K any, V any](defaultExpiration, cleanupInterval time.Duration, zeroValue V, k2str func(K) string) *Store[K, V] { - return &Store[K, V]{ - c: cache.New(defaultExpiration, cleanupInterval), - zeroValue: zeroValue, - k2str: k2str, - } -} - -func (s *Store[K, V]) SetDefault(k K, v V) { - s.c.SetDefault(s.k2str(k), v) -} - -func (s *Store[K, V]) Set(k K, v V, d time.Duration) { - s.c.Set(s.k2str(k), v, d) -} - -func (s *Store[K, V]) Get(k K) (zero V) { - v, found := s.c.Get(s.k2str(k)) - if !found { - return s.zeroValue - } - return v.(V) -} - -func (s *Store[K, V]) Delete(k K) { - s.c.Delete(s.k2str(k)) -} - -func (s *Store[K, V]) ForEach(f func(k string, v V)) { - for k, v := range s.c.Items() { - f(k, v.Object.(V)) - } -} - -func (s *Store[K, V]) Count() int { - return s.c.ItemCount() -} diff --git a/tool/cache/kvcache.go b/tool/cache/kvcache.go new file mode 100644 index 0000000..4f40aaa --- /dev/null +++ b/tool/cache/kvcache.go @@ -0,0 +1,59 @@ +package cache + +import ( + "github.com/patrickmn/go-cache" + "time" +) + +const ( + NoExpiration time.Duration = cache.NoExpiration + DefaultExpiration time.Duration = cache.DefaultExpiration +) + +type KVCache[K any, V any] struct { + c *cache.Cache + zeroValue V // 默认值 + k2str func(K) string +} + +func NewKVCache[K any, V any](zeroValue V, k2str func(K) string) *KVCache[K, V] { + return NewExpireStore(cache.NoExpiration, cache.NoExpiration, zeroValue, k2str) +} + +func NewExpireStore[K any, V any](defaultExpiration, cleanupInterval time.Duration, zeroValue V, k2str func(K) string) *KVCache[K, V] { + return &KVCache[K, V]{ + c: cache.New(defaultExpiration, cleanupInterval), + zeroValue: zeroValue, + k2str: k2str, + } +} + +func (s *KVCache[K, V]) SetDefault(k K, v V) { + s.c.SetDefault(s.k2str(k), v) +} + +func (s *KVCache[K, V]) Set(k K, v V, d time.Duration) { + s.c.Set(s.k2str(k), v, d) +} + +func (s *KVCache[K, V]) Get(k K) (zero V) { + v, found := s.c.Get(s.k2str(k)) + if !found { + return s.zeroValue + } + return v.(V) +} + +func (s *KVCache[K, V]) Delete(k K) { + s.c.Delete(s.k2str(k)) +} + +func (s *KVCache[K, V]) ForEach(f func(k string, v V)) { + for k, v := range s.c.Items() { + f(k, v.Object.(V)) + } +} + +func (s *KVCache[K, V]) Count() int { + return s.c.ItemCount() +} diff --git a/tool/collect/collect.go b/tool/collect/collect.go index b56055e..0c33d7f 100644 --- a/tool/collect/collect.go +++ b/tool/collect/collect.go @@ -12,6 +12,10 @@ func In[T comparable](value T, values ...T) bool { return false } +func NotIn[T comparable](value T, values ...T) bool { + return !In(value, values...) +} + func Count[T any](slice []T, isCount func(int, T) bool) int { count := 0 if slice == nil {