2024-04-11 20:48:21 +02:00
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
|
|
|
namespace TanksServer.GameLogic;
|
|
|
|
|
2024-04-17 19:34:19 +02:00
|
|
|
internal sealed class TankSpawnQueue(
|
2024-04-19 13:37:28 +02:00
|
|
|
IOptions<GameRules> options,
|
2024-05-03 15:47:33 +02:00
|
|
|
MapEntityManager entityManager,
|
|
|
|
EmptyTileFinder tileFinder
|
2024-04-29 13:54:29 +02:00
|
|
|
) : ITickStep
|
2024-04-11 20:48:21 +02:00
|
|
|
{
|
2024-04-12 14:28:57 +02:00
|
|
|
private readonly ConcurrentQueue<Player> _queue = new();
|
|
|
|
private readonly ConcurrentDictionary<Player, DateTime> _spawnTimes = new();
|
2024-04-11 20:48:21 +02:00
|
|
|
private readonly TimeSpan _spawnDelay = TimeSpan.FromMilliseconds(options.Value.SpawnDelayMs);
|
2024-04-12 14:28:57 +02:00
|
|
|
private readonly TimeSpan _idleTimeout = TimeSpan.FromMilliseconds(options.Value.IdleTimeoutMs);
|
2024-04-11 20:48:21 +02:00
|
|
|
|
2024-04-13 14:08:51 +02:00
|
|
|
public void EnqueueForImmediateSpawn(Player player) => _queue.Enqueue(player);
|
2024-04-11 20:48:21 +02:00
|
|
|
|
|
|
|
public void EnqueueForDelayedSpawn(Player player)
|
|
|
|
{
|
|
|
|
_spawnTimes.AddOrUpdate(player, DateTime.MinValue, (_, _) => DateTime.Now + _spawnDelay);
|
2024-04-29 13:54:29 +02:00
|
|
|
_queue.Enqueue(player);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ValueTask TickAsync(TimeSpan _)
|
|
|
|
{
|
|
|
|
if (!TryDequeueNext(out var player))
|
|
|
|
return ValueTask.CompletedTask;
|
|
|
|
|
2024-05-03 15:47:33 +02:00
|
|
|
var position = tileFinder.ChooseEmptyTile().GetCenter().ToFloatPosition();
|
|
|
|
entityManager.SpawnTank(player, position);
|
2024-04-29 13:54:29 +02:00
|
|
|
return ValueTask.CompletedTask;
|
2024-04-11 20:48:21 +02:00
|
|
|
}
|
|
|
|
|
2024-04-21 12:38:03 +02:00
|
|
|
private bool TryDequeueNext([MaybeNullWhen(false)] out Player player)
|
2024-04-11 20:48:21 +02:00
|
|
|
{
|
|
|
|
if (!_queue.TryDequeue(out player))
|
2024-04-12 14:28:57 +02:00
|
|
|
return false; // no one on queue
|
2024-04-11 20:48:21 +02:00
|
|
|
|
2024-04-29 13:54:29 +02:00
|
|
|
var now = DateTime.Now;
|
2024-05-02 21:27:56 +02:00
|
|
|
if (player.OpenConnections < 1 || player.LastInput + _idleTimeout < now)
|
2024-04-12 14:28:57 +02:00
|
|
|
{
|
|
|
|
// player idle
|
|
|
|
_queue.Enqueue(player);
|
2024-04-29 13:54:29 +02:00
|
|
|
player = null;
|
2024-04-12 14:28:57 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-04-13 14:08:51 +02:00
|
|
|
|
2024-04-12 14:28:57 +02:00
|
|
|
if (_spawnTimes.GetOrAdd(player, DateTime.MinValue) > now)
|
|
|
|
{
|
|
|
|
// spawn delay
|
|
|
|
_queue.Enqueue(player);
|
2024-04-29 13:54:29 +02:00
|
|
|
player = null;
|
2024-04-12 14:28:57 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-04-11 20:48:21 +02:00
|
|
|
|
2024-04-12 14:28:57 +02:00
|
|
|
return true;
|
2024-04-11 20:48:21 +02:00
|
|
|
}
|
2024-04-13 14:08:51 +02:00
|
|
|
}
|