From d82964526c68965b0d83b3ec425fcb09ff28676e Mon Sep 17 00:00:00 2001 From: edmand46 Date: Sat, 13 Apr 2024 16:17:31 +0300 Subject: [PATCH] feat(wip): room list support --- .../Sources/Handler/JoinSuccessHandler.cs | 8 +- .../Sources/Handler/RoomListHandler.cs | 43 ++++++++++ .../Listener/IRagonRoomListListener.cs | 6 ++ Ragon.Client/Sources/RagonClient.cs | 86 +++++++++---------- Ragon.Client/Sources/RagonListenerList.cs | 7 ++ Ragon.Client/Sources/RagonRoom.cs | 12 +-- Ragon.Client/Sources/RagonRoomInformation.cs | 13 +++ Ragon.Protocol/Sources/RagonOperation.cs | 1 + .../Sources/Handler/RoomCreateOperation.cs | 3 + .../Handler/RoomJoinOrCreateOperation.cs | 7 ++ Ragon.Server/Sources/Lobby/IRagonLobby.cs | 1 + .../Sources/Lobby/RagonLobbyDispatcher.cs | 33 +++++++ .../Sources/Lobby/RagonLobbyInMemory.cs | 2 + Ragon.Server/Sources/RagonServer.cs | 20 ++++- Ragon.Server/Sources/Room/IRagonRoom.cs | 6 ++ Ragon.Server/Sources/Time/RagonActionTimer.cs | 21 +++++ 16 files changed, 215 insertions(+), 54 deletions(-) create mode 100644 Ragon.Client/Sources/Handler/RoomListHandler.cs create mode 100644 Ragon.Client/Sources/Listener/IRagonRoomListListener.cs create mode 100644 Ragon.Client/Sources/RagonRoomInformation.cs create mode 100644 Ragon.Server/Sources/Lobby/RagonLobbyDispatcher.cs create mode 100644 Ragon.Server/Sources/Time/RagonActionTimer.cs diff --git a/Ragon.Client/Sources/Handler/JoinSuccessHandler.cs b/Ragon.Client/Sources/Handler/JoinSuccessHandler.cs index 2d68fc0..8e1c433 100644 --- a/Ragon.Client/Sources/Handler/JoinSuccessHandler.cs +++ b/Ragon.Client/Sources/Handler/JoinSuccessHandler.cs @@ -19,9 +19,9 @@ using Ragon.Protocol; namespace Ragon.Client; -public struct RagonRoomInformation +public struct RoomParameters { - public RagonRoomInformation(string roomId, string playerId, string ownerId, ushort min, ushort max) + public RoomParameters(string roomId, string playerId, string ownerId, ushort min, ushort max) { RoomId = roomId; PlayerId = playerId; @@ -39,6 +39,8 @@ public struct RagonRoomInformation internal class JoinSuccessHandler : IHandler { + + private readonly RagonListenerList _listenerList; private readonly RagonPlayerCache _playerCache; private readonly RagonEntityCache _entityCache; @@ -67,7 +69,7 @@ internal class JoinSuccessHandler : IHandler var sceneName = reader.ReadString(); var scene = new RagonScene(_client, _playerCache, _entityCache, sceneName); - var roomInfo = new RagonRoomInformation(roomId, localId, ownerId, min, max); + var roomInfo = new RoomParameters(roomId, localId, ownerId, min, max); var room = new RagonRoom(_client, _entityCache, _playerCache, roomInfo, scene); _playerCache.SetOwnerAndLocal(ownerId, localId); diff --git a/Ragon.Client/Sources/Handler/RoomListHandler.cs b/Ragon.Client/Sources/Handler/RoomListHandler.cs new file mode 100644 index 0000000..6656893 --- /dev/null +++ b/Ragon.Client/Sources/Handler/RoomListHandler.cs @@ -0,0 +1,43 @@ +using Ragon.Protocol; + +namespace Ragon.Client; + +internal class RoomListHandler: IHandler +{ + private RagonListenerList _listenerList; + private RagonSession _session; + + public RoomListHandler(RagonSession session, RagonListenerList list) + { + _session = session; + _listenerList = list; + } + + public void Handle(RagonBuffer reader) + { + var roomCount = reader.ReadUShort(); + var roomList = new RagonRoomInformation[roomCount]; + for (int i = 0; i < roomCount; i++) + { + var id = reader.ReadString(); + var scene = reader.ReadString(); + var players = reader.ReadUShort(); + var maxPlayers = reader.ReadUShort(); + var minPlayers = reader.ReadUShort(); + + var roomInfo = new RagonRoomInformation() + { + Id = id, + Scene = scene, + PlayerCount = players, + PlayerMax = maxPlayers, + PlayerMin = minPlayers, + Properties = new Dictionary() + }; + + roomList[i] = roomInfo; + } + + _listenerList.OnRoomList(roomList); + } +} \ No newline at end of file diff --git a/Ragon.Client/Sources/Listener/IRagonRoomListListener.cs b/Ragon.Client/Sources/Listener/IRagonRoomListListener.cs new file mode 100644 index 0000000..5b91ee3 --- /dev/null +++ b/Ragon.Client/Sources/Listener/IRagonRoomListListener.cs @@ -0,0 +1,6 @@ +namespace Ragon.Client; + +public interface IRagonRoomListListener +{ + public void OnRoomListUpdate(IReadOnlyList roomsInfos); +} \ No newline at end of file diff --git a/Ragon.Client/Sources/RagonClient.cs b/Ragon.Client/Sources/RagonClient.cs index 7e7644c..a3533b8 100644 --- a/Ragon.Client/Sources/RagonClient.cs +++ b/Ragon.Client/Sources/RagonClient.cs @@ -29,7 +29,7 @@ namespace Ragon.Client private RagonBuffer _writeBuffer; private RagonRoom _room; private RagonSession _session; - private RagonListenerList listeners; + private RagonListenerList _listeners; private RagonPlayerCache _playerCache; private RagonEntityCache _entityCache; private RagonEventCache _eventCache; @@ -56,7 +56,7 @@ namespace Ragon.Client public RagonClient(INetworkConnection connection, int rate) { - listeners = new RagonListenerList(this); + _listeners = new RagonListenerList(this); _connection = connection; _connection.OnData += OnData; @@ -104,25 +104,26 @@ namespace Ragon.Client _entityCache = new RagonEntityCache(this, _playerCache, _sceneCollector); _handlers = new IHandler[byte.MaxValue]; - _handlers[(byte)RagonOperation.AUTHORIZED_SUCCESS] = new AuthorizeSuccessHandler(this, listeners); - _handlers[(byte)RagonOperation.AUTHORIZED_FAILED] = new AuthorizeFailedHandler(listeners); - _handlers[(byte)RagonOperation.JOIN_SUCCESS] = new JoinSuccessHandler(this, listeners, _playerCache, _entityCache); - _handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(listeners); - _handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, listeners, _entityCache); - _handlers[(byte)RagonOperation.OWNERSHIP_ROOM_CHANGED] = new OwnershipRoomHandler(listeners, _playerCache, _entityCache); - _handlers[(byte)RagonOperation.OWNERSHIP_ENTITY_CHANGED] = new EntityOwnershipHandler(listeners, _playerCache, _entityCache); - _handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_playerCache, listeners); - _handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_entityCache, _playerCache, listeners); - _handlers[(byte)RagonOperation.LOAD_SCENE] = new SceneLoadHandler(this, listeners); + _handlers[(byte)RagonOperation.AUTHORIZED_SUCCESS] = new AuthorizeSuccessHandler(this, _listeners); + _handlers[(byte)RagonOperation.AUTHORIZED_FAILED] = new AuthorizeFailedHandler(_listeners); + _handlers[(byte)RagonOperation.JOIN_SUCCESS] = new JoinSuccessHandler(this, _listeners, _playerCache, _entityCache); + _handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(_listeners); + _handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, _listeners, _entityCache); + _handlers[(byte)RagonOperation.OWNERSHIP_ROOM_CHANGED] = new OwnershipRoomHandler(_listeners, _playerCache, _entityCache); + _handlers[(byte)RagonOperation.OWNERSHIP_ENTITY_CHANGED] = new EntityOwnershipHandler(_listeners, _playerCache, _entityCache); + _handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_playerCache, _listeners); + _handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_entityCache, _playerCache, _listeners); + _handlers[(byte)RagonOperation.LOAD_SCENE] = new SceneLoadHandler(this, _listeners); _handlers[(byte)RagonOperation.CREATE_ENTITY] = new EntityCreateHandler(this, _playerCache, _entityCache, _entityListener); _handlers[(byte)RagonOperation.REMOVE_ENTITY] = new EntityRemoveHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_STATE] = new StateEntityHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_EVENT] = new EntityEventHandler(_playerCache, _entityCache); _handlers[(byte)RagonOperation.REPLICATE_ROOM_EVENT] = new RoomEventHandler(this, _playerCache); - _handlers[(byte)RagonOperation.SNAPSHOT] = new SnapshotHandler(this, listeners, _entityCache, _playerCache, _entityListener); + _handlers[(byte)RagonOperation.SNAPSHOT] = new SnapshotHandler(this, _listeners, _entityCache, _playerCache, _entityListener); _handlers[(byte)RagonOperation.TIMESTAMP_SYNCHRONIZATION] = new TimestampHandler(this); - _handlers[(byte)RagonOperation.REPLICATE_RAW_DATA] = new RoomDataHandler(_playerCache, listeners); - + _handlers[(byte)RagonOperation.REPLICATE_RAW_DATA] = new RoomDataHandler(_playerCache, _listeners); + _handlers[(byte)RagonOperation.ROOM_LIST_UPDATED] = new RoomListHandler(_session, _listeners); + var protocolRaw = RagonVersion.Parse(protocol); _connection.Connect(address, port, protocolRaw); } @@ -152,7 +153,7 @@ namespace Ragon.Client _stats.Update(_connection.BytesSent, _connection.BytesReceived, _connection.Ping, dt); } - listeners.Update(); + _listeners.Update(); _connection.Update(); } @@ -166,31 +167,30 @@ namespace Ragon.Client _connection.Dispose(); } - public void AddListener(IRagonListener listener) => listeners.Add(listener); - public void AddListener(IRagonAuthorizationListener listener) => listeners.Add(listener); - public void AddListener(IRagonConnectionListener listener) => listeners.Add(listener); - public void AddListener(IRagonFailedListener listener) => listeners.Add(listener); - public void AddListener(IRagonJoinListener listener) => listeners.Add(listener); - public void AddListener(IRagonLeftListener listener) => listeners.Add(listener); - public void AddListener(IRagonOwnershipChangedListener listener) => listeners.Add(listener); - public void AddListener(IRagonPlayerJoinListener listener) => listeners.Add(listener); - public void AddListener(IRagonPlayerLeftListener listener) => listeners.Add(listener); - public void AddListener(IRagonSceneListener listener) => listeners.Add(listener); - public void AddListener(IRagonSceneRequestListener listener) => listeners.Add(listener); - public void AddListener(IRagonDataListener listener) => listeners.Add(listener); - - public void RemoveListener(IRagonListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonAuthorizationListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonConnectionListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonFailedListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonJoinListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonLeftListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonOwnershipChangedListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonPlayerJoinListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonPlayerLeftListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonSceneListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonSceneRequestListener listener) => listeners.Remove(listener); - public void RemoveListener(IRagonDataListener listener) => listeners.Remove(listener); + public void AddListener(IRagonListener listener) => _listeners.Add(listener); + public void AddListener(IRagonAuthorizationListener listener) => _listeners.Add(listener); + public void AddListener(IRagonConnectionListener listener) => _listeners.Add(listener); + public void AddListener(IRagonFailedListener listener) => _listeners.Add(listener); + public void AddListener(IRagonJoinListener listener) => _listeners.Add(listener); + public void AddListener(IRagonLeftListener listener) => _listeners.Add(listener); + public void AddListener(IRagonOwnershipChangedListener listener) => _listeners.Add(listener); + public void AddListener(IRagonPlayerJoinListener listener) => _listeners.Add(listener); + public void AddListener(IRagonPlayerLeftListener listener) => _listeners.Add(listener); + public void AddListener(IRagonSceneListener listener) => _listeners.Add(listener); + public void AddListener(IRagonSceneRequestListener listener) => _listeners.Add(listener); + public void AddListener(IRagonDataListener listener) => _listeners.Add(listener); + public void RemoveListener(IRagonListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonAuthorizationListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonConnectionListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonFailedListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonJoinListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonLeftListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonOwnershipChangedListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonPlayerJoinListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonPlayerLeftListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonSceneListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonSceneRequestListener listener) => _listeners.Remove(listener); + public void RemoveListener(IRagonDataListener listener) => _listeners.Remove(listener); #endregion @@ -234,7 +234,7 @@ namespace Ragon.Client { RagonLog.Trace("Connected"); - listeners.OnConnected(); + _listeners.OnConnected(); _status = RagonStatus.CONNECTED; } @@ -242,7 +242,7 @@ namespace Ragon.Client { RagonLog.Trace($"Disconnected: {reason}"); - listeners.OnDisconnected(reason); + _listeners.OnDisconnected(reason); _status = RagonStatus.DISCONNECTED; } diff --git a/Ragon.Client/Sources/RagonListenerList.cs b/Ragon.Client/Sources/RagonListenerList.cs index 24af60d..10b8848 100644 --- a/Ragon.Client/Sources/RagonListenerList.cs +++ b/Ragon.Client/Sources/RagonListenerList.cs @@ -32,6 +32,7 @@ namespace Ragon.Client private readonly List _playerJoinListeners = new(); private readonly List _playerLeftListeners = new(); private readonly List _dataListeners = new(); + private readonly List _roomListListeners = new(); private readonly List _delayedActions = new(); public RagonListenerList(RagonClient client) @@ -263,5 +264,11 @@ namespace Ragon.Client foreach (var listener in _dataListeners) listener.OnData(player, data); } + + public void OnRoomList(RagonRoomInformation[] roomInfos) + { + foreach (var listListener in _roomListListeners) + listListener.OnRoomListUpdate(roomInfos); + } } } \ No newline at end of file diff --git a/Ragon.Client/Sources/RagonRoom.cs b/Ragon.Client/Sources/RagonRoom.cs index 3d46051..bf8d7c9 100644 --- a/Ragon.Client/Sources/RagonRoom.cs +++ b/Ragon.Client/Sources/RagonRoom.cs @@ -53,11 +53,11 @@ namespace Ragon.Client private RagonScene _scene; private RagonEntityCache _entityCache; private RagonPlayerCache _playerCache; - private RagonRoomInformation _information; + private RoomParameters _parameters; - public string Id => _information.RoomId; - public int MinPlayers => _information.Min; - public int MaxPlayers => _information.Max; + public string Id => _parameters.RoomId; + public int MinPlayers => _parameters.Min; + public int MaxPlayers => _parameters.Max; public string Scene => _scene.Name; public IReadOnlyList Players => _playerCache.Players; @@ -71,11 +71,11 @@ namespace Ragon.Client public RagonRoom(RagonClient client, RagonEntityCache entityCache, RagonPlayerCache playerCache, - RagonRoomInformation information, + RoomParameters parameters, RagonScene scene) { _client = client; - _information = information; + _parameters = parameters; _entityCache = entityCache; _playerCache = playerCache; _scene = scene; diff --git a/Ragon.Client/Sources/RagonRoomInformation.cs b/Ragon.Client/Sources/RagonRoomInformation.cs new file mode 100644 index 0000000..aeda469 --- /dev/null +++ b/Ragon.Client/Sources/RagonRoomInformation.cs @@ -0,0 +1,13 @@ +using Ragon.Protocol; + +namespace Ragon.Client; + +public struct RagonRoomInformation +{ + public string Id; + public string Scene; + public int PlayerMax; + public int PlayerMin; + public int PlayerCount; + public Dictionary Properties; +} \ No newline at end of file diff --git a/Ragon.Protocol/Sources/RagonOperation.cs b/Ragon.Protocol/Sources/RagonOperation.cs index 2c43def..b7d6787 100644 --- a/Ragon.Protocol/Sources/RagonOperation.cs +++ b/Ragon.Protocol/Sources/RagonOperation.cs @@ -44,5 +44,6 @@ namespace Ragon.Protocol TRANSFER_ROOM_OWNERSHIP = 23, TRANSFER_ENTITY_OWNERSHIP = 24, TIMESTAMP_SYNCHRONIZATION = 25, + ROOM_LIST_UPDATED = 26, } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs index a2b5b10..90060ce 100644 --- a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs @@ -80,6 +80,9 @@ public sealed class RoomCreateOperation : BaseOperation var roomPlugin = _serverPlugin.CreateRoomPlugin(information); var room = new RagonRoom(roomId, information, roomPlugin); + if (!roomPlugin.OnPlayerJoined(roomPlayer)) + return; + roomPlayer.OnAttached(room); context.Scheduler.Run(room); diff --git a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs index c19938b..325cfaf 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs @@ -53,6 +53,10 @@ public sealed class RoomJoinOrCreateOperation : BaseOperation if (context.Lobby.FindRoomByScene(_roomParameters.Scene, out var existsRoom)) { var player = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name); + + if (!existsRoom.Plugin.OnPlayerJoined(player)) + return; + context.SetRoom(existsRoom, player); _ragonWebHookPlugin.RoomJoined(context, existsRoom, player); @@ -72,6 +76,9 @@ public sealed class RoomJoinOrCreateOperation : BaseOperation var roomPlugin = _serverPlugin.CreateRoomPlugin(information); var room = new RagonRoom(roomId, information, roomPlugin); + if (!roomPlugin.OnPlayerJoined(roomPlayer)) + return; + _ragonWebHookPlugin.RoomCreated(context, room, roomPlayer); context.Lobby.Persist(room); diff --git a/Ragon.Server/Sources/Lobby/IRagonLobby.cs b/Ragon.Server/Sources/Lobby/IRagonLobby.cs index 2c047a3..f80eecb 100644 --- a/Ragon.Server/Sources/Lobby/IRagonLobby.cs +++ b/Ragon.Server/Sources/Lobby/IRagonLobby.cs @@ -21,6 +21,7 @@ namespace Ragon.Server.Lobby; public interface IRagonLobby { + public IReadOnlyList Rooms { get; } public bool FindRoomById(string roomId, [MaybeNullWhen(false)] out RagonRoom room); public bool FindRoomByScene(string sceneName, [MaybeNullWhen(false)] out RagonRoom room); public void Persist(RagonRoom room); diff --git a/Ragon.Server/Sources/Lobby/RagonLobbyDispatcher.cs b/Ragon.Server/Sources/Lobby/RagonLobbyDispatcher.cs new file mode 100644 index 0000000..e843c67 --- /dev/null +++ b/Ragon.Server/Sources/Lobby/RagonLobbyDispatcher.cs @@ -0,0 +1,33 @@ +using Ragon.Protocol; +using Ragon.Server.Room; + +namespace Ragon.Server.Lobby; + +public class RagonLobbyDispatcher +{ + private IRagonLobby _lobby; + + public RagonLobbyDispatcher(IRagonLobby lobby) + { + _lobby = lobby; + } + + public void Write(RagonBuffer writer) + { + writer.Clear(); + writer.Write((byte)RagonOperation.ROOM_LIST_UPDATED); + var rooms = _lobby.Rooms; + + writer.WriteUShort((ushort)rooms.Count); + for (int i = 0; i < rooms.Count; i++) + { + var room = rooms[i]; + + writer.WriteString(room.Id); + writer.WriteString(room.Scene); + writer.WriteUShort((ushort)room.PlayerMax); + writer.WriteUShort((ushort)room.PlayerMin); + writer.WriteUShort((ushort)room.PlayerCount); + } + } +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs b/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs index f3b287c..42073b6 100644 --- a/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs +++ b/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs @@ -25,6 +25,8 @@ public class LobbyInMemory : IRagonLobby private readonly List _rooms = new(); private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + public IReadOnlyList Rooms => _rooms.AsReadOnly(); + public bool FindRoomById(string roomId, [MaybeNullWhen(false)] out RagonRoom room) { foreach (var existRagonRoom in _rooms) diff --git a/Ragon.Server/Sources/RagonServer.cs b/Ragon.Server/Sources/RagonServer.cs index 2b3e1e0..a504049 100644 --- a/Ragon.Server/Sources/RagonServer.cs +++ b/Ragon.Server/Sources/RagonServer.cs @@ -45,6 +45,7 @@ public class RagonServer : IRagonServer, INetworkListener private readonly Dictionary _contextsByConnection; private readonly Dictionary _contextsByPlayerId; private readonly Stopwatch _timer; + private readonly RagonLobbyDispatcher _lobbySerializer; private readonly long _tickRate = 0; public RagonServer( @@ -59,6 +60,7 @@ public class RagonServer : IRagonServer, INetworkListener _contextsByConnection = new Dictionary(); _contextsByPlayerId = new Dictionary(); _lobby = new LobbyInMemory(); + _lobbySerializer = new RagonLobbyDispatcher(_lobby); _scheduler = new RagonScheduler(); _webhooks = new RagonWebHookPlugin(this, configuration); _dedicatedThread = new Thread(Execute); @@ -68,9 +70,11 @@ public class RagonServer : IRagonServer, INetworkListener _writer = new RagonBuffer(); _tickRate = 1000 / _configuration.ServerTickRate; _timer = new Stopwatch(); - + var contextObserver = new RagonContextObserver(_contextsByPlayerId); - + + _scheduler.Run(new RagonActionTimer(SendRoomList, 1.0f)); + _serverPlugin.OnAttached(this); _handlers = new BaseOperation[byte.MaxValue]; @@ -228,6 +232,18 @@ public class RagonServer : IRagonServer, INetworkListener _server.Broadcast(sendData, NetworkChannel.UNRELIABLE); } + public void SendRoomList() + { + _lobbySerializer.Write(_writer); + + var sendData = _writer.ToArray(); + foreach (var (_, value) in _contextsByPlayerId) + { + if (value.Room == null) // If only in lobby, then send room list data + value.Connection.Reliable.Send(sendData); + } + } + public BaseOperation ResolveHandler(RagonOperation operation) { return _handlers[(byte)operation]; diff --git a/Ragon.Server/Sources/Room/IRagonRoom.cs b/Ragon.Server/Sources/Room/IRagonRoom.cs index 54c4134..de2aacb 100644 --- a/Ragon.Server/Sources/Room/IRagonRoom.cs +++ b/Ragon.Server/Sources/Room/IRagonRoom.cs @@ -21,6 +21,12 @@ namespace Ragon.Server.Room; public interface IRagonRoom { + public string Id { get; } + public string Scene { get; } + public int PlayerMin { get; } + public int PlayerMax { get; } + public int PlayerCount { get; } + RagonRoomPlayer GetPlayerByConnection(INetworkConnection connection); RagonRoomPlayer GetPlayerById(string id); IRagonEntity GetEntityById(ushort id); diff --git a/Ragon.Server/Sources/Time/RagonActionTimer.cs b/Ragon.Server/Sources/Time/RagonActionTimer.cs new file mode 100644 index 0000000..d9ebedf --- /dev/null +++ b/Ragon.Server/Sources/Time/RagonActionTimer.cs @@ -0,0 +1,21 @@ +using Ragon.Server.Time; + +public class RagonActionTimer: IRagonAction +{ + private Action _callback; + private float _timer; + private float _time; + + public RagonActionTimer(Action callback, float timeInSeconds) + { + _callback = callback; + _time = timeInSeconds * 1000; + } + + public void Tick(float dt) + { + _timer += dt; + if (_timer >= _time) + _callback?.Invoke(); + } +} \ No newline at end of file