neon-sprawl/server/NeonSprawl.Server/Game/AbilityInput/InMemoryPlayerAbilityCooldo...

48 lines
1.4 KiB
C#

using System.Collections.Concurrent;
namespace NeonSprawl.Server.Game.AbilityInput;
/// <summary>Thread-safe in-memory cooldown map (NEO-32); not persisted across process restarts.</summary>
public sealed class InMemoryPlayerAbilityCooldownStore : IPlayerAbilityCooldownStore
{
private readonly ConcurrentDictionary<string, ConcurrentDictionary<int, DateTimeOffset>> ends = new(StringComparer.Ordinal);
public bool IsOnCooldown(string playerId, int slotIndex, DateTimeOffset now)
{
if (!ends.TryGetValue(playerId, out var perSlot))
{
return false;
}
if (!perSlot.TryGetValue(slotIndex, out var end))
{
return false;
}
if (now >= end)
{
perSlot.TryRemove(slotIndex, out _);
return false;
}
return true;
}
public void StartCooldown(string playerId, int slotIndex, DateTimeOffset now, TimeSpan duration)
{
var perSlot = ends.GetOrAdd(playerId, _ => new ConcurrentDictionary<int, DateTimeOffset>());
perSlot[slotIndex] = now + duration;
}
public bool TryGetCooldownEndUtc(string playerId, int slotIndex, out DateTimeOffset endUtc)
{
endUtc = default;
if (!ends.TryGetValue(playerId, out var perSlot))
{
return false;
}
return perSlot.TryGetValue(slotIndex, out endUtc);
}
}