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.

205 lines
6.6KB

  1. using Svelto.ECS;
  2. using Gamecraft.Wires;
  3. using GamecraftModdingAPI.Engines;
  4. namespace GamecraftModdingAPI.Blocks
  5. {
  6. /// <summary>
  7. /// Engine which executes signal actions
  8. /// </summary>
  9. public class SignalEngine : IApiEngine
  10. {
  11. public const float POSITIVE_HIGH = 1.0f;
  12. public const float NEGATIVE_HIGH = -1.0f;
  13. public const float HIGH = 1.0f;
  14. public const float ZERO = 0.0f;
  15. public string Name { get; } = "GamecraftModdingAPISignalGameEngine";
  16. public EntitiesDB entitiesDB { set; private get; }
  17. public bool isRemovable => false;
  18. public bool IsInGame = false;
  19. public void Dispose()
  20. {
  21. IsInGame = false;
  22. }
  23. public void Ready()
  24. {
  25. IsInGame = true;
  26. }
  27. // implementations for Signal static class
  28. public bool SetSignal(EGID blockID, float signal, out uint signalID, bool input = true)
  29. {
  30. signalID = GetSignalIDs(blockID, input)[0];
  31. return SetSignal(signalID, signal);
  32. }
  33. public bool SetSignal(uint signalID, float signal, bool input = true)
  34. {
  35. var array = GetSignalStruct(signalID, out uint index, input);
  36. if (array != null) array[index].valueAsFloat = signal;
  37. return false;
  38. }
  39. public float AddSignal(EGID blockID, float signal, out uint signalID, bool clamp = true, bool input = true)
  40. {
  41. signalID = GetSignalIDs(blockID, input)[0];
  42. return AddSignal(signalID, signal, clamp, input);
  43. }
  44. public float AddSignal(uint signalID, float signal, bool clamp = true, bool input = true)
  45. {
  46. var array = GetSignalStruct(signalID, out uint index, input);
  47. if (array != null)
  48. {
  49. ref var channelData = ref array[index];
  50. channelData.valueAsFloat += signal;
  51. if (clamp)
  52. {
  53. if (channelData.valueAsFloat > POSITIVE_HIGH)
  54. {
  55. channelData.valueAsFloat = POSITIVE_HIGH;
  56. }
  57. else if (channelData.valueAsFloat < NEGATIVE_HIGH)
  58. {
  59. channelData.valueAsFloat = NEGATIVE_HIGH;
  60. }
  61. return channelData.valueAsFloat;
  62. }
  63. }
  64. return signal;
  65. }
  66. public float GetSignal(EGID blockID, out uint signalID, bool input = true)
  67. {
  68. signalID = GetSignalIDs(blockID, input)[0];
  69. return GetSignal(signalID, input);
  70. }
  71. public float GetSignal(uint signalID, bool input = true)
  72. {
  73. var array = GetSignalStruct(signalID, out uint index, input);
  74. return array?[index].valueAsFloat ?? 0f;
  75. }
  76. public uint[] GetSignalIDs(EGID blockID, bool input = true)
  77. {
  78. ref BlockPortsStruct bps = ref entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
  79. uint[] signals;
  80. if (input) {
  81. signals = new uint[bps.inputCount];
  82. for (uint i = 0u; i < bps.inputCount; i++)
  83. {
  84. signals[i] = bps.firstInputID + i;
  85. }
  86. } else {
  87. signals = new uint[bps.outputCount];
  88. for (uint i = 0u; i < bps.outputCount; i++)
  89. {
  90. signals[i] = bps.firstOutputID + i;
  91. }
  92. }
  93. return signals;
  94. }
  95. public EGID[] GetSignalInputs(EGID blockID)
  96. {
  97. BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
  98. EGID[] inputs = new EGID[ports.inputCount];
  99. for (uint i = 0; i < ports.inputCount; i++)
  100. {
  101. inputs[i] = new EGID(i + ports.firstInputID, NamedExclusiveGroup<InputPortsGroup>.Group);
  102. }
  103. return inputs;
  104. }
  105. public EGID[] GetSignalOutputs(EGID blockID)
  106. {
  107. BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
  108. EGID[] outputs = new EGID[ports.outputCount];
  109. for (uint i = 0; i < ports.outputCount; i++)
  110. {
  111. outputs[i] = new EGID(i + ports.firstOutputID, NamedExclusiveGroup<OutputPortsGroup>.Group);
  112. }
  113. return outputs;
  114. }
  115. public ref WireEntityStruct MatchPortToWire(EGID portID, EGID blockID, out bool exists)
  116. {
  117. ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
  118. WireEntityStruct[] wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group).ToFastAccess(out uint count);
  119. for (uint i = 0; i < count; i++)
  120. {
  121. if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID)
  122. || (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID))
  123. {
  124. exists = true;
  125. return ref wires[i];
  126. }
  127. }
  128. exists = false;
  129. WireEntityStruct[] defRef = new WireEntityStruct[1];
  130. return ref defRef[0];
  131. }
  132. public ref ChannelDataStruct GetChannelDataStruct(EGID portID, out bool exists)
  133. {
  134. ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
  135. ChannelDataStruct[] channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group).ToFastAccess(out uint count);
  136. if (port.firstChannelIndexCachedInSim < count)
  137. {
  138. exists = true;
  139. return ref channels[port.firstChannelIndexCachedInSim];
  140. }
  141. exists = false;
  142. ChannelDataStruct[] defRef = new ChannelDataStruct[1];
  143. return ref defRef[0];
  144. }
  145. public EGID[] GetElectricBlocks()
  146. {
  147. uint count = entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS) + entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
  148. uint i = 0;
  149. EGID[] res = new EGID[count];
  150. foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS))
  151. {
  152. res[i] = s.ID;
  153. i++;
  154. }
  155. foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS))
  156. {
  157. res[i] = s.ID;
  158. i++;
  159. }
  160. return res;
  161. }
  162. private ChannelDataStruct[] GetSignalStruct(uint signalID, out uint index, bool input = true)
  163. {
  164. ExclusiveGroup group = input
  165. ? NamedExclusiveGroup<InputPortsGroup>.Group
  166. : NamedExclusiveGroup<OutputPortsGroup>.Group;
  167. if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
  168. {
  169. index = entitiesDB.QueryEntity<PortEntityStruct>(signalID, group).anyChannelIndex;
  170. ChannelDataStruct[] channelData = entitiesDB
  171. .QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group)
  172. .ToFastAccess(out uint _);
  173. return channelData;
  174. }
  175. index = 0;
  176. return null;
  177. }
  178. }
  179. }