From c01b748031e6e693570fa04bb64bfbeeeae05dd2 Mon Sep 17 00:00:00 2001 From: edmand45 Date: Sat, 29 Jul 2023 10:58:06 +0300 Subject: [PATCH 1/2] wip --- Ragon.Client/Ragon.Client.csproj | 2 +- Ragon.Client/Sources/Entity/RagonEntity.cs | 13 +--- Ragon.Client/Sources/Entity/RagonPayload.cs | 10 +-- .../Sources/Handler/EntityCreateHandler.cs | 16 +++-- .../Sources/Handler/PlayerLeftHandler.cs | 3 +- .../Sources/Handler/SnapshotHandler.cs | 60 +++++++++++----- Ragon.Client/Sources/RagonClient.cs | 6 +- Ragon.Client/Sources/RagonEntityCache.cs | 68 ++++++++++--------- Ragon.Client/Sources/RagonPlayerCache.cs | 3 +- Ragon.Client/Sources/RagonRoom.cs | 4 +- Ragon.Protocol/Ragon.Protocol.csproj | 2 +- Ragon.Protocol/Sources/RagonBuffer.cs | 38 +++++------ Ragon.Server/Sources/Entity/RagonEvent.cs | 7 +- Ragon.Server/Sources/Entity/RagonPayload.cs | 10 +-- Ragon.Server/Sources/Entity/RagonProperty.cs | 8 +-- .../Sources/Handler/SceneLoadedOperation.cs | 1 - 16 files changed, 133 insertions(+), 118 deletions(-) diff --git a/Ragon.Client/Ragon.Client.csproj b/Ragon.Client/Ragon.Client.csproj index effaeb8..41c4715 100644 --- a/Ragon.Client/Ragon.Client.csproj +++ b/Ragon.Client/Ragon.Client.csproj @@ -1,12 +1,12 @@ - netstandard2.1 enable enable 10 Ragon.Client.Simulation Eduard Kargin (Edmand46) + netstandard2.0 diff --git a/Ragon.Client/Sources/Entity/RagonEntity.cs b/Ragon.Client/Sources/Entity/RagonEntity.cs index 9cd5287..2a2149b 100644 --- a/Ragon.Client/Sources/Entity/RagonEntity.cs +++ b/Ragon.Client/Sources/Entity/RagonEntity.cs @@ -60,7 +60,7 @@ namespace Ragon.Client _sceneId = sceneId; } - internal void Attach(RagonClient client, ushort entityId, ushort entityType, bool hasAuthority, RagonPlayer owner, RagonPayload payload) + internal void Attach(RagonClient client, ushort entityId, ushort entityType, bool hasAuthority, RagonPlayer owner) { Type = entityType; Id = entityId; @@ -70,7 +70,6 @@ namespace Ragon.Client HasAuthority = hasAuthority; _client = client; - _spawnPayload = payload; Attached?.Invoke(this); } @@ -96,15 +95,9 @@ namespace Ragon.Client return payload; } - public void AttachPayload(IRagonPayload? payload) + public void AttachPayload(RagonPayload payload) { - if (payload == null) return; - - var buffer = new RagonBuffer(); - payload.Serialize(buffer); - - _spawnPayload = new RagonPayload(); - _spawnPayload.Read(buffer); + _spawnPayload = payload; } public T GetAttachPayload() where T : IRagonPayload, new() diff --git a/Ragon.Client/Sources/Entity/RagonPayload.cs b/Ragon.Client/Sources/Entity/RagonPayload.cs index d81dc23..1d13161 100644 --- a/Ragon.Client/Sources/Entity/RagonPayload.cs +++ b/Ragon.Client/Sources/Entity/RagonPayload.cs @@ -19,7 +19,7 @@ using Ragon.Protocol; namespace Ragon.Client; -public struct RagonPayload +public class RagonPayload { private readonly uint[] _data = new uint[128]; private readonly int _size = 0; @@ -32,16 +32,12 @@ public struct RagonPayload public void Read(RagonBuffer buffer) { - var readOnlySpan = _data.AsSpan(); - - buffer.ReadSpan(ref readOnlySpan, _size); + buffer.ReadArray(_data, _size); } public void Write(RagonBuffer buffer) { - ReadOnlySpan readOnlySpan = _data.AsSpan(); - - buffer.WriteSpan(ref readOnlySpan, _size); + buffer.WriteArray(_data, _size); } public override string ToString() diff --git a/Ragon.Client/Sources/Handler/EntityCreateHandler.cs b/Ragon.Client/Sources/Handler/EntityCreateHandler.cs index e784ac1..7615e23 100644 --- a/Ragon.Client/Sources/Handler/EntityCreateHandler.cs +++ b/Ragon.Client/Sources/Handler/EntityCreateHandler.cs @@ -23,16 +23,18 @@ internal class EntityCreateHandler : Handler private readonly RagonClient _client; private readonly RagonPlayerCache _playerCache; private readonly RagonEntityCache _entityCache; - + private readonly IRagonEntityListener _entityListener; public EntityCreateHandler( RagonClient client, RagonPlayerCache playerCache, - RagonEntityCache entityCache + RagonEntityCache entityCache, + IRagonEntityListener entityListener ) { _client = client; _entityCache = entityCache; _playerCache = playerCache; + _entityListener = entityListener; } public void Handle(RagonBuffer buffer) @@ -52,7 +54,13 @@ internal class EntityCreateHandler : Handler } var hasAuthority = _playerCache.Local.Id == player.Id; - var entity = _entityCache.OnCreate(attachId, entityType, 0, entityId, hasAuthority); - entity.Attach(_client, entityId, entityType, hasAuthority, player, payload); + var entity = _entityCache.TryGetEntity(attachId, entityType, 0, entityId, hasAuthority, out var hasCreated); + + entity.AttachPayload(payload); + + if (hasCreated) + _entityListener.OnEntityCreated(entity); + + entity.Attach(_client, entityId, entityType, hasAuthority, player); } } \ No newline at end of file diff --git a/Ragon.Client/Sources/Handler/PlayerLeftHandler.cs b/Ragon.Client/Sources/Handler/PlayerLeftHandler.cs index fcff2c9..f19080e 100644 --- a/Ragon.Client/Sources/Handler/PlayerLeftHandler.cs +++ b/Ragon.Client/Sources/Handler/PlayerLeftHandler.cs @@ -53,8 +53,9 @@ internal class PlayerLeftHandler : Handler toDeleteIds[i] = entityId; } + var emptyPayload = new RagonPayload(0); foreach (var id in toDeleteIds) - _entityCache.OnDestroy(id, new RagonPayload()); + _entityCache.OnDestroy(id, emptyPayload); } } } \ No newline at end of file diff --git a/Ragon.Client/Sources/Handler/SnapshotHandler.cs b/Ragon.Client/Sources/Handler/SnapshotHandler.cs index a163ac5..3798e12 100644 --- a/Ragon.Client/Sources/Handler/SnapshotHandler.cs +++ b/Ragon.Client/Sources/Handler/SnapshotHandler.cs @@ -22,19 +22,22 @@ namespace Ragon.Client; internal class SnapshotHandler : Handler { - private RagonClient _client; - private RagonListenerList _listenerList; - private RagonEntityCache _entityCache; - private RagonPlayerCache _playerCache; + private readonly IRagonEntityListener _entityListener; + private readonly RagonClient _client; + private readonly RagonListenerList _listenerList; + private readonly RagonEntityCache _entityCache; + private readonly RagonPlayerCache _playerCache; public SnapshotHandler( RagonClient ragonClient, RagonListenerList listenerList, RagonEntityCache entityCache, - RagonPlayerCache playerCache + RagonPlayerCache playerCache, + IRagonEntityListener entityListener ) { _client = ragonClient; + _entityListener = entityListener; _listenerList = listenerList; _entityCache = entityCache; _playerCache = playerCache; @@ -49,9 +52,12 @@ internal class SnapshotHandler : Handler var playerPeerId = buffer.ReadUShort(); var playerId = buffer.ReadString(); var playerName = buffer.ReadString(); - + _playerCache.AddPlayer(playerPeerId, playerId, playerName); + + RagonLog.Trace($"Player {playerPeerId} - {playerId} - {playerName}"); } + var dynamicEntities = buffer.ReadUShort(); RagonLog.Trace("Dynamic Entities: " + dynamicEntities); for (var i = 0; i < dynamicEntities; i++) @@ -60,16 +66,27 @@ internal class SnapshotHandler : Handler var entityId = buffer.ReadUShort(); var ownerPeerId = buffer.ReadUShort(); var payloadSize = buffer.ReadUShort(); - var player = _playerCache.GetPlayerByPeer(ownerPeerId); - var payload = new RagonPayload(payloadSize); payload.Read(buffer); + + RagonLog.Trace($"Entity {entityType} - {entityId} - {ownerPeerId} - {payloadSize}"); + + var player = _playerCache.GetPlayerByPeer(ownerPeerId); + if (player == null) + { + RagonLog.Error($"Player not found with peerId: ${ownerPeerId}"); + return; + } var hasAuthority = _playerCache.Local.Id == player.Id; - var entity = _entityCache.OnCreate(0, entityType, 0, entityId, hasAuthority); + var entity = _entityCache.TryGetEntity(0, entityType, 0, entityId, hasAuthority, out _); entity.Read(buffer); - entity.Attach(_client, entityId, entityType, hasAuthority, player, payload); + entity.AttachPayload(payload); + + _entityListener.OnEntityCreated(entity); + + entity.Attach(_client, entityId, entityType, hasAuthority, player); } var staticEntities = buffer.ReadUShort(); @@ -81,18 +98,29 @@ internal class SnapshotHandler : Handler var staticId = buffer.ReadUShort(); var ownerPeerId = buffer.ReadUShort(); var payloadSize = buffer.ReadUShort(); - var player = _playerCache.GetPlayerByPeer(ownerPeerId); - var payload = new RagonPayload(payloadSize); payload.Read(buffer); - + + RagonLog.Trace($"Entity {entityType} - {entityId} - {ownerPeerId} - {payloadSize}"); + + var player = _playerCache.GetPlayerByPeer(ownerPeerId); + if (player == null) + { + RagonLog.Error($"Player not found with peerId: ${ownerPeerId}"); + return; + } + var hasAuthority = _playerCache.Local.Id == player.Id; - var entity = _entityCache.OnCreate(0, entityType, staticId, entityId, hasAuthority); + var entity = _entityCache.TryGetEntity(0, entityType, staticId, entityId, hasAuthority, out _); entity.Read(buffer); - entity.Attach(_client, entityId, entityType, hasAuthority, player, payload); + entity.AttachPayload(payload); + + _entityListener.OnEntityCreated(entity); + + entity.Attach(_client, entityId, entityType, hasAuthority, player); } - + _listenerList.OnJoined(); } } \ No newline at end of file diff --git a/Ragon.Client/Sources/RagonClient.cs b/Ragon.Client/Sources/RagonClient.cs index 25bb559..49ed555 100644 --- a/Ragon.Client/Sources/RagonClient.cs +++ b/Ragon.Client/Sources/RagonClient.cs @@ -99,7 +99,7 @@ namespace Ragon.Client _session = new RagonSession(this, _readBuffer); _playerCache = new RagonPlayerCache(); - _entityCache = new RagonEntityCache(this, _playerCache, _entityListener, _sceneCollector); + _entityCache = new RagonEntityCache(this, _playerCache, _sceneCollector); _handlers = new Handler[byte.MaxValue]; _handlers[(byte)RagonOperation.AUTHORIZED_SUCCESS] = new AuthorizeSuccessHandler(_listenerList); @@ -112,11 +112,11 @@ namespace Ragon.Client _handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_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.CREATE_ENTITY] = new EntityCreateHandler(this, _playerCache, _entityCache, _entityListener); _handlers[(byte)RagonOperation.REMOVE_ENTITY] = new EntityRemoveHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_STATE] = new StateEntityHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_EVENT] = new EntityEventHandler(this, _playerCache, _entityCache); - _handlers[(byte)RagonOperation.SNAPSHOT] = new SnapshotHandler(this, _listenerList, _entityCache, _playerCache); + _handlers[(byte)RagonOperation.SNAPSHOT] = new SnapshotHandler(this, _listenerList, _entityCache, _playerCache, _entityListener); var protocolRaw = RagonVersion.Parse(protocol); _connection.Connect(address, port, protocolRaw); diff --git a/Ragon.Client/Sources/RagonEntityCache.cs b/Ragon.Client/Sources/RagonEntityCache.cs index 34ac98c..1bbb7c7 100644 --- a/Ragon.Client/Sources/RagonEntityCache.cs +++ b/Ragon.Client/Sources/RagonEntityCache.cs @@ -26,7 +26,6 @@ public sealed class RagonEntityCache private readonly Dictionary _sceneEntities = new(); private readonly RagonClient _client; - private readonly IRagonEntityListener _entityListener; private readonly IRagonSceneCollector _sceneCollector; private readonly RagonPlayerCache _playerCache; @@ -35,12 +34,10 @@ public sealed class RagonEntityCache public RagonEntityCache( RagonClient client, RagonPlayerCache playerCache, - IRagonEntityListener listener, IRagonSceneCollector sceneCollector ) { _client = client; - _entityListener = listener; _sceneCollector = sceneCollector; _playerCache = playerCache; } @@ -50,7 +47,7 @@ public sealed class RagonEntityCache return _entityMap.TryGetValue(id, out entity); } - public void Create(RagonEntity entity, IRagonPayload? spawnPayload) + public void Create(RagonEntity entity, RagonPayload spawnPayload) { var attachId = (ushort)(_playerCache.Local.PeerId + _localEntitiesCounter++); var buffer = _client.Buffer; @@ -63,7 +60,7 @@ public sealed class RagonEntityCache entity.State.WriteInfo(buffer); - spawnPayload?.Serialize(buffer); + spawnPayload.Write(buffer); _pendingEntities.Add(attachId, entity); @@ -84,7 +81,7 @@ public sealed class RagonEntityCache _client.Reliable.Send(sendData); } - public void Destroy(RagonEntity entity, IRagonPayload? destroyPayload) + public void Destroy(RagonEntity entity, RagonPayload destroyPayload) { if (!entity.IsAttached) { @@ -98,7 +95,7 @@ public sealed class RagonEntityCache buffer.WriteOperation(RagonOperation.REMOVE_ENTITY); buffer.WriteUShort(entity.Id); - destroyPayload?.Serialize(buffer); + destroyPayload.Write(buffer); var sendData = buffer.ToArray(); _client.Reliable.Send(sendData); @@ -162,61 +159,66 @@ public sealed class RagonEntityCache internal void Cleanup() { - var payload = new RagonPayload(); + var payload = new RagonPayload(0); foreach (var ent in _entityList) ent.Detach(payload); _entityMap.Clear(); _entityList.Clear(); } - - internal RagonEntity OnCreate(ushort attachId, ushort entityType, ushort sceneId, ushort entityId, bool hasAuthority) + + internal RagonEntity TryGetEntity(ushort attachId, ushort entityType, ushort sceneId, ushort entityId, bool hasAuthority, out bool hasCreated) { if (sceneId > 0) { - if (_sceneEntities.TryGetValue(sceneId, out var entity)) + if (_sceneEntities.TryGetValue(sceneId, out var sceneEntity)) { - _entityMap.Add(entityId, entity); + _entityMap.Add(entityId, sceneEntity); if (hasAuthority) - _entityList.Add(entity); - - return entity; + _entityList.Add(sceneEntity); + + hasCreated = false; + + return sceneEntity; } } - if (_pendingEntities.Remove(attachId, out var existsEntity)) + if (_pendingEntities.TryGetValue(attachId, out var pendingEntity)) { - _entityMap.Add(entityId, existsEntity); + _pendingEntities.Remove(attachId); + _entityMap.Add(entityId, pendingEntity); if (hasAuthority) - _entityList.Add(existsEntity); + _entityList.Add(pendingEntity); - return existsEntity; + hasCreated = false; + + return pendingEntity; } - else - { - var entity = new RagonEntity(entityType, sceneId); - _entityMap.Add(entityId, entity); - if (hasAuthority) - _entityList.Add(entity); + var entity = new RagonEntity(entityType, sceneId); + + _entityMap.Add(entityId, entity); + + if (hasAuthority) + _entityList.Add(entity); - _entityListener.OnEntityCreated(entity); - - return entity; - } + hasCreated = true; + + return entity; } internal void OnDestroy(ushort entityId, RagonPayload payload) { - if (_entityMap.Remove(entityId, out var ragonEntity)) + if (_entityMap.TryGetValue(entityId, out var entity)) { - _entityList.Remove(ragonEntity); + _entityMap.Remove(entityId); + _entityList.Remove(entity); - ragonEntity.Detach(payload); + entity.Detach(payload); } } @@ -244,7 +246,7 @@ public sealed class RagonEntityCache _entityList.Add(entity); else _entityList.Remove(entity); - + entity.OnOwnershipChanged(player); } else diff --git a/Ragon.Client/Sources/RagonPlayerCache.cs b/Ragon.Client/Sources/RagonPlayerCache.cs index bec7bbc..55f66f2 100644 --- a/Ragon.Client/Sources/RagonPlayerCache.cs +++ b/Ragon.Client/Sources/RagonPlayerCache.cs @@ -64,9 +64,10 @@ public sealed class RagonPlayerCache public void RemovePlayer(string playerId) { - if (_playersById.Remove(playerId, out var player)) + if (_playersById.TryGetValue(playerId, out var player)) { _players.Remove(player); + _playersById.Remove(playerId); _playersByConnection.Remove(player.PeerId); } } diff --git a/Ragon.Client/Sources/RagonRoom.cs b/Ragon.Client/Sources/RagonRoom.cs index 3a1a5ba..cd00af9 100644 --- a/Ragon.Client/Sources/RagonRoom.cs +++ b/Ragon.Client/Sources/RagonRoom.cs @@ -55,10 +55,10 @@ namespace Ragon.Client public void SceneLoaded() => _scene.SceneLoaded(); public void CreateEntity(RagonEntity entity) => CreateEntity(entity, null); - public void CreateEntity(RagonEntity entity, IRagonPayload? payload) => _entityCache.Create(entity, payload); + public void CreateEntity(RagonEntity entity, RagonPayload payload) => _entityCache.Create(entity, payload); public void TransferEntity(RagonEntity entity, RagonPlayer player) => _entityCache.Transfer(entity, player); public void DestroyEntity(RagonEntity entityId) => DestroyEntity(entityId, null); - public void DestroyEntity(RagonEntity entityId, IRagonPayload? payload) => _entityCache.Destroy(entityId, payload); + public void DestroyEntity(RagonEntity entityId, RagonPayload payload) => _entityCache.Destroy(entityId, payload); } } \ No newline at end of file diff --git a/Ragon.Protocol/Ragon.Protocol.csproj b/Ragon.Protocol/Ragon.Protocol.csproj index ed88ebb..c2a2e8f 100644 --- a/Ragon.Protocol/Ragon.Protocol.csproj +++ b/Ragon.Protocol/Ragon.Protocol.csproj @@ -13,7 +13,7 @@ https://github.com/edmand46/Ragon Source Apache-2.0 - netstandard2.1 + netstandard2.0 diff --git a/Ragon.Protocol/Sources/RagonBuffer.cs b/Ragon.Protocol/Sources/RagonBuffer.cs index 27aabb6..f8cb693 100644 --- a/Ragon.Protocol/Sources/RagonBuffer.cs +++ b/Ragon.Protocol/Sources/RagonBuffer.cs @@ -58,7 +58,6 @@ using System; using System.Diagnostics; -using System.Linq; using System.Runtime.CompilerServices; using System.Text; @@ -245,7 +244,7 @@ namespace Ragon.Protocol if (currentBucketIndex + 1 >= _buckets.Length) Resize(1); - + _buckets[currentBucketIndex] = (uint)result; _buckets[currentBucketIndex + 1] = (uint)(result >> 32); @@ -292,13 +291,13 @@ namespace Ragon.Protocol } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ReadSpan(ref Span data, int size) + public void ReadArray(uint[] data, int size) { var used = _read & 0x0000001F; var index = _read >> 5; var limit = (size + 32 - 1) / 32; var capacity = size; - + for (int i = 0; i < limit; i++) { var dataSize = capacity > 32 ? 32 : capacity; @@ -306,23 +305,24 @@ namespace Ragon.Protocol var bucketRaw = (ulong)_buckets[index]; if (index + 1 < _buckets.Length) bucketRaw |= (ulong)_buckets[index + 1] << 32; - + var bucket = bucketRaw >> used; var result = bucket & mask; - + data[i] = (uint)result; if (i + 1 < data.Length) data[i + 1] = (uint)(result >> 32); - + index += 1; capacity -= dataSize; } - + _read += size; } - + + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteSpan(ref ReadOnlySpan data, int size) + public void WriteArray(uint[] data, int size) { var used = _write & 0x0000001F; var index = _write >> 5; @@ -330,20 +330,20 @@ namespace Ragon.Protocol if (index + limit >= _buckets.Length) Resize(size); - + for (var i = 0; i < limit; i += 1) { - var prepared = (ulong) data[i] << used; + var prepared = (ulong)data[i] << used; var mask = (1UL << used) - 1; var scratch = _buckets[index] & mask; var result = scratch | prepared; - + _buckets[index] = (uint)result; _buckets[index + 1] = (uint)(result >> 32); - + index += 1; } - + _write += size; } @@ -356,17 +356,15 @@ namespace Ragon.Protocol [MethodImpl(MethodImplOptions.AggressiveInlining)] public void FromBuffer(RagonBuffer buffer, int size) { - ReadOnlySpan data = buffer._buckets.AsSpan(); - WriteSpan(ref data, size); + WriteArray(buffer._buckets, size); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBuffer(RagonBuffer buffer, int size) { - var data = buffer._buckets.AsSpan(); - ReadSpan(ref data, size); + ReadArray(buffer._buckets, size); } - + public void FromArray(byte[] data) { var length = data.Length; diff --git a/Ragon.Server/Sources/Entity/RagonEvent.cs b/Ragon.Server/Sources/Entity/RagonEvent.cs index ae0a773..3fac411 100644 --- a/Ragon.Server/Sources/Entity/RagonEvent.cs +++ b/Ragon.Server/Sources/Entity/RagonEvent.cs @@ -39,15 +39,12 @@ public class RagonEvent public void Read(RagonBuffer buffer) { - var readOnlySpan = _data.AsSpan(); - _size = buffer.Capacity; - buffer.ReadSpan(ref readOnlySpan, _size); + buffer.ReadArray(_data, buffer.Capacity); } public void Write(RagonBuffer buffer) { if (_size == 0) return; - ReadOnlySpan readOnlySpan = _data.AsSpan(); - buffer.WriteSpan(ref readOnlySpan, _size); + buffer.WriteArray(_data, _size); } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Entity/RagonPayload.cs b/Ragon.Server/Sources/Entity/RagonPayload.cs index b461759..d073273 100644 --- a/Ragon.Server/Sources/Entity/RagonPayload.cs +++ b/Ragon.Server/Sources/Entity/RagonPayload.cs @@ -28,19 +28,13 @@ public class RagonPayload public void Read(RagonBuffer buffer) { - var readOnlySpan = _data.AsSpan(); - _size = buffer.Capacity; - - buffer.ReadSpan(ref readOnlySpan, _size); + buffer.ReadArray(_data, _size); } public void Write(RagonBuffer buffer) { if (_size == 0) return; - - ReadOnlySpan readOnlySpan = _data.AsSpan(); - - buffer.WriteSpan(ref readOnlySpan, _size); + buffer.WriteArray(_data, _size); } } \ No newline at end of file diff --git a/Ragon.Server/Sources/Entity/RagonProperty.cs b/Ragon.Server/Sources/Entity/RagonProperty.cs index 7738caf..b01509f 100644 --- a/Ragon.Server/Sources/Entity/RagonProperty.cs +++ b/Ragon.Server/Sources/Entity/RagonProperty.cs @@ -37,15 +37,14 @@ public class RagonProperty : RagonPayload public void Read(RagonBuffer buffer) { - var readOnlySpan = _data.AsSpan(); if (IsFixed) { - buffer.ReadSpan(ref readOnlySpan, Size); + buffer.ReadArray(_data, Size); } else { Size = (int) buffer.Read(); - buffer.ReadSpan(ref readOnlySpan, Size); + buffer.ReadArray(_data, Size); } IsDirty = true; @@ -53,8 +52,7 @@ public class RagonProperty : RagonPayload public void Write(RagonBuffer buffer) { - ReadOnlySpan readOnlySpan = _data.AsSpan(); - buffer.WriteSpan(ref readOnlySpan, Size); + buffer.WriteArray(_data, Size); } public void Clear() diff --git a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs index eed63d8..7701fa6 100644 --- a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs +++ b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs @@ -42,7 +42,6 @@ public sealed class SceneLoadedOperation : IRagonOperation if (player == owner) { - var statics = reader.ReadUShort(); for (var staticIndex = 0; staticIndex < statics; staticIndex++) { From 5199b5271b84d67eff791f381a1c31acc159c293 Mon Sep 17 00:00:00 2001 From: edmand45 Date: Sun, 30 Jul 2023 16:56:11 +0300 Subject: [PATCH 2/2] :bug: Remove listener inside callback --- Ragon.Client/Ragon.Client.csproj | 4 +- Ragon.Client/Sources/Entity/RagonEntity.cs | 4 +- .../Sources/Handler/SnapshotHandler.cs | 35 ++++++------- Ragon.Client/Sources/RagonClient.cs | 3 +- Ragon.Client/Sources/RagonEntityCache.cs | 4 +- Ragon.Client/Sources/RagonListenerList.cs | 50 ++++++++++++------- Ragon.Server/Sources/Entity/RagonEntity.cs | 6 ++- .../Sources/Handler/SceneLoadedOperation.cs | 2 +- 8 files changed, 62 insertions(+), 46 deletions(-) diff --git a/Ragon.Client/Ragon.Client.csproj b/Ragon.Client/Ragon.Client.csproj index 41c4715..c94409a 100644 --- a/Ragon.Client/Ragon.Client.csproj +++ b/Ragon.Client/Ragon.Client.csproj @@ -12,11 +12,11 @@ true none - /Users/edmand46/RagonProjects/ragon-oss-sdk/Assets/Ragon/Plugins/ + /Users/edmand46/RagonProjects/ragon-oss-examples/Assets/Ragon/Plugins/ - /Users/edmand46/RagonProjects/ragon-unity-sdk/Assets/Ragon/Runtime/Plugins + /Users/edmand46/RagonProjects/ragon-oss-examples/Assets/Ragon/Plugins/ diff --git a/Ragon.Client/Sources/Entity/RagonEntity.cs b/Ragon.Client/Sources/Entity/RagonEntity.cs index 2a2149b..29b1250 100644 --- a/Ragon.Client/Sources/Entity/RagonEntity.cs +++ b/Ragon.Client/Sources/Entity/RagonEntity.cs @@ -56,7 +56,9 @@ namespace Ragon.Client { State = new RagonEntityState(this); Type = type; - + + _spawnPayload = new RagonPayload(0); + _destroyPayload = new RagonPayload(0); _sceneId = sceneId; } diff --git a/Ragon.Client/Sources/Handler/SnapshotHandler.cs b/Ragon.Client/Sources/Handler/SnapshotHandler.cs index 3798e12..09611a5 100644 --- a/Ragon.Client/Sources/Handler/SnapshotHandler.cs +++ b/Ragon.Client/Sources/Handler/SnapshotHandler.cs @@ -33,7 +33,7 @@ internal class SnapshotHandler : Handler RagonListenerList listenerList, RagonEntityCache entityCache, RagonPlayerCache playerCache, - IRagonEntityListener entityListener + IRagonEntityListener entityListener ) { _client = ragonClient; @@ -52,9 +52,9 @@ internal class SnapshotHandler : Handler var playerPeerId = buffer.ReadUShort(); var playerId = buffer.ReadString(); var playerName = buffer.ReadString(); - + _playerCache.AddPlayer(playerPeerId, playerId, playerName); - + RagonLog.Trace($"Player {playerPeerId} - {playerId} - {playerName}"); } @@ -66,10 +66,7 @@ internal class SnapshotHandler : Handler var entityId = buffer.ReadUShort(); var ownerPeerId = buffer.ReadUShort(); var payloadSize = buffer.ReadUShort(); - var payload = new RagonPayload(payloadSize); - payload.Read(buffer); - - RagonLog.Trace($"Entity {entityType} - {entityId} - {ownerPeerId} - {payloadSize}"); + RagonLog.Trace("Read offset: " + buffer.ReadOffset); var player = _playerCache.GetPlayerByPeer(ownerPeerId); if (player == null) @@ -81,11 +78,17 @@ internal class SnapshotHandler : Handler var hasAuthority = _playerCache.Local.Id == player.Id; var entity = _entityCache.TryGetEntity(0, entityType, 0, entityId, hasAuthority, out _); - entity.Read(buffer); - entity.AttachPayload(payload); + if (payloadSize > 0) + { + var payload = new RagonPayload(payloadSize); + payload.Read(buffer); + + entity.AttachPayload(payload); + } _entityListener.OnEntityCreated(entity); + entity.Read(buffer); entity.Attach(_client, entityId, entityType, hasAuthority, player); } @@ -98,26 +101,20 @@ internal class SnapshotHandler : Handler var staticId = buffer.ReadUShort(); var ownerPeerId = buffer.ReadUShort(); var payloadSize = buffer.ReadUShort(); - var payload = new RagonPayload(payloadSize); - payload.Read(buffer); - - RagonLog.Trace($"Entity {entityType} - {entityId} - {ownerPeerId} - {payloadSize}"); - + var player = _playerCache.GetPlayerByPeer(ownerPeerId); if (player == null) { RagonLog.Error($"Player not found with peerId: ${ownerPeerId}"); return; } - + var hasAuthority = _playerCache.Local.Id == player.Id; var entity = _entityCache.TryGetEntity(0, entityType, staticId, entityId, hasAuthority, out _); - - entity.Read(buffer); - entity.AttachPayload(payload); - + _entityListener.OnEntityCreated(entity); + entity.Read(buffer); entity.Attach(_client, entityId, entityType, hasAuthority, player); } diff --git a/Ragon.Client/Sources/RagonClient.cs b/Ragon.Client/Sources/RagonClient.cs index 49ed555..655c9b0 100644 --- a/Ragon.Client/Sources/RagonClient.cs +++ b/Ragon.Client/Sources/RagonClient.cs @@ -144,7 +144,8 @@ namespace Ragon.Client _stats.Update(_connection.BytesSent, _connection.BytesReceived, _connection.Ping, dt); } - + + _listenerList.Update(); _connection.Update(); } diff --git a/Ragon.Client/Sources/RagonEntityCache.cs b/Ragon.Client/Sources/RagonEntityCache.cs index 1bbb7c7..31f841d 100644 --- a/Ragon.Client/Sources/RagonEntityCache.cs +++ b/Ragon.Client/Sources/RagonEntityCache.cs @@ -60,7 +60,7 @@ public sealed class RagonEntityCache entity.State.WriteInfo(buffer); - spawnPayload.Write(buffer); + spawnPayload?.Write(buffer); _pendingEntities.Add(attachId, entity); @@ -95,7 +95,7 @@ public sealed class RagonEntityCache buffer.WriteOperation(RagonOperation.REMOVE_ENTITY); buffer.WriteUShort(entity.Id); - destroyPayload.Write(buffer); + destroyPayload?.Write(buffer); var sendData = buffer.ToArray(); _client.Reliable.Send(sendData); diff --git a/Ragon.Client/Sources/RagonListenerList.cs b/Ragon.Client/Sources/RagonListenerList.cs index 4e33d07..f3ebe16 100644 --- a/Ragon.Client/Sources/RagonListenerList.cs +++ b/Ragon.Client/Sources/RagonListenerList.cs @@ -30,6 +30,7 @@ namespace Ragon.Client private readonly List _ownershipChangedListeners = new(); private readonly List _playerJoinListeners = new(); private readonly List _playerLeftListeners = new(); + private readonly List _delayedActions = new(); public RagonListenerList(RagonClient client) { @@ -51,16 +52,28 @@ namespace Ragon.Client public void Remove(IRagonListener listener) { - _authorizationListeners.Remove(listener); - _connectionListeners.Remove(listener); - _failedListeners.Remove(listener); - _joinListeners.Remove(listener); - _leftListeners.Remove(listener); - _levelListeners.Remove(listener); - _ownershipChangedListeners.Remove(listener); - _playerJoinListeners.Remove(listener); - _playerLeftListeners.Remove(listener); + _delayedActions.Add(() => + { + _authorizationListeners.Remove(listener); + _connectionListeners.Remove(listener); + _failedListeners.Remove(listener); + _joinListeners.Remove(listener); + _leftListeners.Remove(listener); + _levelListeners.Remove(listener); + _ownershipChangedListeners.Remove(listener); + _playerJoinListeners.Remove(listener); + _playerLeftListeners.Remove(listener); + }); } + + public void Update() + { + foreach (var action in _delayedActions) + action.Invoke(); + + _delayedActions.Clear(); + } + public void Add(IRagonAuthorizationListener listener) { @@ -109,47 +122,48 @@ namespace Ragon.Client public void Remove(IRagonAuthorizationListener listener) { - _authorizationListeners.Remove(listener); + _delayedActions.Add(() => _authorizationListeners.Remove(listener)); } public void Remove(IRagonConnectionListener listener) { - _connectionListeners.Remove(listener); + + _delayedActions.Add(() => _connectionListeners.Remove(listener)); } public void Remove(IRagonFailedListener listener) { - _failedListeners.Remove(listener); + _delayedActions.Add(() => _failedListeners.Remove(listener)); } public void Remove(IRagonJoinListener listener) { - _joinListeners.Remove(listener); + _delayedActions.Add(() => _joinListeners.Remove(listener)); } public void Remove(IRagonLeftListener listener) { - _leftListeners.Remove(listener); + _delayedActions.Add(() => _leftListeners.Remove(listener)); } public void Remove(IRagonLevelListener listener) { - _levelListeners.Remove(listener); + _delayedActions.Add(() => _levelListeners.Remove(listener)); } public void Remove(IRagonOwnershipChangedListener listener) { - _ownershipChangedListeners.Remove(listener); + _delayedActions.Add(() => _ownershipChangedListeners.Remove(listener)); } public void Remove(IRagonPlayerJoinListener listener) { - _playerJoinListeners.Remove(listener); + _delayedActions.Add(() => _playerJoinListeners.Remove(listener)); } public void Remove(IRagonPlayerLeftListener listener) { - _playerLeftListeners.Remove(listener); + _delayedActions.Add(() => _playerLeftListeners.Remove(listener)); } public void OnAuthorizationSuccess(string playerId, string playerName, string payload) diff --git a/Ragon.Server/Sources/Entity/RagonEntity.cs b/Ragon.Server/Sources/Entity/RagonEntity.cs index 842d441..a487bd1 100644 --- a/Ragon.Server/Sources/Entity/RagonEntity.cs +++ b/Ragon.Server/Sources/Entity/RagonEntity.cs @@ -117,13 +117,15 @@ public class RagonEntity : IRagonEntity { buffer.WriteUShort(Type); buffer.WriteUShort(Id); + if (StaticId != 0) buffer.WriteUShort(StaticId); + buffer.WriteUShort(Owner.Connection.Id); - buffer.WriteUShort(Payload.Size); + Payload.Write(buffer); - + _state.Snapshot(buffer); } diff --git a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs index 7701fa6..a037e72 100644 --- a/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs +++ b/Ragon.Server/Sources/Handler/SceneLoadedOperation.cs @@ -72,7 +72,7 @@ public sealed class SceneLoadedOperation : IRagonOperation var playerInfo = $"Player {context.Connection.Id}|{context.LobbyPlayer.Name}"; var entityInfo = $"{entity.Id}:{entity.Type}"; - _logger.Trace($"{playerInfo} created entity {entityInfo}"); + _logger.Trace($"{playerInfo} created static entity {entityInfo}"); entity.Attach(player); room.AttachEntity(entity);