using System.Diagnostics.CodeAnalysis; namespace TanksServer.GameLogic; internal sealed class SpawnQueue( IOptions options ) { private readonly ConcurrentQueue _queue = new(); private readonly ConcurrentDictionary _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); } public 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; } }