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.

173 lines
6.6KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using RobocraftX;
  7. using RobocraftX.Blocks;
  8. using RobocraftX.Blocks.Ghost;
  9. using RobocraftX.Common;
  10. using RobocraftX.Multiplayer;
  11. using RobocraftX.SimulationModeState;
  12. using RobocraftX.UECS;
  13. using Unity.Entities;
  14. using Svelto.Context;
  15. using Svelto.ECS;
  16. using Svelto.ECS.EntityStructs;
  17. using Unity.Transforms;
  18. using Unity.Mathematics;
  19. using UnityEngine;
  20. using GamecraftModdingAPI.Utility;
  21. namespace GamecraftModdingAPI.Blocks
  22. {
  23. /// <summary>
  24. /// Engine which executes block movement actions
  25. /// </summary>
  26. public class SignalEngine : IApiEngine
  27. {
  28. public string Name { get; } = "GamecraftModdingAPISignalGameEngine";
  29. public IEntitiesDB entitiesDB { set; private get; }
  30. public bool IsInGame = false;
  31. private Stack<uint> cubesStack = new Stack<uint>();
  32. private bool stackInUse = false;
  33. private Gamecraft.DataStructures.FasterList<uint> cubesList = new Gamecraft.DataStructures.FasterList<uint>();
  34. private bool listInUse = false;
  35. public void Dispose()
  36. {
  37. IsInGame = false;
  38. }
  39. public void Ready()
  40. {
  41. IsInGame = true;
  42. }
  43. // implementations for Signal static class
  44. public bool SetSignal(uint blockID, uint channel, float signal, out EGID clusterID)
  45. {
  46. clusterID = GetClusterEGID(blockID, channel);
  47. return SetSignal(clusterID, signal);
  48. }
  49. public bool SetSignal(EGID clusterID, float signal)
  50. {
  51. if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID))
  52. {
  53. entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID).outputSignal = signal;
  54. return true;
  55. }
  56. return false;
  57. }
  58. public float AddSignal(uint blockID, uint channel, float signal, out EGID clusterID, bool clamp = true)
  59. {
  60. clusterID = GetClusterEGID(blockID, channel);
  61. return AddSignal(clusterID, signal, clamp);
  62. }
  63. public float AddSignal(EGID clusterID, float signal, bool clamp=true)
  64. {
  65. if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID))
  66. {
  67. ref ChannelOutputSignalDataStruct chanOutSig = ref entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID);
  68. chanOutSig.outputSignal += signal;
  69. if (clamp)
  70. {
  71. if (chanOutSig.outputSignal > Signals.POSITIVE_HIGH)
  72. {
  73. chanOutSig.outputSignal = Signals.POSITIVE_HIGH;
  74. }
  75. else if (chanOutSig.outputSignal < Signals.NEGATIVE_HIGH)
  76. {
  77. chanOutSig.outputSignal = Signals.NEGATIVE_HIGH;
  78. }
  79. return chanOutSig.outputSignal;
  80. }
  81. }
  82. return signal;
  83. }
  84. public float GetSignal(uint blockID, uint channel, out EGID clusterID)
  85. {
  86. clusterID = GetClusterEGID(blockID, channel);
  87. return GetSignal(clusterID);
  88. }
  89. public float GetSignal(EGID clusterID)
  90. {
  91. if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID))
  92. {
  93. return entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID).outputSignal;
  94. }
  95. return 0f;
  96. }
  97. public EGID GetClusterEGID(uint blockID, uint channel)
  98. {
  99. uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID);
  100. uint index;
  101. ElectricityEntityStruct[] structs;
  102. Logging.CommandLog($"Found {connectedCubeIDs.Length} connected cubes");
  103. for (int i = 0; i < connectedCubeIDs.Length; i++)
  104. {
  105. if (entitiesDB.TryQueryEntitiesAndIndex(new EGID(connectedCubeIDs[i], CommonExclusiveGroups.OWNED_BLOCKS_GROUP), out index, out structs)
  106. || entitiesDB.TryQueryEntitiesAndIndex(new EGID(connectedCubeIDs[i], CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP), out index, out structs))
  107. {
  108. ref ConductiveClusterID clusterId = ref entitiesDB.QueryEntity<ConductiveClusterIdStruct>(structs[index].ID).clusterId;
  109. uint operatingChannel = entitiesDB.QueryEntity<SignalOperatingChannelStruct>(structs[index].ID).operatingChannel;
  110. Logging.CommandLog($"Channel {operatingChannel} found");
  111. EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterId.ID);
  112. if (clusterId.initialized && clusterId.isConductive && entitiesDB.Exists<ChannelOutputSignalDataStruct>(eGID))
  113. {
  114. return eGID;
  115. }
  116. }
  117. }
  118. // failsafe; not 100% reliable
  119. foreach (ref ConductiveClusterIdStruct clusterIdStruct in entitiesDB.QueryEntities<ConductiveClusterIdStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD))
  120. {
  121. EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterIdStruct.clusterId.ID);
  122. if (clusterIdStruct.clusterId.initialized && clusterIdStruct.clusterId.isConductive && entitiesDB.Exists<ChannelOutputSignalDataStruct>(eGID))
  123. {
  124. return eGID;
  125. }
  126. }
  127. return default;
  128. }
  129. private uint[] GetConductivelyConnectedBlocks(uint blockID)
  130. {
  131. if (!(stackInUse || listInUse))
  132. {
  133. stackInUse = true;
  134. listInUse = true;
  135. cubesStack.Clear();
  136. cubesList.FastClear();
  137. ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return false; });
  138. uint[] res = cubesList.ToArray();
  139. stackInUse = false;
  140. listInUse = false;
  141. return res;
  142. }
  143. Stack<uint> cubeStack = new Stack<uint>();
  144. Gamecraft.DataStructures.FasterList<uint> cubeList = new Gamecraft.DataStructures.FasterList<uint>();
  145. ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return false; });
  146. return cubeList.ToArray();
  147. }
  148. public bool IsSimulationMode()
  149. {
  150. return SimModeUtil.IsSimulationMode(this.entitiesDB);
  151. }
  152. }
  153. }