182 lines
6.0 KiB
C#
182 lines
6.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using UnityEngine;
|
|
using BITKit;
|
|
using BITKit.SubSystems;
|
|
using BITKit.Entities;
|
|
namespace BITKit.Entities
|
|
{
|
|
|
|
public interface IDamageType { }
|
|
public interface IDamageService
|
|
{
|
|
public event Action<DamageMessage> OnEntityDamaged;
|
|
public event Action<DamageMessage> OnEntityKilled;
|
|
void Execute(DamageMessage damageMessage);
|
|
}
|
|
public struct MeleeDamageMessage : IDamageType
|
|
{
|
|
public bool Bleeding;
|
|
}
|
|
public struct BulletDamageMessage:IDamageType{}
|
|
[Serializable]
|
|
public class DamageServiceSingleton:IDamageService
|
|
{
|
|
private IDamageService _damageServiceImplementation => DamageService.Singleton;
|
|
public event Action<DamageMessage> OnEntityDamaged
|
|
{
|
|
add => _damageServiceImplementation.OnEntityDamaged += value;
|
|
remove => _damageServiceImplementation.OnEntityDamaged -= value;
|
|
}
|
|
|
|
public event Action<DamageMessage> OnEntityKilled
|
|
{
|
|
add => _damageServiceImplementation.OnEntityKilled += value;
|
|
remove => _damageServiceImplementation.OnEntityKilled -= value;
|
|
}
|
|
|
|
public void Execute(DamageMessage damageMessage)
|
|
{
|
|
_damageServiceImplementation.Execute(damageMessage);
|
|
}
|
|
}
|
|
[Serializable]
|
|
public class DamageServiceMonoProxy:IDamageService
|
|
{
|
|
[SerializeField] private MonoBehaviour monoBehaviour;
|
|
private IDamageService _damageServiceImplementation=>monoBehaviour as IDamageService;
|
|
public event Action<DamageMessage> OnEntityDamaged
|
|
{
|
|
add => _damageServiceImplementation.OnEntityDamaged += value;
|
|
remove => _damageServiceImplementation.OnEntityDamaged -= value;
|
|
}
|
|
|
|
public event Action<DamageMessage> OnEntityKilled
|
|
{
|
|
add => _damageServiceImplementation.OnEntityKilled += value;
|
|
remove => _damageServiceImplementation.OnEntityKilled -= value;
|
|
}
|
|
|
|
public void Execute(DamageMessage damageMessage)
|
|
{
|
|
_damageServiceImplementation.Execute(damageMessage);
|
|
}
|
|
}
|
|
public record DamageMessage
|
|
{
|
|
public IUnityEntity Initiator;
|
|
public IUnityEntity Target;
|
|
public bool RawDamage;
|
|
public int Damage;
|
|
public IDamagable Hit;
|
|
public Vector3 Position;
|
|
public Quaternion Rotation;
|
|
public IDamageType DamageType;
|
|
public RaycastHit? RaycastHit;
|
|
}
|
|
|
|
public sealed class DamageMessageNetMessageWriter : NetMessageReader<DamageMessage>
|
|
{
|
|
public override DamageMessage ReadBinary(BinaryReader reader)
|
|
{
|
|
UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var initiator);
|
|
UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var target);
|
|
return new DamageMessage()
|
|
{
|
|
Initiator = initiator as Entity,
|
|
Target = target as Entity,
|
|
RawDamage = reader.ReadBoolean(),
|
|
Damage = reader.ReadInt32(),
|
|
Position = reader.ReadFloat3(),
|
|
Rotation = reader.ReadQuaternion(),
|
|
};
|
|
}
|
|
public override void WriteBinary(BinaryWriter writer, DamageMessage value)
|
|
{
|
|
writer.Write(value.Initiator?.Id ?? 0);
|
|
writer.Write(value.Target?.Id ?? 0);
|
|
writer.Write(value.RawDamage);
|
|
writer.Write(value.Damage);
|
|
writer.WriteFloat3(value.Position);
|
|
writer.WriteQuaternion(value.Rotation);
|
|
}
|
|
}
|
|
|
|
public interface IDamageCallback
|
|
{
|
|
void OnGetDamage(DamageMessage message);
|
|
}
|
|
public interface IDamagable
|
|
{
|
|
string Tag { get; }
|
|
IHealth Health { get; }
|
|
IUnityEntity UnityEntity { get; }
|
|
Rigidbody Rigidbody { get; }
|
|
void GiveDamage(DamageMessage message);
|
|
}
|
|
public class DamageService:MonoBehaviour,IDamageService
|
|
{
|
|
public static IDamageService Singleton { get;private set; }
|
|
private readonly Queue<DamageMessage> Messages = new();
|
|
|
|
[SerializeReference,SubclassSelector] private INetClient netClient;
|
|
[SerializeReference,SubclassSelector] private INetServer netServer;
|
|
|
|
private INetProvider netClientProvider => netClient.Source as INetProvider;
|
|
private INetProvider netServerProvider => netServer.Source as INetProvider;
|
|
|
|
private void Awake()
|
|
{
|
|
Singleton = this;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
netClientProvider.AddCommandListener<DamageMessage>(ExecuteInternal);
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (!netServer.IsRunningServer && netClient.IsConnected) return;
|
|
while (Messages.TryDequeue(out var damageMessage))
|
|
{
|
|
var unityEntity = (Entity)damageMessage.Target;
|
|
if (!unityEntity || !unityEntity.TryGetComponent<IHealth>(out var heal) || !heal.IsAlive) continue;
|
|
|
|
ExecuteInternal(damageMessage);
|
|
|
|
netServerProvider?.AllClientCommand(damageMessage);
|
|
}
|
|
}
|
|
|
|
private void ExecuteInternal(DamageMessage damageMessage)
|
|
{
|
|
IHealth heal = null;
|
|
if (damageMessage.Target?.TryGetComponent<IHealth>(out heal) is false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
damageMessage.Initiator?.Invoke(damageMessage);
|
|
damageMessage.Target?.Invoke(damageMessage);
|
|
|
|
if (heal!.IsAlive)
|
|
{
|
|
OnEntityDamaged?.Invoke(damageMessage);
|
|
|
|
}
|
|
else
|
|
{
|
|
OnEntityKilled?.Invoke(damageMessage);
|
|
}
|
|
}
|
|
|
|
public event Action<DamageMessage> OnEntityDamaged;
|
|
public event Action<DamageMessage> OnEntityKilled;
|
|
public void Execute(DamageMessage damageMessage)=>Messages.Enqueue(damageMessage);
|
|
|
|
|
|
}
|
|
} |