更多的辅助函数、补位模式
This commit is contained in:
parent
dfa5f7a063
commit
46017d8bc0
|
@ -2,29 +2,38 @@ package builtin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kercylan98/minotaur/game"
|
"github.com/kercylan98/minotaur/game"
|
||||||
|
"github.com/kercylan98/minotaur/utils/hash"
|
||||||
|
"github.com/kercylan98/minotaur/utils/slice"
|
||||||
"github.com/kercylan98/minotaur/utils/synchronization"
|
"github.com/kercylan98/minotaur/utils/synchronization"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewRoomSeat[PlayerID comparable, Player game.Player[PlayerID]](room game.Room[PlayerID, Player]) *RoomSeat[PlayerID, Player] {
|
func NewRoomSeat[PlayerID comparable, Player game.Player[PlayerID]](room game.Room[PlayerID, Player], options ...RoomSeatOption[PlayerID, Player]) *RoomSeat[PlayerID, Player] {
|
||||||
roomSeat := &RoomSeat[PlayerID, Player]{
|
roomSeat := &RoomSeat[PlayerID, Player]{
|
||||||
Room: room,
|
Room: room,
|
||||||
seatPS: synchronization.NewMap[PlayerID, int](),
|
seatPS: synchronization.NewMap[PlayerID, int](),
|
||||||
}
|
}
|
||||||
room.RegPlayerJoinRoomEvent(roomSeat.onJoinRoom)
|
room.RegPlayerJoinRoomEvent(roomSeat.onJoinRoom)
|
||||||
room.RegPlayerLeaveRoomEvent(roomSeat.onLeaveRoom)
|
room.RegPlayerLeaveRoomEvent(roomSeat.onLeaveRoom)
|
||||||
|
for _, option := range options {
|
||||||
|
option(roomSeat)
|
||||||
|
}
|
||||||
return roomSeat
|
return roomSeat
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoomSeat[PlayerID comparable, Player game.Player[PlayerID]] struct {
|
type RoomSeat[PlayerID comparable, Player game.Player[PlayerID]] struct {
|
||||||
game.Room[PlayerID, Player]
|
game.Room[PlayerID, Player]
|
||||||
mutex sync.Mutex
|
mutex sync.RWMutex
|
||||||
vacancy []int
|
vacancy []int
|
||||||
seatPS *synchronization.Map[PlayerID, int]
|
seatPS *synchronization.Map[PlayerID, int]
|
||||||
seatSP []*PlayerID
|
seatSP []*PlayerID
|
||||||
|
|
||||||
|
fillIn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) SetSeat(id PlayerID, seat int) error {
|
func (slf *RoomSeat[PlayerID, Player]) SetSeat(id PlayerID, seat int) error {
|
||||||
|
slf.mutex.Lock()
|
||||||
|
defer slf.mutex.Unlock()
|
||||||
oldSeat, err := slf.GetSeat(id)
|
oldSeat, err := slf.GetSeat(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -39,6 +48,15 @@ func (slf *RoomSeat[PlayerID, Player]) SetSeat(id PlayerID, seat int) error {
|
||||||
} else {
|
} else {
|
||||||
maxSeat := len(slf.seatSP) - 1
|
maxSeat := len(slf.seatSP) - 1
|
||||||
if seat > maxSeat {
|
if seat > maxSeat {
|
||||||
|
if slf.fillIn {
|
||||||
|
seat = maxSeat + 1
|
||||||
|
defer func() {
|
||||||
|
slice.Del(&slf.seatSP, oldSeat)
|
||||||
|
for i := oldSeat; i < len(slf.seatSP); i++ {
|
||||||
|
slf.seatPS.Set(*slf.seatSP[i], i)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
count := seat - maxSeat
|
count := seat - maxSeat
|
||||||
slf.seatSP = append(slf.seatSP, make([]*PlayerID, count)...)
|
slf.seatSP = append(slf.seatSP, make([]*PlayerID, count)...)
|
||||||
}
|
}
|
||||||
|
@ -58,6 +76,8 @@ func (slf *RoomSeat[PlayerID, Player]) GetSeat(id PlayerID) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetPlayerWithSeat(seat int) (player Player, err error) {
|
func (slf *RoomSeat[PlayerID, Player]) GetPlayerWithSeat(seat int) (player Player, err error) {
|
||||||
|
slf.mutex.RLock()
|
||||||
|
defer slf.mutex.RUnlock()
|
||||||
if seat > len(slf.seatSP)-1 {
|
if seat > len(slf.seatSP)-1 {
|
||||||
return player, ErrRoomNotHasPlayer
|
return player, ErrRoomNotHasPlayer
|
||||||
}
|
}
|
||||||
|
@ -68,6 +88,35 @@ func (slf *RoomSeat[PlayerID, Player]) GetPlayerWithSeat(seat int) (player Playe
|
||||||
return slf.GetPlayer(*id), nil
|
return slf.GetPlayer(*id), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (slf *RoomSeat[PlayerID, Player]) GetSeatInfo() []*PlayerID {
|
||||||
|
slf.mutex.RLock()
|
||||||
|
defer slf.mutex.RUnlock()
|
||||||
|
return slf.seatSP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *RoomSeat[PlayerID, Player]) GetSeatInfoMap() map[int]PlayerID {
|
||||||
|
var seatInfo = make(map[int]PlayerID)
|
||||||
|
slf.mutex.RLock()
|
||||||
|
defer slf.mutex.RUnlock()
|
||||||
|
for seat, playerId := range slf.seatSP {
|
||||||
|
if playerId == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seatInfo[seat] = *playerId
|
||||||
|
}
|
||||||
|
return seatInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *RoomSeat[PlayerID, Player]) GetSeatInfoMapVacancy() map[int]*PlayerID {
|
||||||
|
slf.mutex.RLock()
|
||||||
|
defer slf.mutex.RUnlock()
|
||||||
|
return hash.ToMap(slf.seatSP)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *RoomSeat[PlayerID, Player]) GetSeatInfoWithPlayerIDMap() map[PlayerID]int {
|
||||||
|
return slf.seatPS.Map()
|
||||||
|
}
|
||||||
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) onJoinRoom(room game.Room[PlayerID, Player], player Player) {
|
func (slf *RoomSeat[PlayerID, Player]) onJoinRoom(room game.Room[PlayerID, Player], player Player) {
|
||||||
slf.mutex.Lock()
|
slf.mutex.Lock()
|
||||||
defer slf.mutex.Unlock()
|
defer slf.mutex.Unlock()
|
||||||
|
@ -84,6 +133,16 @@ func (slf *RoomSeat[PlayerID, Player]) onJoinRoom(room game.Room[PlayerID, Playe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) onLeaveRoom(room game.Room[PlayerID, Player], player Player) {
|
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())
|
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.seatSP[seat] = nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/game"
|
||||||
|
|
||||||
|
type RoomSeatOption[PlayerID comparable, Player game.Player[PlayerID]] func(seat *RoomSeat[PlayerID, Player])
|
||||||
|
|
||||||
|
// WithRoomSeatFillIn 通过补位的方式创建带有座位号的房间
|
||||||
|
// - 默认情况下玩家离开座位不会影响其他玩家
|
||||||
|
// - 补位情况下,靠前的玩家离开座位将有后方玩家向前补位
|
||||||
|
func WithRoomSeatFillIn[PlayerID comparable, Player game.Player[PlayerID]]() RoomSeatOption[PlayerID, Player] {
|
||||||
|
return func(seatRoom *RoomSeat[PlayerID, Player]) {
|
||||||
|
seatRoom.fillIn = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,4 +9,12 @@ type RoomSeat[PlayerID comparable, P Player[PlayerID]] interface {
|
||||||
GetSeat(id PlayerID) (int, error)
|
GetSeat(id PlayerID) (int, error)
|
||||||
// GetPlayerWithSeat 根据座位号获取玩家
|
// GetPlayerWithSeat 根据座位号获取玩家
|
||||||
GetPlayerWithSeat(seat int) (P, error)
|
GetPlayerWithSeat(seat int) (P, error)
|
||||||
|
// GetSeatInfo 获取座位信息,空缺的位置将为空
|
||||||
|
GetSeatInfo() []*PlayerID
|
||||||
|
// GetSeatInfoMap 以map的方式获取座位号
|
||||||
|
GetSeatInfoMap() map[int]PlayerID
|
||||||
|
// GetSeatInfoMapVacancy 以map的方式获取座位号,空缺的位置将被保留为nil
|
||||||
|
GetSeatInfoMapVacancy() map[int]*PlayerID
|
||||||
|
// GetSeatInfoWithPlayerIDMap 获取座位信息,将以玩家ID作为key
|
||||||
|
GetSeatInfoWithPlayerIDMap() map[PlayerID]int
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue