From c8d701bea5ee8e751feb76be1c6bfa18ca892356 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Fri, 12 May 2023 10:28:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=8B=E5=8A=A8=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=BA=A7=E4=BD=8D=E4=BF=A1=E6=81=AF=E7=9A=84=E5=87=BD?= =?UTF-8?q?=E6=95=B0=EF=BC=8C=E9=BB=98=E8=AE=A4=E6=94=B9=E4=B8=BA=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E7=AE=A1=E7=90=86=EF=BC=8C=E6=B7=BB=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E7=AE=A1=E7=90=86=E7=9A=84=E5=8F=AF=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/builtin/room_seat.go | 113 +++++++++++++++++++----------- game/builtin/room_seat_options.go | 12 ++++ game/room_seat.go | 15 +++- 3 files changed, 97 insertions(+), 43 deletions(-) diff --git a/game/builtin/room_seat.go b/game/builtin/room_seat.go index e697ea0..e4ce3a5 100644 --- a/game/builtin/room_seat.go +++ b/game/builtin/room_seat.go @@ -13,8 +13,6 @@ func NewRoomSeat[PlayerID comparable, Player game.Player[PlayerID]](room game.Ro Room: room, seatPS: synchronization.NewMap[PlayerID, int](), } - room.RegPlayerJoinRoomEvent(roomSeat.onJoinRoom) - room.RegPlayerLeaveRoomEvent(roomSeat.onLeaveRoom) for _, option := range options { option(roomSeat) } @@ -23,28 +21,83 @@ func NewRoomSeat[PlayerID comparable, Player game.Player[PlayerID]](room game.Ro type RoomSeat[PlayerID comparable, Player game.Player[PlayerID]] struct { game.Room[PlayerID, Player] - mutex sync.RWMutex - vacancy []int - seatPS *synchronization.Map[PlayerID, int] - seatSP []*PlayerID + mutex sync.RWMutex + vacancy []int + seatPS *synchronization.Map[PlayerID, int] + seatSP []*PlayerID + duplicateLock bool + fillIn bool + autoMode sync.Once +} - fillIn bool +func (slf *RoomSeat[PlayerID, Player]) AddSeat(id PlayerID) { + if slf.seatPS.Exist(id) { + return + } + slf.mutex.Lock() + defer slf.mutex.Unlock() + if len(slf.vacancy) > 0 { + seat := slf.vacancy[0] + slf.vacancy = slf.vacancy[1:] + slf.seatPS.Set(id, seat) + slf.seatSP[seat] = &id + } else { + slf.seatPS.Set(id, len(slf.seatSP)) + slf.seatSP = append(slf.seatSP, &id) + } +} + +func (slf *RoomSeat[PlayerID, Player]) AddSeatWithAssign(id PlayerID, seat int) { + slf.AddSeat(id) + _ = slf.SetSeat(id, seat) +} + +func (slf *RoomSeat[PlayerID, Player]) RemovePlayerSeat(id PlayerID) { + if !slf.seatPS.Exist(id) { + return + } + slf.mutex.Lock() + defer slf.mutex.Unlock() + seat := slf.seatPS.DeleteGet(id) + if slf.fillIn { + slice.Del(&slf.seatSP, seat) + for i := seat; i < len(slf.seatSP); i++ { + slf.seatPS.Set(*slf.seatSP[i], i) + } + return + } + slf.seatSP[seat] = nil +} + +func (slf *RoomSeat[PlayerID, Player]) RemoveSeat(seat int) { + if seat >= len(slf.seatSP) { + return + } + playerId := slf.seatSP[seat] + if playerId == nil { + return + } + slf.RemovePlayerSeat(*playerId) } func (slf *RoomSeat[PlayerID, Player]) SetSeat(id PlayerID, seat int) error { slf.mutex.Lock() - defer slf.mutex.Unlock() + slf.duplicateLock = true + defer func() { + slf.mutex.Unlock() + slf.duplicateLock = false + }() oldSeat, err := slf.GetSeat(id) if err != nil { return err } - player, err := slf.GetPlayerWithSeat(seat) + 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(player.GetID(), oldSeat) + slf.seatPS.Set(playerId, oldSeat) } else { maxSeat := len(slf.seatSP) - 1 if seat > maxSeat { @@ -75,17 +128,19 @@ func (slf *RoomSeat[PlayerID, Player]) GetSeat(id PlayerID) (int, error) { return seat, nil } -func (slf *RoomSeat[PlayerID, Player]) GetPlayerWithSeat(seat int) (player Player, err error) { - slf.mutex.RLock() - defer slf.mutex.RUnlock() +func (slf *RoomSeat[PlayerID, Player]) GetPlayerIDWithSeat(seat int) (playerId PlayerID, err error) { + if !slf.duplicateLock { + slf.mutex.RLock() + defer slf.mutex.RUnlock() + } if seat > len(slf.seatSP)-1 { - return player, ErrRoomNotHasPlayer + return playerId, ErrRoomNotHasPlayer } id := slf.seatSP[seat] if id == nil { - return player, ErrRoomNotHasPlayer + return playerId, ErrRoomNotHasPlayer } - return slf.GetPlayer(*id), nil + return *id, nil } func (slf *RoomSeat[PlayerID, Player]) GetSeatInfo() []*PlayerID { @@ -118,31 +173,9 @@ func (slf *RoomSeat[PlayerID, Player]) GetSeatInfoWithPlayerIDMap() map[PlayerID } func (slf *RoomSeat[PlayerID, Player]) onJoinRoom(room game.Room[PlayerID, Player], player Player) { - slf.mutex.Lock() - defer slf.mutex.Unlock() - playerId := player.GetID() - if len(slf.vacancy) > 0 { - seat := slf.vacancy[0] - slf.vacancy = slf.vacancy[1:] - slf.seatPS.Set(player.GetID(), seat) - slf.seatSP[seat] = &playerId - } else { - slf.seatPS.Set(player.GetID(), len(slf.seatSP)) - slf.seatSP = append(slf.seatSP, &playerId) - } + slf.AddSeat(player.GetID()) } func (slf *RoomSeat[PlayerID, Player]) onLeaveRoom(room game.Room[PlayerID, Player], player Player) { - slf.mutex.Lock() - defer slf.mutex.Unlock() - seat := slf.seatPS.DeleteGet(player.GetID()) - if slf.fillIn { - slice.Del(&slf.seatSP, seat) - for i := seat; i < len(slf.seatSP); i++ { - slf.seatPS.Set(*slf.seatSP[i], i) - } - return - } - slf.seatSP[seat] = nil - + slf.RemovePlayerSeat(player.GetID()) } diff --git a/game/builtin/room_seat_options.go b/game/builtin/room_seat_options.go index 5e53026..e8a3766 100644 --- a/game/builtin/room_seat_options.go +++ b/game/builtin/room_seat_options.go @@ -4,6 +4,18 @@ import "github.com/kercylan98/minotaur/game" type RoomSeatOption[PlayerID comparable, Player game.Player[PlayerID]] func(seat *RoomSeat[PlayerID, Player]) +// WithRoomSeatAutoManage 通过自动管理的方式创建带有座位号的房间 +// - 默认情况下需要自行维护房间用户的座位号信息 +// - 自动管理模式下,将注册房间的 Room.RegPlayerJoinRoomEvent 和 Room.RegPlayerLeaveRoomEvent 事件以便玩家在加入或者离开时维护座位信息 +func WithRoomSeatAutoManage[PlayerID comparable, Player game.Player[PlayerID]]() RoomSeatOption[PlayerID, Player] { + return func(seatRoom *RoomSeat[PlayerID, Player]) { + seatRoom.autoMode.Do(func() { + seatRoom.RegPlayerJoinRoomEvent(seatRoom.onJoinRoom) + seatRoom.RegPlayerLeaveRoomEvent(seatRoom.onLeaveRoom) + }) + } +} + // WithRoomSeatFillIn 通过补位的方式创建带有座位号的房间 // - 默认情况下玩家离开座位不会影响其他玩家 // - 补位情况下,靠前的玩家离开座位将有后方玩家向前补位 diff --git a/game/room_seat.go b/game/room_seat.go index 3b2ccb4..a8ea404 100644 --- a/game/room_seat.go +++ b/game/room_seat.go @@ -3,12 +3,21 @@ package game // RoomSeat 带有座位号的房间实现 type RoomSeat[PlayerID comparable, P Player[PlayerID]] interface { Room[PlayerID, P] - // SetSeat 设置玩家座位号 + // AddSeat 将玩家添加到座位号中 + AddSeat(id PlayerID) + // AddSeatWithAssign 将玩家添加到座位号中,并分配特定的座位号 + AddSeatWithAssign(id PlayerID, seat int) + // RemovePlayerSeat 移除玩家的座位号 + RemovePlayerSeat(id PlayerID) + // RemoveSeat 移除特定座位号 + RemoveSeat(seat int) + // SetSeat 设置玩家座位号,当玩家没有座位号时,将会返回错误信息 + // - 如果座位号有其他玩家,他们的位置将互换 SetSeat(id PlayerID, seat int) error // GetSeat 获取玩家座位号 GetSeat(id PlayerID) (int, error) - // GetPlayerWithSeat 根据座位号获取玩家 - GetPlayerWithSeat(seat int) (P, error) + // GetPlayerIDWithSeat 根据座位号获取玩家ID + GetPlayerIDWithSeat(seat int) (PlayerID, error) // GetSeatInfo 获取座位信息,空缺的位置将为空 GetSeatInfo() []*PlayerID // GetSeatInfoMap 以map的方式获取座位号