2024-11-23 17:20:13 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using BITKit;
|
2025-03-09 13:38:32 +08:00
|
|
|
using BITKit.Entities;
|
|
|
|
using BITKit.WorldNode;
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
2024-11-23 17:20:13 +08:00
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
|
|
|
namespace Net.Project.B.Health
|
|
|
|
{
|
2025-03-09 13:38:32 +08:00
|
|
|
[Serializable]
|
|
|
|
public class KnockedComponent:IKnockedComponent,IWorldNode{}
|
|
|
|
public interface IKnockedComponent
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2024-11-23 17:20:13 +08:00
|
|
|
/// <summary>
|
|
|
|
/// 击倒服务
|
|
|
|
/// </summary>
|
|
|
|
public interface IKnockedService
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// 击倒列表
|
|
|
|
/// </summary>
|
|
|
|
public HashSet<int> Knocked { get; }
|
|
|
|
/// <summary>
|
|
|
|
/// 击倒生命值
|
|
|
|
/// </summary>
|
|
|
|
public IReadOnlyDictionary<int,int> KnockedHealth { get; }
|
|
|
|
/// <summary>
|
|
|
|
/// 击倒回调
|
|
|
|
/// </summary>
|
|
|
|
public event Action<int, bool> OnKnocked;
|
|
|
|
/// <summary>
|
|
|
|
/// 击倒生命值回调
|
|
|
|
/// </summary>
|
|
|
|
public event Action<int, int, int> OnKnockedHealthChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
public class KnockedService : IKnockedService,IDisposable
|
|
|
|
{
|
2025-03-09 13:38:32 +08:00
|
|
|
private readonly IEntitiesService _entitiesService;
|
2024-11-23 17:20:13 +08:00
|
|
|
private readonly IHealthService _healthService;
|
|
|
|
private readonly ILogger<KnockedService> _logger;
|
|
|
|
|
2025-03-09 13:38:32 +08:00
|
|
|
public KnockedService(IHealthService healthService, ILogger<KnockedService> logger, IEntitiesService entitiesService)
|
2024-11-23 17:20:13 +08:00
|
|
|
{
|
|
|
|
_healthService = healthService;
|
|
|
|
_logger = logger;
|
2025-03-09 13:38:32 +08:00
|
|
|
_entitiesService = entitiesService;
|
2024-11-23 17:20:13 +08:00
|
|
|
_healthService.OnHealthPlus += OnHealthPlus;
|
|
|
|
_healthService.OnHealthChanged += OnHealthChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
private int OnHealthPlus(int id, int oldHp, int plus, object sendor)
|
|
|
|
{
|
2025-03-09 13:38:32 +08:00
|
|
|
if (_entitiesService.TryGetEntity(id, out var entity) is false) return plus;
|
|
|
|
|
|
|
|
if (entity.ServiceProvider.GetService<IKnockedComponent>() is null) return plus;
|
|
|
|
|
2024-11-23 17:20:13 +08:00
|
|
|
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);
|
2025-03-09 13:38:32 +08:00
|
|
|
// _logger.LogInformation($"Entity {id} 的击倒生命值减少了,剩余{_knockedHealth[id]}");
|
2024-11-23 17:20:13 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
_knockedHealth.Set(id,-1);
|
|
|
|
return plus;
|
|
|
|
}
|
|
|
|
_knockedHealth.TryAdd(id, 100);
|
|
|
|
_knocked.Add(id);
|
|
|
|
_onKnocked?.Invoke(id, true);
|
2025-03-09 13:38:32 +08:00
|
|
|
// _logger.LogInformation($"Entity {id} 被击倒了");
|
2025-04-14 15:39:24 +08:00
|
|
|
return oldHp-1;
|
2024-11-23 17:20:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2025-03-09 13:38:32 +08:00
|
|
|
// _logger.LogInformation($"Entity {arg1} 自起了");
|
2024-11-23 17:20:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private static readonly HashSet<int> _knocked = new();
|
|
|
|
private static readonly ConcurrentDictionary<int,int> _knockedHealth = new();
|
|
|
|
private static event Action<int, bool> _onKnocked;
|
|
|
|
private static event Action<int, int, int> _onKnockedHealthChanged;
|
|
|
|
public HashSet<int> Knocked=> _knocked;
|
|
|
|
public IReadOnlyDictionary<int, int> KnockedHealth => _knockedHealth;
|
|
|
|
public event Action<int, bool> OnKnocked
|
|
|
|
{
|
|
|
|
add => _onKnocked += value;
|
|
|
|
remove => _onKnocked -= value;
|
|
|
|
}
|
|
|
|
public event Action<int, int, int> OnKnockedHealthChanged
|
|
|
|
{
|
|
|
|
add => _onKnockedHealthChanged += value;
|
|
|
|
remove => _onKnockedHealthChanged -= value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
_healthService.OnHealthPlus -= OnHealthPlus;
|
|
|
|
_healthService.OnHealthChanged -= OnHealthChanged;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|