feat: ticks, state authority, event authority
This commit is contained in:
@@ -3,3 +3,4 @@
|
||||
.vs
|
||||
obj
|
||||
bin
|
||||
*.user
|
||||
@@ -1,70 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Game.Source.Events;
|
||||
using NLog;
|
||||
using Ragon.Core;
|
||||
|
||||
namespace Game.Source
|
||||
{
|
||||
public class ExamplePlugin: PluginBase
|
||||
{
|
||||
public override void OnStart()
|
||||
{
|
||||
_logger.Info("Plugin started");
|
||||
|
||||
/*Subscribe<TestEvent>(123, OnTestEvent);
|
||||
*/
|
||||
// Subscribe(500, OnTestEvent2);;
|
||||
}
|
||||
|
||||
private void OnTestEvent2(Player obj)
|
||||
{
|
||||
_logger.Info("Event without data");
|
||||
}
|
||||
|
||||
public override void OnStop()
|
||||
{
|
||||
_logger.Info("Plugin stopped");
|
||||
}
|
||||
|
||||
private void OnTestEvent(Player player, TestEvent myEvent)
|
||||
{
|
||||
_logger.Info("Data " + myEvent.TestData);
|
||||
}
|
||||
|
||||
public override void OnPlayerJoined(Player player)
|
||||
{
|
||||
_logger.Info("Player joined " + player.PlayerName);
|
||||
|
||||
SendEvent(player, 123, new TestEvent()
|
||||
{
|
||||
TestData = "asdf"
|
||||
});
|
||||
|
||||
SendEvent(123, new TestEvent()
|
||||
{
|
||||
TestData = "Hello!",
|
||||
});
|
||||
}
|
||||
|
||||
public override void OnPlayerLeaved(Player player)
|
||||
{
|
||||
_logger.Info("Player leaved " + player.PlayerName);
|
||||
}
|
||||
|
||||
public override void OnEntityCreated(Player creator, Entity entity)
|
||||
{
|
||||
// entity.
|
||||
// Subscribe(entity, 500, OnEntityTestEvent);
|
||||
}
|
||||
|
||||
public override void OnEntityDestroyed(Player destoyer, Entity entity)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnEntityTestEvent(Player player, Entity entity)
|
||||
{
|
||||
_logger.Info("Entity event with empty payload");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"apiKey": "123",
|
||||
"server": {
|
||||
"port": 5000,
|
||||
"skipTimeout": 60
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Ragon.Common
|
||||
{
|
||||
public enum RagonAuthority: byte
|
||||
{
|
||||
OWNER_ONLY,
|
||||
ALL,
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ namespace Ragon.Common
|
||||
RESTORED,
|
||||
|
||||
REPLICATE_ENTITY_STATE,
|
||||
REPLICATE_ENTITY_PROPERTY,
|
||||
REPLICATE_ENTITY_EVENT,
|
||||
REPLICATE_EVENT,
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<OutputPath>/Users/edmand46/UnityProjects/Ragon-Unity-SDK/Assets/RagonSDK/Plugins/</OutputPath>
|
||||
<OutputPath></OutputPath>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;NETSTACK_SPAN</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<OutputPath>/Users/edmand46/UnityProjects/Ragon-Unity-SDK/Assets/RagonSDK/Plugins/</OutputPath>
|
||||
<OutputPath></OutputPath>
|
||||
<DefineConstants>TRACE;NETSTACK_SPAN</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon", "Ragon\Ragon.csproj", "{BABA1AF0-CF91-43F2-9577-53800068ACCF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Game", "Game\Game.csproj", "{C2B87ADE-A122-4366-8EB7-24DAE11EBAF0}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleServer", "SimpleServer\SimpleServer.csproj", "{C2B87ADE-A122-4366-8EB7-24DAE11EBAF0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Common", "Ragon.Common\Ragon.Common.csproj", "{F478B2A2-36F4-43B9-9BB7-382A57C449B2}"
|
||||
EndProject
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
<PackageReference Include="ENet-CSharp" Version="2.4.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.5.61" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="8.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,12 +6,13 @@ namespace Ragon.Core
|
||||
public struct Server
|
||||
{
|
||||
public ushort Port;
|
||||
public ushort TickRate;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct Configuration
|
||||
{
|
||||
public string ApiKey;
|
||||
public string Key;
|
||||
public Server Server;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Ragon.Common;
|
||||
|
||||
namespace Ragon.Core;
|
||||
|
||||
@@ -8,13 +8,15 @@ public class Entity
|
||||
public int EntityId { get; private set; }
|
||||
public uint OwnerId { get; private set; }
|
||||
public ushort EntityType { get; private set; }
|
||||
public byte[] State { get; set; }
|
||||
public Dictionary<int, byte[]> Properties { get; set; }
|
||||
public RagonAuthority Authority { get; private set; }
|
||||
public EntityState State { get; private set; }
|
||||
|
||||
public Entity(uint ownerId, ushort entityType)
|
||||
public Entity(uint ownerId, ushort entityType, RagonAuthority stateAuthority, RagonAuthority eventAuthority)
|
||||
{
|
||||
OwnerId = ownerId;
|
||||
EntityType = entityType;
|
||||
EntityId = _idGenerator++;
|
||||
State = new EntityState(stateAuthority);
|
||||
Authority = eventAuthority;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Ragon.Common;
|
||||
|
||||
namespace Ragon.Core;
|
||||
|
||||
public class EntityState
|
||||
{
|
||||
public bool isDirty { get; private set; }
|
||||
public RagonAuthority Authority { get; private set; }
|
||||
|
||||
public byte[] Data
|
||||
{
|
||||
get => Data;
|
||||
set
|
||||
{
|
||||
Data = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public EntityState(RagonAuthority ragonAuthority)
|
||||
{
|
||||
Authority = ragonAuthority;
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
@@ -280,7 +280,7 @@ namespace Ragon.Core
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnTick(float deltaTime)
|
||||
public virtual void OnTick(ulong ticks, float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+58
-69
@@ -22,6 +22,7 @@ namespace Ragon.Core
|
||||
private Dictionary<uint, Player> _players = new();
|
||||
private Dictionary<int, Entity> _entities = new();
|
||||
private uint _owner;
|
||||
private uint _ticks;
|
||||
|
||||
private readonly PluginBase _plugin;
|
||||
private readonly RoomThread _roomThread;
|
||||
@@ -69,7 +70,7 @@ namespace Ragon.Core
|
||||
|
||||
var sendData = new byte[idRaw.Length + 18];
|
||||
var data = sendData.AsSpan();
|
||||
|
||||
|
||||
Span<byte> operationData = data.Slice(0, 2);
|
||||
Span<byte> peerData = data.Slice(2, 4);
|
||||
Span<byte> ownerData = data.Slice(4, 4);
|
||||
@@ -84,7 +85,7 @@ namespace Ragon.Core
|
||||
RagonHeader.WriteInt(PlayersMax, ref maxData);
|
||||
|
||||
idRaw.CopyTo(idData);
|
||||
|
||||
|
||||
Send(peerId, sendData);
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ namespace Ragon.Core
|
||||
var sceneRawData = Encoding.UTF8.GetBytes(Map).AsSpan();
|
||||
var sendData = new byte[sceneRawData.Length + 2];
|
||||
var data = sendData.AsSpan();
|
||||
|
||||
|
||||
Span<byte> operationData = data.Slice(0, 2);
|
||||
Span<byte> sceneData = data.Slice(2, sceneRawData.Length);
|
||||
|
||||
@@ -135,56 +136,33 @@ namespace Ragon.Core
|
||||
{
|
||||
var entityData = rawData.Slice(2, 4);
|
||||
var entityId = RagonHeader.ReadInt(ref entityData);
|
||||
if (_entities.TryGetValue(entityId, out var ent) && ent.OwnerId == peerId)
|
||||
if (_entities.TryGetValue(entityId, out var ent))
|
||||
{
|
||||
ent.State = rawData.Slice(6, rawData.Length - 6).ToArray();
|
||||
if (ent.State.Authority == RagonAuthority.OWNER_ONLY && ent.OwnerId != peerId)
|
||||
return;
|
||||
|
||||
ent.State.Data = rawData.Slice(6, rawData.Length - 6).ToArray();
|
||||
|
||||
var data = new byte[rawData.Length];
|
||||
|
||||
|
||||
rawData.CopyTo(data);
|
||||
|
||||
|
||||
Broadcast(_readyPlayers, data);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RagonOperation.REPLICATE_ENTITY_PROPERTY:
|
||||
{
|
||||
var entityData = rawData.Slice(2, 4);
|
||||
var entityId = RagonHeader.ReadInt(ref entityData);
|
||||
if (_entities.TryGetValue(entityId, out var ent) && ent.OwnerId == peerId)
|
||||
{
|
||||
var propertyData = rawData.Slice(6, 4);
|
||||
var propertyId = RagonHeader.ReadInt(ref propertyData);
|
||||
var payload = rawData.Slice(10, rawData.Length - 10).ToArray();
|
||||
var props = _entities[entityId].Properties;
|
||||
|
||||
if (props.ContainsKey(propertyId))
|
||||
props[propertyId] = payload;
|
||||
else
|
||||
props.Add(propertyId, payload);
|
||||
|
||||
var sendData = new byte[rawData.Length];
|
||||
|
||||
rawData.CopyTo(sendData);
|
||||
|
||||
Broadcast(_readyPlayers, sendData, DeliveryType.Reliable);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RagonOperation.REPLICATE_ENTITY_EVENT:
|
||||
{
|
||||
|
||||
var evntCodeData = rawData.Slice(2, 2);
|
||||
var entityIdData = rawData.Slice(4, 4);
|
||||
var evntId = RagonHeader.ReadUShort(ref evntCodeData);
|
||||
var entityId = RagonHeader.ReadInt(ref entityIdData);
|
||||
|
||||
if (!_entities.ContainsKey(entityId))
|
||||
|
||||
if (!_entities.TryGetValue(entityId, out var ent))
|
||||
return;
|
||||
|
||||
if (_entities[entityId].OwnerId != peerId)
|
||||
|
||||
if (ent.Authority == RagonAuthority.OWNER_ONLY && ent.OwnerId != peerId)
|
||||
return;
|
||||
|
||||
var payload = rawData.Slice(8, rawData.Length - 8);
|
||||
@@ -208,21 +186,23 @@ namespace Ragon.Core
|
||||
return;
|
||||
|
||||
var data = new byte[rawData.Length];
|
||||
|
||||
|
||||
rawData.CopyTo(data);
|
||||
|
||||
|
||||
Broadcast(_readyPlayers, data, DeliveryType.Reliable);
|
||||
break;
|
||||
}
|
||||
case RagonOperation.CREATE_ENTITY:
|
||||
{
|
||||
var typeData = rawData.Slice(2, 2);
|
||||
var authorityData = rawData.Slice(2, 2);
|
||||
var entityPayloadData = rawData.Slice(4, rawData.Length - 4);
|
||||
|
||||
var entityType = RagonHeader.ReadUShort(ref typeData);
|
||||
var entity = new Entity(peerId, entityType);
|
||||
entity.State = entityPayloadData.ToArray();
|
||||
entity.Properties = new Dictionary<int, byte[]>();
|
||||
var stateAuthority = (RagonAuthority) authorityData[0];
|
||||
var eventAuthority = (RagonAuthority) authorityData[1];
|
||||
var entity = new Entity(peerId, entityType, stateAuthority, eventAuthority);
|
||||
entity.State.Data = entityPayloadData.ToArray();
|
||||
|
||||
var player = _players[peerId];
|
||||
player.Entities.Add(entity);
|
||||
@@ -233,16 +213,20 @@ namespace Ragon.Core
|
||||
|
||||
_plugin.OnEntityCreated(player, entity);
|
||||
|
||||
var data = new byte[entityPayloadData.Length + 12];
|
||||
var data = new byte[entityPayloadData.Length + 14];
|
||||
var sendData = data.AsSpan();
|
||||
var operationData = sendData.Slice(0, 2);
|
||||
var entityTypeData = sendData.Slice(2, 2);
|
||||
var entityIdData = sendData.Slice(4, 4);
|
||||
var peerData = sendData.Slice(8, 4);
|
||||
var payload = sendData.Slice(12, entityPayloadData.Length);
|
||||
var authority = sendData.Slice(4, 2);
|
||||
var entityIdData = sendData.Slice(6, 4);
|
||||
var peerData = sendData.Slice(10, 4);
|
||||
var payload = sendData.Slice(14, entityPayloadData.Length);
|
||||
|
||||
entityPayloadData.CopyTo(payload);
|
||||
|
||||
authority[0] = authorityData[0];
|
||||
authority[1] = authorityData[1];
|
||||
|
||||
RagonHeader.WriteUShort((ushort) RagonOperation.CREATE_ENTITY, ref operationData);
|
||||
RagonHeader.WriteUShort(entityType, ref entityTypeData);
|
||||
RagonHeader.WriteInt(entity.EntityId, ref entityIdData);
|
||||
@@ -257,24 +241,24 @@ namespace Ragon.Core
|
||||
var entityId = RagonHeader.ReadInt(ref entityData);
|
||||
if (_entities.TryGetValue(entityId, out var entity))
|
||||
{
|
||||
if (entity.OwnerId == peerId)
|
||||
{
|
||||
var player = _players[peerId];
|
||||
if (entity.Authority == RagonAuthority.OWNER_ONLY && entity.OwnerId != peerId)
|
||||
return;
|
||||
|
||||
var player = _players[peerId];
|
||||
|
||||
player.Entities.Remove(entity);
|
||||
player.EntitiesIds.Remove(entity.EntityId);
|
||||
player.Entities.Remove(entity);
|
||||
player.EntitiesIds.Remove(entity.EntityId);
|
||||
|
||||
_entities.Remove(entityId);
|
||||
_entitiesAll = _entities.Values.ToArray();
|
||||
_entities.Remove(entityId);
|
||||
_entitiesAll = _entities.Values.ToArray();
|
||||
|
||||
_plugin.OnEntityDestroyed(player, entity);
|
||||
_plugin.OnEntityDestroyed(player, entity);
|
||||
|
||||
var data = new byte[rawData.Length];
|
||||
Span<byte> sendData = data.AsSpan();
|
||||
rawData.CopyTo(sendData);
|
||||
|
||||
Broadcast(_readyPlayers, data, DeliveryType.Reliable);
|
||||
}
|
||||
var data = new byte[rawData.Length];
|
||||
Span<byte> sendData = data.AsSpan();
|
||||
rawData.CopyTo(sendData);
|
||||
|
||||
Broadcast(_readyPlayers, data, DeliveryType.Reliable);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -284,23 +268,27 @@ namespace Ragon.Core
|
||||
Send(peerId, RagonOperation.RESTORE_BEGIN, DeliveryType.Reliable);
|
||||
foreach (var entity in _entities.Values)
|
||||
{
|
||||
var entityState = entity.State.AsSpan();
|
||||
var data = new byte[entity.State.Length + 12];
|
||||
|
||||
var entityState = entity.State.Data.AsSpan();
|
||||
var data = new byte[entity.State.Data.Length + 12];
|
||||
|
||||
Span<byte> sendData = data.AsSpan();
|
||||
Span<byte> operationData = sendData.Slice(0, 2);
|
||||
Span<byte> entityTypeData = sendData.Slice(2, 2);
|
||||
Span<byte> entityData = sendData.Slice(4, 4);
|
||||
Span<byte> ownerData = sendData.Slice(8, 4);
|
||||
Span<byte> entityStateData = sendData.Slice(12, entity.State.Length);
|
||||
Span<byte> authorityData = sendData.Slice(4, 2);
|
||||
Span<byte> entityData = sendData.Slice(6, 4);
|
||||
Span<byte> ownerData = sendData.Slice(10, 4);
|
||||
Span<byte> entityStateData = sendData.Slice(14, entity.State.Data.Length);
|
||||
|
||||
RagonHeader.WriteUShort((ushort) RagonOperation.CREATE_ENTITY, ref operationData);
|
||||
RagonHeader.WriteUShort(entity.EntityType, ref entityTypeData);
|
||||
RagonHeader.WriteInt(entity.EntityId, ref entityData);
|
||||
RagonHeader.WriteInt((int) entity.OwnerId, ref ownerData);
|
||||
|
||||
authorityData[0] = (byte) entity.State.Authority;
|
||||
authorityData[1] = (byte) entity.Authority;
|
||||
|
||||
entityState.CopyTo(entityStateData);
|
||||
|
||||
|
||||
Send(peerId, data, DeliveryType.Reliable);
|
||||
}
|
||||
|
||||
@@ -320,7 +308,8 @@ namespace Ragon.Core
|
||||
|
||||
public void Tick(float deltaTime)
|
||||
{
|
||||
_plugin.OnTick(deltaTime);
|
||||
_ticks++;
|
||||
_plugin.OnTick(_ticks, deltaTime);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
@@ -350,7 +339,7 @@ namespace Ragon.Core
|
||||
{
|
||||
var rawData = new byte[2];
|
||||
var rawDataSpan = new Span<byte>(rawData);
|
||||
|
||||
|
||||
RagonHeader.WriteUShort((ushort) operation, ref rawDataSpan);
|
||||
|
||||
_roomThread.WriteOutEvent(new Event()
|
||||
|
||||
@@ -15,26 +15,27 @@ namespace Ragon.Core
|
||||
private readonly Thread _thread;
|
||||
private readonly Stopwatch _timer;
|
||||
private readonly ILogger _logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly float _deltaTime = 0.0f;
|
||||
private RingBuffer<Event> _receiveBuffer = new RingBuffer<Event>(8192 + 8192);
|
||||
private RingBuffer<Event> _sendBuffer = new RingBuffer<Event>(8192 + 8192);
|
||||
|
||||
|
||||
public Configuration Configuration { get; private set; }
|
||||
public bool ReadOutEvent(out Event evnt) => _sendBuffer.TryDequeue(out evnt);
|
||||
public void WriteOutEvent(Event evnt) => _sendBuffer.Enqueue(evnt);
|
||||
|
||||
public bool ReadIntEvent(out Event evnt) => _receiveBuffer.TryDequeue(out evnt);
|
||||
public void WriteInEvent(Event evnt) => _receiveBuffer.Enqueue(evnt);
|
||||
|
||||
|
||||
public RoomThread(PluginFactory factory, Configuration configuration)
|
||||
{
|
||||
_thread = new Thread(Execute);
|
||||
_thread.IsBackground = true;
|
||||
_timer = new Stopwatch();
|
||||
_socketByRooms = new Dictionary<uint, Room>();
|
||||
|
||||
|
||||
Configuration = configuration;
|
||||
|
||||
_deltaTime = 1000.0f / Configuration.Server.TickRate;
|
||||
|
||||
_roomManager = new RoomManager(this, factory);
|
||||
_roomManager.OnJoined += (tuple) => _socketByRooms.Add(tuple.Item1, tuple.Item2);
|
||||
_roomManager.OnLeaved += (tuple) => _socketByRooms.Remove(tuple.Item1);
|
||||
@@ -55,52 +56,50 @@ namespace Ragon.Core
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var deltaTime = _timer.ElapsedMilliseconds;
|
||||
if (deltaTime > 1000 / 60)
|
||||
while (_receiveBuffer.TryDequeue(out var evnt))
|
||||
{
|
||||
while (_receiveBuffer.TryDequeue(out var evnt))
|
||||
if (evnt.Type == EventType.DISCONNECTED || evnt.Type == EventType.TIMEOUT)
|
||||
{
|
||||
if (evnt.Type == EventType.DISCONNECTED || evnt.Type == EventType.TIMEOUT)
|
||||
if (_socketByRooms.ContainsKey(evnt.PeerId))
|
||||
{
|
||||
if (_socketByRooms.ContainsKey(evnt.PeerId))
|
||||
{
|
||||
_roomManager.Disconnected(evnt.PeerId);
|
||||
_socketByRooms.Remove(evnt.PeerId);
|
||||
}
|
||||
}
|
||||
|
||||
if (evnt.Type == EventType.DATA)
|
||||
{
|
||||
var data = new ReadOnlySpan<byte>(evnt.Data);
|
||||
var operationData = data.Slice(0, 2);
|
||||
var operation = (RagonOperation) RagonHeader.ReadUShort(ref operationData);
|
||||
if (_socketByRooms.TryGetValue(evnt.PeerId, out var room))
|
||||
{
|
||||
try
|
||||
{
|
||||
room.ProcessEvent(operation, evnt.PeerId, data);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var payload = data.Slice(2, data.Length - 2);
|
||||
_roomManager.ProcessEvent(operation, evnt.PeerId, payload);
|
||||
}
|
||||
_roomManager.Disconnected(evnt.PeerId);
|
||||
_socketByRooms.Remove(evnt.PeerId);
|
||||
}
|
||||
}
|
||||
|
||||
_roomManager.Tick(deltaTime / 1000.0f);
|
||||
if (evnt.Type == EventType.DATA)
|
||||
{
|
||||
var data = new ReadOnlySpan<byte>(evnt.Data);
|
||||
var operationData = data.Slice(0, 2);
|
||||
var operation = (RagonOperation) RagonHeader.ReadUShort(ref operationData);
|
||||
if (_socketByRooms.TryGetValue(evnt.PeerId, out var room))
|
||||
{
|
||||
try
|
||||
{
|
||||
room.ProcessEvent(operation, evnt.PeerId, data);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var payload = data.Slice(2, data.Length - 2);
|
||||
_roomManager.ProcessEvent(operation, evnt.PeerId, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_timer.Restart();
|
||||
}
|
||||
else
|
||||
var elapsedMilliseconds = _timer.ElapsedMilliseconds;
|
||||
if (elapsedMilliseconds > _deltaTime)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
_roomManager.Tick(elapsedMilliseconds / 1000.0f);
|
||||
_timer.Restart();
|
||||
continue;
|
||||
}
|
||||
|
||||
Thread.Sleep(15);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"key": "defaultkey",
|
||||
"server": {
|
||||
"port": 4444,
|
||||
"skipTimeout": 60,
|
||||
"tickRate": 30
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user