This commit is contained in:
2023-07-29 10:58:06 +03:00
parent 0a8d761cc1
commit c01b748031
16 changed files with 133 additions and 118 deletions
+3 -10
View File
@@ -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<T>() where T : IRagonPayload, new()
+3 -7
View File
@@ -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<uint> readOnlySpan = _data.AsSpan();
buffer.WriteSpan(ref readOnlySpan, _size);
buffer.WriteArray(_data, _size);
}
public override string ToString()
@@ -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);
}
}
@@ -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);
}
}
}
+44 -16
View File
@@ -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();
}
}
+3 -3
View File
@@ -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);
+35 -33
View File
@@ -26,7 +26,6 @@ public sealed class RagonEntityCache
private readonly Dictionary<uint, RagonEntity> _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
+2 -1
View File
@@ -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);
}
}
+2 -2
View File
@@ -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);
}
}