feat: added safe get entity by id

This commit is contained in:
2023-07-09 07:40:06 +03:00
parent 1406b17d62
commit 0479a21980
5 changed files with 72 additions and 46 deletions
+33 -23
View File
@@ -22,16 +22,17 @@ namespace Ragon.Client
public sealed class RagonEntity public sealed class RagonEntity
{ {
private delegate void OnEventDelegate(RagonPlayer player, RagonBuffer serializer); private delegate void OnEventDelegate(RagonPlayer player, RagonBuffer serializer);
private RagonClient _client; private RagonClient _client;
public ushort Id { get; private set; } public ushort Id { get; private set; }
public ushort Type { get; private set; } public ushort Type { get; private set; }
public bool Replication { get; private set; } public bool Replication { get; private set; }
public RagonAuthority Authority { get; private set; } public RagonAuthority Authority { get; private set; }
public RagonPlayer Owner { get; private set; } public RagonPlayer Owner { get; private set; }
public RagonEntityState State { get; private set; } public RagonEntityState State { get; private set; }
public bool IsAttached { get; private set; } public bool IsAttached { get; private set; }
public bool HasAuthority { get; private set; } public bool HasAuthority { get; private set; }
@@ -41,7 +42,7 @@ namespace Ragon.Client
internal bool PropertiesChanged => _propertiesChanged; internal bool PropertiesChanged => _propertiesChanged;
internal ushort SceneId => _sceneId; internal ushort SceneId => _sceneId;
private ushort _sceneId; private ushort _sceneId;
private bool _propertiesChanged; private bool _propertiesChanged;
@@ -55,7 +56,7 @@ namespace Ragon.Client
{ {
State = new RagonEntityState(this); State = new RagonEntityState(this);
Type = type; Type = type;
_sceneId = sceneId; _sceneId = sceneId;
} }
@@ -67,17 +68,17 @@ namespace Ragon.Client
IsAttached = true; IsAttached = true;
Replication = true; Replication = true;
HasAuthority = hasAuthority; HasAuthority = hasAuthority;
_client = client; _client = client;
_spawnPayload = payload; _spawnPayload = payload;
Attached?.Invoke(this); Attached?.Invoke(this);
} }
internal void Detach(RagonPayload payload) internal void Detach(RagonPayload payload)
{ {
_destroyPayload = payload; _destroyPayload = payload;
Detached?.Invoke(); Detached?.Invoke();
} }
@@ -91,6 +92,15 @@ namespace Ragon.Client
return payload; return payload;
} }
public void PreAttach(IRagonPayload payload)
{
var buffer = new RagonBuffer();
payload.Serialize(buffer);
_spawnPayload = new RagonPayload();
_spawnPayload.Read(buffer);
}
public T GetAttachPayload<T>() where T : IRagonPayload, new() public T GetAttachPayload<T>() where T : IRagonPayload, new()
{ {
@@ -110,7 +120,7 @@ namespace Ragon.Client
RagonLog.Error("Entity not attached"); RagonLog.Error("Entity not attached");
return; return;
} }
var evntId = _client.Event.GetEventCode(evnt); var evntId = _client.Event.GetEventCode(evnt);
var buffer = _client.Buffer; var buffer = _client.Buffer;
@@ -118,12 +128,12 @@ namespace Ragon.Client
buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT); buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
buffer.WriteUShort(Id); buffer.WriteUShort(Id);
buffer.WriteUShort(evntId); buffer.WriteUShort(evntId);
buffer.WriteByte((byte) replicationMode); buffer.WriteByte((byte)replicationMode);
buffer.WriteByte((byte) RagonTarget.Player); buffer.WriteByte((byte)RagonTarget.Player);
buffer.WriteUShort(target.PeerId); buffer.WriteUShort(target.PeerId);
evnt.Serialize(buffer); evnt.Serialize(buffer);
var sendData = buffer.ToArray(); var sendData = buffer.ToArray();
_client.Reliable.Send(sendData); _client.Reliable.Send(sendData);
} }
@@ -139,7 +149,7 @@ namespace Ragon.Client
RagonLog.Error("Entity not attached"); RagonLog.Error("Entity not attached");
return; return;
} }
if (target != RagonTarget.ExceptOwner) if (target != RagonTarget.ExceptOwner)
{ {
if (replicationMode == RagonReplicationMode.Local) if (replicationMode == RagonReplicationMode.Local)
@@ -163,8 +173,8 @@ namespace Ragon.Client
buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT); buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
buffer.WriteUShort(Id); buffer.WriteUShort(Id);
buffer.WriteUShort(evntId); buffer.WriteUShort(evntId);
buffer.WriteByte((byte) replicationMode); buffer.WriteByte((byte)replicationMode);
buffer.WriteByte((byte) target); buffer.WriteByte((byte)target);
evnt.Serialize(buffer); evnt.Serialize(buffer);
@@ -181,18 +191,18 @@ namespace Ragon.Client
{ {
_events.Remove(eventCode); _events.Remove(eventCode);
_localEvents.Remove(eventCode); _localEvents.Remove(eventCode);
RagonLog.Warn($"Event already {eventCode} subscribed, removed old one!"); RagonLog.Warn($"Event already {eventCode} subscribed, removed old one!");
} }
_localEvents.Add(eventCode, (player, eventData) => { callback.Invoke(player, (TEvent) eventData); }); _localEvents.Add(eventCode, (player, eventData) => { callback.Invoke(player, (TEvent)eventData); });
_events.Add(eventCode, (player, serializer) => _events.Add(eventCode, (player, serializer) =>
{ {
t.Deserialize(serializer); t.Deserialize(serializer);
callback.Invoke(player, t); callback.Invoke(player, t);
}); });
} }
internal void Write(RagonBuffer buffer) internal void Write(RagonBuffer buffer)
{ {
buffer.WriteUShort(Id); buffer.WriteUShort(Id);
@@ -212,7 +222,7 @@ namespace Ragon.Client
{ {
if (_events.TryGetValue(eventCode, out var evnt)) if (_events.TryGetValue(eventCode, out var evnt))
evnt?.Invoke(caller, buffer); evnt?.Invoke(caller, buffer);
else else
RagonLog.Warn($"Handler event on entity {Id} with eventCode {eventCode} not defined"); RagonLog.Warn($"Handler event on entity {Id} with eventCode {eventCode} not defined");
} }
@@ -224,10 +234,10 @@ namespace Ragon.Client
public void OnOwnershipChanged(RagonPlayer player) public void OnOwnershipChanged(RagonPlayer player)
{ {
var prevOwner = Owner; var prevOwner = Owner;
Owner = player; Owner = player;
HasAuthority = player.IsLocal; HasAuthority = player.IsLocal;
OwnershipChanged?.Invoke(prevOwner, player); OwnershipChanged?.Invoke(prevOwner, player);
} }
} }
+29 -12
View File
@@ -21,8 +21,8 @@ namespace Ragon.Client
public sealed class RagonClient public sealed class RagonClient
{ {
private readonly INetworkConnection _connection; private readonly INetworkConnection _connection;
private readonly IRagonEntityListener _entityListener; private IRagonEntityListener _entityListener;
private readonly IRagonSceneCollector _sceneCollector; private IRagonSceneCollector _sceneCollector;
private Handler[] _handlers; private Handler[] _handlers;
private RagonBuffer _readBuffer; private RagonBuffer _readBuffer;
private RagonBuffer _writeBuffer; private RagonBuffer _writeBuffer;
@@ -52,21 +52,15 @@ namespace Ragon.Client
#region PUBLIC #region PUBLIC
public RagonClient( public RagonClient(INetworkConnection connection, int rate)
INetworkConnection connection,
IRagonEntityListener entityListener,
IRagonSceneCollector sceneCollector,
int rate)
{ {
_listenerList = new RagonListenerList(this);
_entityListener = entityListener;
_sceneCollector = sceneCollector;
_connection = connection; _connection = connection;
_connection.OnData += OnData; _connection.OnData += OnData;
_connection.OnConnected += OnConnected; _connection.OnConnected += OnConnected;
_connection.OnDisconnected += OnDisconnected; _connection.OnDisconnected += OnDisconnected;
_listenerList = new RagonListenerList(this);
_replicationRate = (1000.0f / rate) / 1000.0f; _replicationRate = (1000.0f / rate) / 1000.0f;
_replicationTime = 0; _replicationTime = 0;
@@ -74,9 +68,32 @@ namespace Ragon.Client
_stats = new NetworkStatistics(); _stats = new NetworkStatistics();
_status = RagonStatus.DISCONNECTED; _status = RagonStatus.DISCONNECTED;
} }
public void Configure(IRagonSceneCollector sceneCollector)
{
_sceneCollector = sceneCollector;
}
public void Configure(IRagonEntityListener listener)
{
_entityListener = listener;
}
public void Connect(string address, ushort port, string protocol) public void Connect(string address, ushort port, string protocol)
{ {
if (_sceneCollector == null)
{
RagonLog.Error("Scene collector is not defined!");
return;
}
if (_entityListener == null)
{
RagonLog.Error("Entity Listener is not defined!");
return;
}
_writeBuffer = new RagonBuffer(); _writeBuffer = new RagonBuffer();
_readBuffer = new RagonBuffer(); _readBuffer = new RagonBuffer();
_session = new RagonSession(this, _readBuffer); _session = new RagonSession(this, _readBuffer);
+2 -2
View File
@@ -45,9 +45,9 @@ public sealed class RagonEntityCache
_playerCache = playerCache; _playerCache = playerCache;
} }
public RagonEntity FindById(ushort id) public bool TryGetEntity(ushort id, out RagonEntity entity)
{ {
return _entityMap[id]; return _entityMap.TryGetValue(id, out entity);
} }
public void Create(RagonEntity entity, IRagonPayload? spawnPayload) public void Create(RagonEntity entity, IRagonPayload? spawnPayload)
@@ -54,8 +54,8 @@ public sealed class EntityCreateOperation : IRagonOperation
if (reader.Capacity > 0) if (reader.Capacity > 0)
entity.Payload.Read(reader); entity.Payload.Read(reader);
var roomPlugin = room.Plugin; var plugin = room.Plugin;
if (!roomPlugin.OnEntityCreate(player, entity)) if (!plugin.OnEntityCreate(player, entity))
return; return;
entity.Attach(player); entity.Attach(player);
@@ -40,20 +40,19 @@ public sealed class EntityEventOperation : IRagonOperation
var eventMode = (RagonReplicationMode)reader.ReadByte(); var eventMode = (RagonReplicationMode)reader.ReadByte();
var targetMode = (RagonTarget)reader.ReadByte(); var targetMode = (RagonTarget)reader.ReadByte();
var targetPlayerPeerId = (ushort)0; var targetPlayerPeerId = (ushort)0;
if (targetMode == RagonTarget.Player) if (targetMode == RagonTarget.Player)
targetPlayerPeerId = reader.ReadUShort(); targetPlayerPeerId = reader.ReadUShort();
var ragonEvent = new RagonEvent(player, eventId); var @event = new RagonEvent(player, eventId);
ragonEvent.Read(reader); @event.Read(reader);
if (targetMode == RagonTarget.Player && if (targetMode == RagonTarget.Player && room.Players.TryGetValue(targetPlayerPeerId, out var targetPlayer))
context.Room.Players.TryGetValue(targetPlayerPeerId, out var targetPlayer))
{ {
ent.ReplicateEvent(player, ragonEvent, eventMode, targetPlayer); ent.ReplicateEvent(player, @event, eventMode, targetPlayer);
return; return;
} }
ent.ReplicateEvent(player, ragonEvent, eventMode, targetMode); ent.ReplicateEvent(player, @event, eventMode, targetMode);
} }
} }