TechbloxModdingAPI/TechbloxModdingAPI/SimBody.cs

177 lines
5.9 KiB
C#

using System;
using Svelto.ECS;
using Unity.Mathematics;
using UnityEngine;
using Gamecraft.Damage;
using RobocraftX.Common;
using RobocraftX.Physics;
namespace TechbloxModdingAPI
{
/// <summary>
/// A rigid body (like a chunk of connected blocks) during simulation.
/// </summary>
public class SimBody : EcsObjectBase, IEquatable<SimBody>, IEquatable<EGID>
{
/// <summary>
/// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist.
/// Get the SimBody from a Block if possible for good performance here.
/// </summary>
public Cluster Cluster => cluster ??= clusterId == uint.MaxValue // Return cluster or if it's null then set it
? Block.BlockEngine.GetCluster(Id.entityID) // If we don't have a clusterId set then get it from the game
: GetInstance(new EGID(clusterId, CommonExclusiveGroups.SIMULATION_CLUSTERS_GROUP),
egid => new Cluster(egid)); // Otherwise get the cluster from the ID
private Cluster cluster;
private readonly uint clusterId = uint.MaxValue;
public SimBody(EGID id) : base(id)
{
}
public SimBody(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_BODIES_GROUP))
{
}
internal SimBody(uint id, uint clusterID) : this(id)
{
clusterId = clusterID;
}
/// <summary>
/// The position of this body. When setting the position, update the position of the connected bodies as well,
/// otherwise unexpected forces may arise.
/// </summary>
public float3 Position
{
get => GetStruct().position;
set => GetStruct().position = value;
}
public float3 Velocity
{
get => GetStruct().velocity;
set => GetStruct().velocity = value;
}
public float3 AngularVelocity
{
get => GetStruct().angularVelocity;
set => GetStruct().angularVelocity = value;
} //Delta versions are used internally, can't be set or get
public float3 Rotation
{
get => ((Quaternion) GetStruct().rotation).eulerAngles;
set
{
ref var str = ref GetStruct();
Quaternion quaternion = str.rotation;
quaternion.eulerAngles = value;
str.rotation = quaternion;
}
}
[Obsolete] //Cannot get mass even from UECS
public float Mass
{
get => 0f;
//set => GetStruct().physicsMass.InverseMass = math.rcp(value);
}
public float3 CenterOfMass
{
get => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(this).centreOfMass;
//set => GetStruct().physicsMass.CenterOfMass = value;
}
public float Volume
{
get => GetStruct().volume;
}
public float InitialHealth
{
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth = value;
}
public float CurrentHealth
{
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth = value;
}
public float HealthMultiplier
{
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier = value;
}
/// <summary>
/// Whether the body can be moved or static.
/// </summary>
public bool Static => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(this).isStatic; //Setting it doesn't have any effect
/// <summary>
/// The rigid bodies connected to this one via functional joints (broken ones don't count).
/// </summary>
public SimBody[] GetConnectedBodies()
{
return Block.BlockEngine.GetConnectedSimBodies(Id.entityID);
}
/// <summary>
/// The blocks that form this rigid body.
/// </summary>
/// <returns></returns>
public Block[] GetBlocks()
{
return Block.BlockEngine.GetBodyBlocks(Id.entityID);
}
private ref RigidBodyEntityStruct GetStruct()
{
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(this);
}
public override string ToString()
{
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Mass)}: {Mass}, {nameof(Static)}: {Static}";
}
public bool Equals(SimBody other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Id.Equals(other.Id);
}
public bool Equals(EGID other)
{
return Id.Equals(other);
}
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((SimBody) obj);
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
/// <summary>
/// Returns the object identified by the given ID (A-Z).
/// This has the same result as calling ObjectIdentifier.GetByID(id) and then GetRigidBody() with the duplicates filtered out.
/// </summary>
/// <param name="id">The alphabetical ID</param>
/// <returns>An array that may be empty</returns>
public static SimBody[] GetFromObjectID(char id) => Block.BlockEngine.GetSimBodiesFromID((byte) (id - 'A'));
}
}