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.

179 lines
6.0KB

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