A stable modding interface between Techblox and mods https://mod.exmods.org/
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

307 Zeilen
9.1KB

  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] = new Block(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> GetBlockInfo<T>(EGID blockID) where T : unmanaged, IEntityComponent
  62. {
  63. return entitiesDB.TryQueryEntitiesAndIndex<T>(blockID, out uint index, out var array)
  64. ? new OptionalRef<T>(array, index)
  65. : new OptionalRef<T>();
  66. }
  67. public ref T GetBlockInfoViewStruct<T>(EGID blockID) where T : struct, INeedEGID, IEntityViewComponent
  68. {
  69. if (entitiesDB.Exists<T>(blockID))
  70. return ref entitiesDB.QueryEntity<T>(blockID);
  71. T[] structHolder = new T[1]; //Create something that can be referenced
  72. return ref structHolder[0]; //Gets a default value automatically
  73. }
  74. public U GetBlockInfo<T, U>(Block block, Func<T, U> getter,
  75. U def = default) where T : unmanaged, IEntityComponent
  76. {
  77. if (entitiesDB.Exists<T>(block.Id))
  78. return getter(entitiesDB.QueryEntity<T>(block.Id));
  79. return GetBlockInitInfo(block, getter, def);
  80. }
  81. public U GetBlockInfoViewStruct<T, U>(Block block, Func<T, U> getter,
  82. U def = default) where T : struct, IEntityViewComponent
  83. {
  84. if (entitiesDB.Exists<T>(block.Id))
  85. return getter(entitiesDB.QueryEntity<T>(block.Id));
  86. return GetBlockInitInfo(block, getter, def);
  87. }
  88. private U GetBlockInitInfo<T, U>(Block block, Func<T, U> getter, U def) where T : struct, IEntityComponent
  89. {
  90. if (block.InitData.Group == null) return def;
  91. var initializer = new EntityInitializer(block.Id, block.InitData.Group, block.InitData.Reference);
  92. if (initializer.Has<T>())
  93. return getter(initializer.Get<T>());
  94. return def;
  95. }
  96. public delegate void Setter<T, U>(ref T component, U value) where T : struct, IEntityComponent;
  97. public void SetBlockInfoViewStruct<T, U>(Block block, Setter<T, U> setter, U value) where T : struct, IEntityViewComponent
  98. {
  99. if (entitiesDB.Exists<T>(block.Id))
  100. setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
  101. else
  102. SetBlockInitInfo(block, setter, value);
  103. }
  104. public void SetBlockInfo<T, U>(Block block, Setter<T, U> setter, U value) where T : unmanaged, IEntityComponent
  105. {
  106. if (entitiesDB.Exists<T>(block.Id))
  107. setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
  108. else
  109. SetBlockInitInfo(block, setter, value);
  110. }
  111. private void SetBlockInitInfo<T, U>(Block block, Setter<T, U> setter, U value)
  112. where T : struct, IEntityComponent
  113. {
  114. if (block.InitData.Group != null)
  115. {
  116. var initializer = new EntityInitializer(block.Id, block.InitData.Group, block.InitData.Reference);
  117. T component = initializer.Has<T>() ? initializer.Get<T>() : default;
  118. ref T structRef = ref component;
  119. setter(ref structRef, value);
  120. initializer.Init(structRef);
  121. }
  122. }
  123. public void UpdateDisplayedBlock(EGID id)
  124. {
  125. if (!BlockExists(id)) return;
  126. var pos = entitiesDB.QueryEntity<PositionEntityStruct>(id);
  127. var rot = entitiesDB.QueryEntity<RotationEntityStruct>(id);
  128. var scale = entitiesDB.QueryEntity<ScalingEntityStruct>(id);
  129. entitiesDB.QueryEntity<RenderingDataStruct>(id).matrix = float4x4.TRS(pos.position, rot.rotation, scale.scale);
  130. }
  131. internal void UpdatePrefab(Block block, ushort type, byte material, bool flipped)
  132. {
  133. uint pid = PrefabsID.GetOrCreatePrefabID(type, material, 0, flipped);
  134. entitiesDB.QueryEntityOrDefault<GFXPrefabEntityStructGPUI>()
  135. }
  136. public bool BlockExists(EGID blockID)
  137. {
  138. return entitiesDB.Exists<DBEntityStruct>(blockID);
  139. }
  140. public bool GetBlockInfoExists<T>(Block block) where T : struct, IEntityComponent
  141. {
  142. if (entitiesDB.Exists<T>(block.Id))
  143. return true;
  144. if (block.InitData.Group == null)
  145. return false;
  146. var init = new EntityInitializer(block.Id, block.InitData.Group, block.InitData.Reference);
  147. return init.Has<T>();
  148. }
  149. public SimBody[] GetSimBodiesFromID(byte id)
  150. {
  151. var ret = new FasterList<SimBody>(4);
  152. var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>();
  153. EGIDMapper<GridConnectionsEntityStruct>? connections = null;
  154. foreach (var ((oids, count), _) in oide)
  155. {
  156. for (int i = 0; i < count; i++)
  157. {
  158. ref ObjectIdEntityStruct oid = ref oids[i];
  159. if (oid.objectId != id) continue;
  160. if (!connections.HasValue) //Would need reflection to get the group from the build group otherwise
  161. connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(oid.ID.groupID);
  162. var rid = connections.Value.Entity(oid.ID.entityID).machineRigidBodyId;
  163. foreach (var rb in ret)
  164. {
  165. if (rb.Id.entityID == rid)
  166. goto DUPLICATE; //Multiple Object Identifiers on one rigid body
  167. }
  168. ret.Add(new SimBody(rid));
  169. DUPLICATE: ;
  170. }
  171. }
  172. return ret.ToArray();
  173. }
  174. public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim)
  175. {
  176. var ret = new FasterList<ObjectIdentifier>(4);
  177. var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>();
  178. foreach (var ((oids, count), _) in oide)
  179. {
  180. for (int i = 0; i < count; i++)
  181. {
  182. ref ObjectIdEntityStruct oid = ref oids[i];
  183. if (sim ? oid.simObjectId == id : oid.objectId == id)
  184. ret.Add(new ObjectIdentifier(oid.ID));
  185. }
  186. }
  187. return ret.ToArray();
  188. }
  189. public SimBody[] GetConnectedSimBodies(uint id)
  190. {
  191. var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP).ToBuffer();
  192. var list = new FasterList<SimBody>(4);
  193. for (int i = 0; i < joints.count; i++)
  194. {
  195. ref var joint = ref joints.buffer[i];
  196. if (joint.isBroken) continue;
  197. if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB));
  198. else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));
  199. }
  200. return list.ToArray();
  201. }
  202. public SimBody[] GetClusterBodies(uint cid)
  203. {
  204. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  205. var bodies = new HashSet<uint>();
  206. foreach (var (coll, _) in groups)
  207. {
  208. var array = coll.ToBuffer().buffer;
  209. for (var index = 0; index < array.capacity; index++)
  210. {
  211. var conn = array[index];
  212. if (conn.clusterId == cid)
  213. bodies.Add(conn.machineRigidBodyId);
  214. }
  215. }
  216. return bodies.Select(id => new SimBody(id, cid)).ToArray();
  217. }
  218. public EGID? FindBlockEGID(uint id)
  219. {
  220. var groups = entitiesDB.FindGroups<DBEntityStruct>();
  221. foreach (ExclusiveGroupStruct group in groups)
  222. {
  223. if (entitiesDB.Exists<DBEntityStruct>(id, group))
  224. return new EGID(id, group);
  225. }
  226. return null;
  227. }
  228. public Cluster GetCluster(uint sbid)
  229. {
  230. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  231. foreach (var (coll, _) in groups)
  232. {
  233. var array = coll.ToBuffer().buffer;
  234. for (var index = 0; index < array.capacity; index++)
  235. {
  236. var conn = array[index];
  237. //Static blocks don't have a cluster ID but the cluster destruction manager should have one
  238. if (conn.machineRigidBodyId == sbid && conn.clusterId != uint.MaxValue)
  239. return new Cluster(conn.clusterId);
  240. }
  241. }
  242. return null;
  243. }
  244. public Block[] GetBodyBlocks(uint sbid)
  245. {
  246. var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
  247. var set = new HashSet<Block>();
  248. foreach (var (coll, _) in groups)
  249. {
  250. var array = coll.ToBuffer().buffer;
  251. for (var index = 0; index < array.capacity; index++)
  252. {
  253. var conn = array[index];
  254. if (conn.machineRigidBodyId == sbid)
  255. set.Add(new Block(conn.ID));
  256. }
  257. }
  258. return set.ToArray();
  259. }
  260. #if DEBUG
  261. public EntitiesDB GetEntitiesDB()
  262. {
  263. return entitiesDB;
  264. }
  265. #endif
  266. }
  267. }