servicepoint-tanks/tanks-backend/TanksServer/GameLogic/TankSpawnQueue.cs
2024-04-28 15:34:32 +02:00

55 lines
1.6 KiB
C#

using System.Diagnostics.CodeAnalysis;
namespace TanksServer.GameLogic;
internal sealed class TankSpawnQueue(
IOptions<GameRules> options,
MapEntityManager entityManager
): ITickStep
{
private readonly ConcurrentQueue<Player> _queue = new();
private readonly ConcurrentDictionary<Player, DateTime> _spawnTimes = new();
private readonly TimeSpan _spawnDelay = TimeSpan.FromMilliseconds(options.Value.SpawnDelayMs);
private readonly TimeSpan _idleTimeout = TimeSpan.FromMilliseconds(options.Value.IdleTimeoutMs);
public void EnqueueForImmediateSpawn(Player player) => _queue.Enqueue(player);
public void EnqueueForDelayedSpawn(Player player)
{
_queue.Enqueue(player);
_spawnTimes.AddOrUpdate(player, DateTime.MinValue, (_, _) => DateTime.Now + _spawnDelay);
}
private bool TryDequeueNext([MaybeNullWhen(false)] out Player player)
{
if (!_queue.TryDequeue(out player))
return false; // no one on queue
if (player.LastInput + _idleTimeout < DateTime.Now)
{
// player idle
_queue.Enqueue(player);
return false;
}
var now = DateTime.Now;
if (_spawnTimes.GetOrAdd(player, DateTime.MinValue) > now)
{
// spawn delay
_queue.Enqueue(player);
return false;
}
return true;
}
public ValueTask TickAsync(TimeSpan _)
{
if (!TryDequeueNext(out var player))
return ValueTask.CompletedTask;
entityManager.SpawnTank(player);
return ValueTask.CompletedTask;
}
}