A stable modding interface between Techblox and mods https://mod.exmods.org/
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

264 строки
7.7KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Gamecraft.ColourPalette;
  5. using Gamecraft.TimeRunning;
  6. using Gamecraft.Wires;
  7. using RobocraftX.Blocks;
  8. using RobocraftX.Common;
  9. using RobocraftX.Physics;
  10. using RobocraftX.Rendering;
  11. using RobocraftX.Rendering.GPUI;
  12. using Svelto.ECS.EntityStructs;
  13. using Svelto.DataStructures;
  14. using Svelto.ECS;
  15. using Svelto.ECS.Hybrid;
  16. using Unity.Mathematics;
  17. using TechbloxModdingAPI.Engines;
  18. using TechbloxModdingAPI.Utility;
  19. namespace TechbloxModdingAPI.Blocks
  20. {
  21. /// <summary>
  22. /// Engine for executing general block actions
  23. /// </summary>
  24. public partial class BlockEngine : IApiEngine
  25. {
  26. public string Name { get; } = "TechbloxModdingAPIBlockGameEngine";
  27. public EntitiesDB entitiesDB { set; private get; }
  28. public bool isRemovable => false;
  29. public void Dispose()
  30. {
  31. }
  32. public void Ready()
  33. {
  34. }
  35. public Block[] GetConnectedBlocks(EGID blockID)
  36. {
  37. if (!BlockExists(blockID)) return new Block[0];
  38. Stack<EGID> cubeStack = new Stack<EGID>();
  39. FasterList<EGID> cubes = new FasterList<EGID>(10);
  40. var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  41. foreach (var (ecoll, _) in coll)
  42. {
  43. var ecollB = ecoll.ToBuffer();
  44. for(int i = 0; i < ecoll.count; i++)
  45. {
  46. ref var conn = ref ecollB.buffer[i];
  47. conn.isProcessed = false;
  48. }
  49. }
  50. ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubes,
  51. (in GridConnectionsEntityStruct g) => { return 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. CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour;
  61. public OptionalRef<T> GetBlockInfoOptional<T>(Block block) where T : unmanaged, IEntityComponent
  62. {
  63. return entitiesDB.QueryEntityOptional<T>(block);
  64. }
  65. public ref T GetBlockInfo<T>(Block block) where T : unmanaged, IEntityComponent
  66. {
  67. return ref entitiesDB.QueryEntityOrDefault<T>(block);
  68. }
  69. internal ref T GetBlockInfo<T>(EcsObjectBase obj) where T : unmanaged, IEntityComponent
  70. {
  71. return ref entitiesDB.QueryEntityOrDefault<T>(obj);
  72. }
  73. public ref T GetBlockInfoViewComponent<T>(Block block) where T : struct, IEntityViewComponent
  74. {
  75. return ref entitiesDB.QueryEntityOrDefault<T>(block);
  76. }
  77. public void UpdateDisplayedBlock(EGID id)
  78. {
  79. if (!BlockExists(id)) return;
  80. var pos = entitiesDB.QueryEntity<PositionEntityStruct>(id);
  81. var rot = entitiesDB.QueryEntity<RotationEntityStruct>(id);
  82. var scale = entitiesDB.QueryEntity<ScalingEntityStruct>(id);
  83. entitiesDB.QueryEntity<RenderingDataStruct>(id).matrix = float4x4.TRS(pos.position, rot.rotation, scale.scale);
  84. }
  85. internal void UpdatePrefab(Block block, byte material, bool flipped)
  86. {
  87. var prefabAssetIDOpt = entitiesDB.QueryEntityOptional<PrefabAssetIDComponent>(block);
  88. uint prefabAssetID = prefabAssetIDOpt
  89. ? prefabAssetIDOpt.Get().prefabAssetID
  90. : uint.MaxValue;
  91. if (prefabAssetID == uint.MaxValue)
  92. {
  93. if (entitiesDB.QueryEntityOptional<DBEntityStruct>(block)) //The block exists
  94. throw new BlockException("Prefab asset ID not found for block " + block); //Set by the game
  95. return;
  96. }
  97. uint prefabId =
  98. PrefabsID.GetOrCreatePrefabID((ushort) prefabAssetID, material, 1, flipped);
  99. entitiesDB.QueryEntityOrDefault<GFXPrefabEntityStructGPUI>(block).prefabID = prefabId;
  100. if (block.Exists)
  101. entitiesDB.PublishEntityChange<GFXPrefabEntityStructGPUI>(block.Id);
  102. //Phyiscs prefab: prefabAssetID, set on block creation from the CubeListData
  103. /*Console.WriteLine("Materials:\n" + FullGameFields._dataDb.GetValues<MaterialPropertiesData>()
  104. .Select(kv => $"{kv.Key}: {((MaterialPropertiesData) kv.Value).Name}")
  105. .Aggregate((a, b) => a + "\n" + b));*/
  106. }
  107. public bool BlockExists(EGID blockID)
  108. {
  109. return entitiesDB.Exists<DBEntityStruct>(blockID);
  110. }
  111. public SimBody[] GetSimBodiesFromID(byte id)
  112. {
  113. var ret = new FasterList<SimBody>(4);
  114. var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>();
  115. EGIDMapper<GridConnectionsEntityStruct>? connections = null;
  116. foreach (var ((oids, count), _) in oide)
  117. {
  118. for (int i = 0; i < count; i++)
  119. {
  120. ref ObjectIdEntityStruct oid = ref oids[i];
  121. if (oid.objectId != id) continue;
  122. if (!connections.HasValue) //Would need reflection to get the group from the build group otherwise
  123. connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(oid.ID.groupID);
  124. var rid = connections.Value.Entity(oid.ID.entityID).machineRigidBodyId;
  125. foreach (var rb in ret)
  126. {
  127. if (rb.Id.entityID == rid)
  128. goto DUPLICATE; //Multiple Object Identifiers on one rigid body
  129. }
  130. ret.Add(new SimBody(rid));
  131. DUPLICATE: ;
  132. }
  133. }
  134. return ret.ToArray();
  135. }
  136. public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim)
  137. {
  138. var ret = new FasterList<ObjectIdentifier>(4);
  139. var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>();
  140. foreach (var ((oids, count), _) in oide)
  141. {
  142. for (int i = 0; i < count; i++)
  143. {
  144. ref ObjectIdEntityStruct oid = ref oids[i];
  145. if (sim ? oid.simObjectId == id : oid.objectId == id)
  146. ret.Add(new ObjectIdentifier(oid.ID));
  147. }
  148. }
  149. return ret.ToArray();
  150. }
  151. public SimBody[] GetConnectedSimBodies(uint id)
  152. {
  153. var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP).ToBuffer();
  154. var list = new FasterList<SimBody>(4);
  155. for (int i = 0; i < joints.count; i++)
  156. {
  157. ref var joint = ref joints.buffer[i];
  158. if (joint.isBroken) continue;
  159. if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB));
  160. else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));
  161. }
  162. return list.ToArray();
  163. }
  164. public SimBody[] GetClusterBodies(uint cid)
  165. {
  166. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  167. var bodies = new HashSet<uint>();
  168. foreach (var (coll, _) in groups)
  169. {
  170. var array = coll.ToBuffer().buffer;
  171. for (var index = 0; index < array.capacity; index++)
  172. {
  173. var conn = array[index];
  174. if (conn.clusterId == cid)
  175. bodies.Add(conn.machineRigidBodyId);
  176. }
  177. }
  178. return bodies.Select(id => new SimBody(id, cid)).ToArray();
  179. }
  180. public EGID? FindBlockEGID(uint id)
  181. {
  182. var groups = entitiesDB.FindGroups<DBEntityStruct>();
  183. foreach (ExclusiveGroupStruct group in groups)
  184. {
  185. if (entitiesDB.Exists<DBEntityStruct>(id, group))
  186. return new EGID(id, group);
  187. }
  188. return null;
  189. }
  190. public Cluster GetCluster(uint sbid)
  191. {
  192. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  193. foreach (var (coll, _) in groups)
  194. {
  195. var array = coll.ToBuffer().buffer;
  196. for (var index = 0; index < array.capacity; index++)
  197. {
  198. var conn = array[index];
  199. //Static blocks don't have a cluster ID but the cluster destruction manager should have one
  200. if (conn.machineRigidBodyId == sbid && conn.clusterId != uint.MaxValue)
  201. return new Cluster(conn.clusterId);
  202. }
  203. }
  204. return null;
  205. }
  206. public Block[] GetBodyBlocks(uint sbid)
  207. {
  208. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  209. var set = new HashSet<Block>();
  210. foreach (var (coll, _) in groups)
  211. {
  212. var array = coll.ToBuffer().buffer;
  213. for (var index = 0; index < array.capacity; index++)
  214. {
  215. var conn = array[index];
  216. if (conn.machineRigidBodyId == sbid)
  217. set.Add(Block.New(conn.ID));
  218. }
  219. }
  220. return set.ToArray();
  221. }
  222. #if DEBUG
  223. public EntitiesDB GetEntitiesDB()
  224. {
  225. return entitiesDB;
  226. }
  227. #endif
  228. }
  229. }