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.

181 lines
5.5KB

  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. return entitiesDB.Exists<DBEntityStruct>(id);
  93. }
  94. public bool GetBlockInfoExists<T>(EGID blockID) where T : struct, IEntityComponent
  95. {
  96. return entitiesDB.Exists<T>(blockID);
  97. }
  98. public SimBody[] GetSimBodiesFromID(byte id)
  99. {
  100. var ret = new FasterList<SimBody>(4);
  101. if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP))
  102. return new SimBody[0];
  103. var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  104. var connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  105. foreach (ref ObjectIdEntityStruct oid in oids)
  106. {
  107. if (oid.objectId != id) continue;
  108. var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId;
  109. foreach (var rb in ret)
  110. {
  111. if (rb.Id.entityID == rid)
  112. goto DUPLICATE; //Multiple Object Identifiers on one rigid body
  113. }
  114. ret.Add(new SimBody(rid));
  115. DUPLICATE: ;
  116. }
  117. return ret.ToArray();
  118. }
  119. public ObjectIdentifier[] GetObjectIDsFromID(byte id)
  120. {
  121. var ret = new FasterList<ObjectIdentifier>(4);
  122. if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP))
  123. return new ObjectIdentifier[0];
  124. var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  125. foreach (ref ObjectIdEntityStruct oid in oids)
  126. if (oid.objectId == id)
  127. ret.Add(new ObjectIdentifier(oid.ID));
  128. return ret.ToArray();
  129. }
  130. public SimBody[] GetConnectedSimBodies(uint id)
  131. {
  132. var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP);
  133. var list = new FasterList<SimBody>(4);
  134. foreach (var joint in joints)
  135. {
  136. if (joint.jointState == JointState.Broken) continue;
  137. if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB));
  138. else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));
  139. }
  140. return list.ToArray();
  141. }
  142. /// <summary>
  143. /// Synchronize newly created entity components with entities DB.
  144. /// This forces a partial game tick, so it may be slow.
  145. /// This also has the potential to make Gamecraft unstable.
  146. /// Use this sparingly.
  147. /// </summary>
  148. private static void Sync()
  149. {
  150. DeterministicStepCompositionRootPatch.SubmitEntitiesNow();
  151. }
  152. #if DEBUG
  153. public EntitiesDB GetEntitiesDB()
  154. {
  155. return entitiesDB;
  156. }
  157. #endif
  158. }
  159. }