203 lines
6.6 KiB
C#
203 lines
6.6 KiB
C#
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.count > 0) 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.count > 0)
|
|
{
|
|
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.count > 0 ? 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);
|
|
var wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group);
|
|
for (uint i = 0; i < wires.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);
|
|
var channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group);
|
|
if (port.firstChannelIndexCachedInSim < channels.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 EntityCollection<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;
|
|
var channelData =
|
|
entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group);
|
|
return channelData;
|
|
}
|
|
|
|
index = 0;
|
|
return default; //count: 0
|
|
}
|
|
}
|
|
}
|