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.

204 lines
6.0KB

  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<EGID> cubeStack = new Stack<EGID>();
  33. FasterList<EGID> cubes = new FasterList<EGID>(10);
  34. var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  35. foreach (var (ecoll, _) in coll)
  36. foreach (ref var conn in ecoll)
  37. conn.isProcessed = false;
  38. ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubes,
  39. (in GridConnectionsEntityStruct g) => { return false; });
  40. var ret = new Block[cubes.count];
  41. for (int i = 0; i < cubes.count; i++)
  42. ret[i] = new Block(cubes[i]);
  43. return ret;
  44. }
  45. public void SetBlockColorFromPalette(ref ColourParameterEntityStruct color)
  46. {
  47. ref var paletteEntry = ref entitiesDB.QueryEntity<PaletteEntryEntityStruct>(color.indexInPalette,
  48. CommonExclusiveGroups.COLOUR_PALETTE_GROUP);
  49. color.paletteColour = paletteEntry.Colour;
  50. }
  51. /// <summary>
  52. /// Get a struct of a block. Can be used to set properties.
  53. /// Returns a default value if not found.
  54. /// </summary>
  55. /// <param name="blockID">The block's ID</param>
  56. /// <typeparam name="T">The struct to query</typeparam>
  57. /// <returns>An editable reference to the struct</returns>
  58. public ref T GetBlockInfo<T>(EGID blockID) where T : struct, IEntityComponent
  59. {
  60. if (!Synced)
  61. {
  62. Sync();
  63. Synced = true;
  64. }
  65. if (entitiesDB.Exists<T>(blockID))
  66. return ref entitiesDB.QueryEntity<T>(blockID);
  67. T[] structHolder = new T[1]; //Create something that can be referenced
  68. return ref structHolder[0]; //Gets a default value automatically
  69. }
  70. /// <summary>
  71. /// Get a struct of a block. Can be used to set properties.
  72. /// Returns a default value if not found.
  73. /// </summary>
  74. /// <param name="blockID">The block's ID</param>
  75. /// <param name="exists">Whether the specified struct exists for the block</param>
  76. /// <typeparam name="T">The struct to query</typeparam>
  77. /// <returns>An editable reference to the struct</returns>
  78. public ref T GetBlockInfo<T>(EGID blockID, out bool exists) where T : struct, IEntityComponent
  79. {
  80. if (!Synced)
  81. {
  82. Sync();
  83. Synced = true;
  84. }
  85. exists = entitiesDB.Exists<T>(blockID);
  86. if (exists)
  87. return ref entitiesDB.QueryEntity<T>(blockID);
  88. T[] structHolder = new T[1];
  89. return ref structHolder[0];
  90. }
  91. public bool BlockExists(EGID id)
  92. {
  93. if (!Synced)
  94. {
  95. Sync();
  96. Synced = true;
  97. }
  98. return entitiesDB.Exists<DBEntityStruct>(id);
  99. }
  100. public bool GetBlockInfoExists<T>(EGID blockID) where T : struct, IEntityComponent
  101. {
  102. if (!Synced)
  103. {
  104. Sync();
  105. Synced = true;
  106. }
  107. return entitiesDB.Exists<T>(blockID);
  108. }
  109. public SimBody[] GetSimBodiesFromID(byte id)
  110. {
  111. var ret = new FasterList<SimBody>(4);
  112. if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP))
  113. return new SimBody[0];
  114. var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP);
  115. var connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP);
  116. foreach (ref ObjectIdEntityStruct oid in oids)
  117. {
  118. if (oid.objectId != id) continue;
  119. var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId;
  120. foreach (var rb in ret)
  121. {
  122. if (rb.Id.entityID == rid)
  123. goto DUPLICATE; //Multiple Object Identifiers on one rigid body
  124. }
  125. ret.Add(new SimBody(rid));
  126. DUPLICATE: ;
  127. }
  128. return ret.ToArray();
  129. }
  130. public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim)
  131. {
  132. var ret = new FasterList<ObjectIdentifier>(4);
  133. if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP))
  134. return new ObjectIdentifier[0];
  135. var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP);
  136. foreach (ref ObjectIdEntityStruct oid in oids)
  137. if (sim ? oid.simObjectId == id : oid.objectId == id)
  138. ret.Add(new ObjectIdentifier(oid.ID));
  139. return ret.ToArray();
  140. }
  141. public SimBody[] GetConnectedSimBodies(uint id)
  142. {
  143. var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP);
  144. var list = new FasterList<SimBody>(4);
  145. foreach (var joint in joints)
  146. {
  147. if (joint.jointState == JointState.Broken) continue;
  148. if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB));
  149. else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));
  150. }
  151. return list.ToArray();
  152. }
  153. public EGID? FindBlockEGID(uint id)
  154. {
  155. var groups = entitiesDB.FindGroups<DBEntityStruct>();
  156. foreach (ExclusiveGroupStruct group in groups)
  157. {
  158. if (entitiesDB.Exists<DBEntityStruct>(id, group))
  159. return new EGID(id, group);
  160. }
  161. return null;
  162. }
  163. /// <summary>
  164. /// Synchronize newly created entity components with entities DB.
  165. /// This forces a partial game tick, so it may be slow.
  166. /// This also has the potential to make Gamecraft unstable.
  167. /// Use this sparingly.
  168. /// </summary>
  169. private static void Sync()
  170. {
  171. DeterministicStepCompositionRootPatch.SubmitEntitiesNow();
  172. }
  173. #if DEBUG
  174. public EntitiesDB GetEntitiesDB()
  175. {
  176. return entitiesDB;
  177. }
  178. #endif
  179. }
  180. }