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.

229 lines
11KB

  1. using System;
  2. using System.Reflection;
  3. using Gamecraft.Blocks.BlockGroups;
  4. using Gamecraft.GUI.Blueprints;
  5. using GamecraftModdingAPI.Engines;
  6. using GamecraftModdingAPI.Utility;
  7. using HarmonyLib;
  8. using RobocraftX.Blocks;
  9. using RobocraftX.Common;
  10. using RobocraftX.CR.MachineEditing.BoxSelect;
  11. using RobocraftX.CR.MachineEditing.BoxSelect.ClipboardOperations;
  12. using Svelto.DataStructures;
  13. using Svelto.ECS;
  14. using Svelto.ECS.DataStructures;
  15. using Svelto.ECS.EntityStructs;
  16. using Svelto.ECS.Serialization;
  17. using Unity.Collections;
  18. using Unity.Mathematics;
  19. using UnityEngine;
  20. using Allocator = Svelto.Common.Allocator;
  21. namespace GamecraftModdingAPI.Blocks
  22. {
  23. public class BlueprintEngine : IApiEngine
  24. {
  25. private readonly MethodInfo getBlocksFromGroup =
  26. AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup");
  27. private NativeDynamicArray selectedBlocksInGroup;
  28. private NativeHashSet<ulong> removedConnections = new NativeHashSet<ulong>();
  29. private static readonly Type PlaceBlueprintUtilityType =
  30. AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceBlueprintUtility");
  31. private static readonly FieldInfo LocalBlockMap =
  32. AccessTools.DeclaredField(PlaceBlueprintUtilityType, "_localBlockMap");
  33. private static readonly MethodInfo BuildBlock = AccessTools.Method(PlaceBlueprintUtilityType, "BuildBlock");
  34. private static readonly MethodInfo BuildWires = AccessTools.Method(PlaceBlueprintUtilityType, "BuildWires");
  35. private static NativeEntityRemove nativeRemove;
  36. private static MachineGraphConnectionEntityFactory connectionFactory;
  37. private static IEntityFunctions entityFunctions;
  38. private static ClipboardSerializationDataResourceManager clipboardManager;
  39. private static IEntitySerialization entitySerialization;
  40. private static IEntityFactory entityFactory;
  41. private static FasterList<EGID> globalBlockMap;
  42. public void Ready()
  43. {
  44. selectedBlocksInGroup = NativeDynamicArray.Alloc<EGID>(Allocator.Persistent);
  45. }
  46. public EntitiesDB entitiesDB { get; set; }
  47. public void Dispose()
  48. {
  49. selectedBlocksInGroup.Dispose();
  50. }
  51. public Block[] GetBlocksFromGroup(EGID blockID, out float3 pos, out quaternion rot)
  52. {
  53. var blockPos = default(float3);
  54. var blockRot = default(quaternion);
  55. var parameters = new object[] {blockID, selectedBlocksInGroup, entitiesDB, blockPos, blockRot};
  56. getBlocksFromGroup.Invoke(null, parameters);
  57. pos = (float3) parameters[3];
  58. rot = (quaternion) parameters[4];
  59. int count = selectedBlocksInGroup.Count<EGID>();
  60. var ret = new Block[count];
  61. for (uint i = 0; i < count; i++)
  62. ret[i] = new Block(selectedBlocksInGroup.Get<EGID>(i));
  63. selectedBlocksInGroup.FastClear();
  64. return ret;
  65. }
  66. public void RemoveBlockGroup(int id)
  67. {
  68. BlockGroupUtility.RemoveAllBlocksInBlockGroup(id, entitiesDB, removedConnections, nativeRemove,
  69. connectionFactory, default).Complete();
  70. }
  71. public void SelectBlueprint(uint resourceID)
  72. {
  73. BlueprintUtil.SelectBlueprint(null, new BlueprintInventoryItemEntityStruct
  74. {
  75. blueprintResourceId = resourceID,
  76. });
  77. }
  78. public uint CreateBlueprint()
  79. {
  80. uint index = clipboardManager.AllocateSerializationData();
  81. return index;
  82. }
  83. public void ReplaceBlueprint(uint playerID, uint blueprintID, Block[] selected, float3 pos, quaternion rot)
  84. {
  85. var blockIDs = new EGID[selected.Length];
  86. for (var i = 0; i < selected.Length; i++)
  87. {
  88. var block = selected[i];
  89. blockIDs[i] = block.Id;
  90. }
  91. var serializationData = clipboardManager.GetSerializationData(blueprintID);
  92. SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData);
  93. if (selected.Length == 0)
  94. return;
  95. //ref BlockGroupTransformEntityComponent groupTransform = ref EntityNativeDBExtensions.QueryEntity<BlockGroupTransformEntityComponent>(entitiesDb, (uint) local1.currentBlockGroup, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
  96. //ref ColliderAabb collider = ref EntityNativeDBExtensions.QueryEntity<ColliderAabb>(entitiesDB, (uint) groupID, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
  97. //float3 bottomOffset = PlaceBlockUtility.GetBottomOffset(collider);
  98. //var rootPosition = math.mul(groupTransform.blockGroupGridRotation, bottomOffset) + groupTransform.blockGroupGridPosition;
  99. //var rootRotation = groupTransform.blockGroupGridRotation;
  100. if (math.all(pos == default))
  101. pos = selected[0].Position;
  102. if (math.all(rot.value == default))
  103. rot = Quaternion.Euler(selected[0].Rotation);
  104. clipboardManager.SetGhostSerialized(blueprintID, false);
  105. SelectionSerializationUtility.CopySelectionToClipboard(playerID, entitiesDB,
  106. serializationData.blueprintData, entitySerialization, entityFactory, blockIDs,
  107. (uint) blockIDs.Length, pos, rot);
  108. }
  109. public Block[] PlaceBlueprintBlocks(uint blueprintID, uint playerID, float3 pos, float3 rot)
  110. { //RobocraftX.CR.MachineEditing.PlaceBlueprintUtility.PlaceBlocksFromSerialisedData
  111. var serializationData = clipboardManager.GetSerializationData(blueprintID);
  112. var blueprintData = serializationData.blueprintData;
  113. blueprintData.dataPos = 0U;
  114. uint selectionSize;
  115. PositionEntityStruct selectionPosition;
  116. RotationEntityStruct selectionRotation;
  117. uint version;
  118. BoxSelectSerializationUtilities.ReadClipboardHeader(blueprintData, out selectionSize, out selectionPosition, out selectionRotation, out version);
  119. ((FasterList<EGID>) LocalBlockMap.GetValue(null)).Clear();
  120. if (version <= 1U)
  121. {
  122. uint groupsCount;
  123. BoxSelectSerializationUtilities.ReadBlockGroupData(blueprintData, out groupsCount);
  124. for (int index = 0; (long) index < (long) groupsCount; ++index)
  125. {
  126. int nextFilterId = BlockGroupUtility.NextFilterId;
  127. entitySerialization.DeserializeNewEntity(new EGID((uint) nextFilterId, BlockGroupExclusiveGroups.BlockGroupEntityGroup), blueprintData, 1);
  128. }
  129. }
  130. int nextFilterId1 = BlockGroupUtility.NextFilterId;
  131. entityFactory.BuildEntity<BlockGroupEntityDescriptor>(new EGID((uint) nextFilterId1, BlockGroupExclusiveGroups.BlockGroupEntityGroup)).Init(new BlockGroupTransformEntityComponent
  132. {
  133. blockGroupGridPosition = selectionPosition.position,
  134. blockGroupGridRotation = selectionRotation.rotation
  135. });
  136. var frot = Quaternion.Euler(rot);
  137. var grid = new GridRotationStruct {position = pos, rotation = frot};
  138. var poss = new PositionEntityStruct {position = pos};
  139. var rots = new RotationEntityStruct {rotation = frot};
  140. for (int index = 0; (long) index < (long) selectionSize; ++index)
  141. BuildBlock.Invoke(null,
  142. new object[]
  143. {
  144. playerID, grid, poss, rots, selectionPosition, selectionRotation, blueprintData,
  145. entitiesDB, entitySerialization, nextFilterId1
  146. });
  147. /*
  148. uint playerId, in GridRotationStruct ghostParentGrid,
  149. in PositionEntityStruct ghostParentPosition, in RotationEntityStruct ghostParentRotation,
  150. in PositionEntityStruct selectionPosition, in RotationEntityStruct selectionRotation,
  151. ISerializationData serializationData, EntitiesDB entitiesDb,
  152. IEntitySerialization entitySerialization, int blockGroupId
  153. */
  154. if (globalBlockMap == null)
  155. globalBlockMap = FullGameFields._deserialisedBlockMap;
  156. var placedBlocks = (FasterList<EGID>) LocalBlockMap.GetValue(null);
  157. globalBlockMap.Clear();
  158. globalBlockMap.AddRange(placedBlocks);
  159. BuildWires.Invoke(null,
  160. new object[] {playerID, blueprintData, entitySerialization, entitiesDB, entityFactory});
  161. var blocks = new Block[placedBlocks.count];
  162. for (int i = 0; i < blocks.Length; i++)
  163. blocks[i] = new Block(placedBlocks[i]);
  164. return blocks;
  165. }
  166. public void InitBlueprint(uint blueprintID)
  167. {
  168. clipboardManager.IncrementRefCount(blueprintID);
  169. }
  170. public void DisposeBlueprint(uint blueprintID)
  171. {
  172. clipboardManager.DecrementRefCount(blueprintID);
  173. }
  174. public string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine";
  175. public bool isRemovable { get; }
  176. [HarmonyPatch]
  177. private static class RemoveEnginePatch
  178. {
  179. public static void Prefix(IEntityFunctions entityFunctions,
  180. MachineGraphConnectionEntityFactory machineGraphConnectionEntityFactory)
  181. {
  182. nativeRemove = entityFunctions.ToNativeRemove<BlockEntityDescriptor>("GCAPI" + nameof(BlueprintEngine));
  183. connectionFactory = machineGraphConnectionEntityFactory;
  184. BlueprintEngine.entityFunctions = entityFunctions;
  185. }
  186. public static MethodBase TargetMethod()
  187. {
  188. return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.RemoveBlockEngine"))[0];
  189. }
  190. }
  191. [HarmonyPatch]
  192. private static class SelectEnginePatch
  193. {
  194. public static void Prefix(ClipboardSerializationDataResourceManager clipboardSerializationDataResourceManager,
  195. IEntitySerialization entitySerialization,
  196. IEntityFactory entityFactory)
  197. {
  198. clipboardManager = clipboardSerializationDataResourceManager;
  199. BlueprintEngine.entitySerialization = entitySerialization;
  200. BlueprintEngine.entityFactory = entityFactory;
  201. }
  202. public static MethodBase TargetMethod()
  203. {
  204. return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine"))[0];
  205. }
  206. }
  207. }
  208. }