Files
AreaJumpDepleter/AreaJumpDepleter/Utils/TriggerArea.cs
2022-11-16 22:56:13 +07:00

116 lines
3.3 KiB
C#

using Havok;
using Sandbox.Engine.Physics;
using Sandbox.Game.Entities;
using VRage;
using VRage.Game.Components;
using VRage.Game.Entity;
using VRage.ObjectBuilders;
using VRageMath;
namespace AreaJumpDepleter.Utils;
public class TriggerArea : IDisposable, IEquatable<TriggerArea>
{
private Dummy? _entity;
public BoundingSphere Sphere { get; }
public event EventHandler<MyEntity>? EntityEntered;
public event EventHandler<MyEntity>? EntityLeft;
public TriggerArea(BoundingSphere sphere)
{
Sphere = sphere;
}
public void Create()
{
_entity = new Dummy(Sphere, EnterHandler, ExitHandler);
_entity.Init(null);
MyEntities.Add(_entity);
}
private void ExitHandler(MyEntity entity)
{
EntityEntered?.Invoke(this, entity);
}
private void EnterHandler(MyEntity entity)
{
EntityLeft?.Invoke(this, entity);
}
public void Dispose()
{
if (_entity != null)
MyEntities.Close(_entity);
}
public bool Equals(TriggerArea? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Sphere.Equals(other.Sphere);
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TriggerArea)obj);
}
public override int GetHashCode()
{
return Sphere.GetHashCode();
}
private class Dummy : MyEntity
{
private readonly BoundingSphere _sphere;
private readonly Action<MyEntity> _enterHandler;
private readonly Action<MyEntity> _exitHandler;
public Dummy(BoundingSphere sphere, Action<MyEntity> enterHandler, Action<MyEntity> exitHandler)
{
_sphere = sphere;
_enterHandler = enterHandler;
_exitHandler = exitHandler;
}
public override void Init(MyObjectBuilder_EntityBase? objectBuilder)
{
base.Init(objectBuilder);
PositionComp.LocalAABB = BoundingBox.CreateFromSphere(_sphere);
Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_STATIC);
Physics.IsPhantom = true;
var phantom = new HkPhantomCallbackShape(EnterCallback, LeaveCallback);
var shape = new HkBvShape(new HkSphereShape(_sphere.Radius), phantom, HkReferencePolicy.TakeOwnership);
((MyPhysicsBody)Physics).CreateFromCollisionObject(shape, _sphere.Center, MatrixD.Identity);
shape.Base.RemoveReference();
Physics.Enabled = true;
BoundingSphereD sphere = _sphere;
foreach (var entity in MyEntities.GetTopMostEntitiesInSphere(ref sphere))
{
_enterHandler(entity);
}
}
private void LeaveCallback(HkPhantomCallbackShape shape, HkRigidBody body)
{
if (body.GetSingleEntity() is MyEntity entity)
_exitHandler(entity);
}
private void EnterCallback(HkPhantomCallbackShape shape, HkRigidBody body)
{
if (body.GetSingleEntity() is MyEntity entity)
_enterHandler(entity);
}
}
}