From 3dec4075d5929dcd4a064350dcdfbe8e3287b7e4 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Fri, 28 Jul 2023 10:48:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20room=20=E5=8C=85=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=A4=A7=E9=87=8F=20error=20=E8=BF=94=E5=9B=9E=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=98=93=E4=BA=8E=E6=88=BF=E9=97=B4=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=20Helper=20=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E9=80=9A=E8=BF=87=20Manager.GetHelper=20?= =?UTF-8?q?=E5=92=8C=20room.NewHelper=20=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/room/events.go | 1 + game/room/helper.go | 127 ++++++++++++++++++++++++++++++ game/room/info.go | 2 +- game/room/manager.go | 158 ++++++++++++++++++++++++++++++-------- game/room/room.go | 2 +- game/room/room_options.go | 19 +++++ game/room/seat.go | 123 ++++++++++++++++++----------- notify/manager.go | 6 +- 8 files changed, 356 insertions(+), 82 deletions(-) create mode 100644 game/room/helper.go create mode 100644 game/room/room_options.go diff --git a/game/room/events.go b/game/room/events.go index c394b56..b3bb33e 100644 --- a/game/room/events.go +++ b/game/room/events.go @@ -195,6 +195,7 @@ func (slf *event[PID, P, R]) RegPlayerSeatChangeEvent(handle PlayerSeatChangeEve } // RegPlayerSeatChangeEventWithRoom 玩家座位改变时将立即执行被注册的事件处理函数 +// - 当玩家之前没有座位时,oldSeat 为 NoSeat func (slf *event[PID, P, R]) RegPlayerSeatChangeEventWithRoom(room R, handle PlayerSeatChangeEventHandle[PID, P, R]) { slf.playerSeatChangeEventRoomHandles[room.GetGuid()] = append(slf.playerSeatChangeEventRoomHandles[room.GetGuid()], handle) } diff --git a/game/room/helper.go b/game/room/helper.go new file mode 100644 index 0000000..8b62b01 --- /dev/null +++ b/game/room/helper.go @@ -0,0 +1,127 @@ +package room + +import ( + "github.com/kercylan98/minotaur/game" + "github.com/kercylan98/minotaur/utils/hash" +) + +// NewHelper 创建房间助手 +func NewHelper[PID comparable, P game.Player[PID], R Room](manager *Manager[PID, P, R], room R) *Helper[PID, P, R] { + return &Helper[PID, P, R]{ + m: manager, + room: room, + Seat: manager.GetSeatInfo(room.GetGuid()), + } +} + +// Helper 易于快捷使用的房间助手 +type Helper[PID comparable, P game.Player[PID], R Room] struct { + m *Manager[PID, P, R] + *Seat[PID, P, R] + room R +} + +// Room 获取房间 +func (slf *Helper[PID, P, R]) Room() R { + return slf.room +} + +// GetPlayer 获取玩家 +func (slf *Helper[PID, P, R]) GetPlayer(playerId PID) P { + return slf.m.GetRoomPlayer(slf.room.GetGuid(), playerId) +} + +// GetPlayers 获取房间中的所有玩家 +func (slf *Helper[PID, P, R]) GetPlayers() map[PID]P { + return slf.m.GetRoomPlayers(slf.room.GetGuid()) +} + +// GetPlayerCount 获取房间中的玩家数量 +func (slf *Helper[PID, P, R]) GetPlayerCount() int { + return slf.m.GetRoomPlayerCount(slf.room.GetGuid()) +} + +// GetPlayerLimit 获取房间中的玩家数量上限 +func (slf *Helper[PID, P, R]) GetPlayerLimit() int { + return slf.m.GetRoomPlayerLimit(slf.room.GetGuid()) +} + +// GetPlayerRooms 获取玩家所在的所有房间 +func (slf *Helper[PID, P, R]) GetPlayerRooms(playerId PID) map[int64]R { + return slf.m.GetPlayerRooms(playerId) +} + +// GetPlayerRoomHelpers 获取玩家所在的所有房间助手 +func (slf *Helper[PID, P, R]) GetPlayerRoomHelpers(playerId PID) map[int64]*Helper[PID, P, R] { + return slf.m.GetPlayerRoomHelpers(playerId) +} + +// SetPlayerLimit 设置房间中的玩家数量上限 +func (slf *Helper[PID, P, R]) SetPlayerLimit(limit int) { + slf.m.SetPlayerLimit(slf.room.GetGuid(), limit) +} + +// GetPlayerIDs 获取房间中的所有玩家ID +func (slf *Helper[PID, P, R]) GetPlayerIDs() []PID { + return hash.KeyToSlice(slf.GetPlayers()) +} + +// SetOwner 设置房主 +func (slf *Helper[PID, P, R]) SetOwner(playerId PID) { + slf.m.SetOwner(slf.room.GetGuid(), playerId) +} + +// CancelOwner 取消房主 +func (slf *Helper[PID, P, R]) CancelOwner() { + slf.manager.CancelOwner(slf.room.GetGuid()) +} + +// HasPlayer 是否有玩家 +func (slf *Helper[PID, P, R]) HasPlayer(playerId PID) bool { + return slf.m.InRoom(slf.room.GetGuid(), playerId) +} + +// IsFull 房间是否已满 +func (slf *Helper[PID, P, R]) IsFull() bool { + return slf.GetPlayerCount() == slf.GetPlayerLimit() +} + +// IsEmpty 房间是否为空 +func (slf *Helper[PID, P, R]) IsEmpty() bool { + return slf.GetPlayerCount() == 0 +} + +// GetRemainder 获取房间还可以容纳多少玩家 +func (slf *Helper[PID, P, R]) GetRemainder() int { + return slf.GetPlayerLimit() - slf.GetPlayerCount() +} + +// IsOwner 是否是房主 +func (slf *Helper[PID, P, R]) IsOwner(playerId PID) bool { + return slf.m.IsOwner(slf.room.GetGuid(), playerId) +} + +// HasOwner 是否有房主 +func (slf *Helper[PID, P, R]) HasOwner() bool { + return slf.m.HasOwner(slf.room.GetGuid()) +} + +// GetOwner 获取房主 +func (slf *Helper[PID, P, R]) GetOwner() P { + return slf.m.GetOwner(slf.room.GetGuid()) +} + +// Join 加入房间 +func (slf *Helper[PID, P, R]) Join(player P) error { + return slf.m.Join(slf.room.GetGuid(), player) +} + +// Leave 离开房间 +func (slf *Helper[PID, P, R]) Leave(player P) { + slf.m.Leave(slf.room.GetGuid(), player) +} + +// KickOut 踢出房间 +func (slf *Helper[PID, P, R]) KickOut(executor, kicked PID, reason string) error { + return slf.m.KickOut(slf.room.GetGuid(), executor, kicked, reason) +} diff --git a/game/room/info.go b/game/room/info.go index 93cea46..06d1305 100644 --- a/game/room/info.go +++ b/game/room/info.go @@ -2,7 +2,7 @@ package room import "github.com/kercylan98/minotaur/game" -type info[PlayerID comparable, P game.Player[PlayerID], R Room] struct { +type Info[PlayerID comparable, P game.Player[PlayerID], R Room] struct { room R playerLimit int // 玩家人数上限, <= 0 表示无限制 owner *PlayerID // 房主 diff --git a/game/room/manager.go b/game/room/manager.go index 558f2c2..6678e66 100644 --- a/game/room/manager.go +++ b/game/room/manager.go @@ -10,10 +10,11 @@ import ( func NewManager[PID comparable, P game.Player[PID], R Room]() *Manager[PID, P, R] { manager := &Manager[PID, P, R]{ event: newEvent[PID, P, R](), - rooms: concurrent.NewBalanceMap[int64, *info[PID, P, R]](), + rooms: concurrent.NewBalanceMap[int64, *Info[PID, P, R]](), players: concurrent.NewBalanceMap[PID, P](), pr: concurrent.NewBalanceMap[PID, map[int64]struct{}](), rp: concurrent.NewBalanceMap[int64, map[PID]struct{}](), + helpers: concurrent.NewBalanceMap[int64, *Helper[PID, P, R]](), } return manager @@ -22,19 +23,33 @@ func NewManager[PID comparable, P game.Player[PID], R Room]() *Manager[PID, P, R // Manager 房间管理器 type Manager[PID comparable, P game.Player[PID], R Room] struct { *event[PID, P, R] - rooms *concurrent.BalanceMap[int64, *info[PID, P, R]] // 所有房间 - players *concurrent.BalanceMap[PID, P] // 所有加入房间的玩家 - pr *concurrent.BalanceMap[PID, map[int64]struct{}] // 玩家所在房间 - rp *concurrent.BalanceMap[int64, map[PID]struct{}] // 房间中的玩家 + rooms *concurrent.BalanceMap[int64, *Info[PID, P, R]] // 所有房间 + players *concurrent.BalanceMap[PID, P] // 所有加入房间的玩家 + pr *concurrent.BalanceMap[PID, map[int64]struct{}] // 玩家所在房间 + rp *concurrent.BalanceMap[int64, map[PID]struct{}] // 房间中的玩家 + helpers *concurrent.BalanceMap[int64, *Helper[PID, P, R]] // 房间助手 +} +// GetHelper 获取房间助手 +func (slf *Manager[PID, P, R]) GetHelper(room R) *Helper[PID, P, R] { + helper, exist := slf.helpers.GetExist(room.GetGuid()) + if exist { + return helper + } + helper = NewHelper[PID, P, R](slf, room) + slf.helpers.Set(room.GetGuid(), helper) + return helper } // CreateRoom 创建房间 -func (slf *Manager[PID, P, R]) CreateRoom(room R) { - roomInfo := &info[PID, P, R]{ +func (slf *Manager[PID, P, R]) CreateRoom(room R, options ...Option[PID, P, R]) { + roomInfo := &Info[PID, P, R]{ room: room, seat: newSeat[PID, P, R](slf, room, slf.event), } + for _, option := range options { + option(roomInfo) + } slf.rooms.Set(room.GetGuid(), roomInfo) } @@ -42,6 +57,16 @@ func (slf *Manager[PID, P, R]) CreateRoom(room R) { func (slf *Manager[PID, P, R]) ReleaseRoom(guid int64) { slf.unReg(guid) slf.rooms.Delete(guid) + slf.helpers.Delete(guid) + slf.rp.Atom(func(m map[int64]map[PID]struct{}) { + players := m[guid] + slf.pr.Atom(func(m map[PID]map[int64]struct{}) { + for playerId := range players { + delete(m[playerId], guid) + } + }) + }) + slf.rp.Delete(guid) } // SetPlayerLimit 设置房间人数上限 @@ -51,7 +76,7 @@ func (slf *Manager[PID, P, R]) SetPlayerLimit(roomId int64, limit int) { } var room R var oldLimit int - slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) { + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { info, ok := m[roomId] if !ok { return @@ -69,7 +94,7 @@ func (slf *Manager[PID, P, R]) SetPlayerLimit(roomId int64, limit int) { func (slf *Manager[PID, P, R]) CancelOwner(roomId int64) { var room R var oldOwner P - slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) { + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { info, ok := m[roomId] if !ok { return @@ -85,15 +110,81 @@ func (slf *Manager[PID, P, R]) CancelOwner(roomId int64) { } } -// SetOwner 设置房主 -func (slf *Manager[PID, P, R]) SetOwner(roomId int64, owner PID) error { - var err error - var oldOwner, newOwner P - var room R - slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) { +// GetPlayerRooms 获取玩家所在的房间 +func (slf *Manager[PID, P, R]) GetPlayerRooms(playerId PID) (rooms map[int64]R) { + rooms = map[int64]R{} + slf.pr.Atom(func(m map[PID]map[int64]struct{}) { + for roomId := range m[playerId] { + room, ok := slf.rooms.GetExist(roomId) + if !ok { + continue + } + rooms[roomId] = room.room + } + }) + return +} + +// GetPlayerRoomHelpers 获取玩家所在的房间助手 +func (slf *Manager[PID, P, R]) GetPlayerRoomHelpers(playerId PID) (helpers map[int64]*Helper[PID, P, R]) { + helpers = map[int64]*Helper[PID, P, R]{} + slf.pr.Atom(func(m map[PID]map[int64]struct{}) { + for roomId := range m[playerId] { + room, ok := slf.rooms.GetExist(roomId) + if !ok { + continue + } + helpers[roomId] = slf.GetHelper(room.room) + } + }) + return +} + +// IsOwner 检查玩家是否是房主 +func (slf *Manager[PID, P, R]) IsOwner(roomId int64, playerId PID) bool { + var isOwner bool + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { + info, ok := m[roomId] + if !ok { + return + } + isOwner = info.owner != nil && *info.owner == playerId + }) + return isOwner +} + +// HasOwner 检查房间是否有房主 +func (slf *Manager[PID, P, R]) HasOwner(roomId int64) bool { + var hasOwner bool + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { + info, ok := m[roomId] + if !ok { + return + } + hasOwner = info.owner != nil + }) + return hasOwner +} + +// GetOwner 获取房主 +func (slf *Manager[PID, P, R]) GetOwner(roomId int64) (player P) { + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { + info, ok := m[roomId] + if !ok || info.owner == nil { + return + } + player = slf.GetRoomPlayer(roomId, *info.owner) + }) + return +} + +// SetOwner 设置房主 +func (slf *Manager[PID, P, R]) SetOwner(roomId int64, owner PID) { + var oldOwner, newOwner P + var room R + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { info, ok := m[roomId] if !ok { - err = ErrRoomNotExist return } room = info.room @@ -102,13 +193,14 @@ func (slf *Manager[PID, P, R]) SetOwner(roomId int64, owner PID) error { } newOwner = slf.GetRoomPlayer(roomId, owner) if generic.IsNil(newOwner) { - err = ErrRoomOrPlayerNotExist return } info.owner = &owner }) + if generic.IsNil(newOwner) { + return + } slf.OnPlayerUpgradeOwnerEvent(room, oldOwner, newOwner) - return err } // GetRoom 获取房间 @@ -124,7 +216,7 @@ func (slf *Manager[PID, P, R]) Exist(guid int64) bool { // GetRooms 获取所有房间 func (slf *Manager[PID, P, R]) GetRooms() map[int64]R { var rooms = make(map[int64]R) - slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) { + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { for id, info := range m { rooms[id] = info.room } @@ -152,7 +244,7 @@ func (slf *Manager[PID, P, R]) ExistPlayer(id PID) bool { } // InRoom 检查玩家是否在指定房间内 -func (slf *Manager[PID, P, R]) InRoom(id PID, guid int64) bool { +func (slf *Manager[PID, P, R]) InRoom(guid int64, id PID) bool { var in bool slf.pr.Atom(func(m map[PID]map[int64]struct{}) { rooms, exist := m[id] @@ -242,8 +334,8 @@ func (slf *Manager[PID, P, R]) GetRoomPlayerLimit(guid int64) int { // Leave 使玩家离开房间 func (slf *Manager[PID, P, R]) Leave(roomId int64, player P) { - var roomInfo *info[PID, P, R] - slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) { + var roomInfo *Info[PID, P, R] + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { room, exist := m[roomId] if !exist { return @@ -254,7 +346,11 @@ func (slf *Manager[PID, P, R]) Leave(roomId int64, player P) { return } slf.OnPlayerLeaveRoomEvent(roomInfo.room, player) - roomInfo.seat.removePlayerSeat(player.GetID()) + seat := roomInfo.seat.GetSeat(player.GetID()) + if seat != NoSeat && slf.IsOwner(roomId, player.GetID()) && slf.GetPlayerCount() > 1 { + slf.SetOwner(roomId, roomInfo.seat.GetPlayerIDWithSeat(roomInfo.seat.GetNextSeat(seat))) + } + roomInfo.seat.RemoveSeat(player.GetID()) slf.pr.Atom(func(m map[PID]map[int64]struct{}) { rooms, exist := m[player.GetID()] if !exist { @@ -274,8 +370,8 @@ func (slf *Manager[PID, P, R]) Leave(roomId int64, player P) { // Join 使玩家加入房间 func (slf *Manager[PID, P, R]) Join(roomId int64, player P) error { var err error - var roomInfo *info[PID, P, R] - slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) { + var roomInfo *Info[PID, P, R] + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { room, exist := m[roomId] if !exist { err = ErrRoomNotExist @@ -304,7 +400,9 @@ func (slf *Manager[PID, P, R]) Join(roomId int64, player P) error { slf.players.Set(player.GetID(), player) roomInfo = room }) - roomInfo.seat.addSeat(player.GetID()) + if roomInfo.seat.autoSitDown { + roomInfo.seat.AddSeat(player.GetID()) + } slf.OnPlayerJoinRoomEvent(roomInfo.room, player) return err } @@ -336,16 +434,14 @@ func (slf *Manager[PID, P, R]) KickOut(roomId int64, executor, kicked PID, reaso } // GetSeatInfo 获取座位信息 -func (slf *Manager[PID, P, R]) GetSeatInfo(roomId int64) (*Seat[PID, P, R], error) { +func (slf *Manager[PID, P, R]) GetSeatInfo(roomId int64) *Seat[PID, P, R] { var result *Seat[PID, P, R] - var err error - slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) { + slf.rooms.Atom(func(m map[int64]*Info[PID, P, R]) { room, exist := m[roomId] if !exist { - err = ErrRoomNotExist return } result = room.seat }) - return result, err + return result } diff --git a/game/room/room.go b/game/room/room.go index a52a0f7..7a55191 100644 --- a/game/room/room.go +++ b/game/room/room.go @@ -1,6 +1,6 @@ package room -// Room 房间类似于简版的游戏世界(World),不过没有游戏实体 +// Room 游戏房间接口 type Room interface { // GetGuid 获取房间的唯一标识符 GetGuid() int64 diff --git a/game/room/room_options.go b/game/room/room_options.go new file mode 100644 index 0000000..d5f2e35 --- /dev/null +++ b/game/room/room_options.go @@ -0,0 +1,19 @@ +package room + +import "github.com/kercylan98/minotaur/game" + +type Option[PID comparable, P game.Player[PID], R Room] func(info *Info[PID, P, R]) + +// WithPlayerLimit 设置房间人数上限 +func WithPlayerLimit[PID comparable, P game.Player[PID], R Room](limit int) Option[PID, P, R] { + return func(info *Info[PID, P, R]) { + info.playerLimit = limit + } +} + +// WithNotAutoJoinSeat 设置不自动加入座位 +func WithNotAutoJoinSeat[PID comparable, P game.Player[PID], R Room]() Option[PID, P, R] { + return func(info *Info[PID, P, R]) { + info.seat.autoSitDown = false + } +} diff --git a/game/room/seat.go b/game/room/seat.go index e7143c6..761c650 100644 --- a/game/room/seat.go +++ b/game/room/seat.go @@ -7,12 +7,17 @@ import ( "sync" ) +const ( + NoSeat = -1 // 无座位 +) + func newSeat[PlayerID comparable, P game.Player[PlayerID], R Room](manager *Manager[PlayerID, P, R], room R, event *event[PlayerID, P, R]) *Seat[PlayerID, P, R] { roomSeat := &Seat[PlayerID, P, R]{ - manager: manager, - room: room, - event: event, - seatPS: concurrent.NewBalanceMap[PlayerID, int](), + manager: manager, + room: room, + event: event, + seatPS: concurrent.NewBalanceMap[PlayerID, int](), + autoSitDown: true, } return roomSeat } @@ -27,12 +32,12 @@ type Seat[PlayerID comparable, P game.Player[PlayerID], R Room] struct { seatPS *concurrent.BalanceMap[PlayerID, int] seatSP []*PlayerID duplicateLock bool - autoMode sync.Once + autoSitDown bool } -// addSeat 为特定玩家添加座位 +// AddSeat 为特定玩家添加座位 // - 当座位存在空缺的时候,玩家将会优先在空缺位置坐下,否则将会在末位追加 -func (slf *Seat[PlayerID, P, R]) addSeat(id PlayerID) { +func (slf *Seat[PlayerID, P, R]) AddSeat(id PlayerID) { if slf.seatPS.Exist(id) { return } @@ -52,8 +57,8 @@ func (slf *Seat[PlayerID, P, R]) addSeat(id PlayerID) { slf.event.OnPlayerSeatSetEvent(slf.room, slf.manager.GetPlayer(id), seat) } -// removePlayerSeat 删除玩家座位 -func (slf *Seat[PlayerID, P, R]) removePlayerSeat(id PlayerID) { +// RemoveSeat 删除玩家座位 +func (slf *Seat[PlayerID, P, R]) RemoveSeat(id PlayerID) { if !slf.seatPS.Exist(id) { return } @@ -64,36 +69,38 @@ func (slf *Seat[PlayerID, P, R]) removePlayerSeat(id PlayerID) { slf.seatSP[seat] = nil } -// SetSeat 设置玩家的座位号 -// - 如果玩家没有预先添加过座位将会返回错误 -// - 如果位置已经有玩家,将会与其进行更换 -func (slf *Seat[PlayerID, P, R]) SetSeat(id PlayerID, seat int) error { - oldSeat, err := slf.setSeat(id, seat) - if err != nil { - return err - } - slf.event.OnPlayerSeatChangeEvent(slf.room, slf.manager.GetPlayer(id), oldSeat, seat) - return nil +// HasSeat 判断玩家是否有座位 +func (slf *Seat[PlayerID, P, R]) HasSeat(id PlayerID) bool { + return slf.seatPS.Exist(id) } -func (slf *Seat[PlayerID, P, R]) setSeat(id PlayerID, seat int) (int, error) { +// SetSeat 设置玩家的座位号 +// - 如果位置已经有玩家,将会与其进行更换 +func (slf *Seat[PlayerID, P, R]) SetSeat(id PlayerID, seat int) int { slf.mutex.Lock() slf.duplicateLock = true defer func() { slf.mutex.Unlock() slf.duplicateLock = false }() - oldSeat, err := slf.GetSeat(id) - if err != nil { - return oldSeat, err - } - playerId, err := slf.GetPlayerIDWithSeat(seat) - if err != nil { - ov := slf.seatSP[oldSeat] - slf.seatSP[oldSeat] = slf.seatSP[seat] - slf.seatSP[seat] = ov - slf.seatPS.Set(id, seat) - slf.seatPS.Set(playerId, oldSeat) + oldSeat := slf.GetSeat(id) + player := slf.GetPlayerWithSeat(seat) + if player != nil { + if oldSeat == NoSeat { + maxSeat := len(slf.seatSP) - 1 + if seat > maxSeat { + count := seat - maxSeat + slf.seatSP = append(slf.seatSP, make([]*PlayerID, count)...) + } + slf.seatSP[seat] = &id + slf.seatPS.Set(id, seat) + } else { + ov := slf.seatSP[oldSeat] + slf.seatSP[oldSeat] = slf.seatSP[seat] + slf.seatSP[seat] = ov + slf.seatPS.Set(id, seat) + slf.seatPS.Set(player.GetID(), oldSeat) + } } else { maxSeat := len(slf.seatSP) - 1 if seat > maxSeat { @@ -104,32 +111,55 @@ func (slf *Seat[PlayerID, P, R]) setSeat(id PlayerID, seat int) (int, error) { slf.seatSP[oldSeat] = nil slf.seatPS.Set(id, seat) } - return oldSeat, nil + slf.event.OnPlayerSeatChangeEvent(slf.room, slf.manager.GetPlayer(id), oldSeat, seat) + return oldSeat +} + +// IsNoSeat 判断玩家是否没有座位 +func (slf *Seat[PlayerID, P, R]) IsNoSeat(id PlayerID) bool { + return slf.GetSeat(id) == NoSeat } // GetSeat 获取玩家座位号 -func (slf *Seat[PlayerID, P, R]) GetSeat(id PlayerID) (int, error) { +// - 如果玩家没有座位,将会返回 NoSeat +func (slf *Seat[PlayerID, P, R]) GetSeat(id PlayerID) int { seat, exist := slf.seatPS.GetExist(id) if !exist { - return 0, ErrPlayerNotInRoom + return NoSeat } - return seat, nil + return seat } -// GetPlayerIDWithSeat 获取特定座位号的玩家 -func (slf *Seat[PlayerID, P, R]) GetPlayerIDWithSeat(seat int) (playerId PlayerID, err error) { +// GetPlayerIDWithSeat 获取特定座位号的玩家ID +func (slf *Seat[PlayerID, P, R]) GetPlayerIDWithSeat(seat int) (id PlayerID) { if !slf.duplicateLock { slf.mutex.RLock() defer slf.mutex.RUnlock() } - if seat > len(slf.seatSP)-1 { - return playerId, ErrPlayerNotInRoom + if seat >= len(slf.seatSP) || seat < 0 { + return id + } + playerId := slf.seatSP[seat] + if playerId == nil { + return id + } + return *playerId +} + +// GetPlayerWithSeat 获取特定座位号的玩家 +func (slf *Seat[PlayerID, P, R]) GetPlayerWithSeat(seat int) (player P) { + if !slf.duplicateLock { + slf.mutex.RLock() + defer slf.mutex.RUnlock() + } + if seat >= len(slf.seatSP) || seat < 0 { + return player } id := slf.seatSP[seat] if id == nil { - return playerId, ErrPlayerNotInRoom + return player } - return *id, nil + return slf.manager.GetRoomPlayer(slf.room.GetGuid(), *id) } // GetSeatInfo 获取所有座位号 @@ -169,20 +199,21 @@ func (slf *Seat[PlayerID, P, R]) GetSeatInfoWithPlayerIDMap() map[PlayerID]int { } // GetFirstSeat 获取第一个未缺席的座位号 +// - 如果没有,将会返回 NoSeat func (slf *Seat[PlayerID, P, R]) GetFirstSeat() int { for seat, playerId := range slf.seatSP { if playerId != nil { return seat } } - return -1 + return NoSeat } // GetNextSeat 获取特定座位号下一个未缺席的座位号 func (slf *Seat[PlayerID, P, R]) GetNextSeat(seat int) int { l := len(slf.seatSP) if l == 0 || seat >= l || seat < 0 { - return -1 + return NoSeat } var target = seat for { @@ -204,7 +235,7 @@ func (slf *Seat[PlayerID, P, R]) GetNextSeat(seat int) int { func (slf *Seat[PlayerID, P, R]) GetNextSeatVacancy(seat int) int { l := len(slf.seatSP) if l == 0 || seat >= l || seat < 0 { - return -1 + return NoSeat } seat++ if seat >= l { @@ -217,7 +248,7 @@ func (slf *Seat[PlayerID, P, R]) GetNextSeatVacancy(seat int) int { func (slf *Seat[PlayerID, P, R]) GetPrevSeat(seat int) int { l := len(slf.seatSP) if l == 0 || seat >= l || seat < 0 { - return -1 + return NoSeat } var target = seat for { @@ -239,7 +270,7 @@ func (slf *Seat[PlayerID, P, R]) GetPrevSeat(seat int) int { func (slf *Seat[PlayerID, P, R]) GetPrevSeatVacancy(seat int) int { l := len(slf.seatSP) if l == 0 || seat >= l || seat < 0 { - return -1 + return NoSeat } seat-- if seat < 0 { diff --git a/notify/manager.go b/notify/manager.go index 4c4829e..d7bc469 100644 --- a/notify/manager.go +++ b/notify/manager.go @@ -19,19 +19,19 @@ func NewManager(senders ...Sender) *Manager { case <-manager.closeChannel: close(manager.closeChannel) close(manager.notifyChannel) - log.Info("Manager", log.String("state", "release")) + log.Info("m", log.String("state", "release")) return case notify := <-manager.notifyChannel: for _, sender := range manager.senders { if err := sender.Push(notify); err != nil { - log.Error("Manager", log.String("sender", reflect.TypeOf(sender).String()), log.Err(err)) + log.Error("m", log.String("sender", reflect.TypeOf(sender).String()), log.Err(err)) } } } } }() - log.Info("Manager", log.String("state", "running")) + log.Info("m", log.String("state", "running")) return manager }