This commit is contained in:
2023-10-11 19:37:50 +03:00
parent 5d812d7acc
commit 6422db783a
33 changed files with 300 additions and 129 deletions
+23 -15
View File
@@ -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<Action<RagonPlayer, IRagonEvent>>();
_listeners.Add(eventCode, callbacks);
}
var localCallbacks = _localListeners[eventCode];
if (localCallbacks == null)
if (!_localListeners.TryGetValue(eventCode, out var localCallbacks))
{
localCallbacks = new List<Action<RagonPlayer, IRagonEvent>>();
_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)
@@ -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,
@@ -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;
@@ -1,11 +1,47 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* 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);
}
}
@@ -0,0 +1,22 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* 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);
}
+12 -6
View File
@@ -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
+3 -1
View File
@@ -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();
+50 -35
View File
@@ -31,13 +31,14 @@ namespace Ragon.Client
private readonly List<IRagonOwnershipChangedListener> _ownershipChangedListeners = new();
private readonly List<IRagonPlayerJoinListener> _playerJoinListeners = new();
private readonly List<IRagonPlayerLeftListener> _playerLeftListeners = new();
private readonly List<IRagonDataListener> _dataListeners = new();
private readonly List<Action> _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);
}
}
}
+20 -16
View File
@@ -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<Action<RagonPlayer, IRagonEvent>>();
_listeners.Add(eventCode, callbacks);
}
var localCallbacks = _localListeners[eventCode];
if (localCallbacks == null)
if (!_localListeners.TryGetValue(eventCode, out var localCallbacks))
{
localCallbacks = new List<Action<RagonPlayer, IRagonEvent>>();
_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>(TEvent evnt, RagonTarget target, RagonReplicationMode mode) where TEvent : IRagonEvent, new() => _scene.ReplicateEvent(evnt, target, mode);
public void ReplicateEvent<TEvent>(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);
+12
View File
@@ -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);
}
}