You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
3.6 KiB
166 lines
3.6 KiB
package store |
|
|
|
import ( |
|
"context" |
|
"errors" |
|
"fmt" |
|
"sonet/api/gen/mahjong" |
|
"sonet/internal/mahjong/game" |
|
"sonet/internal/mahjong/helper" |
|
"sonet/pkg/protocol/deliver" |
|
"sonet/pkg/utils/collect" |
|
"sonet/pkg/utils/logger" |
|
"strconv" |
|
"sync" |
|
"sync/atomic" |
|
) |
|
|
|
type Store struct { |
|
players *sync.Map // <playerId string, *MjPlayer> |
|
tables *sync.Map // <tableId string, *MjTable> 在线麻将牌桌列表 |
|
prevTableId int32 |
|
deliver *deliver.Deliver |
|
} |
|
|
|
func NewStore(deliver *deliver.Deliver) *Store { |
|
return &Store{ |
|
players: &sync.Map{}, |
|
tables: &sync.Map{}, |
|
prevTableId: 10000, |
|
deliver: deliver, |
|
} |
|
} |
|
|
|
func (s *Store) StorePlayer(player *game.MjPlayer) { |
|
v, ok := s.players.Load(player.PlayerId) |
|
if ok { |
|
if v == player { |
|
return |
|
} else { |
|
v.(*game.MjPlayer).Close() |
|
} |
|
} |
|
s.players.Store(player.PlayerId, player) |
|
c, done := player.Chan() |
|
go func() { |
|
for { |
|
select { |
|
case <-done: |
|
return |
|
case setState := <-c: |
|
fmt.Println("player states:", setState) |
|
mjState, err := helper.SetState2MjSetState(setState) |
|
if err != nil { |
|
logger.Error(err) |
|
continue |
|
} |
|
|
|
msg := &mahjong.NoticePlayerState{PlayerId: player.PlayerId, State: mjState} |
|
var receivers []string |
|
if setState.Broadcast { // 广播 |
|
if player.MjTable != nil { |
|
receivers = player.MjTable.GetPlayerIds(setState.ExcludeReceivers...) |
|
} else if collect.NotIn(player.PlayerId, setState.ExcludeReceivers...) { |
|
receivers = []string{player.PlayerId} |
|
} |
|
} else { |
|
receivers = setState.IncludeReceivers |
|
} |
|
if len(receivers) == 0 { |
|
continue |
|
} |
|
|
|
_, err = s.deliver.DeliverBatch(context.Background(), msg, receivers) |
|
if err != nil { |
|
logger.Error("deliver batch store state error: ", err) |
|
continue |
|
} |
|
} |
|
} |
|
}() |
|
} |
|
|
|
func (s *Store) RemovePlayer(playerId string) { |
|
defer func() { s.players.Delete(playerId) }() |
|
|
|
v, ok := s.players.Load(playerId) |
|
if !ok { |
|
return |
|
} |
|
v.(*game.MjPlayer).Close() |
|
} |
|
|
|
func (s *Store) StoreTable(table *game.MjTable) { |
|
v, ok := s.tables.Load(table.TableId) |
|
if ok { |
|
if v == table { |
|
return |
|
} else { |
|
v.(*game.MjTable).Close() |
|
} |
|
} |
|
s.tables.Store(table.TableId, table) |
|
c, done := table.Chan() |
|
go func() { |
|
for { |
|
select { |
|
case <-done: |
|
return |
|
case setState := <-c: |
|
fmt.Println("table states:", setState) |
|
mjState, err := helper.SetState2MjSetState(setState) |
|
if err != nil { |
|
logger.Error(err) |
|
continue |
|
} |
|
|
|
msg := &mahjong.NoticeTableState{State: mjState} |
|
var receivers []string |
|
if setState.Broadcast { // 广播 |
|
receivers = table.GetPlayerIds(setState.ExcludeReceivers...) |
|
} else { |
|
receivers = setState.IncludeReceivers |
|
} |
|
if len(receivers) > 0 { |
|
// deliver players table state change |
|
_, _ = s.deliver.DeliverBatch(context.Background(), msg, receivers) |
|
} |
|
} |
|
} |
|
}() |
|
} |
|
|
|
func (s *Store) RemoveTable(tableId string) { |
|
defer func() { s.tables.Delete(tableId) }() |
|
|
|
v, ok := s.tables.Load(tableId) |
|
if !ok { |
|
return |
|
} |
|
v.(*game.MjTable).Close() |
|
} |
|
|
|
func (s *Store) RangeTable(f func(key, value any) bool) { |
|
s.tables.Range(f) |
|
} |
|
|
|
func (s *Store) NextTableId() string { |
|
tid := atomic.AddInt32(&s.prevTableId, 1) |
|
return strconv.Itoa(int(tid)) |
|
} |
|
|
|
func (s *Store) LoadPlayer(playerId string) (*game.MjPlayer, error) { |
|
val, ok := s.players.Load(playerId) |
|
if !ok { |
|
return nil, errors.New("玩家已离线") |
|
} |
|
return val.(*game.MjPlayer), nil |
|
} |
|
|
|
func (s *Store) LoadTable(tableId string) (*game.MjTable, error) { |
|
val, ok := s.tables.Load(tableId) |
|
if !ok { |
|
return nil, errors.New("牌桌不存在") |
|
} |
|
return val.(*game.MjTable), nil |
|
}
|
|
|