Browse Source

牌局结束,清理离线玩家

master
tangmingyou 3 years ago
parent
commit
12323c35b2
  1. 2
      internal/game/actions.go
  2. 0
      internal/game/dealer.go
  3. 30
      internal/game/delayer/delayer.go
  4. 62
      internal/game/event/game_round_end.go
  5. 22
      internal/game/store.go
  6. 19
      internal/game/table.go
  7. 6
      internal/logic/auth.go
  8. 4
      internal/logic/delayer/auto_betting.go
  9. 25
      internal/logic/delayer/offline_clean.go
  10. 0
      internal/logic/event/event_type.go
  11. 20
      internal/logic/event/offline.go
  12. 2
      internal/logic/event/online.go
  13. 2
      internal/logic/service.go
  14. 38
      internal/logic/store/store.go
  15. 41
      internal/logic/table.go
  16. 10
      internal/server/route.go
  17. 2
      internal/server/ws.go
  18. 26
      internal/server/wsroute.go
  19. 94
      internal/service/store/store.go
  20. 59
      tool/cache/kvcache.go
  21. 4
      tool/collect/collect.go

2
internal/game/actions.go

@ -124,7 +124,7 @@ func Fold4Limited(player *Player, betChip int32) proto.Message {
player.SetStatus(7) player.SetStatus(7)
betNotice.Line2 = "弃牌" betNotice.Line2 = "弃牌"
// 剩余玩家数为1则结束, 在 service 中判断 // 剩余玩家数为1则结束, 在 logic 中判断
//leftPlayers := collect.Filter(player.GameTable.Players, func(i int, p *Player) bool { //leftPlayers := collect.Filter(player.GameTable.Players, func(i int, p *Player) bool {
// return p != nil && p.Status != 7 // return p != nil && p.Status != 7
//}) //})

0
internal/game/game.go → internal/game/dealer.go

30
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()
}

62
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()
}
}

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

19
internal/game/table.go

@ -135,14 +135,13 @@ func (t *Table) PlayerCount() int32 {
func (t *Table) NextPlayerPos(current int) int { func (t *Table) NextPlayerPos(current int) int {
// 当前位置往后 // 当前位置往后
for i := current + 1; i < len(t.Players); i++ { for i := current + 1; i < len(t.Players); i++ {
if t.Players[i] == nil { if t.Players[i] != nil {
continue return i
} }
return i
} }
// 从头找 // 从头找
for i, p := range t.Players { for i := 0; i < current && i < len(t.Players); i++ {
if p != nil { if t.Players[i] != nil {
return i return i
} }
} }
@ -438,14 +437,14 @@ func (t *Table) SetNextPlayer(current int) {
} }
// RoundOver 当前回合结束 // RoundOver 当前回合结束
func (t *Table) RoundOver() error { func (t *Table) RoundOver() (finished bool, err error) {
// TODO 记录 t.RoundBetLogs[] // TODO 记录 t.RoundBetLogs[]
// 游戏结束,开牌结算 // 游戏结束,开牌结算
if t.Stage == 5 || 1 == len(collect.Filter(t.Players, func(i int, p *Player) bool { if t.Stage == 5 || 1 == len(collect.Filter(t.Players, func(i int, p *Player) bool {
return p != nil && p.Status != 7 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.PlayerBetting.SetNextPlayer(true, t, nil)
// t.SetNextPlayerWithRoundStart() // t.SetNextPlayerWithRoundStart()
return nil return false, nil
} }
// cardFightAndSettle 斗牌并结算 // cardFightAndSettle 斗牌并结算
@ -511,9 +510,9 @@ func (t *Table) cardFightAndSettle() error {
if winners == nil { if winners == nil {
winners = []*Player{p} winners = []*Player{p}
} else { } else {
if p.Hand.point > winners[0].Hand.point { if p.Hand.GetPoint() > winners[0].Hand.GetPoint() {
winners = []*Player{p} 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) winners = append(winners, p)
} }

6
internal/service/auth.go → internal/logic/auth.go

@ -1,4 +1,4 @@
package service package logic
import ( import (
"encoding/base64" "encoding/base64"
@ -15,9 +15,9 @@ import (
"texas-poker-bk/api" "texas-poker-bk/api"
"texas-poker-bk/internal/conf" "texas-poker-bk/internal/conf"
"texas-poker-bk/internal/dao" "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/model/entity"
"texas-poker-bk/internal/service/event"
"texas-poker-bk/internal/service/store"
"texas-poker-bk/internal/session" "texas-poker-bk/internal/session"
"texas-poker-bk/tool/collect" "texas-poker-bk/tool/collect"
"texas-poker-bk/tool/security" "texas-poker-bk/tool/security"

4
internal/service/event/auto_betting.go → internal/logic/delayer/auto_betting.go

@ -1,11 +1,11 @@
package event package delayer
import ( import (
"fmt" "fmt"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"texas-poker-bk/api" "texas-poker-bk/api"
"texas-poker-bk/internal/game" "texas-poker-bk/internal/game"
"texas-poker-bk/internal/service/store" "texas-poker-bk/internal/logic/store"
"texas-poker-bk/tool/async" "texas-poker-bk/tool/async"
"time" "time"
) )

25
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 持久化账户金额
}

0
internal/service/event/event_type.go → internal/logic/event/event_type.go

20
internal/service/event/offline.go → internal/logic/event/offline.go

@ -2,8 +2,8 @@ package event
import ( import (
"fmt" "fmt"
"texas-poker-bk/internal/service/store" "texas-poker-bk/internal/logic/delayer"
"texas-poker-bk/tool/async" "texas-poker-bk/internal/logic/store"
"texas-poker-bk/tool/collect" "texas-poker-bk/tool/collect"
"texas-poker-bk/tool/watcher" "texas-poker-bk/tool/watcher"
"time" "time"
@ -12,15 +12,11 @@ import (
var ( var (
// OfflineWatcher 离线动作 // OfflineWatcher 离线动作
OfflineWatcher *watcher.Watcher[int64, bool] OfflineWatcher *watcher.Watcher[int64, bool]
offlineCleanDelayer *async.DelayQueue[int64]
) )
func init() { func init() {
OfflineWatcher = watcher.NewWatcher(128, handleOffline) OfflineWatcher = watcher.NewWatcher(128, handleOffline)
go OfflineWatcher.Run() go OfflineWatcher.Run()
offlineCleanDelayer = async.NewDelayQueue(time.Second, 128, removeMemoryAccount)
} }
func handleOffline(e *watcher.Event[int64, bool]) { func handleOffline(e *watcher.Event[int64, bool]) {
@ -34,14 +30,14 @@ func handleOffline(e *watcher.Event[int64, bool]) {
} }
if account.Player == nil { if account.Player == nil {
// 不在游戏中,n秒后移除 // 不在游戏中,n秒后移除
account.OfflineCleanCanceler = offlineCleanDelayer.Delay(10*time.Second, account.Id) account.OfflineCleanCanceler = delayer.OfflineCleanDelayer.Delay(10*time.Second, account.Id)
return return
} }
if collect.In(account.Player.GameTable.Stage, 1, 9) { if collect.In(account.Player.GameTable.Stage, 1, 9) {
// 牌局未在进行中直接移除玩家并下线 // 牌局未在进行中直接移除玩家并下线
account.Player.GameTable.RemovePlayer(account.Id) account.Player.GameTable.RemovePlayer(account.Id)
account.SettlePlayerChip() account.SettlePlayerChip()
account.OfflineCleanCanceler = offlineCleanDelayer.Delay(10*time.Second, account.Id) account.OfflineCleanCanceler = delayer.OfflineCleanDelayer.Delay(10*time.Second, account.Id)
return return
} }
// 判断当前是玩家回合(60s自动过牌/弃牌) // 判断当前是玩家回合(60s自动过牌/弃牌)
@ -50,11 +46,3 @@ func handleOffline(e *watcher.Event[int64, bool]) {
} }
// 待玩家回合时还是offline(自动过牌/弃牌) // 待玩家回合时还是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 持久化账户金额
}

2
internal/service/event/online.go → internal/logic/event/online.go

@ -1,7 +1,7 @@
package event package event
import ( import (
"texas-poker-bk/internal/service/store" "texas-poker-bk/internal/logic/store"
"texas-poker-bk/tool/watcher" "texas-poker-bk/tool/watcher"
) )

2
internal/service/service.go → internal/logic/service.go

@ -1,4 +1,4 @@
package service package logic
import ( import (
"bytes" "bytes"

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

41
internal/service/table.go → internal/logic/table.go

@ -1,4 +1,4 @@
package service package logic
import ( import (
"fmt" "fmt"
@ -7,15 +7,18 @@ import (
"sort" "sort"
"texas-poker-bk/api" "texas-poker-bk/api"
"texas-poker-bk/internal/game" "texas-poker-bk/internal/game"
"texas-poker-bk/internal/service/event" "texas-poker-bk/internal/game/delayer"
"texas-poker-bk/internal/service/store" "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/internal/session"
"texas-poker-bk/tool/collect" "texas-poker-bk/tool/collect"
"time"
) )
func init() { func init() {
// TODO 循环依赖 ioc 参考 // TODO 循环依赖 ioc 参考
event.HandleReqBetting = HandleReqBetting delayer2.HandleReqBetting = HandleReqBetting
} }
// HandleReqCreateTable 创建桌面 // HandleReqCreateTable 创建桌面
@ -40,7 +43,7 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable)
} }
// 初始化一个牌桌 // 初始化一个牌桌
table := &game.Table{ table := &game.Table{
TableNo: store.TableNo.Add(1), TableNo: game.TableNo.Add(1),
MasterId: account.Id, MasterId: account.Id,
PlayerNum: playerNum + 1, PlayerNum: playerNum + 1,
@ -51,7 +54,7 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable)
SmallBlindChip: msg.BigBlind / 2, SmallBlindChip: msg.BigBlind / 2,
LimitInAmount: msg.BigBlind * 100, LimitInAmount: msg.BigBlind * 100,
TexasType: msg.TexasType, TexasType: msg.TexasType,
RefAutoBettingDelayQueue: event.AutoBettingDelayQueue, RefAutoBettingDelayQueue: delayer2.AutoBettingDelayQueue,
} }
// 游戏类型 对应 下注处理流程 // 游戏类型 对应 下注处理流程
switch msg.TexasType { switch msg.TexasType {
@ -87,7 +90,7 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable)
for i := 0; i < int(robotNum); i++ { for i := 0; i < int(robotNum); i++ {
table.Robots[i] = &game.Robot{} table.Robots[i] = &game.Robot{}
} }
store.LobbyTables.SetDefault(table.TableNo, table) game.LobbyTables.SetDefault(table.TableNo, table)
//err := store.SaveNewTable(table) //err := store.SaveNewTable(table)
//if err != nil { //if err != nil {
// return &api.ResFail{Msg: err.Error()}, nil // return &api.ResFail{Msg: err.Error()}, nil
@ -98,10 +101,10 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable)
// HandleReqLobbyView 返回当前所有桌面和玩家数量 // HandleReqLobbyView 返回当前所有桌面和玩家数量
func HandleReqLobbyView(account *session.NetAccount, _ *api.ReqLobbyView) (proto.Message, error) { func HandleReqLobbyView(account *session.NetAccount, _ *api.ReqLobbyView) (proto.Message, error) {
res := &api.ResLobbyView{} res := &api.ResLobbyView{}
if store.LobbyTables.Count() == 0 { if game.LobbyTables.Count() == 0 {
return res, nil return res, nil
} }
tables := make([]*api.LobbyTable, store.LobbyTables.Count()) tables := make([]*api.LobbyTable, game.LobbyTables.Count())
if account.Player != nil { if account.Player != nil {
res.CurTableNo = account.Player.GameTable.TableNo res.CurTableNo = account.Player.GameTable.TableNo
} }
@ -109,7 +112,7 @@ func HandleReqLobbyView(account *session.NetAccount, _ *api.ReqLobbyView) (proto
// 遍历 store tables 转换为视图层结构体 // 遍历 store tables 转换为视图层结构体
idx := 0 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 := &api.LobbyTable{TableNo: t.TableNo, PlayerNum: t.PlayerNum, RobotNum: t.RobotNum}
table.Players = make([]*api.LobbyPlayer, t.PlayerNum+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 { if account.Player != nil {
return &api.ResFail{Msg: fmt.Sprintf("当前已加入#%d牌桌", account.Player.GameTable.TableNo)}, 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 { if table == nil {
return &api.ResFail{Msg: "牌桌不存在"}, 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) { func HandleReqDismissGameTable(player *game.Player, _ *api.ReqDismissGameTable) (proto.Message, error) {
player.GameTable.Lock.Lock() player.GameTable.Lock.Lock()
defer player.GameTable.Lock.Unlock() 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 return &api.ResFail{Msg: fmt.Sprintf("#%d,牌局进行中", player.GameTable.Stage)}, nil
} }
player.GameTable.Stage = 9 player.GameTable.Stage = 9
store.LobbyTables.Delete(player.GameTable.TableNo) game.LobbyTables.Delete(player.GameTable.TableNo)
// 通知所有玩家,解除账号绑定,结算玩家金额 // 通知所有玩家,解除账号绑定,结算玩家金额
for i, p := range player.GameTable.Players { for i, p := range player.GameTable.Players {
if p == nil { if p == nil {
continue continue
} }
account := store.NetAccounts.Get(p.Id) account := store.NetAccounts.Get(p.Id)
account.IncrementBalance(p.Chip) account.SettlePlayerChip()
account.Player = nil
player.GameTable.Players[i] = nil player.GameTable.Players[i] = nil
if p.Id != player.Id { if p.Id != player.Id {
p.Client.Write(&api.ResDismissGameTable{}) 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) { if table.PlayerBetting.IsRoundOver(player, table.LastPosBetOp) {
// 开启下一轮 // 开启下一轮
err := table.RoundOver() finished, err := table.RoundOver()
if err != nil { if err != nil {
return &api.ResFail{Code: 500, Msg: err.Error()}, 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 return res, nil
} }

10
internal/server/route.go

@ -5,13 +5,13 @@ import (
"net/http" "net/http"
"texas-poker-bk/api" "texas-poker-bk/api"
"texas-poker-bk/internal/dao" "texas-poker-bk/internal/dao"
"texas-poker-bk/internal/service" "texas-poker-bk/internal/logic"
) )
func NewServer() *gin.Engine { func NewServer() *gin.Engine {
server := gin.Default() server := gin.Default()
// token认证过滤器 // token认证过滤器
server.Use(service.SubjectAuthFilter) server.Use(logic.SubjectAuthFilter)
// session storage // session storage
server.Use(SessionStore("golang-tech-stack")) server.Use(SessionStore("golang-tech-stack"))
@ -27,13 +27,13 @@ func NewServer() *gin.Engine {
conn.GET("/route_ws", RouteWs) conn.GET("/route_ws", RouteWs)
auth := base.Group("/auth") auth := base.Group("/auth")
auth.GET("/captcha", service.Captcha) // 验证码 auth.GET("/captcha", logic.Captcha) // 验证码
auth.POST("/authorize", service.Authorize) // 登录或注册认证 auth.POST("/authorize", logic.Authorize) // 登录或注册认证
user := base.Group("/user") user := base.Group("/user")
user.GET("/findByName", dao.FindUserByName) user.GET("/findByName", dao.FindUserByName)
gm := base.Group("/gm") gm := base.Group("/gm")
gm.GET("/avatar/:avatar", service.Avatar) gm.GET("/avatar/:avatar", logic.Avatar)
return server return server
} }

2
internal/server/ws.go

@ -9,7 +9,7 @@ import (
"net/http" "net/http"
"texas-poker-bk/api" "texas-poker-bk/api"
"texas-poker-bk/internal/conf" "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/internal/session"
"texas-poker-bk/tool/ip" "texas-poker-bk/tool/ip"
"time" "time"

26
internal/server/wsroute.go

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"texas-poker-bk/api" "texas-poker-bk/api"
"texas-poker-bk/internal/game" "texas-poker-bk/internal/game"
"texas-poker-bk/internal/service" "texas-poker-bk/internal/logic"
"texas-poker-bk/internal/session" "texas-poker-bk/internal/session"
) )
@ -19,30 +19,30 @@ func init() {
return &api.Pong{PingMs: ping.Ms}, nil return &api.Pong{PingMs: ping.Ms}, nil
}) })
// 连接token认证 // 连接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) { func checkExistsTypeHandler(op int32, err error) {

94
internal/service/store/store.go

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

59
tool/cache/kvcache.go vendored

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

4
tool/collect/collect.go

@ -12,6 +12,10 @@ func In[T comparable](value T, values ...T) bool {
return false 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 { func Count[T any](slice []T, isCount func(int, T) bool) int {
count := 0 count := 0
if slice == nil { if slice == nil {

Loading…
Cancel
Save