added transfer ownership, limit buffered events

This commit is contained in:
2023-07-01 07:47:57 +03:00
parent 20662ae24d
commit 105457ffa0
24 changed files with 134 additions and 108 deletions
+1 -1
View File
@@ -226,7 +226,7 @@ namespace Ragon.Client
var prevOwner = Owner; var prevOwner = Owner;
Owner = player; Owner = player;
HasAuthority = player.PeerId == _client.Room.Local.PeerId; HasAuthority = player.IsLocal;
OwnershipChanged?.Invoke(prevOwner, player); OwnershipChanged?.Invoke(prevOwner, player);
} }
@@ -19,13 +19,13 @@ using Ragon.Protocol;
namespace Ragon.Client; namespace Ragon.Client;
internal class OwnershipEntityHandler: Handler internal class EntityOwnershipHandler: Handler
{ {
private readonly RagonListenerList _listenerList; private readonly RagonListenerList _listenerList;
private readonly RagonPlayerCache _playerCache; private readonly RagonPlayerCache _playerCache;
private readonly RagonEntityCache _entityCache; private readonly RagonEntityCache _entityCache;
public OwnershipEntityHandler( public EntityOwnershipHandler(
RagonListenerList listenerList, RagonListenerList listenerList,
RagonPlayerCache playerCache, RagonPlayerCache playerCache,
RagonEntityCache entityCache) RagonEntityCache entityCache)
@@ -37,13 +37,16 @@ internal class OwnershipEntityHandler: Handler
public void Handle(RagonBuffer buffer) public void Handle(RagonBuffer buffer)
{ {
var newOwnerId = buffer.ReadString(); var newOwnerId = buffer.ReadUShort();
var player = _playerCache.GetPlayerById(newOwnerId);
var entities = buffer.ReadUShort(); var entities = buffer.ReadUShort();
var player = _playerCache.GetPlayerByPeer(newOwnerId);
for (var i = 0; i < entities; i++) for (var i = 0; i < entities; i++)
{ {
var entityId = buffer.ReadUShort(); var entityId = buffer.ReadUShort();
_entityCache.OnOwnershipChanged(player, entityId); _entityCache.OnOwnershipChanged(player, entityId);
RagonLog.Trace("Entity changed owner: " + entityId);
} }
} }
} }
@@ -37,8 +37,8 @@ internal class OwnershipRoomHandler: Handler
public void Handle(RagonBuffer buffer) public void Handle(RagonBuffer buffer)
{ {
var newOwnerId = buffer.ReadString(); var newOwnerId = buffer.ReadUShort();
var player = _playerCache.GetPlayerById(newOwnerId); var player = _playerCache.GetPlayerByPeer(newOwnerId);
_playerCache.OnOwnershipChanged(newOwnerId); _playerCache.OnOwnershipChanged(newOwnerId);
_listenerList.OnOwnershipChanged(player); _listenerList.OnOwnershipChanged(player);
+1 -1
View File
@@ -91,7 +91,7 @@ namespace Ragon.Client
_handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(_listenerList); _handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(_listenerList);
_handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, _listenerList, _entityCache); _handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, _listenerList, _entityCache);
_handlers[(byte)RagonOperation.OWNERSHIP_ROOM_CHANGED] = new OwnershipRoomHandler(_listenerList, _playerCache, _entityCache); _handlers[(byte)RagonOperation.OWNERSHIP_ROOM_CHANGED] = new OwnershipRoomHandler(_listenerList, _playerCache, _entityCache);
_handlers[(byte)RagonOperation.OWNERSHIP_ENTITY_CHANGED] = new OwnershipEntityHandler(_listenerList, _playerCache, _entityCache); _handlers[(byte)RagonOperation.OWNERSHIP_ENTITY_CHANGED] = new EntityOwnershipHandler(_listenerList, _playerCache, _entityCache);
_handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_playerCache, _listenerList); _handlers[(byte)RagonOperation.PLAYER_JOINED] = new PlayerJoinHandler(_playerCache, _listenerList);
_handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_entityCache, _playerCache, _listenerList); _handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_entityCache, _playerCache, _listenerList);
_handlers[(byte)RagonOperation.LOAD_SCENE] = new SceneLoadHandler(this, _listenerList); _handlers[(byte)RagonOperation.LOAD_SCENE] = new SceneLoadHandler(this, _listenerList);
+51 -42
View File
@@ -24,20 +24,20 @@ public sealed class RagonEntityCache
private readonly Dictionary<uint, RagonEntity> _entityMap = new(); private readonly Dictionary<uint, RagonEntity> _entityMap = new();
private readonly Dictionary<uint, RagonEntity> _pendingEntities = new(); private readonly Dictionary<uint, RagonEntity> _pendingEntities = new();
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 IRagonEntityListener _entityListener;
private readonly IRagonSceneCollector _sceneCollector; private readonly IRagonSceneCollector _sceneCollector;
private readonly RagonPlayerCache _playerCache; private readonly RagonPlayerCache _playerCache;
private int _localEntitiesCounter = 0; private int _localEntitiesCounter = 0;
public RagonEntityCache( public RagonEntityCache(
RagonClient client, RagonClient client,
RagonPlayerCache playerCache, RagonPlayerCache playerCache,
IRagonEntityListener listener, IRagonEntityListener listener,
IRagonSceneCollector sceneCollector IRagonSceneCollector sceneCollector
) )
{ {
_client = client; _client = client;
_entityListener = listener; _entityListener = listener;
@@ -49,24 +49,24 @@ public sealed class RagonEntityCache
{ {
return _entityMap[id]; return _entityMap[id];
} }
public void Create(RagonEntity entity, IRagonPayload? spawnPayload) public void Create(RagonEntity entity, IRagonPayload? spawnPayload)
{ {
var attachId = (ushort) (_playerCache.Local.PeerId + _localEntitiesCounter++) ; var attachId = (ushort)(_playerCache.Local.PeerId + _localEntitiesCounter++);
var buffer = _client.Buffer; var buffer = _client.Buffer;
buffer.Clear(); buffer.Clear();
buffer.WriteOperation(RagonOperation.CREATE_ENTITY); buffer.WriteOperation(RagonOperation.CREATE_ENTITY);
buffer.WriteUShort(attachId); buffer.WriteUShort(attachId);
buffer.WriteUShort(entity.Type); buffer.WriteUShort(entity.Type);
buffer.WriteByte((byte) entity.Authority); buffer.WriteByte((byte)entity.Authority);
entity.State.WriteInfo(buffer); entity.State.WriteInfo(buffer);
spawnPayload?.Serialize(buffer); spawnPayload?.Serialize(buffer);
_pendingEntities.Add(attachId, entity); _pendingEntities.Add(attachId, entity);
var sendData = buffer.ToArray(); var sendData = buffer.ToArray();
_client.Reliable.Send(sendData); _client.Reliable.Send(sendData);
} }
@@ -74,16 +74,16 @@ public sealed class RagonEntityCache
public void Transfer(RagonEntity entity, RagonPlayer player) public void Transfer(RagonEntity entity, RagonPlayer player)
{ {
var buffer = _client.Buffer; var buffer = _client.Buffer;
buffer.Clear(); buffer.Clear();
buffer.WriteOperation(RagonOperation.TRANSFER_ENTITY_OWNERSHIP); buffer.WriteOperation(RagonOperation.TRANSFER_ENTITY_OWNERSHIP);
buffer.WriteUShort(entity.Id); buffer.WriteUShort(entity.Id);
buffer.WriteUShort(player.PeerId); buffer.WriteUShort(player.PeerId);
var sendData = buffer.ToArray(); var sendData = buffer.ToArray();
_client.Reliable.Send(sendData); _client.Reliable.Send(sendData);
} }
public void Destroy(RagonEntity entity, IRagonPayload? destroyPayload) public void Destroy(RagonEntity entity, IRagonPayload? destroyPayload)
{ {
if (!entity.IsAttached) if (!entity.IsAttached)
@@ -91,9 +91,9 @@ public sealed class RagonEntityCache
RagonLog.Warn("Can't destroy object, he is not created"); RagonLog.Warn("Can't destroy object, he is not created");
return; return;
} }
var buffer = _client.Buffer; var buffer = _client.Buffer;
buffer.Clear(); buffer.Clear();
buffer.WriteOperation(RagonOperation.REMOVE_ENTITY); buffer.WriteOperation(RagonOperation.REMOVE_ENTITY);
buffer.WriteUShort(entity.Id); buffer.WriteUShort(entity.Id);
@@ -107,7 +107,7 @@ public sealed class RagonEntityCache
internal void WriteState(RagonBuffer buffer) internal void WriteState(RagonBuffer buffer)
{ {
var changedEntities = 0u; var changedEntities = 0u;
buffer.Clear(); buffer.Clear();
buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_STATE); buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_STATE);
@@ -119,34 +119,34 @@ public sealed class RagonEntityCache
if (!ent.IsAttached || if (!ent.IsAttached ||
!ent.Replication || !ent.Replication ||
!ent.PropertiesChanged) continue; !ent.PropertiesChanged) continue;
ent.Write(buffer); ent.Write(buffer);
changedEntities++; changedEntities++;
} }
if (changedEntities <= 0) return; if (changedEntities <= 0) return;
buffer.Write(changedEntities, 16, offset); buffer.Write(changedEntities, 16, offset);
var data = buffer.ToArray(); var data = buffer.ToArray();
_client.Unreliable.Send(data); _client.Unreliable.Send(data);
} }
internal void WriteScene(RagonBuffer buffer) internal void WriteScene(RagonBuffer buffer)
{ {
_sceneEntities.Clear(); _sceneEntities.Clear();
var entities = _sceneCollector.Collect(); var entities = _sceneCollector.Collect();
buffer.WriteUShort((ushort) entities.Length); buffer.WriteUShort((ushort)entities.Length);
foreach (var entity in entities) foreach (var entity in entities)
{ {
buffer.WriteUShort(entity.Type); buffer.WriteUShort(entity.Type);
buffer.WriteByte((byte) entity.Authority); buffer.WriteByte((byte)entity.Authority);
buffer.WriteUShort(entity.SceneId); buffer.WriteUShort(entity.SceneId);
entity.State.WriteInfo(buffer); entity.State.WriteInfo(buffer);
_sceneEntities.Add(entity.SceneId, entity); _sceneEntities.Add(entity.SceneId, entity);
} }
} }
@@ -154,12 +154,12 @@ public sealed class RagonEntityCache
internal void CacheScene() internal void CacheScene()
{ {
_sceneEntities.Clear(); _sceneEntities.Clear();
var entities = _sceneCollector.Collect(); var entities = _sceneCollector.Collect();
foreach (var entity in entities) foreach (var entity in entities)
_sceneEntities.Add(entity.SceneId, entity); _sceneEntities.Add(entity.SceneId, entity);
} }
internal void Cleanup() internal void Cleanup()
{ {
var payload = new RagonPayload(); var payload = new RagonPayload();
@@ -169,7 +169,7 @@ public sealed class RagonEntityCache
_entityMap.Clear(); _entityMap.Clear();
_entityList.Clear(); _entityList.Clear();
} }
internal RagonEntity OnCreate(ushort attachId, ushort entityType, ushort sceneId, ushort entityId, bool hasAuthority) internal RagonEntity OnCreate(ushort attachId, ushort entityType, ushort sceneId, ushort entityId, bool hasAuthority)
{ {
if (sceneId > 0) if (sceneId > 0)
@@ -177,45 +177,45 @@ public sealed class RagonEntityCache
if (_sceneEntities.TryGetValue(sceneId, out var entity)) if (_sceneEntities.TryGetValue(sceneId, out var entity))
{ {
_entityMap.Add(entityId, entity); _entityMap.Add(entityId, entity);
if (hasAuthority) if (hasAuthority)
_entityList.Add(entity); _entityList.Add(entity);
return entity; return entity;
} }
} }
if (_pendingEntities.Remove(attachId, out var existsEntity)) if (_pendingEntities.Remove(attachId, out var existsEntity))
{ {
_entityMap.Add(entityId, existsEntity); _entityMap.Add(entityId, existsEntity);
if (hasAuthority) if (hasAuthority)
_entityList.Add(existsEntity); _entityList.Add(existsEntity);
return existsEntity; return existsEntity;
} }
else else
{ {
var entity = new RagonEntity(entityType, sceneId); var entity = new RagonEntity(entityType, sceneId);
_entityMap.Add(entityId, entity); _entityMap.Add(entityId, entity);
if (hasAuthority) if (hasAuthority)
_entityList.Add(entity); _entityList.Add(entity);
_entityListener.OnEntityCreated(entity); _entityListener.OnEntityCreated(entity);
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.Remove(entityId, out var ragonEntity))
{ {
_entityList.Remove(ragonEntity); _entityList.Remove(ragonEntity);
ragonEntity.Detach(payload); ragonEntity.Detach(payload);
} }
} }
@@ -224,7 +224,7 @@ public sealed class RagonEntityCache
{ {
if (_entityMap.TryGetValue(entityId, out var entity)) if (_entityMap.TryGetValue(entityId, out var entity))
entity.Read(buffer); entity.Read(buffer);
else else
RagonLog.Warn($"Entity {entityId} not found!"); RagonLog.Warn($"Entity {entityId} not found!");
} }
@@ -232,15 +232,24 @@ public sealed class RagonEntityCache
{ {
if (_entityMap.TryGetValue(entityId, out var entity)) if (_entityMap.TryGetValue(entityId, out var entity))
entity.Event(eventCode, player, buffer); entity.Event(eventCode, player, buffer);
else else
RagonLog.Warn($"Entity {entityId} not found!"); RagonLog.Warn($"Entity {entityId} not found!");
} }
internal void OnOwnershipChanged(RagonPlayer player, ushort entityId) internal void OnOwnershipChanged(RagonPlayer player, ushort entityId)
{ {
if (_entityMap.TryGetValue(entityId, out var entity)) if (_entityMap.TryGetValue(entityId, out var entity))
{
if (player.IsLocal)
_entityList.Add(entity);
else
_entityList.Remove(entity);
entity.OnOwnershipChanged(player); entity.OnOwnershipChanged(player);
}
else else
{
RagonLog.Warn($"Entity {entityId} not found!"); RagonLog.Warn($"Entity {entityId} not found!");
}
} }
} }
+5 -3
View File
@@ -71,13 +71,15 @@ public sealed class RagonPlayerCache
} }
} }
public void OnOwnershipChanged(string playerId) public void OnOwnershipChanged(ushort playerPeerId)
{ {
foreach (var player in _players) foreach (var player in _players)
{ {
if (player.Id == playerId) if (player.PeerId == playerPeerId)
{
Owner = player; Owner = player;
player.IsRoomOwner = player.Id == playerId; Owner.IsRoomOwner = true;
}
} }
} }
+1 -1
View File
@@ -24,7 +24,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ragon.Server.ENet\Ragon.Server.ENet.csproj" /> <ProjectReference Include="..\Ragon.Server.ENet\Ragon.Server.ENet.csproj" />
<ProjectReference Include="..\Ragon.Server.DotNetWebSockets\Ragon.Server.DotNetWebSockets.csproj" /> <ProjectReference Include="..\Ragon.Server.WebSocketServer\Ragon.Server.WebSocketServer.csproj" />
<ProjectReference Include="..\Ragon.Server\Ragon.Server.csproj" /> <ProjectReference Include="..\Ragon.Server\Ragon.Server.csproj" />
</ItemGroup> </ItemGroup>
+4 -4
View File
@@ -17,7 +17,7 @@
using NLog; using NLog;
using Ragon.Server; using Ragon.Server;
using Ragon.Server.ENet; using Ragon.Server.ENet;
using Ragon.Server.DotNetWebsockets; using Ragon.Server.WebSocketServer;
using Ragon.Server.IO; using Ragon.Server.IO;
using Ragon.Server.Plugin; using Ragon.Server.Plugin;
@@ -30,8 +30,8 @@ public class Relay
var logger = LogManager.GetLogger("Ragon.Relay"); var logger = LogManager.GetLogger("Ragon.Relay");
logger.Info("Relay Application"); logger.Info("Relay Application");
var configuration = Configuration.Load("relay.config.json"); var configuration = RagonServerConfiguration.Load("relay.config.json");
var serverType = Configuration.GetServerType(configuration.ServerType); var serverType = RagonServerConfiguration.GetServerType(configuration.ServerType);
INetworkServer networkServer = new ENetServer(); INetworkServer networkServer = new ENetServer();
IServerPlugin plugin = new RelayServerPlugin(); IServerPlugin plugin = new RelayServerPlugin();
@@ -41,7 +41,7 @@ public class Relay
networkServer = new ENetServer(); networkServer = new ENetServer();
break; break;
case ServerType.WEBSOCKET: case ServerType.WEBSOCKET:
networkServer = new DotNetWebSocketServer(); networkServer = new WebSocketServer();
break; break;
} }
+1
View File
@@ -9,6 +9,7 @@
"limitConnections": 4095, "limitConnections": 4095,
"limitPlayersPerRoom": 20, "limitPlayersPerRoom": 20,
"limitRooms": 200, "limitRooms": 200,
"limitBufferedEvents": 50,
"webHooks": "webHooks":
{ {
"room-created": "http://127.0.0.1:3000/service/create-room", "room-created": "http://127.0.0.1:3000/service/create-room",
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Ragon.WebSockets</RootNamespace> <RootNamespace>Ragon.WebSockets</RootNamespace>
@@ -18,7 +18,7 @@ using NLog;
using System.Net.WebSockets; using System.Net.WebSockets;
using Ragon.Server.IO; using Ragon.Server.IO;
namespace Ragon.Server.DotNetWebsockets; namespace Ragon.Server.WebSocketServer;
public sealed class WebSocketConnection : INetworkConnection public sealed class WebSocketConnection : INetworkConnection
{ {
@@ -17,7 +17,7 @@
using System.Net.WebSockets; using System.Net.WebSockets;
using Ragon.Server.IO; using Ragon.Server.IO;
namespace Ragon.Server.DotNetWebsockets; namespace Ragon.Server.WebSocketServer;
public class WebSocketReliableChannel : INetworkChannel public class WebSocketReliableChannel : INetworkChannel
{ {
@@ -20,9 +20,9 @@ using NLog;
using Ragon.Protocol; using Ragon.Protocol;
using Ragon.Server.IO; using Ragon.Server.IO;
namespace Ragon.Server.DotNetWebsockets; namespace Ragon.Server.WebSocketServer;
public class DotNetWebSocketServer : INetworkServer public class WebSocketServer : INetworkServer
{ {
public Executor Executor => _executor; public Executor Executor => _executor;
@@ -35,7 +35,7 @@ public class DotNetWebSocketServer : INetworkServer
private List<WebSocketConnection> _activeConnections; private List<WebSocketConnection> _activeConnections;
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
public DotNetWebSocketServer() public WebSocketServer()
{ {
_sequencer = new Stack<ushort>(); _sequencer = new Stack<ushort>();
_connections = Array.Empty<WebSocketConnection>(); _connections = Array.Empty<WebSocketConnection>();
+17 -14
View File
@@ -20,7 +20,7 @@ using Ragon.Server.Room;
namespace Ragon.Server.Entity; namespace Ragon.Server.Entity;
public class RagonEntity: IRagonEntity public class RagonEntity : IRagonEntity
{ {
private static ushort _idGenerator = 100; private static ushort _idGenerator = 100;
public ushort Id { get; private set; } public ushort Id { get; private set; }
@@ -31,24 +31,26 @@ public class RagonEntity: IRagonEntity
public RagonAuthority Authority { get; private set; } public RagonAuthority Authority { get; private set; }
public RagonPayload Payload { get; private set; } public RagonPayload Payload { get; private set; }
public IRagonEntityState State => _state; public IRagonEntityState State => _state;
private readonly List<RagonEvent> _bufferedEvents; private readonly List<RagonEvent> _bufferedEvents;
private readonly int _limitBufferedEvents;
private readonly RagonEntityState _state; private readonly RagonEntityState _state;
public RagonEntity(RagonEntityParameters parameters) public RagonEntity(RagonEntityParameters parameters)
{ {
Id = _idGenerator++; Id = _idGenerator++;
StaticId = parameters.StaticId; StaticId = parameters.StaticId;
Type = parameters.Type; Type = parameters.Type;
AttachId = parameters.AttachId; AttachId = parameters.AttachId;
Authority = parameters.Authority; Authority = parameters.Authority;
Payload = new RagonPayload(); Payload = new RagonPayload();
_state = new RagonEntityState(this); _state = new RagonEntityState(this);
_bufferedEvents = new List<RagonEvent>(); _bufferedEvents = new List<RagonEvent>();
_limitBufferedEvents = parameters.BufferedEvents;
} }
public void Attach(RagonRoomPlayer owner) public void Attach(RagonRoomPlayer owner)
{ {
Owner = owner; Owner = owner;
@@ -56,8 +58,7 @@ public class RagonEntity: IRagonEntity
public void Detach() public void Detach()
{ {
}
}
public void RestoreBufferedEvents(RagonRoomPlayer roomPlayer, RagonBuffer writer) public void RestoreBufferedEvents(RagonRoomPlayer roomPlayer, RagonBuffer writer)
{ {
@@ -88,7 +89,7 @@ public class RagonEntity: IRagonEntity
buffer.WriteUShort(Type); buffer.WriteUShort(Type);
buffer.WriteUShort(Id); buffer.WriteUShort(Id);
buffer.WriteUShort(Owner.Connection.Id); buffer.WriteUShort(Owner.Connection.Id);
Payload.Write(buffer); Payload.Write(buffer);
var sendData = buffer.ToArray(); var sendData = buffer.ToArray();
@@ -122,7 +123,7 @@ public class RagonEntity: IRagonEntity
buffer.WriteUShort(Payload.Size); buffer.WriteUShort(Payload.Size);
Payload.Write(buffer); Payload.Write(buffer);
_state.Snapshot(buffer); _state.Snapshot(buffer);
} }
@@ -163,7 +164,9 @@ public class RagonEntity: IRagonEntity
return; return;
} }
if (eventMode == RagonReplicationMode.Buffered && targetMode != RagonTarget.Owner) if (eventMode == RagonReplicationMode.Buffered &&
targetMode != RagonTarget.Owner &&
_bufferedEvents.Count < _limitBufferedEvents)
{ {
_bufferedEvents.Add(evnt); _bufferedEvents.Add(evnt);
} }
@@ -221,7 +224,7 @@ public class RagonEntity: IRagonEntity
{ {
_state.AddProperty(property); _state.AddProperty(property);
} }
public void WriteState(RagonBuffer writer) public void WriteState(RagonBuffer writer)
{ {
_state.Write(writer); _state.Write(writer);
@@ -231,9 +234,9 @@ public class RagonEntity: IRagonEntity
{ {
if (Owner.Connection.Id != player.Connection.Id) if (Owner.Connection.Id != player.Connection.Id)
return false; return false;
_state.Read(reader); _state.Read(reader);
return true; return true;
} }
} }
@@ -24,4 +24,5 @@ public ref struct RagonEntityParameters
public ushort StaticId; public ushort StaticId;
public ushort AttachId; public ushort AttachId;
public RagonAuthority Authority; public RagonAuthority Authority;
public int BufferedEvents;
} }
@@ -28,16 +28,14 @@ public sealed class AuthorizationOperation: IRagonOperation
private Logger _logger = LogManager.GetCurrentClassLogger(); private Logger _logger = LogManager.GetCurrentClassLogger();
private readonly RagonWebHookPlugin _ragonWebHook; private readonly RagonWebHookPlugin _ragonWebHook;
private readonly RagonContextObserver _contextObserver; private readonly RagonContextObserver _contextObserver;
private readonly Configuration _configuration;
private readonly RagonBuffer _writer; private readonly RagonBuffer _writer;
public AuthorizationOperation(RagonWebHookPlugin ragonWebHook, public AuthorizationOperation(
RagonWebHookPlugin ragonWebHook,
RagonContextObserver contextObserver, RagonContextObserver contextObserver,
RagonBuffer writer, RagonBuffer writer)
Configuration configuration)
{ {
_ragonWebHook = ragonWebHook; _ragonWebHook = ragonWebHook;
_configuration = configuration;
_contextObserver = contextObserver; _contextObserver = contextObserver;
_writer = writer; _writer = writer;
} }
@@ -55,12 +53,13 @@ public sealed class AuthorizationOperation: IRagonOperation
_logger.Warn("Player already request authorization!"); _logger.Warn("Player already request authorization!");
return; return;
} }
var configuration = context.Configuration;
var key = reader.ReadString(); var key = reader.ReadString();
var name = reader.ReadString(); var name = reader.ReadString();
var payload = reader.ReadString(); var payload = reader.ReadString();
if (key == _configuration.ServerKey) if (key == configuration.ServerKey)
{ {
if (_ragonWebHook.RequestAuthorization(context, name, payload)) if (_ragonWebHook.RequestAuthorization(context, name, payload))
return; return;
@@ -38,7 +38,8 @@ public sealed class EntityCreateOperation : IRagonOperation
Type = entityType, Type = entityType,
Authority = eventAuthority, Authority = eventAuthority,
AttachId = attachId, AttachId = attachId,
StaticId = 0 StaticId = 0,
BufferedEvents = context.Configuration.LimitBufferedEvents,
}; };
var entity = new RagonEntity(entityParameters); var entity = new RagonEntity(entityParameters);
@@ -9,11 +9,11 @@ public sealed class EntityOwnershipOperation : IRagonOperation
public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer) public void Handle(RagonContext context, RagonBuffer reader, RagonBuffer writer)
{ {
var player = context.RoomPlayer; var currentOwner = context.RoomPlayer;
var room = context.Room; var room = context.Room;
var entityId = reader.ReadUShort(); var entityId = reader.ReadUShort();
var playerId = reader.ReadUShort(); var playerPeerId = reader.ReadUShort();
if (!room.Entities.TryGetValue(entityId, out var entity)) if (!room.Entities.TryGetValue(entityId, out var entity))
{ {
@@ -21,29 +21,33 @@ public sealed class EntityOwnershipOperation : IRagonOperation
return; return;
} }
if (entity.Owner.Connection.Id != player.Connection.Id) if (entity.Owner.Connection.Id != currentOwner.Connection.Id)
{ {
_logger.Error($"Player not owner of entity with id {entityId}"); _logger.Error($"Player not owner of entity with id {entityId}");
return; return;
} }
if (!room.Players.TryGetValue(playerId, out var nextOwner)) if (!room.Players.TryGetValue(playerPeerId, out var nextOwner))
{ {
_logger.Error($"Player not found with id {entityId}"); _logger.Error($"Player not found with id {entityId}");
return; return;
} }
writer.Clear(); currentOwner.Entities.Remove(entity);
writer.WriteOperation(RagonOperation.OWNERSHIP_ENTITY_CHANGED);
writer.WriteUShort(nextOwner.Connection.Id);
writer.WriteUShort(1);
writer.WriteUShort(entity.Id);
player.Entities.Remove(entity);
nextOwner.Entities.Add(entity); nextOwner.Entities.Add(entity);
entity.Attach(nextOwner); entity.Attach(nextOwner);
_logger.Trace($"Entity {entity.Id} next owner {nextOwner.Connection.Id}"); _logger.Trace($"Entity {entity.Id} next owner {nextOwner.Connection.Id}");
writer.Clear();
writer.WriteOperation(RagonOperation.OWNERSHIP_ENTITY_CHANGED);
writer.WriteUShort(playerPeerId);
writer.WriteUShort(1);
writer.WriteUShort(entity.Id);
var sendData = writer.ToArray();
foreach (var player in room.PlayerList)
player.Connection.Reliable.Send(sendData);
} }
} }
+1 -1
View File
@@ -91,7 +91,7 @@ public class RagonHttpServer
} }
} }
public void Start(Configuration configuration) public void Start(RagonServerConfiguration configuration)
{ {
_cancellationTokenSource = new CancellationTokenSource(); _cancellationTokenSource = new CancellationTokenSource();
_logger.Info($"Listen at http://0.0.0.0:{configuration.HttpPort}/"); _logger.Info($"Listen at http://0.0.0.0:{configuration.HttpPort}/");
@@ -31,7 +31,7 @@ public class RagonWebHookPlugin
private RagonServer _server; private RagonServer _server;
private HttpClient _httpClient; private HttpClient _httpClient;
public RagonWebHookPlugin(RagonServer server, Configuration configuration) public RagonWebHookPlugin(RagonServer server, RagonServerConfiguration configuration)
{ {
_webHooks = new Dictionary<string, string>(configuration.WebHooks); _webHooks = new Dictionary<string, string>(configuration.WebHooks);
_httpClient = new HttpClient(); _httpClient = new HttpClient();
+3 -1
View File
@@ -26,7 +26,7 @@ public class RagonContext
public ConnectionStatus ConnectionStatus { get; set; } public ConnectionStatus ConnectionStatus { get; set; }
public INetworkConnection Connection { get; } public INetworkConnection Connection { get; }
public IExecutor Executor { get; private set; } public IExecutor Executor { get; private set; }
public RagonServerConfiguration Configuration { get; private set; }
public IRagonLobby Lobby { get; private set; } public IRagonLobby Lobby { get; private set; }
public RagonLobbyPlayer? LobbyPlayer { get; private set; } public RagonLobbyPlayer? LobbyPlayer { get; private set; }
@@ -37,11 +37,13 @@ public class RagonContext
public RagonContext( public RagonContext(
INetworkConnection connection, INetworkConnection connection,
RagonServerConfiguration configuration,
IExecutor executor, IExecutor executor,
IRagonLobby lobby, IRagonLobby lobby,
RagonScheduler scheduler) RagonScheduler scheduler)
{ {
ConnectionStatus = ConnectionStatus.Unauthorized; ConnectionStatus = ConnectionStatus.Unauthorized;
Configuration = configuration;
Connection = connection; Connection = connection;
Executor = executor; Executor = executor;
Lobby = lobby; Lobby = lobby;
+4 -4
View File
@@ -36,7 +36,7 @@ public class RagonServer : IRagonServer, INetworkListener
private readonly IServerPlugin _serverPlugin; private readonly IServerPlugin _serverPlugin;
private readonly Thread _dedicatedThread; private readonly Thread _dedicatedThread;
private readonly Executor _executor; private readonly Executor _executor;
private readonly Configuration _configuration; private readonly RagonServerConfiguration _configuration;
private readonly RagonWebHookPlugin _webhooks; private readonly RagonWebHookPlugin _webhooks;
private readonly RagonHttpServer _httpServer; private readonly RagonHttpServer _httpServer;
private readonly RagonBuffer _reader; private readonly RagonBuffer _reader;
@@ -50,7 +50,7 @@ public class RagonServer : IRagonServer, INetworkListener
public RagonServer( public RagonServer(
INetworkServer server, INetworkServer server,
IServerPlugin plugin, IServerPlugin plugin,
Configuration configuration) RagonServerConfiguration configuration)
{ {
_server = server; _server = server;
_executor = _server.Executor; _executor = _server.Executor;
@@ -74,7 +74,7 @@ public class RagonServer : IRagonServer, INetworkListener
_serverPlugin.OnAttached(this); _serverPlugin.OnAttached(this);
_handlers = new IRagonOperation[byte.MaxValue]; _handlers = new IRagonOperation[byte.MaxValue];
_handlers[(byte) RagonOperation.AUTHORIZE] = new AuthorizationOperation(_webhooks, contextObserver, _writer, configuration); _handlers[(byte) RagonOperation.AUTHORIZE] = new AuthorizationOperation(_webhooks, contextObserver, _writer);
_handlers[(byte) RagonOperation.JOIN_OR_CREATE_ROOM] = new RoomJoinOrCreateOperation(plugin, _webhooks); _handlers[(byte) RagonOperation.JOIN_OR_CREATE_ROOM] = new RoomJoinOrCreateOperation(plugin, _webhooks);
_handlers[(byte) RagonOperation.CREATE_ROOM] = new RoomCreateOperation(plugin, _webhooks); _handlers[(byte) RagonOperation.CREATE_ROOM] = new RoomCreateOperation(plugin, _webhooks);
_handlers[(byte) RagonOperation.JOIN_ROOM] = new RoomJoinOperation(_webhooks); _handlers[(byte) RagonOperation.JOIN_ROOM] = new RoomJoinOperation(_webhooks);
@@ -136,7 +136,7 @@ public class RagonServer : IRagonServer, INetworkListener
public void OnConnected(INetworkConnection connection) public void OnConnected(INetworkConnection connection)
{ {
var context = new RagonContext(connection, _executor, _lobby, _scheduler); var context = new RagonContext(connection, _configuration, _executor, _lobby, _scheduler);
_logger.Trace($"Connected: {connection.Id}"); _logger.Trace($"Connected: {connection.Id}");
_contextsByConnection.Add(connection.Id, context); _contextsByConnection.Add(connection.Id, context);
@@ -31,7 +31,7 @@ public class WebHook
} }
[Serializable] [Serializable]
public struct Configuration public struct RagonServerConfiguration
{ {
public string ServerKey; public string ServerKey;
public string ServerType; public string ServerType;
@@ -43,6 +43,7 @@ public struct Configuration
public int LimitConnections; public int LimitConnections;
public int LimitPlayersPerRoom; public int LimitPlayersPerRoom;
public int LimitRooms; public int LimitRooms;
public int LimitBufferedEvents;
public Dictionary<string, string> WebHooks; public Dictionary<string, string> WebHooks;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@@ -53,12 +54,12 @@ public struct Configuration
{"websocket", Server.ServerType.WEBSOCKET} {"websocket", Server.ServerType.WEBSOCKET}
}; };
public static Configuration Load(string filePath) public static RagonServerConfiguration Load(string filePath)
{ {
CopyrightInfo(); CopyrightInfo();
var data = File.ReadAllText(filePath); var data = File.ReadAllText(filePath);
var configuration = JsonConvert.DeserializeObject<Configuration>(data); var configuration = JsonConvert.DeserializeObject<RagonServerConfiguration>(data);
return configuration; return configuration;
} }
+1 -1
View File
@@ -6,7 +6,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Protocol", "Ragon.Pro
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server", "Ragon.Server\Ragon.Server.csproj", "{F4AA86B9-2486-4B53-BA77-43D958A2FDC3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server", "Ragon.Server\Ragon.Server.csproj", "{F4AA86B9-2486-4B53-BA77-43D958A2FDC3}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.DotNetWebSockets", "Ragon.Server.DotNetWebSockets\Ragon.Server.DotNetWebSockets.csproj", "{81050343-A9B8-487B-86C8-7A5B7DD9C39B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.WebSocketServer", "Ragon.Server.WebSocketServer\Ragon.Server.WebSocketServer.csproj", "{81050343-A9B8-487B-86C8-7A5B7DD9C39B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.ENet", "Ragon.Server.ENet\Ragon.Server.ENet.csproj", "{DD79AC4F-9E5C-4938-850E-805D537E68D0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.ENet", "Ragon.Server.ENet\Ragon.Server.ENet.csproj", "{DD79AC4F-9E5C-4938-850E-805D537E68D0}"
EndProject EndProject