refactor: 移除原有的 builtin 中的各类 room 实现
This commit is contained in:
parent
d06c840c46
commit
ee18934768
|
@ -4,8 +4,6 @@ package game
|
||||||
// - 需要注意 Actor 不等于 Player
|
// - 需要注意 Actor 不等于 Player
|
||||||
// - 在 Minotaur 中,每个网络连接可以表示一个 Player,而每个玩家可以拥有多个 Actor
|
// - 在 Minotaur 中,每个网络连接可以表示一个 Player,而每个玩家可以拥有多个 Actor
|
||||||
// - Actor 并非 Player 独有,场景中也可包含各类无主的 Actor
|
// - Actor 并非 Player 独有,场景中也可包含各类无主的 Actor
|
||||||
// - 内置实现:builtin.Actor
|
|
||||||
// - 构建函数:builtin.NewActor
|
|
||||||
type Actor interface {
|
type Actor interface {
|
||||||
// SetGuid 设置对象的唯一标识符
|
// SetGuid 设置对象的唯一标识符
|
||||||
// - 需要注意的是该函数不应该主动执行,否则可能产生意想不到的情况
|
// - 需要注意的是该函数不应该主动执行,否则可能产生意想不到的情况
|
||||||
|
|
|
@ -1,166 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kercylan98/minotaur/game"
|
|
||||||
"github.com/kercylan98/minotaur/utils/concurrent"
|
|
||||||
"github.com/kercylan98/minotaur/utils/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewRoom 创建一个默认的内置游戏房间 Room
|
|
||||||
func NewRoom[PlayerID comparable, Player game.Player[PlayerID]](guid int64, options ...RoomOption[PlayerID, Player]) *Room[PlayerID, Player] {
|
|
||||||
room := &Room[PlayerID, Player]{
|
|
||||||
guid: guid,
|
|
||||||
players: concurrent.NewBalanceMap[PlayerID, Player](),
|
|
||||||
}
|
|
||||||
for _, option := range options {
|
|
||||||
option(room)
|
|
||||||
}
|
|
||||||
return room
|
|
||||||
}
|
|
||||||
|
|
||||||
// Room 默认的内置游戏房间实现
|
|
||||||
// - 实现了最大人数控制、房主、踢出玩家、玩家维护等功能
|
|
||||||
// - 支持并发安全和非并发安全的模式
|
|
||||||
type Room[PlayerID comparable, Player game.Player[PlayerID]] struct {
|
|
||||||
guid int64
|
|
||||||
owner PlayerID
|
|
||||||
noMaster bool
|
|
||||||
playerLimit int
|
|
||||||
players *concurrent.BalanceMap[PlayerID, Player]
|
|
||||||
kickCheckHandle func(room *Room[PlayerID, Player], id, target PlayerID) error
|
|
||||||
|
|
||||||
playerJoinRoomEventHandles []game.PlayerJoinRoomEventHandle[PlayerID, Player]
|
|
||||||
playerLeaveRoomEventHandles []game.PlayerLeaveRoomEventHandle[PlayerID, Player]
|
|
||||||
playerKickedOutEventHandles []game.PlayerKickedOutEventHandle[PlayerID, Player]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetGuid 获取房间唯一标识
|
|
||||||
func (slf *Room[PlayerID, Player]) GetGuid() int64 {
|
|
||||||
return slf.guid
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPlayerLimit 获取最大玩家上限
|
|
||||||
func (slf *Room[PlayerID, Player]) GetPlayerLimit() int {
|
|
||||||
return slf.playerLimit
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPlayer 根据玩家id获取玩家
|
|
||||||
func (slf *Room[PlayerID, Player]) GetPlayer(id PlayerID) Player {
|
|
||||||
return slf.players.Get(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPlayers 获取所有玩家
|
|
||||||
func (slf *Room[PlayerID, Player]) GetPlayers() map[PlayerID]Player {
|
|
||||||
return slf.players.Map()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPlayerCount 获取玩家数量
|
|
||||||
func (slf *Room[PlayerID, Player]) GetPlayerCount() int {
|
|
||||||
return slf.players.Size()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsExistPlayer 房间内是否存在某玩家
|
|
||||||
func (slf *Room[PlayerID, Player]) IsExistPlayer(id PlayerID) bool {
|
|
||||||
return slf.players.Exist(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOwner 检查特定玩家是否是房主
|
|
||||||
// - 当房间为无主模式(WithRoomNoMaster)时,将会始终返回false
|
|
||||||
func (slf *Room[PlayerID, Player]) IsOwner(id PlayerID) bool {
|
|
||||||
return !slf.noMaster && slf.owner == id
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeOwner 改变房主
|
|
||||||
// - 当房间为无主模式(WithRoomNoMaster)时,将不会发生任何变化
|
|
||||||
func (slf *Room[PlayerID, Player]) ChangeOwner(id PlayerID) {
|
|
||||||
if slf.noMaster || slf.owner == id {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
slf.owner = id
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join 控制玩家加入到该房间
|
|
||||||
func (slf *Room[PlayerID, Player]) Join(player Player) error {
|
|
||||||
playerId := player.GetID()
|
|
||||||
exist := slf.players.Exist(playerId)
|
|
||||||
if !exist && slf.players.Size() >= slf.playerLimit && slf.playerLimit > 0 {
|
|
||||||
return ErrRoomPlayerLimit
|
|
||||||
}
|
|
||||||
slf.players.Set(playerId, player)
|
|
||||||
if !exist {
|
|
||||||
log.Debug("Room.Join", log.Any("guid", slf.GetGuid()), log.Any("player", playerId))
|
|
||||||
if slf.players.Size() == 1 && !slf.noMaster {
|
|
||||||
slf.owner = playerId
|
|
||||||
}
|
|
||||||
slf.OnPlayerJoinRoomEvent(player)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leave 控制玩家离开房间
|
|
||||||
func (slf *Room[PlayerID, Player]) Leave(id PlayerID) {
|
|
||||||
player, exist := slf.players.GetExist(id)
|
|
||||||
if !exist {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Debug("Room.Leave", log.Any("guid", slf.GetGuid()), log.Any("player", id))
|
|
||||||
slf.OnPlayerLeaveRoomEvent(player)
|
|
||||||
slf.players.Delete(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// KickOut 以某种原因踢出特定玩家
|
|
||||||
// - 当设置了房间踢出玩家的检查处理函数(WithRoomKickPlayerCheckHandle)时,将会根据检查结果进行处理,即便是无主模式。其他情况如下
|
|
||||||
// - 如果是无主模式(WithRoomNoMaster),将会返回错误
|
|
||||||
// - 如果不是房主发起的踢出玩家,将会返回错误
|
|
||||||
func (slf *Room[PlayerID, Player]) KickOut(id, target PlayerID, reason string) error {
|
|
||||||
player, exist := slf.players.GetExist(target)
|
|
||||||
if !exist {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if slf.kickCheckHandle != nil {
|
|
||||||
if err := slf.kickCheckHandle(slf, id, target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if slf.noMaster {
|
|
||||||
return ErrRoomNoHasMaster
|
|
||||||
} else if slf.owner != id {
|
|
||||||
return ErrRoomNotIsOwner
|
|
||||||
}
|
|
||||||
|
|
||||||
slf.OnPlayerKickedOutEvent(id, target, reason)
|
|
||||||
slf.Leave(player.GetID())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegPlayerJoinRoomEvent 玩家进入房间时将立即执行被注册的事件处理函数
|
|
||||||
func (slf *Room[PlayerID, Player]) RegPlayerJoinRoomEvent(handle game.PlayerJoinRoomEventHandle[PlayerID, Player]) {
|
|
||||||
slf.playerJoinRoomEventHandles = append(slf.playerJoinRoomEventHandles, handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *Room[PlayerID, Player]) OnPlayerJoinRoomEvent(player Player) {
|
|
||||||
for _, handle := range slf.playerJoinRoomEventHandles {
|
|
||||||
handle(slf, player)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegPlayerLeaveRoomEvent 玩家离开房间时将立即执行被注册的事件处理函数
|
|
||||||
func (slf *Room[PlayerID, Player]) RegPlayerLeaveRoomEvent(handle game.PlayerLeaveRoomEventHandle[PlayerID, Player]) {
|
|
||||||
slf.playerLeaveRoomEventHandles = append(slf.playerLeaveRoomEventHandles, handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *Room[PlayerID, Player]) OnPlayerLeaveRoomEvent(player Player) {
|
|
||||||
for _, handle := range slf.playerLeaveRoomEventHandles {
|
|
||||||
handle(slf, player)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegPlayerKickedOutEvent 当玩家被踢出游戏时将立即执行被注册的事件处理函数
|
|
||||||
func (slf *Room[PlayerID, Player]) RegPlayerKickedOutEvent(handle game.PlayerKickedOutEventHandle[PlayerID, Player]) {
|
|
||||||
slf.playerKickedOutEventHandles = append(slf.playerKickedOutEventHandles, handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *Room[PlayerID, Player]) OnPlayerKickedOutEvent(executor, kicked PlayerID, reason string) {
|
|
||||||
for _, handle := range slf.playerKickedOutEventHandles {
|
|
||||||
handle(slf, executor, kicked, reason)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrRoomPlayerLimit = errors.New("the number of players in the room has reached the upper limit") // 玩家数量达到上限
|
|
||||||
ErrRoomNoHasMaster = errors.New("room not has master, can't kick player")
|
|
||||||
ErrRoomNotIsOwner = errors.New("not is room owner, can't kick player")
|
|
||||||
)
|
|
|
@ -1,34 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kercylan98/minotaur/game"
|
|
||||||
"github.com/kercylan98/minotaur/utils/concurrent"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewRoomManager[PlayerID comparable, Room game.Room[PlayerID, game.Player[PlayerID]]]() *RoomManager[PlayerID, Room] {
|
|
||||||
return &RoomManager[PlayerID, Room]{
|
|
||||||
rooms: concurrent.NewBalanceMap[int64, Room](),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoomManager 房间管理器
|
|
||||||
type RoomManager[PlayerID comparable, Room game.Room[PlayerID, game.Player[PlayerID]]] struct {
|
|
||||||
guid atomic.Int64
|
|
||||||
rooms *concurrent.BalanceMap[int64, Room]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenGuid 生成一个新的房间guid
|
|
||||||
func (slf *RoomManager[PlayerID, Room]) GenGuid() int64 {
|
|
||||||
return slf.guid.Add(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddRoom 添加房间到房间管理器中
|
|
||||||
func (slf *RoomManager[PlayerID, Room]) AddRoom(room Room) {
|
|
||||||
slf.rooms.Set(room.GetGuid(), room)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseRoom 关闭特定guid的房间
|
|
||||||
func (slf *RoomManager[PlayerID, Room]) CloseRoom(guid int64) {
|
|
||||||
slf.rooms.Delete(guid)
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kercylan98/minotaur/game"
|
|
||||||
"github.com/kercylan98/minotaur/utils/concurrent"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RoomOption 房间构建可选项
|
|
||||||
type RoomOption[PlayerID comparable, Player game.Player[PlayerID]] func(room *Room[PlayerID, Player])
|
|
||||||
|
|
||||||
// WithRoomSync 通过线程安全的方式创建房间
|
|
||||||
func WithRoomSync[PlayerID comparable, Player game.Player[PlayerID]]() RoomOption[PlayerID, Player] {
|
|
||||||
return func(room *Room[PlayerID, Player]) {
|
|
||||||
room.players = concurrent.NewBalanceMap[PlayerID, Player]()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRoomPlayerLimit 限制房间的玩家数量上限
|
|
||||||
func WithRoomPlayerLimit[PlayerID comparable, Player game.Player[PlayerID]](playerLimit int) RoomOption[PlayerID, Player] {
|
|
||||||
return func(room *Room[PlayerID, Player]) {
|
|
||||||
room.playerLimit = playerLimit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRoomNoMaster 设置房间为无主的
|
|
||||||
func WithRoomNoMaster[PlayerID comparable, Player game.Player[PlayerID]]() RoomOption[PlayerID, Player] {
|
|
||||||
return func(room *Room[PlayerID, Player]) {
|
|
||||||
room.noMaster = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRoomKickPlayerCheckHandle 设置房间踢出玩家的检查处理函数
|
|
||||||
// - 当没有设置该函数时,如果不是房主,将无法进行踢出
|
|
||||||
func WithRoomKickPlayerCheckHandle[PlayerID comparable, Player game.Player[PlayerID]](handle func(room *Room[PlayerID, Player], id, target PlayerID) error) RoomOption[PlayerID, Player] {
|
|
||||||
return func(room *Room[PlayerID, Player]) {
|
|
||||||
room.kickCheckHandle = handle
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,284 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kercylan98/minotaur/game"
|
|
||||||
"github.com/kercylan98/minotaur/utils/concurrent"
|
|
||||||
"github.com/kercylan98/minotaur/utils/hash"
|
|
||||||
"github.com/kercylan98/minotaur/utils/slice"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewRoomSeat 基于特定游戏房间(game.Room)的实现创建一个支持座位号管理的房间实现(RoomSeat)
|
|
||||||
func NewRoomSeat[PlayerID comparable, Player game.Player[PlayerID]](room game.Room[PlayerID, Player], options ...RoomSeatOption[PlayerID, Player]) *RoomSeat[PlayerID, Player] {
|
|
||||||
roomSeat := &RoomSeat[PlayerID, Player]{
|
|
||||||
Room: room,
|
|
||||||
seatPS: concurrent.NewBalanceMap[PlayerID, int](),
|
|
||||||
}
|
|
||||||
for _, option := range options {
|
|
||||||
option(roomSeat)
|
|
||||||
}
|
|
||||||
return roomSeat
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoomSeat 包含座位号的默认内置房间实现,依赖于游戏房间(game.Room)实现
|
|
||||||
// - 实现了对玩家座位号的管理,分别为自动管理(WithRoomSeatAutoManage)及手工管理,默认清空下为手工管理
|
|
||||||
type RoomSeat[PlayerID comparable, Player game.Player[PlayerID]] struct {
|
|
||||||
game.Room[PlayerID, Player]
|
|
||||||
mutex sync.RWMutex
|
|
||||||
vacancy []int
|
|
||||||
seatPS *concurrent.BalanceMap[PlayerID, int]
|
|
||||||
seatSP []*PlayerID
|
|
||||||
duplicateLock bool
|
|
||||||
fillIn bool
|
|
||||||
autoMode sync.Once
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddSeat 为特定玩家添加座位
|
|
||||||
// - 当座位存在空缺的时候,玩家将会优先在空缺位置坐下,否则将会在末位追加
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddSeatWithAssign 将玩家添加到特定的座位
|
|
||||||
// - 如果位置已经有玩家,将会与其进行更换
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) AddSeatWithAssign(id PlayerID, seat int) {
|
|
||||||
slf.AddSeat(id)
|
|
||||||
_ = slf.SetSeat(id, seat)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemovePlayerSeat 删除玩家座位
|
|
||||||
// - 受补位模式(WithRoomSeatFillIn)影响
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveSeat 删除特定座位的玩家
|
|
||||||
// - 受补位模式(WithRoomSeatFillIn)影响
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSeat 设置玩家的座位号
|
|
||||||
// - 如果玩家没有预先添加过座位将会返回错误
|
|
||||||
// - 如果位置已经有玩家,将会与其进行更换
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) SetSeat(id PlayerID, seat int) error {
|
|
||||||
slf.mutex.Lock()
|
|
||||||
slf.duplicateLock = true
|
|
||||||
defer func() {
|
|
||||||
slf.mutex.Unlock()
|
|
||||||
slf.duplicateLock = false
|
|
||||||
}()
|
|
||||||
oldSeat, err := slf.GetSeat(id)
|
|
||||||
if err != nil {
|
|
||||||
return 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)
|
|
||||||
} else {
|
|
||||||
maxSeat := len(slf.seatSP) - 1
|
|
||||||
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
|
|
||||||
slf.seatSP = append(slf.seatSP, make([]*PlayerID, count)...)
|
|
||||||
}
|
|
||||||
slf.seatSP[seat] = slf.seatSP[oldSeat]
|
|
||||||
slf.seatSP[oldSeat] = nil
|
|
||||||
slf.seatPS.Set(id, seat)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSeat 获取玩家座位号
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetSeat(id PlayerID) (int, error) {
|
|
||||||
seat, exist := slf.seatPS.GetExist(id)
|
|
||||||
if !exist {
|
|
||||||
return 0, ErrRoomNotHasPlayer
|
|
||||||
}
|
|
||||||
return seat, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPlayerIDWithSeat 获取特定座位号的玩家
|
|
||||||
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 playerId, ErrRoomNotHasPlayer
|
|
||||||
}
|
|
||||||
id := slf.seatSP[seat]
|
|
||||||
if id == nil {
|
|
||||||
return playerId, ErrRoomNotHasPlayer
|
|
||||||
}
|
|
||||||
return *id, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSeatInfo 获取所有座位号
|
|
||||||
// - 在非补位模式(WithRoomSeatFillIn)下由于座位号可能存在缺席的情况,所以需要根据是否为空指针进行判断
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetSeatInfo() []*PlayerID {
|
|
||||||
slf.mutex.RLock()
|
|
||||||
defer slf.mutex.RUnlock()
|
|
||||||
return slf.seatSP
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSeatInfoMap 获取座位号及其对应的玩家信息
|
|
||||||
// - 缺席情况将被忽略
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSeatInfoMapVacancy 获取座位号及其对应的玩家信息
|
|
||||||
// - 缺席情况将不会被忽略
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetSeatInfoMapVacancy() map[int]*PlayerID {
|
|
||||||
slf.mutex.RLock()
|
|
||||||
defer slf.mutex.RUnlock()
|
|
||||||
return hash.ToMap(slf.seatSP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSeatInfoWithPlayerIDMap 获取玩家及其座位号信息
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetSeatInfoWithPlayerIDMap() map[PlayerID]int {
|
|
||||||
return slf.seatPS.Map()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFirstSeat 获取第一个未缺席的座位号
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetFirstSeat() int {
|
|
||||||
for seat, playerId := range slf.seatSP {
|
|
||||||
if playerId != nil {
|
|
||||||
return seat
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNextSeat 获取特定座位号下一个未缺席的座位号
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetNextSeat(seat int) int {
|
|
||||||
l := len(slf.seatSP)
|
|
||||||
if l == 0 || seat >= l || seat < 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
var target = seat
|
|
||||||
for {
|
|
||||||
target++
|
|
||||||
if target >= l {
|
|
||||||
target = 0
|
|
||||||
}
|
|
||||||
if target == seat {
|
|
||||||
return seat
|
|
||||||
}
|
|
||||||
if slf.seatSP[target] != nil {
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNextSeatVacancy 获取特定座位号下一个座位号
|
|
||||||
// - 缺席将不会被忽略
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetNextSeatVacancy(seat int) int {
|
|
||||||
l := len(slf.seatSP)
|
|
||||||
if l == 0 || seat >= l || seat < 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
seat++
|
|
||||||
if seat >= l {
|
|
||||||
seat = 0
|
|
||||||
}
|
|
||||||
return seat
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPrevSeat 获取特定座位号上一个未缺席的座位号
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetPrevSeat(seat int) int {
|
|
||||||
l := len(slf.seatSP)
|
|
||||||
if l == 0 || seat >= l || seat < 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
var target = seat
|
|
||||||
for {
|
|
||||||
target--
|
|
||||||
if target < 0 {
|
|
||||||
target = l - 1
|
|
||||||
}
|
|
||||||
if target == seat {
|
|
||||||
return seat
|
|
||||||
}
|
|
||||||
if slf.seatSP[target] != nil {
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPrevSeatVacancy 获取特定座位号上一个座位号
|
|
||||||
// - 缺席将不会被忽略
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) GetPrevSeatVacancy(seat int) int {
|
|
||||||
l := len(slf.seatSP)
|
|
||||||
if l == 0 || seat >= l || seat < 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
seat--
|
|
||||||
if seat < 0 {
|
|
||||||
seat = l - 1
|
|
||||||
}
|
|
||||||
return seat
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) onJoinRoom(room game.Room[PlayerID, Player], player Player) {
|
|
||||||
slf.AddSeat(player.GetID())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (slf *RoomSeat[PlayerID, Player]) onLeaveRoom(room game.Room[PlayerID, Player], player Player) {
|
|
||||||
slf.RemovePlayerSeat(player.GetID())
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrRoomNotHasPlayer = errors.New("player not exist")
|
|
||||||
)
|
|
|
@ -1,26 +0,0 @@
|
||||||
package builtin
|
|
||||||
|
|
||||||
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 通过补位的方式创建带有座位号的房间
|
|
||||||
// - 默认情况下玩家离开座位不会影响其他玩家
|
|
||||||
// - 补位情况下,靠前的玩家离开座位将有后方玩家向前补位
|
|
||||||
func WithRoomSeatFillIn[PlayerID comparable, Player game.Player[PlayerID]]() RoomSeatOption[PlayerID, Player] {
|
|
||||||
return func(seatRoom *RoomSeat[PlayerID, Player]) {
|
|
||||||
seatRoom.fillIn = true
|
|
||||||
}
|
|
||||||
}
|
|
44
game/room.go
44
game/room.go
|
@ -1,44 +0,0 @@
|
||||||
package game
|
|
||||||
|
|
||||||
// Room 房间类似于简版的游戏世界(World),不过没有游戏实体
|
|
||||||
type Room[PlayerID comparable, P Player[PlayerID]] interface {
|
|
||||||
// GetGuid 获取房间的唯一标识符
|
|
||||||
GetGuid() int64
|
|
||||||
// GetPlayerLimit 获取玩家人数上限
|
|
||||||
GetPlayerLimit() int
|
|
||||||
// GetPlayer 根据玩家id获取玩家
|
|
||||||
GetPlayer(id PlayerID) P
|
|
||||||
// GetPlayers 获取房间中的所有玩家
|
|
||||||
GetPlayers() map[PlayerID]P
|
|
||||||
// GetPlayerCount 获取玩家数量
|
|
||||||
GetPlayerCount() int
|
|
||||||
// IsExistPlayer 检查房间中是否存在特定玩家
|
|
||||||
IsExistPlayer(id PlayerID) bool
|
|
||||||
// IsOwner 检查玩家是否是房主
|
|
||||||
IsOwner(id PlayerID) bool
|
|
||||||
// ChangeOwner 设置玩家为房主
|
|
||||||
ChangeOwner(id PlayerID)
|
|
||||||
|
|
||||||
// Join 使特定玩家加入房间
|
|
||||||
Join(player P) error
|
|
||||||
// Leave 使特定玩家离开房间
|
|
||||||
Leave(id PlayerID)
|
|
||||||
// KickOut 将特定玩家踢出房间
|
|
||||||
KickOut(id, target PlayerID, reason string) error
|
|
||||||
|
|
||||||
// RegPlayerJoinRoomEvent 玩家进入房间时将立即执行被注册的事件处理函数
|
|
||||||
RegPlayerJoinRoomEvent(handle PlayerJoinRoomEventHandle[PlayerID, P])
|
|
||||||
OnPlayerJoinRoomEvent(player P)
|
|
||||||
// RegPlayerLeaveRoomEvent 玩家离开房间时将立即执行被注册的事件处理函数
|
|
||||||
RegPlayerLeaveRoomEvent(handle PlayerLeaveRoomEventHandle[PlayerID, P])
|
|
||||||
OnPlayerLeaveRoomEvent(player P)
|
|
||||||
// RegPlayerKickedOutEvent 当玩家被踢出游戏时将立即执行被注册的事件处理函数
|
|
||||||
RegPlayerKickedOutEvent(handle PlayerKickedOutEventHandle[PlayerID, P])
|
|
||||||
OnPlayerKickedOutEvent(executor, kicked PlayerID, reason string)
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
|
||||||
PlayerJoinRoomEventHandle[ID comparable, P Player[ID]] func(room Room[ID, P], player P)
|
|
||||||
PlayerLeaveRoomEventHandle[ID comparable, P Player[ID]] func(room Room[ID, P], player P)
|
|
||||||
PlayerKickedOutEventHandle[ID comparable, P Player[ID]] func(room Room[ID, P], executor, kicked ID, reason string)
|
|
||||||
)
|
|
|
@ -4,26 +4,26 @@ import "github.com/kercylan98/minotaur/game"
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// PlayerJoinRoomEventHandle 玩家加入房间事件处理函数
|
// PlayerJoinRoomEventHandle 玩家加入房间事件处理函数
|
||||||
PlayerJoinRoomEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P)
|
PlayerJoinRoomEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, player P)
|
||||||
// PlayerLeaveRoomEventHandle 玩家离开房间事件处理函数
|
// PlayerLeaveRoomEventHandle 玩家离开房间事件处理函数
|
||||||
PlayerLeaveRoomEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P)
|
PlayerLeaveRoomEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, player P)
|
||||||
// PlayerKickedOutEventHandle 玩家被踢出房间事件处理函数
|
// PlayerKickedOutEventHandle 玩家被踢出房间事件处理函数
|
||||||
PlayerKickedOutEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, executor, kicked P, reason string)
|
PlayerKickedOutEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, executor, kicked P, reason string)
|
||||||
// PlayerUpgradeOwnerEventHandle 玩家成为房主事件处理函数
|
// PlayerUpgradeOwnerEventHandle 玩家成为房主事件处理函数
|
||||||
PlayerUpgradeOwnerEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, oldOwner, newOwner P)
|
PlayerUpgradeOwnerEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, oldOwner, newOwner P)
|
||||||
// CancelOwnerEventHandle 取消房主事件处理函数
|
// CancelOwnerEventHandle 取消房主事件处理函数
|
||||||
CancelOwnerEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, oldOwner P)
|
CancelOwnerEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, oldOwner P)
|
||||||
// ChangePlayerLimitEventHandle 改变房间人数上限事件处理函数
|
// ChangePlayerLimitEventHandle 改变房间人数上限事件处理函数
|
||||||
ChangePlayerLimitEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, oldLimit, newLimit int)
|
ChangePlayerLimitEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, oldLimit, newLimit int)
|
||||||
// PlayerSeatChangeEventHandle 玩家座位改变事件处理函数
|
// PlayerSeatChangeEventHandle 玩家座位改变事件处理函数
|
||||||
PlayerSeatChangeEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P, oldSeat, newSeat int)
|
PlayerSeatChangeEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, player P, oldSeat, newSeat int)
|
||||||
// PlayerSeatSetEventHandle 玩家座位设置事件处理函数
|
// PlayerSeatSetEventHandle 玩家座位设置事件处理函数
|
||||||
PlayerSeatSetEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P, seat int)
|
PlayerSeatSetEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, player P, seat int)
|
||||||
// PlayerSeatCancelEventHandle 玩家座位取消事件处理函数
|
// PlayerSeatCancelEventHandle 玩家座位取消事件处理函数
|
||||||
PlayerSeatCancelEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P, seat int)
|
PlayerSeatCancelEventHandle[PID comparable, P game.Player[PID], R Room] func(room R, player P, seat int)
|
||||||
)
|
)
|
||||||
|
|
||||||
func newEvent[PID comparable, P game.Player[PID], R Room[PID, P]]() *event[PID, P, R] {
|
func newEvent[PID comparable, P game.Player[PID], R Room]() *event[PID, P, R] {
|
||||||
return &event[PID, P, R]{
|
return &event[PID, P, R]{
|
||||||
playerJoinRoomEventRoomHandles: make(map[int64][]PlayerJoinRoomEventHandle[PID, P, R]),
|
playerJoinRoomEventRoomHandles: make(map[int64][]PlayerJoinRoomEventHandle[PID, P, R]),
|
||||||
playerLeaveRoomEventRoomHandles: make(map[int64][]PlayerLeaveRoomEventHandle[PID, P, R]),
|
playerLeaveRoomEventRoomHandles: make(map[int64][]PlayerLeaveRoomEventHandle[PID, P, R]),
|
||||||
|
@ -36,7 +36,7 @@ func newEvent[PID comparable, P game.Player[PID], R Room[PID, P]]() *event[PID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type event[PID comparable, P game.Player[PID], R Room[PID, P]] struct {
|
type event[PID comparable, P game.Player[PID], R Room] struct {
|
||||||
playerJoinRoomEventHandles []PlayerJoinRoomEventHandle[PID, P, R]
|
playerJoinRoomEventHandles []PlayerJoinRoomEventHandle[PID, P, R]
|
||||||
playerJoinRoomEventRoomHandles map[int64][]PlayerJoinRoomEventHandle[PID, P, R]
|
playerJoinRoomEventRoomHandles map[int64][]PlayerJoinRoomEventHandle[PID, P, R]
|
||||||
playerLeaveRoomEventHandles []PlayerLeaveRoomEventHandle[PID, P, R]
|
playerLeaveRoomEventHandles []PlayerLeaveRoomEventHandle[PID, P, R]
|
||||||
|
|
|
@ -2,7 +2,7 @@ package room
|
||||||
|
|
||||||
import "github.com/kercylan98/minotaur/game"
|
import "github.com/kercylan98/minotaur/game"
|
||||||
|
|
||||||
type info[PlayerID comparable, P game.Player[PlayerID], R Room[PlayerID, P]] struct {
|
type info[PlayerID comparable, P game.Player[PlayerID], R Room] struct {
|
||||||
room R
|
room R
|
||||||
playerLimit int // 玩家人数上限, <= 0 表示无限制
|
playerLimit int // 玩家人数上限, <= 0 表示无限制
|
||||||
owner *PlayerID // 房主
|
owner *PlayerID // 房主
|
||||||
|
|
|
@ -3,10 +3,11 @@ package room
|
||||||
import (
|
import (
|
||||||
"github.com/kercylan98/minotaur/game"
|
"github.com/kercylan98/minotaur/game"
|
||||||
"github.com/kercylan98/minotaur/utils/concurrent"
|
"github.com/kercylan98/minotaur/utils/concurrent"
|
||||||
|
"github.com/kercylan98/minotaur/utils/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewManager 创建房间管理器
|
// NewManager 创建房间管理器
|
||||||
func NewManager[PID comparable, P game.Player[PID], R Room[PID, P]]() *Manager[PID, P, R] {
|
func NewManager[PID comparable, P game.Player[PID], R Room]() *Manager[PID, P, R] {
|
||||||
manager := &Manager[PID, P, R]{
|
manager := &Manager[PID, P, R]{
|
||||||
event: newEvent[PID, P, R](),
|
event: newEvent[PID, P, R](),
|
||||||
rooms: concurrent.NewBalanceMap[int64, *info[PID, P, R]](),
|
rooms: concurrent.NewBalanceMap[int64, *info[PID, P, R]](),
|
||||||
|
@ -18,7 +19,7 @@ func NewManager[PID comparable, P game.Player[PID], R Room[PID, P]]() *Manager[P
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manager 房间管理器
|
// Manager 房间管理器
|
||||||
type Manager[PID comparable, P game.Player[PID], R Room[PID, P]] struct {
|
type Manager[PID comparable, P game.Player[PID], R Room] struct {
|
||||||
*event[PID, P, R]
|
*event[PID, P, R]
|
||||||
rooms *concurrent.BalanceMap[int64, *info[PID, P, R]] // 所有房间
|
rooms *concurrent.BalanceMap[int64, *info[PID, P, R]] // 所有房间
|
||||||
players *concurrent.BalanceMap[PID, P] // 所有加入房间的玩家
|
players *concurrent.BalanceMap[PID, P] // 所有加入房间的玩家
|
||||||
|
@ -78,7 +79,7 @@ func (slf *Manager[PID, P, R]) CancelOwner(roomId int64) {
|
||||||
info.owner = nil
|
info.owner = nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if oldOwner != nil {
|
if !generic.IsNil(oldOwner) {
|
||||||
slf.OnCancelOwnerEvent(room, oldOwner)
|
slf.OnCancelOwnerEvent(room, oldOwner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +100,7 @@ func (slf *Manager[PID, P, R]) SetOwner(roomId int64, owner PID) error {
|
||||||
oldOwner = slf.GetRoomPlayer(roomId, *info.owner)
|
oldOwner = slf.GetRoomPlayer(roomId, *info.owner)
|
||||||
}
|
}
|
||||||
newOwner = slf.GetRoomPlayer(roomId, owner)
|
newOwner = slf.GetRoomPlayer(roomId, owner)
|
||||||
if newOwner == nil {
|
if generic.IsNil(newOwner) {
|
||||||
err = ErrRoomOrPlayerNotExist
|
err = ErrRoomOrPlayerNotExist
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -270,7 +271,7 @@ func (slf *Manager[PID, P, R]) Leave(roomId int64, player P) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join 使玩家加入房间
|
// Join 使玩家加入房间
|
||||||
func (slf *Manager[PID, P, R]) Join(player P, roomId int64) error {
|
func (slf *Manager[PID, P, R]) Join(roomId int64, player P) error {
|
||||||
var err error
|
var err error
|
||||||
var roomInfo *info[PID, P, R]
|
var roomInfo *info[PID, P, R]
|
||||||
slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) {
|
slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) {
|
||||||
|
@ -315,12 +316,12 @@ func (slf *Manager[PID, P, R]) KickOut(roomId int64, executor, kicked PID, reaso
|
||||||
var executorPlayer, kickedPlayer P
|
var executorPlayer, kickedPlayer P
|
||||||
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
executorPlayer, kickedPlayer = slf.GetRoomPlayer(roomId, executor), slf.GetRoomPlayer(roomId, kicked)
|
executorPlayer, kickedPlayer = slf.GetRoomPlayer(roomId, executor), slf.GetRoomPlayer(roomId, kicked)
|
||||||
if executorPlayer == nil || kickedPlayer == nil {
|
if generic.IsHasNil(executorPlayer, kickedPlayer) {
|
||||||
err = ErrRoomOrPlayerNotExist
|
err = ErrRoomOrPlayerNotExist
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
room = slf.rooms.Get(roomId).room
|
room = slf.rooms.Get(roomId).room
|
||||||
if room == nil {
|
if generic.IsNil(room) {
|
||||||
err = ErrRoomNotExist
|
err = ErrRoomNotExist
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,7 @@
|
||||||
package room
|
package room
|
||||||
|
|
||||||
import "github.com/kercylan98/minotaur/game"
|
|
||||||
|
|
||||||
// Room 房间类似于简版的游戏世界(World),不过没有游戏实体
|
// Room 房间类似于简版的游戏世界(World),不过没有游戏实体
|
||||||
type Room[PlayerID comparable, P game.Player[PlayerID]] interface {
|
type Room interface {
|
||||||
// GetGuid 获取房间的唯一标识符
|
// GetGuid 获取房间的唯一标识符
|
||||||
GetGuid() int64
|
GetGuid() int64
|
||||||
// GetPlayerLimit 获取玩家人数上限
|
|
||||||
GetPlayerLimit() int
|
|
||||||
// GetPlayer 根据玩家id获取玩家
|
|
||||||
GetPlayer(id PlayerID) P
|
|
||||||
// GetPlayers 获取房间中的所有玩家
|
|
||||||
GetPlayers() map[PlayerID]P
|
|
||||||
// GetPlayerCount 获取玩家数量
|
|
||||||
GetPlayerCount() int
|
|
||||||
// IsExistPlayer 检查房间中是否存在特定玩家
|
|
||||||
IsExistPlayer(id PlayerID) bool
|
|
||||||
// IsOwner 检查玩家是否是房主
|
|
||||||
IsOwner(id PlayerID) bool
|
|
||||||
// ChangeOwner 设置玩家为房主
|
|
||||||
ChangeOwner(id PlayerID)
|
|
||||||
|
|
||||||
// Join 使特定玩家加入房间
|
|
||||||
Join(player P) error
|
|
||||||
// Leave 使特定玩家离开房间
|
|
||||||
Leave(id PlayerID)
|
|
||||||
// KickOut 将特定玩家踢出房间
|
|
||||||
KickOut(id, target PlayerID, reason string) error
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newSeat[PlayerID comparable, P game.Player[PlayerID], R Room[PlayerID, P]](manager *Manager[PlayerID, P, R], room R, event *event[PlayerID, P, R]) *Seat[PlayerID, P, R] {
|
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]{
|
roomSeat := &Seat[PlayerID, P, R]{
|
||||||
manager: manager,
|
manager: manager,
|
||||||
room: room,
|
room: room,
|
||||||
|
@ -18,7 +18,7 @@ func newSeat[PlayerID comparable, P game.Player[PlayerID], R Room[PlayerID, P]](
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seat 房间座位信息
|
// Seat 房间座位信息
|
||||||
type Seat[PlayerID comparable, P game.Player[PlayerID], R Room[PlayerID, P]] struct {
|
type Seat[PlayerID comparable, P game.Player[PlayerID], R Room] struct {
|
||||||
manager *Manager[PlayerID, P, R]
|
manager *Manager[PlayerID, P, R]
|
||||||
room R
|
room R
|
||||||
event *event[PlayerID, P, R]
|
event *event[PlayerID, P, R]
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
package game
|
|
||||||
|
|
||||||
// RoomSeat 带有座位号的房间实现
|
|
||||||
type RoomSeat[PlayerID comparable, P Player[PlayerID]] interface {
|
|
||||||
Room[PlayerID, P]
|
|
||||||
// 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)
|
|
||||||
// GetPlayerIDWithSeat 根据座位号获取玩家ID
|
|
||||||
GetPlayerIDWithSeat(seat int) (PlayerID, error)
|
|
||||||
// GetSeatInfo 获取座位信息,空缺的位置将为空
|
|
||||||
GetSeatInfo() []*PlayerID
|
|
||||||
// GetSeatInfoMap 以map的方式获取座位号
|
|
||||||
GetSeatInfoMap() map[int]PlayerID
|
|
||||||
// GetSeatInfoMapVacancy 以map的方式获取座位号,空缺的位置将被保留为nil
|
|
||||||
GetSeatInfoMapVacancy() map[int]*PlayerID
|
|
||||||
// GetSeatInfoWithPlayerIDMap 获取座位信息,将以玩家ID作为key
|
|
||||||
GetSeatInfoWithPlayerIDMap() map[PlayerID]int
|
|
||||||
// GetFirstSeat 获取第一个非空缺座位号,不存在时将返回-1
|
|
||||||
GetFirstSeat() int
|
|
||||||
// GetNextSeat 获取下一个座位号,空缺的位置将会被跳过
|
|
||||||
// - 超出范围将返回-1
|
|
||||||
// - 当没有下一个座位号时将始终返回本身
|
|
||||||
GetNextSeat(seat int) int
|
|
||||||
// GetNextSeatVacancy 获取下一个座位号,空缺的位置将被保留
|
|
||||||
// - 超出范围将返回-1
|
|
||||||
// - 当没有下一个座位号时将始终返回本身
|
|
||||||
GetNextSeatVacancy(seat int) int
|
|
||||||
// GetPrevSeat 获取上一个座位号,空缺的位置将会被跳过
|
|
||||||
// - 超出范围将返回-1
|
|
||||||
// - 当没有上一个座位号时将始终返回本身
|
|
||||||
GetPrevSeat(seat int) int
|
|
||||||
// GetPrevSeatVacancy 获取上一个座位号,空缺的位置将被保留
|
|
||||||
// - 超出范围将返回-1
|
|
||||||
// - 当没有上一个座位号时将始终返回本身
|
|
||||||
GetPrevSeatVacancy(seat int) int
|
|
||||||
}
|
|
Loading…
Reference in New Issue