Browse Source

Modify & Fix signal API

tags/v0.1.3.0
NGnius 4 years ago
parent
commit
0459bdf9d9
3 changed files with 209 additions and 153 deletions
  1. +92
    -102
      GamecraftModdingAPI/Blocks/SignalEngine.cs
  2. +89
    -44
      GamecraftModdingAPI/Blocks/Signals.cs
  3. +28
    -7
      GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs

+ 92
- 102
GamecraftModdingAPI/Blocks/SignalEngine.cs View File

@@ -19,6 +19,7 @@ using Svelto.ECS.EntityStructs;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;
using Gamecraft.Wires;

using GamecraftModdingAPI.Utility;

@@ -35,11 +36,7 @@ namespace GamecraftModdingAPI.Blocks

public bool IsInGame = false;

private Stack<uint> cubesStack = new Stack<uint>();
private bool stackInUse = false;

private FasterList<uint> cubesList = new FasterList<uint>();
private bool listInUse = false;
private System.Random random = new System.Random();

public void Dispose()
{
@@ -51,137 +48,130 @@ namespace GamecraftModdingAPI.Blocks
IsInGame = true;
}

public void DoTheThing()
{
GamecraftModdingAPI.Tasks.Repeatable thing = new GamecraftModdingAPI.Tasks.Repeatable(
() => { Thing(); },
() => { return IsSimulationMode(); } );
GamecraftModdingAPI.Tasks.Scheduler.Schedule(thing);
}

public void Thing()
{
uint count = 0;
EGID[] eBlocks = GetElectricBlocks();
for (uint i = 0u; i < eBlocks.Length; i++)
{
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(uint blockID, uint channel, float signal, out EGID clusterID)
public bool SetSignal(EGID blockID, float signal, out uint signalID, bool input = true)
{
clusterID = GetClusterEGID(blockID, channel);
return SetSignal(clusterID, signal);
signalID = GetSignalIDs(blockID, input)[0];
return SetSignal(signalID, signal);
}

public bool SetSignal(EGID clusterID, float signal)
public bool SetSignal(uint signalID, float signal, bool input = true)
{
if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID))
ExclusiveGroup group = input ? NamedExclusiveGroup<InputPortsGroup>.Group : NamedExclusiveGroup<OutputPortsGroup>.Group;
if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
{
entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID).outputSignal = signal;
return true;
entitiesDB.QueryEntity<PortEntityStruct>(signalID, group).value = signal;
return true;
}
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);
return AddSignal(clusterID, signal, clamp);
signalID = GetSignalIDs(blockID, input)[0];
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))
{
ref ChannelOutputSignalDataStruct chanOutSig = ref entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID);
chanOutSig.outputSignal += signal;
if (clamp)
{
if (chanOutSig.outputSignal > Signals.POSITIVE_HIGH)
{
chanOutSig.outputSignal = Signals.POSITIVE_HIGH;
}
else if (chanOutSig.outputSignal < Signals.NEGATIVE_HIGH)
{
chanOutSig.outputSignal = Signals.NEGATIVE_HIGH;
}
return chanOutSig.outputSignal;
}
}
ExclusiveGroup group = input ? NamedExclusiveGroup<InputPortsGroup>.Group : NamedExclusiveGroup<OutputPortsGroup>.Group;
if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
{
ref PortEntityStruct pes = ref entitiesDB.QueryEntity<PortEntityStruct>(signalID, group);
pes.value += signal;
if (clamp)
{
if (pes.value > Signals.POSITIVE_HIGH)
{
pes.value = Signals.POSITIVE_HIGH;
}
else if (pes.value < Signals.NEGATIVE_HIGH)
{
pes.value = Signals.NEGATIVE_HIGH;
}
return pes.value;
}
}
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);
return GetSignal(clusterID);
signalID = GetSignalIDs(blockID, input)[0];
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;
}

public EGID GetClusterEGID(uint blockID, uint channel)
{
//uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID);
//uint index;
//ElectricityEntityStruct[] structs;
EGID elecEGID = new EGID(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID))
{
elecEGID = new EGID(blockID, CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP);
}
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID))
{
return default;
}
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;
}
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 uint[] GetElectricBlocks()
{
uint count = entitiesDB.Count<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[0])
+ entitiesDB.Count<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[1]);
public EGID[] GetElectricBlocks()
{
uint count = entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS) + entitiesDB.Count<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
uint i = 0;
uint[] res = new uint[count];
foreach (ref var ees in entitiesDB.QueryEntities<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD))
EGID[] res = new EGID[count];
foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.OWNED_BLOCKS))
{
res[i] = ees.ID.entityID;
res[i] = s.ID;
i++;
}
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
foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities<BlockPortsStruct>(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS))
{
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;
res[i] = s.ID;
i++;
}
return res;
}

