From f084613aa9ba6b24c89110d765cccb75a6dda0e0 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Fri, 5 May 2023 17:25:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=88=BF=E9=97=B4=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/builtin/room.go | 92 ++++++++++++++++++++++++++++++++++++ game/builtin/room_options.go | 13 +++++ game/room.go | 36 ++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 game/builtin/room.go create mode 100644 game/builtin/room_options.go create mode 100644 game/room.go diff --git a/game/builtin/room.go b/game/builtin/room.go new file mode 100644 index 0000000..c6ae16d --- /dev/null +++ b/game/builtin/room.go @@ -0,0 +1,92 @@ +package builtin + +import ( + "go.uber.org/zap" + "minotaur/game" + "minotaur/utils/log" + "minotaur/utils/synchronization" +) + +func NewRoom[PlayerID comparable, Player game.Player[PlayerID]](guid int64) *Room[PlayerID, Player] { + return &Room[PlayerID, Player]{ + guid: guid, + playersConn: synchronization.NewMap[string, Player](), + players: synchronization.NewMap[PlayerID, Player](), + } +} + +type Room[PlayerID comparable, Player game.Player[PlayerID]] struct { + guid int64 + playerLimit int + playersConn *synchronization.Map[string, Player] + players *synchronization.Map[PlayerID, Player] + + playerJoinRoomEventHandles []game.PlayerJoinRoomEventHandle[PlayerID, Player] + playerLeaveRoomEventHandles []game.PlayerLeaveRoomEventHandle[PlayerID, Player] +} + +func (slf *Room[PlayerID, Player]) GetGuid() int64 { + return slf.guid +} + +func (slf *Room[PlayerID, Player]) GetPlayerLimit() int { + return slf.playerLimit +} + +func (slf *Room[PlayerID, Player]) GetPlayerWithConnID(id string) Player { + return slf.playersConn.Get(id) +} + +func (slf *Room[PlayerID, Player]) GetPlayer(id PlayerID) Player { + return slf.players.Get(id) +} + +func (slf *Room[PlayerID, Player]) GetPlayers() synchronization.MapReadonly[PlayerID, Player] { + return slf.players +} + +func (slf *Room[PlayerID, Player]) IsExistPlayer(id PlayerID) bool { + return slf.players.Exist(id) +} + +func (slf *Room[PlayerID, Player]) Join(player Player) error { + if slf.players.Size() >= slf.playerLimit && slf.playerLimit > 0 { + return ErrWorldPlayerLimit + } + log.Debug("Room.Join", zap.Any("guid", slf.GetGuid()), zap.Any("player", player.GetID()), zap.String("conn", player.GetConnID())) + slf.players.Set(player.GetID(), player) + slf.playersConn.Set(player.GetConnID(), player) + slf.OnPlayerJoinRoomEvent(player) + return nil +} + +func (slf *Room[PlayerID, Player]) Leave(id PlayerID) { + player, exist := slf.players.GetExist(id) + if !exist { + return + } + log.Debug("Room.Leave", zap.Any("guid", slf.GetGuid()), zap.Any("player", player.GetID()), zap.String("conn", player.GetConnID())) + slf.OnPlayerLeaveRoomEvent(player) + slf.players.Delete(player.GetID()) + slf.playersConn.Delete(player.GetConnID()) +} + +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) + } +} + +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) + } +} diff --git a/game/builtin/room_options.go b/game/builtin/room_options.go new file mode 100644 index 0000000..7d5251b --- /dev/null +++ b/game/builtin/room_options.go @@ -0,0 +1,13 @@ +package builtin + +import "minotaur/game" + +// RoomOption 房间构建可选项 +type RoomOption[PlayerID comparable, Player game.Player[PlayerID]] func(room *Room[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 + } +} diff --git a/game/room.go b/game/room.go new file mode 100644 index 0000000..39fcd8b --- /dev/null +++ b/game/room.go @@ -0,0 +1,36 @@ +package game + +import "minotaur/utils/synchronization" + +// Room 房间类似于简版的游戏世界,不过没有游戏实体 +type Room[PlayerID comparable, P Player[PlayerID]] interface { + // GetGuid 获取房间的唯一标识符 + GetGuid() int64 + // GetPlayerLimit 获取玩家人数上限 + GetPlayerLimit() int + // GetPlayerWithConnID 根据连接ID获取玩家 + GetPlayerWithConnID(id string) P + // GetPlayer 根据玩家id获取玩家 + GetPlayer(id PlayerID) P + // GetPlayers 获取房间中的所有玩家 + GetPlayers() synchronization.MapReadonly[PlayerID, P] + // IsExistPlayer 检查房间中是否存在特定玩家 + IsExistPlayer(id PlayerID) bool + + // Join 使特定玩家加入房间 + Join(player P) error + // Leave 使特定玩家离开房间 + Leave(id PlayerID) + + // RegPlayerJoinRoomEvent 玩家进入房间时将立即执行被注册的事件处理函数 + RegPlayerJoinRoomEvent(handle PlayerJoinRoomEventHandle[PlayerID, P]) + OnPlayerJoinRoomEvent(player P) + // RegPlayerLeaveRoomEvent 玩家离开房间时将立即执行被注册的事件处理函数 + RegPlayerLeaveRoomEvent(handle PlayerLeaveRoomEventHandle[PlayerID, P]) + OnPlayerLeaveRoomEvent(player P) +} + +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) +)