diff --git a/GamecraftModdingAPI/Blocks/SignalEngine.cs b/GamecraftModdingAPI/Blocks/SignalEngine.cs index 62006e3..cbc61a0 100644 --- a/GamecraftModdingAPI/Blocks/SignalEngine.cs +++ b/GamecraftModdingAPI/Blocks/SignalEngine.cs @@ -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 cubesStack = new Stack(); - private bool stackInUse = false; - - private FasterList cubesList = new FasterList(); - private bool listInUse = false; + private System.Random random = new System.Random(); public void Dispose() { @@ -51,139 +48,132 @@ 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(clusterID)) + ExclusiveGroup group = input ? NamedExclusiveGroup.Group : NamedExclusiveGroup.Group; + if (entitiesDB.Exists(signalID, group)) { - entitiesDB.QueryEntity(clusterID).outputSignal = signal; - return true; + entitiesDB.QueryEntity(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(clusterID)) - { - ref ChannelOutputSignalDataStruct chanOutSig = ref entitiesDB.QueryEntity(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.Group : NamedExclusiveGroup.Group; + if (entitiesDB.Exists(signalID, group)) + { + ref PortEntityStruct pes = ref entitiesDB.QueryEntity(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(clusterID)) + ExclusiveGroup group = input ? NamedExclusiveGroup.Group : NamedExclusiveGroup.Group; + if (entitiesDB.Exists(signalID, group)) { - return entitiesDB.QueryEntity(clusterID).outputSignal; + return entitiesDB.QueryEntity(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(elecEGID)) - { - elecEGID = new EGID(blockID, CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP); - } - if (!entitiesDB.Exists(elecEGID)) - { - return default; - } - ref ElectricityEntityStruct eStruct = ref entitiesDB.QueryEntity(elecEGID); - ref ConductiveClusterID clusterId = ref entitiesDB.QueryEntity(eStruct.ID).clusterId; - uint operatingChannel = entitiesDB.QueryEntity(eStruct.ID).operatingChannel; - EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterId.ID); - if (clusterId.initialized && clusterId.isConductive && entitiesDB.Exists(eGID)) - { - return eGID; - } - return default; - } + 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 uint[] GetElectricBlocks() - { - uint count = entitiesDB.Count(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[0]) - + entitiesDB.Count(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[1]); + public EGID[] GetElectricBlocks() + { + uint count = entitiesDB.Count(BlockIdentifiers.OWNED_BLOCKS) + entitiesDB.Count(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS); uint i = 0; - uint[] res = new uint[count]; - foreach (ref var ees in entitiesDB.QueryEntities(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD)) + EGID[] res = new EGID[count]; + foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities(BlockIdentifiers.OWNED_BLOCKS)) { - res[i] = ees.ID.entityID; + res[i] = s.ID; + i++; + } + foreach (ref BlockPortsStruct s in entitiesDB.QueryEntities(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS)) + { + 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(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false; - } - return res; - } - else - { - Stack cubeStack = new Stack(); - FasterList cubeList = new FasterList(); - ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return g.isIsolator; }); - uint[] res = cubesList.ToArray(); - foreach (var id in res) - { - entitiesDB.QueryEntity(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false; - } - return res; - } - - } - public bool IsSimulationMode() { return GamecraftModdingAPI.Utility.GameState.IsSimulationMode(); diff --git a/GamecraftModdingAPI/Blocks/Signals.cs b/GamecraftModdingAPI/Blocks/Signals.cs index 91d50d1..3895dbe 100644 --- a/GamecraftModdingAPI/Blocks/Signals.cs +++ b/GamecraftModdingAPI/Blocks/Signals.cs @@ -24,110 +24,155 @@ namespace GamecraftModdingAPI.Blocks private static SignalEngine signalEngine = new SignalEngine(); /// - /// Set the electric block's channel to a value + /// Set the electric block's (first) signal value. /// - /// The block's id - /// The channel (1 to 99) - /// The signal value (-1 to 1; not enforced) - public static void SetSignalConnectedBlocks(uint id, uint channel, float signal) + /// The block's id. + /// The signal value (-1 to 1; not enforced). + /// Whether to retrieve input IDs (true) or output IDs (false). + /// Whether the block is in the owned group (true) or functional group (false) + 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()) { - signalEngine.SetSignal(id, channel, signal, out EGID _); + signalEngine.SetSignal(blockID, signal, out uint _, input); } } /// - /// Set a conductive cluster channel to a value + /// Set a signal's value. /// - /// The channel cluster's id - /// The signal value (-1 to 1; not enforced) - public static void SetSignalCluster(EGID clusterID, float signal) + /// The channel cluster's id. + /// The signal value (-1 to 1; not enforced). + /// Whether to retrieve input IDs (true) or output IDs (false). + 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); } } /// - /// Add a value to an electric block's channel signal + /// Add a value to an electric block's signal. /// - /// The block's id - /// The channel (1 to 99) - /// The signal value to add - /// Whether to clamp the resulting signal value between -1 and 1 - public static void AddSignalConnectedBlocks(uint id, uint channel, float signal, bool clamp = true) + /// The block's id. + /// The signal value to add. + /// Whether to clamp the resulting signal value between -1 and 1. + /// Whether to retrieve input IDs (true) or output IDs (false). + /// Whether the block is in the owned group (true) or functional group (false) + /// The signal's new value. + 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()) { - signalEngine.AddSignal(id, channel, signal, out EGID _, clamp); + return signalEngine.AddSignal(egid, signal, out uint _, clamp, input); } + return 0f; } - /// - /// Add a value to a conductive cluster channel - /// - /// The channel cluster's id - /// The signal value to add - /// Whether to clamp the resulting signal value between -1 and 1 - public static void AddSignalCluster(EGID clusterID, float signal, bool clamp = true) + public static float AddSignalByBlock(EGID blockID, float signal, bool clamp = true, bool input = true) { if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) { - signalEngine.AddSignal(clusterID, signal, clamp); - } - } - - /// - /// Get a electric block's channel's signal value - /// - /// The block's id - /// The channel (1 to 99) - /// The signal value - public static float GetSignalBlock(uint id, uint channel) - { - if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) - { - return signalEngine.GetSignal(id, channel, out EGID _); + return signalEngine.AddSignal(blockID, signal, out uint _, clamp, input); } return 0f; } /// - /// Get a conductive cluster channel's signal value + /// Add a value to a conductive cluster channel. /// - /// The channel cluster's id - /// The signal value - public static float GetSignalCluster(EGID clusterID) + /// The channel cluster's id. + /// The signal value to add. + /// Whether to clamp the resulting signal value between -1 and 1. + /// Whether to retrieve input IDs (true) or output IDs (false). + /// The signal's new value. + public static float AddSignalByID(uint signalID, float signal, bool clamp = true, bool input = true) { if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) { - return signalEngine.GetSignal(clusterID); + return signalEngine.AddSignal(signalID, signal, clamp, input); + } + return 0f; + } + + /// + /// Get a electric block's signal's (first) value. + /// + /// The block's id. + /// Whether to retrieve input IDs (true) or output IDs (false). + /// Whether the block is in the owned group (true) or functional group (false) + /// The signal's value. + 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; } /// - /// Get the ID of every electricity consumer in the game world + /// Get a signal's value. /// - /// The block IDs - public static uint[] GetElectricBlocks() + /// The signal's id. + /// Whether to retrieve input IDs (true) or output IDs (false). + /// The signal's value. + public static float GetSignalByID(uint signalID, bool input = true) + { + if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) + { + return signalEngine.GetSignal(signalID, input); + } + return 0f; + } + + /// + /// Get the ID of every electric block in the game world. + /// + /// The block IDs. + public static EGID[] GetElectricBlocks() { return signalEngine.GetElectricBlocks(); } /// - /// Get the conductive cluster's unique identifier for an electric block + /// Get the unique identifiers for the input wires connected to an electric block. /// - /// The block's id - /// - /// The unique ID - public static EGID GetClusterID(uint id, uint channel) + /// The block's id. + /// Whether to retrieve input IDs (true) or output IDs (false). + /// Whether the block is in the owned group (true) or functional group (false) + /// The unique IDs. + 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() { diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs index 09a1215..3a47ad9 100644 --- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs +++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs @@ -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( (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");