using System; using System.Collections.Concurrent; using System.Linq; using System.Threading.Tasks; using WingsEmu.Core.Extensions; using WingsEmu.Game.Entities; using WingsEmu.Game.Managers; namespace WingsEmu.Plugins.BasicImplementations.Managers; public class DelayManager : IDelayManager { private readonly IDelayConfiguration _configuration; private readonly ConcurrentDictionary _playerActions = new(); public DelayManager(IDelayConfiguration configuration) => _configuration = configuration; public ValueTask RegisterAction(IBattleEntity entity, DelayedActionType actionType, TimeSpan time = default) { if (_playerActions.TryGetValue(entity.Id, out DelayedAction action)) { CompleteAction(entity, action.Type); } var delayedAction = new DelayedAction { Type = actionType, Completion = DateTime.UtcNow.Add(time != default ? time : _configuration.GetDelayByAction(actionType)), MapId = entity.MapInstance.MapId, PositionX = entity.PositionX, PositionY = entity.PositionY }; _playerActions.TryAdd(entity.Id, delayedAction); return new ValueTask(delayedAction.Completion); } public ValueTask CanPerformAction(IBattleEntity entity, DelayedActionType actionType) { DelayedAction action = _playerActions.GetOrDefault(entity.Id); if (action == null || action.Type != actionType) { return new ValueTask(false); } return new ValueTask(action.Completion <= DateTime.UtcNow && entity.MapInstance.MapId == action.MapId && entity.PositionX == action.PositionX && entity.PositionY == action.PositionY); } public ValueTask CompleteAction(IBattleEntity entity, DelayedActionType actionType) { DelayedAction action = _playerActions.GetOrDefault(entity.Id); if (action == null || action.Type != actionType) { return new ValueTask(false); } return new ValueTask(_playerActions.TryRemove(entity.Id, out DelayedAction delayedAction)); } public ValueTask RemoveAllOutdatedActions(TimeSpan time) { var keys = _playerActions.Where(x => x.Value.Completion.Add(time) < DateTime.UtcNow).Select(x => x.Key).ToList(); foreach (long key in keys) { _playerActions.TryRemove(key, out DelayedAction action); } return new ValueTask(keys.Count); } private class DelayedAction { public DelayedActionType Type { get; set; } public DateTime Completion { get; set; } public int MapId { get; set; } public short PositionX { get; set; } public short PositionY { get; set; } } }