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.9KB

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