refactoring: heap -> span
This commit is contained in:
@@ -19,4 +19,8 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Source\Events" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using Game.Source;
|
using Game.Source;
|
||||||
using NetStack.Serialization;
|
using NetStack.Serialization;
|
||||||
using Ragon.Core;
|
using Ragon.Core;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Ragon.Core;
|
||||||
|
|
||||||
|
namespace Game.Source;
|
||||||
|
|
||||||
|
public class GameAuthorizer: AuthorizationManager
|
||||||
|
{
|
||||||
|
public override bool OnAuthorize(uint peerId, byte[] payload)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Ragon.Core;
|
||||||
|
|
||||||
|
namespace Game.Source
|
||||||
|
{
|
||||||
|
public class GameFactory : PluginFactory
|
||||||
|
{
|
||||||
|
public string PluginName { get; set; } = "ExamplePlugin";
|
||||||
|
public PluginBase CreatePlugin(string map) => new ExamplePlugin();
|
||||||
|
public AuthorizationManager CreateManager() => new GameAuthorizer();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,14 @@
|
|||||||
using Game.Source.Events;
|
using NLog;
|
||||||
using NLog;
|
|
||||||
using Ragon.Core;
|
using Ragon.Core;
|
||||||
|
|
||||||
namespace Game.Source
|
namespace Game.Source
|
||||||
{
|
{
|
||||||
public class SpawnPlugin: PluginBase
|
public class ExamplePlugin: PluginBase
|
||||||
{
|
{
|
||||||
private ILogger _logger = LogManager.GetCurrentClassLogger();
|
private ILogger _logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public void SpawnEvent(SpawnEvent evnt)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
public override void OnStart()
|
public override void OnStart()
|
||||||
{
|
{
|
||||||
Subscribe<SpawnEvent>(SpawnEvent);
|
|
||||||
|
|
||||||
_logger.Info("Plugin started");
|
_logger.Info("Plugin started");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"apiKey": "123",
|
||||||
"server": {
|
"server": {
|
||||||
"port": 4444,
|
"port": 4444,
|
||||||
"skipTimeout": 60
|
"skipTimeout": 60
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NetStack.Serialization;
|
|
||||||
|
|
||||||
namespace Ragon.Common
|
|
||||||
{
|
|
||||||
public static class BitBufferExtension
|
|
||||||
{
|
|
||||||
public static BitBuffer AddBytes(this BitBuffer buffer, byte[] data)
|
|
||||||
{
|
|
||||||
buffer.AddInt(data.Length);
|
|
||||||
foreach (var b in data)
|
|
||||||
buffer.AddByte(b);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] ReadBytes(this BitBuffer buffer)
|
|
||||||
{
|
|
||||||
var size = buffer.ReadInt();
|
|
||||||
var data = new byte[size];
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
while (i < size)
|
|
||||||
data[i] = buffer.ReadByte();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
using NetStack.Serialization;
|
|
||||||
|
|
||||||
namespace Ragon.Core
|
|
||||||
{
|
|
||||||
|
|
||||||
public class AuthorationData : IData
|
|
||||||
{
|
|
||||||
public string Login { get; set; }
|
|
||||||
public string Password { get; set; }
|
|
||||||
|
|
||||||
public void Serialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
buffer.AddString(Login);
|
|
||||||
buffer.AddString(Password);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Deserialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
Login = buffer.ReadString();
|
|
||||||
Password = buffer.ReadString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using NetStack.Serialization;
|
|
||||||
|
|
||||||
namespace Ragon.Core
|
|
||||||
{
|
|
||||||
public class FindAndJoinData: IData
|
|
||||||
{
|
|
||||||
public string Map;
|
|
||||||
|
|
||||||
public void Serialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
buffer.AddString(Map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Deserialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
Map = buffer.ReadString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using NetStack.Serialization;
|
|
||||||
|
|
||||||
namespace Ragon.Core
|
|
||||||
{
|
|
||||||
public class SceneLoadData: IData
|
|
||||||
{
|
|
||||||
public string Scene;
|
|
||||||
|
|
||||||
public void Serialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
buffer.AddString(Scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Deserialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
Scene = buffer.ReadString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
using NetStack.Serialization;
|
|
||||||
using Ragon.Common;
|
|
||||||
|
|
||||||
namespace Ragon.Core
|
|
||||||
{
|
|
||||||
|
|
||||||
public class EntityData: IData
|
|
||||||
{
|
|
||||||
public int EntityId;
|
|
||||||
public byte[] State;
|
|
||||||
public void Serialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
buffer.AddInt(EntityId);
|
|
||||||
buffer.AddBytes(State);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Deserialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
EntityId = buffer.ReadInt();
|
|
||||||
State = buffer.ReadBytes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class SnapshotData: IData
|
|
||||||
{
|
|
||||||
public EntityData[] Entities;
|
|
||||||
public void Serialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
buffer.AddInt(Entities.Length);
|
|
||||||
foreach (var entityData in Entities)
|
|
||||||
entityData.Serialize(buffer);
|
|
||||||
}
|
|
||||||
public void Deserialize(BitBuffer buffer)
|
|
||||||
{
|
|
||||||
var entitiesSize = buffer.ReadInt();
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
Entities = new EntityData[entitiesSize];
|
|
||||||
while (i < entitiesSize)
|
|
||||||
{
|
|
||||||
Entities[i] = new EntityData();
|
|
||||||
Entities[i].Deserialize(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@ using NetStack.Serialization;
|
|||||||
|
|
||||||
namespace Ragon.Core
|
namespace Ragon.Core
|
||||||
{
|
{
|
||||||
public interface IData
|
public interface IPacket
|
||||||
{
|
{
|
||||||
public void Serialize(BitBuffer buffer);
|
public void Serialize(BitBuffer buffer);
|
||||||
public void Deserialize(BitBuffer buffer);
|
public void Deserialize(BitBuffer buffer);
|
||||||
@@ -12,8 +12,8 @@ namespace Ragon.Common.Protocol
|
|||||||
LOAD_SCENE,
|
LOAD_SCENE,
|
||||||
SCENE_IS_LOADED,
|
SCENE_IS_LOADED,
|
||||||
|
|
||||||
PLAYER_CONNECTED,
|
PLAYER_JOINED,
|
||||||
PLAYER_DISCONNECTED,
|
PLAYER_LEAVED,
|
||||||
|
|
||||||
CREATE_ENTITY,
|
CREATE_ENTITY,
|
||||||
DESTROY_ENTITY,
|
DESTROY_ENTITY,
|
||||||
@@ -24,6 +24,7 @@ namespace Ragon.Common.Protocol
|
|||||||
|
|
||||||
REPLICATE_ENTITY_STATE,
|
REPLICATE_ENTITY_STATE,
|
||||||
REPLICATE_ENTITY_PROPERTY,
|
REPLICATE_ENTITY_PROPERTY,
|
||||||
|
REPLICATE_ENTITY_EVENT,
|
||||||
REPLICATE_EVENT,
|
REPLICATE_EVENT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using NetStack.Buffers;
|
||||||
|
|
||||||
|
namespace Ragon.Core
|
||||||
|
{
|
||||||
|
public static class ProtocolHeader
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void WriteUShort(ushort id, ref Span<byte> data) {
|
||||||
|
data[0] = (byte)(id & 0x00FF);
|
||||||
|
data[1] = (byte)((id & 0xFF00) >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static ushort ReadUShort(ref ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
return (ushort)(data[0] + (data[1] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void WriteInt(int id, ref Span<byte> data) {
|
||||||
|
data[0] = (byte)(id & 0x00FF);
|
||||||
|
data[1] = (byte)((id & 0xFF00) >> 8);
|
||||||
|
data[2] = (byte)((id & 0xFF00) >> 16);
|
||||||
|
data[3] = (byte)((id & 0xFF00) >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int ReadInt(ref ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
return (ushort)(data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using NetStack.Buffers;
|
|
||||||
|
|
||||||
namespace Ragon.Common.Protocol
|
|
||||||
{
|
|
||||||
public static class ProtocolHeader
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static void WriteOperation(ushort id, byte[] data) {
|
|
||||||
data[0] = (byte)(id & 0x00FF);
|
|
||||||
data[1] = (byte)((id & 0xFF00) >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static ushort ReadOperation(byte[] data, int offset = 0)
|
|
||||||
{
|
|
||||||
return (ushort)(data[offset] + (data[offset + 1] << 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static void WriteEntity(int id, byte[] data, int offset = 2) {
|
|
||||||
data[offset] = (byte)(id & 0x00FF);
|
|
||||||
data[offset + 1] = (byte)((id & 0xFF00) >> 8);
|
|
||||||
data[offset + 2] = (byte)((id & 0xFF00) >> 16);
|
|
||||||
data[offset + 3] = (byte)((id & 0xFF00) >> 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int ReadEntity(byte[] data, int offset = 2)
|
|
||||||
{
|
|
||||||
return (ushort)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int ReadProperty(byte[] data, int offset = 2)
|
|
||||||
{
|
|
||||||
return ReadEntity(data, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteProperty(int id, byte[] data)
|
|
||||||
{
|
|
||||||
WriteEntity(id, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int ReadEvent(byte[] data, int offset = 2)
|
|
||||||
{
|
|
||||||
return ReadEntity(data, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteEvent(int id, byte[] data)
|
|
||||||
{
|
|
||||||
WriteEntity(id, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,10 +11,12 @@
|
|||||||
<OutputPath>/Users/edmand46/UnityProjects/ragon-client/Assets/RagonSDK/</OutputPath>
|
<OutputPath>/Users/edmand46/UnityProjects/ragon-client/Assets/RagonSDK/</OutputPath>
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>false</DebugSymbols>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<DefineConstants>TRACE;NETSTACK_SPAN</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
<OutputPath>/Users/edmand46/UnityProjects/ragon-client/Assets/RagonSDK/</OutputPath>
|
<OutputPath>/Users/edmand46/UnityProjects/ragon-client/Assets/RagonSDK/</OutputPath>
|
||||||
|
<DefineConstants>TRACE;NETSTACK_SPAN</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon", "Ragon\Ragon.csproj", "{BABA1AF0-CF91-43F2-9577-53800068ACCF}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon", "Ragon\Ragon.csproj", "{BABA1AF0-CF91-43F2-9577-53800068ACCF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YohohoArenaPlugin", "YohohoArenaPlugin\YohohoArenaPlugin.csproj", "{C2B87ADE-A122-4366-8EB7-24DAE11EBAF0}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Game", "Game\Game.csproj", "{C2B87ADE-A122-4366-8EB7-24DAE11EBAF0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Common", "Ragon.Common\Ragon.Common.csproj", "{F478B2A2-36F4-43B9-9BB7-382A57C449B2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Common", "Ragon.Common\Ragon.Common.csproj", "{F478B2A2-36F4-43B9-9BB7-382A57C449B2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@@ -6,6 +6,16 @@
|
|||||||
<TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<DefineConstants>TRACE;NETSTACK_SPAN</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<DefineConstants>TRACE;NETSTACK_SPAN</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ENet-CSharp" Version="2.4.8" />
|
<PackageReference Include="ENet-CSharp" Version="2.4.8" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
@@ -16,4 +26,8 @@
|
|||||||
<ProjectReference Include="..\Ragon.Common\Ragon.Common.csproj" />
|
<ProjectReference Include="..\Ragon.Common\Ragon.Common.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Sources\Protocol" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=sources/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ragon.Core;
|
||||||
|
|
||||||
|
public class AuthorizationManager
|
||||||
|
{
|
||||||
|
public virtual bool OnAuthorize(uint peerId, byte[] payload)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
{
|
{
|
||||||
public class Configuration
|
public class Configuration
|
||||||
{
|
{
|
||||||
public string[] blacklist;
|
public int UdpPort;
|
||||||
|
public int WsPort;
|
||||||
|
public string Transport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+16
-16
@@ -5,7 +5,6 @@ using System.Threading;
|
|||||||
using DisruptorUnity3d;
|
using DisruptorUnity3d;
|
||||||
using ENet;
|
using ENet;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.LayoutRenderers.Wrappers;
|
|
||||||
|
|
||||||
namespace Ragon.Core
|
namespace Ragon.Core
|
||||||
{
|
{
|
||||||
@@ -19,15 +18,6 @@ namespace Ragon.Core
|
|||||||
Connected
|
Connected
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeliveryType
|
|
||||||
{
|
|
||||||
UnreliableUnsequenced,
|
|
||||||
UnreliableSequenced,
|
|
||||||
UnreliableFragmented,
|
|
||||||
ReliableSequenced
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class ENetServer : IDisposable
|
public class ENetServer : IDisposable
|
||||||
{
|
{
|
||||||
public Status Status { get; private set; }
|
public Status Status { get; private set; }
|
||||||
@@ -70,11 +60,25 @@ namespace Ragon.Core
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (_sendBuffer.TryDequeue(out var data))
|
while (_sendBuffer.TryDequeue(out var data))
|
||||||
|
{
|
||||||
|
if (data.Type == EventType.DATA)
|
||||||
{
|
{
|
||||||
var newPacket = new Packet();
|
var newPacket = new Packet();
|
||||||
newPacket.Create(data.Data, data.Data.Length, PacketFlags.Reliable);
|
|
||||||
|
var packetFlags = PacketFlags.Instant;
|
||||||
|
if (data.Delivery == DeliveryType.Reliable)
|
||||||
|
packetFlags = PacketFlags.Reliable;
|
||||||
|
else if (data.Delivery == DeliveryType.Unreliable)
|
||||||
|
packetFlags = PacketFlags.Instant;
|
||||||
|
|
||||||
|
newPacket.Create(data.Data, data.Data.Length, packetFlags);
|
||||||
_peers[data.PeerId].Send(0, ref newPacket);
|
_peers[data.PeerId].Send(0, ref newPacket);
|
||||||
}
|
}
|
||||||
|
else if (data.Type == EventType.DISCONNECTED)
|
||||||
|
{
|
||||||
|
_peers[data.PeerId].DisconnectNow(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool polled = false;
|
bool polled = false;
|
||||||
while (!polled)
|
while (!polled)
|
||||||
@@ -96,7 +100,6 @@ namespace Ragon.Core
|
|||||||
case ENet.EventType.Connect:
|
case ENet.EventType.Connect:
|
||||||
{
|
{
|
||||||
var @event = new Event {PeerId = _netEvent.Peer.ID, Type = EventType.CONNECTED};
|
var @event = new Event {PeerId = _netEvent.Peer.ID, Type = EventType.CONNECTED};
|
||||||
// Console.WriteLine("Client connected - ID: " + _netEvent.Peer.ID + ", IP: " + _netEvent.Peer.IP);
|
|
||||||
_peers[_netEvent.Peer.ID] = _netEvent.Peer;
|
_peers[_netEvent.Peer.ID] = _netEvent.Peer;
|
||||||
_receiveBuffer.Enqueue(@event);
|
_receiveBuffer.Enqueue(@event);
|
||||||
break;
|
break;
|
||||||
@@ -104,22 +107,19 @@ namespace Ragon.Core
|
|||||||
case ENet.EventType.Disconnect:
|
case ENet.EventType.Disconnect:
|
||||||
{
|
{
|
||||||
var @event = new Event {PeerId = _netEvent.Peer.ID, Type = EventType.DISCONNECTED};
|
var @event = new Event {PeerId = _netEvent.Peer.ID, Type = EventType.DISCONNECTED};
|
||||||
// Console.WriteLine("Client disconnected - ID: " + _netEvent.Peer.ID + ", IP: " + _netEvent.Peer.IP);
|
|
||||||
_receiveBuffer.Enqueue(@event);
|
_receiveBuffer.Enqueue(@event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENet.EventType.Timeout:
|
case ENet.EventType.Timeout:
|
||||||
{
|
{
|
||||||
// Console.WriteLine("Client timeout - ID: " + _netEvent.Peer.ID + ", IP: " + _netEvent.Peer.IP);
|
|
||||||
var @event = new Event {PeerId = _netEvent.Peer.ID, Type = EventType.TIMEOUT};
|
var @event = new Event {PeerId = _netEvent.Peer.ID, Type = EventType.TIMEOUT};
|
||||||
// Console.WriteLine("Client disconnected - ID: " + _netEvent.Peer.ID + ", IP: " + _netEvent.Peer.IP);
|
|
||||||
_receiveBuffer.Enqueue(@event);
|
_receiveBuffer.Enqueue(@event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENet.EventType.Receive:
|
case ENet.EventType.Receive:
|
||||||
{
|
{
|
||||||
// Console.WriteLine("Packet received from - ID: " + _netEvent.Peer.ID + ", IP: " + _netEvent.Peer.IP + ", Channel ID: " + _netEvent.ChannelID + ", Data length: " + _netEvent.Packet.Length);
|
|
||||||
var data = new byte[_netEvent.Packet.Length];
|
var data = new byte[_netEvent.Packet.Length];
|
||||||
|
|
||||||
_netEvent.Packet.CopyTo(data);
|
_netEvent.Packet.CopyTo(data);
|
||||||
_netEvent.Packet.Dispose();
|
_netEvent.Packet.Dispose();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Ragon.Core;
|
||||||
|
|
||||||
|
public enum DeliveryType
|
||||||
|
{
|
||||||
|
Unreliable,
|
||||||
|
Reliable
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace Ragon.Core
|
namespace Ragon.Core
|
||||||
{
|
{
|
||||||
public struct Event
|
public struct Event
|
||||||
{
|
{
|
||||||
public EventType Type;
|
public EventType Type;
|
||||||
|
public DeliveryType Delivery;
|
||||||
public uint PeerId;
|
public uint PeerId;
|
||||||
public byte[] Data;
|
public byte[] Data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.ExceptionServices;
|
||||||
|
using DisruptorUnity3d;
|
||||||
|
|
||||||
|
namespace Ragon.Core;
|
||||||
|
|
||||||
|
public class EventStream
|
||||||
|
{
|
||||||
|
private Stack<Event> _pool = new Stack<Event>(1024);
|
||||||
|
private RingBuffer<Event> _events = new RingBuffer<Event>(1024);
|
||||||
|
|
||||||
|
// public ref Event Reserve()
|
||||||
|
// {
|
||||||
|
// if (_pool.Count == 0)
|
||||||
|
// {
|
||||||
|
// var evnt = new Event();
|
||||||
|
// return ref evnt;
|
||||||
|
// }
|
||||||
|
// // var evnt = _pool.Pop();
|
||||||
|
// // ref Event evntRef = ref evnt;
|
||||||
|
// // return evntRef;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void Retain(ref Event @event)
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void WriteEvent(ref Event evnt)
|
||||||
|
// {
|
||||||
|
// // _pool.Push(evnt);
|
||||||
|
// _events.Enqueue(evnt);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public ref Event ReadEvent()
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -1,25 +1,121 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using NetStack.Serialization;
|
||||||
|
using Ragon.Common.Protocol;
|
||||||
|
|
||||||
namespace Ragon.Core
|
namespace Ragon.Core
|
||||||
{
|
{
|
||||||
public class PluginBase
|
public class PluginBase
|
||||||
{
|
{
|
||||||
static class Storage<T>
|
private delegate void SubscribeDelegate(Player player, ref ReadOnlySpan<byte> data);
|
||||||
|
private Dictionary<ushort, SubscribeDelegate> _subscribes = new();
|
||||||
|
private BitBuffer _buffer = new BitBuffer(1024);
|
||||||
|
|
||||||
|
protected Room Room { get; private set; }
|
||||||
|
|
||||||
|
public void Attach(Room room) => Room = room;
|
||||||
|
public void Detach() => _subscribes.Clear();
|
||||||
|
|
||||||
|
public void Subscribe<T>(ushort evntCode, Action<Player, T> action) where T: IPacket, new()
|
||||||
{
|
{
|
||||||
public static Dictionary<Room, Dictionary<ushort, Action<T>>> Subscribes = new();
|
var data = new T();
|
||||||
|
_subscribes.Add(evntCode, (Player player, ref ReadOnlySpan<byte> raw) =>
|
||||||
|
{
|
||||||
|
_buffer.Clear();
|
||||||
|
_buffer.FromSpan(ref raw, raw.Length);
|
||||||
|
data.Deserialize(_buffer);
|
||||||
|
action.Invoke(player, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void Subscribe<T>(RagonOperation operation, Action<Player, Span<byte> action) where T: IPacket, new()
|
||||||
|
// {
|
||||||
|
// var data = new T();
|
||||||
|
// _subscribes.Add(evntCode, (Player player, ref ReadOnlySpan<byte> raw) =>
|
||||||
|
// {
|
||||||
|
// _buffer.Clear();
|
||||||
|
// _buffer.FromSpan(ref raw, raw.Length);
|
||||||
|
// data.Deserialize(_buffer);
|
||||||
|
// action.Invoke(player, data);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
public void UnsubscribeAll()
|
||||||
|
{
|
||||||
|
_subscribes.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Room _room;
|
public bool InternalHandle(uint peerId, ushort evntCode, ref ReadOnlySpan<byte> payload)
|
||||||
// protected Dictionary<ushort, > _subscribes = new Dictionary<ushort,???>();
|
|
||||||
public void Attach(Room room) => _room = room;
|
|
||||||
|
|
||||||
public void Subscribe<T>(ushort evntCode, Action<T> val)
|
|
||||||
{
|
{
|
||||||
Storage<T>.Subscribes.Add(_room, val);
|
if (_subscribes.ContainsKey(evntCode))
|
||||||
|
{
|
||||||
|
var player = Room.GetPlayerByPeerId(peerId);
|
||||||
|
_subscribes[evntCode].Invoke(player, ref payload);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(Player player, RagonOperation operation, IPacket payload)
|
||||||
|
{
|
||||||
|
Send(player.PeerId, operation, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Broadcast(Player[] players, RagonOperation operation, IPacket payload)
|
||||||
|
{
|
||||||
|
var ids = new uint[players.Length];
|
||||||
|
for (int i = 0; i < players.Length; i++)
|
||||||
|
ids[i] = players[i].PeerId;
|
||||||
|
|
||||||
|
Broadcast(ids, operation, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(uint peerId, RagonOperation operation, IPacket payload)
|
||||||
|
{
|
||||||
|
_buffer.Clear();
|
||||||
|
|
||||||
|
payload.Serialize(_buffer);
|
||||||
|
|
||||||
|
Span<byte> data = stackalloc byte[_buffer.Length + 2];
|
||||||
|
Span<byte> bufferSpan = data.Slice(2, data.Length - 2);
|
||||||
|
|
||||||
|
_buffer.ToSpan(ref bufferSpan);
|
||||||
|
|
||||||
|
ProtocolHeader.WriteUShort((ushort) operation, ref data);
|
||||||
|
|
||||||
|
Room.Send(peerId, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Broadcast(uint[] peersIds, RagonOperation operation, IPacket payload)
|
||||||
|
{
|
||||||
|
_buffer.Clear();
|
||||||
|
payload.Serialize(_buffer);
|
||||||
|
|
||||||
|
Span<byte> data = stackalloc byte[_buffer.Length + 2];
|
||||||
|
Span<byte> bufferSpan = data.Slice(2, data.Length - 2);
|
||||||
|
|
||||||
|
_buffer.ToSpan(ref bufferSpan);
|
||||||
|
|
||||||
|
ProtocolHeader.WriteUShort((ushort) operation, ref data);
|
||||||
|
|
||||||
|
Room.Broadcast(peersIds, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region VIRTUAL
|
||||||
|
|
||||||
|
public virtual void OnRoomJoined()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnRoomLeaved()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void OnStart()
|
public virtual void OnStart()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -32,5 +128,7 @@ namespace Ragon.Core
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,10 @@ namespace Ragon.Core
|
|||||||
{
|
{
|
||||||
public interface PluginFactory
|
public interface PluginFactory
|
||||||
{
|
{
|
||||||
|
public string PluginName { get; set; }
|
||||||
public PluginBase CreatePlugin(string map);
|
public PluginBase CreatePlugin(string map);
|
||||||
|
public AuthorizationManager CreateManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+130
-137
@@ -1,9 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using NetStack.Serialization;
|
using NetStack.Serialization;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NLog.LayoutRenderers;
|
||||||
using Ragon.Common.Protocol;
|
using Ragon.Common.Protocol;
|
||||||
|
|
||||||
namespace Ragon.Core
|
namespace Ragon.Core
|
||||||
@@ -13,10 +15,7 @@ namespace Ragon.Core
|
|||||||
private ILogger _logger = LogManager.GetCurrentClassLogger();
|
private ILogger _logger = LogManager.GetCurrentClassLogger();
|
||||||
private Dictionary<uint, Player> _players = new();
|
private Dictionary<uint, Player> _players = new();
|
||||||
private Dictionary<int, Entity> _entities = new();
|
private Dictionary<int, Entity> _entities = new();
|
||||||
private uint Owner;
|
private uint _owner;
|
||||||
|
|
||||||
private BitBuffer _buffer = new BitBuffer(8192);
|
|
||||||
private byte[] _bytes = new byte[8192];
|
|
||||||
|
|
||||||
private readonly PluginBase _plugin;
|
private readonly PluginBase _plugin;
|
||||||
private readonly RoomThread _roomThread;
|
private readonly RoomThread _roomThread;
|
||||||
@@ -25,9 +24,8 @@ namespace Ragon.Core
|
|||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
private uint[] _readyPlayers = Array.Empty<uint>();
|
private uint[] _readyPlayers = Array.Empty<uint>();
|
||||||
|
private uint[] _allPlayers = Array.Empty<uint>();
|
||||||
public int Players => _players.Count;
|
private Entity[] _entitiesAll = Array.Empty<Entity>();
|
||||||
public int MaxPlayers { get; } = 0;
|
|
||||||
|
|
||||||
public Room(RoomThread roomThread, PluginBase pluginBase, string map)
|
public Room(RoomThread roomThread, PluginBase pluginBase, string map)
|
||||||
{
|
{
|
||||||
@@ -35,6 +33,7 @@ namespace Ragon.Core
|
|||||||
_plugin = pluginBase;
|
_plugin = pluginBase;
|
||||||
_map = map;
|
_map = map;
|
||||||
|
|
||||||
|
_logger.Info("Room created");
|
||||||
_plugin.Attach(this);
|
_plugin.Attach(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ namespace Ragon.Core
|
|||||||
{
|
{
|
||||||
if (_players.Count == 0)
|
if (_players.Count == 0)
|
||||||
{
|
{
|
||||||
Owner = peerId;
|
_owner = peerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
var player = new Player()
|
var player = new Player()
|
||||||
@@ -55,88 +54,112 @@ namespace Ragon.Core
|
|||||||
};
|
};
|
||||||
|
|
||||||
_players.Add(peerId, player);
|
_players.Add(peerId, player);
|
||||||
_plugin.OnPlayerConnected(player);
|
|
||||||
|
|
||||||
var data = new byte[8];
|
_allPlayers = _players.Select(p => p.Key).ToArray();
|
||||||
ProtocolHeader.WriteEntity((int) peerId, data, 0);
|
|
||||||
ProtocolHeader.WriteEntity((int) Owner, data, 4);
|
|
||||||
Send(peerId, RagonOperation.JOIN_ROOM, data);
|
|
||||||
|
|
||||||
var sceneRawData = Encoding.UTF8.GetBytes(_map);
|
Span<byte> data = stackalloc byte[10];
|
||||||
Send(peerId, RagonOperation.LOAD_SCENE, sceneRawData);
|
Span<byte> operationData = data.Slice(0, 2);
|
||||||
|
Span<byte> peerData = data.Slice(2, 4);
|
||||||
|
Span<byte> ownerData = data.Slice(4, 4);
|
||||||
|
|
||||||
|
ProtocolHeader.WriteUShort((ushort) RagonOperation.JOIN_ROOM, ref operationData);
|
||||||
|
ProtocolHeader.WriteInt((int) peerId, ref peerData);
|
||||||
|
ProtocolHeader.WriteInt((int) _owner, ref ownerData);
|
||||||
|
|
||||||
|
Send(peerId, data);
|
||||||
|
|
||||||
|
// var sceneRawData = Encoding.UTF8.GetBytes(_map);
|
||||||
|
// Send(peerId, RagonOperation.LOAD_SCENE, sceneRawData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Leave(uint peerId)
|
public void Leave(uint peerId)
|
||||||
{
|
{
|
||||||
if (_players.Remove(peerId, out var player))
|
if (_players.Remove(peerId, out var player))
|
||||||
{
|
{
|
||||||
_plugin.OnPlayerDisconnected(player);
|
_allPlayers = _players.Select(p => p.Key).ToArray();
|
||||||
|
|
||||||
foreach (var entityId in player.EntitiesIds)
|
foreach (var entityId in player.EntitiesIds)
|
||||||
{
|
{
|
||||||
var entityData = new byte[4];
|
Span<byte> entityData = stackalloc byte[6];
|
||||||
ProtocolHeader.WriteEntity(entityId, entityData, 0);
|
var operationData = entityData.Slice(0, 2);
|
||||||
Broadcast(_readyPlayers, RagonOperation.DESTROY_ENTITY, entityData);
|
|
||||||
|
ProtocolHeader.WriteUShort((ushort) RagonOperation.DESTROY_ENTITY, ref operationData);
|
||||||
|
ProtocolHeader.WriteInt(entityId, ref entityData);
|
||||||
|
|
||||||
|
Broadcast(_allPlayers, entityData);
|
||||||
|
|
||||||
_entities.Remove(entityId);
|
_entities.Remove(entityId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessEvent(RagonOperation operation, uint peerId, byte[] rawData)
|
public void ProcessEvent(RagonOperation operation, uint peerId, ReadOnlySpan<byte> rawData)
|
||||||
{
|
{
|
||||||
|
if (_plugin.InternalHandle(peerId, (ushort) operation, ref rawData)) return;
|
||||||
|
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case RagonOperation.REPLICATE_ENTITY_STATE:
|
case RagonOperation.REPLICATE_ENTITY_STATE:
|
||||||
{
|
{
|
||||||
var entityId = ProtocolHeader.ReadEntity(rawData, 2);
|
var entityData = rawData.Slice(2, 4);
|
||||||
|
var entityId = ProtocolHeader.ReadInt(ref entityData);
|
||||||
if (_entities.TryGetValue(entityId, out var ent))
|
if (_entities.TryGetValue(entityId, out var ent))
|
||||||
{
|
{
|
||||||
var data = new byte[rawData.Length - 6]; // opcode(ushort)(2) + entity(int)(4)
|
ent.State = rawData.Slice(6, rawData.Length - 6).ToArray();
|
||||||
Array.Copy(rawData, 6, data, 0, rawData.Length - 6);
|
|
||||||
_entities[entityId].State = data;
|
|
||||||
|
|
||||||
Broadcast(_readyPlayers, rawData);
|
Span<byte> data = stackalloc byte[rawData.Length];
|
||||||
|
rawData.CopyTo(data);
|
||||||
|
Broadcast(_readyPlayers, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RagonOperation.REPLICATE_ENTITY_PROPERTY:
|
case RagonOperation.REPLICATE_ENTITY_PROPERTY:
|
||||||
{
|
{
|
||||||
var entityId = ProtocolHeader.ReadEntity(rawData, 2);
|
var entityData = rawData.Slice(2, 4);
|
||||||
|
var entityId = ProtocolHeader.ReadInt(ref entityData);
|
||||||
if (_entities.TryGetValue(entityId, out var ent))
|
if (_entities.TryGetValue(entityId, out var ent))
|
||||||
{
|
{
|
||||||
var propertyId = ProtocolHeader.ReadProperty(rawData, 6);
|
var propertyData = rawData.Slice(6, 4);
|
||||||
var data = new byte[rawData.Length - 10]; // opcode(ushort)(2) + entity(int)(4) + propertyId(int)(4)
|
var propertyId = ProtocolHeader.ReadInt(ref propertyData);
|
||||||
Array.Copy(rawData, 10, data, 0, rawData.Length - 10);
|
var payload = rawData.Slice(10, rawData.Length - 10).ToArray();
|
||||||
|
|
||||||
var props = _entities[entityId].Properties;
|
var props = _entities[entityId].Properties;
|
||||||
|
|
||||||
if (props.ContainsKey(propertyId))
|
if (props.ContainsKey(propertyId))
|
||||||
{
|
{
|
||||||
props[propertyId] = data;
|
props[propertyId] = payload;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
props.Add(propertyId, data);
|
props.Add(propertyId, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
Broadcast(_readyPlayers, RagonOperation.REPLICATE_ENTITY_PROPERTY, rawData);
|
// Span<byte> sendData = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(rawData), rawData.Length);
|
||||||
|
|
||||||
|
Span<byte> sendData = stackalloc byte[rawData.Length];
|
||||||
|
rawData.CopyTo(sendData);
|
||||||
|
Broadcast(_readyPlayers, sendData, DeliveryType.Reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RagonOperation.REPLICATE_EVENT:
|
case RagonOperation.REPLICATE_EVENT:
|
||||||
|
case RagonOperation.REPLICATE_ENTITY_EVENT:
|
||||||
{
|
{
|
||||||
|
Span<byte> data = stackalloc byte[rawData.Length + 4];
|
||||||
|
Span<byte> peerData = data.Slice(2, 4);
|
||||||
|
Span<byte> rawDataSlice = data.Slice(4, rawData.Length);
|
||||||
|
|
||||||
Broadcast(_readyPlayers, rawData);
|
rawData.CopyTo(rawDataSlice);
|
||||||
|
ProtocolHeader.WriteInt((int) peerId, ref peerData);
|
||||||
|
|
||||||
|
Broadcast(_readyPlayers, data, DeliveryType.Reliable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RagonOperation.CREATE_ENTITY:
|
case RagonOperation.CREATE_ENTITY:
|
||||||
{
|
{
|
||||||
var entity = new Entity(peerId);
|
var entity = new Entity(peerId);
|
||||||
var data = new byte[rawData.Length - 2]; // opcode(ushort)(2)
|
var entityPayload = rawData.Slice(2, rawData.Length - 2);
|
||||||
Array.Copy(rawData, 2, data, 0, rawData.Length - 2);
|
entity.State = entityPayload.ToArray();
|
||||||
|
|
||||||
entity.State = data;
|
|
||||||
entity.Properties = new Dictionary<int, byte[]>();
|
entity.Properties = new Dictionary<int, byte[]>();
|
||||||
|
|
||||||
var player = _players[peerId];
|
var player = _players[peerId];
|
||||||
@@ -144,21 +167,27 @@ namespace Ragon.Core
|
|||||||
player.EntitiesIds.Add(entity.EntityId);
|
player.EntitiesIds.Add(entity.EntityId);
|
||||||
|
|
||||||
_entities.Add(entity.EntityId, entity);
|
_entities.Add(entity.EntityId, entity);
|
||||||
|
_entitiesAll = _entities.Values.ToArray();
|
||||||
|
|
||||||
var entityData = new byte[entity.State.Length + 8];
|
Span<byte> data = stackalloc byte[entityPayload.Length + 10];
|
||||||
ProtocolHeader.WriteEntity(entity.EntityId, entityData, 0);
|
var operationData = data.Slice(0, 2);
|
||||||
ProtocolHeader.WriteEntity((int) peerId, entityData, 4);
|
var entityData = data.Slice(2, 4);
|
||||||
|
var peerData = data.Slice(6, 4);
|
||||||
|
var payload = data.Slice(10, entityPayload.Length);
|
||||||
|
|
||||||
Array.Copy(entity.State, 0, entityData, 8, entity.State.Length);
|
entityPayload.CopyTo(payload);
|
||||||
|
|
||||||
_logger.Trace("Create entity Owner:" + peerId + " Id: " + entity.EntityId);
|
ProtocolHeader.WriteUShort((ushort) RagonOperation.CREATE_ENTITY, ref operationData);
|
||||||
|
ProtocolHeader.WriteInt(entity.EntityId, ref entityData);
|
||||||
|
ProtocolHeader.WriteInt((int) peerId, ref peerData);
|
||||||
|
|
||||||
Broadcast(_readyPlayers, RagonOperation.CREATE_ENTITY, entityData);
|
Broadcast(_allPlayers, data, DeliveryType.Reliable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RagonOperation.DESTROY_ENTITY:
|
case RagonOperation.DESTROY_ENTITY:
|
||||||
{
|
{
|
||||||
var entityId = ProtocolHeader.ReadEntity(rawData);
|
var entityData = rawData.Slice(2, 4);
|
||||||
|
var entityId = ProtocolHeader.ReadInt(ref entityData);
|
||||||
if (_entities.TryGetValue(entityId, out var entity))
|
if (_entities.TryGetValue(entityId, out var entity))
|
||||||
{
|
{
|
||||||
if (entity.OwnerId == peerId)
|
if (entity.OwnerId == peerId)
|
||||||
@@ -169,8 +198,11 @@ namespace Ragon.Core
|
|||||||
player.EntitiesIds.Remove(entity.EntityId);
|
player.EntitiesIds.Remove(entity.EntityId);
|
||||||
|
|
||||||
_entities.Remove(entityId);
|
_entities.Remove(entityId);
|
||||||
|
_entitiesAll = _entities.Values.ToArray();
|
||||||
|
|
||||||
Broadcast(_readyPlayers, rawData);
|
Span<byte> sendData = stackalloc byte[rawData.Length];
|
||||||
|
rawData.CopyTo(sendData);
|
||||||
|
Broadcast(_readyPlayers, sendData, DeliveryType.Reliable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,17 +210,26 @@ namespace Ragon.Core
|
|||||||
}
|
}
|
||||||
case RagonOperation.SCENE_IS_LOADED:
|
case RagonOperation.SCENE_IS_LOADED:
|
||||||
{
|
{
|
||||||
Send(peerId, RagonOperation.RESTORE_BEGIN, Array.Empty<byte>());
|
Send(peerId, RagonOperation.RESTORE_BEGIN);
|
||||||
foreach (var entity in _entities.Values)
|
foreach (var entity in _entities.Values)
|
||||||
{
|
{
|
||||||
var entityData = new byte[entity.State.Length + 8];
|
var entityState = entity.State.AsSpan();
|
||||||
ProtocolHeader.WriteEntity(entity.EntityId, entityData, 0);
|
|
||||||
ProtocolHeader.WriteEntity((int) entity.OwnerId, entityData, 4);
|
|
||||||
|
|
||||||
Array.Copy(entity.State, 0, entityData, 8, entity.State.Length);
|
Span<byte> sendData = stackalloc byte[entity.State.Length + 10];
|
||||||
Send(peerId, RagonOperation.CREATE_ENTITY, entityData);
|
Span<byte> operationData = sendData.Slice(0, 2);
|
||||||
|
Span<byte> entityData = sendData.Slice(2, 4);
|
||||||
|
Span<byte> ownerData = sendData.Slice(6, 4);
|
||||||
|
Span<byte> entityStateData = sendData.Slice(10, entity.State.Length);
|
||||||
|
|
||||||
|
ProtocolHeader.WriteUShort((ushort) RagonOperation.CREATE_ENTITY, ref operationData);;
|
||||||
|
ProtocolHeader.WriteInt(entity.EntityId, ref entityData);
|
||||||
|
ProtocolHeader.WriteInt((int) entity.OwnerId, ref ownerData);
|
||||||
|
|
||||||
|
entityState.CopyTo(entityStateData);
|
||||||
|
|
||||||
|
Send(peerId, sendData, DeliveryType.Reliable);
|
||||||
}
|
}
|
||||||
Send(peerId, RagonOperation.RESTORE_END, Array.Empty<byte>());
|
Send(peerId, RagonOperation.RESTORE_END);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RagonOperation.RESTORED:
|
case RagonOperation.RESTORED:
|
||||||
@@ -203,140 +244,92 @@ namespace Ragon.Core
|
|||||||
public void Tick(float deltaTime)
|
public void Tick(float deltaTime)
|
||||||
{
|
{
|
||||||
_ticks++;
|
_ticks++;
|
||||||
|
|
||||||
_plugin.OnTick(_ticks, deltaTime);
|
_plugin.OnTick(_ticks, deltaTime);
|
||||||
|
|
||||||
|
// for (var i = 0; i < _entitiesAll.Length; i++)
|
||||||
|
// {
|
||||||
|
// var entity = _entities[i];
|
||||||
|
// Span<byte> data = stackalloc byte[entity.State.Length];
|
||||||
|
// rawData.CopyTo(data);
|
||||||
|
// Broadcast(_readyPlayers, data);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
_logger.Info("Room started");
|
||||||
_plugin.OnStart();
|
_plugin.OnStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
|
_logger.Info("Room stopped");
|
||||||
_plugin.OnStop();
|
_plugin.OnStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_logger.Info("Room destroyed");
|
||||||
|
_plugin.Detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Send(uint peerId, RagonOperation operation, byte[] payload)
|
public Player GetPlayerByPeerId(uint peerId) => _players[peerId];
|
||||||
{
|
public Player GetOwner() => _players[_owner];
|
||||||
if (payload.Length > 0)
|
public int PlayersCount => _players.Count;
|
||||||
{
|
|
||||||
var data = new byte[payload.Length + 2];
|
|
||||||
|
|
||||||
Array.Copy(payload, 0, data, 2, payload.Length);
|
public void Send(uint peerId, RagonOperation operation, DeliveryType deliveryType = DeliveryType.Unreliable)
|
||||||
ProtocolHeader.WriteOperation((ushort) operation, data);
|
{
|
||||||
|
Span<byte> data = stackalloc byte[2];
|
||||||
|
ProtocolHeader.WriteUShort((ushort) operation, ref data);
|
||||||
|
|
||||||
|
var bytes = data.ToArray();
|
||||||
_roomThread.WriteOutEvent(new Event()
|
_roomThread.WriteOutEvent(new Event()
|
||||||
{
|
{
|
||||||
PeerId = peerId,
|
PeerId = peerId,
|
||||||
Data = data,
|
Data = bytes,
|
||||||
Type = EventType.DATA,
|
Type = EventType.DATA,
|
||||||
|
Delivery = deliveryType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
public void Send(uint peerId, Span<byte> payload, DeliveryType deliveryType = DeliveryType.Unreliable)
|
||||||
{
|
{
|
||||||
var data = new byte[2];
|
var bytes = payload.ToArray();
|
||||||
|
|
||||||
ProtocolHeader.WriteOperation((ushort) operation, data);
|
|
||||||
|
|
||||||
_roomThread.WriteOutEvent(new Event()
|
_roomThread.WriteOutEvent(new Event()
|
||||||
{
|
{
|
||||||
PeerId = peerId,
|
PeerId = peerId,
|
||||||
Data = data,
|
Data = bytes,
|
||||||
Type = EventType.DATA,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Send(uint peerId, RagonOperation operation, IData payload)
|
|
||||||
{
|
|
||||||
_buffer.Clear();
|
|
||||||
payload.Serialize(_buffer);
|
|
||||||
_buffer.ToArray(_bytes);
|
|
||||||
|
|
||||||
var data = new byte[_buffer.Length + 2];
|
|
||||||
|
|
||||||
Array.Copy(_bytes, 0, data, 2, _buffer.Length);
|
|
||||||
|
|
||||||
ProtocolHeader.WriteOperation((ushort) operation, data);
|
|
||||||
|
|
||||||
_roomThread.WriteOutEvent(new Event()
|
|
||||||
{
|
|
||||||
PeerId = peerId,
|
|
||||||
Data = data,
|
|
||||||
Type = EventType.DATA,
|
Type = EventType.DATA,
|
||||||
|
Delivery = deliveryType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Broadcast(uint[] peersIds, Span<byte> rawData, DeliveryType deliveryType = DeliveryType.Unreliable)
|
||||||
public void Broadcast(uint[] peersIds, RagonOperation operation, IData payload)
|
|
||||||
{
|
{
|
||||||
_buffer.Clear();
|
var bytes = rawData.ToArray();
|
||||||
payload.Serialize(_buffer);
|
|
||||||
_buffer.ToArray(_bytes);
|
|
||||||
|
|
||||||
var data = new byte[_buffer.Length + 2];
|
|
||||||
|
|
||||||
Array.Copy(_bytes, 0, data, 2, _buffer.Length);
|
|
||||||
|
|
||||||
ProtocolHeader.WriteOperation((ushort) operation, data);
|
|
||||||
|
|
||||||
foreach (var peer in peersIds)
|
foreach (var peer in peersIds)
|
||||||
{
|
{
|
||||||
_roomThread.WriteOutEvent(new Event()
|
_roomThread.WriteOutEvent(new Event()
|
||||||
{
|
{
|
||||||
PeerId = peer,
|
PeerId = peer,
|
||||||
Data = data,
|
Data = bytes,
|
||||||
Type = EventType.DATA,
|
Type = EventType.DATA,
|
||||||
|
Delivery = deliveryType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Broadcast(uint[] peersIds, RagonOperation operation, byte[] payload)
|
public void Broadcast(Span<byte> rawData, DeliveryType deliveryType = DeliveryType.Unreliable)
|
||||||
{
|
|
||||||
var data = new byte[payload.Length + 2];
|
|
||||||
|
|
||||||
Array.Copy(payload, 0, data, 2, payload.Length);
|
|
||||||
|
|
||||||
ProtocolHeader.WriteOperation((ushort) operation, data);
|
|
||||||
|
|
||||||
foreach (var peer in peersIds)
|
|
||||||
{
|
|
||||||
_roomThread.WriteOutEvent(new Event()
|
|
||||||
{
|
|
||||||
PeerId = peer,
|
|
||||||
Data = data,
|
|
||||||
Type = EventType.DATA,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Broadcast(uint[] peersIds, byte[] rawData)
|
|
||||||
{
|
|
||||||
foreach (var peer in peersIds)
|
|
||||||
{
|
|
||||||
_roomThread.WriteOutEvent(new Event()
|
|
||||||
{
|
|
||||||
PeerId = peer,
|
|
||||||
Data = rawData,
|
|
||||||
Type = EventType.DATA,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Broadcast(byte[] rawData)
|
|
||||||
{
|
{
|
||||||
|
var bytes = rawData.ToArray();
|
||||||
foreach (var player in _players.Values.ToArray())
|
foreach (var player in _players.Values.ToArray())
|
||||||
{
|
{
|
||||||
_roomThread.WriteOutEvent(new Event()
|
_roomThread.WriteOutEvent(new Event()
|
||||||
{
|
{
|
||||||
PeerId = player.PeerId,
|
PeerId = player.PeerId,
|
||||||
Data = rawData,
|
Data = bytes,
|
||||||
Type = EventType.DATA,
|
Type = EventType.DATA,
|
||||||
|
Delivery = deliveryType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using NetStack.Serialization;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using Ragon.Common.Protocol;
|
using Ragon.Common.Protocol;
|
||||||
|
|
||||||
@@ -13,8 +12,8 @@ namespace Ragon.Core
|
|||||||
private List<Room> _rooms;
|
private List<Room> _rooms;
|
||||||
private Dictionary<uint, Room> _peersByRoom;
|
private Dictionary<uint, Room> _peersByRoom;
|
||||||
private PluginFactory _factory;
|
private PluginFactory _factory;
|
||||||
|
private AuthorizationManager _manager;
|
||||||
private RoomThread _roomThread;
|
private RoomThread _roomThread;
|
||||||
private BitBuffer _bitBuffer;
|
|
||||||
|
|
||||||
public Action<(uint, Room)> OnJoined;
|
public Action<(uint, Room)> OnJoined;
|
||||||
public Action<(uint, Room)> OnLeaved;
|
public Action<(uint, Room)> OnLeaved;
|
||||||
@@ -23,12 +22,13 @@ namespace Ragon.Core
|
|||||||
{
|
{
|
||||||
_roomThread = roomThread;
|
_roomThread = roomThread;
|
||||||
_factory = factory;
|
_factory = factory;
|
||||||
|
|
||||||
|
_manager = _factory.CreateManager();
|
||||||
_rooms = new List<Room>();
|
_rooms = new List<Room>();
|
||||||
_peersByRoom = new Dictionary<uint, Room>();
|
_peersByRoom = new Dictionary<uint, Room>();
|
||||||
_bitBuffer = new BitBuffer(1024);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProccessEvent(RagonOperation operation, uint peerId, byte[] payload)
|
public void ProcessEvent(RagonOperation operation, uint peerId, byte[] payload)
|
||||||
{
|
{
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
@@ -54,28 +54,47 @@ namespace Ragon.Core
|
|||||||
|
|
||||||
public void OnAuthorize(uint peerId, byte[] payload)
|
public void OnAuthorize(uint peerId, byte[] payload)
|
||||||
{
|
{
|
||||||
_bitBuffer.Clear();
|
if (_manager.OnAuthorize(peerId, payload))
|
||||||
// _bitBuffer.FromArray(payload, payload.Length);
|
{
|
||||||
|
Span<byte> data = stackalloc byte[2];
|
||||||
|
ProtocolHeader.WriteUShort((ushort) RagonOperation.AUTHORIZED_SUCCESS, ref data);
|
||||||
|
|
||||||
// var authorizePacket = new AuthorationData();
|
var bytes = data.ToArray();
|
||||||
// authorizePacket.Deserialize(_bitBuffer);
|
_roomThread.WriteOutEvent(new Event()
|
||||||
|
{
|
||||||
|
Delivery = DeliveryType.Reliable,
|
||||||
|
Type = EventType.DATA,
|
||||||
|
Data = bytes,
|
||||||
|
PeerId = peerId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Span<byte> data = stackalloc byte[2];
|
||||||
|
ProtocolHeader.WriteUShort((ushort) RagonOperation.AUTHORIZED_FAILED, ref data);
|
||||||
|
|
||||||
var data = new byte[2];
|
var bytes = data.ToArray();
|
||||||
|
_roomThread.WriteOutEvent(new Event()
|
||||||
ProtocolHeader.WriteOperation((ushort) RagonOperation.AUTHORIZED_SUCCESS, data);
|
{
|
||||||
|
Delivery = DeliveryType.Reliable,
|
||||||
|
Type = EventType.DATA,
|
||||||
|
Data = bytes,
|
||||||
|
PeerId = peerId,
|
||||||
|
});
|
||||||
|
|
||||||
_roomThread.WriteOutEvent(new Event()
|
_roomThread.WriteOutEvent(new Event()
|
||||||
{
|
{
|
||||||
Type = EventType.DATA,
|
Delivery = DeliveryType.Reliable,
|
||||||
Data = data,
|
Type = EventType.DISCONNECTED,
|
||||||
|
Data = Array.Empty<byte>(),
|
||||||
PeerId = peerId,
|
PeerId = peerId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Room Join(uint peerId, byte[] payload)
|
public Room Join(uint peerId, byte[] payload)
|
||||||
{
|
{
|
||||||
var map = Encoding.UTF8.GetString(payload);
|
var map = Encoding.UTF8.GetString(payload);
|
||||||
|
|
||||||
if (_rooms.Count > 0)
|
if (_rooms.Count > 0)
|
||||||
{
|
{
|
||||||
var existsRoom = _rooms[0];
|
var existsRoom = _rooms[0];
|
||||||
@@ -89,10 +108,10 @@ namespace Ragon.Core
|
|||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
throw new NullReferenceException($"Plugin for map {map} is null");
|
throw new NullReferenceException($"Plugin for map {map} is null");
|
||||||
|
|
||||||
_logger.Info("Room created");
|
|
||||||
|
|
||||||
var room = new Room(_roomThread, plugin, map);
|
var room = new Room(_roomThread, plugin, map);
|
||||||
room.Joined(peerId, payload);
|
room.Joined(peerId, payload);
|
||||||
|
room.Start();
|
||||||
|
|
||||||
_peersByRoom.Add(peerId, room);
|
_peersByRoom.Add(peerId, room);
|
||||||
|
|
||||||
_rooms.Add(room);
|
_rooms.Add(room);
|
||||||
@@ -103,11 +122,26 @@ namespace Ragon.Core
|
|||||||
public Room Left(uint peerId, byte[] payload)
|
public Room Left(uint peerId, byte[] payload)
|
||||||
{
|
{
|
||||||
_peersByRoom.Remove(peerId, out var room);
|
_peersByRoom.Remove(peerId, out var room);
|
||||||
room?.Leave(peerId);
|
|
||||||
|
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Disconnected(uint peerId)
|
||||||
|
{
|
||||||
|
_peersByRoom.Remove(peerId, out var room);
|
||||||
|
if (room != null)
|
||||||
|
{
|
||||||
|
room.Leave(peerId);
|
||||||
|
if (room.PlayersCount <= 0)
|
||||||
|
{
|
||||||
|
_rooms.Remove(room);
|
||||||
|
|
||||||
|
room.Stop();
|
||||||
|
room.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick(float deltaTime)
|
public void Tick(float deltaTime)
|
||||||
{
|
{
|
||||||
foreach (Room room in _rooms)
|
foreach (Room room in _rooms)
|
||||||
|
|||||||
@@ -62,14 +62,15 @@ namespace Ragon.Core
|
|||||||
|
|
||||||
if (_socketByRooms.ContainsKey(evnt.PeerId))
|
if (_socketByRooms.ContainsKey(evnt.PeerId))
|
||||||
{
|
{
|
||||||
_roomManager.Left(evnt.PeerId, Array.Empty<byte>());
|
_roomManager.Disconnected(evnt.PeerId);
|
||||||
_socketByRooms.Remove(evnt.PeerId);
|
_socketByRooms.Remove(evnt.PeerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evnt.Type == EventType.DATA)
|
if (evnt.Type == EventType.DATA)
|
||||||
{
|
{
|
||||||
var operation = (RagonOperation) ProtocolHeader.ReadOperation(evnt.Data, 0);
|
ReadOnlySpan<byte> data = evnt.Data.AsSpan();
|
||||||
|
var operation = (RagonOperation) ProtocolHeader.ReadUShort(ref data);
|
||||||
if (_socketByRooms.TryGetValue(evnt.PeerId, out var room))
|
if (_socketByRooms.TryGetValue(evnt.PeerId, out var room))
|
||||||
{
|
{
|
||||||
room.ProcessEvent(operation, evnt.PeerId, evnt.Data);
|
room.ProcessEvent(operation, evnt.PeerId, evnt.Data);
|
||||||
@@ -77,10 +78,8 @@ namespace Ragon.Core
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var payload = new byte[evnt.Data.Length - 2];
|
var payload = new byte[evnt.Data.Length - 2];
|
||||||
|
|
||||||
Array.Copy(evnt.Data, 2, payload, 0, evnt.Data.Length - 2);
|
Array.Copy(evnt.Data, 2, payload, 0, evnt.Data.Length - 2);
|
||||||
|
_roomManager.ProcessEvent(operation, evnt.PeerId, payload);
|
||||||
_roomManager.ProccessEvent(operation, evnt.PeerId, payload);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
- Send states only on scene loaded
|
|
||||||
- Add events global and by entity
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
using NLog;
|
|
||||||
using Ragon.Core;
|
|
||||||
|
|
||||||
namespace Game.Source
|
|
||||||
{
|
|
||||||
public class ArenaPlugin: PluginBase
|
|
||||||
{
|
|
||||||
private ILogger _logger = LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
public override void OnStart()
|
|
||||||
{
|
|
||||||
// _logger.Info("Plugin started");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnStop()
|
|
||||||
{
|
|
||||||
// _logger.Info("Plugin stopped");
|
|
||||||
}
|
|
||||||
|
|
||||||
public long FindPrimeNumber(int n)
|
|
||||||
{
|
|
||||||
int count=0;
|
|
||||||
long a = 2;
|
|
||||||
while(count<n)
|
|
||||||
{
|
|
||||||
long b = 2;
|
|
||||||
int prime = 1;// to check if found a prime
|
|
||||||
while(b * b <= a)
|
|
||||||
{
|
|
||||||
if(a % b == 0)
|
|
||||||
{
|
|
||||||
prime = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
if(prime > 0)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
a++;
|
|
||||||
}
|
|
||||||
return (--a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Game.Source.Events;
|
|
||||||
|
|
||||||
public class SpawnEvent
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using Ragon.Core;
|
|
||||||
|
|
||||||
namespace Game.Source
|
|
||||||
{
|
|
||||||
public class GameFactory : PluginFactory
|
|
||||||
{
|
|
||||||
public PluginBase CreatePlugin(string map)
|
|
||||||
{
|
|
||||||
// if (map == "spawn")
|
|
||||||
// return new SpawnPlugin();
|
|
||||||
//
|
|
||||||
// if (map == "arena")
|
|
||||||
// return new ArenaPlugin();
|
|
||||||
return new SpawnPlugin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,5 +2,12 @@
|
|||||||
<img src="Images/logo.png" width="200" >
|
<img src="Images/logo.png" width="200" >
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Ragon - high perfomance game server with plugin based architecture.
|
Ragon - high perfomance room based game server with plugin based architecture.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Room base architecture
|
||||||
|
- Efficient memory management
|
||||||
|
- Flexible plugin system
|
||||||
|
- No CCU limitations
|
||||||
|
- Fully multithreaded
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user