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.

243 lines
7.8KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Gamecraft.ColourPalette;
  5. using Gamecraft.Wires;
  6. using RobocraftX.Blocks;
  7. using RobocraftX.Common;
  8. using RobocraftX.Physics;
  9. using RobocraftX.Rendering;
  10. using RobocraftX.Rendering.GPUI;
  11. using Svelto.DataStructures;
  12. using Svelto.ECS;
  13. using Svelto.ECS.EntityStructs;
  14. using Svelto.ECS.Experimental;
  15. using Techblox.ObjectIDBlockServer;
  16. using TechbloxModdingAPI.Common.Engines;
  17. using Unity.Mathematics;
  18. using TechbloxModdingAPI.Utility.ECS;
  19. using PrefabsID = RobocraftX.Common.PrefabsID;
  20. namespace TechbloxModdingAPI.Blocks.Engines
  21. {
  22. /// <summary>
  23. /// Engine for executing general block actions
  24. /// </summary>
  25. public partial class BlockEngine : IApiEngine
  26. {
  27. public string Name { get; } = "TechbloxModdingAPIBlockGameEngine";
  28. public EntitiesDB entitiesDB { set; private get; }
  29. public bool isRemovable => false;
  30. public void Dispose()
  31. {
  32. }
  33. public void Ready()
  34. {
  35. }
  36. public Block[] GetConnectedBlocks(EGID blockID)
  37. {
  38. if (!BlockExists(blockID)) return Array.Empty<Block>();
  39. Stack<EGID> cubeStack = new Stack<EGID>();
  40. FasterList<EGID> cubes = new FasterList<EGID>(10);
  41. var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  42. foreach (var ((ecoll, count), _) in coll)
  43. {
  44. for(int i = 0; i < count; i++)
  45. {
  46. ecoll[i].areConnectionsAssigned = false;
  47. }
  48. }
  49. //TODO: GetConnectedCubesUtility
  50. /*ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubes,
  51. (in GridConnectionsEntityStruct _) => false);*/
  52. var ret = new Block[cubes.count];
  53. for (int i = 0; i < cubes.count; i++)
  54. ret[i] = Block.New(cubes[i]);
  55. return ret;
  56. }
  57. public float4 ConvertBlockColor(byte index) => index == byte.MaxValue
  58. ? new float4(-1f, -1f, -1f, -1f)
  59. : entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index,
  60. ColourPaletteExclusiveGroups.COLOUR_PALETTE_GROUP).Colour;
  61. public void UpdateDisplayData(EGID id)
  62. {
  63. if (!BlockExists(id)) return;
  64. var pos = entitiesDB.QueryEntity<PositionEntityStruct>(id);
  65. var rot = entitiesDB.QueryEntity<RotationEntityStruct>(id);
  66. var scale = entitiesDB.QueryEntity<ScalingEntityStruct>(id);
  67. var skew = entitiesDB.QueryEntity<SkewComponent>(id);
  68. entitiesDB.QueryEntity<RenderingDataStruct>(id).matrix =
  69. math.mul(float4x4.TRS(pos.position, rot.rotation, scale.scale), skew.skewMatrix);
  70. entitiesDB.PublishEntityChangeDelayed<GFXPrefabEntityStructGPUI>(id); // Signal a prefab change so it updates the render buffers
  71. }
  72. internal void UpdateDisplayedPrefab(Block block, byte material, bool flipped)
  73. {
  74. var prefabAssetIDOpt = entitiesDB.QueryEntityOptional<PrefabAssetIDComponent>(block);
  75. uint prefabAssetID = prefabAssetIDOpt
  76. ? prefabAssetIDOpt.Get().prefabAssetID
  77. : uint.MaxValue;
  78. if (prefabAssetID == uint.MaxValue)
  79. {
  80. if (entitiesDB.QueryEntityOptional<BlockTagEntityStruct>(block)) //The block exists
  81. throw new BlockException("Prefab asset ID not found for block " + block); //Set by the game
  82. return;
  83. }
  84. uint prefabId =
  85. PrefabsID.GetOrAddPrefabID((ushort) prefabAssetID, material, 1, flipped);
  86. entitiesDB.QueryEntityOrDefault<GFXPrefabEntityStructGPUI>(block).prefabID = prefabId;
  87. if (block.Exists)
  88. {
  89. entitiesDB.PublishEntityChangeDelayed<CubeMaterialStruct>(block.Id);
  90. entitiesDB.PublishEntityChangeDelayed<GFXPrefabEntityStructGPUI>(block.Id);
  91. /*ref BuildingActionComponent local =
  92. ref entitiesDB.QueryEntity<BuildingActionComponent>(BuildingDroneUtility
  93. .GetLocalBuildingDrone(entitiesDB).ToEGID(entitiesDB));
  94. local.buildAction = BuildAction.ChangeMaterial;
  95. local.targetPosition = block.Position; - TODO: This probably only plays the audio
  96. this.entitiesDB.PublishEntityChangeDelayed<BuildingActionComponent>(local.ID);*/
  97. }
  98. //Phyiscs prefab: prefabAssetID, set on block creation from the CubeListData
  99. }
  100. public void UpdateBlockColor(EGID id)
  101. {
  102. entitiesDB.PublishEntityChangeDelayed<ColourParameterEntityStruct>(id);
  103. }
  104. public bool BlockExists(EGID blockID)
  105. {
  106. return entitiesDB.Exists<BlockTagEntityStruct>(blockID);
  107. }
  108. public SimBody[] GetSimBodiesFromID(byte id)
  109. {
  110. var ret = new FasterList<SimBody>(4);
  111. var oids = entitiesDB.QueryEntitiesOptional<ObjectIdEntityStruct>(ObjectIDBlockExclusiveGroups.OBJECT_ID_BLOCK_GROUP);
  112. EGIDMapper<GridConnectionsEntityStruct>? connections = null;
  113. foreach (var oid in oids)
  114. {
  115. if (oid.Get().objectId != id) continue;
  116. if (!connections.HasValue) //Would need reflection to get the group from the build group otherwise
  117. connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(oid.EGID.groupID);
  118. //var rid = connections.Value.Entity(tag.ID.entityID).machineRigidBodyId;
  119. /*foreach (var rb in ret) - TODO
  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 SimBody[] GetConnectedSimBodies(uint id)
  130. {
  131. var (joints, count) = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP);
  132. var list = new FasterList<SimBody>(4);
  133. for (int i = 0; i < count; i++)
  134. {
  135. ref var joint = ref joints[i];
  136. if (joint.isBroken) continue;
  137. /*if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB)); - TODO:
  138. else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));*/
  139. }
  140. return list.ToArray();
  141. }
  142. public SimBody[] GetClusterBodies(uint cid)
  143. {
  144. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  145. var bodies = new HashSet<uint>();
  146. foreach (var ((coll, count), _) in groups)
  147. {
  148. for (var index = 0; index < count; index++)
  149. {
  150. var conn = coll[index];
  151. /*if (conn.clusterId == cid) - TODO
  152. bodies.Add(conn.machineRigidBodyId);*/
  153. }
  154. }
  155. return bodies.Select(id => new SimBody(id, cid)).ToArray();
  156. }
  157. public EGID? FindBlockEGID(uint id)
  158. {
  159. var groups = entitiesDB.FindGroups<BlockTagEntityStruct>();
  160. foreach (ExclusiveGroupStruct group in groups)
  161. {
  162. if (entitiesDB.Exists<BlockTagEntityStruct>(id, group))
  163. return new EGID(id, group);
  164. }
  165. return null;
  166. }
  167. public Cluster GetCluster(uint sbid)
  168. {
  169. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  170. foreach (var ((coll, count), _) in groups)
  171. {
  172. for (var index = 0; index < count; index++)
  173. {
  174. var conn = coll[index];
  175. //Static blocks don't have a cluster ID but the cluster destruction manager should have one
  176. /*if (conn.machineRigidBodyId == sbid && conn.clusterId != uint.MaxValue) - TODO:
  177. return new Cluster(conn.clusterId);*/
  178. }
  179. }
  180. return null;
  181. }
  182. public Block[] GetBodyBlocks(uint sbid)
  183. {
  184. var groups = entitiesDB.FindGroups<GridConnectionsEntityStruct>();
  185. groups = new QueryGroups(groups).Except(CommonExclusiveGroups.DISABLED_JOINTS_IN_SIM_GROUP).Evaluate().result;
  186. var set = new HashSet<Block>();
  187. foreach (var ((coll, tags, count), _) in entitiesDB.QueryEntities<GridConnectionsEntityStruct, BlockTagEntityStruct>(groups))
  188. {
  189. for (var index = 0; index < count; index++)
  190. {
  191. var conn = coll[index];
  192. /*if (conn.machineRigidBodyId == sbid) - TODO
  193. set.Add(Block.New(tags[index].ID));*/
  194. }
  195. }
  196. return set.ToArray();
  197. }
  198. public ObjectID[] GetObjectIDsFromID(byte id)
  199. {
  200. if (!entitiesDB.HasAny<ObjectIDTweakableComponent>(ObjectIDBlockExclusiveGroups.OBJECT_ID_BLOCK_GROUP))
  201. return Array.Empty<ObjectID>();
  202. var ret = new FasterList<ObjectID>(4);
  203. var oids = entitiesDB.QueryEntitiesOptional<ObjectIDTweakableComponent>(ObjectIDBlockExclusiveGroups.OBJECT_ID_BLOCK_GROUP);
  204. foreach (var oid in oids)
  205. {
  206. if (oid.Get().objectIDToTrigger == id)
  207. ret.Add(new ObjectID(oid.EGID));
  208. }
  209. return ret.ToArray();
  210. }
  211. }
  212. }