Moar Gamecraft commands!
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.

200 lines
11KB

  1. using System;
  2. using System.Collections.Generic;
  3. using RobocraftX.Multiplayer;
  4. using RobocraftX.Common;
  5. using RobocraftX.Blocks;
  6. using RobocraftX.Blocks.Ghost;
  7. using Svelto.ECS;
  8. using Svelto.ECS.EntityStructs;
  9. using Unity.Entities;
  10. using Svelto.Context;
  11. using Svelto.Tasks;
  12. using RobocraftX;
  13. using RobocraftX.SimulationModeState;
  14. using RobocraftX.UECS;
  15. using Unity.Transforms;
  16. using Unity.Mathematics;
  17. using UnityEngine;
  18. namespace ExtraCommands.Building
  19. {
  20. [CustomCommand("MoveBlocks", "Move all blocks (including ground) from their original position")]
  21. [CustomCommand("MoveLastBlock", "Move last block from their original position")]
  22. [CustomCommand("MoveNearBlock", "Move blocks attached to your ghost block from their original position")]
  23. [CustomCommand("SetNearThreshold", "Set the threshold for a block to be considered 'near' to the ghost block")]
  24. class MoveBlocksCommandEngine : CustomCommandEngine
  25. {
  26. private float nearbyThreshold = 0.2f;
  27. public MoveBlocksCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams)
  28. {
  29. }
  30. public override void Ready()
  31. {
  32. CustomCommandUtility.Register<float, float, float>("MoveBlocks", MoveBlocksCommand, "Move all blocks (including ground) from their original position");
  33. CustomCommandUtility.Register<float, float, float>("MoveLastBlock", MoveLastBlockCommand, "Move last block from their original position");
  34. //CustomCommandUtility.Register<float, float, float>("MoveNearBlock", MoveNearbyBlockCommand, "Move blocks near your ghost block from their original position");
  35. //CustomCommandUtility.Register<float>("SetNearThreshold", (float t)=> { this.nearbyThreshold = t; }, "Set the threshold for a block to be considered 'near' to the ghost block");
  36. }
  37. // Move every block by vector (x,y,z)
  38. private void MoveBlocksCommand(float x, float y, float z)
  39. {
  40. ref SimulationModeStateEntityStruct simMode = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP);
  41. if (simMode.simulationMode != SimulationMode.Build)
  42. {
  43. uREPL.Log.Error("Blocks can only be moved in Build Mode");
  44. return;
  45. }
  46. uint count = this.entitiesDB.Count<PositionEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  47. float3 translationVector = new float3(x,y,z);
  48. for (uint i = 0; i < count; i++)
  49. {
  50. TranslateSingleBlock(i, translationVector);
  51. }
  52. uREPL.Log.Output($"Moved {count} blocks");
  53. }
  54. // Move block with highest index by vector (x,y,z)
  55. private void MoveLastBlockCommand(float x, float y, float z)
  56. {
  57. //uint count = entitiesDB.Count<PositionEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  58. ref SimulationModeStateEntityStruct simMode = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP);
  59. if (simMode.simulationMode != SimulationMode.Build)
  60. {
  61. uREPL.Log.Error("Blocks can only be moved in Build Mode");
  62. return;
  63. }
  64. float3 newPos = TranslateConnectedBlocks(CommonExclusiveGroups.CurrentBlockEntityID-1, new float3(x,y,z));
  65. uREPL.Log.Output($"Moved block to ({newPos.x},{newPos.y},{newPos.z})");
  66. }
  67. private void MoveNearbyBlockCommand(float x, float y, float z)
  68. {
  69. ref SimulationModeStateEntityStruct simMode = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP);
  70. if (simMode.simulationMode != SimulationMode.Build)
  71. {
  72. uREPL.Log.Error("Blocks can only be moved in Build Mode");
  73. return;
  74. }
  75. // get ghost block data
  76. uint ghostCount;
  77. uint ghostBlockIndex = 0;
  78. Vector3 ghostLocation = Vector3.zero;
  79. PositionEntityStruct[] ghostBlockPositions = entitiesDB.QueryEntities<PositionEntityStruct>(GHOST_BLOCKS.GHOST_GROUPS_INCLUDING_INVISIBLE[0], out ghostCount);
  80. for (uint i = 0; i < ghostCount; i++)
  81. {
  82. ref PositionEntityStruct pacman = ref ghostBlockPositions[i];
  83. if ((Vector3)pacman.position != Vector3.zero)
  84. {
  85. ghostLocation = pacman.position;
  86. ghostBlockIndex = i;
  87. break;
  88. }
  89. }
  90. if (ghostLocation == Vector3.zero)
  91. {
  92. uREPL.Log.Output("Ghost block not found; nothing moved");
  93. return;
  94. }
  95. uint count;
  96. PositionEntityStruct[] positions = entitiesDB.QueryEntities<PositionEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP, out count);
  97. for (uint i = 0; i < count; i++)
  98. {
  99. if (Math.Abs(positions[i].position.x - ghostLocation.x) < nearbyThreshold
  100. && Math.Abs(positions[i].position.y - ghostLocation.y) < nearbyThreshold
  101. && Math.Abs(positions[i].position.z - ghostLocation.z) < nearbyThreshold)
  102. {
  103. float3 newPos = TranslateConnectedBlocks(i, new float3(x, y, z));
  104. uREPL.Log.Output($"Moved block to ({newPos.x},{newPos.y},{newPos.z})");
  105. return;
  106. }
  107. }
  108. uREPL.Log.Output("No block found near ghost block");
  109. }
  110. // Move the block denoted by blockID by translationVector (old_position += translationVector)
  111. private float3 TranslateSingleBlock(uint blockID, float3 translationVector)
  112. {
  113. ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  114. ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  115. ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  116. ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  117. // main (persistent) position
  118. posStruct.position.x += translationVector.x;
  119. posStruct.position.y += translationVector.y;
  120. posStruct.position.z += translationVector.z;
  121. // placement grid position
  122. gridStruct.position.x += translationVector.x;
  123. gridStruct.position.y += translationVector.y;
  124. gridStruct.position.z += translationVector.z;
  125. // rendered position
  126. transStruct.position.x += translationVector.x;
  127. transStruct.position.y += translationVector.y;
  128. transStruct.position.z += translationVector.z;
  129. // collision position
  130. this.physWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation
  131. {
  132. Value = posStruct.position
  133. });
  134. return posStruct.position;
  135. }
  136. private float3 TranslateConnectedBlocks(uint blockID, float3 translationVector)
  137. {
  138. uREPL.Log.Output($"Last block id {CommonExclusiveGroups.CurrentBlockEntityID}, chosen {blockID}");
  139. //float3 newPosition = TranslateSingleBlock(blockID, translationVector);
  140. //HashSet<uint> processedCubes = new HashSet<uint>();
  141. Stack<uint> cubeStack = new Stack<uint>();
  142. //cubeStack.Push(blockID);
  143. //uint count;
  144. //GridConnectionsEntityStruct[] blockConnections;
  145. //MachineGraphConnectionEntityStruct[] connections;
  146. Gamecraft.DataStructures.FasterList<uint> cubesToMove = new Gamecraft.DataStructures.FasterList<uint>();
  147. ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubesToMove, (in GridConnectionsEntityStruct g) => { return false; });
  148. for(int i = 0; i < cubesToMove.Count; i++) {
  149. TranslateSingleBlock(cubesToMove[i], translationVector);
  150. entitiesDB.QueryEntity<GridConnectionsEntityStruct>(cubesToMove[i], CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false;
  151. }
  152. /*
  153. while (cubeStack.Count > 0) // find all inter-connected blocks
  154. {
  155. uint connectedBlockID = cubeStack.Pop();
  156. processedCubes.Add(connectedBlockID);
  157. //ScalingEntityStruct scale = entitiesDB.QueryEntity<ScalingEntityStruct>(connectedBlockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
  158. //uREPL.Log.Output($"Catching {connectedBlockID} with scale {scale.scale}");
  159. uint index;
  160. blockConnections = entitiesDB.QueryEntitiesAndIndex<GridConnectionsEntityStruct>(connectedBlockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP, out index);
  161. connections = entitiesDB.QueryEntities<MachineGraphConnectionEntityStruct>(blockConnections[(int)index].connectionGroup, out count);
  162. foreach (MachineGraphConnectionEntityStruct conn in connections)
  163. {
  164. if (!processedCubes.Contains(conn.connectedBlock.entityID)
  165. && blockConnections[(int)index].isConnectionGroupAssigned
  166. && (conn.oppositeConnectionEgid.entityID != 0u
  167. || conn.oppositeConnectionEgid.entityID != conn.connectedBlock.entityID))
  168. {
  169. //uREPL.Log.Output($"Block {connectedBlockID} connects to {conn.connectedBlock.entityID} (opposite {conn.oppositeConnectionEgid.entityID})");
  170. cubeStack.Push(conn.connectedBlock.entityID);
  171. }
  172. }
  173. }
  174. foreach (uint id in processedCubes)
  175. {
  176. TranslateSingleBlock(id, translationVector);
  177. }*/
  178. uREPL.Log.Output($"Found {cubesToMove.Count} connected blocks");
  179. return this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).position;
  180. }
  181. public override void Dispose()
  182. {
  183. CustomCommandUtility.Unregister("MoveBlocks");
  184. CustomCommandUtility.Unregister("MoveLastBlock");
  185. //CustomCommandUtility.Unregister("MoveNearBlock");
  186. //CustomCommandUtility.Unregister("SetNearThreshold");
  187. }
  188. }
  189. }