using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using BITKit; using BITKit.Entities; using BITKit.WorldNode; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Net.Project.B.Health { [Serializable] public class KnockedComponent:IKnockedComponent,IWorldNode{} public interface IKnockedComponent { } /// /// 击倒服务 /// 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 IEntitiesService _entitiesService; private readonly IHealthService _healthService; private readonly ILogger _logger; public KnockedService(IHealthService healthService, ILogger logger, IEntitiesService entitiesService) { _healthService = healthService; _logger = logger; _entitiesService = entitiesService; _healthService.OnHealthPlus += OnHealthPlus; _healthService.OnHealthChanged += OnHealthChanged; } private int OnHealthPlus(int id, int oldHp, int plus, object sendor) { if (_entitiesService.TryGetEntity(id, out var entity) is false) return plus; if (entity.ServiceProvider.GetService() is null) return plus; 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 oldHp-1; } 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; } } }