|
- using Svelto.ECS;
- using Gamecraft.Wires;
-
- using GamecraftModdingAPI.Engines;
-
- namespace GamecraftModdingAPI.Blocks
- {
- /// <summary>
- /// Engine which executes signal actions
- /// </summary>
- public class SignalEngine : IApiEngine
- {
- public const float POSITIVE_HIGH = 1.0f;
- public const float NEGATIVE_HIGH = -1.0f;
- public const float HIGH = 1.0f;
- public const float ZERO = 0.0f;
-
- public string Name { get; } = "GamecraftModdingAPISignalGameEngine";
-
- public EntitiesDB entitiesDB { set; private get; }
-
- public bool isRemovable => false;
-
- public bool IsInGame = false;
-
- public void Dispose()
- {
- IsInGame = false;
- }
-
- public void Ready()
- {
- IsInGame = true;
- }
-
- // implementations for Signal static class
-
- public bool SetSignal(EGID blockID, float signal, out uint signalID, bool input = true)
- {
- signalID = GetSignalIDs(blockID, input)[0];
- return SetSignal(signalID, signal);
- }
-
- public bool SetSignal(uint signalID, float signal, bool input = true)
- {
- var array = GetSignalStruct(signalID, out uint index, input);
- if (array != null) array[index].valueAsFloat = signal;
- return false;
- }
-
- public float AddSignal(EGID blockID, float signal, out uint signalID, bool clamp = true, bool input = true)
- {
- signalID = GetSignalIDs(blockID, input)[0];
- return AddSignal(signalID, signal, clamp, input);
- }
-
- public float AddSignal(uint signalID, float signal, bool clamp = true, bool input = true)
- {
- var array = GetSignalStruct(signalID, out uint index, input);
- if (array != null)
- {
- ref var channelData = ref array[index];
- channelData.valueAsFloat += signal;
- if (clamp)
- {
- if (channelData.valueAsFloat > POSITIVE_HIGH)
- {
- channelData.valueAsFloat = POSITIVE_HIGH;
- }
- else if (channelData.valueAsFloat < NEGATIVE_HIGH)
- {
- channelData.valueAsFloat = NEGATIVE_HIGH;
- }
-
- return channelData.valueAsFloat;
- }
- }
-
- return signal;
- }
-
- public float GetSignal(EGID blockID, out uint signalID, bool input = true)
- {
- signalID = GetSignalIDs(blockID, input)[0];
- return GetSignal(signalID, input);
- }
-
- public float GetSignal(uint signalID, bool input = true)
- {
- var array = GetSignalStruct(signalID, out uint index, input);
- return array?[index].valueAsFloat ?? 0f;
- }
-
- public uint[] GetSignalIDs(EGID blockID, bool input = true)
- {
- ref BlockPortsStruct bps = ref entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
- uint[] signals;
- if (input) {
- signals = new uint[bps.inputCount];
- for (uint i = 0u; i < bps.inputCount; i++)
- {
- signals[i] = bps.firstInputID + i;
- }
- } else {
- signals = new uint[bps.outputCount];
- for (uint i = 0u; i < bps.outputCount; i++)
- {
- signals[i] = bps.firstOutputID + i;
- }
- }
- return signals;
- }
-
- public EGID[] GetSignalInputs(EGID blockID)
- {
- BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
- EGID[] inputs = new EGID[ports.inputCount];
- for (uint i = 0; i < ports.inputCount; i++)
- {
- inputs[i] = new EGID(i + ports.firstInputID, NamedExclusiveGroup<InputPortsGroup>.Group);
- }
- return inputs;
- }
-
- public EGID[] GetSignalOutputs(EGID blockID)
- {
- BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
- EGID[] outputs = new EGID[ports.outputCount];
- for (uint i = 0; i < ports.outputCount; i++)
- {
- outputs[i] = new EGID(i + ports.firstOutputID, NamedExclusiveGroup<OutputPortsGroup>.Group);
- }
- return outputs;
- }
-
- public ref WireEntityStruct MatchPortToWire(EGID portID, EGID blockID, out bool exists)
- {
- ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
- WireEntityStruct[] wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group).ToFastAccess(out uint count);
- for (uint i = 0; i < count; i++)
- {
- if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID)
- || (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID))
- {
- exists = true;
- return ref wires[i];
- }
- }
- exists = false;
- WireEntityStruct[] defRef = new WireEntityStruct[1];
- return ref defRef[0];
- }
-
- public ref ChannelDataStruct GetChannelDataStruct(EGID portID, out bool exists)
- {
- ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
- ChannelDataStruct[] channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group).ToFastAccess(out uint count);
- if (port.firstChannelIndexCachedInSim < count)
- {
- exists = true;
- return ref channels[port.firstChannelIndexCachedInSim];
- }
- exists = false;
- ChannelDataStruct[] defRef = new ChannelDataStruct[1];
- return ref defRef[0];
- }
-
- public EGID[] GetElectricBlocks()
- {
- uint count = entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS) + entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
- uint i = 0;
- EGID[] res = new EGID[count];
- foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS))
- {
- res[i] = s.ID;
- i++;
- }
- foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS))
- {
- res[i] = s.ID;
- i++;
- }
- return res;
- }
-
- private ChannelDataStruct[] GetSignalStruct(uint signalID, out uint index, bool input = true)
- {
- ExclusiveGroup group = input
- ? NamedExclusiveGroup<InputPortsGroup>.Group
- : NamedExclusiveGroup<OutputPortsGroup>.Group;
- if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
- {
- index = entitiesDB.QueryEntity<PortEntityStruct>(signalID, group).anyChannelIndex;
- ChannelDataStruct[] channelData = entitiesDB
- .QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group)
- .ToFastAccess(out uint _);
- return channelData;
- }
-
- index = 0;
- return null;
- }
- }
- }
|