Compare commits

...

10 Commits

Author SHA1 Message Date
edmand46 fb58dedfaf changed scene loading flow 2023-07-30 21:46:42 +03:00
edmand46 92062cd708 🎨 update naming of fields 2023-07-30 21:19:39 +03:00
edmand46 5fc55eaddc wip 2023-07-30 21:14:14 +03:00
edmand46 4a8aae11e3 🚑 fixed empty state values 2023-07-30 17:44:51 +03:00
edmand46 cd9304e63a Merge pull request #13 from edmand46/fix/payload
Fix/payload
2023-07-30 17:01:08 +03:00
edmand46 5199b5271b 🐛 Remove listener inside callback 2023-07-30 16:56:11 +03:00
edmand46 c01b748031 wip 2023-07-29 10:58:06 +03:00
edmand46 0a8d761cc1 🐛 empty payload 2023-07-23 15:56:08 +03:00
edmand46 f38c7e98de ⬆️ deps 2023-07-23 11:23:38 +03:00
edmand46 0479a21980 feat: added safe get entity by id 2023-07-09 07:40:06 +03:00
43 changed files with 457 additions and 324 deletions
+25 -21
View File
@@ -4,7 +4,7 @@ using Ragon.Protocol;
namespace Ragon.Client.Simulation; namespace Ragon.Client.Simulation;
public class Game : IRagonListener public class Game : IRagonListener, IRagonSceneRequestListener
{ {
private RagonFloat _health; private RagonFloat _health;
private RagonInt _points; private RagonInt _points;
@@ -36,23 +36,7 @@ public class Game : IRagonListener
public void OnJoined(RagonClient client) public void OnJoined(RagonClient client)
{ {
RagonLog.Trace("Joined");
_health = new RagonFloat(100.0f, false, 0);
_health.Changed += () => Console.WriteLine($"[Ragon Property] Health: {_health.Value}");
_points = new RagonInt(0, -1000, 1000, false, 0);
_points.Changed += () => Console.WriteLine($"[Ragon Property] Points: {_points.Value}");
_name = new RagonString("Edmand 000", false);
_name.Changed += () => Console.WriteLine($"[Ragon Property] Name: {_name.Value}");
_entity = new RagonEntity(12, 0);
_entity.State.AddProperty(_health);
_entity.State.AddProperty(_points);
_entity.State.AddProperty(_name);
client.Room.CreateEntity(_entity);
} }
public void OnFailed(RagonClient client, string message) public void OnFailed(RagonClient client, string message)
@@ -85,11 +69,25 @@ public class Game : IRagonListener
RagonLog.Trace("Owner ship changed"); RagonLog.Trace("Owner ship changed");
} }
public void OnLevel(RagonClient client, string sceneName) public void OnSceneLoaded(RagonClient client)
{ {
RagonLog.Trace($"New level: {sceneName}"); RagonLog.Trace("Joined");
client.Room.SceneLoaded(); _health = new RagonFloat(100.0f, false, 0);
_health.Changed += () => Console.WriteLine($"[Ragon Property] Health: {_health.Value}");
_points = new RagonInt(0, -1000, 1000, false, 0);
_points.Changed += () => Console.WriteLine($"[Ragon Property] Points: {_points.Value}");
_name = new RagonString("Edmand 000", false);
_name.Changed += () => Console.WriteLine($"[Ragon Property] Name: {_name.Value}");
_entity = new RagonEntity(12, 0);
_entity.State.AddProperty(_health);
_entity.State.AddProperty(_points);
_entity.State.AddProperty(_name);
client.Room.CreateEntity(_entity);
} }
private float _timer = 0; private float _timer = 0;
@@ -109,4 +107,10 @@ public class Game : IRagonListener
_timer = 0; _timer = 0;
} }
} }
public void OnRequestScene(RagonClient client, string sceneName)
{
client.Room.SceneLoaded();
}
} }
+3 -3
View File
@@ -1,22 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>10</LangVersion> <LangVersion>10</LangVersion>
<RootNamespace>Ragon.Client.Simulation</RootNamespace> <RootNamespace>Ragon.Client.Simulation</RootNamespace>
<Authors>Eduard Kargin (Edmand46)</Authors> <Authors>Eduard Kargin (Edmand46)</Authors>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>none</DebugType> <DebugType>none</DebugType>
<OutputPath>/Users/edmand46/RagonProjects/ragon-oss-sdk/Assets/Ragon/Plugins/</OutputPath> <OutputPath>/Users/edmand46/RagonProjects/ragon-oss-examples/Assets/Ragon/Plugins/</OutputPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>/Users/edmand46/RagonProjects/ragon-unity-sdk/Assets/Ragon/Runtime/Plugins</OutputPath> <OutputPath>/Users/edmand46/RagonProjects/ragon-oss-examples/Assets/Ragon/Plugins/</OutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+43 -36
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,25 +42,27 @@ 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;
private RagonPayload _spawnPayload; private RagonPayload _spawnPayload;
private RagonPayload _destroyPayload; private RagonPayload _destroyPayload;
private Dictionary<int, OnEventDelegate> _events = new(); private readonly Dictionary<int, OnEventDelegate> _events = new Dictionary<int, OnEventDelegate>();
private Dictionary<int, Action<RagonPlayer, IRagonEvent>> _localEvents = new(); private readonly Dictionary<int, Action<RagonPlayer, IRagonEvent>> _localEvents = new Dictionary<int, Action<RagonPlayer, IRagonEvent>>();
public RagonEntity(ushort type = 0, ushort sceneId = 0) public RagonEntity(ushort type = 0, ushort sceneId = 0)
{ {
State = new RagonEntityState(this); State = new RagonEntityState(this);
Type = type; Type = type;
_spawnPayload = new RagonPayload(0);
_destroyPayload = new RagonPayload(0);
_sceneId = sceneId; _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; Type = entityType;
Id = entityId; Id = entityId;
@@ -67,30 +70,37 @@ namespace Ragon.Client
IsAttached = true; IsAttached = true;
Replication = true; Replication = true;
HasAuthority = hasAuthority; HasAuthority = hasAuthority;
_client = client; _client = client;
_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();
} }
internal T GetPayload<T>(RagonPayload data) where T : IRagonPayload, new() internal T GetPayload<T>(RagonPayload data) where T : IRagonPayload, new()
{ {
var buffer = new RagonBuffer();
data.Write(buffer);
var payload = new T(); var payload = new T();
if (data.Size <= 0) return payload;
var buffer = new RagonBuffer();
data.Write(buffer);
payload.Deserialize(buffer); payload.Deserialize(buffer);
return payload; return payload;
} }
public void AttachPayload(RagonPayload payload)
{
_spawnPayload = payload;
}
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,32 +149,29 @@ namespace Ragon.Client
RagonLog.Error("Entity not attached"); RagonLog.Error("Entity not attached");
return; return;
} }
var eventCode = _client.Event.GetEventCode(evnt);
if (target != RagonTarget.ExceptOwner) if (target != RagonTarget.ExceptOwner)
{ {
if (replicationMode == RagonReplicationMode.Local) if (replicationMode == RagonReplicationMode.Local)
{ {
var eventCode = _client.Event.GetEventCode(evnt);
_localEvents[eventCode].Invoke(_client.Room.Local, evnt); _localEvents[eventCode].Invoke(_client.Room.Local, evnt);
return; return;
} }
if (replicationMode == RagonReplicationMode.LocalAndServer) if (replicationMode == RagonReplicationMode.LocalAndServer)
{ {
var eventCode = _client.Event.GetEventCode(evnt);
_localEvents[eventCode].Invoke(_client.Room.Local, evnt); _localEvents[eventCode].Invoke(_client.Room.Local, evnt);
} }
} }
var evntId = _client.Event.GetEventCode(evnt);
var buffer = _client.Buffer; var buffer = _client.Buffer;
buffer.Clear(); buffer.Clear();
buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT); buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
buffer.WriteUShort(Id); buffer.WriteUShort(Id);
buffer.WriteUShort(evntId); buffer.WriteUShort(eventCode);
buffer.WriteByte((byte) replicationMode); buffer.WriteByte((byte)replicationMode);
buffer.WriteByte((byte) target); buffer.WriteByte((byte)target);
evnt.Serialize(buffer); evnt.Serialize(buffer);
@@ -181,18 +188,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 +219,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 +231,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);
} }
} }
+5 -9
View File
@@ -19,10 +19,10 @@ using Ragon.Protocol;
namespace Ragon.Client; namespace Ragon.Client;
public struct RagonPayload public class RagonPayload
{ {
private uint[] _data = new uint[128]; private readonly uint[] _data = new uint[128];
private int _size = 0; private readonly int _size = 0;
public RagonPayload(int capacity) public RagonPayload(int capacity)
{ {
@@ -32,16 +32,12 @@ public struct RagonPayload
public void Read(RagonBuffer buffer) public void Read(RagonBuffer buffer)
{ {
var readOnlySpan = _data.AsSpan(); buffer.ReadArray(_data, _size);
buffer.ReadSpan(ref readOnlySpan, _size);
} }
public void Write(RagonBuffer buffer) public void Write(RagonBuffer buffer)
{ {
ReadOnlySpan<uint> readOnlySpan = _data.AsSpan(); buffer.WriteArray(_data, _size);
buffer.WriteSpan(ref readOnlySpan, _size);
} }
public override string ToString() public override string ToString()
@@ -22,9 +22,13 @@ namespace Ragon.Client;
internal class AuthorizeSuccessHandler: Handler internal class AuthorizeSuccessHandler: Handler
{ {
private readonly RagonListenerList _listenerList; private readonly RagonListenerList _listenerList;
private readonly RagonClient _client;
public AuthorizeSuccessHandler(RagonListenerList listenerList) public AuthorizeSuccessHandler(
RagonClient client,
RagonListenerList listenerList)
{ {
_client = client;
_listenerList = listenerList; _listenerList = listenerList;
} }
@@ -34,6 +38,7 @@ internal class AuthorizeSuccessHandler: Handler
var playerName = buffer.ReadString(); var playerName = buffer.ReadString();
var playerPayload = buffer.ReadString(); var playerPayload = buffer.ReadString();
_client.SetStatus(RagonStatus.LOBBY);
_listenerList.OnAuthorizationSuccess(playerId, playerName, playerPayload); _listenerList.OnAuthorizationSuccess(playerId, playerName, playerPayload);
} }
} }
@@ -23,16 +23,18 @@ internal class EntityCreateHandler : Handler
private readonly RagonClient _client; private readonly RagonClient _client;
private readonly RagonPlayerCache _playerCache; private readonly RagonPlayerCache _playerCache;
private readonly RagonEntityCache _entityCache; private readonly RagonEntityCache _entityCache;
private readonly IRagonEntityListener _entityListener;
public EntityCreateHandler( public EntityCreateHandler(
RagonClient client, RagonClient client,
RagonPlayerCache playerCache, RagonPlayerCache playerCache,
RagonEntityCache entityCache RagonEntityCache entityCache,
IRagonEntityListener entityListener
) )
{ {
_client = client; _client = client;
_entityCache = entityCache; _entityCache = entityCache;
_playerCache = playerCache; _playerCache = playerCache;
_entityListener = entityListener;
} }
public void Handle(RagonBuffer buffer) public void Handle(RagonBuffer buffer)
@@ -52,7 +54,13 @@ internal class EntityCreateHandler : Handler
} }
var hasAuthority = _playerCache.Local.Id == player.Id; var hasAuthority = _playerCache.Local.Id == player.Id;
var entity = _entityCache.OnCreate(attachId, entityType, 0, entityId, hasAuthority); var entity = _entityCache.TryGetEntity(attachId, entityType, 0, entityId, hasAuthority, out var hasCreated);
entity.Attach(_client, entityId, entityType, hasAuthority, player, payload);
entity.AttachPayload(payload);
if (hasCreated)
_entityListener.OnEntityCreated(entity);
entity.Attach(_client, entityId, entityType, hasAuthority, player);
} }
} }
@@ -43,7 +43,6 @@ internal class JoinSuccessHandler : Handler
private readonly RagonPlayerCache _playerCache; private readonly RagonPlayerCache _playerCache;
private readonly RagonEntityCache _entityCache; private readonly RagonEntityCache _entityCache;
private readonly RagonClient _client; private readonly RagonClient _client;
private readonly RagonBuffer _buffer;
public JoinSuccessHandler( public JoinSuccessHandler(
RagonClient client, RagonClient client,
@@ -53,7 +52,6 @@ internal class JoinSuccessHandler : Handler
RagonEntityCache entityCache RagonEntityCache entityCache
) )
{ {
_buffer = buffer;
_client = client; _client = client;
_listenerList = listenerList; _listenerList = listenerList;
_entityCache = entityCache; _entityCache = entityCache;
@@ -67,14 +65,15 @@ internal class JoinSuccessHandler : Handler
var ownerId = buffer.ReadString(); var ownerId = buffer.ReadString();
var min = buffer.ReadUShort(); var min = buffer.ReadUShort();
var max = buffer.ReadUShort(); var max = buffer.ReadUShort();
var map = buffer.ReadString(); var sceneName = buffer.ReadString();
var scene = new RagonScene(_client, _playerCache, _entityCache); var scene = new RagonScene(_client, _playerCache, _entityCache, sceneName);
var roomInfo = new RagonRoomInformation(roomId, localId, ownerId, min, max); var roomInfo = new RagonRoomInformation(roomId, localId, ownerId, min, max);
var room = new RagonRoom(_client, _entityCache, _playerCache, roomInfo, scene); var room = new RagonRoom(_client, _entityCache, _playerCache, roomInfo, scene);
_playerCache.SetOwnerAndLocal(ownerId, localId); _playerCache.SetOwnerAndLocal(ownerId, localId);
_client.AssignRoom(room); _client.AssignRoom(room);
_listenerList.OnLevel(map);
_listenerList.OnSceneRequest(sceneName);
} }
} }
@@ -38,7 +38,8 @@ internal class SceneLoadHandler: Handler
var room = _client.Room; var room = _client.Room;
room.Cleanup(); room.Cleanup();
room.Update(sceneName);
_listenerList.OnLevel(sceneName); _listenerList.OnSceneRequest(sceneName);
} }
} }
@@ -53,8 +53,9 @@ internal class PlayerLeftHandler : Handler
toDeleteIds[i] = entityId; toDeleteIds[i] = entityId;
} }
var emptyPayload = new RagonPayload(0);
foreach (var id in toDeleteIds) foreach (var id in toDeleteIds)
_entityCache.OnDestroy(id, new RagonPayload()); _entityCache.OnDestroy(id, emptyPayload);
} }
} }
} }
+48 -17
View File
@@ -22,19 +22,22 @@ namespace Ragon.Client;
internal class SnapshotHandler : Handler internal class SnapshotHandler : Handler
{ {
private RagonClient _client; private readonly IRagonEntityListener _entityListener;
private RagonListenerList _listenerList; private readonly RagonClient _client;
private RagonEntityCache _entityCache; private readonly RagonListenerList _listenerList;
private RagonPlayerCache _playerCache; private readonly RagonEntityCache _entityCache;
private readonly RagonPlayerCache _playerCache;
public SnapshotHandler( public SnapshotHandler(
RagonClient ragonClient, RagonClient ragonClient,
RagonListenerList listenerList, RagonListenerList listenerList,
RagonEntityCache entityCache, RagonEntityCache entityCache,
RagonPlayerCache playerCache RagonPlayerCache playerCache,
IRagonEntityListener entityListener
) )
{ {
_client = ragonClient; _client = ragonClient;
_entityListener = entityListener;
_listenerList = listenerList; _listenerList = listenerList;
_entityCache = entityCache; _entityCache = entityCache;
_playerCache = playerCache; _playerCache = playerCache;
@@ -51,7 +54,10 @@ internal class SnapshotHandler : Handler
var playerName = buffer.ReadString(); var playerName = buffer.ReadString();
_playerCache.AddPlayer(playerPeerId, playerId, playerName); _playerCache.AddPlayer(playerPeerId, playerId, playerName);
RagonLog.Trace($"Player {playerPeerId} - {playerId} - {playerName}");
} }
var dynamicEntities = buffer.ReadUShort(); var dynamicEntities = buffer.ReadUShort();
RagonLog.Trace("Dynamic Entities: " + dynamicEntities); RagonLog.Trace("Dynamic Entities: " + dynamicEntities);
for (var i = 0; i < dynamicEntities; i++) for (var i = 0; i < dynamicEntities; i++)
@@ -60,16 +66,29 @@ internal class SnapshotHandler : Handler
var entityId = buffer.ReadUShort(); var entityId = buffer.ReadUShort();
var ownerPeerId = buffer.ReadUShort(); var ownerPeerId = buffer.ReadUShort();
var payloadSize = buffer.ReadUShort(); var payloadSize = buffer.ReadUShort();
var player = _playerCache.GetPlayerByPeer(ownerPeerId);
var payload = new RagonPayload(payloadSize); var player = _playerCache.GetPlayerByPeer(ownerPeerId);
payload.Read(buffer); if (player == null)
{
RagonLog.Error($"Player not found with peerId: ${ownerPeerId}");
return;
}
var hasAuthority = _playerCache.Local.Id == player.Id; 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 _);
if (payloadSize > 0)
{
var payload = new RagonPayload(payloadSize);
payload.Read(buffer);
entity.AttachPayload(payload);
}
_entityListener.OnEntityCreated(entity);
entity.Read(buffer); entity.Read(buffer);
entity.Attach(_client, entityId, entityType, hasAuthority, player, payload); entity.Attach(_client, entityId, entityType, hasAuthority, player);
} }
var staticEntities = buffer.ReadUShort(); var staticEntities = buffer.ReadUShort();
@@ -81,18 +100,30 @@ internal class SnapshotHandler : Handler
var staticId = buffer.ReadUShort(); var staticId = buffer.ReadUShort();
var ownerPeerId = buffer.ReadUShort(); var ownerPeerId = buffer.ReadUShort();
var payloadSize = buffer.ReadUShort(); var payloadSize = buffer.ReadUShort();
var player = _playerCache.GetPlayerByPeer(ownerPeerId); var player = _playerCache.GetPlayerByPeer(ownerPeerId);
if (player == null)
var payload = new RagonPayload(payloadSize); {
payload.Read(buffer); RagonLog.Error($"Player not found with peerId: ${ownerPeerId}");
return;
}
var hasAuthority = _playerCache.Local.Id == player.Id; 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 _);
_entityListener.OnEntityCreated(entity);
entity.Read(buffer); entity.Read(buffer);
entity.Attach(_client, entityId, entityType, hasAuthority, player, payload); entity.Attach(_client, entityId, entityType, hasAuthority, player);
} }
_listenerList.OnJoined(); if (_client.Status == RagonStatus.LOBBY)
{
_client.SetStatus(RagonStatus.ROOM);
_listenerList.OnJoined();
}
_listenerList.OnSceneLoaded();
} }
} }
@@ -22,10 +22,11 @@ namespace Ragon.Client
IRagonFailedListener, IRagonFailedListener,
IRagonJoinListener, IRagonJoinListener,
IRagonLeftListener, IRagonLeftListener,
IRagonLevelListener, IRagonSceneListener,
IRagonOwnershipChangedListener, IRagonOwnershipChangedListener,
IRagonPlayerJoinListener, IRagonPlayerJoinListener,
IRagonPlayerLeftListener IRagonPlayerLeftListener
{ {
} }
} }
@@ -16,7 +16,7 @@
namespace Ragon.Client; namespace Ragon.Client;
public interface IRagonLevelListener public interface IRagonSceneListener
{ {
void OnLevel(RagonClient client, string sceneName); void OnSceneLoaded(RagonClient client);
} }
@@ -0,0 +1,6 @@
namespace Ragon.Client;
public interface IRagonSceneRequestListener
{
void OnRequestScene(RagonClient client, string sceneName);
}
+76 -52
View File
@@ -21,19 +21,19 @@ namespace Ragon.Client
public sealed class RagonClient public sealed class RagonClient
{ {
private readonly INetworkConnection _connection; private readonly INetworkConnection _connection;
private readonly IRagonEntityListener _entityListener; private readonly NetworkStatistics _stats;
private readonly IRagonSceneCollector _sceneCollector; private IRagonEntityListener _entityListener;
private IRagonSceneCollector _sceneCollector;
private Handler[] _handlers; private Handler[] _handlers;
private RagonBuffer _readBuffer; private RagonBuffer _readBuffer;
private RagonBuffer _writeBuffer; private RagonBuffer _writeBuffer;
private RagonRoom _room; private RagonRoom _room;
private RagonSession _session; private RagonSession _session;
private RagonListenerList _listenerList; private RagonListenerList listeners;
private RagonPlayerCache _playerCache; private RagonPlayerCache _playerCache;
private RagonEntityCache _entityCache; private RagonEntityCache _entityCache;
private RagonEventCache _eventCache; private RagonEventCache _eventCache;
private RagonStatus _status; private RagonStatus _status;
private NetworkStatistics _stats;
private float _replicationRate = 0; private float _replicationRate = 0;
private float _replicationTime = 0; private float _replicationTime = 0;
@@ -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;
listeners = new RagonListenerList(this);
_replicationRate = (1000.0f / rate) / 1000.0f; _replicationRate = (1000.0f / rate) / 1000.0f;
_replicationTime = 0; _replicationTime = 0;
@@ -74,32 +68,55 @@ 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);
_playerCache = new RagonPlayerCache(); _playerCache = new RagonPlayerCache();
_entityCache = new RagonEntityCache(this, _playerCache, _entityListener, _sceneCollector); _entityCache = new RagonEntityCache(this, _playerCache, _sceneCollector);
_handlers = new Handler[byte.MaxValue]; _handlers = new Handler[byte.MaxValue];
_handlers[(byte)RagonOperation.AUTHORIZED_SUCCESS] = new AuthorizeSuccessHandler(_listenerList); _handlers[(byte)RagonOperation.AUTHORIZED_SUCCESS] = new AuthorizeSuccessHandler(this, listeners);
_handlers[(byte)RagonOperation.AUTHORIZED_FAILED] = new AuthorizeFailedHandler(_listenerList); _handlers[(byte)RagonOperation.AUTHORIZED_FAILED] = new AuthorizeFailedHandler(listeners);
_handlers[(byte)RagonOperation.JOIN_SUCCESS] = new JoinSuccessHandler(this, _readBuffer, _listenerList, _playerCache, _entityCache); _handlers[(byte)RagonOperation.JOIN_SUCCESS] = new JoinSuccessHandler(this, _readBuffer, listeners, _playerCache, _entityCache);
_handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(_listenerList); _handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(listeners);
_handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, _listenerList, _entityCache); _handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, listeners, _entityCache);
_handlers[(byte)RagonOperation.OWNERSHIP_ROOM_CHANGED] = new OwnershipRoomHandler(_listenerList, _playerCache, _entityCache); _handlers[(byte)RagonOperation.OWNERSHIP_ROOM_CHANGED] = new OwnershipRoomHandler(listeners, _playerCache, _entityCache);
_handlers[(byte)RagonOperation.OWNERSHIP_ENTITY_CHANGED] = new EntityOwnershipHandler(_listenerList, _playerCache, _entityCache); _handlers[(byte)RagonOperation.OWNERSHIP_ENTITY_CHANGED] = new EntityOwnershipHandler(listeners, _playerCache, _entityCache);
_handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_playerCache, _listenerList); _handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_playerCache, listeners);
_handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_entityCache, _playerCache, _listenerList); _handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_entityCache, _playerCache, listeners);
_handlers[(byte)RagonOperation.LOAD_SCENE] = new SceneLoadHandler(this, _listenerList); _handlers[(byte)RagonOperation.LOAD_SCENE] = new SceneLoadHandler(this, listeners);
_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.REMOVE_ENTITY] = new EntityRemoveHandler(_entityCache);
_handlers[(byte)RagonOperation.REPLICATE_ENTITY_STATE] = new StateEntityHandler(_entityCache); _handlers[(byte)RagonOperation.REPLICATE_ENTITY_STATE] = new StateEntityHandler(_entityCache);
_handlers[(byte)RagonOperation.REPLICATE_ENTITY_EVENT] = new EntityEventHandler(this, _playerCache, _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, listeners, _entityCache, _playerCache, _entityListener);
var protocolRaw = RagonVersion.Parse(protocol); var protocolRaw = RagonVersion.Parse(protocol);
_connection.Connect(address, port, protocolRaw); _connection.Connect(address, port, protocolRaw);
@@ -110,7 +127,7 @@ namespace Ragon.Client
_status = RagonStatus.DISCONNECTED; _status = RagonStatus.DISCONNECTED;
_room.Cleanup(); _room.Cleanup();
_connection.Disconnect(); _connection.Disconnect();
OnDisconnected(RagonDisconnect.MANUAL); OnDisconnected(RagonDisconnect.MANUAL);
} }
@@ -128,6 +145,7 @@ namespace Ragon.Client
_stats.Update(_connection.BytesSent, _connection.BytesReceived, _connection.Ping, dt); _stats.Update(_connection.BytesSent, _connection.BytesReceived, _connection.Ping, dt);
} }
listeners.Update();
_connection.Update(); _connection.Update();
} }
@@ -138,28 +156,30 @@ namespace Ragon.Client
_connection.Dispose(); _connection.Dispose();
} }
public void AddListener(IRagonListener listener) => _listenerList.Add(listener); public void AddListener(IRagonListener listener) => listeners.Add(listener);
public void AddListener(IRagonAuthorizationListener listener) => _listenerList.Add(listener); public void AddListener(IRagonAuthorizationListener listener) => listeners.Add(listener);
public void AddListener(IRagonConnectionListener listener) => _listenerList.Add(listener); public void AddListener(IRagonConnectionListener listener) => listeners.Add(listener);
public void AddListener(IRagonFailedListener listener) => _listenerList.Add(listener); public void AddListener(IRagonFailedListener listener) => listeners.Add(listener);
public void AddListener(IRagonJoinListener listener) => _listenerList.Add(listener); public void AddListener(IRagonJoinListener listener) => listeners.Add(listener);
public void AddListener(IRagonLeftListener listener) => _listenerList.Add(listener); public void AddListener(IRagonLeftListener listener) => listeners.Add(listener);
public void AddListener(IRagonLevelListener listener) => _listenerList.Add(listener); public void AddListener(IRagonOwnershipChangedListener listener) => listeners.Add(listener);
public void AddListener(IRagonOwnershipChangedListener listener) => _listenerList.Add(listener); public void AddListener(IRagonPlayerJoinListener listener) => listeners.Add(listener);
public void AddListener(IRagonPlayerJoinListener listener) => _listenerList.Add(listener); public void AddListener(IRagonPlayerLeftListener listener) => listeners.Add(listener);
public void AddListener(IRagonPlayerLeftListener listener) => _listenerList.Add(listener); public void AddListener(IRagonSceneListener listener) => listeners.Add(listener);
public void AddListener(IRagonSceneRequestListener listener) => listeners.Add(listener);
public void RemoveListener(IRagonListener listener) => listeners.Remove(listener);
public void RemoveListener(IRagonAuthorizationListener listener) => listeners.Remove(listener);
public void RemoveListener(IRagonConnectionListener listener) => listeners.Remove(listener);
public void RemoveListener(IRagonFailedListener listener) => listeners.Remove(listener);
public void RemoveListener(IRagonJoinListener listener) => listeners.Remove(listener);
public void RemoveListener(IRagonLeftListener listener) => listeners.Remove(listener);
public void RemoveListener(IRagonOwnershipChangedListener listener) => listeners.Remove(listener);
public void RemoveListener(IRagonPlayerJoinListener listener) => listeners.Remove(listener);
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(IRagonListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonAuthorizationListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonConnectionListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonFailedListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonJoinListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonLeftListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonLevelListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonOwnershipChangedListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonPlayerJoinListener listener) => _listenerList.Remove(listener);
public void RemoveListener(IRagonPlayerLeftListener listener) => _listenerList.Remove(listener);
#endregion #endregion
#region INTERNAL #region INTERNAL
@@ -167,7 +187,11 @@ namespace Ragon.Client
internal void AssignRoom(RagonRoom room) internal void AssignRoom(RagonRoom room)
{ {
_room = room; _room = room;
_status = RagonStatus.ROOM; }
internal void SetStatus(RagonStatus status)
{
_status = status;
} }
#endregion #endregion
@@ -178,7 +202,7 @@ namespace Ragon.Client
{ {
RagonLog.Trace("Connected"); RagonLog.Trace("Connected");
_listenerList.OnConnected(); listeners.OnConnected();
_status = RagonStatus.CONNECTED; _status = RagonStatus.CONNECTED;
} }
@@ -186,7 +210,7 @@ namespace Ragon.Client
{ {
RagonLog.Trace($"Disconnected: {reason}"); RagonLog.Trace($"Disconnected: {reason}");
_listenerList.OnDisconnected(reason); listeners.OnDisconnected(reason);
_status = RagonStatus.DISCONNECTED; _status = RagonStatus.DISCONNECTED;
} }
+37 -35
View File
@@ -26,7 +26,6 @@ public sealed class RagonEntityCache
private readonly Dictionary<uint, RagonEntity> _sceneEntities = new(); private readonly Dictionary<uint, RagonEntity> _sceneEntities = new();
private readonly RagonClient _client; private readonly RagonClient _client;
private readonly IRagonEntityListener _entityListener;
private readonly IRagonSceneCollector _sceneCollector; private readonly IRagonSceneCollector _sceneCollector;
private readonly RagonPlayerCache _playerCache; private readonly RagonPlayerCache _playerCache;
@@ -35,22 +34,20 @@ public sealed class RagonEntityCache
public RagonEntityCache( public RagonEntityCache(
RagonClient client, RagonClient client,
RagonPlayerCache playerCache, RagonPlayerCache playerCache,
IRagonEntityListener listener,
IRagonSceneCollector sceneCollector IRagonSceneCollector sceneCollector
) )
{ {
_client = client; _client = client;
_entityListener = listener;
_sceneCollector = sceneCollector; _sceneCollector = sceneCollector;
_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, RagonPayload spawnPayload)
{ {
var attachId = (ushort)(_playerCache.Local.PeerId + _localEntitiesCounter++); var attachId = (ushort)(_playerCache.Local.PeerId + _localEntitiesCounter++);
var buffer = _client.Buffer; var buffer = _client.Buffer;
@@ -63,7 +60,7 @@ public sealed class RagonEntityCache
entity.State.WriteInfo(buffer); entity.State.WriteInfo(buffer);
spawnPayload?.Serialize(buffer); spawnPayload?.Write(buffer);
_pendingEntities.Add(attachId, entity); _pendingEntities.Add(attachId, entity);
@@ -84,7 +81,7 @@ public sealed class RagonEntityCache
_client.Reliable.Send(sendData); _client.Reliable.Send(sendData);
} }
public void Destroy(RagonEntity entity, IRagonPayload? destroyPayload) public void Destroy(RagonEntity entity, RagonPayload destroyPayload)
{ {
if (!entity.IsAttached) if (!entity.IsAttached)
{ {
@@ -98,7 +95,7 @@ public sealed class RagonEntityCache
buffer.WriteOperation(RagonOperation.REMOVE_ENTITY); buffer.WriteOperation(RagonOperation.REMOVE_ENTITY);
buffer.WriteUShort(entity.Id); buffer.WriteUShort(entity.Id);
destroyPayload?.Serialize(buffer); destroyPayload?.Write(buffer);
var sendData = buffer.ToArray(); var sendData = buffer.ToArray();
_client.Reliable.Send(sendData); _client.Reliable.Send(sendData);
@@ -162,61 +159,66 @@ public sealed class RagonEntityCache
internal void Cleanup() internal void Cleanup()
{ {
var payload = new RagonPayload(); var payload = new RagonPayload(0);
foreach (var ent in _entityList) foreach (var ent in _entityList)
ent.Detach(payload); ent.Detach(payload);
_entityMap.Clear(); _entityMap.Clear();
_entityList.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 (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) if (hasAuthority)
_entityList.Add(entity); _entityList.Add(sceneEntity);
return entity; 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) 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) var entity = new RagonEntity(entityType, sceneId);
_entityList.Add(entity);
_entityMap.Add(entityId, entity);
if (hasAuthority)
_entityList.Add(entity);
_entityListener.OnEntityCreated(entity); hasCreated = true;
return entity; return entity;
}
} }
internal void OnDestroy(ushort entityId, RagonPayload payload) 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); _entityList.Add(entity);
else else
_entityList.Remove(entity); _entityList.Remove(entity);
entity.OnOwnershipChanged(player); entity.OnOwnershipChanged(player);
} }
else else
+57 -26
View File
@@ -26,10 +26,12 @@ namespace Ragon.Client
private readonly List<IRagonFailedListener> _failedListeners = new(); private readonly List<IRagonFailedListener> _failedListeners = new();
private readonly List<IRagonJoinListener> _joinListeners = new(); private readonly List<IRagonJoinListener> _joinListeners = new();
private readonly List<IRagonLeftListener> _leftListeners = new(); private readonly List<IRagonLeftListener> _leftListeners = new();
private readonly List<IRagonLevelListener> _levelListeners = new(); private readonly List<IRagonSceneListener> _sceneListeners = new();
private readonly List<IRagonSceneRequestListener> _sceneRequestListeners = new();
private readonly List<IRagonOwnershipChangedListener> _ownershipChangedListeners = new(); private readonly List<IRagonOwnershipChangedListener> _ownershipChangedListeners = new();
private readonly List<IRagonPlayerJoinListener> _playerJoinListeners = new(); private readonly List<IRagonPlayerJoinListener> _playerJoinListeners = new();
private readonly List<IRagonPlayerLeftListener> _playerLeftListeners = new(); private readonly List<IRagonPlayerLeftListener> _playerLeftListeners = new();
private readonly List<Action> _delayedActions = new();
public RagonListenerList(RagonClient client) public RagonListenerList(RagonClient client)
{ {
@@ -43,7 +45,7 @@ namespace Ragon.Client
_failedListeners.Add(listener); _failedListeners.Add(listener);
_joinListeners.Add(listener); _joinListeners.Add(listener);
_leftListeners.Add(listener); _leftListeners.Add(listener);
_levelListeners.Add(listener); _sceneListeners.Add(listener);
_ownershipChangedListeners.Add(listener); _ownershipChangedListeners.Add(listener);
_playerJoinListeners.Add(listener); _playerJoinListeners.Add(listener);
_playerLeftListeners.Add(listener); _playerLeftListeners.Add(listener);
@@ -51,22 +53,39 @@ namespace Ragon.Client
public void Remove(IRagonListener listener) public void Remove(IRagonListener listener)
{ {
_authorizationListeners.Remove(listener); _delayedActions.Add(() =>
_connectionListeners.Remove(listener); {
_failedListeners.Remove(listener); _authorizationListeners.Remove(listener);
_joinListeners.Remove(listener); _connectionListeners.Remove(listener);
_leftListeners.Remove(listener); _failedListeners.Remove(listener);
_levelListeners.Remove(listener); _joinListeners.Remove(listener);
_ownershipChangedListeners.Remove(listener); _leftListeners.Remove(listener);
_playerJoinListeners.Remove(listener); _sceneListeners.Remove(listener);
_playerLeftListeners.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) public void Add(IRagonAuthorizationListener listener)
{ {
_authorizationListeners.Add(listener); _authorizationListeners.Add(listener);
} }
public void Add(IRagonSceneRequestListener listener)
{
_sceneRequestListeners.Add(listener);
}
public void Add(IRagonConnectionListener listener) public void Add(IRagonConnectionListener listener)
{ {
_connectionListeners.Add(listener); _connectionListeners.Add(listener);
@@ -87,9 +106,9 @@ namespace Ragon.Client
_leftListeners.Add(listener); _leftListeners.Add(listener);
} }
public void Add(IRagonLevelListener listener) public void Add(IRagonSceneListener listener)
{ {
_levelListeners.Add(listener); _sceneListeners.Add(listener);
} }
public void Add(IRagonOwnershipChangedListener listener) public void Add(IRagonOwnershipChangedListener listener)
@@ -107,49 +126,55 @@ namespace Ragon.Client
_playerLeftListeners.Add(listener); _playerLeftListeners.Add(listener);
} }
public void Remove(IRagonSceneRequestListener listener)
{
_delayedActions.Add(() => _sceneRequestListeners.Remove(listener));
}
public void Remove(IRagonAuthorizationListener listener) public void Remove(IRagonAuthorizationListener listener)
{ {
_authorizationListeners.Remove(listener); _delayedActions.Add(() => _authorizationListeners.Remove(listener));
} }
public void Remove(IRagonConnectionListener listener) public void Remove(IRagonConnectionListener listener)
{ {
_connectionListeners.Remove(listener);
_delayedActions.Add(() => _connectionListeners.Remove(listener));
} }
public void Remove(IRagonFailedListener listener) public void Remove(IRagonFailedListener listener)
{ {
_failedListeners.Remove(listener); _delayedActions.Add(() => _failedListeners.Remove(listener));
} }
public void Remove(IRagonJoinListener listener) public void Remove(IRagonJoinListener listener)
{ {
_joinListeners.Remove(listener); _delayedActions.Add(() => _joinListeners.Remove(listener));
} }
public void Remove(IRagonLeftListener listener) public void Remove(IRagonLeftListener listener)
{ {
_leftListeners.Remove(listener); _delayedActions.Add(() => _leftListeners.Remove(listener));
} }
public void Remove(IRagonLevelListener listener) public void Remove(IRagonSceneListener listener)
{ {
_levelListeners.Remove(listener); _delayedActions.Add(() => _sceneListeners.Remove(listener));
} }
public void Remove(IRagonOwnershipChangedListener listener) public void Remove(IRagonOwnershipChangedListener listener)
{ {
_ownershipChangedListeners.Remove(listener); _delayedActions.Add(() => _ownershipChangedListeners.Remove(listener));
} }
public void Remove(IRagonPlayerJoinListener listener) public void Remove(IRagonPlayerJoinListener listener)
{ {
_playerJoinListeners.Remove(listener); _delayedActions.Add(() => _playerJoinListeners.Remove(listener));
} }
public void Remove(IRagonPlayerLeftListener listener) public void Remove(IRagonPlayerLeftListener listener)
{ {
_playerLeftListeners.Remove(listener); _delayedActions.Add(() => _playerLeftListeners.Remove(listener));
} }
public void OnAuthorizationSuccess(string playerId, string playerName, string payload) public void OnAuthorizationSuccess(string playerId, string playerName, string payload)
@@ -194,10 +219,16 @@ namespace Ragon.Client
listener.OnPlayerJoined(_client, player); listener.OnPlayerJoined(_client, player);
} }
public void OnLevel(string sceneName) public void OnSceneLoaded()
{ {
foreach (var listener in _levelListeners) foreach (var listener in _sceneListeners)
listener.OnLevel(_client, sceneName); listener.OnSceneLoaded(_client);
}
public void OnSceneRequest(string sceneName)
{
foreach (var listener in _sceneRequestListeners)
listener.OnRequestScene(_client, sceneName);
} }
public void OnJoined() public void OnJoined()
+2 -1
View File
@@ -64,9 +64,10 @@ public sealed class RagonPlayerCache
public void RemovePlayer(string playerId) public void RemovePlayer(string playerId)
{ {
if (_playersById.Remove(playerId, out var player)) if (_playersById.TryGetValue(playerId, out var player))
{ {
_players.Remove(player); _players.Remove(player);
_playersById.Remove(playerId);
_playersByConnection.Remove(player.PeerId); _playersByConnection.Remove(player.PeerId);
} }
} }
+9 -3
View File
@@ -27,6 +27,7 @@ namespace Ragon.Client
public string Id => _information.RoomId; public string Id => _information.RoomId;
public int MinPlayers => _information.Min; public int MinPlayers => _information.Min;
public int MaxPlayers => _information.Max; public int MaxPlayers => _information.Max;
public string Scene => _scene.Name;
public IReadOnlyList<RagonPlayer> Players => _playerCache.Players; public IReadOnlyList<RagonPlayer> Players => _playerCache.Players;
public RagonPlayer Local => _playerCache.Local; public RagonPlayer Local => _playerCache.Local;
@@ -51,14 +52,19 @@ namespace Ragon.Client
_playerCache.Cleanup(); _playerCache.Cleanup();
} }
public void LoadScene(string map) => _scene.Load(map); internal void Update(string sceneName)
{
_scene.Update(sceneName);
}
public void LoadScene(string sceneName) => _scene.Load(sceneName);
public void SceneLoaded() => _scene.SceneLoaded(); public void SceneLoaded() => _scene.SceneLoaded();
public void CreateEntity(RagonEntity entity) => CreateEntity(entity, null); 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 TransferEntity(RagonEntity entity, RagonPlayer player) => _entityCache.Transfer(entity, player);
public void DestroyEntity(RagonEntity entityId) => DestroyEntity(entityId, null); 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);
} }
} }
+12 -3
View File
@@ -20,24 +20,33 @@ namespace Ragon.Client;
public class RagonScene public class RagonScene
{ {
public string Name { get; private set; }
private readonly RagonClient _client; private readonly RagonClient _client;
private readonly RagonEntityCache _entityCache; private readonly RagonEntityCache _entityCache;
private readonly RagonPlayerCache _playerCache; private readonly RagonPlayerCache _playerCache;
public RagonScene(RagonClient client, RagonPlayerCache playerCache, RagonEntityCache entityCache) public RagonScene(RagonClient client, RagonPlayerCache playerCache, RagonEntityCache entityCache, string sceneName)
{ {
Name = sceneName;
_client = client; _client = client;
_playerCache = playerCache; _playerCache = playerCache;
_entityCache = entityCache; _entityCache = entityCache;
} }
internal void Load(string map) internal void Update(string scene)
{
Name = scene;
}
internal void Load(string sceneName)
{ {
var buffer = _client.Buffer; var buffer = _client.Buffer;
buffer.Clear(); buffer.Clear();
buffer.WriteOperation(RagonOperation.LOAD_SCENE); buffer.WriteOperation(RagonOperation.LOAD_SCENE);
buffer.WriteString(map); buffer.WriteString(sceneName);
var sendData = buffer.ToArray(); var sendData = buffer.ToArray();
_client.Reliable.Send(sendData); _client.Reliable.Send(sendData);
+6 -6
View File
@@ -29,9 +29,9 @@ namespace Ragon.Client
_buffer = buffer; _buffer = buffer;
} }
public void CreateOrJoin(string map, int minPlayers, int maxPlayers) public void CreateOrJoin(string sceneName, int minPlayers, int maxPlayers)
{ {
var parameters = new RagonRoomParameters() {Map = map, Min = minPlayers, Max = maxPlayers}; var parameters = new RagonRoomParameters() {Scene = sceneName, Min = minPlayers, Max = maxPlayers};
CreateOrJoin(parameters); CreateOrJoin(parameters);
} }
@@ -46,14 +46,14 @@ namespace Ragon.Client
_client.Reliable.Send(sendData); _client.Reliable.Send(sendData);
} }
public void Create(string map, int minPlayers, int maxPlayers) public void Create(string sceneName, int minPlayers, int maxPlayers)
{ {
Create(null, new RagonRoomParameters() {Map = map, Min = minPlayers, Max = maxPlayers}); Create(null, new RagonRoomParameters() {Scene = sceneName, Min = minPlayers, Max = maxPlayers});
} }
public void Create(string roomId, string map, int minPlayers, int maxPlayers) public void Create(string roomId, string sceneNa, int minPlayers, int maxPlayers)
{ {
Create(roomId, new RagonRoomParameters() {Map = map, Min = minPlayers, Max = maxPlayers}); Create(roomId, new RagonRoomParameters() {Scene = sceneNa, Min = minPlayers, Max = maxPlayers});
} }
public void Create(string roomId, RagonRoomParameters parameters) public void Create(string roomId, RagonRoomParameters parameters)
+11 -3
View File
@@ -4,8 +4,16 @@
<ImplicitUsings>disable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable> <Nullable>disable</Nullable>
<LangVersion>8</LangVersion> <LangVersion>8</LangVersion>
<TargetFramework>netstandard2.1</TargetFramework>
<RootNamespace>Ragon.Common</RootNamespace> <RootNamespace>Ragon.Common</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.2.4-rc</Version>
<Title>Ragon.Protocol</Title>
<Copyright>Eduard Kargin</Copyright>
<PackageProjectUrl>https://ragon-server.com</PackageProjectUrl>
<RepositoryUrl>https://github.com/edmand46/Ragon</RepositoryUrl>
<RepositoryType>Source</RepositoryType>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
@@ -16,8 +24,8 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>C:\Users\edmand46\RagonProjects\ragon-unity-sdk\Assets\Ragon-Unity-SDK\Runtime\Plugins</OutputPath> <OutputPath></OutputPath>
<DefineConstants>TRACE;NETSTACK_SPAN</DefineConstants> <DefineConstants>TRACE;</DefineConstants>
<DebugType>none</DebugType> <DebugType>none</DebugType>
</PropertyGroup> </PropertyGroup>
</Project> </Project>
+18 -20
View File
@@ -58,7 +58,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
@@ -245,7 +244,7 @@ namespace Ragon.Protocol
if (currentBucketIndex + 1 >= _buckets.Length) if (currentBucketIndex + 1 >= _buckets.Length)
Resize(1); Resize(1);
_buckets[currentBucketIndex] = (uint)result; _buckets[currentBucketIndex] = (uint)result;
_buckets[currentBucketIndex + 1] = (uint)(result >> 32); _buckets[currentBucketIndex + 1] = (uint)(result >> 32);
@@ -292,13 +291,13 @@ namespace Ragon.Protocol
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ReadSpan(ref Span<uint> data, int size) public void ReadArray(uint[] data, int size)
{ {
var used = _read & 0x0000001F; var used = _read & 0x0000001F;
var index = _read >> 5; var index = _read >> 5;
var limit = (size + 32 - 1) / 32; var limit = (size + 32 - 1) / 32;
var capacity = size; var capacity = size;
for (int i = 0; i < limit; i++) for (int i = 0; i < limit; i++)
{ {
var dataSize = capacity > 32 ? 32 : capacity; var dataSize = capacity > 32 ? 32 : capacity;
@@ -306,23 +305,24 @@ namespace Ragon.Protocol
var bucketRaw = (ulong)_buckets[index]; var bucketRaw = (ulong)_buckets[index];
if (index + 1 < _buckets.Length) if (index + 1 < _buckets.Length)
bucketRaw |= (ulong)_buckets[index + 1] << 32; bucketRaw |= (ulong)_buckets[index + 1] << 32;
var bucket = bucketRaw >> used; var bucket = bucketRaw >> used;
var result = bucket & mask; var result = bucket & mask;
data[i] = (uint)result; data[i] = (uint)result;
if (i + 1 < data.Length) if (i + 1 < data.Length)
data[i + 1] = (uint)(result >> 32); data[i + 1] = (uint)(result >> 32);
index += 1; index += 1;
capacity -= dataSize; capacity -= dataSize;
} }
_read += size; _read += size;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteSpan(ref ReadOnlySpan<uint> data, int size) public void WriteArray(uint[] data, int size)
{ {
var used = _write & 0x0000001F; var used = _write & 0x0000001F;
var index = _write >> 5; var index = _write >> 5;
@@ -330,20 +330,20 @@ namespace Ragon.Protocol
if (index + limit >= _buckets.Length) if (index + limit >= _buckets.Length)
Resize(size); Resize(size);
for (var i = 0; i < limit; i += 1) 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 mask = (1UL << used) - 1;
var scratch = _buckets[index] & mask; var scratch = _buckets[index] & mask;
var result = scratch | prepared; var result = scratch | prepared;
_buckets[index] = (uint)result; _buckets[index] = (uint)result;
_buckets[index + 1] = (uint)(result >> 32); _buckets[index + 1] = (uint)(result >> 32);
index += 1; index += 1;
} }
_write += size; _write += size;
} }
@@ -356,17 +356,15 @@ namespace Ragon.Protocol
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBuffer(RagonBuffer buffer, int size) public void FromBuffer(RagonBuffer buffer, int size)
{ {
ReadOnlySpan<uint> data = buffer._buckets.AsSpan(); WriteArray(buffer._buckets, size);
WriteSpan(ref data, size);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBuffer(RagonBuffer buffer, int size) public void ToBuffer(RagonBuffer buffer, int size)
{ {
var data = buffer._buckets.AsSpan(); ReadArray(buffer._buckets, size);
ReadSpan(ref data, size);
} }
public void FromArray(byte[] data) public void FromArray(byte[] data)
{ {
var length = data.Length; var length = data.Length;
@@ -19,20 +19,20 @@ namespace Ragon.Protocol
{ {
public class RagonRoomParameters: IRagonSerializable public class RagonRoomParameters: IRagonSerializable
{ {
public string Map { get; set; } public string Scene { get; set; }
public int Min { get; set; } public int Min { get; set; }
public int Max { get; set; } public int Max { get; set; }
public void Serialize(RagonBuffer buffer) public void Serialize(RagonBuffer buffer)
{ {
buffer.WriteString(Map); buffer.WriteString(Scene);
buffer.WriteInt(Min, 1, 32); buffer.WriteInt(Min, 1, 32);
buffer.WriteInt(Max, 1, 32); buffer.WriteInt(Max, 1, 32);
} }
public void Deserialize(RagonBuffer buffer) public void Deserialize(RagonBuffer buffer)
{ {
Map = buffer.ReadString(); Scene = buffer.ReadString();
Min = buffer.ReadInt(1, 32); Min = buffer.ReadInt(1, 32);
Max = buffer.ReadInt(1, 32); Max = buffer.ReadInt(1, 32);
} }
+1 -1
View File
@@ -21,7 +21,7 @@ namespace Ragon.Protocol
{ {
public static uint Parse(string version) public static uint Parse(string version)
{ {
var strings = version.Split("."); var strings = version.Split('.');
if (strings.Length < 3) if (strings.Length < 3)
return 0; return 0;
+2 -2
View File
@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Ragon.ENet</RootNamespace> <RootNamespace>Ragon.ENet</RootNamespace>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ENet-CSharp" Version="2.4.8" /> <PackageReference Include="ENet-CSharp" Version="2.4.8" />
<PackageReference Include="NLog" Version="5.1.1" /> <PackageReference Include="NLog" Version="5.2.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Ragon.WebSockets</RootNamespace> <RootNamespace>Ragon.WebSockets</RootNamespace>
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NLog" Version="5.1.1" /> <PackageReference Include="NLog" Version="5.2.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+13 -4
View File
@@ -1,19 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Ragon.Core</RootNamespace> <RootNamespace>Ragon.Core</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.2.4-rc</Version>
<Title>Ragon.Server</Title>
<Copyright>Eduard Kargin</Copyright>
<PackageProjectUrl>https://ragon-server.com</PackageProjectUrl>
<RepositoryUrl>https://github.com/edmand46/Ragon</RepositoryUrl>
<RepositoryType>Source</RepositoryType>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<LangVersion>10</LangVersion>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2-beta2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.1.1" /> <PackageReference Include="NLog" Version="5.2.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ragon.Protocol\Ragon.Protocol.csproj" /> <ProjectReference Include="..\Ragon.Protocol\Ragon.Protocol.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+4 -2
View File
@@ -117,13 +117,15 @@ public class RagonEntity : IRagonEntity
{ {
buffer.WriteUShort(Type); buffer.WriteUShort(Type);
buffer.WriteUShort(Id); buffer.WriteUShort(Id);
if (StaticId != 0) if (StaticId != 0)
buffer.WriteUShort(StaticId); buffer.WriteUShort(StaticId);
buffer.WriteUShort(Owner.Connection.Id); buffer.WriteUShort(Owner.Connection.Id);
buffer.WriteUShort(Payload.Size); buffer.WriteUShort(Payload.Size);
Payload.Write(buffer); Payload.Write(buffer);
_state.Snapshot(buffer); _state.Snapshot(buffer);
} }
@@ -21,14 +21,12 @@ namespace Ragon.Server.Entity;
public class RagonEntityState: IRagonEntityState public class RagonEntityState: IRagonEntityState
{ {
private List<RagonProperty> _properties; private readonly List<RagonProperty> _properties;
private RagonEntity _entity; private readonly RagonEntity _entity;
private RagonBuffer _buffer;
public RagonEntityState(RagonEntity entity, int capacity = 10) public RagonEntityState(RagonEntity entity, int capacity = 10)
{ {
_entity = entity; _entity = entity;
_buffer = new RagonBuffer(8);
_properties = new List<RagonProperty>(capacity); _properties = new List<RagonProperty>(capacity);
} }
@@ -67,8 +65,7 @@ public class RagonEntityState: IRagonEntityState
{ {
foreach (var property in _properties) foreach (var property in _properties)
{ {
var hasPayloadOrFixed = property.IsFixed || property is { IsFixed: false, Size: > 0 }; if (property.HasData)
if (hasPayloadOrFixed)
{ {
buffer.WriteBool(true); buffer.WriteBool(true);
property.Write(buffer); property.Write(buffer);
+2 -5
View File
@@ -39,15 +39,12 @@ public class RagonEvent
public void Read(RagonBuffer buffer) public void Read(RagonBuffer buffer)
{ {
var readOnlySpan = _data.AsSpan(); buffer.ReadArray(_data, buffer.Capacity);
_size = buffer.Capacity;
buffer.ReadSpan(ref readOnlySpan, _size);
} }
public void Write(RagonBuffer buffer) public void Write(RagonBuffer buffer)
{ {
if (_size == 0) return; if (_size == 0) return;
ReadOnlySpan<uint> readOnlySpan = _data.AsSpan(); buffer.WriteArray(_data, _size);
buffer.WriteSpan(ref readOnlySpan, _size);
} }
} }
+2 -8
View File
@@ -28,19 +28,13 @@ public class RagonPayload
public void Read(RagonBuffer buffer) public void Read(RagonBuffer buffer)
{ {
var readOnlySpan = _data.AsSpan();
_size = buffer.Capacity; _size = buffer.Capacity;
buffer.ReadArray(_data, _size);
buffer.ReadSpan(ref readOnlySpan, _size);
} }
public void Write(RagonBuffer buffer) public void Write(RagonBuffer buffer)
{ {
if (_size == 0) return; if (_size == 0) return;
buffer.WriteArray(_data, _size);
ReadOnlySpan<uint> readOnlySpan = _data.AsSpan();
buffer.WriteSpan(ref readOnlySpan, _size);
} }
} }
+5 -5
View File
@@ -23,6 +23,7 @@ public class RagonProperty : RagonPayload
public int Size { get; set; } public int Size { get; set; }
public bool IsDirty { get; private set; } public bool IsDirty { get; private set; }
public bool IsFixed { get; private set; } public bool IsFixed { get; private set; }
public bool HasData { get; private set; }
private uint[] _data; private uint[] _data;
@@ -37,24 +38,23 @@ public class RagonProperty : RagonPayload
public void Read(RagonBuffer buffer) public void Read(RagonBuffer buffer)
{ {
var readOnlySpan = _data.AsSpan();
if (IsFixed) if (IsFixed)
{ {
buffer.ReadSpan(ref readOnlySpan, Size); buffer.ReadArray(_data, Size);
} }
else else
{ {
Size = (int) buffer.Read(); Size = (int) buffer.Read();
buffer.ReadSpan(ref readOnlySpan, Size); buffer.ReadArray(_data, Size);
} }
HasData = true;
IsDirty = true; IsDirty = true;
} }
public void Write(RagonBuffer buffer) public void Write(RagonBuffer buffer)
{ {
ReadOnlySpan<uint> readOnlySpan = _data.AsSpan(); buffer.WriteArray(_data, Size);
buffer.WriteSpan(ref readOnlySpan, Size);
} }
public void Clear() public void Clear()
@@ -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);
} }
} }
@@ -68,7 +68,7 @@ public sealed class RoomCreateOperation: IRagonOperation
var information = new RoomInformation() var information = new RoomInformation()
{ {
Map = _roomParameters.Map, Scene = _roomParameters.Scene,
Max = _roomParameters.Max, Max = _roomParameters.Max,
Min = _roomParameters.Min, Min = _roomParameters.Min,
}; };
@@ -87,7 +87,7 @@ public sealed class RoomCreateOperation: IRagonOperation
_ragonWebHookPlugin.RoomCreated(context, room, roomPlayer); _ragonWebHookPlugin.RoomCreated(context, room, roomPlayer);
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} with map {information.Map}"); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} with scene {information.Scene}");
JoinSuccess(roomPlayer, room, writer); JoinSuccess(roomPlayer, room, writer);
@@ -103,7 +103,7 @@ public sealed class RoomCreateOperation: IRagonOperation
writer.WriteString(room.Owner.Id); writer.WriteString(room.Owner.Id);
writer.WriteUShort((ushort) room.PlayerMin); writer.WriteUShort((ushort) room.PlayerMin);
writer.WriteUShort((ushort) room.PlayerMax); writer.WriteUShort((ushort) room.PlayerMax);
writer.WriteString(room.Map); writer.WriteString(room.Scene);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
player.Connection.Reliable.Send(sendData); player.Connection.Reliable.Send(sendData);
@@ -68,7 +68,7 @@ public sealed class RoomJoinOperation : IRagonOperation
writer.WriteString(room.Owner.Id); writer.WriteString(room.Owner.Id);
writer.WriteUShort((ushort) room.PlayerMin); writer.WriteUShort((ushort) room.PlayerMin);
writer.WriteUShort((ushort) room.PlayerMax); writer.WriteUShort((ushort) room.PlayerMax);
writer.WriteString(room.Map); writer.WriteString(room.Scene);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
context.Connection.Reliable.Send(sendData); context.Connection.Reliable.Send(sendData);
@@ -49,7 +49,7 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation
_roomParameters.Deserialize(reader); _roomParameters.Deserialize(reader);
if (context.Lobby.FindRoomByMap(_roomParameters.Map, out var existsRoom)) if (context.Lobby.FindRoomByScene(_roomParameters.Scene, out var existsRoom))
{ {
var player = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name); var player = new RagonRoomPlayer(context.Connection, lobbyPlayer.Id, lobbyPlayer.Name);
context.SetRoom(existsRoom, player); context.SetRoom(existsRoom, player);
@@ -62,7 +62,7 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation
{ {
var information = new RoomInformation() var information = new RoomInformation()
{ {
Map = _roomParameters.Map, Scene = _roomParameters.Scene,
Max = _roomParameters.Max, Max = _roomParameters.Max,
Min = _roomParameters.Min, Min = _roomParameters.Min,
}; };
@@ -77,7 +77,7 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation
context.Scheduler.Run(room); context.Scheduler.Run(room);
context.SetRoom(room, roomPlayer); context.SetRoom(room, roomPlayer);
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} with map {information.Map}"); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} create room {room.Id} with scene {information.Scene}");
JoinSuccess(roomPlayer, room, writer); JoinSuccess(roomPlayer, room, writer);
} }
@@ -92,7 +92,7 @@ public sealed class RoomJoinOrCreateOperation : IRagonOperation
writer.WriteString(room.Owner.Id); writer.WriteString(room.Owner.Id);
writer.WriteUShort((ushort) room.PlayerMin); writer.WriteUShort((ushort) room.PlayerMin);
writer.WriteUShort((ushort) room.PlayerMax); writer.WriteUShort((ushort) room.PlayerMax);
writer.WriteString(room.Map); writer.WriteString(room.Scene);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
player.Connection.Reliable.Send(sendData); player.Connection.Reliable.Send(sendData);
@@ -33,7 +33,7 @@ public class SceneLoadOperation: IRagonOperation
if (roomOwner.Connection.Id != currentPlayer.Connection.Id) if (roomOwner.Connection.Id != currentPlayer.Connection.Id)
{ {
_logger.Warn("Only owner can change map!"); _logger.Warn("Only owner can change scene!");
return; return;
} }
@@ -42,7 +42,6 @@ public sealed class SceneLoadedOperation : IRagonOperation
if (player == owner) if (player == owner)
{ {
var statics = reader.ReadUShort(); var statics = reader.ReadUShort();
for (var staticIndex = 0; staticIndex < statics; staticIndex++) for (var staticIndex = 0; staticIndex < statics; staticIndex++)
{ {
@@ -73,7 +72,7 @@ public sealed class SceneLoadedOperation : IRagonOperation
var playerInfo = $"Player {context.Connection.Id}|{context.LobbyPlayer.Name}"; var playerInfo = $"Player {context.Connection.Id}|{context.LobbyPlayer.Name}";
var entityInfo = $"{entity.Id}:{entity.Type}"; var entityInfo = $"{entity.Id}:{entity.Type}";
_logger.Trace($"{playerInfo} created entity {entityInfo}"); _logger.Trace($"{playerInfo} created static entity {entityInfo}");
entity.Attach(player); entity.Attach(player);
room.AttachEntity(entity); room.AttachEntity(entity);
+1 -1
View File
@@ -22,7 +22,7 @@ namespace Ragon.Server.Lobby;
public interface IRagonLobby public interface IRagonLobby
{ {
public bool FindRoomById(string roomId, [MaybeNullWhen(false)] out RagonRoom room); public bool FindRoomById(string roomId, [MaybeNullWhen(false)] out RagonRoom room);
public bool FindRoomByMap(string map, [MaybeNullWhen(false)] out RagonRoom room); public bool FindRoomByScene(string sceneName, [MaybeNullWhen(false)] out RagonRoom room);
public void Persist(RagonRoom room); public void Persist(RagonRoom room);
public bool RemoveIfEmpty(RagonRoom room); public bool RemoveIfEmpty(RagonRoom room);
} }
@@ -40,11 +40,11 @@ public class LobbyInMemory : IRagonLobby
return false; return false;
} }
public bool FindRoomByMap(string map, [MaybeNullWhen(false)] out RagonRoom room) public bool FindRoomByScene(string sceneName, [MaybeNullWhen(false)] out RagonRoom room)
{ {
foreach (var existsRoom in _rooms) foreach (var existsRoom in _rooms)
{ {
if (existsRoom.Map == map && existsRoom.PlayerCount < existsRoom.PlayerMax) if (existsRoom.Scene == sceneName && existsRoom.PlayerCount < existsRoom.PlayerMax)
{ {
room = existsRoom; room = existsRoom;
return true; return true;
@@ -61,7 +61,7 @@ public class LobbyInMemory : IRagonLobby
_logger.Trace($"New room: {room.Id}"); _logger.Trace($"New room: {room.Id}");
foreach (var r in _rooms) foreach (var r in _rooms)
_logger.Trace($"Room: {r.Id} Map: {r.Map} Players: {r.Players.Count} Entities: {r.Entities.Count}"); _logger.Trace($"Room: {r.Id} Scene: {r.Scene} Players: {r.Players.Count} Entities: {r.Entities.Count}");
} }
public bool RemoveIfEmpty(RagonRoom room) public bool RemoveIfEmpty(RagonRoom room)
@@ -76,7 +76,7 @@ public class LobbyInMemory : IRagonLobby
} }
foreach (var r in _rooms) foreach (var r in _rooms)
_logger.Trace($"Room: {r.Id} Map: {r.Map} Players: {r.Players.Count} Entities: {r.Entities.Count}"); _logger.Trace($"Room: {r.Id} Scene: {r.Scene} Players: {r.Players.Count} Entities: {r.Entities.Count}");
return result; return result;
} }
+7 -9
View File
@@ -25,15 +25,15 @@ namespace Ragon.Server.Room;
public class RagonRoom : IRagonRoom, IRagonAction public class RagonRoom : IRagonRoom, IRagonAction
{ {
public string Id { get; private set; } public string Id { get; private set; }
public string Map { get; private set; } public string Scene { get; private set; }
public int PlayerMax { get; private set; } public int PlayerMax { get; private set; }
public int PlayerMin { get; private set; } public int PlayerMin { get; private set; }
public int PlayerCount => WaitPlayersList.Count; public int PlayerCount => WaitPlayersList.Count;
public RagonRoomPlayer Owner { get; private set; } public RagonRoomPlayer Owner { get; private set; }
public RagonBuffer Writer { get; } public RagonBuffer Writer { get; }
public IRoomPlugin Plugin { get; private set; } public IRoomPlugin Plugin { get; private set; }
public Dictionary<ushort, RagonRoomPlayer> Players { get; private set; } public Dictionary<ushort, RagonRoomPlayer> Players { get; private set; }
public List<RagonRoomPlayer> WaitPlayersList { get; private set; } public List<RagonRoomPlayer> WaitPlayersList { get; private set; }
public List<RagonRoomPlayer> ReadyPlayersList { get; private set; } public List<RagonRoomPlayer> ReadyPlayersList { get; private set; }
@@ -45,11 +45,11 @@ public class RagonRoom : IRagonRoom, IRagonAction
public List<RagonEntity> EntityList { get; private set; } public List<RagonEntity> EntityList { get; private set; }
private readonly HashSet<RagonEntity> _entitiesDirtySet; private readonly HashSet<RagonEntity> _entitiesDirtySet;
public RagonRoom(string roomId, RoomInformation info, IRoomPlugin roomPlugin) public RagonRoom(string roomId, RoomInformation info, IRoomPlugin roomPlugin)
{ {
Id = roomId; Id = roomId;
Map = info.Map; Scene = info.Scene;
PlayerMax = info.Max; PlayerMax = info.Max;
PlayerMin = info.Min; PlayerMin = info.Min;
Plugin = roomPlugin; Plugin = roomPlugin;
@@ -182,7 +182,7 @@ public class RagonRoom : IRagonRoom, IRagonAction
public void UpdateMap(string sceneName) public void UpdateMap(string sceneName)
{ {
Map = sceneName; Scene = sceneName;
DynamicEntitiesList.Clear(); DynamicEntitiesList.Clear();
StaticEntitiesList.Clear(); StaticEntitiesList.Clear();
@@ -218,9 +218,7 @@ public class RagonRoom : IRagonRoom, IRagonAction
public IRagonEntity? GetEntityById(ushort id) public IRagonEntity? GetEntityById(ushort id)
{ {
return Entities.TryGetValue(id, out var entity) ? return Entities.TryGetValue(id, out var entity) ? entity : null;
entity :
null;
} }
public IRagonEntity[] GetEntitiesOfPlayer(RagonRoomPlayer player) public IRagonEntity[] GetEntitiesOfPlayer(RagonRoomPlayer player)
@@ -18,7 +18,7 @@ namespace Ragon.Server;
public ref struct RoomInformation public ref struct RoomInformation
{ {
public string Map; public string Scene;
public int Min; public int Min;
public int Max; public int Max;
} }