A stable modding interface between Techblox and mods https://mod.exmods.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
5.7KB

  1. using System;
  2. using Svelto.ECS;
  3. using Unity.Mathematics;
  4. using UnityEngine;
  5. using Gamecraft.Damage;
  6. using RobocraftX.Common;
  7. using RobocraftX.Physics;
  8. namespace TechbloxModdingAPI
  9. {
  10. /// <summary>
  11. /// A rigid body (like a chunk of connected blocks) during simulation.
  12. /// </summary>
  13. public class SimBody : EcsObjectBase, IEquatable<SimBody>, IEquatable<EGID>
  14. {
  15. public override EGID Id { get; }
  16. /// <summary>
  17. /// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist.
  18. /// Get the SimBody from a Block if possible for good performance here.
  19. /// </summary>
  20. public Cluster Cluster => cluster ?? (cluster = clusterId == uint.MaxValue ? Block.BlockEngine.GetCluster(Id.entityID) : new Cluster(clusterId));
  21. private Cluster cluster;
  22. private readonly uint clusterId = uint.MaxValue;
  23. public SimBody(EGID id)
  24. {
  25. Id = id;
  26. }
  27. public SimBody(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_BODIES_GROUP))
  28. {
  29. }
  30. internal SimBody(uint id, uint clusterID) : this(id)
  31. {
  32. clusterId = clusterID;
  33. }
  34. /// <summary>
  35. /// The position of this body. When setting the position, update the position of the connected bodies as well,
  36. /// otherwise unexpected forces may arise.
  37. /// </summary>
  38. public float3 Position
  39. {
  40. get => GetStruct().position;
  41. set => GetStruct().position = value;
  42. }
  43. public float3 Velocity
  44. {
  45. get => GetStruct().velocity;
  46. set => GetStruct().velocity = value;
  47. }
  48. public float3 AngularVelocity
  49. {
  50. get => GetStruct().angularVelocity;
  51. set => GetStruct().angularVelocity = value;
  52. } //Delta versions are used internally, can't be set or get
  53. public float3 Rotation
  54. {
  55. get => ((Quaternion) GetStruct().rotation).eulerAngles;
  56. set
  57. {
  58. ref var str = ref GetStruct();
  59. Quaternion quaternion = str.rotation;
  60. quaternion.eulerAngles = value;
  61. str.rotation = quaternion;
  62. }
  63. }
  64. public float Mass
  65. {
  66. get => math.rcp(GetStruct().physicsMass.InverseMass);
  67. //set => GetStruct().physicsMass.InverseMass = math.rcp(value);
  68. }
  69. public float3 CenterOfMass
  70. {
  71. get => GetStruct().physicsMass.CenterOfMass;
  72. //set => GetStruct().physicsMass.CenterOfMass = value;
  73. }
  74. public float Volume
  75. {
  76. get => GetStruct().volume;
  77. }
  78. public float InitialHealth
  79. {
  80. get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth;
  81. set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth = value;
  82. }
  83. public float CurrentHealth
  84. {
  85. get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth;
  86. set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth = value;
  87. }
  88. public float HealthMultiplier
  89. {
  90. get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier;
  91. set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier = value;
  92. }
  93. /// <summary>
  94. /// Whether the body can be moved or static.
  95. /// </summary>
  96. public bool Static => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(this).isStatic; //Setting it doesn't have any effect
  97. /// <summary>
  98. /// The rigid bodies connected to this one via functional joints (broken ones don't count).
  99. /// </summary>
  100. public SimBody[] GetConnectedBodies()
  101. {
  102. return Block.BlockEngine.GetConnectedSimBodies(Id.entityID);
  103. }
  104. /// <summary>
  105. /// The blocks that form this rigid body.
  106. /// </summary>
  107. /// <returns></returns>
  108. public Block[] GetBlocks()
  109. {
  110. return Block.BlockEngine.GetBodyBlocks(Id.entityID);
  111. }
  112. private ref RigidBodyEntityStruct GetStruct()
  113. {
  114. return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(this);
  115. }
  116. public override string ToString()
  117. {
  118. return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Mass)}: {Mass}, {nameof(Static)}: {Static}";
  119. }
  120. public bool Equals(SimBody other)
  121. {
  122. if (ReferenceEquals(null, other)) return false;
  123. if (ReferenceEquals(this, other)) return true;
  124. return Id.Equals(other.Id);
  125. }
  126. public bool Equals(EGID other)
  127. {
  128. return Id.Equals(other);
  129. }
  130. public override bool Equals(object obj)
  131. {
  132. if (ReferenceEquals(null, obj)) return false;
  133. if (ReferenceEquals(this, obj)) return true;
  134. if (obj.GetType() != this.GetType()) return false;
  135. return Equals((SimBody) obj);
  136. }
  137. public override int GetHashCode()
  138. {
  139. return Id.GetHashCode();
  140. }
  141. /// <summary>
  142. /// Returns the object identified by the given ID (A-Z).
  143. /// This has the same result as calling ObjectIdentifier.GetByID(id) and then GetRigidBody() with the duplicates filtered out.
  144. /// </summary>
  145. /// <param name="id">The alphabetical ID</param>
  146. /// <returns>An array that may be empty</returns>
  147. public static SimBody[] GetFromObjectID(char id) => Block.BlockEngine.GetSimBodiesFromID((byte) (id - 'A'));
  148. }
  149. }