Modify & Fix signal API

This commit is contained in:
NGnius 2020-02-19 20:32:58 -05:00
parent c57154a970
commit 0459bdf9d9
3 changed files with 220 additions and 164 deletions

View file

@ -19,6 +19,7 @@ using Svelto.ECS.EntityStructs;
using Unity.Transforms; using Unity.Transforms;
using Unity.Mathematics; using Unity.Mathematics;
using UnityEngine; using UnityEngine;
using Gamecraft.Wires;
using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Utility;
@ -35,11 +36,7 @@ namespace GamecraftModdingAPI.Blocks
public bool IsInGame = false; public bool IsInGame = false;
private Stack<uint> cubesStack = new Stack<uint>(); private System.Random random = new System.Random();
private bool stackInUse = false;
private FasterList<uint> cubesList = new FasterList<uint>();
private bool listInUse = false;
public void Dispose() public void Dispose()
{ {
@ -51,139 +48,132 @@ namespace GamecraftModdingAPI.Blocks
IsInGame = true; IsInGame = true;
} }
// implementations for Signal static class public void DoTheThing()
public bool SetSignal(uint blockID, uint channel, float signal, out EGID clusterID)
{ {
clusterID = GetClusterEGID(blockID, channel); GamecraftModdingAPI.Tasks.Repeatable thing = new GamecraftModdingAPI.Tasks.Repeatable(
return SetSignal(clusterID, signal); () => { Thing(); },
() => { return IsSimulationMode(); } );
GamecraftModdingAPI.Tasks.Scheduler.Schedule(thing);
} }
public bool SetSignal(EGID clusterID, float signal) public void Thing()
{ {
if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID)) uint count = 0;
EGID[] eBlocks = GetElectricBlocks();
for (uint i = 0u; i < eBlocks.Length; i++)
{ {
entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID).outputSignal = signal; uint[] ids = GetSignalIDs(eBlocks[i]);
for (uint j = 0u; j < ids.Length; j++)
{
SetSignal(ids[j], (float)random.NextDouble());
count++;
}
}
Logging.Log($"Did the thing on {count} inputs");
}
// 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)
{
ExclusiveGroup group = input ? NamedExclusiveGroup<InputPortsGroup>.Group : NamedExclusiveGroup<OutputPortsGroup>.Group;
if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
{
entitiesDB.QueryEntity<PortEntityStruct>(signalID, group).value = signal;
return true; return true;
} }
return false; return false;
} }
public float AddSignal(uint blockID, uint channel, float signal, out EGID clusterID, bool clamp = true) public float AddSignal(EGID blockID, float signal, out uint signalID, bool clamp = true, bool input = true)
{ {
clusterID = GetClusterEGID(blockID, channel); signalID = GetSignalIDs(blockID, input)[0];
return AddSignal(clusterID, signal, clamp); return AddSignal(signalID, signal, clamp, input);
} }
public float AddSignal(EGID clusterID, float signal, bool clamp=true) public float AddSignal(uint signalID, float signal, bool clamp = true, bool input = true)
{ {
if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID)) ExclusiveGroup group = input ? NamedExclusiveGroup<InputPortsGroup>.Group : NamedExclusiveGroup<OutputPortsGroup>.Group;
if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
{ {
ref ChannelOutputSignalDataStruct chanOutSig = ref entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID); ref PortEntityStruct pes = ref entitiesDB.QueryEntity<PortEntityStruct>(signalID, group);
chanOutSig.outputSignal += signal; pes.value += signal;
if (clamp) if (clamp)
{ {
if (chanOutSig.outputSignal > Signals.POSITIVE_HIGH) if (pes.value > Signals.POSITIVE_HIGH)
{ {
chanOutSig.outputSignal = Signals.POSITIVE_HIGH; pes.value = Signals.POSITIVE_HIGH;
} }
else if (chanOutSig.outputSignal < Signals.NEGATIVE_HIGH) else if (pes.value < Signals.NEGATIVE_HIGH)
{ {
chanOutSig.outputSignal = Signals.NEGATIVE_HIGH; pes.value = Signals.NEGATIVE_HIGH;
} }
return chanOutSig.outputSignal; return pes.value;
} }
} }
return signal; return signal;
} }
public float GetSignal(uint blockID, uint channel, out EGID clusterID) public float GetSignal(EGID blockID, out uint signalID, bool input = true)
{ {
clusterID = GetClusterEGID(blockID, channel); signalID = GetSignalIDs(blockID, input)[0];
return GetSignal(clusterID); return GetSignal(signalID, input);
} }
public float GetSignal(EGID clusterID) public float GetSignal(uint signalID, bool input = true)
{ {
if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID)) ExclusiveGroup group = input ? NamedExclusiveGroup<InputPortsGroup>.Group : NamedExclusiveGroup<OutputPortsGroup>.Group;
if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
{ {
return entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID).outputSignal; return entitiesDB.QueryEntity<PortEntityStruct>(signalID, group).value;
} }
return 0f; return 0f;
} }
public EGID GetClusterEGID(uint blockID, uint channel) public uint[] GetSignalIDs(EGID blockID, bool input = true)
{ {
//uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID); ref BlockPortsStruct bps = ref entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
//uint index; uint[] signals;
//ElectricityEntityStruct[] structs; if (input) {
EGID elecEGID = new EGID(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); signals = new uint[bps.inputCount];
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID)) for (uint i = 0u; i < bps.inputCount; i++)
{ {
elecEGID = new EGID(blockID, CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP); signals[i] = bps.firstInputID + i;
} }
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID)) } else {
signals = new uint[bps.outputCount];
for (uint i = 0u; i < bps.outputCount; i++)
{ {
return default; signals[i] = bps.firstOutputID + i;
} }
ref ElectricityEntityStruct eStruct = ref entitiesDB.QueryEntity<ElectricityEntityStruct>(elecEGID);
ref ConductiveClusterID clusterId = ref entitiesDB.QueryEntity<ConductiveClusterIdStruct>(eStruct.ID).clusterId;
uint operatingChannel = entitiesDB.QueryEntity<SignalOperatingChannelStruct>(eStruct.ID).operatingChannel;
EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterId.ID);
if (clusterId.initialized && clusterId.isConductive && entitiesDB.Exists<ChannelOutputSignalDataStruct>(eGID))
{
return eGID;
} }
return default; return signals;
} }
public uint[] GetElectricBlocks() public EGID[] GetElectricBlocks()
{ {
uint count = entitiesDB.Count<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[0]) uint count = entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS) + entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
+ entitiesDB.Count<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[1]);
uint i = 0; uint i = 0;
uint[] res = new uint[count]; EGID[] res = new EGID[count];
foreach (ref var ees in entitiesDB.QueryEntities<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD)) foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS))
{ {
res[i] = ees.ID.entityID; res[i] = s.ID;
i++;
}
foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS))
{
res[i] = s.ID;
i++; i++;
} }
return res; return res;
} }
private uint[] GetConductivelyConnectedBlocks(uint blockID)
{
if (!(stackInUse || listInUse))
{
stackInUse = true;
listInUse = true;
cubesStack.Clear();
cubesList.FastClear();
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return g.isIsolator; });
uint[] res = cubesList.ToArray();
stackInUse = false;
listInUse = false;
foreach (var id in res)
{
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false;
}
return res;
}
else
{
Stack<uint> cubeStack = new Stack<uint>();
FasterList<uint> cubeList = new FasterList<uint>();
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return g.isIsolator; });
uint[] res = cubesList.ToArray();
foreach (var id in res)
{
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false;
}
return res;
}
}
public bool IsSimulationMode() public bool IsSimulationMode()
{ {
return GamecraftModdingAPI.Utility.GameState.IsSimulationMode(); return GamecraftModdingAPI.Utility.GameState.IsSimulationMode();

View file

@ -24,110 +24,155 @@ namespace GamecraftModdingAPI.Blocks
private static SignalEngine signalEngine = new SignalEngine(); private static SignalEngine signalEngine = new SignalEngine();
/// <summary> /// <summary>
/// Set the electric block's channel to a value /// Set the electric block's (first) signal value.
/// </summary> /// </summary>
/// <param name="id">The block's id</param> /// <param name="blockID">The block's id.</param>
/// <param name="channel">The channel (1 to 99)</param> /// <param name="signal">The signal value (-1 to 1; not enforced).</param>
/// <param name="signal">The signal value (-1 to 1; not enforced)</param> /// <param name="input">Whether to retrieve input IDs (true) or output IDs (false).</param>
public static void SetSignalConnectedBlocks(uint id, uint channel, float signal) /// <param name="owned">Whether the block is in the owned group (true) or functional group (false)</param>
public static void SetSignalByBlock(uint blockID, float signal, bool input = true, bool owned = true)
{
EGID egid = new EGID(blockID, owned ? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
signalEngine.SetSignal(egid, signal, out uint _, input);
}
}
public static void SetSignalByBlock(EGID blockID, float signal, bool input = true)
{ {
if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{ {
signalEngine.SetSignal(id, channel, signal, out EGID _); signalEngine.SetSignal(blockID, signal, out uint _, input);
} }
} }
/// <summary> /// <summary>
/// Set a conductive cluster channel to a value /// Set a signal's value.
/// </summary> /// </summary>
/// <param name="clusterID">The channel cluster's id</param> /// <param name="signalID">The channel cluster's id.</param>
/// <param name="signal">The signal value (-1 to 1; not enforced)</param> /// <param name="signal">The signal value (-1 to 1; not enforced).</param>
public static void SetSignalCluster(EGID clusterID, float signal) /// <param name="input">Whether to retrieve input IDs (true) or output IDs (false).</param>
public static void SetSignalByID(uint signalID, float signal, bool input = true)
{ {
if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{ {
signalEngine.SetSignal(clusterID, signal); signalEngine.SetSignal(signalID, signal, input);
} }
} }
/// <summary> /// <summary>
/// Add a value to an electric block's channel signal /// Add a value to an electric block's signal.
/// </summary> /// </summary>
/// <param name="id">The block's id</param> /// <param name="blockID">The block's id.</param>
/// <param name="channel">The channel (1 to 99)</param> /// <param name="signal">The signal value to add.</param>
/// <param name="signal">The signal value to add</param> /// <param name="clamp">Whether to clamp the resulting signal value between -1 and 1.</param>
/// <param name="clamp">Whether to clamp the resulting signal value between -1 and 1</param> /// <param name="input">Whether to retrieve input IDs (true) or output IDs (false).</param>
public static void AddSignalConnectedBlocks(uint id, uint channel, float signal, bool clamp = true) /// <param name="owned">Whether the block is in the owned group (true) or functional group (false)</param>
/// <returns>The signal's new value.</returns>
public static float AddSignalByBlock(uint blockID, float signal, bool clamp = true, bool input = true, bool owned = true)
{ {
EGID egid = new EGID(blockID, owned ? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{ {
signalEngine.AddSignal(id, channel, signal, out EGID _, clamp); return signalEngine.AddSignal(egid, signal, out uint _, clamp, input);
} }
return 0f;
} }
/// <summary> public static float AddSignalByBlock(EGID blockID, float signal, bool clamp = true, bool input = true)
/// Add a value to a conductive cluster channel
/// </summary>
/// <param name="clusterID">The channel cluster's id</param>
/// <param name="signal">The signal value to add</param>
/// <param name="clamp">Whether to clamp the resulting signal value between -1 and 1</param>
public static void AddSignalCluster(EGID clusterID, float signal, bool clamp = true)
{ {
if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{ {
signalEngine.AddSignal(clusterID, signal, clamp); return signalEngine.AddSignal(blockID, signal, out uint _, clamp, input);
}
}
/// <summary>
/// Get a electric block's channel's signal value
/// </summary>
/// <param name="id">The block's id</param>
/// <param name="channel">The channel (1 to 99)</param>
/// <returns>The signal value</returns>
public static float GetSignalBlock(uint id, uint channel)
{
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
return signalEngine.GetSignal(id, channel, out EGID _);
} }
return 0f; return 0f;
} }
/// <summary> /// <summary>
/// Get a conductive cluster channel's signal value /// Add a value to a conductive cluster channel.
/// </summary> /// </summary>
/// <param name="clusterID">The channel cluster's id</param> /// <param name="signalID">The channel cluster's id.</param>
/// <returns>The signal value</returns> /// <param name="signal">The signal value to add.</param>
public static float GetSignalCluster(EGID clusterID) /// <param name="clamp">Whether to clamp the resulting signal value between -1 and 1.</param>
/// <param name="input">Whether to retrieve input IDs (true) or output IDs (false).</param>
/// <returns>The signal's new value.</returns>
public static float AddSignalByID(uint signalID, float signal, bool clamp = true, bool input = true)
{ {
if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{ {
return signalEngine.GetSignal(clusterID); return signalEngine.AddSignal(signalID, signal, clamp, input);
} }
return 0f; return 0f;
} }
/// <summary> /// <summary>
/// Get the ID of every electricity consumer in the game world /// Get a electric block's signal's (first) value.
/// </summary> /// </summary>
/// <returns>The block IDs</returns> /// <param name="blockID">The block's id.</param>
public static uint[] GetElectricBlocks() /// <param name="input">Whether to retrieve input IDs (true) or output IDs (false).</param>
/// <param name="owned">Whether the block is in the owned group (true) or functional group (false)</param>
/// <returns>The signal's value.</returns>
public static float GetSignalByBlock(uint blockID, bool input = true, bool owned = true)
{
EGID egid = new EGID(blockID, owned? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
return signalEngine.GetSignal(egid, out uint _, input);
}
return 0f;
}
public static float GetSignalByBlock(EGID blockID, bool input = true)
{
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
return signalEngine.GetSignal(blockID, out uint _, input);
}
return 0f;
}
/// <summary>
/// Get a signal's value.
/// </summary>
/// <param name="signalID">The signal's id.</param>
/// <param name="input">Whether to retrieve input IDs (true) or output IDs (false).</param>
/// <returns>The signal's value.</returns>
public static float GetSignalByID(uint signalID, bool input = true)
{
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
return signalEngine.GetSignal(signalID, input);
}
return 0f;
}
/// <summary>
/// Get the ID of every electric block in the game world.
/// </summary>
/// <returns>The block IDs.</returns>
public static EGID[] GetElectricBlocks()
{ {
return signalEngine.GetElectricBlocks(); return signalEngine.GetElectricBlocks();
} }
/// <summary> /// <summary>
/// Get the conductive cluster's unique identifier for an electric block /// Get the unique identifiers for the input wires connected to an electric block.
/// </summary> /// </summary>
/// <param name="id">The block's id</param> /// <param name="blockID">The block's id.</param>
/// <param name="channel"></param> /// <param name="input">Whether to retrieve input IDs (true) or output IDs (false).</param>
/// <returns>The unique ID</returns> /// <param name="owned">Whether the block is in the owned group (true) or functional group (false)</param>
public static EGID GetClusterID(uint id, uint channel) /// <returns>The unique IDs.</returns>
public static uint[] GetSignalIDs(uint blockID, bool input = true, bool owned = true)
{ {
return signalEngine.GetClusterEGID(id, channel); EGID egid = new EGID(blockID, owned ? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
return signalEngine.GetSignalIDs(egid, input);
} }
public static uint[] GetSignalIDs(EGID blockID, bool input = true, bool owned = true)
{
return signalEngine.GetSignalIDs(blockID, input);
}
public static void Init() public static void Init()
{ {

View file

@ -51,13 +51,7 @@ namespace GamecraftModdingAPI.Tests
//AnalyticsDisablerPatch.DisableAnalytics = true; //AnalyticsDisablerPatch.DisableAnalytics = true;
// disable background music // disable background music
Logging.MetaDebugLog("Audio Mixers: "+string.Join(",", AudioTools.GetMixers())); Logging.MetaDebugLog("Audio Mixers: "+string.Join(",", AudioTools.GetMixers()));
//AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called //AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called :(
/*if (!FMODUnity.RuntimeManager.HasBankLoaded("Modded"))
{
FMODUnity.RuntimeManager.LoadBank("Modded", true);
}
FMODUnity.RuntimeManager.PlayOneShot("event:/ModEvents/KillDashNine3D");*/
// debug/test handlers // debug/test handlers
EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("App Inited event!"); }, () => { }, EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("App Inited event!"); }, () => { },
@ -99,7 +93,34 @@ namespace GamecraftModdingAPI.Tests
CommandManager.AddCommand(new SimpleCustomCommandEngine<string>( CommandManager.AddCommand(new SimpleCustomCommandEngine<string>(
(s) => { Analytics.DeltaDNAHelper.SendActionCompletedEvent(in plp, s.Replace(", ", " ")); }, (s) => { Analytics.DeltaDNAHelper.SendActionCompletedEvent(in plp, s.Replace(", ", " ")); },
"SendAnalyticsAction", "Send an analytics action")); "SendAnalyticsAction", "Send an analytics action"));
System.Random random = new System.Random(); // for command below
CommandManager.AddCommand(new SimpleCustomCommandEngine(
() => {
if (!GameState.IsSimulationMode())
{
Logging.CommandLogError("You must be in simulation mode for this to work!");
return;
} }
Tasks.Repeatable task = new Tasks.Repeatable(() => {
uint count = 0;
EGID[] eBlocks = Blocks.Signals.GetElectricBlocks();
for (uint i = 0u; i < eBlocks.Length; i++)
{
uint[] ids = Blocks.Signals.GetSignalIDs(eBlocks[i]);
for (uint j = 0u; j < ids.Length; j++)
{
Blocks.Signals.SetSignalByID(ids[j], (float)random.NextDouble());
count++;
}
}
Logging.MetaDebugLog($"Did the thing on {count} inputs");
},
() => { return GameState.IsSimulationMode(); });
Tasks.Scheduler.Schedule(task);
}, "RandomizeSignalsInputs", "Do the thing"));
}
// dependency test
if (Dependency.Hell("GamecraftScripting", new Version("0.0.1.0"))) if (Dependency.Hell("GamecraftScripting", new Version("0.0.1.0")))
{ {
Logging.LogWarning("You're in GamecraftScripting dependency hell"); Logging.LogWarning("You're in GamecraftScripting dependency hell");