using Svelto.ECS;
using Gamecraft.Wires;
using GamecraftModdingAPI.Engines;
namespace GamecraftModdingAPI.Blocks
{
///
/// Engine which executes signal actions
///
public class SignalEngine : IApiEngine
{
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 > Signals.POSITIVE_HIGH)
{
channelData.valueAsFloat = Signals.POSITIVE_HIGH;
}
else if (channelData.valueAsFloat < Signals.NEGATIVE_HIGH)
{
channelData.valueAsFloat = Signals.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(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[] GetElectricBlocks()
{
uint count = entitiesDB.Count(BlockIdentifiers.OWNED_BLOCKS) + entitiesDB.Count(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
uint i = 0;
EGID[] res = new EGID[count];
foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities(BlockIdentifiers.OWNED_BLOCKS))
{
res[i] = s.ID;
i++;
}
foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities(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.Group
: NamedExclusiveGroup.Group;
if (entitiesDB.Exists(signalID, group))
{
index = entitiesDB.QueryEntity(signalID, group).anyChannelIndex;
ChannelDataStruct[] channelData = entitiesDB
.QueryEntities(NamedExclusiveGroup.Group)
.ToFastAccess(out uint _);
return channelData;
}
index = 0;
return null;
}
}
}