feat: added scheduler, minor fixes
This commit is contained in:
@@ -14,7 +14,7 @@ public class AuthorizationManager : IAuthorizationManager
|
||||
private RagonSerializer _serializer;
|
||||
private readonly Dictionary<uint, Player> _playersByPeers;
|
||||
private readonly Dictionary<string, Player> _playersByIds;
|
||||
|
||||
|
||||
public AuthorizationManager(IAuthorizationProvider provider, IGameThread gameThread, Lobby lobby, RagonSerializer serializer)
|
||||
{
|
||||
_serializer = serializer;
|
||||
@@ -28,15 +28,10 @@ public class AuthorizationManager : IAuthorizationManager
|
||||
public void OnAuthorization(uint peerId, string key, string name, byte protocol)
|
||||
{
|
||||
var dispatcher = _gameThread.ThreadDispatcher;
|
||||
|
||||
_provider.OnAuthorizationRequest(key, name, protocol, Array.Empty<byte>(),
|
||||
(playerId, playerName) =>
|
||||
{
|
||||
dispatcher.Dispatch(() => Accepted(peerId, playerId, playerName));
|
||||
},
|
||||
(errorCode) =>
|
||||
{
|
||||
dispatcher.Dispatch(() => Rejected(peerId, errorCode));
|
||||
});
|
||||
(playerId, playerName) => { dispatcher.Dispatch(() => Accepted(peerId, playerId, playerName)); },
|
||||
(errorCode) => { dispatcher.Dispatch(() => Rejected(peerId, errorCode)); });
|
||||
}
|
||||
|
||||
public void Accepted(uint peerId, string playerId, string playerName)
|
||||
@@ -45,7 +40,7 @@ public class AuthorizationManager : IAuthorizationManager
|
||||
_serializer.WriteOperation(RagonOperation.AUTHORIZED_SUCCESS);
|
||||
_serializer.WriteString(playerId);
|
||||
_serializer.WriteString(playerName);
|
||||
|
||||
|
||||
var player = new Player()
|
||||
{
|
||||
Id = playerId,
|
||||
@@ -55,10 +50,10 @@ public class AuthorizationManager : IAuthorizationManager
|
||||
Entities = new List<Entity>(),
|
||||
EntitiesIds = new List<int>(),
|
||||
};
|
||||
|
||||
|
||||
_playersByIds.Add(playerId, player);
|
||||
_playersByPeers.Add(peerId, player);
|
||||
|
||||
|
||||
var sendData = _serializer.ToArray();
|
||||
_gameThread.Server.Send(peerId, sendData, DeliveryType.Reliable);
|
||||
}
|
||||
@@ -84,10 +79,10 @@ public class AuthorizationManager : IAuthorizationManager
|
||||
{
|
||||
if (_playersByPeers.TryGetValue(peerId, out var player))
|
||||
return player;
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Player GetPlayer(string playerId)
|
||||
{
|
||||
return _playersByIds[playerId];
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Ragon.Core
|
||||
public ushort SendRate;
|
||||
public ushort Port;
|
||||
public int SkipTimeout;
|
||||
public int ReconnectTimeout;
|
||||
public int MaxConnections;
|
||||
public int MaxPlayersPerRoom;
|
||||
public int MaxRooms;
|
||||
|
||||
@@ -20,8 +20,9 @@ namespace Ragon.Core
|
||||
private Dictionary<int, Entity> _entities = new();
|
||||
private uint _owner;
|
||||
|
||||
private readonly PluginBase _plugin;
|
||||
private readonly IScheduler _scheduler;
|
||||
private readonly IGameThread _gameThread;
|
||||
private readonly PluginBase _plugin;
|
||||
private readonly RagonSerializer _serializer = new(512);
|
||||
|
||||
// Cache
|
||||
@@ -33,6 +34,7 @@ namespace Ragon.Core
|
||||
{
|
||||
_gameThread = gameThread;
|
||||
_plugin = pluginBase;
|
||||
_scheduler = new Scheduler();
|
||||
|
||||
Map = map;
|
||||
PlayersMin = min;
|
||||
@@ -162,6 +164,7 @@ namespace Ragon.Core
|
||||
case RagonOperation.REPLICATE_ENTITY_EVENT:
|
||||
{
|
||||
var evntId = _serializer.ReadUShort();
|
||||
var evntMode = _serializer.ReadByte();
|
||||
var entityId = _serializer.ReadInt();
|
||||
|
||||
if (!_entities.TryGetValue(entityId, out var ent))
|
||||
@@ -181,6 +184,8 @@ namespace Ragon.Core
|
||||
_serializer.Clear();
|
||||
_serializer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
|
||||
_serializer.WriteUShort(evntId);
|
||||
_serializer.WriteUShort((ushort) peerId);
|
||||
_serializer.WriteByte(evntMode);
|
||||
_serializer.WriteInt(entityId);
|
||||
_serializer.WriteData(ref payload);
|
||||
var sendData = _serializer.ToArray();
|
||||
@@ -191,7 +196,7 @@ namespace Ragon.Core
|
||||
case RagonOperation.REPLICATE_EVENT:
|
||||
{
|
||||
var evntId = _serializer.ReadUShort();
|
||||
|
||||
var evntMode = _serializer.ReadByte();
|
||||
Span<byte> payloadRaw = stackalloc byte[_serializer.Size];
|
||||
var payloadData = _serializer.ReadData(_serializer.Size);
|
||||
payloadData.CopyTo(payloadRaw);
|
||||
@@ -202,6 +207,8 @@ namespace Ragon.Core
|
||||
|
||||
_serializer.Clear();
|
||||
_serializer.WriteOperation(RagonOperation.REPLICATE_EVENT);
|
||||
_serializer.WriteUShort((ushort) peerId);
|
||||
_serializer.WriteByte(evntMode);
|
||||
_serializer.WriteUShort(evntId);
|
||||
_serializer.WriteData(ref payload);
|
||||
|
||||
@@ -323,8 +330,8 @@ namespace Ragon.Core
|
||||
|
||||
public void Tick(float deltaTime)
|
||||
{
|
||||
_plugin.OnTick(deltaTime);
|
||||
|
||||
_scheduler.Tick(deltaTime);
|
||||
|
||||
foreach (var entity in _entitiesAll)
|
||||
{
|
||||
if (entity.State.isDirty)
|
||||
@@ -351,6 +358,9 @@ namespace Ragon.Core
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
foreach (var peerId in _allPlayers)
|
||||
_gameThread.Server.Disconnect(peerId, 0);
|
||||
|
||||
_plugin.OnStop();
|
||||
_plugin.Detach();
|
||||
}
|
||||
@@ -363,6 +373,8 @@ namespace Ragon.Core
|
||||
|
||||
public IDispatcher GetThreadDispatcher() => _gameThread.ThreadDispatcher;
|
||||
|
||||
public IScheduler GetScheduler() => _scheduler;
|
||||
|
||||
public void Send(uint peerId, byte[] rawData, DeliveryType deliveryType = DeliveryType.Unreliable)
|
||||
{
|
||||
_gameThread.Server.Send(peerId, rawData, deliveryType);
|
||||
|
||||
@@ -12,6 +12,7 @@ public interface IGameRoom
|
||||
public Entity GetEntityById(int entityId);
|
||||
public Player GetOwner();
|
||||
public IDispatcher GetThreadDispatcher();
|
||||
public IScheduler GetScheduler();
|
||||
|
||||
public void Send(uint peerId, byte[] rawData, DeliveryType deliveryType = DeliveryType.Unreliable);
|
||||
public void Broadcast(uint[] peersIds, byte[] rawData, DeliveryType deliveryType = DeliveryType.Unreliable);
|
||||
|
||||
@@ -8,14 +8,15 @@ public class Lobby : ILobby
|
||||
{
|
||||
private readonly RagonSerializer _serializer;
|
||||
private readonly RoomManager _roomManager;
|
||||
private readonly AuthorizationManager _authorizationManager;
|
||||
|
||||
public AuthorizationManager AuthorizationManager { get; private set; }
|
||||
public AuthorizationManager AuthorizationManager => _authorizationManager;
|
||||
|
||||
public Lobby(IAuthorizationProvider provider, RoomManager manager, IGameThread gameThread)
|
||||
{
|
||||
_roomManager = manager;
|
||||
_serializer = new RagonSerializer();
|
||||
AuthorizationManager = new AuthorizationManager(provider, gameThread, this, _serializer);
|
||||
_authorizationManager = new AuthorizationManager(provider, gameThread, this, _serializer);
|
||||
}
|
||||
|
||||
public void ProcessEvent(uint peerId, ReadOnlySpan<byte> data)
|
||||
@@ -33,30 +34,30 @@ public class Lobby : ILobby
|
||||
var key = _serializer.ReadString();
|
||||
var playerName = _serializer.ReadString();
|
||||
var protocol = _serializer.ReadByte();
|
||||
AuthorizationManager.OnAuthorization(peerId, key, playerName, protocol);
|
||||
_authorizationManager.OnAuthorization(peerId, key, playerName, protocol);
|
||||
break;
|
||||
}
|
||||
case RagonOperation.JOIN_ROOM:
|
||||
{
|
||||
var roomId = _serializer.ReadString();
|
||||
var player = AuthorizationManager.GetPlayer(peerId);
|
||||
var player = _authorizationManager.GetPlayer(peerId);
|
||||
if (player != null)
|
||||
_roomManager.Join(player, roomId, Array.Empty<byte>());
|
||||
break;
|
||||
}
|
||||
case RagonOperation.JOIN_OR_CREATE_ROOM:
|
||||
{
|
||||
var min = _serializer.ReadUShort();
|
||||
var max = _serializer.ReadUShort();
|
||||
var map = _serializer.ReadString();
|
||||
var min = _serializer.ReadInt();
|
||||
var max = _serializer.ReadInt();
|
||||
var player = AuthorizationManager.GetPlayer(peerId);
|
||||
var player = _authorizationManager.GetPlayer(peerId);
|
||||
if (player != null)
|
||||
_roomManager.JoinOrCreate(player, map, min, max, Array.Empty<byte>());
|
||||
break;
|
||||
}
|
||||
case RagonOperation.LEAVE_ROOM:
|
||||
{
|
||||
var player = AuthorizationManager.GetPlayer(peerId);
|
||||
var player = _authorizationManager.GetPlayer(peerId);
|
||||
if (player != null)
|
||||
_roomManager.Left(player, Array.Empty<byte>());
|
||||
break;
|
||||
@@ -66,6 +67,6 @@ public class Lobby : ILobby
|
||||
|
||||
public void OnDisconnected(uint peerId)
|
||||
{
|
||||
AuthorizationManager.Cleanup(peerId);
|
||||
_authorizationManager.Cleanup(peerId);
|
||||
}
|
||||
}
|
||||
@@ -264,11 +264,7 @@ namespace Ragon.Core
|
||||
public virtual void OnStop()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnTick(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Ragon.Core;
|
||||
|
||||
public interface IScheduler
|
||||
{
|
||||
public SchedulerTask Schedule(Action<SchedulerTask> action, float interval, int count = 1);
|
||||
public SchedulerTask ScheduleForever(Action<SchedulerTask> action, float interval);
|
||||
public void StopSchedule(SchedulerTask schedulerTask);
|
||||
|
||||
public void Tick(float deltaTime);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Ragon.Core
|
||||
{
|
||||
public class Scheduler: IScheduler
|
||||
{
|
||||
List<SchedulerTask> _scheduledTasks;
|
||||
|
||||
public Scheduler(int defaultCapacity = 100)
|
||||
{
|
||||
_scheduledTasks = new List<SchedulerTask>(defaultCapacity);
|
||||
}
|
||||
|
||||
public SchedulerTask Schedule(Action<SchedulerTask> action, float interval, int count = 1)
|
||||
{
|
||||
var newTask = new SchedulerTask(action, interval, count - 1);
|
||||
_scheduledTasks.Add(newTask);
|
||||
return newTask;
|
||||
}
|
||||
|
||||
public SchedulerTask ScheduleForever(Action<SchedulerTask> action, float interval)
|
||||
{
|
||||
var newTask = new SchedulerTask(action, interval, -1);
|
||||
_scheduledTasks.Add(newTask);
|
||||
return newTask;
|
||||
}
|
||||
|
||||
public void StopSchedule(SchedulerTask schedulerTask)
|
||||
{
|
||||
if (_scheduledTasks.Contains(schedulerTask))
|
||||
_scheduledTasks.Remove(schedulerTask);
|
||||
}
|
||||
|
||||
public void Tick(float deltaTime)
|
||||
{
|
||||
for (int i = _scheduledTasks.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var scheduledTask = _scheduledTasks[i];
|
||||
scheduledTask.Tick(deltaTime);
|
||||
|
||||
if (!scheduledTask.IsActive)
|
||||
_scheduledTasks.Remove(scheduledTask);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_scheduledTasks.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public class SchedulerTask
|
||||
{
|
||||
private Action<SchedulerTask> _action;
|
||||
private float _timer = 0;
|
||||
private float _interval = 0;
|
||||
private int _repeats = 0;
|
||||
private bool _active;
|
||||
|
||||
public int Repeats => _repeats;
|
||||
public bool IsActive => _active;
|
||||
|
||||
public SchedulerTask(Action<SchedulerTask> task, float interval, int repeatCount = 0)
|
||||
{
|
||||
_action = task;
|
||||
_interval = interval;
|
||||
_timer = 0;
|
||||
_active = true;
|
||||
_repeats = repeatCount;
|
||||
}
|
||||
|
||||
public void Tick(float deltaTime)
|
||||
{
|
||||
_timer += deltaTime;
|
||||
if (_timer >= _interval)
|
||||
{
|
||||
_action.Invoke(this);
|
||||
if (_repeats == -1)
|
||||
{
|
||||
_timer = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_repeats > 0)
|
||||
{
|
||||
_timer = 0;
|
||||
_repeats--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_repeats == 0)
|
||||
_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user