140 lines
4.6 KiB
C#
140 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using BITKit;
|
|
using BITKit.Entities;
|
|
using BITKit.WorldNode;
|
|
using Cysharp.Threading.Tasks;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
|
namespace Net.Project.B.Health
|
|
{
|
|
public interface IHealthComponent
|
|
{
|
|
public int HealthPoint { get;internal set; }
|
|
public int MaxHealthPoint { get; }
|
|
public event Action<int, int> OnHealthChanged;
|
|
}
|
|
|
|
[Serializable]
|
|
public class HealthComponent:IHealthComponent,IWorldNode
|
|
{
|
|
public int maxHealthPoint = 100;
|
|
public int healthPoint;
|
|
|
|
int IHealthComponent.HealthPoint
|
|
{
|
|
get => healthPoint;
|
|
set
|
|
{
|
|
var prevHp = healthPoint;
|
|
if(prevHp==value)return;
|
|
healthPoint = value;
|
|
OnHealthChanged?.Invoke(prevHp,healthPoint);
|
|
}
|
|
}
|
|
|
|
public int MaxHealthPoint => maxHealthPoint;
|
|
public event Action<int, int> OnHealthChanged;
|
|
}
|
|
/// <summary>
|
|
/// 生命值服务
|
|
/// </summary>
|
|
public interface IHealthService
|
|
{
|
|
/// <summary>
|
|
/// 已缓存的生命值
|
|
/// </summary>
|
|
public IReadOnlyDictionary<int,int> Healths { get; }
|
|
/// <summary>
|
|
/// 在改变生命值前,ID,当前生命值,新的生命值,来源
|
|
/// <returns>增加的数值</returns>
|
|
/// </summary>
|
|
public event Func<int,int,int,object,int> OnHealthPlus;
|
|
/// <summary>
|
|
/// 在改变生命值后
|
|
/// </summary>
|
|
/// /// <summary>
|
|
/// 当健康值发生变化时触发的事件。
|
|
/// </summary>
|
|
public event Action<int,int,int,object> OnHealthChanged;
|
|
/// <summary>
|
|
/// 调整生命值
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <param name="value">+- not set</param>
|
|
/// <returns></returns>
|
|
public UniTask<int> AddHealth(int id,int value,object arg);
|
|
}
|
|
public class HealthService:IHealthService,IDisposable
|
|
{ private static HealthService _singleton;
|
|
private readonly IEntitiesService _entitiesService;
|
|
|
|
private static readonly ConcurrentDictionary<int, IHealthComponent> HealthComponents = new();
|
|
|
|
public HealthService(IEntitiesService entitiesService)
|
|
{
|
|
_entitiesService = entitiesService;
|
|
_singleton = this;
|
|
|
|
_entitiesService.OnAdd += OnAdd;
|
|
}
|
|
|
|
private void OnAdd(IEntity obj)
|
|
{
|
|
if (obj.ServiceProvider.QueryComponents(out IHealthComponent healthComponent) is false) return;
|
|
HealthComponents[obj.Id] = healthComponent;
|
|
Healths[obj.Id] = healthComponent.HealthPoint = healthComponent.MaxHealthPoint <= 0 ? 100 : healthComponent.MaxHealthPoint;
|
|
}
|
|
|
|
[BITCommand]
|
|
public static void SetHealth(int id, int newHealth)
|
|
{
|
|
Healths.GetOrAdd(id,100);
|
|
Healths.Set(id,newHealth);
|
|
OnHealthChanged?.Invoke(id,newHealth,newHealth,null);
|
|
}
|
|
[BITCommand]
|
|
public static void AddHealth(int id, int newHealth)
|
|
{
|
|
Healths.GetOrAdd(id,100);
|
|
_singleton.AddHealth(id, newHealth, null).Forget();
|
|
}
|
|
|
|
IReadOnlyDictionary<int, int> IHealthService.Healths => Healths;
|
|
private static event Func<int,int,int,object,int> OnHealthChange;
|
|
private static event Action<int,int,int,object> OnHealthChanged;
|
|
private static readonly ConcurrentDictionary<int, int> Healths = new();
|
|
|
|
event Func<int,int,int,object,int> IHealthService.OnHealthPlus
|
|
{
|
|
add => OnHealthChange += value;
|
|
remove => OnHealthChange -= value;
|
|
}
|
|
event Action<int,int,int,object> IHealthService.OnHealthChanged
|
|
{
|
|
add => OnHealthChanged += value;
|
|
remove => OnHealthChanged -= value;
|
|
}
|
|
public UniTask<int> AddHealth(int id, int value,object arg)
|
|
{
|
|
if (Healths.TryGetValue(id,out var current) is false) return UniTask.FromResult(-1);
|
|
|
|
foreach (var func in OnHealthChange.CastAsFunc())
|
|
{
|
|
value =func.Invoke(id,current, value, arg);
|
|
}
|
|
var newHp = Math.Clamp(current + value, -1, HealthComponents[id].MaxHealthPoint);
|
|
Healths.Set(id,HealthComponents[id].HealthPoint = newHp);
|
|
OnHealthChanged?.Invoke(id,current,newHp,arg);
|
|
return UniTask.FromResult(newHp);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_entitiesService.OnAdd -= OnAdd;
|
|
}
|
|
}
|
|
}
|