feat: websockets
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Diagnostics;
|
||||
using NLog;
|
||||
using Ragon.Common;
|
||||
using Ragon.Core.Lobby;
|
||||
using Ragon.Core.Server;
|
||||
using Ragon.Core.Time;
|
||||
using Ragon.Server;
|
||||
using Ragon.Server.ENet;
|
||||
@@ -13,6 +14,7 @@ public class Application : INetworkListener
|
||||
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
private readonly INetworkServer _server;
|
||||
private readonly Thread _dedicatedThread;
|
||||
private readonly Executor _executor;
|
||||
private readonly Configuration _configuration;
|
||||
private readonly HandlerRegistry _handlerRegistry;
|
||||
private readonly ILobby _lobby;
|
||||
@@ -22,6 +24,7 @@ public class Application : INetworkListener
|
||||
public Application(Configuration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_executor = new Executor();
|
||||
_dedicatedThread = new Thread(Execute);
|
||||
_dedicatedThread.IsBackground = true;
|
||||
_contexts = new Dictionary<ushort, PlayerContext>();
|
||||
@@ -29,20 +32,24 @@ public class Application : INetworkListener
|
||||
_lobby = new LobbyInMemory();
|
||||
_loop = new Loop();
|
||||
|
||||
if (configuration.Socket == "enet")
|
||||
if (configuration.ServerType == "enet")
|
||||
_server = new ENetServer();
|
||||
|
||||
if (configuration.ServerType == "websocket")
|
||||
_server = new NativeWebSocketServer(_executor);
|
||||
|
||||
Debug.Assert(_server != null, $"Socket type not supported: {configuration.Socket}. Supported: [enet, websocket]");
|
||||
Debug.Assert(_server != null, $"Socket type not supported: {configuration.ServerType}. Supported: [enet, websocket]");
|
||||
}
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_executor.Execute();
|
||||
_loop.Tick();
|
||||
_server.Poll();
|
||||
|
||||
Thread.Sleep((int) 1000.0f / _configuration.SendRate);
|
||||
|
||||
Thread.Sleep((int)1000.0f / _configuration.ServerTickRate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +58,7 @@ public class Application : INetworkListener
|
||||
var networkConfiguration = new NetworkConfiguration()
|
||||
{
|
||||
LimitConnections = _configuration.LimitConnections,
|
||||
Protocol = RagonVersion.Parse(_configuration.Protocol),
|
||||
Protocol = RagonVersion.Parse(_configuration.GameProtocol),
|
||||
Address = "0.0.0.0",
|
||||
Port = _configuration.Port,
|
||||
};
|
||||
@@ -86,9 +93,10 @@ public class Application : INetworkListener
|
||||
if (room != null)
|
||||
{
|
||||
room.RemovePlayer(context.RoomPlayer);
|
||||
|
||||
|
||||
_lobby.RemoveIfEmpty(room);
|
||||
}
|
||||
|
||||
context.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,11 @@ namespace Ragon.Core;
|
||||
[Serializable]
|
||||
public struct Configuration
|
||||
{
|
||||
public string Key;
|
||||
public string Protocol;
|
||||
public string Socket;
|
||||
public ushort SendRate;
|
||||
public string ServerKey;
|
||||
public string ServerType;
|
||||
public ushort ServerTickRate;
|
||||
public string GameProtocol;
|
||||
public ushort Port;
|
||||
public int SkipTimeout;
|
||||
public int ReconnectTimeout;
|
||||
public int LimitConnections;
|
||||
public int LimitPlayersPerRoom;
|
||||
public int LimitRooms;
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using NLog.LayoutRenderers.Wrappers;
|
||||
|
||||
namespace Ragon.Core;
|
||||
|
||||
public class Executor: TaskScheduler
|
||||
{
|
||||
private ChannelReader<Task> _reader;
|
||||
private ChannelWriter<Task> _writer;
|
||||
private Queue<Task> _pendingTasks;
|
||||
|
||||
public void Run(Task task)
|
||||
{
|
||||
task.Start(this);
|
||||
}
|
||||
|
||||
public Executor()
|
||||
{
|
||||
var channel = Channel.CreateUnbounded<Task>();
|
||||
_reader = channel.Reader;
|
||||
_writer = channel.Writer;
|
||||
|
||||
_pendingTasks = new Queue<Task>();
|
||||
}
|
||||
|
||||
protected override IEnumerable<Task>? GetScheduledTasks()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
protected override void QueueTask(Task task)
|
||||
{
|
||||
_writer.TryWrite(task);
|
||||
}
|
||||
|
||||
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
while (_reader.TryRead(out var task))
|
||||
{
|
||||
TryExecuteTask(task);
|
||||
|
||||
if (task.Status == TaskStatus.Running)
|
||||
_pendingTasks.Enqueue(task);
|
||||
}
|
||||
|
||||
while (_pendingTasks.TryDequeue(out var task))
|
||||
_writer.TryWrite(task);
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class Entity
|
||||
writer.WriteData(ref data);
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
roomPlayer.Connection.ReliableChannel.Send(sendData);
|
||||
roomPlayer.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,14 +68,14 @@ public class Entity
|
||||
serializer.WriteUShort(Type);
|
||||
serializer.WriteUShort(Id);
|
||||
serializer.WriteUShort(Owner.Connection.Id);
|
||||
|
||||
|
||||
ReadOnlySpan<byte> entityPayload = Payload.AsSpan();
|
||||
serializer.WriteUShort((ushort)entityPayload.Length);
|
||||
serializer.WriteData(ref entityPayload);
|
||||
|
||||
var sendData = serializer.ToArray();
|
||||
foreach (var player in room.ReadyPlayersList)
|
||||
player.Connection.ReliableChannel.Send(sendData);
|
||||
player.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
|
||||
public void Destroy(byte[] payload)
|
||||
@@ -91,7 +91,7 @@ public class Entity
|
||||
|
||||
var sendData = serializer.ToArray();
|
||||
foreach (var player in room.ReadyPlayersList)
|
||||
player.Connection.ReliableChannel.Send(sendData);
|
||||
player.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
|
||||
public void ReplicateEvent(
|
||||
@@ -114,7 +114,7 @@ public class Entity
|
||||
serializer.WriteData(ref payload);
|
||||
|
||||
var sendData = serializer.ToArray();
|
||||
targetPlayer.Connection.ReliableChannel.Send(sendData);
|
||||
targetPlayer.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
|
||||
public void ReplicateEvent(
|
||||
@@ -155,7 +155,7 @@ public class Entity
|
||||
{
|
||||
case RagonTarget.Owner:
|
||||
{
|
||||
Owner.Connection.ReliableChannel.Send(sendData);
|
||||
Owner.Connection.Reliable.Send(sendData);
|
||||
break;
|
||||
}
|
||||
case RagonTarget.ExceptOwner:
|
||||
@@ -163,7 +163,7 @@ public class Entity
|
||||
foreach (var roomPlayer in room.ReadyPlayersList)
|
||||
{
|
||||
if (roomPlayer.Connection.Id != Owner.Connection.Id)
|
||||
roomPlayer.Connection.ReliableChannel.Send(sendData);
|
||||
roomPlayer.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -173,7 +173,7 @@ public class Entity
|
||||
foreach (var roomPlayer in room.ReadyPlayersList)
|
||||
{
|
||||
if (roomPlayer.Connection.Id != caller.Connection.Id)
|
||||
roomPlayer.Connection.ReliableChannel.Send(sendData);
|
||||
roomPlayer.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -181,7 +181,7 @@ public class Entity
|
||||
case RagonTarget.All:
|
||||
{
|
||||
foreach (var roomPlayer in room.ReadyPlayersList)
|
||||
roomPlayer.Connection.ReliableChannel.Send(sendData);
|
||||
roomPlayer.Connection.Reliable.Send(sendData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class Room: IAction
|
||||
|
||||
var sendData = Writer.ToArray();
|
||||
foreach (var roomPlayer in ReadyPlayersList)
|
||||
roomPlayer.Connection.UnreliableChannel.Send(sendData);
|
||||
roomPlayer.Connection.Unreliable.Send(sendData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,6 @@ public class Room: IAction
|
||||
public void Broadcast(byte[] data)
|
||||
{
|
||||
foreach (var readyPlayer in ReadyPlayersList)
|
||||
readyPlayer.Connection.ReliableChannel.Send(data);
|
||||
readyPlayer.Connection.Reliable.Send(data);
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public sealed class AuthorizationHandler: IHandler
|
||||
writer.WriteString(playerName);
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
context.Connection.ReliableChannel.Send(sendData);
|
||||
context.Connection.Reliable.Send(sendData);
|
||||
|
||||
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} authorized");
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public sealed class CreateHandler: IHandler
|
||||
writer.WriteString($"Room with id {roomId} already exists");
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
context.Connection.ReliableChannel.Send(sendData);
|
||||
context.Connection.Reliable.Send(sendData);
|
||||
|
||||
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} join failed to room {roomId}, room already exist");
|
||||
return;
|
||||
@@ -79,6 +79,6 @@ public sealed class CreateHandler: IHandler
|
||||
writer.WriteString(room.Info.Map);
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
player.Connection.ReliableChannel.Send(sendData);
|
||||
player.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public sealed class JoinHandler : IHandler
|
||||
writer.WriteString(room.Info.Map);
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
player.Connection.ReliableChannel.Send(sendData);
|
||||
player.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
|
||||
private void JoinFailed(LobbyPlayer player, RagonSerializer writer)
|
||||
@@ -57,6 +57,6 @@ public sealed class JoinHandler : IHandler
|
||||
writer.WriteString($"Room not exists");
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
player.Connection.ReliableChannel.Send(sendData);
|
||||
player.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public sealed class JoinOrCreateHandler : IHandler
|
||||
writer.WriteString(room.Info.Map);
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
player.Connection.ReliableChannel.Send(sendData);
|
||||
player.Connection.Reliable.Send(sendData);
|
||||
|
||||
_logger.Trace($"Joined to room {room.Id}");
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public sealed class SceneLoadedHandler : IHandler
|
||||
foreach (var awaiter in room.ReadyPlayersList)
|
||||
{
|
||||
if (awaiter != roomPlayer)
|
||||
awaiter.Connection.ReliableChannel.Send(sendData);
|
||||
awaiter.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,6 @@ public sealed class SceneLoadedHandler : IHandler
|
||||
|
||||
var sendData = writer.ToArray();
|
||||
foreach (var player in receviersList)
|
||||
player.Connection.ReliableChannel.Send(sendData);
|
||||
player.Connection.Reliable.Send(sendData);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ragon.Protocol\Ragon.Protocol.csproj" />
|
||||
<ProjectReference Include="..\Ragon.Server.ENet\Ragon.Server.ENet.csproj" />
|
||||
<ProjectReference Include="..\Ragon.Server.WebSockets\Ragon.Server.WebSockets.csproj" />
|
||||
<ProjectReference Include="..\Ragon.Server.NativeWebSockets\Ragon.Server.NativeWebSockets.csproj" />
|
||||
<ProjectReference Include="..\Ragon.Server\Ragon.Server.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user