添加手动管理座位信息的函数,默认改为手动管理,添加自动管理的可选项
This commit is contained in:
parent
9a58405f70
commit
c8d701bea5
|
@ -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)
|
||||
}
|
||||
|
@ -27,24 +25,79 @@ type RoomSeat[PlayerID comparable, Player game.Player[PlayerID]] struct {
|
|||
vacancy []int
|
||||
seatPS *synchronization.Map[PlayerID, int]
|
||||
seatSP []*PlayerID
|
||||
|
||||
duplicateLock bool
|
||||
fillIn bool
|
||||
autoMode sync.Once
|
||||
}
|
||||
|
||||
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) {
|
||||
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())
|
||||
}
|
||||
|
|
|
@ -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 通过补位的方式创建带有座位号的房间
|
||||
// - 默认情况下玩家离开座位不会影响其他玩家
|
||||
// - 补位情况下,靠前的玩家离开座位将有后方玩家向前补位
|
||||
|
|
|
@ -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的方式获取座位号
|
||||
|
|
Loading…
Reference in New Issue