using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using BITKit; using Microsoft.Extensions.Logging; namespace Net.Project.B.Health { /// /// 击倒服务 /// public interface IKnockedService { /// /// 击倒列表 /// public HashSet Knocked { get; } /// /// 击倒生命值 /// public IReadOnlyDictionary KnockedHealth { get; } /// /// 击倒回调 /// public event Action OnKnocked; /// /// 击倒生命值回调 /// public event Action OnKnockedHealthChanged; } public class KnockedService : IKnockedService,IDisposable { private readonly IHealthService _healthService; private readonly ILogger _logger; public KnockedService(IHealthService healthService, ILogger logger) { _healthService = healthService; _logger = logger; _healthService.OnHealthPlus += OnHealthPlus; _healthService.OnHealthChanged += OnHealthChanged; } private int OnHealthPlus(int id, int oldHp, int plus, object sendor) { var isKnocked = _knocked.Contains(id); if (oldHp < 0) return plus; if ((oldHp + plus) > -1) return plus; if (plus > 0) return plus; if (isKnocked) { var currentHealth = _knockedHealth.GetOrAdd(id,100); if (currentHealth + plus > -1) { var nextHealth = currentHealth + plus; _knockedHealth[id] = nextHealth; _onKnockedHealthChanged?.Invoke(id, currentHealth, nextHealth); _logger.LogInformation($"Entity {id} 的击倒生命值减少了,剩余{_knockedHealth[id]}"); return 0; } _knockedHealth.Set(id,-1); return plus; } _knockedHealth.TryAdd(id, 100); _knocked.Add(id); _onKnocked?.Invoke(id, true); _logger.LogInformation($"Entity {id} 被击倒了"); return 0; } private void OnHealthChanged(int arg1, int arg2, int arg3, object arg4) { var isKnocked = _knocked.Contains(arg1); if(isKnocked is false)return; if (arg3 <= arg2) return; _knocked.Remove(arg1); _knockedHealth.TryRemove(arg1,out _); _onKnocked?.Invoke(arg1, false); _logger.LogInformation($"Entity {arg1} 自起了"); } private static readonly HashSet _knocked = new(); private static readonly ConcurrentDictionary _knockedHealth = new(); private static event Action _onKnocked; private static event Action _onKnockedHealthChanged; public HashSet Knocked=> _knocked; public IReadOnlyDictionary KnockedHealth => _knockedHealth; public event Action OnKnocked { add => _onKnocked += value; remove => _onKnocked -= value; } public event Action OnKnockedHealthChanged { add => _onKnockedHealthChanged += value; remove => _onKnockedHealthChanged -= value; } public void Dispose() { _healthService.OnHealthPlus -= OnHealthPlus; _healthService.OnHealthChanged -= OnHealthChanged; } } }