feat: room 包添加更多的事件,添加座位号支持
This commit is contained in:
parent
9fcc75e0d7
commit
c8f181f63e
|
@ -7,6 +7,8 @@ var (
|
||||||
ErrRoomNotExist = errors.New("room not exist")
|
ErrRoomNotExist = errors.New("room not exist")
|
||||||
// ErrRoomPlayerFull 房间人数已满
|
// ErrRoomPlayerFull 房间人数已满
|
||||||
ErrRoomPlayerFull = errors.New("room player full")
|
ErrRoomPlayerFull = errors.New("room player full")
|
||||||
// ErrPlayerNotExist 玩家不存在
|
// ErrPlayerNotInRoom 玩家不在房间中
|
||||||
ErrPlayerNotExist = errors.New("player not exist")
|
ErrPlayerNotInRoom = errors.New("player not in room")
|
||||||
|
// ErrRoomOrPlayerNotExist 房间不存在或玩家不在房间中
|
||||||
|
ErrRoomOrPlayerNotExist = errors.New("room or player not exist")
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,30 +8,65 @@ type (
|
||||||
// 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[PID, P]] func(room R, player P)
|
||||||
// PlayerKickedOutEventHandle 玩家被踢出房间事件处理函数
|
// PlayerKickedOutEventHandle 玩家被踢出房间事件处理函数
|
||||||
PlayerKickedOutEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, executor, kicked PID, reason string)
|
PlayerKickedOutEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, executor, kicked P, reason string)
|
||||||
|
// PlayerUpgradeOwnerEventHandle 玩家成为房主事件处理函数
|
||||||
|
PlayerUpgradeOwnerEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, oldOwner, newOwner P)
|
||||||
|
// CancelOwnerEventHandle 取消房主事件处理函数
|
||||||
|
CancelOwnerEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, oldOwner P)
|
||||||
|
// ChangePlayerLimitEventHandle 改变房间人数上限事件处理函数
|
||||||
|
ChangePlayerLimitEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, oldLimit, newLimit int)
|
||||||
|
// PlayerSeatChangeEventHandle 玩家座位改变事件处理函数
|
||||||
|
PlayerSeatChangeEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P, oldSeat, newSeat int)
|
||||||
|
// PlayerSeatSetEventHandle 玩家座位设置事件处理函数
|
||||||
|
PlayerSeatSetEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P, seat int)
|
||||||
|
// PlayerSeatCancelEventHandle 玩家座位取消事件处理函数
|
||||||
|
PlayerSeatCancelEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] 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[PID, P]]() *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]),
|
||||||
playerKickedOutEventRoomHandles: make(map[int64][]PlayerKickedOutEventHandle[PID, P, R]),
|
playerKickedOutEventRoomHandles: make(map[int64][]PlayerKickedOutEventHandle[PID, P, R]),
|
||||||
|
playerUpgradeOwnerEventRoomHandles: make(map[int64][]PlayerUpgradeOwnerEventHandle[PID, P, R]),
|
||||||
|
cancelOwnerEventRoomHandles: make(map[int64][]CancelOwnerEventHandle[PID, P, R]),
|
||||||
|
changePlayerLimitEventRoomHandles: make(map[int64][]ChangePlayerLimitEventHandle[PID, P, R]),
|
||||||
|
playerSeatChangeEventRoomHandles: make(map[int64][]PlayerSeatChangeEventHandle[PID, P, R]),
|
||||||
|
playerSeatSetEventRoomHandles: make(map[int64][]PlayerSeatSetEventHandle[PID, P, R]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type event[PID comparable, P game.Player[PID], R Room[PID, P]] struct {
|
type event[PID comparable, P game.Player[PID], R Room[PID, P]] 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]
|
||||||
playerLeaveRoomEventRoomHandles map[int64][]PlayerLeaveRoomEventHandle[PID, P, R]
|
playerLeaveRoomEventRoomHandles map[int64][]PlayerLeaveRoomEventHandle[PID, P, R]
|
||||||
playerKickedOutEventHandles []PlayerKickedOutEventHandle[PID, P, R]
|
playerKickedOutEventHandles []PlayerKickedOutEventHandle[PID, P, R]
|
||||||
playerKickedOutEventRoomHandles map[int64][]PlayerKickedOutEventHandle[PID, P, R]
|
playerKickedOutEventRoomHandles map[int64][]PlayerKickedOutEventHandle[PID, P, R]
|
||||||
|
playerUpgradeOwnerEventHandles []PlayerUpgradeOwnerEventHandle[PID, P, R]
|
||||||
|
playerUpgradeOwnerEventRoomHandles map[int64][]PlayerUpgradeOwnerEventHandle[PID, P, R]
|
||||||
|
cancelOwnerEventHandles []CancelOwnerEventHandle[PID, P, R]
|
||||||
|
cancelOwnerEventRoomHandles map[int64][]CancelOwnerEventHandle[PID, P, R]
|
||||||
|
changePlayerLimitEventHandles []ChangePlayerLimitEventHandle[PID, P, R]
|
||||||
|
changePlayerLimitEventRoomHandles map[int64][]ChangePlayerLimitEventHandle[PID, P, R]
|
||||||
|
playerSeatChangeEventHandles []PlayerSeatChangeEventHandle[PID, P, R]
|
||||||
|
playerSeatChangeEventRoomHandles map[int64][]PlayerSeatChangeEventHandle[PID, P, R]
|
||||||
|
playerSeatSetEventHandles []PlayerSeatSetEventHandle[PID, P, R]
|
||||||
|
playerSeatSetEventRoomHandles map[int64][]PlayerSeatSetEventHandle[PID, P, R]
|
||||||
|
playerSeatCancelEventHandles []PlayerSeatCancelEventHandle[PID, P, R]
|
||||||
|
playerSeatCancelEventRoomHandles map[int64][]PlayerSeatCancelEventHandle[PID, P, R]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *event[PID, P, R]) unReg(guid int64) {
|
func (slf *event[PID, P, R]) unReg(guid int64) {
|
||||||
delete(slf.playerJoinRoomEventRoomHandles, guid)
|
delete(slf.playerJoinRoomEventRoomHandles, guid)
|
||||||
delete(slf.playerLeaveRoomEventRoomHandles, guid)
|
delete(slf.playerLeaveRoomEventRoomHandles, guid)
|
||||||
delete(slf.playerKickedOutEventRoomHandles, guid)
|
delete(slf.playerKickedOutEventRoomHandles, guid)
|
||||||
|
delete(slf.playerUpgradeOwnerEventRoomHandles, guid)
|
||||||
|
delete(slf.cancelOwnerEventRoomHandles, guid)
|
||||||
|
delete(slf.changePlayerLimitEventRoomHandles, guid)
|
||||||
|
delete(slf.playerSeatChangeEventRoomHandles, guid)
|
||||||
|
delete(slf.playerSeatSetEventRoomHandles, guid)
|
||||||
|
delete(slf.playerSeatCancelEventRoomHandles, guid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegPlayerJoinRoomEvent 玩家进入房间时将立即执行被注册的事件处理函数
|
// RegPlayerJoinRoomEvent 玩家进入房间时将立即执行被注册的事件处理函数
|
||||||
|
@ -85,7 +120,7 @@ func (slf *event[PID, P, R]) RegPlayerKickedOutEventWithRoom(room R, handle Play
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnPlayerKickedOutEvent 玩家被踢出房间时将立即执行被注册的事件处理函数
|
// OnPlayerKickedOutEvent 玩家被踢出房间时将立即执行被注册的事件处理函数
|
||||||
func (slf *event[PID, P, R]) OnPlayerKickedOutEvent(room R, executor, kicked PID, reason string) {
|
func (slf *event[PID, P, R]) OnPlayerKickedOutEvent(room R, executor, kicked P, reason string) {
|
||||||
for _, handle := range slf.playerKickedOutEventHandles {
|
for _, handle := range slf.playerKickedOutEventHandles {
|
||||||
handle(room, executor, kicked, reason)
|
handle(room, executor, kicked, reason)
|
||||||
}
|
}
|
||||||
|
@ -93,3 +128,123 @@ func (slf *event[PID, P, R]) OnPlayerKickedOutEvent(room R, executor, kicked PID
|
||||||
handle(room, executor, kicked, reason)
|
handle(room, executor, kicked, reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegPlayerUpgradeOwnerEvent 玩家成为房主时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerUpgradeOwnerEvent(handle PlayerUpgradeOwnerEventHandle[PID, P, R]) {
|
||||||
|
slf.playerUpgradeOwnerEventHandles = append(slf.playerUpgradeOwnerEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerUpgradeOwnerEventWithRoom 玩家成为房主时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerUpgradeOwnerEventWithRoom(room R, handle PlayerUpgradeOwnerEventHandle[PID, P, R]) {
|
||||||
|
slf.playerUpgradeOwnerEventRoomHandles[room.GetGuid()] = append(slf.playerUpgradeOwnerEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnPlayerUpgradeOwnerEvent 玩家成为房主时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnPlayerUpgradeOwnerEvent(room R, executor, newOwner P) {
|
||||||
|
for _, handle := range slf.playerUpgradeOwnerEventHandles {
|
||||||
|
handle(room, executor, newOwner)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.playerUpgradeOwnerEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, executor, newOwner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegCancelOwnerEvent 取消房主时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegCancelOwnerEvent(handle CancelOwnerEventHandle[PID, P, R]) {
|
||||||
|
slf.cancelOwnerEventHandles = append(slf.cancelOwnerEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegCancelOwnerEventWithRoom 取消房主时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegCancelOwnerEventWithRoom(room R, handle CancelOwnerEventHandle[PID, P, R]) {
|
||||||
|
slf.cancelOwnerEventRoomHandles[room.GetGuid()] = append(slf.cancelOwnerEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnCancelOwnerEvent 取消房主时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnCancelOwnerEvent(room R, oldOwner P) {
|
||||||
|
for _, handle := range slf.cancelOwnerEventHandles {
|
||||||
|
handle(room, oldOwner)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.cancelOwnerEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, oldOwner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegChangePlayerLimitEvent 修改玩家上限时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegChangePlayerLimitEvent(handle ChangePlayerLimitEventHandle[PID, P, R]) {
|
||||||
|
slf.changePlayerLimitEventHandles = append(slf.changePlayerLimitEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegChangePlayerLimitEventWithRoom 修改玩家上限时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegChangePlayerLimitEventWithRoom(room R, handle ChangePlayerLimitEventHandle[PID, P, R]) {
|
||||||
|
slf.changePlayerLimitEventRoomHandles[room.GetGuid()] = append(slf.changePlayerLimitEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnChangePlayerLimitEvent 修改玩家上限时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnChangePlayerLimitEvent(room R, oldLimit, newLimit int) {
|
||||||
|
for _, handle := range slf.changePlayerLimitEventHandles {
|
||||||
|
handle(room, oldLimit, newLimit)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.changePlayerLimitEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, oldLimit, newLimit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerSeatChangeEvent 玩家座位改变时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerSeatChangeEvent(handle PlayerSeatChangeEventHandle[PID, P, R]) {
|
||||||
|
slf.playerSeatChangeEventHandles = append(slf.playerSeatChangeEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerSeatChangeEventWithRoom 玩家座位改变时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerSeatChangeEventWithRoom(room R, handle PlayerSeatChangeEventHandle[PID, P, R]) {
|
||||||
|
slf.playerSeatChangeEventRoomHandles[room.GetGuid()] = append(slf.playerSeatChangeEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnPlayerSeatChangeEvent 玩家座位改变时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnPlayerSeatChangeEvent(room R, player P, oldSeat, newSeat int) {
|
||||||
|
for _, handle := range slf.playerSeatChangeEventHandles {
|
||||||
|
handle(room, player, oldSeat, newSeat)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.playerSeatChangeEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, player, oldSeat, newSeat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerSeatSetEvent 玩家座位设置时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerSeatSetEvent(handle PlayerSeatSetEventHandle[PID, P, R]) {
|
||||||
|
slf.playerSeatSetEventHandles = append(slf.playerSeatSetEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerSeatSetEventWithRoom 玩家座位设置时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerSeatSetEventWithRoom(room R, handle PlayerSeatSetEventHandle[PID, P, R]) {
|
||||||
|
slf.playerSeatSetEventRoomHandles[room.GetGuid()] = append(slf.playerSeatSetEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnPlayerSeatSetEvent 玩家座位设置时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnPlayerSeatSetEvent(room R, player P, seat int) {
|
||||||
|
for _, handle := range slf.playerSeatSetEventHandles {
|
||||||
|
handle(room, player, seat)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.playerSeatSetEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, player, seat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerSeatCancelEvent 玩家座位取消时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerSeatCancelEvent(handle PlayerSeatCancelEventHandle[PID, P, R]) {
|
||||||
|
slf.playerSeatCancelEventHandles = append(slf.playerSeatCancelEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerSeatCancelEventWithRoom 玩家座位取消时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerSeatCancelEventWithRoom(room R, handle PlayerSeatCancelEventHandle[PID, P, R]) {
|
||||||
|
slf.playerSeatCancelEventRoomHandles[room.GetGuid()] = append(slf.playerSeatCancelEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnPlayerSeatCancelEvent 玩家座位取消时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnPlayerSeatCancelEvent(room R, player P, seat int) {
|
||||||
|
for _, handle := range slf.playerSeatCancelEventHandles {
|
||||||
|
handle(room, player, seat)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.playerSeatCancelEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, player, seat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,5 +4,7 @@ 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[PlayerID, P]] struct {
|
||||||
room R
|
room R
|
||||||
playerLimit int // 玩家人数上限, <= 0 表示无限制
|
playerLimit int // 玩家人数上限, <= 0 表示无限制
|
||||||
|
owner *PlayerID // 房主
|
||||||
|
seat *Seat[PlayerID, P, R]
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,10 @@ type Manager[PID comparable, P game.Player[PID], R Room[PID, P]] struct {
|
||||||
|
|
||||||
// CreateRoom 创建房间
|
// CreateRoom 创建房间
|
||||||
func (slf *Manager[PID, P, R]) CreateRoom(room R) {
|
func (slf *Manager[PID, P, R]) CreateRoom(room R) {
|
||||||
roomInfo := &info[PID, P, R]{room: room}
|
roomInfo := &info[PID, P, R]{
|
||||||
|
room: room,
|
||||||
|
seat: newSeat[PID, P, R](slf, room, slf.event),
|
||||||
|
}
|
||||||
slf.rooms.Set(room.GetGuid(), roomInfo)
|
slf.rooms.Set(room.GetGuid(), roomInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +42,73 @@ func (slf *Manager[PID, P, R]) ReleaseRoom(guid int64) {
|
||||||
slf.rooms.Delete(guid)
|
slf.rooms.Delete(guid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPlayerLimit 设置房间人数上限
|
||||||
|
func (slf *Manager[PID, P, R]) SetPlayerLimit(roomId int64, limit int) {
|
||||||
|
if limit <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var room R
|
||||||
|
var oldLimit int
|
||||||
|
slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) {
|
||||||
|
info, ok := m[roomId]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oldLimit = info.playerLimit
|
||||||
|
info.playerLimit = limit
|
||||||
|
})
|
||||||
|
if oldLimit == limit {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slf.OnChangePlayerLimitEvent(room, oldLimit, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOwner 取消房主
|
||||||
|
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]) {
|
||||||
|
info, ok := m[roomId]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
room = info.room
|
||||||
|
if info.owner != nil {
|
||||||
|
oldOwner = slf.GetRoomPlayer(roomId, *info.owner)
|
||||||
|
info.owner = nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if oldOwner != nil {
|
||||||
|
slf.OnCancelOwnerEvent(room, oldOwner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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]) {
|
||||||
|
info, ok := m[roomId]
|
||||||
|
if !ok {
|
||||||
|
err = ErrRoomNotExist
|
||||||
|
return
|
||||||
|
}
|
||||||
|
room = info.room
|
||||||
|
if info.owner != nil {
|
||||||
|
oldOwner = slf.GetRoomPlayer(roomId, *info.owner)
|
||||||
|
}
|
||||||
|
newOwner = slf.GetRoomPlayer(roomId, owner)
|
||||||
|
if newOwner == nil {
|
||||||
|
err = ErrRoomOrPlayerNotExist
|
||||||
|
return
|
||||||
|
}
|
||||||
|
info.owner = &owner
|
||||||
|
})
|
||||||
|
slf.OnPlayerUpgradeOwnerEvent(room, oldOwner, newOwner)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// GetRoom 获取房间
|
// GetRoom 获取房间
|
||||||
func (slf *Manager[PID, P, R]) GetRoom(guid int64) R {
|
func (slf *Manager[PID, P, R]) GetRoom(guid int64) R {
|
||||||
return slf.rooms.Get(guid).room
|
return slf.rooms.Get(guid).room
|
||||||
|
@ -170,32 +240,39 @@ func (slf *Manager[PID, P, R]) GetRoomPlayerLimit(guid int64) int {
|
||||||
|
|
||||||
// Leave 使玩家离开房间
|
// Leave 使玩家离开房间
|
||||||
func (slf *Manager[PID, P, R]) Leave(roomId int64, player P) {
|
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]) {
|
slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) {
|
||||||
room, exist := m[roomId]
|
room, exist := m[roomId]
|
||||||
if !exist {
|
if !exist {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
slf.OnPlayerLeaveRoomEvent(room.room, player)
|
roomInfo = room
|
||||||
slf.pr.Atom(func(m map[PID]map[int64]struct{}) {
|
})
|
||||||
rooms, exist := m[player.GetID()]
|
if roomInfo == nil {
|
||||||
if !exist {
|
return
|
||||||
return
|
}
|
||||||
}
|
slf.OnPlayerLeaveRoomEvent(roomInfo.room, player)
|
||||||
delete(rooms, roomId)
|
roomInfo.seat.removePlayerSeat(player.GetID())
|
||||||
})
|
slf.pr.Atom(func(m map[PID]map[int64]struct{}) {
|
||||||
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
rooms, exist := m[player.GetID()]
|
||||||
players, exist := m[roomId]
|
if !exist {
|
||||||
if !exist {
|
return
|
||||||
return
|
}
|
||||||
}
|
delete(rooms, roomId)
|
||||||
delete(players, player.GetID())
|
})
|
||||||
})
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
|
players, exist := m[roomId]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(players, player.GetID())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join 使玩家加入房间
|
// Join 使玩家加入房间
|
||||||
func (slf *Manager[PID, P, R]) Join(player P, roomId int64) error {
|
func (slf *Manager[PID, P, R]) Join(player P, roomId int64) error {
|
||||||
var err error
|
var err error
|
||||||
|
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]) {
|
||||||
room, exist := m[roomId]
|
room, exist := m[roomId]
|
||||||
if !exist {
|
if !exist {
|
||||||
|
@ -223,8 +300,10 @@ func (slf *Manager[PID, P, R]) Join(player P, roomId int64) error {
|
||||||
players[player.GetID()] = struct{}{}
|
players[player.GetID()] = struct{}{}
|
||||||
})
|
})
|
||||||
slf.players.Set(player.GetID(), player)
|
slf.players.Set(player.GetID(), player)
|
||||||
slf.OnPlayerJoinRoomEvent(room.room, player)
|
roomInfo = room
|
||||||
})
|
})
|
||||||
|
roomInfo.seat.addSeat(player.GetID())
|
||||||
|
slf.OnPlayerJoinRoomEvent(roomInfo.room, player)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,27 +312,38 @@ func (slf *Manager[PID, P, R]) Join(player P, roomId int64) error {
|
||||||
func (slf *Manager[PID, P, R]) KickOut(roomId int64, executor, kicked PID, reason string) error {
|
func (slf *Manager[PID, P, R]) KickOut(roomId int64, executor, kicked PID, reason string) error {
|
||||||
var err error
|
var err error
|
||||||
var room R
|
var room R
|
||||||
|
var executorPlayer, kickedPlayer P
|
||||||
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
players, exist := m[roomId]
|
executorPlayer, kickedPlayer = slf.GetRoomPlayer(roomId, executor), slf.GetRoomPlayer(roomId, kicked)
|
||||||
if !exist {
|
if executorPlayer == nil || kickedPlayer == nil {
|
||||||
err = ErrPlayerNotExist
|
err = ErrRoomOrPlayerNotExist
|
||||||
return
|
|
||||||
}
|
|
||||||
_, exist = players[executor]
|
|
||||||
if !exist {
|
|
||||||
err = ErrPlayerNotExist
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, exist = players[kicked]
|
|
||||||
if !exist {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
room = slf.rooms.Get(roomId).room
|
room = slf.rooms.Get(roomId).room
|
||||||
|
if room == nil {
|
||||||
|
err = ErrRoomNotExist
|
||||||
|
return
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slf.OnPlayerKickedOutEvent(room, executor, kicked, reason)
|
slf.OnPlayerKickedOutEvent(room, executorPlayer, kickedPlayer, reason)
|
||||||
slf.Leave(roomId, slf.players.Get(kicked))
|
slf.Leave(roomId, slf.players.Get(kicked))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSeatInfo 获取座位信息
|
||||||
|
func (slf *Manager[PID, P, R]) GetSeatInfo(roomId int64) (*Seat[PID, P, R], error) {
|
||||||
|
var result *Seat[PID, P, R]
|
||||||
|
var err error
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,249 @@
|
||||||
|
package room
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/game"
|
||||||
|
"github.com/kercylan98/minotaur/utils/concurrent"
|
||||||
|
"github.com/kercylan98/minotaur/utils/hash"
|
||||||
|
"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] {
|
||||||
|
roomSeat := &Seat[PlayerID, P, R]{
|
||||||
|
manager: manager,
|
||||||
|
room: room,
|
||||||
|
event: event,
|
||||||
|
seatPS: concurrent.NewBalanceMap[PlayerID, int](),
|
||||||
|
}
|
||||||
|
return roomSeat
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seat 房间座位信息
|
||||||
|
type Seat[PlayerID comparable, P game.Player[PlayerID], R Room[PlayerID, P]] struct {
|
||||||
|
manager *Manager[PlayerID, P, R]
|
||||||
|
room R
|
||||||
|
event *event[PlayerID, P, R]
|
||||||
|
mutex sync.RWMutex
|
||||||
|
vacancy []int
|
||||||
|
seatPS *concurrent.BalanceMap[PlayerID, int]
|
||||||
|
seatSP []*PlayerID
|
||||||
|
duplicateLock bool
|
||||||
|
autoMode sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
// addSeat 为特定玩家添加座位
|
||||||
|
// - 当座位存在空缺的时候,玩家将会优先在空缺位置坐下,否则将会在末位追加
|
||||||
|
func (slf *Seat[PlayerID, P, R]) addSeat(id PlayerID) {
|
||||||
|
if slf.seatPS.Exist(id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var seat int
|
||||||
|
slf.mutex.Lock()
|
||||||
|
if len(slf.vacancy) > 0 {
|
||||||
|
seat = slf.vacancy[0]
|
||||||
|
slf.vacancy = slf.vacancy[1:]
|
||||||
|
slf.seatPS.Set(id, seat)
|
||||||
|
slf.seatSP[seat] = &id
|
||||||
|
} else {
|
||||||
|
seat = len(slf.seatSP)
|
||||||
|
slf.seatPS.Set(id, seat)
|
||||||
|
slf.seatSP = append(slf.seatSP, &id)
|
||||||
|
}
|
||||||
|
slf.mutex.Unlock()
|
||||||
|
slf.event.OnPlayerSeatSetEvent(slf.room, slf.manager.GetPlayer(id), seat)
|
||||||
|
}
|
||||||
|
|
||||||
|
// removePlayerSeat 删除玩家座位
|
||||||
|
func (slf *Seat[PlayerID, P, R]) removePlayerSeat(id PlayerID) {
|
||||||
|
if !slf.seatPS.Exist(id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slf.event.OnPlayerSeatCancelEvent(slf.room, slf.manager.GetPlayer(id), slf.seatPS.Get(id))
|
||||||
|
slf.mutex.Lock()
|
||||||
|
defer slf.mutex.Unlock()
|
||||||
|
seat := slf.seatPS.DeleteGet(id)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Seat[PlayerID, P, R]) setSeat(id PlayerID, seat int) (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 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)
|
||||||
|
} else {
|
||||||
|
maxSeat := len(slf.seatSP) - 1
|
||||||
|
if seat > maxSeat {
|
||||||
|
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 oldSeat, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSeat 获取玩家座位号
|
||||||
|
func (slf *Seat[PlayerID, P, R]) GetSeat(id PlayerID) (int, error) {
|
||||||
|
seat, exist := slf.seatPS.GetExist(id)
|
||||||
|
if !exist {
|
||||||
|
return 0, ErrPlayerNotInRoom
|
||||||
|
}
|
||||||
|
return seat, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayerIDWithSeat 获取特定座位号的玩家
|
||||||
|
func (slf *Seat[PlayerID, P, R]) 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, ErrPlayerNotInRoom
|
||||||
|
}
|
||||||
|
id := slf.seatSP[seat]
|
||||||
|
if id == nil {
|
||||||
|
return playerId, ErrPlayerNotInRoom
|
||||||
|
}
|
||||||
|
return *id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSeatInfo 获取所有座位号
|
||||||
|
// - 在非补位模式(WithRoomSeatFillIn)下由于座位号可能存在缺席的情况,所以需要根据是否为空指针进行判断
|
||||||
|
func (slf *Seat[PlayerID, P, R]) GetSeatInfo() []*PlayerID {
|
||||||
|
slf.mutex.RLock()
|
||||||
|
defer slf.mutex.RUnlock()
|
||||||
|
return slf.seatSP
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSeatInfoMap 获取座位号及其对应的玩家信息
|
||||||
|
// - 缺席情况将被忽略
|
||||||
|
func (slf *Seat[PlayerID, P, R]) 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 *Seat[PlayerID, P, R]) GetSeatInfoMapVacancy() map[int]*PlayerID {
|
||||||
|
slf.mutex.RLock()
|
||||||
|
defer slf.mutex.RUnlock()
|
||||||
|
return hash.ToMap(slf.seatSP)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSeatInfoWithPlayerIDMap 获取玩家及其座位号信息
|
||||||
|
func (slf *Seat[PlayerID, P, R]) GetSeatInfoWithPlayerIDMap() map[PlayerID]int {
|
||||||
|
return slf.seatPS.Map()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFirstSeat 获取第一个未缺席的座位号
|
||||||
|
func (slf *Seat[PlayerID, P, R]) GetFirstSeat() int {
|
||||||
|
for seat, playerId := range slf.seatSP {
|
||||||
|
if playerId != nil {
|
||||||
|
return seat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNextSeat 获取特定座位号下一个未缺席的座位号
|
||||||
|
func (slf *Seat[PlayerID, P, R]) 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 *Seat[PlayerID, P, R]) 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 *Seat[PlayerID, P, R]) 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 *Seat[PlayerID, P, R]) 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
|
||||||
|
}
|
Loading…
Reference in New Issue