public bool IsSimulationMode()


+ 89
- 44
GamecraftModdingAPI/Blocks/Signals.cs View File

@@ -24,110 +24,155 @@ namespace GamecraftModdingAPI.Blocks
private static SignalEngine signalEngine = new SignalEngine();

/// <summary>
/// Set the electric block's channel to a value
/// Set the electric block's (first) signal value.
/// </summary>
/// <param name="id">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>
public static void SetSignalConnectedBlocks(uint id, uint channel, float signal)
/// <param name="blockID">The block's id.</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>
/// <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(id, channel, signal, out EGID _);
signalEngine.SetSignal(egid, signal, out uint _, input);
}
}

public static void SetSignalByBlock(EGID blockID, float signal, bool input = true)
{
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
signalEngine.SetSignal(blockID, signal, out uint _, input);
}
}

/// <summary>
/// Set a conductive cluster channel to a value
/// Set a signal's value.
/// </summary>
/// <param name="clusterID">The channel cluster's id</param>
/// <param name="signal">The signal value (-1 to 1; not enforced)</param>
public static void SetSignalCluster(EGID clusterID, float signal)
/// <param name="signalID">The channel cluster's id.</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 SetSignalByID(uint signalID, float signal, bool input = true)
{
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
signalEngine.SetSignal(clusterID, signal);
signalEngine.SetSignal(signalID, signal, input);
}
}

/// <summary>
/// Add a value to an electric block's channel signal
/// Add a value to an electric block's signal.
/// </summary>
/// <param name="id">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="clamp">Whether to clamp the resulting signal value between -1 and 1</param>
public static void AddSignalConnectedBlocks(uint id, uint channel, float signal, bool clamp = true)
/// <param name="blockID">The block'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>
/// <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 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())
{
return signalEngine.AddSignal(egid, signal, out uint _, clamp, input);
}
return 0f;
}

public static float AddSignalByBlock(EGID blockID, float signal, bool clamp = true, bool input = true)
{
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{
signalEngine.AddSignal(id, channel, signal, out EGID _, clamp);
return signalEngine.AddSignal(blockID, signal, out uint _, clamp, input);
}
return 0f;
}

/// <summary>
/// Add a value to a conductive cluster channel
/// 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)
/// <param name="signalID">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>
/// <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())
{
signalEngine.AddSignal(clusterID, signal, clamp);
return signalEngine.AddSignal(signalID, signal, clamp, input);
}
return 0f;
}

/// <summary>
/// Get a electric block's channel's signal value
/// Get a electric block's signal's (first) 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)
/// <param name="blockID">The block's id.</param>
/// <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(id, channel, out EGID _);
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 conductive cluster channel's signal value
/// Get a signal's value.
/// </summary>
/// <param name="clusterID">The channel cluster's id</param>
/// <returns>The signal value</returns>
public static float GetSignalCluster(EGID clusterID)
/// <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(clusterID);
return signalEngine.GetSignal(signalID, input);
}
return 0f;
}

/// <summary>
/// Get the ID of every electricity consumer in the game world
/// Get the ID of every electric block in the game world.
/// </summary>
/// <returns>The block IDs</returns>
public static uint[] GetElectricBlocks()
/// <returns>The block IDs.</returns>
public static EGID[] GetElectricBlocks()
{
return signalEngine.GetElectricBlocks();
}

/// <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>
/// <param name="id">The block's id</param>
/// <param name="channel"></param>
/// <returns>The unique ID</returns>
public static EGID GetClusterID(uint id, uint channel)
/// <param name="blockID">The block's id.</param>
/// <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 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()
{


+ 28
- 7
GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs View File

@@ -51,13 +51,7 @@ namespace GamecraftModdingAPI.Tests
//AnalyticsDisablerPatch.DisableAnalytics = true;
// disable background music
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

/*if (!FMODUnity.RuntimeManager.HasBankLoaded("Modded"))
{
FMODUnity.RuntimeManager.LoadBank("Modded", true);
}
FMODUnity.RuntimeManager.PlayOneShot("event:/ModEvents/KillDashNine3D");*/
//AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called :(

// debug/test handlers
EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("App Inited event!"); }, () => { },
@@ -99,7 +93,34 @@ namespace GamecraftModdingAPI.Tests
CommandManager.AddCommand(new SimpleCustomCommandEngine<string>(
(s) => { Analytics.DeltaDNAHelper.SendActionCompletedEvent(in plp, s.Replace(", ", " ")); },
"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")))
{
Logging.LogWarning("You're in GamecraftScripting dependency hell");


Loading…
Cancel
Save