From 6422db783ab14d0cb14c2128bef2a902e431b5b8 Mon Sep 17 00:00:00 2001 From: edmand46 Date: Wed, 11 Oct 2023 19:37:50 +0300 Subject: [PATCH] wip --- Ragon.Client/Ragon.Client.csproj | 2 +- Ragon.Client/Sources/Entity/RagonEntity.cs | 38 +++++---- .../Sources/Handler/EntityCreateHandler.cs | 1 + .../Sources/Handler/OwnershipRoomHandler.cs | 2 +- .../Sources/Handler/RoomDataHandler.cs | 38 ++++++++- .../Sources/Listener/IRagonDataListener.cs | 22 +++++ Ragon.Client/Sources/RagonClient.cs | 18 ++-- Ragon.Client/Sources/RagonEntityCache.cs | 4 +- Ragon.Client/Sources/RagonListenerList.cs | 85 +++++++++++-------- Ragon.Client/Sources/RagonRoom.cs | 36 ++++---- Ragon.Client/Sources/RagonScene.cs | 12 +++ Ragon.Server.ENetServer/Sources/ENetServer.cs | 18 ++-- .../Sources/WebSocketServer.cs | 21 ++--- .../Sources/Handler/AuthorizationOperation.cs | 3 +- Ragon.Server/Sources/Handler/BaseOperation.cs | 3 +- .../Sources/Handler/EntityCreateOperation.cs | 3 +- .../Sources/Handler/EntityEventOperation.cs | 3 +- .../Handler/EntityOwnershipOperation.cs | 20 ++++- .../Sources/Handler/EntityRemoveOperation.cs | 3 +- .../Sources/Handler/EntityStateOperation.cs | 3 +- .../Sources/Handler/RoomCreateOperation.cs | 3 +- .../Sources/Handler/RoomDataOperation.cs | 7 +- .../Sources/Handler/RoomEventOperation.cs | 3 +- .../Sources/Handler/RoomJoinOperation.cs | 4 +- .../Handler/RoomJoinOrCreateOperation.cs | 3 +- .../Sources/Handler/RoomLeaveOperation.cs | 3 +- .../Sources/Handler/RoomOwnershipOperation.cs | 20 ++++- .../Sources/Handler/SceneLoadOperation.cs | 4 +- .../Sources/Handler/SceneLoadedOperation.cs | 3 +- .../Sources/Handler/TimestampSyncOperation.cs | 19 ++++- Ragon.Server/Sources/IO/INetworkServer.cs | 3 +- Ragon.Server/Sources/IO/NetworkChannel.cs | 18 +++- Ragon.Server/Sources/RagonServer.cs | 4 +- 33 files changed, 300 insertions(+), 129 deletions(-) create mode 100644 Ragon.Client/Sources/Listener/IRagonDataListener.cs diff --git a/Ragon.Client/Ragon.Client.csproj b/Ragon.Client/Ragon.Client.csproj index 1e4cf11..f81f3f1 100644 --- a/Ragon.Client/Ragon.Client.csproj +++ b/Ragon.Client/Ragon.Client.csproj @@ -12,7 +12,7 @@ true none - /Users/edmand46/RagonProjects/ragon-oss-examples/Assets/Ragon/Plugins/netstandard2.0/ + /Users/edmand46/RagonProjects/ragon-oss-becs/Assets/Ragon/Plugins diff --git a/Ragon.Client/Sources/Entity/RagonEntity.cs b/Ragon.Client/Sources/Entity/RagonEntity.cs index ee76844..7e828b5 100644 --- a/Ragon.Client/Sources/Entity/RagonEntity.cs +++ b/Ragon.Client/Sources/Entity/RagonEntity.cs @@ -77,6 +77,11 @@ namespace Ragon.Client Attached?.Invoke(this); } + internal void PrepareDetach() + { + IsAttached = false; + } + internal void Detach(RagonPayload payload) { _destroyPayload = payload; @@ -188,32 +193,34 @@ namespace Ragon.Client { var t = new TEvent(); var eventCode = _client.Event.GetEventCode(t); - var callbacks = _listeners[eventCode]; + var action = (RagonPlayer player, IRagonEvent eventData) => callback.Invoke(player, (TEvent)eventData); - if (callbacks == null) + if (!_listeners.TryGetValue(eventCode, out var callbacks)) { callbacks = new List>(); _listeners.Add(eventCode, callbacks); } - - var localCallbacks = _localListeners[eventCode]; - if (localCallbacks == null) + + if (!_localListeners.TryGetValue(eventCode, out var localCallbacks)) { localCallbacks = new List>(); - _localListeners.Add(eventCode, callbacks); + _localListeners.Add(eventCode, localCallbacks); } callbacks.Add(action); localCallbacks.Add(action); - _events.Add(eventCode, (player, serializer) => + if (!_events.ContainsKey(eventCode)) { - t.Deserialize(serializer); + _events.Add(eventCode, (player, serializer) => + { + t.Deserialize(serializer); - foreach (var callbackListener in callbacks) - callbackListener.Invoke(player, t); - }); + foreach (var callbackListener in callbacks) + callbackListener.Invoke(player, t); + }); + } return action; } @@ -222,11 +229,12 @@ namespace Ragon.Client { var t = new TEvent(); var eventCode = _client.Event.GetEventCode(t); - var callbacks = _listeners[eventCode]; - var localCallbacks = _localListeners[eventCode]; - callbacks?.Remove(callback); - localCallbacks?.Remove(callback); + if (_listeners.TryGetValue(eventCode, out var callbacks)) + callbacks.Remove(callback); + + if (_localListeners.TryGetValue(eventCode, out var localCallbacks)) + localCallbacks.Remove(callback); } internal void Write(RagonBuffer buffer) diff --git a/Ragon.Client/Sources/Handler/EntityCreateHandler.cs b/Ragon.Client/Sources/Handler/EntityCreateHandler.cs index eb4f300..46f2515 100644 --- a/Ragon.Client/Sources/Handler/EntityCreateHandler.cs +++ b/Ragon.Client/Sources/Handler/EntityCreateHandler.cs @@ -24,6 +24,7 @@ internal class EntityCreateHandler : IHandler private readonly RagonPlayerCache _playerCache; private readonly RagonEntityCache _entityCache; private readonly IRagonEntityListener _entityListener; + public EntityCreateHandler( RagonClient client, RagonPlayerCache playerCache, diff --git a/Ragon.Client/Sources/Handler/OwnershipRoomHandler.cs b/Ragon.Client/Sources/Handler/OwnershipRoomHandler.cs index a25ca9e..d91741b 100644 --- a/Ragon.Client/Sources/Handler/OwnershipRoomHandler.cs +++ b/Ragon.Client/Sources/Handler/OwnershipRoomHandler.cs @@ -19,7 +19,7 @@ using Ragon.Protocol; namespace Ragon.Client; -internal class OwnershipRoomHandler: IHandler +internal class OwnershipRoomHandler: IHandler { private readonly RagonListenerList _listenerList; private readonly RagonPlayerCache _playerCache; diff --git a/Ragon.Client/Sources/Handler/RoomDataHandler.cs b/Ragon.Client/Sources/Handler/RoomDataHandler.cs index e2c1389..b7b78fc 100644 --- a/Ragon.Client/Sources/Handler/RoomDataHandler.cs +++ b/Ragon.Client/Sources/Handler/RoomDataHandler.cs @@ -1,11 +1,47 @@ +/* + * 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.Client; -public class RoomDataHandler: IHandler +internal class RoomDataHandler: IHandler { + private readonly RagonListenerList _listeners; + private readonly RagonPlayerCache _playerCache; + + public RoomDataHandler( + RagonPlayerCache playerCache, + RagonListenerList listeners) + { + _playerCache = playerCache; + _listeners = listeners; + } + public void Handle(RagonBuffer reader) { var rawData = reader.RawData; + var peerId = (ushort)(rawData[1] + (rawData[2] << 8)); + var player = _playerCache.GetPlayerByPeer(peerId); + var headerSize = 3; + var payload = new byte[rawData.Length - headerSize]; + + Array.Copy(rawData, headerSize, payload, 0, payload.Length); + + _listeners.OnData(player, payload); } } \ No newline at end of file diff --git a/Ragon.Client/Sources/Listener/IRagonDataListener.cs b/Ragon.Client/Sources/Listener/IRagonDataListener.cs new file mode 100644 index 0000000..006d8d4 --- /dev/null +++ b/Ragon.Client/Sources/Listener/IRagonDataListener.cs @@ -0,0 +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. + */ + +namespace Ragon.Client; + +public interface IRagonDataListener +{ + public void OnData(RagonPlayer player, byte[] data); +} \ No newline at end of file diff --git a/Ragon.Client/Sources/RagonClient.cs b/Ragon.Client/Sources/RagonClient.cs index 25c8159..0886aed 100644 --- a/Ragon.Client/Sources/RagonClient.cs +++ b/Ragon.Client/Sources/RagonClient.cs @@ -57,13 +57,13 @@ namespace Ragon.Client public RagonClient(INetworkConnection connection, int rate) { + listeners = new RagonListenerList(this); + _connection = connection; _connection.OnData += OnData; _connection.OnConnected += OnConnected; _connection.OnDisconnected += OnDisconnected; - - listeners = new RagonListenerList(this); - + _replicationRate = (1000.0f / rate) / 1000.0f; _replicationTime = 0; @@ -119,9 +119,10 @@ namespace Ragon.Client _handlers[(byte)RagonOperation.REMOVE_ENTITY] = new EntityRemoveHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_STATE] = new StateEntityHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_EVENT] = new EntityEventHandler(_playerCache, _entityCache); + _handlers[(byte)RagonOperation.REPLICATE_ROOM_EVENT] = new RoomEventHandler(this, _playerCache); _handlers[(byte)RagonOperation.SNAPSHOT] = new SnapshotHandler(this, listeners, _entityCache, _playerCache, _entityListener); - _handlers[(byte)RagonOperation.REPLICATE_RAW_DATA] = new RoomEventHandler(this, _playerCache); _handlers[(byte)RagonOperation.TIMESTAMP_SYNCHRONIZATION] = new TimestampHandler(this); + _handlers[(byte)RagonOperation.REPLICATE_RAW_DATA] = new RoomDataHandler(_playerCache, listeners); var protocolRaw = RagonVersion.Parse(protocol); _connection.Connect(address, port, protocolRaw); @@ -158,8 +159,11 @@ namespace Ragon.Client public void Dispose() { - _status = RagonStatus.DISCONNECTED; - _connection.Disconnect(); + if (_status != RagonStatus.DISCONNECTED) + { + _status = RagonStatus.DISCONNECTED; + _connection.Disconnect(); + } _connection.Dispose(); } @@ -174,6 +178,7 @@ namespace Ragon.Client public void AddListener(IRagonPlayerLeftListener listener) => listeners.Add(listener); public void AddListener(IRagonSceneListener listener) => listeners.Add(listener); public void AddListener(IRagonSceneRequestListener listener) => listeners.Add(listener); + public void AddListener(IRagonDataListener listener) => listeners.Add(listener); public void RemoveListener(IRagonListener listener) => listeners.Remove(listener); public void RemoveListener(IRagonAuthorizationListener listener) => listeners.Remove(listener); @@ -186,6 +191,7 @@ namespace Ragon.Client public void RemoveListener(IRagonPlayerLeftListener listener) => listeners.Remove(listener); public void RemoveListener(IRagonSceneListener listener) => listeners.Remove(listener); public void RemoveListener(IRagonSceneRequestListener listener) => listeners.Remove(listener); + public void RemoveListener(IRagonDataListener listener) => listeners.Remove(listener); #endregion diff --git a/Ragon.Client/Sources/RagonEntityCache.cs b/Ragon.Client/Sources/RagonEntityCache.cs index 27095c8..1628883 100644 --- a/Ragon.Client/Sources/RagonEntityCache.cs +++ b/Ragon.Client/Sources/RagonEntityCache.cs @@ -88,7 +88,9 @@ public sealed class RagonEntityCache RagonLog.Warn("Can't destroy object, he is not created"); return; } - + + entity.PrepareDetach(); + var buffer = _client.Buffer; buffer.Clear(); diff --git a/Ragon.Client/Sources/RagonListenerList.cs b/Ragon.Client/Sources/RagonListenerList.cs index c03455d..24af60d 100644 --- a/Ragon.Client/Sources/RagonListenerList.cs +++ b/Ragon.Client/Sources/RagonListenerList.cs @@ -31,13 +31,14 @@ namespace Ragon.Client private readonly List _ownershipChangedListeners = new(); private readonly List _playerJoinListeners = new(); private readonly List _playerLeftListeners = new(); + private readonly List _dataListeners = new(); private readonly List _delayedActions = new(); - + public RagonListenerList(RagonClient client) { _client = client; } - + public void Add(IRagonListener listener) { _authorizationListeners.Add(listener); @@ -71,108 +72,116 @@ namespace Ragon.Client { foreach (var action in _delayedActions) action.Invoke(); - + _delayedActions.Clear(); } - + + public void Add(IRagonDataListener dataListener) + { + _dataListeners.Add(dataListener); + } public void Add(IRagonAuthorizationListener listener) { _authorizationListeners.Add(listener); } - + public void Add(IRagonSceneRequestListener listener) { _sceneRequestListeners.Add(listener); } - + public void Add(IRagonConnectionListener listener) { _connectionListeners.Add(listener); } - + public void Add(IRagonFailedListener listener) { _failedListeners.Add(listener); } - + public void Add(IRagonJoinListener listener) { _joinListeners.Add(listener); } - - public void Add(IRagonLeftListener listener) + + public void Add(IRagonLeftListener listener) { _leftListeners.Add(listener); } - - public void Add(IRagonSceneListener listener) + + public void Add(IRagonSceneListener listener) { _sceneListeners.Add(listener); } - - public void Add(IRagonOwnershipChangedListener listener) + + public void Add(IRagonOwnershipChangedListener listener) { _ownershipChangedListeners.Add(listener); } - public void Add(IRagonPlayerJoinListener listener) + public void Add(IRagonPlayerJoinListener listener) { _playerJoinListeners.Add(listener); } - - public void Add(IRagonPlayerLeftListener listener) + + public void Add(IRagonPlayerLeftListener listener) { _playerLeftListeners.Add(listener); } - + + public void Remove(IRagonDataListener listener) + { + _delayedActions.Add(() => _dataListeners.Remove(listener)); + } + public void Remove(IRagonSceneRequestListener listener) { _delayedActions.Add(() => _sceneRequestListeners.Remove(listener)); } - + public void Remove(IRagonAuthorizationListener listener) { _delayedActions.Add(() => _authorizationListeners.Remove(listener)); } - + public void Remove(IRagonConnectionListener listener) { - _delayedActions.Add(() => _connectionListeners.Remove(listener)); } - + public void Remove(IRagonFailedListener listener) { _delayedActions.Add(() => _failedListeners.Remove(listener)); } - + public void Remove(IRagonJoinListener listener) { _delayedActions.Add(() => _joinListeners.Remove(listener)); } - - public void Remove(IRagonLeftListener listener) + + public void Remove(IRagonLeftListener listener) { _delayedActions.Add(() => _leftListeners.Remove(listener)); } - - public void Remove(IRagonSceneListener listener) + + public void Remove(IRagonSceneListener listener) { _delayedActions.Add(() => _sceneListeners.Remove(listener)); } - - public void Remove(IRagonOwnershipChangedListener listener) + + public void Remove(IRagonOwnershipChangedListener listener) { _delayedActions.Add(() => _ownershipChangedListeners.Remove(listener)); } - public void Remove(IRagonPlayerJoinListener listener) + public void Remove(IRagonPlayerJoinListener listener) { _delayedActions.Add(() => _playerJoinListeners.Remove(listener)); } - - public void Remove(IRagonPlayerLeftListener listener) + + public void Remove(IRagonPlayerLeftListener listener) { _delayedActions.Add(() => _playerLeftListeners.Remove(listener)); } @@ -182,13 +191,13 @@ namespace Ragon.Client foreach (var listener in _authorizationListeners) listener.OnAuthorizationSuccess(_client, playerId, playerName); } - + public void OnAuthorizationFailed(string message) { foreach (var listener in _authorizationListeners) listener.OnAuthorizationFailed(_client, message); } - + public void OnLeft() { foreach (var listener in _leftListeners) @@ -224,7 +233,7 @@ namespace Ragon.Client foreach (var listener in _sceneListeners) listener.OnSceneLoaded(_client); } - + public void OnSceneRequest(string sceneName) { foreach (var listener in _sceneRequestListeners) @@ -248,5 +257,11 @@ namespace Ragon.Client foreach (var listener in _connectionListeners) listener.OnDisconnected(_client, disconnect); } + + public void OnData(RagonPlayer player, byte[] data) + { + foreach (var listener in _dataListeners) + listener.OnData(player, data); + } } } \ No newline at end of file diff --git a/Ragon.Client/Sources/RagonRoom.cs b/Ragon.Client/Sources/RagonRoom.cs index 0f9244e..7e4aa8f 100644 --- a/Ragon.Client/Sources/RagonRoom.cs +++ b/Ragon.Client/Sources/RagonRoom.cs @@ -77,32 +77,34 @@ namespace Ragon.Client { var t = new TEvent(); var eventCode = _client.Event.GetEventCode(t); - var callbacks = _listeners[eventCode]; + var action = (RagonPlayer player, IRagonEvent eventData) => callback.Invoke(player, (TEvent)eventData); - if (callbacks == null) + if (!_listeners.TryGetValue(eventCode, out var callbacks)) { callbacks = new List>(); _listeners.Add(eventCode, callbacks); } - - var localCallbacks = _localListeners[eventCode]; - if (localCallbacks == null) + + if (!_localListeners.TryGetValue(eventCode, out var localCallbacks)) { localCallbacks = new List>(); - _localListeners.Add(eventCode, callbacks); + _localListeners.Add(eventCode, localCallbacks); } - + callbacks.Add(action); localCallbacks.Add(action); - _events.Add(eventCode, (player, serializer) => + if (!_events.ContainsKey(eventCode)) { - t.Deserialize(serializer); + _events.Add(eventCode, (player, serializer) => + { + t.Deserialize(serializer); - foreach (var callbackListener in callbacks) - callbackListener.Invoke(player, t); - }); + foreach (var callbackListener in callbacks) + callbackListener.Invoke(player, t); + }); + } return action; } @@ -111,11 +113,12 @@ namespace Ragon.Client { var t = new TEvent(); var eventCode = _client.Event.GetEventCode(t); - var callbacks = _listeners[eventCode]; - var localCallbacks = _localListeners[eventCode]; - callbacks?.Remove(callback); - localCallbacks?.Remove(callback); + if (_listeners.TryGetValue(eventCode, out var callbacks)) + callbacks.Remove(callback); + + if (_localListeners.TryGetValue(eventCode, out var localCallbacks)) + localCallbacks.Remove(callback); } public void LoadScene(string sceneName) => _scene.Load(sceneName); @@ -123,6 +126,7 @@ namespace Ragon.Client public void ReplicateEvent(TEvent evnt, RagonTarget target, RagonReplicationMode mode) where TEvent : IRagonEvent, new() => _scene.ReplicateEvent(evnt, target, mode); public void ReplicateEvent(TEvent evnt, RagonPlayer target, RagonReplicationMode mode) where TEvent : IRagonEvent, new() => _scene.ReplicateEvent(evnt, target, mode); + public void ReplicateData(byte[] data, bool reliable = false) => _scene.ReplicateData(data, reliable); public void CreateEntity(RagonEntity entity) => CreateEntity(entity, null); public void CreateEntity(RagonEntity entity, RagonPayload payload) => _entityCache.Create(entity, payload); diff --git a/Ragon.Client/Sources/RagonScene.cs b/Ragon.Client/Sources/RagonScene.cs index aa01a44..186dd49 100644 --- a/Ragon.Client/Sources/RagonScene.cs +++ b/Ragon.Client/Sources/RagonScene.cs @@ -102,4 +102,16 @@ public class RagonScene var sendData = buffer.ToArray(); _client.Reliable.Send(sendData); } + + public void ReplicateData(byte[] data, bool reliable) + { + var sendData = new byte[data.Length + 1]; + sendData[0] = (byte) RagonOperation.REPLICATE_RAW_DATA; + Array.Copy(data, 0, sendData, 1, data.Length); + + if (reliable) + _client.Reliable.Send(sendData); + else + _client.Unreliable.Send(sendData); + } } \ No newline at end of file diff --git a/Ragon.Server.ENetServer/Sources/ENetServer.cs b/Ragon.Server.ENetServer/Sources/ENetServer.cs index c577913..c0f5a41 100644 --- a/Ragon.Server.ENetServer/Sources/ENetServer.cs +++ b/Ragon.Server.ENetServer/Sources/ENetServer.cs @@ -118,22 +118,16 @@ namespace Ragon.Server.ENetServer } } - public void BroadcastReliable(byte[] data) + public void Broadcast(byte[] data, NetworkChannel channel) { var packet = new Packet(); - packet.Create(data, PacketFlags.Reliable); + var flag = channel == NetworkChannel.RELIABLE? PacketFlags.Reliable: PacketFlags.None; + + packet.Create(data, flag); - _host.Broadcast((byte)NetworkChannel.RELIABLE, ref packet); + _host.Broadcast((byte)channel, ref packet); } - - public void BroadcastUnreliable(byte[] data) - { - var packet = new Packet(); - packet.Create(data, PacketFlags.None); - - _host.Broadcast((byte)NetworkChannel.UNRELIABLE, ref packet); - } - + public void Stop() { _host?.Dispose(); diff --git a/Ragon.Server.WebSocketServer/Sources/WebSocketServer.cs b/Ragon.Server.WebSocketServer/Sources/WebSocketServer.cs index 5c5933a..8361e63 100644 --- a/Ragon.Server.WebSocketServer/Sources/WebSocketServer.cs +++ b/Ragon.Server.WebSocketServer/Sources/WebSocketServer.cs @@ -25,7 +25,7 @@ namespace Ragon.Server.WebSocketServer; public class WebSocketServer : INetworkServer { public Executor Executor => _executor; - + private ILogger _logger = LogManager.GetCurrentClassLogger(); private INetworkListener _networkListener; private Stack _sequencer; @@ -34,7 +34,7 @@ public class WebSocketServer : INetworkServer private WebSocketConnection[] _connections; private List _activeConnections; private CancellationTokenSource _cancellationTokenSource; - + public WebSocketServer() { _sequencer = new Stack(); @@ -42,7 +42,7 @@ public class WebSocketServer : INetworkServer _activeConnections = new List(); _executor = new Executor(); } - + public async void StartAccept(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) @@ -61,7 +61,7 @@ public class WebSocketServer : INetworkServer var peerId = _sequencer.Pop(); var connection = new WebSocketConnection(webSocket, peerId); - + _connections[peerId] = connection; StartListen(connection, cancellationToken); } @@ -84,9 +84,8 @@ public class WebSocketServer : INetworkServer var result = await webSocket.ReceiveAsync(buffer, cancellationToken); if (result.Count > 0) { - var channel = (RagonOperation) bytes[0] == RagonOperation.REPLICATE_RAW_DATA ? NetworkChannel.RAW : NetworkChannel.RELIABLE; var payload = buffer.Slice(0, buffer.Length); - _networkListener.OnData(connection, channel , payload.ToArray()); + _networkListener.OnData(connection, NetworkChannel.RELIABLE, payload.ToArray()); } } catch (Exception ex) @@ -105,16 +104,10 @@ public class WebSocketServer : INetworkServer Flush(); } - public void BroadcastUnreliable(byte[] data) + public void Broadcast(byte[] data, NetworkChannel channel) { foreach (var activeConnection in _activeConnections) - activeConnection.Unreliable.Send(data); - } - - public void BroadcastReliable(byte[] data) - { - foreach (var activeConnection in _activeConnections) - activeConnection.Reliable.Send(data); + activeConnection.Reliable.Send(data); } public async void Flush() diff --git a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs index 3eb7561..6ed25bb 100644 --- a/Ragon.Server/Sources/Handler/AuthorizationOperation.cs +++ b/Ragon.Server/Sources/Handler/AuthorizationOperation.cs @@ -16,6 +16,7 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.IO; using Ragon.Server.Lobby; using Ragon.Server.Plugin.Web; @@ -40,7 +41,7 @@ public sealed class AuthorizationOperation: BaseOperation _writer = writer; } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { if (context.ConnectionStatus == ConnectionStatus.Authorized) { diff --git a/Ragon.Server/Sources/Handler/BaseOperation.cs b/Ragon.Server/Sources/Handler/BaseOperation.cs index df284b7..6654691 100644 --- a/Ragon.Server/Sources/Handler/BaseOperation.cs +++ b/Ragon.Server/Sources/Handler/BaseOperation.cs @@ -15,6 +15,7 @@ */ using Ragon.Protocol; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -29,5 +30,5 @@ public abstract class BaseOperation Writer = writer; } - public abstract void Handle(RagonContext context); + public abstract void Handle(RagonContext context, NetworkChannel channel); } \ No newline at end of file diff --git a/Ragon.Server/Sources/Handler/EntityCreateOperation.cs b/Ragon.Server/Sources/Handler/EntityCreateOperation.cs index 0c48906..546f5d8 100644 --- a/Ragon.Server/Sources/Handler/EntityCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityCreateOperation.cs @@ -17,6 +17,7 @@ using NLog; using Ragon.Protocol; using Ragon.Server.Entity; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -28,7 +29,7 @@ public sealed class EntityCreateOperation : BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var player = context.RoomPlayer; var room = context.Room; diff --git a/Ragon.Server/Sources/Handler/EntityEventOperation.cs b/Ragon.Server/Sources/Handler/EntityEventOperation.cs index bf22e6a..7227adf 100644 --- a/Ragon.Server/Sources/Handler/EntityEventOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityEventOperation.cs @@ -17,6 +17,7 @@ using NLog; using Ragon.Protocol; using Ragon.Server.Event; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -28,7 +29,7 @@ public sealed class EntityEventOperation : BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var player = context.RoomPlayer; var room = context.Room; diff --git a/Ragon.Server/Sources/Handler/EntityOwnershipOperation.cs b/Ragon.Server/Sources/Handler/EntityOwnershipOperation.cs index cecba20..9ae4592 100644 --- a/Ragon.Server/Sources/Handler/EntityOwnershipOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityOwnershipOperation.cs @@ -1,5 +1,23 @@ +/* + * 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 Ragon.Protocol; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -11,7 +29,7 @@ public sealed class EntityOwnershipOperation : BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var currentOwner = context.RoomPlayer; var room = context.Room; diff --git a/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs b/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs index ef7fd37..13de6f7 100644 --- a/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityRemoveOperation.cs @@ -17,6 +17,7 @@ using NLog; using Ragon.Protocol; using Ragon.Server.Entity; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -28,7 +29,7 @@ public sealed class EntityDestroyOperation: BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var player = context.RoomPlayer; var room = context.Room; diff --git a/Ragon.Server/Sources/Handler/EntityStateOperation.cs b/Ragon.Server/Sources/Handler/EntityStateOperation.cs index 876fb8d..c5fcca3 100644 --- a/Ragon.Server/Sources/Handler/EntityStateOperation.cs +++ b/Ragon.Server/Sources/Handler/EntityStateOperation.cs @@ -16,6 +16,7 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -27,7 +28,7 @@ public sealed class EntityStateOperation: BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var room = context.Room; var player = context.RoomPlayer; diff --git a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs index 9858cbe..a2b5b10 100644 --- a/Ragon.Server/Sources/Handler/RoomCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomCreateOperation.cs @@ -16,6 +16,7 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.IO; using Ragon.Server.Lobby; using Ragon.Server.Plugin; using Ragon.Server.Plugin.Web; @@ -36,7 +37,7 @@ public sealed class RoomCreateOperation : BaseOperation _ragonWebHookPlugin = ragonWebHook; } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { if (context.ConnectionStatus == ConnectionStatus.Unauthorized) { diff --git a/Ragon.Server/Sources/Handler/RoomDataOperation.cs b/Ragon.Server/Sources/Handler/RoomDataOperation.cs index 71905d7..ac42d18 100644 --- a/Ragon.Server/Sources/Handler/RoomDataOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomDataOperation.cs @@ -16,6 +16,7 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -25,7 +26,7 @@ public sealed class RoomDataOperation : BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var player = context.RoomPlayer; var room = context.Room; @@ -42,8 +43,8 @@ public sealed class RoomDataOperation : BaseOperation var sendData = new byte[size]; Array.Copy(playerData, 0, sendData, 0, playerData.Length); - Array.Copy(payloadData, 0, sendData, playerData.Length, payloadData.Length); + Array.Copy(payloadData, 1, sendData, playerData.Length, payloadData.Length - 1); - room.Broadcast(sendData); + room.Broadcast(sendData, channel); } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Handler/RoomEventOperation.cs b/Ragon.Server/Sources/Handler/RoomEventOperation.cs index b314806..a74a5c9 100644 --- a/Ragon.Server/Sources/Handler/RoomEventOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomEventOperation.cs @@ -1,5 +1,6 @@ using Ragon.Protocol; using Ragon.Server.Event; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -9,7 +10,7 @@ public class RoomEventOperation : BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var room = context.Room; var player = context.RoomPlayer; diff --git a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs index bf5eab5..7ae9166 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOperation.cs @@ -16,7 +16,7 @@ using NLog; using Ragon.Protocol; -using Ragon.Server.Plugin; +using Ragon.Server.IO; using Ragon.Server.Plugin.Web; using Ragon.Server.Room; @@ -33,7 +33,7 @@ public sealed class RoomJoinOperation : BaseOperation } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var roomId = Reader.ReadString(); var lobbyPlayer = context.LobbyPlayer; diff --git a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs index cf936e3..c19938b 100644 --- a/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomJoinOrCreateOperation.cs @@ -16,6 +16,7 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.IO; using Ragon.Server.Lobby; using Ragon.Server.Plugin; using Ragon.Server.Plugin.Web; @@ -36,7 +37,7 @@ public sealed class RoomJoinOrCreateOperation : BaseOperation _ragonWebHookPlugin = plugin; } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { if (context.ConnectionStatus == ConnectionStatus.Unauthorized) { diff --git a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs index ab740db..3010264 100644 --- a/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomLeaveOperation.cs @@ -16,6 +16,7 @@ using NLog; using Ragon.Protocol; +using Ragon.Server.IO; using Ragon.Server.Plugin; using Ragon.Server.Plugin.Web; @@ -31,7 +32,7 @@ public sealed class RoomLeaveOperation: BaseOperation _webHook = plugin; } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var room = context.Room; var roomPlayer = context.RoomPlayer; diff --git a/Ragon.Server/Sources/Handler/RoomOwnershipOperation.cs b/Ragon.Server/Sources/Handler/RoomOwnershipOperation.cs index db93166..32e9a2c 100644 --- a/Ragon.Server/Sources/Handler/RoomOwnershipOperation.cs +++ b/Ragon.Server/Sources/Handler/RoomOwnershipOperation.cs @@ -1,6 +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 Ragon.Protocol; -using Ragon.Server.Entity; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -12,7 +28,7 @@ public sealed class RoomOwnershipOperation : BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { } diff --git a/Ragon.Server/Sources/Handler/SceneLoadOperation.cs b/Ragon.Server/Sources/Handler/SceneLoadOperation.cs index 9f8378c..a8f3498 100644 --- a/Ragon.Server/Sources/Handler/SceneLoadOperation.cs +++ b/Ragon.Server/Sources/Handler/SceneLoadOperation.cs @@ -14,9 +14,9 @@ * limitations under the License. */ - using NLog; using Ragon.Protocol; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -26,7 +26,7 @@ public class SceneLoadOperation: BaseOperation public SceneLoadOperation(RagonBuffer reader, RagonBuffer writer) : base(reader, writer) {} - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var roomOwner = context.Room.Owner; var currentPlayer = context.RoomPlayer; diff --git a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs index 5c7c662..80f7aae 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.IO; using Ragon.Server.Lobby; using Ragon.Server.Room; @@ -31,7 +32,7 @@ public sealed class SceneLoadedOperation : BaseOperation } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { if (context.ConnectionStatus == ConnectionStatus.Unauthorized) return; diff --git a/Ragon.Server/Sources/Handler/TimestampSyncOperation.cs b/Ragon.Server/Sources/Handler/TimestampSyncOperation.cs index 7840e03..1d488b8 100644 --- a/Ragon.Server/Sources/Handler/TimestampSyncOperation.cs +++ b/Ragon.Server/Sources/Handler/TimestampSyncOperation.cs @@ -1,4 +1,21 @@ +/* + * 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; +using Ragon.Server.IO; namespace Ragon.Server.Handler; @@ -8,7 +25,7 @@ public class TimestampSyncOperation: BaseOperation { } - public override void Handle(RagonContext context) + public override void Handle(RagonContext context, NetworkChannel channel) { var timestamp0 = Reader.Read(32); var timestamp1 = Reader.Read(32); diff --git a/Ragon.Server/Sources/IO/INetworkServer.cs b/Ragon.Server/Sources/IO/INetworkServer.cs index 91694ea..f1f6054 100644 --- a/Ragon.Server/Sources/IO/INetworkServer.cs +++ b/Ragon.Server/Sources/IO/INetworkServer.cs @@ -21,7 +21,6 @@ public interface INetworkServer public Executor Executor { get; } public void Stop(); public void Update(); - public void BroadcastUnreliable(byte[] data); - public void BroadcastReliable(byte[] data); + public void Broadcast(byte[] data, NetworkChannel channel); public void Start(INetworkListener listener, NetworkConfiguration configuration); } \ No newline at end of file diff --git a/Ragon.Server/Sources/IO/NetworkChannel.cs b/Ragon.Server/Sources/IO/NetworkChannel.cs index 241bffd..f12dfe2 100644 --- a/Ragon.Server/Sources/IO/NetworkChannel.cs +++ b/Ragon.Server/Sources/IO/NetworkChannel.cs @@ -1,8 +1,24 @@ +/* + * 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.IO; public enum NetworkChannel { RELIABLE = 1, UNRELIABLE = 2, - RAW = 3, } \ No newline at end of file diff --git a/Ragon.Server/Sources/RagonServer.cs b/Ragon.Server/Sources/RagonServer.cs index 62dd4d2..532ffc4 100644 --- a/Ragon.Server/Sources/RagonServer.cs +++ b/Ragon.Server/Sources/RagonServer.cs @@ -197,7 +197,7 @@ public class RagonServer : IRagonServer, INetworkListener _reader.FromArray(data); var operation = _reader.ReadByte(); - _handlers[operation].Handle(context); + _handlers[operation].Handle(context, channel); } } catch (Exception ex) @@ -220,7 +220,7 @@ public class RagonServer : IRagonServer, INetworkListener _writer.Write(value.Int1, 32); var sendData = _writer.ToArray(); - _server.BroadcastUnreliable(sendData); + _server.Broadcast(sendData, NetworkChannel.UNRELIABLE); } public BaseOperation ResolveOperation(RagonOperation operation)