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.

191 lines
5.7KB

  1. using System.Collections.Generic;
  2. using Gamecraft.Wires;
  3. using RobocraftX.Blocks;
  4. using RobocraftX.Common;
  5. using RobocraftX.GUI.Hotbar.Colours;
  6. using RobocraftX.Physics;
  7. using RobocraftX.Scene.Simulation;
  8. using Svelto.DataStructures;
  9. using Svelto.ECS;
  10. using GamecraftModdingAPI.Engines;
  11. using GamecraftModdingAPI.Utility;
  12. namespace GamecraftModdingAPI.Blocks
  13. {
  14. /// <summary>
  15. /// Engine for executing general block actions
  16. /// </summary>
  17. public class BlockEngine : IApiEngine
  18. {
  19. public string Name { get; } = "GamecraftModdingAPIBlockGameEngine";
  20. public EntitiesDB entitiesDB { set; private get; }
  21. public bool isRemovable => false;
  22. internal bool Synced = true;
  23. public void Dispose()
  24. {
  25. }
  26. public void Ready()
  27. {
  28. }
  29. public Block[] GetConnectedBlocks(EGID blockID)
  30. {
  31. if (!BlockExists(blockID)) return new Block[0];
  32. Stack<uint> cubeStack = new Stack<uint>();
  33. FasterList<uint> cubes = new FasterList<uint>(10);
  34. var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups
  35. .OWNED_BLOCKS_GROUP);
  36. for (int i = 0; i < coll.count; i++)
  37. coll[i].isProcessed = false;
  38. ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID.entityID, cubeStack, cubes, (in GridConnectionsEntityStruct g) => { return false; });
  39. var ret = new Block[cubes.count];
  40. for (int i = 0; i < cubes.count; i++)
  41. ret[i] = new Block(cubes[i]);
  42. return ret;
  43. }
  44. public void SetBlockColorFromPalette(ref ColourParameterEntityStruct color)
  45. {
  46. ref var paletteEntry = ref entitiesDB.QueryEntity<PaletteEntryEntityStruct>(color.indexInPalette,
  47. CommonExclusiveGroups.COLOUR_PALETTE_GROUP);
  48. color.paletteColour = paletteEntry.Colour;
  49. }
  50. /// <summary>
  51. /// Get a struct of a block. Can be used to set properties.
  52. /// Returns a default value if not found.
  53. /// </summary>
  54. /// <param name="blockID">The block's ID</param>
  55. /// <typeparam name="T">The struct to query</typeparam>
  56. /// <returns>An editable reference to the struct</returns>
  57. public ref T GetBlockInfo<T>(EGID blockID) where T : struct, IEntityComponent
  58. {
  59. if (!Synced)
  60. {
  61. Sync();
  62. Synced = true;
  63. }
  64. if (entitiesDB.Exists<T>(blockID))
  65. return ref entitiesDB.QueryEntity<T>(blockID);
  66. T[] structHolder = new T[1]; //Create something that can be referenced
  67. return ref structHolder[0]; //Gets a default value automatically
  68. }
  69. /// <summary>
  70. /// Get a struct of a block. Can be used to set properties.
  71. /// Returns a default value if not found.
  72. /// </summary>
  73. /// <param name="blockID">The block's ID</param>
  74. /// <param name="exists">Whether the specified struct exists for the block</param>
  75. /// <typeparam name="T">The struct to query</typeparam>
  76. /// <returns>An editable reference to the struct</returns>
  77. public ref T GetBlockInfo<T>(EGID blockID, out bool exists) where T : struct, IEntityComponent
  78. {
  79. if (!Synced)
  80. {
  81. Sync();
  82. Synced = true;
  83. }
  84. exists = entitiesDB.Exists<T>(blockID);
  85. if (exists)
  86. return ref entitiesDB.QueryEntity<T>(blockID);
  87. T[] structHolder = new T[1];
  88. return ref structHolder[0];
  89. }
  90. public bool BlockExists(EGID id)
  91. {
  92. if (!Synced)
  93. {
  94. Sync();
  95. Synced = true;
  96. }
  97. return entitiesDB.Exists<DBEntityStruct>(id);
  98. }
  99. public bool GetBlockInfoExists<T>(EGID blockID) where T : struct, IEntityComponent
  100. {
  101. if (!Synced)
  102. {
  103. Sync();
  104. Synced = true;
  105. }
  106. return entitiesDB.Exists<T>(blockID);
  107. }
  108. public SimBody[] GetSimBodiesFromID(byte id)
  109. {
  110. var ret = new FasterList<SimBody>(4);
  111. if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP))
  112. return new SimBody[0];
  113. var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  114. var connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  115. foreach (ref ObjectIdEntityStruct oid in oids)
  116. {
  117. if (oid.objectId != id) continue;
  118. var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId;
  119. foreach (var rb in ret)
  120. {
  121. if (rb.Id.entityID == rid)
  122. goto DUPLICATE; //Multiple Object Identifiers on one rigid body
  123. }
  124. ret.Add(new SimBody(rid));
  125. DUPLICATE: ;
  126. }
  127. return ret.ToArray();
  128. }
  129. public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim)
  130. {
  131. var ret = new FasterList<ObjectIdentifier>(4);
  132. if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP))
  133. return new ObjectIdentifier[0];
  134. var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  135. foreach (ref ObjectIdEntityStruct oid in oids)
  136. if (sim ? oid.simObjectId == id : oid.objectId == id)
  137. ret.Add(new ObjectIdentifier(oid.ID));
  138. return ret.ToArray();
  139. }
  140. public SimBody[] GetConnectedSimBodies(uint id)
  141. {
  142. var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP);
  143. var list = new FasterList<SimBody>(4);
  144. foreach (var joint in joints)
  145. {
  146. if (joint.jointState == JointState.Broken) continue;
  147. if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB));
  148. else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));
  149. }
  150. return list.ToArray();
  151. }
  152. /// <summary>
  153. /// Synchronize newly created entity components with entities DB.
  154. /// This forces a partial game tick, so it may be slow.
  155. /// This also has the potential to make Gamecraft unstable.
  156. /// Use this sparingly.
  157. /// </summary>
  158. private static void Sync()
  159. {
  160. DeterministicStepCompositionRootPatch.SubmitEntitiesNow();
  161. }
  162. #if DEBUG
  163. public EntitiesDB GetEntitiesDB()
  164. {
  165. return entitiesDB;
  166. }
  167. #endif
  168. }
  169. }