From bfd6c1b54ba25dc15e75b07ab6b3a8a69896637c Mon Sep 17 00:00:00 2001 From: edmand46 Date: Sun, 9 Apr 2023 10:52:18 +0400 Subject: [PATCH 1/4] :construction: plugin system, webhook system --- Ragon.Client.Simulation/Sources/Game.cs | 2 +- Ragon.Client/Ragon.Client.csproj | 2 +- .../Listener/IRagonConnectionListener.cs | 2 +- .../Sources/Listener/IRagonListener.cs | 2 +- Ragon.Client/Sources/RagonClient.cs | 21 ++-- Ragon.Client/Sources/RagonEntityCache.cs | 2 +- Ragon.Client/Sources/RagonListenerList.cs | 6 +- Ragon.Client/Sources/RagonSession.cs | 4 +- Ragon.Protocol/Sources/RagonOperation.cs | 2 +- Ragon.Relay/{ => Sources}/Relay.cs | 13 +- Ragon.Relay/Sources/RelayRoomPlugin.cs | 34 ++++++ Ragon.Relay/Sources/RelayServerPlugin.cs | 39 ++++++ Ragon.Relay/relay.config.json | 9 +- .../Sources/WebSocketConnection.cs | 5 + Ragon.Server.ENet/Sources/ENetConnection.cs | 8 ++ Ragon.Server/Sources/Entity/RagonEntity.cs | 46 ++++--- .../Sources/Entity/RagonEntityParameters.cs | 11 ++ .../Sources/Entity/RagonEntityState.cs | 2 +- Ragon.Server/Sources/Entity/RagonEvent.cs | 4 +- Ragon.Server/Sources/Entity/RagonPayload.cs | 2 +- Ragon.Server/Sources/Entity/RagonProperty.cs | 4 +- .../Sources/Handler/AuthorizationOperation.cs | 88 +++++++++++--- .../Sources/Handler/EntityCreateOperation.cs | 26 +++- .../Sources/Handler/EntityEventOperation.cs | 5 +- ...yOperation.cs => EntityRemoveOperation.cs} | 5 +- .../Sources/Handler/EntityStateOperation.cs | 14 +-- .../Sources/{ => Handler}/IRagonOperation.cs | 2 +- .../Sources/Handler/RoomCreateOperation.cs | 38 ++++-- .../Sources/Handler/RoomJoinOperation.cs | 40 +++++-- .../Handler/RoomJoinOrCreateOperation.cs | 38 ++++-- .../Sources/Handler/RoomLeaveOperation.cs | 18 ++- .../Sources/Handler/SceneLoadOperation.cs | 4 +- .../Sources/Handler/SceneLoadedOperation.cs | 42 +++++-- Ragon.Server/Sources/IO/Executor.cs | 6 +- Ragon.Server/Sources/IO/IExecutor.cs | 4 +- Ragon.Server/Sources/IO/INetworkChannel.cs | 2 +- Ragon.Server/Sources/IO/INetworkConnection.cs | 3 +- Ragon.Server/Sources/IO/INetworkListener.cs | 2 +- Ragon.Server/Sources/IO/INetworkServer.cs | 2 +- .../Sources/IO/NetworkConfiguration.cs | 2 +- Ragon.Server/Sources/Lobby/IRagonLobby.cs | 5 +- .../Sources/Lobby/RagonLobbyInMemory.cs | 20 ++-- .../Sources/Lobby/RagonLobbyPlayer.cs | 21 ++-- Ragon.Server/Sources/Plugin/IRoomPlugin.cs | 26 ++++ Ragon.Server/Sources/Plugin/IServerPlugin.cs | 30 +++++ .../Web/Request/AuthorizationRequest.cs | 8 ++ .../Plugin/Web/Request/RoomCreatedRequest.cs | 7 ++ .../Plugin/Web/Request/RoomJoinedRequest.cs | 6 + .../Plugin/Web/Request/RoomLeavedRequest.cs | 7 ++ .../Plugin/Web/Request/RoomRemovedRequest.cs | 7 ++ .../Web/Response/AuthorizationResponse.cs | 9 ++ .../Sources/Plugin/Web/WebHookPlugin.cs | 112 ++++++++++++++++++ Ragon.Server/Sources/RagonContext.cs | 23 +++- Ragon.Server/Sources/RagonServer.cs | 52 ++++---- .../Sources/RagonServerConfiguration.cs | 35 +++--- Ragon.Server/Sources/Room/RagonRoom.cs | 73 ++++++------ .../Sources/Room/RagonRoomInformation.cs | 13 +- Ragon.Server/Sources/Room/RagonRoomPlayer.cs | 4 +- Ragon.Server/Sources/Time/IRagonAction.cs | 4 +- .../Sources/Time/RagonActionExecutor.cs | 6 +- 60 files changed, 762 insertions(+), 267 deletions(-) rename Ragon.Relay/{ => Sources}/Relay.cs (81%) create mode 100644 Ragon.Relay/Sources/RelayRoomPlugin.cs create mode 100644 Ragon.Relay/Sources/RelayServerPlugin.cs create mode 100644 Ragon.Server/Sources/Entity/RagonEntityParameters.cs rename Ragon.Server/Sources/Handler/{EntityDestroyOperation.cs => EntityRemoveOperation.cs} (90%) rename Ragon.Server/Sources/{ => Handler}/IRagonOperation.cs (96%) create mode 100644 Ragon.Server/Sources/Plugin/IRoomPlugin.cs create mode 100644 Ragon.Server/Sources/Plugin/IServerPlugin.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs diff --git a/Ragon.Client.Simulation/Sources/Game.cs b/Ragon.Client.Simulation/Sources/Game.cs index 60a1c21..feca145 100644 --- a/Ragon.Client.Simulation/Sources/Game.cs +++ b/Ragon.Client.Simulation/Sources/Game.cs @@ -18,7 +18,7 @@ public class Game : IRagonListener public void OnConnected(RagonClient client) { RagonLog.Trace("Connected"); - _client.Session.AuthorizeWithKey("defaultkey", "Player Eduard", Array.Empty()); + _client.Session.AuthorizeWithKey("defaultkey", "Player Eduard"); } public void OnAuthorizationSuccess(RagonClient client, string playerId, string playerName) diff --git a/Ragon.Client/Ragon.Client.csproj b/Ragon.Client/Ragon.Client.csproj index ec23c4d..effaeb8 100644 --- a/Ragon.Client/Ragon.Client.csproj +++ b/Ragon.Client/Ragon.Client.csproj @@ -12,7 +12,7 @@ true none - /Users/edmand46/RagonProjects/ragon-unity-sdk/Assets/Ragon/Runtime/Plugins + /Users/edmand46/RagonProjects/ragon-oss-sdk/Assets/Ragon/Plugins/ diff --git a/Ragon.Client/Sources/Listener/IRagonConnectionListener.cs b/Ragon.Client/Sources/Listener/IRagonConnectionListener.cs index 5cec3e0..ec4e06a 100644 --- a/Ragon.Client/Sources/Listener/IRagonConnectionListener.cs +++ b/Ragon.Client/Sources/Listener/IRagonConnectionListener.cs @@ -16,7 +16,7 @@ namespace Ragon.Client; -public interface IRagonConnectedListener +public interface IRagonConnectionListener { void OnConnected(RagonClient client); void OnDisconnected(RagonClient client); diff --git a/Ragon.Client/Sources/Listener/IRagonListener.cs b/Ragon.Client/Sources/Listener/IRagonListener.cs index 933804e..d5f9c0d 100644 --- a/Ragon.Client/Sources/Listener/IRagonListener.cs +++ b/Ragon.Client/Sources/Listener/IRagonListener.cs @@ -18,7 +18,7 @@ namespace Ragon.Client { public interface IRagonListener : IRagonAuthorizationListener, - IRagonConnectedListener, + IRagonConnectionListener, IRagonFailedListener, IRagonJoinListener, IRagonLeftListener, diff --git a/Ragon.Client/Sources/RagonClient.cs b/Ragon.Client/Sources/RagonClient.cs index dabec77..a059782 100644 --- a/Ragon.Client/Sources/RagonClient.cs +++ b/Ragon.Client/Sources/RagonClient.cs @@ -87,23 +87,18 @@ namespace Ragon.Client _handlers = new Handler[byte.MaxValue]; _handlers[(byte)RagonOperation.AUTHORIZED_SUCCESS] = new AuthorizeSuccessHandler(_listenerList); _handlers[(byte)RagonOperation.AUTHORIZED_FAILED] = new AuthorizeFailedHandler(_listenerList); - _handlers[(byte)RagonOperation.JOIN_SUCCESS] = - new JoinSuccessHandler(this, _readBuffer, _listenerList, _playerCache, _entityCache); + _handlers[(byte)RagonOperation.JOIN_SUCCESS] = new JoinSuccessHandler(this, _readBuffer, _listenerList, _playerCache, _entityCache); _handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(_listenerList); _handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, _listenerList, _entityCache); - _handlers[(byte)RagonOperation.OWNERSHIP_CHANGED] = - new OwnershipHandler(_listenerList, _playerCache, _entityCache); + _handlers[(byte)RagonOperation.OWNERSHIP_CHANGED] = new OwnershipHandler(_listenerList, _playerCache, _entityCache); _handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_playerCache, _listenerList); - _handlers[(byte)RagonOperation.PLAYER_LEAVED] = - new PlayerLeftHandler(_entityCache, _playerCache, _listenerList); + _handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_entityCache, _playerCache, _listenerList); _handlers[(byte)RagonOperation.LOAD_SCENE] = new SceneLoadHandler(this, _listenerList); _handlers[(byte)RagonOperation.CREATE_ENTITY] = new EntityCreateHandler(this, _playerCache, _entityCache); - _handlers[(byte)RagonOperation.DESTROY_ENTITY] = new EntityDestroyHandler(_entityCache); + _handlers[(byte)RagonOperation.REMOVE_ENTITY] = new EntityDestroyHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_STATE] = new StateEntityHandler(_entityCache); - _handlers[(byte)RagonOperation.REPLICATE_ENTITY_EVENT] = - new EntityEventHandler(this, _playerCache, _entityCache); - _handlers[(byte)RagonOperation.SNAPSHOT] = - new SnapshotHandler(this, _listenerList, _entityCache, _playerCache); + _handlers[(byte)RagonOperation.REPLICATE_ENTITY_EVENT] = new EntityEventHandler(this, _playerCache, _entityCache); + _handlers[(byte)RagonOperation.SNAPSHOT] = new SnapshotHandler(this, _listenerList, _entityCache, _playerCache); var protocolRaw = RagonVersion.Parse(protocol); _connection.Connect(address, port, protocolRaw); @@ -144,7 +139,7 @@ namespace Ragon.Client public void AddListener(IRagonListener listener) => _listenerList.Add(listener); public void AddListener(IRagonAuthorizationListener listener) => _listenerList.Add(listener); - public void AddListener(IRagonConnectedListener listener) => _listenerList.Add(listener); + public void AddListener(IRagonConnectionListener listener) => _listenerList.Add(listener); public void AddListener(IRagonFailedListener listener) => _listenerList.Add(listener); public void AddListener(IRagonJoinListener listener) => _listenerList.Add(listener); public void AddListener(IRagonLeftListener listener) => _listenerList.Add(listener); @@ -155,7 +150,7 @@ namespace Ragon.Client public void RemoveListener(IRagonListener listener) => _listenerList.Remove(listener); public void RemoveListener(IRagonAuthorizationListener listener) => _listenerList.Remove(listener); - public void RemoveListener(IRagonConnectedListener listener) => _listenerList.Remove(listener); + public void RemoveListener(IRagonConnectionListener listener) => _listenerList.Remove(listener); public void RemoveListener(IRagonFailedListener listener) => _listenerList.Remove(listener); public void RemoveListener(IRagonJoinListener listener) => _listenerList.Remove(listener); public void RemoveListener(IRagonLeftListener listener) => _listenerList.Remove(listener); diff --git a/Ragon.Client/Sources/RagonEntityCache.cs b/Ragon.Client/Sources/RagonEntityCache.cs index 0c95774..eabc6eb 100644 --- a/Ragon.Client/Sources/RagonEntityCache.cs +++ b/Ragon.Client/Sources/RagonEntityCache.cs @@ -81,7 +81,7 @@ public sealed class RagonEntityCache var buffer = _client.Buffer; buffer.Clear(); - buffer.WriteOperation(RagonOperation.DESTROY_ENTITY); + buffer.WriteOperation(RagonOperation.REMOVE_ENTITY); buffer.WriteUShort(entity.Id); destroyPayload?.Serialize(buffer); diff --git a/Ragon.Client/Sources/RagonListenerList.cs b/Ragon.Client/Sources/RagonListenerList.cs index eca5666..494d746 100644 --- a/Ragon.Client/Sources/RagonListenerList.cs +++ b/Ragon.Client/Sources/RagonListenerList.cs @@ -20,7 +20,7 @@ namespace Ragon.Client { private readonly RagonClient _client; private readonly List _authorizationListeners = new(); - private readonly List _connectionListeners = new(); + private readonly List _connectionListeners = new(); private readonly List _failedListeners = new(); private readonly List _joinListeners = new(); private readonly List _leftListeners = new(); @@ -65,7 +65,7 @@ namespace Ragon.Client _authorizationListeners.Add(listener); } - public void Add(IRagonConnectedListener listener) + public void Add(IRagonConnectionListener listener) { _connectionListeners.Add(listener); } @@ -110,7 +110,7 @@ namespace Ragon.Client _authorizationListeners.Remove(listener); } - public void Remove(IRagonConnectedListener listener) + public void Remove(IRagonConnectionListener listener) { _connectionListeners.Remove(listener); } diff --git a/Ragon.Client/Sources/RagonSession.cs b/Ragon.Client/Sources/RagonSession.cs index 29914ec..fba61ae 100644 --- a/Ragon.Client/Sources/RagonSession.cs +++ b/Ragon.Client/Sources/RagonSession.cs @@ -93,13 +93,13 @@ namespace Ragon.Client _client.Reliable.Send(sendData); } - public void AuthorizeWithKey(string key, string playerName, byte[] additonalData) + public void AuthorizeWithKey(string key, string playerName, string payload = "") { _buffer.Clear(); _buffer.WriteOperation(RagonOperation.AUTHORIZE); _buffer.WriteString(key); _buffer.WriteString(playerName); - _buffer.WriteBytes(additonalData); + _buffer.WriteString(payload); var sendData = _buffer.ToArray(); _client.Reliable.Send(sendData); diff --git a/Ragon.Protocol/Sources/RagonOperation.cs b/Ragon.Protocol/Sources/RagonOperation.cs index d4f110f..c492b68 100644 --- a/Ragon.Protocol/Sources/RagonOperation.cs +++ b/Ragon.Protocol/Sources/RagonOperation.cs @@ -34,7 +34,7 @@ namespace Ragon.Protocol PLAYER_JOINED, PLAYER_LEAVED, CREATE_ENTITY, - DESTROY_ENTITY, + REMOVE_ENTITY, SNAPSHOT, REPLICATE_ENTITY_STATE, REPLICATE_ENTITY_EVENT, diff --git a/Ragon.Relay/Relay.cs b/Ragon.Relay/Sources/Relay.cs similarity index 81% rename from Ragon.Relay/Relay.cs rename to Ragon.Relay/Sources/Relay.cs index 0192094..de307ed 100644 --- a/Ragon.Relay/Relay.cs +++ b/Ragon.Relay/Sources/Relay.cs @@ -19,7 +19,6 @@ using Ragon.Server; using Ragon.Server.ENet; using Ragon.Server.DotNetWebsockets; - namespace Ragon.Relay; public class Relay @@ -32,21 +31,19 @@ public class Relay var configuration = Configuration.Load("relay.config.json"); var serverType = Configuration.GetServerType(configuration.ServerType); - INetworkServer server = null; + INetworkServer networkServer = new ENetServer(); + IServerPlugin plugin = new RelayServerPlugin(); switch (serverType) { case ServerType.ENET: - server = new ENetServer(); + networkServer = new ENetServer(); break; case ServerType.WEBSOCKET: - server = new DotNetWebSocketServer(); - break; - default: - server = new ENetServer(); + networkServer = new DotNetWebSocketServer(); break; } - var relay = new RagonServer(server, configuration); + var relay = new RagonServer(networkServer, plugin, configuration); logger.Info("Started"); relay.Start(); } diff --git a/Ragon.Relay/Sources/RelayRoomPlugin.cs b/Ragon.Relay/Sources/RelayRoomPlugin.cs new file mode 100644 index 0000000..950b0ed --- /dev/null +++ b/Ragon.Relay/Sources/RelayRoomPlugin.cs @@ -0,0 +1,34 @@ +using System; +using Ragon.Server; + +namespace Ragon.Relay; + +public class RelayRoomPlugin: IRoomPlugin +{ + public void Tick(float dt) + { + + } + + public void OnAttached() + { + Console.WriteLine("Room attached"); + } + + public void OnDetached() + { + Console.WriteLine("Room detached"); + } + + public bool OnEntityCreate(RagonRoomPlayer creator, RagonEntity entity) + { + Console.WriteLine($"Entity created: {entity.Id}"); + return true; + } + + public bool OnEntityRemove(RagonRoomPlayer destroyer, RagonEntity entity) + { + Console.WriteLine($"Entity destroyed: {entity.Id}"); + return true; + } +} \ No newline at end of file diff --git a/Ragon.Relay/Sources/RelayServerPlugin.cs b/Ragon.Relay/Sources/RelayServerPlugin.cs new file mode 100644 index 0000000..266128b --- /dev/null +++ b/Ragon.Relay/Sources/RelayServerPlugin.cs @@ -0,0 +1,39 @@ +using System; +using System.Net.Http; +using Ragon.Server; + +namespace Ragon.Relay; + +public class RelayServerPlugin: IServerPlugin +{ + private HttpClient httpClient; + public IRoomPlugin CreateRoomPlugin(RoomInformation information) + { + return new RelayRoomPlugin(); + } + + public RelayServerPlugin() + { + httpClient = new HttpClient(); + } + + public bool OnRoomCreate(RagonLobbyPlayer player, RagonRoom room) + { + return true; + } + + public bool OnRoomRemove(RagonLobbyPlayer player, RagonRoom room) + { + return true; + } + + public bool OnRoomLeave(RagonRoomPlayer player, RagonRoom room) + { + return true; + } + + public bool OnRoomJoin(RagonRoomPlayer player, RagonRoom room) + { + return true; + } +} \ No newline at end of file diff --git a/Ragon.Relay/relay.config.json b/Ragon.Relay/relay.config.json index c6faf4a..7be2b89 100644 --- a/Ragon.Relay/relay.config.json +++ b/Ragon.Relay/relay.config.json @@ -6,5 +6,12 @@ "port": 5000, "limitConnections": 4095, "limitPlayersPerRoom": 20, - "limitRooms": 200 + "limitRooms": 200, + "webHooks": + { + "room-created": "http://127.0.0.1:3000/service/create-room", + "room-removed": "http://127.0.0.1:3000/service/remove-room", + "room-joined": "http://127.0.0.1:3000/service/join-room", + "room-leaved": "http://127.0.0.1:3000/service/leave-room" + } } \ No newline at end of file diff --git a/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs b/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs index ca8a748..88abcb0 100644 --- a/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs +++ b/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs @@ -43,6 +43,11 @@ public sealed class WebSocketConnection : INetworkConnection Unreliable = unreliableChannel; } + public void Close() + { + Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None); + } + public async Task Flush() { foreach (var channel in _channels) diff --git a/Ragon.Server.ENet/Sources/ENetConnection.cs b/Ragon.Server.ENet/Sources/ENetConnection.cs index 837ca78..6f02a18 100644 --- a/Ragon.Server.ENet/Sources/ENetConnection.cs +++ b/Ragon.Server.ENet/Sources/ENetConnection.cs @@ -23,11 +23,19 @@ public sealed class ENetConnection: INetworkConnection public ushort Id { get; } public INetworkChannel Reliable { get; private set; } public INetworkChannel Unreliable { get; private set; } + private Peer _peer; public ENetConnection(Peer peer) { + _peer = peer; + Id = (ushort) peer.ID; Reliable = new ENetReliableChannel(peer, 0); Unreliable = new ENetUnreliableChannel(peer, 1); } + + public void Close() + { + _peer.Disconnect(0); + } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Entity/RagonEntity.cs b/Ragon.Server/Sources/Entity/RagonEntity.cs index c55bacf..da75e00 100644 --- a/Ragon.Server/Sources/Entity/RagonEntity.cs +++ b/Ragon.Server/Sources/Entity/RagonEntity.cs @@ -16,8 +16,9 @@ using Ragon.Protocol; +using Ragon.Server.Room; -namespace Ragon.Server; +namespace Ragon.Server.Entity; public class RagonEntity { @@ -30,29 +31,33 @@ public class RagonEntity public RagonAuthority Authority { get; private set; } public RagonPayload Payload { get; private set; } public RagonEntityState State { get; private set; } - private readonly List _bufferedEvents; - - public RagonEntity(RagonRoomPlayer owner, ushort type, ushort staticId, ushort attachId, RagonAuthority eventAuthority) + + public RagonEntity(RagonEntityParameters parameters) { - Owner = owner; - StaticId = staticId; - Type = type; - AttachId = attachId; Id = _idGenerator++; - Authority = eventAuthority; + + StaticId = parameters.StaticId; + Type = parameters.Type; + AttachId = parameters.AttachId; + Authority = parameters.Authority; + State = new RagonEntityState(this); Payload = new RagonPayload(); - + _bufferedEvents = new List(); } - - - public void SetOwner(RagonRoomPlayer owner) + + public void Attach(RagonRoomPlayer owner) { Owner = owner; } + public void Detach() + { + + } + public void RestoreBufferedEvents(RagonRoomPlayer roomPlayer, RagonBuffer writer) { foreach (var evnt in _bufferedEvents) @@ -96,7 +101,7 @@ public class RagonEntity var buffer = room.Writer; buffer.Clear(); - buffer.WriteOperation(RagonOperation.DESTROY_ENTITY); + buffer.WriteOperation(RagonOperation.REMOVE_ENTITY); buffer.WriteUShort(Id); Payload.Write(buffer); @@ -209,4 +214,17 @@ public class RagonEntity } } } + + public void Write(RagonBuffer writer) + { + State.Write(writer); + } + + public void Read(RagonRoomPlayer player, RagonBuffer reader) + { + if (Owner.Connection.Id != player.Connection.Id) + return; + + State.Read(reader); + } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Entity/RagonEntityParameters.cs b/Ragon.Server/Sources/Entity/RagonEntityParameters.cs new file mode 100644 index 0000000..e1a5972 --- /dev/null +++ b/Ragon.Server/Sources/Entity/RagonEntityParameters.cs @@ -0,0 +1,11 @@ +using Ragon.Protocol; + +namespace Ragon.Server.Entity; + +public ref struct RagonEntityParameters +{ + public ushort Type; + public ushort StaticId; + public ushort AttachId; + public RagonAuthority Authority; +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Entity/RagonEntityState.cs b/Ragon.Server/Sources/Entity/RagonEntityState.cs index bfccd59..140d7af 100644 --- a/Ragon.Server/Sources/Entity/RagonEntityState.cs +++ b/Ragon.Server/Sources/Entity/RagonEntityState.cs @@ -17,7 +17,7 @@ using Ragon.Protocol; -namespace Ragon.Server; +namespace Ragon.Server.Entity; public class RagonEntityState { diff --git a/Ragon.Server/Sources/Entity/RagonEvent.cs b/Ragon.Server/Sources/Entity/RagonEvent.cs index 48069ec..ae0a773 100644 --- a/Ragon.Server/Sources/Entity/RagonEvent.cs +++ b/Ragon.Server/Sources/Entity/RagonEvent.cs @@ -14,10 +14,10 @@ * limitations under the License. */ - using Ragon.Protocol; +using Ragon.Server.Room; -namespace Ragon.Server; +namespace Ragon.Server.Entity; public class RagonEvent { diff --git a/Ragon.Server/Sources/Entity/RagonPayload.cs b/Ragon.Server/Sources/Entity/RagonPayload.cs index 064eb5e..b461759 100644 --- a/Ragon.Server/Sources/Entity/RagonPayload.cs +++ b/Ragon.Server/Sources/Entity/RagonPayload.cs @@ -17,7 +17,7 @@ using Ragon.Protocol; -namespace Ragon.Server; +namespace Ragon.Server.Entity; public class RagonPayload { diff --git a/Ragon.Server/Sources/Entity/RagonProperty.cs b/Ragon.Server/Sources/Entity/RagonProperty.cs index 3f453c1..7738caf 100644 --- a/Ragon.Server/Sources/Entity/RagonProperty.cs +++ b/Ragon.Server/Sources/Entity/RagonProperty.cs @@ -14,11 +14,9 @@ * limitations under the License. */ - -using System.ComponentModel; using Ragon.Protocol; -namespace Ragon.Server; +namespace Ragon.Server.Entity; public class RagonProperty : RagonPayload { diff --git a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs index 6dac1f5..1b5dc0c 100644 --- a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs +++ b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs @@ -16,40 +16,94 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Hander; +using Ragon.Server.Lobby; +using Ragon.Server.Plugin; -namespace Ragon.Server; + +namespace Ragon.Server.Handler; public sealed class AuthorizationOperation: IRagonOperation { private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly WebHookPlugin _webHook; + private readonly Configuration _configuration; + private readonly RagonBuffer _writer; + + public AuthorizationOperation( + WebHookPlugin webHook, + RagonBuffer writer, + Configuration configuration) + { + _webHook = webHook; + _configuration = configuration; + _writer = writer; + } public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { - if (context.LobbyPlayer.Status == LobbyPlayerStatus.Authorized) + if (context.ConnectionStatus == ConnectionStatus.Authorized) { - _logger.Warn("Player already authorized"); + _logger.Warn("Player already authorized!"); + return; + } + + if (context.ConnectionStatus == ConnectionStatus.InProcess) + { + _logger.Warn("Player already request authorization!"); return; } var key = reader.ReadString(); - var playerName = reader.ReadString(); - var additionalPayload = new RagonPayload(); - additionalPayload.Read(reader); - - context.LobbyPlayer.Name = playerName; - context.LobbyPlayer.AdditionalData = Array.Empty(); - context.LobbyPlayer.Status = LobbyPlayerStatus.Authorized; + var name = reader.ReadString(); + var payload = reader.ReadString(); + + if (key == _configuration.ServerKey) + { + if (_webHook.RequestAuthorization(context, name, payload)) + return; + + var lobbyPlayer = new RagonLobbyPlayer(Guid.NewGuid().ToString(), name, payload); + context.SetPlayer(lobbyPlayer); + + Approve(context); + } + else + { + Reject(context); + } + } + public void Approve(RagonContext context) + { + context.ConnectionStatus = ConnectionStatus.Authorized; + var playerId = context.LobbyPlayer.Id; + var playerName = context.LobbyPlayer.Name; + var playerPayload = context.LobbyPlayer.Payload; + + _writer.Clear(); + _writer.WriteOperation(RagonOperation.AUTHORIZED_SUCCESS); + _writer.WriteString(playerId); + _writer.WriteString(playerName); + _writer.WriteString(playerPayload); - writer.Clear(); - writer.WriteOperation(RagonOperation.AUTHORIZED_SUCCESS); - writer.WriteString(playerId); - writer.WriteString(playerName); - - var sendData = writer.ToArray(); + var sendData = _writer.ToArray(); context.Connection.Reliable.Send(sendData); - _logger.Trace($"Connection {context.Connection.Id} as {playerId}|{context.LobbyPlayer.Name} authorized"); + _logger.Trace($"Connection {context.Connection.Id} as {playerId}|{context.LobbyPlayer.Name} authorized"); + } + + public void Reject(RagonContext context) + { + _writer.Clear(); + _writer.WriteOperation(RagonOperation.AUTHORIZED_FAILED); + + var sendData = _writer.ToArray(); + + context.Connection.Reliable.Send(sendData); + context.Connection.Close(); + + _logger.Trace($"Connection {context.Connection.Id}"); } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Handler/EntityCreateOperation.cs b/Ragon.Server/Sources/Handler/EntityCreateOperation.cs index 32c0069..8fb83a6 100644 --- a/Ragon.Server/Sources/Handler/EntityCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityCreateOperation.cs @@ -16,12 +16,13 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Entity; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class EntityCreateOperation : IRagonOperation { - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { @@ -32,7 +33,15 @@ public sealed class EntityCreateOperation : IRagonOperation var eventAuthority = (RagonAuthority) reader.ReadByte(); var propertiesCount = reader.ReadUShort(); - var entity = new RagonEntity(player, entityType, 0, attachId, eventAuthority); + var entityParameters = new RagonEntityParameters() + { + Type = entityType, + Authority = eventAuthority, + AttachId = attachId, + StaticId = 0 + }; + + var entity = new RagonEntity(entityParameters); for (var i = 0; i < propertiesCount; i++) { var propertyType = reader.ReadBool(); @@ -40,13 +49,18 @@ public sealed class EntityCreateOperation : IRagonOperation entity.State.AddProperty(new RagonProperty(propertySize, propertyType)); } - + if (reader.Capacity > 0) entity.Payload.Read(reader); - + + var roomPlugin = room.Plugin; + if (!roomPlugin.OnEntityCreate(player, entity)) + return; + + entity.Attach(player); room.AttachEntity(entity); player.AttachEntity(entity); - + entity.Create(); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} created entity {entity.Id}:{entity.Type}"); diff --git a/Ragon.Server/Sources/Handler/EntityEventOperation.cs b/Ragon.Server/Sources/Handler/EntityEventOperation.cs index 284721a..7eb0fad 100644 --- a/Ragon.Server/Sources/Handler/EntityEventOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityEventOperation.cs @@ -16,12 +16,13 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Hander; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class EntityEventOperation : IRagonOperation { - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { diff --git a/Ragon.Server/Sources/Handler/EntityDestroyOperation.cs b/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs similarity index 90% rename from Ragon.Server/Sources/Handler/EntityDestroyOperation.cs rename to Ragon.Server/Sources/Handler/EntityRemoveOperation.cs index a112529..d9d2326 100644 --- a/Ragon.Server/Sources/Handler/EntityDestroyOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs @@ -16,12 +16,13 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Hander; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class EntityDestroyOperation: IRagonOperation { - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { diff --git a/Ragon.Server/Sources/Handler/EntityStateOperation.cs b/Ragon.Server/Sources/Handler/EntityStateOperation.cs index c463e77..c9ec700 100644 --- a/Ragon.Server/Sources/Handler/EntityStateOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityStateOperation.cs @@ -17,29 +17,25 @@ using NLog; using Ragon.Protocol; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class EntityStateOperation: IRagonOperation { - private ILogger _logger = LogManager.GetCurrentClassLogger(); + private readonly ILogger _logger = LogManager.GetCurrentClassLogger(); public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { var room = context.Room; + var player = context.RoomPlayer; var entitiesCount = reader.ReadUShort(); for (var entityIndex = 0; entityIndex < entitiesCount; entityIndex++) { var entityId = reader.ReadUShort(); - if (room.Entities.TryGetValue(entityId, out var entity) && entity.Owner.Connection.Id == context.Connection.Id) - { - entity.State.Read(reader); - room.Track(entity); - } + if (room.Entities.TryGetValue(entityId, out var entity)) + entity.Read(player, reader); else - { _logger.Error($"Entity with Id {entityId} not found, replication interrupted"); - } } } } \ No newline at end of file diff --git a/Ragon.Server/Sources/IRagonOperation.cs b/Ragon.Server/Sources/Handler/IRagonOperation.cs similarity index 96% rename from Ragon.Server/Sources/IRagonOperation.cs rename to Ragon.Server/Sources/Handler/IRagonOperation.cs index e94882e..3db5c0a 100644 --- a/Ragon.Server/Sources/IRagonOperation.cs +++ b/Ragon.Server/Sources/Handler/IRagonOperation.cs @@ -16,7 +16,7 @@ using Ragon.Protocol; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public interface IRagonOperation { diff --git a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs index a97fad2..f375a35 100644 --- a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs @@ -16,17 +16,28 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Lobby; +using Ragon.Server.Plugin; +using Ragon.Server.Room; -namespace Ragon.Server; +namespace Ragon.Server.Hander; public sealed class RoomCreateOperation: IRagonOperation { - private RagonRoomParameters _roomParameters = new(); - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly RagonRoomParameters _roomParameters = new(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly IServerPlugin _serverPlugin; + private readonly WebHookPlugin _webHookPlugin; + public RoomCreateOperation(IServerPlugin serverPlugin, WebHookPlugin webHook) + { + _serverPlugin = serverPlugin; + _webHookPlugin = webHook; + } + public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { - if (context.LobbyPlayer.Status == LobbyPlayerStatus.Unauthorized) + if (context.ConnectionStatus == ConnectionStatus.Unauthorized) { _logger.Warn($"Player {context.Connection.Id} not authorized for this request"); return; @@ -62,17 +73,20 @@ public sealed class RoomCreateOperation: IRagonOperation }; var lobbyPlayer = context.LobbyPlayer; + var roomPlayer = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name); + + var roomPlugin = _serverPlugin.CreateRoomPlugin(information); + var room = new RagonRoom(roomId, information, roomPlugin); - var room = new RagonRoom(roomId, information); context.Scheduler.Run(room); context.Lobby.Persist(room); + context.SetRoom(room, roomPlayer); - var player = new RagonRoomPlayer(lobbyPlayer.Connection, lobbyPlayer.Id, lobbyPlayer.Name); - context.SetRoom(room, player); + _webHookPlugin.RoomCreated(context, room); - _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} {information}"); + _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} with map {information.Map}"); - JoinSuccess(player, room, writer); + JoinSuccess(roomPlayer, room, writer); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} joined to room {room.Id}"); } @@ -84,9 +98,9 @@ public sealed class RoomCreateOperation: IRagonOperation writer.WriteString(room.Id); writer.WriteString(player.Id); writer.WriteString(room.Owner.Id); - writer.WriteUShort((ushort) room.Info.Min); - writer.WriteUShort((ushort) room.Info.Max); - writer.WriteString(room.Info.Map); + writer.WriteUShort((ushort) room.PlayerMin); + writer.WriteUShort((ushort) room.PlayerMax); + writer.WriteString(room.Map); var sendData = writer.ToArray(); player.Connection.Reliable.Send(sendData); diff --git a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs index a9eda75..08039f8 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs @@ -16,12 +16,21 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Web; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class RoomJoinOperation : IRagonOperation { - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly IServerPlugin _serverPlugin; + private readonly WebHookPlugin _webHookPlugin; + + public RoomJoinOperation(IServerPlugin serverPlugin, WebHookPlugin plugin) + { + _serverPlugin = serverPlugin; + _webHookPlugin = plugin; + } public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { @@ -30,42 +39,47 @@ public sealed class RoomJoinOperation : IRagonOperation if (!context.Lobby.FindRoomById(roomId, out var existsRoom)) { - JoinFailed(lobbyPlayer, writer); + JoinFailed(context, writer); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} failed to join room {roomId}"); return; } - var player = new RagonRoomPlayer(lobbyPlayer.Connection, lobbyPlayer.Id, lobbyPlayer.Name); + var player = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name); context.SetRoom(existsRoom, player); - JoinSuccess(player, existsRoom, writer); + if (!_serverPlugin.OnRoomJoin(player, existsRoom)) + return; + + _webHookPlugin.RoomJoined(context, existsRoom, player); + + JoinSuccess(context, existsRoom, writer); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} joined to {existsRoom.Id}"); } - private void JoinSuccess(RagonRoomPlayer player, RagonRoom room, RagonBuffer writer) + private void JoinSuccess(RagonContext context, RagonRoom room, RagonBuffer writer) { writer.Clear(); writer.WriteOperation(RagonOperation.JOIN_SUCCESS); writer.WriteString(room.Id); - writer.WriteString(player.Id); + writer.WriteString(context.RoomPlayer.Id); writer.WriteString(room.Owner.Id); - writer.WriteUShort((ushort) room.Info.Min); - writer.WriteUShort((ushort) room.Info.Max); - writer.WriteString(room.Info.Map); + writer.WriteUShort((ushort) room.PlayerMin); + writer.WriteUShort((ushort) room.PlayerMax); + writer.WriteString(room.Map); var sendData = writer.ToArray(); - player.Connection.Reliable.Send(sendData); + context.Connection.Reliable.Send(sendData); } - private void JoinFailed(RagonLobbyPlayer player, RagonBuffer writer) + private void JoinFailed(RagonContext context, RagonBuffer writer) { writer.Clear(); writer.WriteOperation(RagonOperation.JOIN_FAILED); writer.WriteString($"Room not exists"); var sendData = writer.ToArray(); - player.Connection.Reliable.Send(sendData); + context.Connection.Reliable.Send(sendData); } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs index 17f509f..192ea60 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs @@ -16,17 +16,26 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Web; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class RoomJoinOrCreateOperation : IRagonOperation { - private RagonRoomParameters _roomParameters = new(); - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly RagonRoomParameters _roomParameters = new(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly IServerPlugin _serverPlugin; + private readonly WebHookPlugin _webHookPlugin; + public RoomJoinOrCreateOperation(IServerPlugin serverPlugin, WebHookPlugin plugin) + { + _serverPlugin = serverPlugin; + _webHookPlugin = plugin; + } + public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { - if (context.LobbyPlayer.Status == LobbyPlayerStatus.Unauthorized) + if (context.ConnectionStatus == ConnectionStatus.Unauthorized) { _logger.Warn("Player not authorized for this request"); return; @@ -39,9 +48,11 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation if (context.Lobby.FindRoomByMap(_roomParameters.Map, out var existsRoom)) { - var player = new RagonRoomPlayer(lobbyPlayer.Connection, lobbyPlayer.Id, lobbyPlayer.Name); + var player = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name); context.SetRoom(existsRoom, player); + _webHookPlugin.RoomJoined(context, existsRoom, player); + JoinSuccess(player, existsRoom, writer); } else @@ -53,14 +64,17 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation Min = _roomParameters.Min, }; - var room = new RagonRoom(roomId, information); + var roomPlayer = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name); + var roomPlugin = _serverPlugin.CreateRoomPlugin(information); + var room = new RagonRoom(roomId, information, roomPlugin); + + _webHookPlugin.RoomCreated(context, room); + context.Lobby.Persist(room); context.Scheduler.Run(room); - - var roomPlayer = new RagonRoomPlayer(lobbyPlayer.Connection, lobbyPlayer.Id, lobbyPlayer.Name); context.SetRoom(room, roomPlayer); - _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} {information}"); + _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} with map {information.Map}"); JoinSuccess(roomPlayer, room, writer); } @@ -73,9 +87,9 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation writer.WriteString(room.Id); writer.WriteString(player.Id); writer.WriteString(room.Owner.Id); - writer.WriteUShort((ushort) room.Info.Min); - writer.WriteUShort((ushort) room.Info.Max); - writer.WriteString(room.Info.Map); + writer.WriteUShort((ushort) room.PlayerMin); + writer.WriteUShort((ushort) room.PlayerMax); + writer.WriteString(room.Map); var sendData = writer.ToArray(); player.Connection.Reliable.Send(sendData); diff --git a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs index c118216..1f1bf06 100644 --- a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs @@ -16,18 +16,30 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Plugin; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class RoomLeaveOperation: IRagonOperation { - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly IServerPlugin _serverPlugin; + private readonly WebHookPlugin _webHookPlugin; + public RoomLeaveOperation(IServerPlugin serverPlugin, WebHookPlugin plugin) + { + _serverPlugin = serverPlugin; + _webHookPlugin = plugin; + } + public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { var room = context.Room; var roomPlayer = context.RoomPlayer; + if (room != null) - { + { + _serverPlugin.OnRoomLeave(roomPlayer, room); + _webHookPlugin.RoomLeaved(context, room, roomPlayer); context.Room?.DetachPlayer(roomPlayer); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} leaved from {room.Id}"); } diff --git a/Ragon.Server/Sources/Handler/SceneLoadOperation.cs b/Ragon.Server/Sources/Handler/SceneLoadOperation.cs index 7aae87c..c92069c 100644 --- a/Ragon.Server/Sources/Handler/SceneLoadOperation.cs +++ b/Ragon.Server/Sources/Handler/SceneLoadOperation.cs @@ -18,11 +18,11 @@ using NLog; using Ragon.Protocol; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public class SceneLoadOperation: IRagonOperation { - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { diff --git a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs index 7c20e6e..0350fd6 100644 --- a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs +++ b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs @@ -16,16 +16,23 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.Entity; +using Ragon.Server.Room; -namespace Ragon.Server; +namespace Ragon.Server.Handler; public sealed class SceneLoadedOperation : IRagonOperation { - private Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + + public SceneLoadedOperation() + { + + } public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) { - if (context.LobbyPlayer.Status == LobbyPlayerStatus.Unauthorized) + if (context.ConnectionStatus == ConnectionStatus.Unauthorized) return; var owner = context.Room.Owner; @@ -34,6 +41,7 @@ public sealed class SceneLoadedOperation : IRagonOperation if (player == owner) { + var statics = reader.ReadUShort(); for (var staticIndex = 0; staticIndex < statics; staticIndex++) { @@ -41,20 +49,32 @@ public sealed class SceneLoadedOperation : IRagonOperation var eventAuthority = (RagonAuthority)reader.ReadByte(); var staticId = reader.ReadUShort(); var propertiesCount = reader.ReadUShort(); - - var entity = new RagonEntity(player, entityType, staticId, 0, eventAuthority); + + var entityParameters = new RagonEntityParameters() + { + Type = entityType, + Authority = eventAuthority, + AttachId = 0, + StaticId = staticId, + }; + + var entity = new RagonEntity(entityParameters); for (var propertyIndex = 0; propertyIndex < propertiesCount; propertyIndex++) { var propertyType = reader.ReadBool(); var propertySize = reader.ReadUShort(); entity.State.AddProperty(new RagonProperty(propertySize, propertyType)); } + + var roomPlugin = room.Plugin; + if (roomPlugin.OnEntityCreate(player, entity)) continue; + + var playerInfo = $"Player {context.Connection.Id}|{context.LobbyPlayer.Name}"; + var entityInfo = $"{entity.Id}:{entity.Type}"; - var playerInfo = $"Player {context.Connection.Id}|{context.LobbyPlayer.Name}"; - var entityInfo = $"{entity.Id}:{entity.Type}"; - _logger.Trace($"{playerInfo} created entity {entityInfo}"); - + + entity.Attach(player); room.AttachEntity(entity); player.AttachEntity(entity); } @@ -123,7 +143,7 @@ public sealed class SceneLoadedOperation : IRagonOperation writer.WriteString(roomPlayer.Id); writer.WriteString(roomPlayer.Name); } - + var dynamicEntities = room.DynamicEntitiesList; var dynamicEntitiesCount = (ushort)dynamicEntities.Count; writer.WriteUShort(dynamicEntitiesCount); @@ -135,7 +155,7 @@ public sealed class SceneLoadedOperation : IRagonOperation writer.WriteUShort(staticEntitiesCount); foreach (var entity in staticEntities) entity.Snapshot(writer); - + var sendData = writer.ToArray(); foreach (var player in receviersList) player.Connection.Reliable.Send(sendData); diff --git a/Ragon.Server/Sources/IO/Executor.cs b/Ragon.Server/Sources/IO/Executor.cs index a503546..a93d38b 100644 --- a/Ragon.Server/Sources/IO/Executor.cs +++ b/Ragon.Server/Sources/IO/Executor.cs @@ -16,7 +16,7 @@ using System.Threading.Channels; -namespace Ragon.Server; +namespace Ragon.Server.IO; public class Executor: TaskScheduler, IExecutor { @@ -25,9 +25,9 @@ public class Executor: TaskScheduler, IExecutor private Queue _pendingTasks; private TaskFactory _taskFactory; - public void Run(Action action) + public Task Run(Action action) { - _taskFactory.StartNew(action); + return _taskFactory.StartNew(action); } public Executor() diff --git a/Ragon.Server/Sources/IO/IExecutor.cs b/Ragon.Server/Sources/IO/IExecutor.cs index e1560ba..b163838 100644 --- a/Ragon.Server/Sources/IO/IExecutor.cs +++ b/Ragon.Server/Sources/IO/IExecutor.cs @@ -14,9 +14,9 @@ * limitations under the License. */ -namespace Ragon.Server; +namespace Ragon.Server.IO; public interface IExecutor { - public void Run(Action action); + public Task Run(Action action); } \ No newline at end of file diff --git a/Ragon.Server/Sources/IO/INetworkChannel.cs b/Ragon.Server/Sources/IO/INetworkChannel.cs index fa8c7e2..f2c8074 100644 --- a/Ragon.Server/Sources/IO/INetworkChannel.cs +++ b/Ragon.Server/Sources/IO/INetworkChannel.cs @@ -14,7 +14,7 @@ * limitations under the License. */ -namespace Ragon.Server; +namespace Ragon.Server.IO; public interface INetworkChannel { diff --git a/Ragon.Server/Sources/IO/INetworkConnection.cs b/Ragon.Server/Sources/IO/INetworkConnection.cs index 4ad3c86..8d79a5c 100644 --- a/Ragon.Server/Sources/IO/INetworkConnection.cs +++ b/Ragon.Server/Sources/IO/INetworkConnection.cs @@ -14,11 +14,12 @@ * limitations under the License. */ -namespace Ragon.Server; +namespace Ragon.Server.IO; public interface INetworkConnection { public ushort Id { get; } public INetworkChannel Reliable { get; } public INetworkChannel Unreliable { get; } + public void Close(); } \ No newline at end of file diff --git a/Ragon.Server/Sources/IO/INetworkListener.cs b/Ragon.Server/Sources/IO/INetworkListener.cs index 7dd3928..ff47db9 100644 --- a/Ragon.Server/Sources/IO/INetworkListener.cs +++ b/Ragon.Server/Sources/IO/INetworkListener.cs @@ -14,7 +14,7 @@ * limitations under the License. */ -namespace Ragon.Server; +namespace Ragon.Server.IO; public interface INetworkListener { diff --git a/Ragon.Server/Sources/IO/INetworkServer.cs b/Ragon.Server/Sources/IO/INetworkServer.cs index 107506a..0108e02 100644 --- a/Ragon.Server/Sources/IO/INetworkServer.cs +++ b/Ragon.Server/Sources/IO/INetworkServer.cs @@ -14,7 +14,7 @@ * limitations under the License. */ -namespace Ragon.Server; +namespace Ragon.Server.IO; public interface INetworkServer { diff --git a/Ragon.Server/Sources/IO/NetworkConfiguration.cs b/Ragon.Server/Sources/IO/NetworkConfiguration.cs index b76768b..90a1023 100644 --- a/Ragon.Server/Sources/IO/NetworkConfiguration.cs +++ b/Ragon.Server/Sources/IO/NetworkConfiguration.cs @@ -14,7 +14,7 @@ * limitations under the License. */ -namespace Ragon.Server; +namespace Ragon.Server.IO; public struct NetworkConfiguration { diff --git a/Ragon.Server/Sources/Lobby/IRagonLobby.cs b/Ragon.Server/Sources/Lobby/IRagonLobby.cs index 7003df4..439b66d 100644 --- a/Ragon.Server/Sources/Lobby/IRagonLobby.cs +++ b/Ragon.Server/Sources/Lobby/IRagonLobby.cs @@ -15,13 +15,14 @@ */ using System.Diagnostics.CodeAnalysis; +using Ragon.Server.Room; -namespace Ragon.Server; +namespace Ragon.Server.Lobby; public interface IRagonLobby { public bool FindRoomById(string roomId, [MaybeNullWhen(false)] out RagonRoom room); public bool FindRoomByMap(string map, [MaybeNullWhen(false)] out RagonRoom room); public void Persist(RagonRoom room); - public void RemoveIfEmpty(RagonRoom room); + public bool RemoveIfEmpty(RagonRoom room); } \ No newline at end of file diff --git a/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs b/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs index 2f1f5f5..0d7b4c8 100644 --- a/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs +++ b/Ragon.Server/Sources/Lobby/RagonLobbyInMemory.cs @@ -16,8 +16,9 @@ using System.Diagnostics.CodeAnalysis; using NLog; +using Ragon.Server.Room; -namespace Ragon.Server; +namespace Ragon.Server.Lobby; public class LobbyInMemory : IRagonLobby { @@ -28,8 +29,7 @@ public class LobbyInMemory : IRagonLobby { foreach (var existRagonRoom in _rooms) { - var info = existRagonRoom.Info; - if (existRagonRoom.Id == RagonRoomId && info.Min < info.Max) + if (existRagonRoom.Id == RagonRoomId && existRagonRoom.PlayerMin < existRagonRoom.PlayerMax) { room = existRagonRoom; return true; @@ -44,8 +44,7 @@ public class LobbyInMemory : IRagonLobby { foreach (var existsRoom in _rooms) { - var info = existsRoom.Info; - if (info.Map == map && existsRoom.Players.Count < info.Max) + if (existsRoom.Map == map && existsRoom.PlayerCount < existsRoom.PlayerMax) { room = existsRoom; return true; @@ -62,18 +61,23 @@ public class LobbyInMemory : IRagonLobby _logger.Trace($"New room: {room.Id}"); foreach (var r in _rooms) - _logger.Trace($"Room: {r.Id} {r.Info} Players: {r.Players.Count} Entities: {r.Entities.Count}"); + _logger.Trace($"Room: {r.Id} Map: {r.Map} Players: {r.Players.Count} Entities: {r.Entities.Count}"); } - public void RemoveIfEmpty(RagonRoom room) + public bool RemoveIfEmpty(RagonRoom room) { + var result = false; if (room.Players.Count == 0) { _rooms.Remove(room); _logger.Trace($"Room {room.Id} removed"); + + result = true; } foreach (var r in _rooms) - _logger.Trace($"Room: {r.Id} {r.Info} Players: {r.Players.Count} Entities: {r.Entities.Count}"); + _logger.Trace($"Room: {r.Id} Map: {r.Map} Players: {r.Players.Count} Entities: {r.Entities.Count}"); + + return result; } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs b/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs index 54bde74..4c241e3 100644 --- a/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs +++ b/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs @@ -14,28 +14,25 @@ * limitations under the License. */ -namespace Ragon.Server; +namespace Ragon.Server.Lobby; -public enum LobbyPlayerStatus +public enum ConnectionStatus { Unauthorized, + InProcess, Authorized, } public class RagonLobbyPlayer { public string Id { get; private set; } - public string Name { get; set; } - public byte[] AdditionalData { get; set; } - public LobbyPlayerStatus Status { get; set; } - public INetworkConnection Connection { get; private set; } + public string Name { get; private set; } + public string Payload { get; private set; } - public RagonLobbyPlayer(INetworkConnection connection) + public RagonLobbyPlayer(string id, string name, string payload) { - Id = Guid.NewGuid().ToString(); - Connection = connection; - Status = LobbyPlayerStatus.Unauthorized; - Name = "None"; - AdditionalData = Array.Empty(); + Id = id; + Name = name; + Payload = payload; } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/IRoomPlugin.cs b/Ragon.Server/Sources/Plugin/IRoomPlugin.cs new file mode 100644 index 0000000..7c85edb --- /dev/null +++ b/Ragon.Server/Sources/Plugin/IRoomPlugin.cs @@ -0,0 +1,26 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Ragon.Server.Plugin; + +public interface IRoomPlugin +{ + void Tick(float dt); + void OnAttached(); + void OnDetached(); + bool OnEntityCreate(RagonRoomPlayer creator, RagonEntity entity); + bool OnEntityRemove(RagonRoomPlayer remover, RagonEntity entity); +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/IServerPlugin.cs b/Ragon.Server/Sources/Plugin/IServerPlugin.cs new file mode 100644 index 0000000..73f2410 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/IServerPlugin.cs @@ -0,0 +1,30 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Ragon.Server.Lobby; +using Ragon.Server.Room; + +namespace Ragon.Server.Plugin; + +public interface IServerPlugin +{ + bool OnRoomCreate(RagonLobbyPlayer player, RagonRoom room); + bool OnRoomRemove(RagonLobbyPlayer player, RagonRoom room); + bool OnRoomLeave(RagonRoomPlayer player, RagonRoom room); + bool OnRoomJoin(RagonRoomPlayer player, RagonRoom room); + + IRoomPlugin CreateRoomPlugin(RoomInformation information); +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs new file mode 100644 index 0000000..64d40cf --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs @@ -0,0 +1,8 @@ +namespace Ragon.Server.Plugin.Web; + +[Serializable] +public class AuthorizationRequest +{ + public string Name; + public string Token; +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs new file mode 100644 index 0000000..539d8c1 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs @@ -0,0 +1,7 @@ +namespace Ragon.Server.Plugin.Web; + +[Serializable] +public class RoomCreatedRequest +{ + +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs new file mode 100644 index 0000000..51474c8 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs @@ -0,0 +1,6 @@ +namespace Ragon.Server.Plugin.Web; + +public class RoomJoinedRequest +{ + +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs new file mode 100644 index 0000000..495a9f0 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs @@ -0,0 +1,7 @@ +namespace Ragon.Server.Plugin.Web; + +[Serializable] +public class RoomLeavedRequest +{ + +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs new file mode 100644 index 0000000..09731d7 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs @@ -0,0 +1,7 @@ +namespace Ragon.Server.Plugin.Web; + +[Serializable] +public class RoomRemovedRequest +{ + +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs b/Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs new file mode 100644 index 0000000..a66dfc1 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs @@ -0,0 +1,9 @@ +namespace Ragon.Server.Plugin.Web; + +[Serializable] +public class AuthorizationResponse +{ + public string Id; + public string Name; + public string Payload; +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs b/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs new file mode 100644 index 0000000..0a8190f --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs @@ -0,0 +1,112 @@ +using System.Net; +using System.Net.Http.Json; +using Newtonsoft.Json; +using Ragon.Protocol; +using Ragon.Server.Lobby; +using Ragon.Server.Plugin.Web; +using Ragon.Server.Room; + +namespace Ragon.Server.Plugin; + +public class WebHookPlugin +{ + private Dictionary _webHooks; + + private RagonServer _server; + private HttpClient _httpClient; + + public WebHookPlugin(RagonServer server, Configuration configuration) + { + _webHooks = new Dictionary(configuration.WebHooks); + _httpClient = new HttpClient(); + _server = server; + } + + public bool RequestAuthorization(RagonContext context, string name, string password) + { + if (_webHooks.TryGetValue("authorization-request", out var value)) + { + var httpContent = new StringContent(""); + var executor = context.Executor; + executor.Run(async () => + { + var authorizationOperation = (AuthorizationOperation) _server.Resolve(RagonOperation.AUTHORIZE); + var response = await _httpClient.PostAsync(new Uri(value), httpContent); + if (response.StatusCode != HttpStatusCode.OK) + { + authorizationOperation.Reject(context); + return; + } + + var content = await response.Content.ReadAsStringAsync(); + var authorizationResponse = JsonConvert.DeserializeObject(content); + if (authorizationResponse != null) + { + var lobbyPlayer = new RagonLobbyPlayer(authorizationResponse.Id, authorizationResponse.Name, authorizationResponse.Payload); + + context.SetPlayer(lobbyPlayer); + authorizationOperation.Approve(context); + } + else + { + authorizationOperation.Reject(context); + } + }); + return true; + } + + return false; + } + + public void RoomCreated(RagonContext context, RagonRoom room) + { + if (_webHooks.TryGetValue("room-created", out var value) && !string.IsNullOrEmpty(value)) + { + var request = new RoomCreatedRequest() + { + }; + var content = JsonContent.Create(request); + var executor = context.Executor; + executor.Run(() => _httpClient.PostAsync(new Uri(value), content, CancellationToken.None)); + } + } + + public void RoomRemoved(RagonContext context, RagonRoom ragonRoom) + { + if (_webHooks.TryGetValue("room-removed", out var value) && !string.IsNullOrEmpty(value)) + { + var request = new RoomCreatedRequest() + { + }; + var content = JsonContent.Create(request); + var executor = context.Executor; + executor.Run(() => _httpClient.PostAsync(new Uri(value), content, CancellationToken.None)); + } + } + + public void RoomJoined(RagonContext context, RagonRoom existsRoom, RagonRoomPlayer player) + { + if (_webHooks.TryGetValue("room-joined", out var value) && !string.IsNullOrEmpty(value)) + { + var request = new RoomCreatedRequest() + { + }; + var content = JsonContent.Create(request); + var executor = context.Executor; + executor.Run(() => _httpClient.PostAsync(new Uri(value), content, CancellationToken.None)); + } + } + + public void RoomLeaved(RagonContext context, RagonRoom room, RagonRoomPlayer roomPlayer) + { + if (_webHooks.TryGetValue("room-leaved", out var value) && !string.IsNullOrEmpty(value)) + { + var request = new RoomCreatedRequest() + { + }; + var content = JsonContent.Create(request); + var executor = context.Executor; + executor.Run(() => _httpClient.PostAsync(new Uri(value), content, CancellationToken.None)); + } + } +} \ No newline at end of file diff --git a/Ragon.Server/Sources/RagonContext.cs b/Ragon.Server/Sources/RagonContext.cs index 1cdb384..5c72877 100644 --- a/Ragon.Server/Sources/RagonContext.cs +++ b/Ragon.Server/Sources/RagonContext.cs @@ -14,33 +14,46 @@ * limitations under the License. */ -using Ragon.Core.Time; -using Ragon.Server; +using Ragon.Server.IO; +using Ragon.Server.Lobby; +using Ragon.Server.Time; +using Ragon.Server.Room; namespace Ragon.Server; public class RagonContext { public INetworkConnection Connection { get; } + public ConnectionStatus ConnectionStatus { get; set; } + public IExecutor Executor { get; private set; } public IRagonLobby Lobby { get; private set; } - public RagonLobbyPlayer LobbyPlayer { get; private set; } + public RagonLobbyPlayer? LobbyPlayer { get; private set; } public RagonRoom? Room { get; private set; } public RagonRoomPlayer? RoomPlayer { get; private set; } public RagonScheduler Scheduler { get; private set; } - public RagonContext(INetworkConnection connection, IExecutor executor, IRagonLobby lobby, RagonScheduler scheduler, RagonLobbyPlayer lobbyPlayer) + public RagonContext( + INetworkConnection connection, + IExecutor executor, + IRagonLobby lobby, + RagonScheduler scheduler) { + ConnectionStatus = ConnectionStatus.Unauthorized; Connection = connection; Executor = executor; Lobby = lobby; Scheduler = scheduler; - LobbyPlayer = lobbyPlayer; } + internal void SetPlayer(RagonLobbyPlayer player) + { + LobbyPlayer = player; + } + internal void SetRoom(RagonRoom room, RagonRoomPlayer player) { Room?.DetachPlayer(RoomPlayer); diff --git a/Ragon.Server/Sources/RagonServer.cs b/Ragon.Server/Sources/RagonServer.cs index 8d310da..0b87e3b 100644 --- a/Ragon.Server/Sources/RagonServer.cs +++ b/Ragon.Server/Sources/RagonServer.cs @@ -16,9 +16,9 @@ using System.Diagnostics; using NLog; -using Ragon.Core.Time; using Ragon.Protocol; -using Ragon.Server; +using Ragon.Server.Plugin; +using Ragon.Server.Time; namespace Ragon.Server; @@ -28,6 +28,7 @@ public class RagonServer : INetworkListener private readonly INetworkServer _server; private readonly Thread _dedicatedThread; private readonly Executor _executor; + private readonly WebHookPlugin _webhooks; private readonly Configuration _configuration; private readonly IRagonOperation[] _handlers; private readonly RagonBuffer _reader; @@ -35,50 +36,56 @@ public class RagonServer : INetworkListener private readonly IRagonLobby _lobby; private readonly RagonScheduler _scheduler; private readonly Dictionary _contexts; - private long _tickrate = 0; - private Stopwatch _timer; + private readonly Stopwatch _timer; + private readonly long _tickRate = 0; - public RagonServer(INetworkServer server, Configuration configuration) + public RagonServer( + INetworkServer server, + IServerPlugin plugin, + Configuration configuration) { _server = server; _executor = _server.Executor; _configuration = configuration; - _dedicatedThread = new Thread(Execute); - _dedicatedThread.IsBackground = true; _contexts = new Dictionary(); _lobby = new LobbyInMemory(); _scheduler = new RagonScheduler(); - + _webhooks = new WebHookPlugin(this, configuration); + _dedicatedThread = new Thread(Execute); + _dedicatedThread.IsBackground = true; + _reader = new RagonBuffer(); _writer = new RagonBuffer(); - _tickrate = 1000 / _configuration.ServerTickRate; + _tickRate = 1000 / _configuration.ServerTickRate; _timer = new Stopwatch(); _handlers = new IRagonOperation[byte.MaxValue]; - _handlers[(byte) RagonOperation.AUTHORIZE] = new AuthorizationOperation(); - _handlers[(byte) RagonOperation.JOIN_OR_CREATE_ROOM] = new RoomJoinOrCreateOperation(); - _handlers[(byte) RagonOperation.CREATE_ROOM] = new RoomCreateOperation(); - _handlers[(byte) RagonOperation.JOIN_ROOM] = new RoomJoinOperation(); - _handlers[(byte) RagonOperation.LEAVE_ROOM] = new RoomLeaveOperation(); + _handlers[(byte) RagonOperation.AUTHORIZE] = new AuthorizationOperation(_webhooks, _writer, configuration); + _handlers[(byte) RagonOperation.JOIN_OR_CREATE_ROOM] = new RoomJoinOrCreateOperation(plugin, _webhooks); + _handlers[(byte) RagonOperation.CREATE_ROOM] = new RoomCreateOperation(plugin, _webhooks); + _handlers[(byte) RagonOperation.JOIN_ROOM] = new RoomJoinOperation(plugin, _webhooks); + _handlers[(byte) RagonOperation.LEAVE_ROOM] = new RoomLeaveOperation(plugin, _webhooks); _handlers[(byte) RagonOperation.LOAD_SCENE] = new SceneLoadOperation(); _handlers[(byte) RagonOperation.SCENE_LOADED] = new SceneLoadedOperation(); _handlers[(byte) RagonOperation.CREATE_ENTITY] = new EntityCreateOperation(); - _handlers[(byte) RagonOperation.DESTROY_ENTITY] = new EntityDestroyOperation(); + _handlers[(byte) RagonOperation.REMOVE_ENTITY] = new EntityDestroyOperation(); _handlers[(byte) RagonOperation.REPLICATE_ENTITY_EVENT] = new EntityEventOperation(); _handlers[(byte) RagonOperation.REPLICATE_ENTITY_STATE] = new EntityStateOperation(); _logger.Trace($"Server Tick Rate: {_configuration.ServerTickRate}"); } + + public IRagonOperation Resolve(RagonOperation operation) => _handlers[(byte)operation]; public void Execute() { _timer.Start(); while (true) { - if (_timer.ElapsedMilliseconds > _tickrate) + if (_timer.ElapsedMilliseconds > _tickRate) { _executor.Update(); - _scheduler.Update(); + _scheduler.Update(_timer.ElapsedMilliseconds / 1000.0f); _timer.Restart(); } @@ -113,9 +120,8 @@ public class RagonServer : INetworkListener public void OnConnected(INetworkConnection connection) { - var lobbyPlayer = new RagonLobbyPlayer(connection); - var context = new RagonContext(connection, _executor, _lobby, _scheduler, lobbyPlayer); - + var context = new RagonContext(connection, _executor, _lobby, _scheduler); + _logger.Trace($"Connected: {connection.Id}"); _contexts.Add(connection.Id, context); } @@ -128,10 +134,11 @@ public class RagonServer : INetworkListener if (room != null) { room.DetachPlayer(context.RoomPlayer); - _lobby.RemoveIfEmpty(room); + if (_lobby.RemoveIfEmpty(room)) + _webhooks.RoomRemoved(context, room); } - _logger.Trace($"Disconnected: {connection.Id}|{context.LobbyPlayer.Name}|{context.LobbyPlayer.Id}"); + _logger.Trace($"Disconnected: {connection.Id}"); } else { @@ -168,7 +175,6 @@ public class RagonServer : INetworkListener _reader.Clear(); _reader.FromArray(data); - // Console.WriteLine($"{string.Join(",", data.Select(d => d.ToString()))}"); var operation = _reader.ReadByte(); _handlers[operation].Handle(context, _reader, _writer); } diff --git a/Ragon.Server/Sources/RagonServerConfiguration.cs b/Ragon.Server/Sources/RagonServerConfiguration.cs index e362e2c..2a327aa 100644 --- a/Ragon.Server/Sources/RagonServerConfiguration.cs +++ b/Ragon.Server/Sources/RagonServerConfiguration.cs @@ -25,6 +25,11 @@ public enum ServerType WEBSOCKET, } +public class WebHook +{ + +} + [Serializable] public struct Configuration { @@ -36,6 +41,7 @@ public struct Configuration public int LimitConnections; public int LimitPlayersPerRoom; public int LimitRooms; + public Dictionary WebHooks; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly string ServerVersion = "1.1.3-rc"; @@ -45,20 +51,6 @@ public struct Configuration {"websocket", Server.ServerType.WEBSOCKET} }; - private static void CopyrightInfo() - { - Logger.Info($"Server Version: {ServerVersion}"); - Logger.Info($"Machine Name: {Environment.MachineName}"); - Logger.Info($"OS: {Environment.OSVersion}"); - Logger.Info($"Processors: {Environment.ProcessorCount}"); - Logger.Info($"Runtime Version: {Environment.Version}"); - Logger.Info("=================================="); - Logger.Info("| |"); - Logger.Info("| Ragon |"); - Logger.Info("| |"); - Logger.Info("=================================="); - } - public static Configuration Load(string filePath) { CopyrightInfo(); @@ -68,5 +60,20 @@ public struct Configuration return configuration; } + private static void CopyrightInfo() + { + Logger.Info($"Server Version: {ServerVersion}"); + Logger.Info($"Machine Name: {Environment.MachineName}"); + Logger.Info($"OS: {Environment.OSVersion}"); + Logger.Info($"Processors: {Environment.ProcessorCount}"); + Logger.Info($"Runtime Version: {Environment.Version}"); + Logger.Info("=================================="); + Logger.Info(@" ___ _ ___ ___ _ _ "); + Logger.Info(@" | _ \ /_\ / __|/ _ \| \| |"); + Logger.Info(@" | / / _ \ (_ | (_) | .` |"); + Logger.Info(@" |_|_\/_/ \_\___|\___/|_|\_|"); + Logger.Info("=================================="); + } + public static ServerType GetServerType(string type) => _serverTypes[type]; } \ No newline at end of file diff --git a/Ragon.Server/Sources/Room/RagonRoom.cs b/Ragon.Server/Sources/Room/RagonRoom.cs index 655820d..039d438 100644 --- a/Ragon.Server/Sources/Room/RagonRoom.cs +++ b/Ragon.Server/Sources/Room/RagonRoom.cs @@ -14,17 +14,24 @@ * limitations under the License. */ -using Ragon.Core.Time; using Ragon.Protocol; +using Ragon.Server.Plugin; +using Ragon.Server.Time; -namespace Ragon.Server; +namespace Ragon.Server.Room; -public class RagonRoom: IRagonAction +public class RagonRoom : IRagonAction { public string Id { get; private set; } - public RoomInformation Info { get; private set; } + public string Map { get; private set; } + public int PlayerMax { get; private set; } + public int PlayerMin { get; private set; } + public int PlayerCount => WaitPlayersList.Count; + public RagonRoomPlayer Owner { get; private set; } - public RagonBuffer Writer { get; } + public RagonBuffer Writer { get; } + public IRoomPlugin Plugin { get; private set; } + public Dictionary Players { get; private set; } public List WaitPlayersList { get; private set; } public List ReadyPlayersList { get; private set; } @@ -37,10 +44,13 @@ public class RagonRoom: IRagonAction private readonly HashSet _entitiesDirtySet; - public RagonRoom(string roomId, RoomInformation info) + public RagonRoom(string roomId, RoomInformation info, IRoomPlugin roomPlugin) { Id = roomId; - Info = info; + Map = info.Map; + PlayerMax = info.Max; + PlayerMin = info.Min; + Plugin = roomPlugin; Players = new Dictionary(info.Max); WaitPlayersList = new List(info.Max); @@ -53,7 +63,7 @@ public class RagonRoom: IRagonAction EntityList = new List(); _entitiesDirtySet = new HashSet(); - + Writer = new RagonBuffer(); } @@ -74,13 +84,13 @@ public class RagonRoom: IRagonAction EntityList.Remove(entity); StaticEntitiesList.Remove(entity); DynamicEntitiesList.Remove(entity); - + _entitiesDirtySet.Remove(entity); } - public void Tick() + public void Tick(float dt) { - var entities = (ushort) _entitiesDirtySet.Count; + var entities = (ushort)_entitiesDirtySet.Count; if (entities > 0) { Writer.Clear(); @@ -88,10 +98,10 @@ public class RagonRoom: IRagonAction Writer.WriteUShort(entities); foreach (var entity in _entitiesDirtySet) - entity.State.Write(Writer); + entity.Write(Writer); _entitiesDirtySet.Clear(); - + var sendData = Writer.ToArray(); foreach (var roomPlayer in ReadyPlayersList) roomPlayer.Connection.Unreliable.Send(sendData); @@ -121,7 +131,7 @@ public class RagonRoom: IRagonAction Writer.WriteString(player.Id); var entitiesToDelete = player.Entities.DynamicList; - Writer.WriteUShort((ushort) entitiesToDelete.Count); + Writer.WriteUShort((ushort)entitiesToDelete.Count); foreach (var entity in entitiesToDelete) { Writer.WriteUShort(entity.Id); @@ -131,34 +141,34 @@ public class RagonRoom: IRagonAction var sendData = Writer.ToArray(); Broadcast(sendData); } - + if (roomPlayer.Connection.Id == Owner.Connection.Id && PlayerList.Count > 0) { var nextOwner = PlayerList[0]; - + Owner = nextOwner; - - var entitiesToUpdate = roomPlayer.Entities.StaticList; - + + var entitiesToUpdate = roomPlayer.Entities.StaticList; + Writer.Clear(); Writer.WriteOperation(RagonOperation.OWNERSHIP_CHANGED); Writer.WriteString(Owner.Id); - Writer.WriteUShort((ushort) entitiesToUpdate.Count); - + Writer.WriteUShort((ushort)entitiesToUpdate.Count); + foreach (var entity in entitiesToUpdate) { Writer.WriteUShort(entity.Id); - - entity.SetOwner(nextOwner); + + entity.Attach(nextOwner); nextOwner.Entities.Add(entity); } var sendData = Writer.ToArray(); Broadcast(sendData); } - + player.OnDetached(); - + UpdateReadyPlayerList(); } } @@ -170,21 +180,16 @@ public class RagonRoom: IRagonAction public void UpdateMap(string sceneName) { - Info = new RoomInformation() - { - Max = Info.Max, - Min = Info.Min, - Map = sceneName, - }; - + Map = sceneName; + DynamicEntitiesList.Clear(); StaticEntitiesList.Clear(); Entities.Clear(); EntityList.Clear(); - + foreach (var player in PlayerList) player.UnsetReady(); - + UpdateReadyPlayerList(); } diff --git a/Ragon.Server/Sources/Room/RagonRoomInformation.cs b/Ragon.Server/Sources/Room/RagonRoomInformation.cs index 6bfd205..1ef8376 100644 --- a/Ragon.Server/Sources/Room/RagonRoomInformation.cs +++ b/Ragon.Server/Sources/Room/RagonRoomInformation.cs @@ -16,14 +16,9 @@ namespace Ragon.Server; -public class RoomInformation +public ref struct RoomInformation { - public string Map { get; init; } = "none"; - public int Min { get; init; } - public int Max { get; init; } - - public override string ToString() - { - return $"Map: {Map} Count: {Min}/{Max}"; - } + public string Map; + public int Min; + public int Max; } \ No newline at end of file diff --git a/Ragon.Server/Sources/Room/RagonRoomPlayer.cs b/Ragon.Server/Sources/Room/RagonRoomPlayer.cs index 47ae625..e034f2a 100644 --- a/Ragon.Server/Sources/Room/RagonRoomPlayer.cs +++ b/Ragon.Server/Sources/Room/RagonRoomPlayer.cs @@ -14,7 +14,9 @@ * limitations under the License. */ -namespace Ragon.Server; +using Ragon.Server.IO; + +namespace Ragon.Server.Room; public class RagonRoomPlayer { diff --git a/Ragon.Server/Sources/Time/IRagonAction.cs b/Ragon.Server/Sources/Time/IRagonAction.cs index 63c9adf..36ec070 100644 --- a/Ragon.Server/Sources/Time/IRagonAction.cs +++ b/Ragon.Server/Sources/Time/IRagonAction.cs @@ -14,9 +14,9 @@ * limitations under the License. */ -namespace Ragon.Core.Time; +namespace Ragon.Server.Time; public interface IRagonAction { - public void Tick(); + public void Tick(float dt); } \ No newline at end of file diff --git a/Ragon.Server/Sources/Time/RagonActionExecutor.cs b/Ragon.Server/Sources/Time/RagonActionExecutor.cs index e6198a7..538b709 100644 --- a/Ragon.Server/Sources/Time/RagonActionExecutor.cs +++ b/Ragon.Server/Sources/Time/RagonActionExecutor.cs @@ -14,7 +14,7 @@ * limitations under the License. */ -namespace Ragon.Core.Time; +namespace Ragon.Server.Time; public class RagonScheduler { @@ -35,9 +35,9 @@ public class RagonScheduler _tasks.Remove(task); } - public void Update() + public void Update(float dt) { foreach (var task in _tasks) - task.Tick(); + task.Tick(dt); } } \ No newline at end of file From 24c9aa204320467892d218ae08b3392a7622e267 Mon Sep 17 00:00:00 2001 From: edmand46 Date: Sun, 9 Apr 2023 11:06:52 +0400 Subject: [PATCH 2/4] :art: namespaces --- Ragon.Relay/Sources/Relay.cs | 2 ++ Ragon.Relay/Sources/RelayRoomPlugin.cs | 3 +++ Ragon.Relay/Sources/RelayServerPlugin.cs | 4 +++- Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs | 3 ++- .../Sources/WebSocketReliableChannel.cs | 2 +- Ragon.Server.DotNetWebSockets/Sources/WebSocketServer.cs | 1 + Ragon.Server.ENet/Sources/ENetConnection.cs | 1 + Ragon.Server.ENet/Sources/ENetReliableChannel.cs | 1 + Ragon.Server.ENet/Sources/ENetServer.cs | 1 + Ragon.Server.ENet/Sources/ENetUnreliableChannel.cs | 1 + Ragon.Server/Sources/Handler/AuthorizationOperation.cs | 2 +- Ragon.Server/Sources/Handler/EntityEventOperation.cs | 2 +- Ragon.Server/Sources/Handler/EntityRemoveOperation.cs | 2 +- Ragon.Server/Sources/Handler/RoomCreateOperation.cs | 3 ++- Ragon.Server/Sources/Handler/RoomJoinOperation.cs | 4 +++- Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs | 5 ++++- Ragon.Server/Sources/Handler/RoomLeaveOperation.cs | 1 + Ragon.Server/Sources/Handler/SceneLoadedOperation.cs | 1 + Ragon.Server/Sources/Plugin/IRoomPlugin.cs | 3 +++ Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs | 4 ++-- Ragon.Server/Sources/RagonEntityCache.cs | 2 ++ Ragon.Server/Sources/RagonServer.cs | 4 ++++ Ragon.Server/Sources/RagonServerConfiguration.cs | 2 +- Ragon.Server/Sources/Room/RagonRoom.cs | 1 + Ragon.Server/Sources/Room/RagonRoomPlayer.cs | 1 + 25 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Ragon.Relay/Sources/Relay.cs b/Ragon.Relay/Sources/Relay.cs index de307ed..a5d8a55 100644 --- a/Ragon.Relay/Sources/Relay.cs +++ b/Ragon.Relay/Sources/Relay.cs @@ -18,6 +18,8 @@ using NLog; using Ragon.Server; using Ragon.Server.ENet; using Ragon.Server.DotNetWebsockets; +using Ragon.Server.IO; +using Ragon.Server.Plugin; namespace Ragon.Relay; diff --git a/Ragon.Relay/Sources/RelayRoomPlugin.cs b/Ragon.Relay/Sources/RelayRoomPlugin.cs index 950b0ed..5a99cd3 100644 --- a/Ragon.Relay/Sources/RelayRoomPlugin.cs +++ b/Ragon.Relay/Sources/RelayRoomPlugin.cs @@ -1,5 +1,8 @@ using System; using Ragon.Server; +using Ragon.Server.Entity; +using Ragon.Server.Plugin; +using Ragon.Server.Room; namespace Ragon.Relay; diff --git a/Ragon.Relay/Sources/RelayServerPlugin.cs b/Ragon.Relay/Sources/RelayServerPlugin.cs index 266128b..f8eee07 100644 --- a/Ragon.Relay/Sources/RelayServerPlugin.cs +++ b/Ragon.Relay/Sources/RelayServerPlugin.cs @@ -1,6 +1,8 @@ -using System; using System.Net.Http; using Ragon.Server; +using Ragon.Server.Lobby; +using Ragon.Server.Plugin; +using Ragon.Server.Room; namespace Ragon.Relay; diff --git a/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs b/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs index 88abcb0..59182c8 100644 --- a/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs +++ b/Ragon.Server.DotNetWebSockets/Sources/WebSocketConnection.cs @@ -14,8 +14,9 @@ * limitations under the License. */ -using System.Net.WebSockets; using NLog; +using System.Net.WebSockets; +using Ragon.Server.IO; namespace Ragon.Server.DotNetWebsockets; diff --git a/Ragon.Server.DotNetWebSockets/Sources/WebSocketReliableChannel.cs b/Ragon.Server.DotNetWebSockets/Sources/WebSocketReliableChannel.cs index 79454df..b310b73 100644 --- a/Ragon.Server.DotNetWebSockets/Sources/WebSocketReliableChannel.cs +++ b/Ragon.Server.DotNetWebSockets/Sources/WebSocketReliableChannel.cs @@ -15,7 +15,7 @@ */ using System.Net.WebSockets; -using Ragon.Server; +using Ragon.Server.IO; namespace Ragon.Server.DotNetWebsockets; diff --git a/Ragon.Server.DotNetWebSockets/Sources/WebSocketServer.cs b/Ragon.Server.DotNetWebSockets/Sources/WebSocketServer.cs index 8e98712..4e94d90 100644 --- a/Ragon.Server.DotNetWebSockets/Sources/WebSocketServer.cs +++ b/Ragon.Server.DotNetWebSockets/Sources/WebSocketServer.cs @@ -18,6 +18,7 @@ using System.Net; using System.Net.WebSockets; using NLog; using Ragon.Protocol; +using Ragon.Server.IO; namespace Ragon.Server.DotNetWebsockets; diff --git a/Ragon.Server.ENet/Sources/ENetConnection.cs b/Ragon.Server.ENet/Sources/ENetConnection.cs index 6f02a18..20b7aba 100644 --- a/Ragon.Server.ENet/Sources/ENetConnection.cs +++ b/Ragon.Server.ENet/Sources/ENetConnection.cs @@ -15,6 +15,7 @@ */ using ENet; +using Ragon.Server.IO; namespace Ragon.Server.ENet; diff --git a/Ragon.Server.ENet/Sources/ENetReliableChannel.cs b/Ragon.Server.ENet/Sources/ENetReliableChannel.cs index 822ba3a..762ae3e 100644 --- a/Ragon.Server.ENet/Sources/ENetReliableChannel.cs +++ b/Ragon.Server.ENet/Sources/ENetReliableChannel.cs @@ -15,6 +15,7 @@ */ using ENet; +using Ragon.Server.IO; namespace Ragon.Server.ENet; diff --git a/Ragon.Server.ENet/Sources/ENetServer.cs b/Ragon.Server.ENet/Sources/ENetServer.cs index 853d934..c953a3d 100644 --- a/Ragon.Server.ENet/Sources/ENetServer.cs +++ b/Ragon.Server.ENet/Sources/ENetServer.cs @@ -17,6 +17,7 @@ using ENet; using NLog; using Ragon.Protocol; +using Ragon.Server.IO; namespace Ragon.Server.ENet { diff --git a/Ragon.Server.ENet/Sources/ENetUnreliableChannel.cs b/Ragon.Server.ENet/Sources/ENetUnreliableChannel.cs index 995fe7c..268128e 100644 --- a/Ragon.Server.ENet/Sources/ENetUnreliableChannel.cs +++ b/Ragon.Server.ENet/Sources/ENetUnreliableChannel.cs @@ -15,6 +15,7 @@ */ using ENet; +using Ragon.Server.IO; namespace Ragon.Server.ENet; diff --git a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs index 1b5dc0c..009681c 100644 --- a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs +++ b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs @@ -16,9 +16,9 @@ using NLog; using Ragon.Protocol; -using Ragon.Server.Hander; using Ragon.Server.Lobby; using Ragon.Server.Plugin; +using Ragon.Server.Plugin.Web; namespace Ragon.Server.Handler; diff --git a/Ragon.Server/Sources/Handler/EntityEventOperation.cs b/Ragon.Server/Sources/Handler/EntityEventOperation.cs index 7eb0fad..18192b8 100644 --- a/Ragon.Server/Sources/Handler/EntityEventOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityEventOperation.cs @@ -16,7 +16,7 @@ using NLog; using Ragon.Protocol; -using Ragon.Server.Hander; +using Ragon.Server.Entity; namespace Ragon.Server.Handler; diff --git a/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs b/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs index d9d2326..e3ec76a 100644 --- a/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs @@ -16,7 +16,7 @@ using NLog; using Ragon.Protocol; -using Ragon.Server.Hander; +using Ragon.Server.Entity; namespace Ragon.Server.Handler; diff --git a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs index f375a35..b4673b6 100644 --- a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs @@ -18,9 +18,10 @@ using NLog; using Ragon.Protocol; using Ragon.Server.Lobby; using Ragon.Server.Plugin; +using Ragon.Server.Plugin.Web; using Ragon.Server.Room; -namespace Ragon.Server.Hander; +namespace Ragon.Server.Handler; public sealed class RoomCreateOperation: IRagonOperation { diff --git a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs index 08039f8..f023dc2 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs @@ -16,7 +16,9 @@ using NLog; using Ragon.Protocol; -using Ragon.Server.Web; +using Ragon.Server.Plugin; +using Ragon.Server.Plugin.Web; +using Ragon.Server.Room; namespace Ragon.Server.Handler; diff --git a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs index 192ea60..4d409c6 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs @@ -16,7 +16,10 @@ using NLog; using Ragon.Protocol; -using Ragon.Server.Web; +using Ragon.Server.Lobby; +using Ragon.Server.Plugin; +using Ragon.Server.Plugin.Web; +using Ragon.Server.Room; namespace Ragon.Server.Handler; diff --git a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs index 1f1bf06..a2b1960 100644 --- a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs @@ -17,6 +17,7 @@ using NLog; using Ragon.Protocol; using Ragon.Server.Plugin; +using Ragon.Server.Plugin.Web; namespace Ragon.Server.Handler; diff --git a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs index 0350fd6..f489887 100644 --- a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs +++ b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs @@ -17,6 +17,7 @@ using NLog; using Ragon.Protocol; using Ragon.Server.Entity; +using Ragon.Server.Lobby; using Ragon.Server.Room; namespace Ragon.Server.Handler; diff --git a/Ragon.Server/Sources/Plugin/IRoomPlugin.cs b/Ragon.Server/Sources/Plugin/IRoomPlugin.cs index 7c85edb..6b261a4 100644 --- a/Ragon.Server/Sources/Plugin/IRoomPlugin.cs +++ b/Ragon.Server/Sources/Plugin/IRoomPlugin.cs @@ -14,6 +14,9 @@ * limitations under the License. */ +using Ragon.Server.Entity; +using Ragon.Server.Room; + namespace Ragon.Server.Plugin; public interface IRoomPlugin diff --git a/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs b/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs index 0a8190f..980bb18 100644 --- a/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs +++ b/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs @@ -2,11 +2,11 @@ using System.Net; using System.Net.Http.Json; using Newtonsoft.Json; using Ragon.Protocol; +using Ragon.Server.Handler; using Ragon.Server.Lobby; -using Ragon.Server.Plugin.Web; using Ragon.Server.Room; -namespace Ragon.Server.Plugin; +namespace Ragon.Server.Plugin.Web; public class WebHookPlugin { diff --git a/Ragon.Server/Sources/RagonEntityCache.cs b/Ragon.Server/Sources/RagonEntityCache.cs index 9a55352..53f091b 100644 --- a/Ragon.Server/Sources/RagonEntityCache.cs +++ b/Ragon.Server/Sources/RagonEntityCache.cs @@ -14,6 +14,8 @@ * limitations under the License. */ +using Ragon.Server.Entity; + namespace Ragon.Server; public class RagonEntityCache diff --git a/Ragon.Server/Sources/RagonServer.cs b/Ragon.Server/Sources/RagonServer.cs index 0b87e3b..d47955c 100644 --- a/Ragon.Server/Sources/RagonServer.cs +++ b/Ragon.Server/Sources/RagonServer.cs @@ -17,7 +17,11 @@ using System.Diagnostics; using NLog; using Ragon.Protocol; +using Ragon.Server.Handler; +using Ragon.Server.IO; +using Ragon.Server.Lobby; using Ragon.Server.Plugin; +using Ragon.Server.Plugin.Web; using Ragon.Server.Time; namespace Ragon.Server; diff --git a/Ragon.Server/Sources/RagonServerConfiguration.cs b/Ragon.Server/Sources/RagonServerConfiguration.cs index 2a327aa..5b14c50 100644 --- a/Ragon.Server/Sources/RagonServerConfiguration.cs +++ b/Ragon.Server/Sources/RagonServerConfiguration.cs @@ -44,7 +44,7 @@ public struct Configuration public Dictionary WebHooks; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private static readonly string ServerVersion = "1.1.3-rc"; + private static readonly string ServerVersion = "1.2.0-rc"; private static Dictionary _serverTypes = new Dictionary() { {"enet", Server.ServerType.ENET}, diff --git a/Ragon.Server/Sources/Room/RagonRoom.cs b/Ragon.Server/Sources/Room/RagonRoom.cs index 039d438..af65d47 100644 --- a/Ragon.Server/Sources/Room/RagonRoom.cs +++ b/Ragon.Server/Sources/Room/RagonRoom.cs @@ -15,6 +15,7 @@ */ using Ragon.Protocol; +using Ragon.Server.Entity; using Ragon.Server.Plugin; using Ragon.Server.Time; diff --git a/Ragon.Server/Sources/Room/RagonRoomPlayer.cs b/Ragon.Server/Sources/Room/RagonRoomPlayer.cs index e034f2a..5cc2c32 100644 --- a/Ragon.Server/Sources/Room/RagonRoomPlayer.cs +++ b/Ragon.Server/Sources/Room/RagonRoomPlayer.cs @@ -14,6 +14,7 @@ * limitations under the License. */ +using Ragon.Server.Entity; using Ragon.Server.IO; namespace Ragon.Server.Room; From e1a9ad476c2965bfdfe80095620521b4b539da97 Mon Sep 17 00:00:00 2001 From: edmand46 Date: Thu, 13 Apr 2023 20:42:05 +0400 Subject: [PATCH 3/4] :sparkles: http-commands --- .../Sources/Command/KickPlayerCommand.cs | 6 ++ Ragon.Relay/Sources/RelayRoomPlugin.cs | 2 +- Ragon.Relay/Sources/RelayServerPlugin.cs | 47 +++------ Ragon.Relay/relay.config.json | 2 + .../Sources/Handler/AuthorizationOperation.cs | 18 ++-- .../Sources/Handler/RoomCreateOperation.cs | 10 +- .../Sources/Handler/RoomJoinOperation.cs | 8 +- .../Handler/RoomJoinOrCreateOperation.cs | 10 +- .../Sources/Handler/RoomLeaveOperation.cs | 8 +- Ragon.Server/Sources/Http/RagonHttpServer.cs | 97 +++++++++++++++++++ Ragon.Server/Sources/IO/Executor.cs | 25 +++-- Ragon.Server/Sources/IO/IExecutor.cs | 2 +- Ragon.Server/Sources/IRagonContextObserver.cs | 15 +++ Ragon.Server/Sources/IRagonServer.cs | 9 ++ .../Sources/Lobby/RagonLobbyPlayer.cs | 6 +- Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs | 53 ++++++++++ .../Sources/Plugin/BaseServerPlugin.cs | 62 ++++++++++++ Ragon.Server/Sources/Plugin/IRoomPlugin.cs | 2 +- Ragon.Server/Sources/Plugin/IServerPlugin.cs | 5 +- .../Sources/Plugin/Web/Dto/PlayerDto.cs | 16 +++ .../Sources/Plugin/Web/Dto/RoomDto.cs | 23 +++++ ...WebHookPlugin.cs => RagonWebHookPlugin.cs} | 23 +++-- .../Plugin/Web/Request/RoomCreatedRequest.cs | 4 +- .../Plugin/Web/Request/RoomJoinedRequest.cs | 5 +- .../Plugin/Web/Request/RoomLeavedRequest.cs | 3 +- .../Plugin/Web/Request/RoomRemovedRequest.cs | 4 +- Ragon.Server/Sources/RagonContext.cs | 3 +- Ragon.Server/Sources/RagonServer.cs | 45 ++++++--- .../Sources/RagonServerConfiguration.cs | 2 + Ragon.Server/Sources/Room/IRagonRoom.cs | 9 ++ Ragon.Server/Sources/Room/RagonRoom.cs | 8 +- 31 files changed, 428 insertions(+), 104 deletions(-) create mode 100644 Ragon.Relay/Sources/Command/KickPlayerCommand.cs create mode 100644 Ragon.Server/Sources/Http/RagonHttpServer.cs create mode 100644 Ragon.Server/Sources/IRagonContextObserver.cs create mode 100644 Ragon.Server/Sources/IRagonServer.cs create mode 100644 Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs create mode 100644 Ragon.Server/Sources/Plugin/BaseServerPlugin.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs create mode 100644 Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs rename Ragon.Server/Sources/Plugin/Web/{WebHookPlugin.cs => RagonWebHookPlugin.cs} (79%) create mode 100644 Ragon.Server/Sources/Room/IRagonRoom.cs diff --git a/Ragon.Relay/Sources/Command/KickPlayerCommand.cs b/Ragon.Relay/Sources/Command/KickPlayerCommand.cs new file mode 100644 index 0000000..8fdcd9a --- /dev/null +++ b/Ragon.Relay/Sources/Command/KickPlayerCommand.cs @@ -0,0 +1,6 @@ +namespace Ragon.Relay; + +public class KickPlayerCommand +{ + public string Id; +} \ No newline at end of file diff --git a/Ragon.Relay/Sources/RelayRoomPlugin.cs b/Ragon.Relay/Sources/RelayRoomPlugin.cs index 5a99cd3..c0d95a2 100644 --- a/Ragon.Relay/Sources/RelayRoomPlugin.cs +++ b/Ragon.Relay/Sources/RelayRoomPlugin.cs @@ -6,7 +6,7 @@ using Ragon.Server.Room; namespace Ragon.Relay; -public class RelayRoomPlugin: IRoomPlugin +public class RelayRoomPlugin: BaseRoomPlugin { public void Tick(float dt) { diff --git a/Ragon.Relay/Sources/RelayServerPlugin.cs b/Ragon.Relay/Sources/RelayServerPlugin.cs index f8eee07..c98ee4c 100644 --- a/Ragon.Relay/Sources/RelayServerPlugin.cs +++ b/Ragon.Relay/Sources/RelayServerPlugin.cs @@ -1,41 +1,24 @@ -using System.Net.Http; -using Ragon.Server; -using Ragon.Server.Lobby; +using System; +using Newtonsoft.Json; using Ragon.Server.Plugin; -using Ragon.Server.Room; namespace Ragon.Relay; -public class RelayServerPlugin: IServerPlugin +public class RelayServerPlugin: BaseServerPlugin { - private HttpClient httpClient; - public IRoomPlugin CreateRoomPlugin(RoomInformation information) - { - return new RelayRoomPlugin(); - } - - public RelayServerPlugin() - { - httpClient = new HttpClient(); - } - - public bool OnRoomCreate(RagonLobbyPlayer player, RagonRoom room) - { - return true; - } - - public bool OnRoomRemove(RagonLobbyPlayer player, RagonRoom room) - { - return true; - } - - public bool OnRoomLeave(RagonRoomPlayer player, RagonRoom room) - { - return true; - } - - public bool OnRoomJoin(RagonRoomPlayer player, RagonRoom room) + public override bool OnCommand(string command, string payload) { + Console.WriteLine(command); + if (command == "kick-player") + { + var commandPayload = JsonConvert.DeserializeObject(payload); + var player = GetPlayerById(commandPayload.Id); + if (player != null) + player.Connection.Close(); + else + Console.WriteLine($"Player not found with Id {commandPayload.Id}"); + } + return true; } } \ No newline at end of file diff --git a/Ragon.Relay/relay.config.json b/Ragon.Relay/relay.config.json index 7be2b89..3e61bde 100644 --- a/Ragon.Relay/relay.config.json +++ b/Ragon.Relay/relay.config.json @@ -4,6 +4,8 @@ "serverTickRate": 30, "gameProtocol": "1.0.0", "port": 5000, + "httpPort": 5001, + "httpKey": "defaultkey", "limitConnections": 4095, "limitPlayersPerRoom": 20, "limitRooms": 200, diff --git a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs index 009681c..b76e6ee 100644 --- a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs +++ b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs @@ -26,17 +26,19 @@ namespace Ragon.Server.Handler; public sealed class AuthorizationOperation: IRagonOperation { private Logger _logger = LogManager.GetCurrentClassLogger(); - private readonly WebHookPlugin _webHook; + private readonly RagonWebHookPlugin _ragonWebHook; + private readonly RagonContextObserver _contextObserver; private readonly Configuration _configuration; private readonly RagonBuffer _writer; - public AuthorizationOperation( - WebHookPlugin webHook, + public AuthorizationOperation(RagonWebHookPlugin ragonWebHook, + RagonContextObserver contextObserver, RagonBuffer writer, Configuration configuration) { - _webHook = webHook; + _ragonWebHook = ragonWebHook; _configuration = configuration; + _contextObserver = contextObserver; _writer = writer; } @@ -60,10 +62,10 @@ public sealed class AuthorizationOperation: IRagonOperation if (key == _configuration.ServerKey) { - if (_webHook.RequestAuthorization(context, name, payload)) + if (_ragonWebHook.RequestAuthorization(context, name, payload)) return; - var lobbyPlayer = new RagonLobbyPlayer(Guid.NewGuid().ToString(), name, payload); + var lobbyPlayer = new RagonLobbyPlayer(context.Connection, Guid.NewGuid().ToString(), name, payload); context.SetPlayer(lobbyPlayer); Approve(context); @@ -77,7 +79,9 @@ public sealed class AuthorizationOperation: IRagonOperation public void Approve(RagonContext context) { context.ConnectionStatus = ConnectionStatus.Authorized; - + + _contextObserver.OnAuthorized(context); + var playerId = context.LobbyPlayer.Id; var playerName = context.LobbyPlayer.Name; var playerPayload = context.LobbyPlayer.Payload; diff --git a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs index b4673b6..011edd5 100644 --- a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs @@ -28,12 +28,12 @@ public sealed class RoomCreateOperation: IRagonOperation private readonly RagonRoomParameters _roomParameters = new(); private readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly IServerPlugin _serverPlugin; - private readonly WebHookPlugin _webHookPlugin; + private readonly RagonWebHookPlugin _ragonWebHookPlugin; - public RoomCreateOperation(IServerPlugin serverPlugin, WebHookPlugin webHook) + public RoomCreateOperation(IServerPlugin serverPlugin, RagonWebHookPlugin ragonWebHook) { _serverPlugin = serverPlugin; - _webHookPlugin = webHook; + _ragonWebHookPlugin = ragonWebHook; } public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) @@ -79,11 +79,13 @@ public sealed class RoomCreateOperation: IRagonOperation var roomPlugin = _serverPlugin.CreateRoomPlugin(information); var room = new RagonRoom(roomId, information, roomPlugin); + roomPlayer.OnAttached(room); + context.Scheduler.Run(room); context.Lobby.Persist(room); context.SetRoom(room, roomPlayer); - _webHookPlugin.RoomCreated(context, room); + _ragonWebHookPlugin.RoomCreated(context, room, roomPlayer); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} with map {information.Map}"); diff --git a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs index f023dc2..c9f2cb6 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs @@ -26,12 +26,12 @@ public sealed class RoomJoinOperation : IRagonOperation { private readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly IServerPlugin _serverPlugin; - private readonly WebHookPlugin _webHookPlugin; + private readonly RagonWebHookPlugin _ragonWebHookPlugin; - public RoomJoinOperation(IServerPlugin serverPlugin, WebHookPlugin plugin) + public RoomJoinOperation(IServerPlugin serverPlugin, RagonWebHookPlugin plugin) { _serverPlugin = serverPlugin; - _webHookPlugin = plugin; + _ragonWebHookPlugin = plugin; } public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) @@ -53,7 +53,7 @@ public sealed class RoomJoinOperation : IRagonOperation if (!_serverPlugin.OnRoomJoin(player, existsRoom)) return; - _webHookPlugin.RoomJoined(context, existsRoom, player); + _ragonWebHookPlugin.RoomJoined(context, existsRoom, player); JoinSuccess(context, existsRoom, writer); diff --git a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs index 4d409c6..74f1a4d 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs @@ -28,12 +28,12 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation private readonly RagonRoomParameters _roomParameters = new(); private readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly IServerPlugin _serverPlugin; - private readonly WebHookPlugin _webHookPlugin; + private readonly RagonWebHookPlugin _ragonWebHookPlugin; - public RoomJoinOrCreateOperation(IServerPlugin serverPlugin, WebHookPlugin plugin) + public RoomJoinOrCreateOperation(IServerPlugin serverPlugin, RagonWebHookPlugin plugin) { _serverPlugin = serverPlugin; - _webHookPlugin = plugin; + _ragonWebHookPlugin = plugin; } public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) @@ -54,7 +54,7 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation var player = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name); context.SetRoom(existsRoom, player); - _webHookPlugin.RoomJoined(context, existsRoom, player); + _ragonWebHookPlugin.RoomJoined(context, existsRoom, player); JoinSuccess(player, existsRoom, writer); } @@ -71,7 +71,7 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation var roomPlugin = _serverPlugin.CreateRoomPlugin(information); var room = new RagonRoom(roomId, information, roomPlugin); - _webHookPlugin.RoomCreated(context, room); + _ragonWebHookPlugin.RoomCreated(context, room, roomPlayer); context.Lobby.Persist(room); context.Scheduler.Run(room); diff --git a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs index a2b1960..4de5f6c 100644 --- a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs @@ -25,11 +25,11 @@ public sealed class RoomLeaveOperation: IRagonOperation { private readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly IServerPlugin _serverPlugin; - private readonly WebHookPlugin _webHookPlugin; - public RoomLeaveOperation(IServerPlugin serverPlugin, WebHookPlugin plugin) + private readonly RagonWebHookPlugin _ragonWebHookPlugin; + public RoomLeaveOperation(IServerPlugin serverPlugin, RagonWebHookPlugin plugin) { _serverPlugin = serverPlugin; - _webHookPlugin = plugin; + _ragonWebHookPlugin = plugin; } public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) @@ -40,7 +40,7 @@ public sealed class RoomLeaveOperation: IRagonOperation if (room != null) { _serverPlugin.OnRoomLeave(roomPlayer, room); - _webHookPlugin.RoomLeaved(context, room, roomPlayer); + _ragonWebHookPlugin.RoomLeaved(context, room, roomPlayer); context.Room?.DetachPlayer(roomPlayer); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} leaved from {room.Id}"); } diff --git a/Ragon.Server/Sources/Http/RagonHttpServer.cs b/Ragon.Server/Sources/Http/RagonHttpServer.cs new file mode 100644 index 0000000..20c8d45 --- /dev/null +++ b/Ragon.Server/Sources/Http/RagonHttpServer.cs @@ -0,0 +1,97 @@ +using NLog; +using System.Net; +using System.Text.Json; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Ragon.Server.IO; +using Ragon.Server.Plugin; + +namespace Ragon.Server.Http; + +public class RagonHttpServer +{ + private readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private readonly IExecutor _executor; + private readonly IServerPlugin _serverPlugin; + private HttpListener _httpListener; + private CancellationTokenSource _cancellationTokenSource; + + public RagonHttpServer(IExecutor executor, IServerPlugin serverPlugin) + { + _serverPlugin = serverPlugin; + _executor = executor; + } + + public async void StartAccept(CancellationToken cancellationToken) + { + while (!cancellationToken.IsCancellationRequested) + { + var context = await _httpListener.GetContextAsync(); + + if (context.Request.HttpMethod != "POST") + { + context.Response.StatusCode = 404; + context.Response.ContentLength64 = 0; + context.Response.Close(); + } + + var request = context.Request; + var reader = new StreamReader(request.InputStream, request.ContentEncoding); + var rawJson = await reader.ReadToEndAsync(); + var httpCommand = JsonDocument.Parse(rawJson); + if (httpCommand != null) + { + try + { + var command = httpCommand.RootElement.GetProperty("command"); + var payload = httpCommand.RootElement.GetProperty("payload"); + + if (_serverPlugin.OnCommand(command.GetString() ?? "none", payload.GetRawText())) + { + context.Response.StatusCode = 200; + context.Response.ContentLength64 = 0; + context.Response.Close(); + } + else + { + context.Response.StatusCode = 403; + context.Response.ContentLength64 = 0; + context.Response.Close(); + } + } + catch (Exception ex) + { + _logger.Error(ex); + + context.Response.StatusCode = 505; + context.Response.ContentLength64 = 0; + context.Response.Close(); + } + + continue; + } + + context.Response.StatusCode = 403; + context.Response.ContentLength64 = 0; + context.Response.Close(); + } + } + + public void Start(Configuration configuration) + { + _cancellationTokenSource = new CancellationTokenSource(); + _logger.Info($"Listen at http://0.0.0.0:{configuration.HttpPort}/"); + + _httpListener = new HttpListener(); + _httpListener.Prefixes.Add($"http://127.0.0.1:{configuration.HttpPort}/"); + _httpListener.Start(); + + _executor.Run(() => StartAccept(_cancellationTokenSource.Token), TaskCreationOptions.LongRunning); + } + + public void Stop() + { + _cancellationTokenSource.Cancel(); + _httpListener.Stop(); + } +} \ No newline at end of file diff --git a/Ragon.Server/Sources/IO/Executor.cs b/Ragon.Server/Sources/IO/Executor.cs index a93d38b..050b872 100644 --- a/Ragon.Server/Sources/IO/Executor.cs +++ b/Ragon.Server/Sources/IO/Executor.cs @@ -18,24 +18,29 @@ using System.Threading.Channels; namespace Ragon.Server.IO; -public class Executor: TaskScheduler, IExecutor +public class Executor : TaskScheduler, IExecutor { - private ChannelReader _reader; - private ChannelWriter _writer; - private Queue _pendingTasks; - private TaskFactory _taskFactory; + private readonly ChannelReader _reader; + private readonly ChannelWriter _writer; + private readonly Queue _pendingTasks; + private readonly TaskFactory _taskFactory; - public Task Run(Action action) + public Task Run(Action action, TaskCreationOptions task = TaskCreationOptions.None) { - return _taskFactory.StartNew(action); + return _taskFactory.StartNew(action, task); } public Executor() { - var channel = Channel.CreateUnbounded(); + var channel = Channel.CreateUnbounded(new UnboundedChannelOptions() + { + SingleReader = true, + SingleWriter = true, + }); + _reader = channel.Reader; _writer = channel.Writer; - + _taskFactory = new TaskFactory(this); _pendingTasks = new Queue(); } @@ -60,7 +65,7 @@ public class Executor: TaskScheduler, IExecutor while (_reader.TryRead(out var task)) { TryExecuteTask(task); - + if (task.Status == TaskStatus.Running) _pendingTasks.Enqueue(task); } diff --git a/Ragon.Server/Sources/IO/IExecutor.cs b/Ragon.Server/Sources/IO/IExecutor.cs index b163838..da9f11d 100644 --- a/Ragon.Server/Sources/IO/IExecutor.cs +++ b/Ragon.Server/Sources/IO/IExecutor.cs @@ -18,5 +18,5 @@ namespace Ragon.Server.IO; public interface IExecutor { - public Task Run(Action action); + public Task Run(Action action, TaskCreationOptions task = TaskCreationOptions.None); } \ No newline at end of file diff --git a/Ragon.Server/Sources/IRagonContextObserver.cs b/Ragon.Server/Sources/IRagonContextObserver.cs new file mode 100644 index 0000000..667a301 --- /dev/null +++ b/Ragon.Server/Sources/IRagonContextObserver.cs @@ -0,0 +1,15 @@ +namespace Ragon.Server; + +public class RagonContextObserver +{ + private Dictionary _contexts; + public RagonContextObserver(Dictionary contexts) + { + _contexts = contexts; + } + + public void OnAuthorized(RagonContext context) + { + _contexts.Add(context.LobbyPlayer.Id, context); + } +} \ No newline at end of file diff --git a/Ragon.Server/Sources/IRagonServer.cs b/Ragon.Server/Sources/IRagonServer.cs new file mode 100644 index 0000000..318774c --- /dev/null +++ b/Ragon.Server/Sources/IRagonServer.cs @@ -0,0 +1,9 @@ +using Ragon.Server.IO; + +namespace Ragon.Server; + +public interface IRagonServer +{ + RagonContext? ResolveContext(INetworkConnection connection); + RagonContext? ResolveContext(string id); +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs b/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs index 4c241e3..69377eb 100644 --- a/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs +++ b/Ragon.Server/Sources/Lobby/RagonLobbyPlayer.cs @@ -14,6 +14,8 @@ * limitations under the License. */ +using Ragon.Server.IO; + namespace Ragon.Server.Lobby; public enum ConnectionStatus @@ -25,14 +27,16 @@ public enum ConnectionStatus public class RagonLobbyPlayer { + public INetworkConnection Connection { get; } public string Id { get; private set; } public string Name { get; private set; } public string Payload { get; private set; } - public RagonLobbyPlayer(string id, string name, string payload) + public RagonLobbyPlayer(INetworkConnection connection, string id, string name, string payload) { Id = id; Name = name; Payload = payload; + Connection = connection; } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs b/Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs new file mode 100644 index 0000000..8c1562d --- /dev/null +++ b/Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs @@ -0,0 +1,53 @@ +using Ragon.Server.Entity; +using Ragon.Server.IO; +using Ragon.Server.Lobby; +using Ragon.Server.Room; +using Ragon.Server.Time; + +namespace Ragon.Server.Plugin; + +public class BaseRoomPlugin: IRoomPlugin +{ + private IRagonRoom _ragonRoom; + + public RagonRoomPlayer GetPlayerById(string id) + { + var player = _ragonRoom.GetPlayerById(id); + return player; + } + + public RagonRoomPlayer GetPlayerByConnection(INetworkConnection connection) + { + var player = _ragonRoom.GetPlayerByConnection(connection); + return player; + } + + public virtual void OnAttached(IRagonRoom room) + { + _ragonRoom = room; + } + + public virtual void OnDetached() + { + + } + + #region VIRTUAL + + public virtual void Tick(float dt) + { + + } + + public virtual bool OnEntityCreate(RagonRoomPlayer creator, RagonEntity entity) + { + return true; + } + + public virtual bool OnEntityRemove(RagonRoomPlayer remover, RagonEntity entity) + { + return true; + } + + #endregion +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/BaseServerPlugin.cs b/Ragon.Server/Sources/Plugin/BaseServerPlugin.cs new file mode 100644 index 0000000..2a064e0 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/BaseServerPlugin.cs @@ -0,0 +1,62 @@ +using Ragon.Server.IO; +using Ragon.Server.Lobby; +using Ragon.Server.Room; + +namespace Ragon.Server.Plugin; + +public class BaseServerPlugin: IServerPlugin +{ + private IRagonServer _ragonServer; + + public RagonLobbyPlayer? GetPlayerById(string id) + { + var context = _ragonServer.ResolveContext(id); + return context?.LobbyPlayer; + } + + public RagonLobbyPlayer? GetPlayerByConnection(INetworkConnection connection) + { + var context = _ragonServer.ResolveContext(connection); + return context?.LobbyPlayer; + } + + public void OnAttached(IRagonServer server) + { + _ragonServer = server; + } + + public void OnDetached() + { + + } + + public virtual bool OnRoomCreate(RagonLobbyPlayer player, RagonRoom room) + { + return true; + } + + public virtual bool OnRoomRemove(RagonLobbyPlayer player, RagonRoom room) + { + return true; + } + + public virtual bool OnRoomLeave(RagonRoomPlayer player, RagonRoom room) + { + return true; + } + + public virtual bool OnRoomJoin(RagonRoomPlayer player, RagonRoom room) + { + return true; + } + + public virtual bool OnCommand(string command, string payload) + { + return true; + } + + public IRoomPlugin CreateRoomPlugin(RoomInformation information) + { + return new BaseRoomPlugin(); + } +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/IRoomPlugin.cs b/Ragon.Server/Sources/Plugin/IRoomPlugin.cs index 6b261a4..679707e 100644 --- a/Ragon.Server/Sources/Plugin/IRoomPlugin.cs +++ b/Ragon.Server/Sources/Plugin/IRoomPlugin.cs @@ -22,7 +22,7 @@ namespace Ragon.Server.Plugin; public interface IRoomPlugin { void Tick(float dt); - void OnAttached(); + void OnAttached(IRagonRoom room); void OnDetached(); bool OnEntityCreate(RagonRoomPlayer creator, RagonEntity entity); bool OnEntityRemove(RagonRoomPlayer remover, RagonEntity entity); diff --git a/Ragon.Server/Sources/Plugin/IServerPlugin.cs b/Ragon.Server/Sources/Plugin/IServerPlugin.cs index 73f2410..cad278e 100644 --- a/Ragon.Server/Sources/Plugin/IServerPlugin.cs +++ b/Ragon.Server/Sources/Plugin/IServerPlugin.cs @@ -14,6 +14,7 @@ * limitations under the License. */ +using Ragon.Server.Http; using Ragon.Server.Lobby; using Ragon.Server.Room; @@ -21,10 +22,12 @@ namespace Ragon.Server.Plugin; public interface IServerPlugin { + void OnAttached(IRagonServer server); + void OnDetached(); bool OnRoomCreate(RagonLobbyPlayer player, RagonRoom room); bool OnRoomRemove(RagonLobbyPlayer player, RagonRoom room); bool OnRoomLeave(RagonRoomPlayer player, RagonRoom room); bool OnRoomJoin(RagonRoomPlayer player, RagonRoom room); - + bool OnCommand(string command, string payload); IRoomPlugin CreateRoomPlugin(RoomInformation information); } \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs b/Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs new file mode 100644 index 0000000..5703f64 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs @@ -0,0 +1,16 @@ +using Ragon.Server.Room; + +namespace Ragon.Server.Plugin.Web; + +[Serializable] +public class PlayerDto +{ + public string Id { get; set;} + public string Name { get; set; } + + public PlayerDto(RagonRoomPlayer ragonRoomPlayer) + { + Id = ragonRoomPlayer.Id; + Name = ragonRoomPlayer.Name; + } +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs b/Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs new file mode 100644 index 0000000..bbe0b13 --- /dev/null +++ b/Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs @@ -0,0 +1,23 @@ +using Ragon.Server.Room; + +namespace Ragon.Server.Plugin.Web; + +[Serializable] +public class RoomDto +{ + public string Id { get; set;} + public int PlayerMin { get; set; } + public int PlayerMax { get; set; } + public int PlayerCount { get; set; } + public PlayerDto[] Players { get; set; } + + public RoomDto(RagonRoom room) + { + Id = room.Id; + PlayerMin = room.PlayerMin; + PlayerMax = room.PlayerMax; + PlayerCount = room.PlayerCount; + + Players = room.PlayerList.Select(p => new PlayerDto(p)).ToArray(); + } +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs b/Ragon.Server/Sources/Plugin/Web/RagonWebHookPlugin.cs similarity index 79% rename from Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs rename to Ragon.Server/Sources/Plugin/Web/RagonWebHookPlugin.cs index 980bb18..b52a36a 100644 --- a/Ragon.Server/Sources/Plugin/Web/WebHookPlugin.cs +++ b/Ragon.Server/Sources/Plugin/Web/RagonWebHookPlugin.cs @@ -8,14 +8,14 @@ using Ragon.Server.Room; namespace Ragon.Server.Plugin.Web; -public class WebHookPlugin +public class RagonWebHookPlugin { private Dictionary _webHooks; private RagonServer _server; private HttpClient _httpClient; - public WebHookPlugin(RagonServer server, Configuration configuration) + public RagonWebHookPlugin(RagonServer server, Configuration configuration) { _webHooks = new Dictionary(configuration.WebHooks); _httpClient = new HttpClient(); @@ -30,7 +30,7 @@ public class WebHookPlugin var executor = context.Executor; executor.Run(async () => { - var authorizationOperation = (AuthorizationOperation) _server.Resolve(RagonOperation.AUTHORIZE); + var authorizationOperation = (AuthorizationOperation) _server.ResolveOperation(RagonOperation.AUTHORIZE); var response = await _httpClient.PostAsync(new Uri(value), httpContent); if (response.StatusCode != HttpStatusCode.OK) { @@ -42,7 +42,7 @@ public class WebHookPlugin var authorizationResponse = JsonConvert.DeserializeObject(content); if (authorizationResponse != null) { - var lobbyPlayer = new RagonLobbyPlayer(authorizationResponse.Id, authorizationResponse.Name, authorizationResponse.Payload); + var lobbyPlayer = new RagonLobbyPlayer(context.Connection, authorizationResponse.Id, authorizationResponse.Name, authorizationResponse.Payload); context.SetPlayer(lobbyPlayer); authorizationOperation.Approve(context); @@ -58,12 +58,14 @@ public class WebHookPlugin return false; } - public void RoomCreated(RagonContext context, RagonRoom room) + public void RoomCreated(RagonContext context, RagonRoom room, RagonRoomPlayer player) { if (_webHooks.TryGetValue("room-created", out var value) && !string.IsNullOrEmpty(value)) { var request = new RoomCreatedRequest() { + Room = new RoomDto(room), + Player = new PlayerDto(player) }; var content = JsonContent.Create(request); var executor = context.Executor; @@ -75,8 +77,9 @@ public class WebHookPlugin { if (_webHooks.TryGetValue("room-removed", out var value) && !string.IsNullOrEmpty(value)) { - var request = new RoomCreatedRequest() + var request = new RoomRemovedRequest() { + Room = new RoomDto(ragonRoom) }; var content = JsonContent.Create(request); var executor = context.Executor; @@ -88,8 +91,10 @@ public class WebHookPlugin { if (_webHooks.TryGetValue("room-joined", out var value) && !string.IsNullOrEmpty(value)) { - var request = new RoomCreatedRequest() + var request = new RoomJoinedRequest() { + Room = new RoomDto(existsRoom), + Player = new PlayerDto(player) }; var content = JsonContent.Create(request); var executor = context.Executor; @@ -101,8 +106,10 @@ public class WebHookPlugin { if (_webHooks.TryGetValue("room-leaved", out var value) && !string.IsNullOrEmpty(value)) { - var request = new RoomCreatedRequest() + var request = new RoomLeavedRequest() { + Room = new RoomDto(room), + Player = new PlayerDto(roomPlayer) }; var content = JsonContent.Create(request); var executor = context.Executor; diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs index 539d8c1..1d54a20 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs @@ -1,7 +1,9 @@ + namespace Ragon.Server.Plugin.Web; [Serializable] public class RoomCreatedRequest { - + public RoomDto Room { get; set; } + public PlayerDto Player { get; set; } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs index 51474c8..54722ae 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs @@ -2,5 +2,6 @@ namespace Ragon.Server.Plugin.Web; public class RoomJoinedRequest { - -} \ No newline at end of file + public RoomDto Room { get; set; } + public PlayerDto Player { get; set; } +} diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs index 495a9f0..1787a4c 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs @@ -3,5 +3,6 @@ namespace Ragon.Server.Plugin.Web; [Serializable] public class RoomLeavedRequest { - + public RoomDto Room { get; set; } + public PlayerDto Player { get; set; } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs index 09731d7..e0917b3 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs @@ -1,7 +1,9 @@ +using Ragon.Server.Plugin.Web; + namespace Ragon.Server.Plugin.Web; [Serializable] public class RoomRemovedRequest { - + public RoomDto Room { get; set; } } \ No newline at end of file diff --git a/Ragon.Server/Sources/RagonContext.cs b/Ragon.Server/Sources/RagonContext.cs index 5c72877..4aafa22 100644 --- a/Ragon.Server/Sources/RagonContext.cs +++ b/Ragon.Server/Sources/RagonContext.cs @@ -23,9 +23,8 @@ namespace Ragon.Server; public class RagonContext { - public INetworkConnection Connection { get; } public ConnectionStatus ConnectionStatus { get; set; } - + public INetworkConnection Connection { get; } public IExecutor Executor { get; private set; } public IRagonLobby Lobby { get; private set; } diff --git a/Ragon.Server/Sources/RagonServer.cs b/Ragon.Server/Sources/RagonServer.cs index d47955c..d49c336 100644 --- a/Ragon.Server/Sources/RagonServer.cs +++ b/Ragon.Server/Sources/RagonServer.cs @@ -18,6 +18,7 @@ using System.Diagnostics; using NLog; using Ragon.Protocol; using Ragon.Server.Handler; +using Ragon.Server.Http; using Ragon.Server.IO; using Ragon.Server.Lobby; using Ragon.Server.Plugin; @@ -26,20 +27,23 @@ using Ragon.Server.Time; namespace Ragon.Server; -public class RagonServer : INetworkListener +public class RagonServer : IRagonServer, INetworkListener { private readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly INetworkServer _server; + private readonly IRagonOperation[] _handlers; + private readonly IRagonLobby _lobby; + private readonly IServerPlugin _serverPlugin; private readonly Thread _dedicatedThread; private readonly Executor _executor; - private readonly WebHookPlugin _webhooks; private readonly Configuration _configuration; - private readonly IRagonOperation[] _handlers; + private readonly RagonWebHookPlugin _webhooks; + private readonly RagonHttpServer _httpServer; private readonly RagonBuffer _reader; private readonly RagonBuffer _writer; - private readonly IRagonLobby _lobby; private readonly RagonScheduler _scheduler; - private readonly Dictionary _contexts; + private readonly Dictionary _contextsByConnection; + private readonly Dictionary _contextsByPlayerId; private readonly Stopwatch _timer; private readonly long _tickRate = 0; @@ -51,20 +55,26 @@ public class RagonServer : INetworkListener _server = server; _executor = _server.Executor; _configuration = configuration; - _contexts = new Dictionary(); + _serverPlugin = plugin; + _contextsByConnection = new Dictionary(); + _contextsByPlayerId = new Dictionary(); _lobby = new LobbyInMemory(); _scheduler = new RagonScheduler(); - _webhooks = new WebHookPlugin(this, configuration); + _webhooks = new RagonWebHookPlugin(this, configuration); _dedicatedThread = new Thread(Execute); _dedicatedThread.IsBackground = true; - + _httpServer = new RagonHttpServer(_executor, plugin); _reader = new RagonBuffer(); _writer = new RagonBuffer(); _tickRate = 1000 / _configuration.ServerTickRate; _timer = new Stopwatch(); + var contextObserver = new RagonContextObserver(_contextsByPlayerId); + + _serverPlugin.OnAttached(this); + _handlers = new IRagonOperation[byte.MaxValue]; - _handlers[(byte) RagonOperation.AUTHORIZE] = new AuthorizationOperation(_webhooks, _writer, configuration); + _handlers[(byte) RagonOperation.AUTHORIZE] = new AuthorizationOperation(_webhooks, contextObserver, _writer, configuration); _handlers[(byte) RagonOperation.JOIN_OR_CREATE_ROOM] = new RoomJoinOrCreateOperation(plugin, _webhooks); _handlers[(byte) RagonOperation.CREATE_ROOM] = new RoomCreateOperation(plugin, _webhooks); _handlers[(byte) RagonOperation.JOIN_ROOM] = new RoomJoinOperation(plugin, _webhooks); @@ -78,8 +88,6 @@ public class RagonServer : INetworkListener _logger.Trace($"Server Tick Rate: {_configuration.ServerTickRate}"); } - - public IRagonOperation Resolve(RagonOperation operation) => _handlers[(byte)operation]; public void Execute() { @@ -88,11 +96,11 @@ public class RagonServer : INetworkListener { if (_timer.ElapsedMilliseconds > _tickRate) { - _executor.Update(); _scheduler.Update(_timer.ElapsedMilliseconds / 1000.0f); _timer.Restart(); } + _executor.Update(); _server.Update(); Thread.Sleep(1); } @@ -108,6 +116,7 @@ public class RagonServer : INetworkListener Port = _configuration.Port, }; + _httpServer.Start(_configuration); _server.Start(this, networkConfiguration); if (executeInDedicatedThread) @@ -118,6 +127,7 @@ public class RagonServer : INetworkListener public void Dispose() { + _serverPlugin.OnDetached(); _server.Stop(); _dedicatedThread.Interrupt(); } @@ -127,12 +137,12 @@ public class RagonServer : INetworkListener var context = new RagonContext(connection, _executor, _lobby, _scheduler); _logger.Trace($"Connected: {connection.Id}"); - _contexts.Add(connection.Id, context); + _contextsByConnection.Add(connection.Id, context); } public void OnDisconnected(INetworkConnection connection) { - if (_contexts.Remove(connection.Id, out var context)) + if (_contextsByConnection.Remove(connection.Id, out var context)) { var room = context.Room; if (room != null) @@ -152,7 +162,7 @@ public class RagonServer : INetworkListener public void OnTimeout(INetworkConnection connection) { - if (_contexts.Remove(connection.Id, out var context)) + if (_contextsByConnection.Remove(connection.Id, out var context)) { var room = context.Room; if (room != null) @@ -173,7 +183,7 @@ public class RagonServer : INetworkListener { try { - if (_contexts.TryGetValue(connection.Id, out var context)) + if (_contextsByConnection.TryGetValue(connection.Id, out var context)) { _writer.Clear(); _reader.Clear(); @@ -188,4 +198,7 @@ public class RagonServer : INetworkListener _logger.Error(ex); } } + public IRagonOperation ResolveOperation(RagonOperation operation) => _handlers[(byte)operation]; + public RagonContext? ResolveContext(INetworkConnection connection) => _contextsByConnection.TryGetValue(connection.Id, out var context) ? context : null; + public RagonContext? ResolveContext(string playerId) => _contextsByPlayerId.TryGetValue(playerId, out var context) ? context : null; } \ No newline at end of file diff --git a/Ragon.Server/Sources/RagonServerConfiguration.cs b/Ragon.Server/Sources/RagonServerConfiguration.cs index 5b14c50..c27a388 100644 --- a/Ragon.Server/Sources/RagonServerConfiguration.cs +++ b/Ragon.Server/Sources/RagonServerConfiguration.cs @@ -38,6 +38,8 @@ public struct Configuration public ushort ServerTickRate; public string GameProtocol; public ushort Port; + public ushort HttpPort; + public string HttpKey; public int LimitConnections; public int LimitPlayersPerRoom; public int LimitRooms; diff --git a/Ragon.Server/Sources/Room/IRagonRoom.cs b/Ragon.Server/Sources/Room/IRagonRoom.cs new file mode 100644 index 0000000..c397d8b --- /dev/null +++ b/Ragon.Server/Sources/Room/IRagonRoom.cs @@ -0,0 +1,9 @@ +using Ragon.Server.IO; + +namespace Ragon.Server.Room; + +public interface IRagonRoom +{ + RagonRoomPlayer GetPlayerByConnection(INetworkConnection connection); + RagonRoomPlayer GetPlayerById(string id); +} \ No newline at end of file diff --git a/Ragon.Server/Sources/Room/RagonRoom.cs b/Ragon.Server/Sources/Room/RagonRoom.cs index af65d47..e5018dd 100644 --- a/Ragon.Server/Sources/Room/RagonRoom.cs +++ b/Ragon.Server/Sources/Room/RagonRoom.cs @@ -16,12 +16,13 @@ using Ragon.Protocol; using Ragon.Server.Entity; +using Ragon.Server.IO; using Ragon.Server.Plugin; using Ragon.Server.Time; namespace Ragon.Server.Room; -public class RagonRoom : IRagonAction +public class RagonRoom : IRagonRoom, IRagonAction { public string Id { get; private set; } public string Map { get; private set; } @@ -44,7 +45,7 @@ public class RagonRoom : IRagonAction public List EntityList { get; private set; } private readonly HashSet _entitiesDirtySet; - + public RagonRoom(string roomId, RoomInformation info, IRoomPlugin roomPlugin) { Id = roomId; @@ -204,4 +205,7 @@ public class RagonRoom : IRagonAction foreach (var readyPlayer in ReadyPlayersList) readyPlayer.Connection.Reliable.Send(data); } + + public RagonRoomPlayer GetPlayerByConnection(INetworkConnection connection) => Players[connection.Id]; + public RagonRoomPlayer GetPlayerById(string id) => PlayerList.First(p => p.Id == id); } \ No newline at end of file From c91551ae082bd0a4099b20358c86bccc98e70974 Mon Sep 17 00:00:00 2001 From: edmand46 Date: Thu, 13 Apr 2023 20:49:00 +0400 Subject: [PATCH 4/4] :memo: update headers --- .../Sources/Entity/RagonEntityParameters.cs | 16 ++++++++++++++++ Ragon.Server/Sources/Http/RagonHttpServer.cs | 18 ++++++++++++++++-- Ragon.Server/Sources/IRagonContextObserver.cs | 16 ++++++++++++++++ Ragon.Server/Sources/IRagonServer.cs | 16 ++++++++++++++++ Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs | 18 ++++++++++++++++-- .../Sources/Plugin/BaseServerPlugin.cs | 16 ++++++++++++++++ .../Sources/Plugin/Web/Dto/PlayerDto.cs | 16 ++++++++++++++++ Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs | 16 ++++++++++++++++ .../Sources/Plugin/Web/RagonWebHookPlugin.cs | 16 ++++++++++++++++ .../Plugin/Web/Request/AuthorizationRequest.cs | 16 ++++++++++++++++ .../Plugin/Web/Request/RoomCreatedRequest.cs | 15 +++++++++++++++ .../Plugin/Web/Request/RoomJoinedRequest.cs | 16 ++++++++++++++++ .../Plugin/Web/Request/RoomLeavedRequest.cs | 16 ++++++++++++++++ .../Plugin/Web/Request/RoomRemovedRequest.cs | 17 ++++++++++++++++- .../Web/Response/AuthorizationResponse.cs | 16 ++++++++++++++++ Ragon.Server/Sources/Room/IRagonRoom.cs | 16 ++++++++++++++++ 16 files changed, 255 insertions(+), 5 deletions(-) diff --git a/Ragon.Server/Sources/Entity/RagonEntityParameters.cs b/Ragon.Server/Sources/Entity/RagonEntityParameters.cs index e1a5972..36bea24 100644 --- a/Ragon.Server/Sources/Entity/RagonEntityParameters.cs +++ b/Ragon.Server/Sources/Entity/RagonEntityParameters.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using Ragon.Protocol; namespace Ragon.Server.Entity; diff --git a/Ragon.Server/Sources/Http/RagonHttpServer.cs b/Ragon.Server/Sources/Http/RagonHttpServer.cs index 20c8d45..4c4b4c8 100644 --- a/Ragon.Server/Sources/Http/RagonHttpServer.cs +++ b/Ragon.Server/Sources/Http/RagonHttpServer.cs @@ -1,8 +1,22 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using NLog; using System.Net; using System.Text.Json; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Ragon.Server.IO; using Ragon.Server.Plugin; diff --git a/Ragon.Server/Sources/IRagonContextObserver.cs b/Ragon.Server/Sources/IRagonContextObserver.cs index 667a301..46e49e5 100644 --- a/Ragon.Server/Sources/IRagonContextObserver.cs +++ b/Ragon.Server/Sources/IRagonContextObserver.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + namespace Ragon.Server; public class RagonContextObserver diff --git a/Ragon.Server/Sources/IRagonServer.cs b/Ragon.Server/Sources/IRagonServer.cs index 318774c..0dcba94 100644 --- a/Ragon.Server/Sources/IRagonServer.cs +++ b/Ragon.Server/Sources/IRagonServer.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using Ragon.Server.IO; namespace Ragon.Server; diff --git a/Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs b/Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs index 8c1562d..62626d0 100644 --- a/Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs +++ b/Ragon.Server/Sources/Plugin/BaseRoomPlugin.cs @@ -1,8 +1,22 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using Ragon.Server.Entity; using Ragon.Server.IO; -using Ragon.Server.Lobby; using Ragon.Server.Room; -using Ragon.Server.Time; namespace Ragon.Server.Plugin; diff --git a/Ragon.Server/Sources/Plugin/BaseServerPlugin.cs b/Ragon.Server/Sources/Plugin/BaseServerPlugin.cs index 2a064e0..fa69c1c 100644 --- a/Ragon.Server/Sources/Plugin/BaseServerPlugin.cs +++ b/Ragon.Server/Sources/Plugin/BaseServerPlugin.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using Ragon.Server.IO; using Ragon.Server.Lobby; using Ragon.Server.Room; diff --git a/Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs b/Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs index 5703f64..faf07cd 100644 --- a/Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs +++ b/Ragon.Server/Sources/Plugin/Web/Dto/PlayerDto.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using Ragon.Server.Room; namespace Ragon.Server.Plugin.Web; diff --git a/Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs b/Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs index bbe0b13..a500fef 100644 --- a/Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs +++ b/Ragon.Server/Sources/Plugin/Web/Dto/RoomDto.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using Ragon.Server.Room; namespace Ragon.Server.Plugin.Web; diff --git a/Ragon.Server/Sources/Plugin/Web/RagonWebHookPlugin.cs b/Ragon.Server/Sources/Plugin/Web/RagonWebHookPlugin.cs index b52a36a..71669ae 100644 --- a/Ragon.Server/Sources/Plugin/Web/RagonWebHookPlugin.cs +++ b/Ragon.Server/Sources/Plugin/Web/RagonWebHookPlugin.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using System.Net; using System.Net.Http.Json; using Newtonsoft.Json; diff --git a/Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs index 64d40cf..66c89f0 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/AuthorizationRequest.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + namespace Ragon.Server.Plugin.Web; [Serializable] diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs index 1d54a20..e398551 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomCreatedRequest.cs @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ namespace Ragon.Server.Plugin.Web; diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs index 54722ae..420b387 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomJoinedRequest.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + namespace Ragon.Server.Plugin.Web; public class RoomJoinedRequest diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs index 1787a4c..7914ed7 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomLeavedRequest.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + namespace Ragon.Server.Plugin.Web; [Serializable] diff --git a/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs b/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs index e0917b3..5d4af96 100644 --- a/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs +++ b/Ragon.Server/Sources/Plugin/Web/Request/RoomRemovedRequest.cs @@ -1,4 +1,19 @@ -using Ragon.Server.Plugin.Web; +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + namespace Ragon.Server.Plugin.Web; diff --git a/Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs b/Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs index a66dfc1..459ec53 100644 --- a/Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs +++ b/Ragon.Server/Sources/Plugin/Web/Response/AuthorizationResponse.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + namespace Ragon.Server.Plugin.Web; [Serializable] diff --git a/Ragon.Server/Sources/Room/IRagonRoom.cs b/Ragon.Server/Sources/Room/IRagonRoom.cs index c397d8b..53c4a5d 100644 --- a/Ragon.Server/Sources/Room/IRagonRoom.cs +++ b/Ragon.Server/Sources/Room/IRagonRoom.cs @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Eduard Kargin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + using Ragon.Server.IO; namespace Ragon.Server.Room;