From 5f05db7ca4ca1782a077e455c0c91e9f6320680c Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 2 Apr 2016 02:25:44 +0300 Subject: [PATCH] - fixed "signal loops" causing StackOverFlowExceptions (now the signals can only take 10 "steps" between components per frame) - parameter for changing the output value of And/Or components when the input conditions aren't met - or components work properly now - a limited number of signals (100) can be queued in a delay component --- Subsurface/Source/Items/Components/Door.cs | 4 +-- .../Source/Items/Components/ItemComponent.cs | 2 +- .../Items/Components/Machines/Controller.cs | 10 +++---- .../Items/Components/Machines/Engine.cs | 4 +-- .../Source/Items/Components/Machines/Pump.cs | 4 +-- .../Items/Components/Machines/Reactor.cs | 4 +-- .../Items/Components/Machines/Steering.cs | 8 ++--- .../Items/Components/Power/PowerContainer.cs | 2 +- .../Items/Components/Power/PowerTransfer.cs | 8 ++--- .../Source/Items/Components/Power/Powered.cs | 2 +- .../Items/Components/Signal/AndComponent.cs | 19 ++++++++---- .../Items/Components/Signal/Connection.cs | 4 +-- .../Items/Components/Signal/DelayComponent.cs | 10 +++++-- .../Items/Components/Signal/LightComponent.cs | 4 +-- .../Items/Components/Signal/NotComponent.cs | 4 +-- .../Items/Components/Signal/OrComponent.cs | 12 ++++---- .../Items/Components/Signal/OxygenDetector.cs | 2 +- .../Components/Signal/RegExFindComponent.cs | 8 ++--- .../Items/Components/Signal/RelayComponent.cs | 23 +++++++------- .../Components/Signal/SignalCheckComponent.cs | 4 +-- .../Items/Components/Signal/WaterDetector.cs | 2 +- .../Items/Components/Signal/WifiComponent.cs | 4 +-- Subsurface/Source/Items/Components/Turret.cs | 2 +- Subsurface/Source/Items/Item.cs | 30 +++++++++++++++++-- 24 files changed, 107 insertions(+), 69 deletions(-) diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index 59367e2c1..4c1dbffbb 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -282,7 +282,7 @@ namespace Barotrauma.Items.Components } - item.SendSignal((isOpen) ? "1" : "0", "state_out"); + item.SendSignal(0, (isOpen) ? "1" : "0", "state_out"); } public override void UpdateBroken(float deltaTime, Camera cam) @@ -436,7 +436,7 @@ namespace Barotrauma.Items.Components } } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { if (isStuck || GameMain.Client != null) return; diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index 5b70eaa0c..25b986577 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -458,7 +458,7 @@ namespace Barotrauma.Items.Components //called then the item is dropped or dragged out of a "limbslot" public virtual void Unequip(Character character) { } - public virtual void ReceiveSignal(string signal, Connection connection, Item sender, float power = 0.0f) + public virtual void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power = 0.0f) { switch (connection.Name) diff --git a/Subsurface/Source/Items/Components/Machines/Controller.cs b/Subsurface/Source/Items/Components/Machines/Controller.cs index 2efa92e1a..5155bd503 100644 --- a/Subsurface/Source/Items/Components/Machines/Controller.cs +++ b/Subsurface/Source/Items/Components/Machines/Controller.cs @@ -137,7 +137,7 @@ namespace Barotrauma.Items.Components return false; } - item.SendSignal("1", "trigger_out"); + item.SendSignal(0, "1", "trigger_out"); ApplyStatusEffects(ActionType.OnUse, 1.0f, activator); @@ -173,7 +173,7 @@ namespace Barotrauma.Items.Components if (focusTarget == null) { - item.SendSignal(ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); + item.SendSignal(0, ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); return; } @@ -185,13 +185,13 @@ namespace Barotrauma.Items.Components if (!character.IsNetworkPlayer || character.ViewTarget == focusTarget) { - item.SendSignal(ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); + item.SendSignal(0, ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); } } public override bool Pick(Character picker) { - item.SendSignal("1", "signal_out"); + item.SendSignal(0, "1", "signal_out"); PlaySound(ActionType.OnUse, item.WorldPosition); @@ -237,7 +237,7 @@ namespace Barotrauma.Items.Components IsActive = true; } - item.SendSignal("1", "signal_out"); + item.SendSignal(0, "1", "signal_out"); return true; } diff --git a/Subsurface/Source/Items/Components/Machines/Engine.cs b/Subsurface/Source/Items/Components/Machines/Engine.cs index 40388ff05..a97d3030c 100644 --- a/Subsurface/Source/Items/Components/Machines/Engine.cs +++ b/Subsurface/Source/Items/Components/Machines/Engine.cs @@ -124,9 +124,9 @@ namespace Barotrauma.Items.Components force = MathHelper.Lerp(force, 0.0f, 0.1f); } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { - base.ReceiveSignal(signal, connection, sender, power); + base.ReceiveSignal(stepsTaken, signal, connection, sender, power); if (connection.Name == "set_force") { diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index 4031b6e40..de68b59dc 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -163,9 +163,9 @@ namespace Barotrauma.Items.Components } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { - base.ReceiveSignal(signal, connection, sender, power); + base.ReceiveSignal(stepsTaken, signal, connection, sender, power); if (connection.Name == "toggle") { diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index 991e82829..8f6e18cd5 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -315,7 +315,7 @@ namespace Barotrauma.Items.Components ExtraCooling = 0.0f; AvailableFuel = 0.0f; - item.SendSignal(((int)temperature).ToString(), "temperature_out"); + item.SendSignal(0, ((int)temperature).ToString(), "temperature_out"); sendUpdateTimer = Math.Max(sendUpdateTimer - deltaTime, 0.0f); @@ -519,7 +519,7 @@ namespace Barotrauma.Items.Components GUI.DrawLine(spriteBatch, prevPoint, lastPoint, color); } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power) { switch (connection.Name) { diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 8e4f20246..59fadf364 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -135,13 +135,13 @@ namespace Barotrauma.Items.Components UpdateAutoPilot(deltaTime); } - item.SendSignal(targetVelocity.X.ToString(CultureInfo.InvariantCulture), "velocity_x_out"); + item.SendSignal(0, targetVelocity.X.ToString(CultureInfo.InvariantCulture), "velocity_x_out"); float targetLevel = -targetVelocity.Y; targetLevel += (neutralBallastLevel - 0.5f) * 100.0f; - item.SendSignal(targetLevel.ToString(CultureInfo.InvariantCulture), "velocity_y_out"); + item.SendSignal(0, targetLevel.ToString(CultureInfo.InvariantCulture), "velocity_y_out"); voltage -= deltaTime; @@ -299,7 +299,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { if (connection.Name == "velocity_in") { @@ -307,7 +307,7 @@ namespace Barotrauma.Items.Components } else { - base.ReceiveSignal(signal, connection, sender, power); + base.ReceiveSignal(stepsTaken, signal, connection, sender, power); } } diff --git a/Subsurface/Source/Items/Components/Power/PowerContainer.cs b/Subsurface/Source/Items/Components/Power/PowerContainer.cs index 474b97ba8..23ab0e9e9 100644 --- a/Subsurface/Source/Items/Components/Power/PowerContainer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerContainer.cs @@ -208,7 +208,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power) { if (!connection.IsPower) return; diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index 824ed435f..4b6ce84e9 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -61,7 +61,7 @@ namespace Barotrauma.Items.Components pt.powerLoad += (fullLoad - pt.powerLoad) / inertia; pt.currPowerConsumption += (-fullPower - pt.currPowerConsumption) / inertia; - pt.Item.SendSignal("", "power", fullPower / Math.Max(fullLoad, 1.0f)); + pt.Item.SendSignal(0, "", "power", fullPower / Math.Max(fullLoad, 1.0f)); //damage the item if voltage is too high if (-pt.currPowerConsumption < Math.Max(pt.powerLoad * Rand.Range(1.95f,2.05f), 200.0f)) continue; @@ -182,13 +182,13 @@ namespace Barotrauma.Items.Components spriteBatch.DrawString(GUI.Font, "Load: " + (int)powerLoad + " kW", new Vector2(x + 30, y + 100), Color.White); } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power) { - base.ReceiveSignal(signal, connection, sender, power); + base.ReceiveSignal(stepsTaken, signal, connection, sender, power); if (connection.Name.Length > 5 && connection.Name.Substring(0, 6).ToLower() == "signal") { - connection.SendSignal(signal, sender, 0.0f); + connection.SendSignal(stepsTaken, signal, sender, 0.0f); } } diff --git a/Subsurface/Source/Items/Components/Power/Powered.cs b/Subsurface/Source/Items/Components/Power/Powered.cs index 5c0ec5002..3e064315c 100644 --- a/Subsurface/Source/Items/Components/Power/Powered.cs +++ b/Subsurface/Source/Items/Components/Power/Powered.cs @@ -83,7 +83,7 @@ namespace Barotrauma.Items.Components } } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power = 0) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power = 0) { if (currPowerConsumption == 0.0f) voltage = 0.0f; if (connection.IsPower) voltage = power; diff --git a/Subsurface/Source/Items/Components/Signal/AndComponent.cs b/Subsurface/Source/Items/Components/Signal/AndComponent.cs index 4795de333..bbed05bfa 100644 --- a/Subsurface/Source/Items/Components/Signal/AndComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/AndComponent.cs @@ -5,7 +5,7 @@ namespace Barotrauma.Items.Components { class AndComponent : ItemComponent { - protected string output; + protected string output, falseOutput; //an array to keep track of how long ago a non-zero signal was received on both inputs protected float[] timeSinceReceived; @@ -30,6 +30,13 @@ namespace Barotrauma.Items.Components set { output = value; } } + [InGameEditable, HasDefaultValue("", true)] + public string FalseOutput + { + get { return falseOutput; } + set { falseOutput = value; } + } + public AndComponent(Item item, XElement element) : base (item, element) { @@ -47,13 +54,13 @@ namespace Barotrauma.Items.Components timeSinceReceived[i] += deltaTime; } - if (sendOutput) - { - item.SendSignal(output, "signal_out"); - } + string signalOut = sendOutput ? output : falseOutput; + if (string.IsNullOrEmpty(signalOut)) return; + + item.SendSignal(0, signalOut, "signal_out"); } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { switch (connection.Name) { diff --git a/Subsurface/Source/Items/Components/Signal/Connection.cs b/Subsurface/Source/Items/Components/Signal/Connection.cs index a04a84a87..0b8d6375e 100644 --- a/Subsurface/Source/Items/Components/Signal/Connection.cs +++ b/Subsurface/Source/Items/Components/Signal/Connection.cs @@ -152,7 +152,7 @@ namespace Barotrauma.Items.Components } - public void SendSignal(string signal, Item sender, float power) + public void SendSignal(int stepsTaken, string signal, Item sender, float power) { for (int i = 0; i> signalQueue; @@ -40,15 +42,17 @@ namespace Barotrauma.Items.Components { var signalOut = signalQueue.Dequeue(); - item.SendSignal(signalOut.Item1, "signal_out"); + item.SendSignal(0, signalOut.Item1, "signal_out"); } } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { switch (connection.Name) { case "signal_in": + if (signalQueue.Count >= SignalQueueSize) return; + signalQueue.Enqueue(new Tuple(signal, DateTime.Now)); break; } diff --git a/Subsurface/Source/Items/Components/Signal/LightComponent.cs b/Subsurface/Source/Items/Components/Signal/LightComponent.cs index ae135333e..390ac749c 100644 --- a/Subsurface/Source/Items/Components/Signal/LightComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/LightComponent.cs @@ -163,9 +163,9 @@ namespace Barotrauma.Items.Components light.Remove(); } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { - base.ReceiveSignal(signal, connection, sender, power); + base.ReceiveSignal(stepsTaken, signal, connection, sender, power); switch (connection.Name) { diff --git a/Subsurface/Source/Items/Components/Signal/NotComponent.cs b/Subsurface/Source/Items/Components/Signal/NotComponent.cs index 076a496c9..123242d72 100644 --- a/Subsurface/Source/Items/Components/Signal/NotComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/NotComponent.cs @@ -9,11 +9,11 @@ namespace Barotrauma.Items.Components { } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { if (connection.Name != "signal_in") return; - item.SendSignal(signal=="0" ? "1" : "0", "signal_out"); + item.SendSignal(stepsTaken, signal=="0" ? "1" : "0", "signal_out"); } } } diff --git a/Subsurface/Source/Items/Components/Signal/OrComponent.cs b/Subsurface/Source/Items/Components/Signal/OrComponent.cs index 5515635d3..49b7c7e1c 100644 --- a/Subsurface/Source/Items/Components/Signal/OrComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/OrComponent.cs @@ -11,17 +11,17 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { - bool sendOutput = true; + bool sendOutput = false; for (int i = 0; i timeFrame) sendOutput = false; + if (timeSinceReceived[i] <= timeFrame) sendOutput = true; timeSinceReceived[i] += deltaTime; } - if (sendOutput) - { - item.SendSignal(output, "signal_out"); - } + string signalOut = sendOutput ? output : falseOutput; + if (string.IsNullOrEmpty(signalOut)) return; + + item.SendSignal(0, signalOut, "signal_out"); } } } diff --git a/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs b/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs index 1a06ccf46..559e56124 100644 --- a/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs +++ b/Subsurface/Source/Items/Components/Signal/OxygenDetector.cs @@ -14,7 +14,7 @@ namespace Barotrauma.Items.Components { if (item.CurrentHull == null) return; - item.SendSignal(((int)item.CurrentHull.OxygenPercentage).ToString(), "signal_out"); + item.SendSignal(0, ((int)item.CurrentHull.OxygenPercentage).ToString(), "signal_out"); } diff --git a/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs b/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs index 75797a326..401fa850b 100644 --- a/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs @@ -40,7 +40,7 @@ namespace Barotrauma.Items.Components catch { - item.SendSignal("ERROR", "signal_out"); + item.SendSignal(0, "ERROR", "signal_out"); return; } } @@ -67,17 +67,17 @@ namespace Barotrauma.Items.Components } catch { - item.SendSignal("ERROR", "signal_out"); + item.SendSignal(0, "ERROR", "signal_out"); previousResult = false; return; } } - item.SendSignal(previousResult ? output : "0", "signal_out"); + item.SendSignal(0, previousResult ? output : "0", "signal_out"); } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power = 0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power = 0.0f) { switch (connection.Name) { diff --git a/Subsurface/Source/Items/Components/Signal/RelayComponent.cs b/Subsurface/Source/Items/Components/Signal/RelayComponent.cs index 00d8333cf..958dffa13 100644 --- a/Subsurface/Source/Items/Components/Signal/RelayComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/RelayComponent.cs @@ -20,20 +20,23 @@ namespace Barotrauma.Items.Components [Editable, HasDefaultValue(false, true)] public bool IsOn { - get { return IsActive; } - set - { - IsActive = value; - } + get; set; } public RelayComponent(Item item, XElement element) : base (item, element) { IsActive = true; + IsOn = true; } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void Update(float deltaTime, Camera cam) + { + + item.SendSignal(0, IsOn ? "1" : "0", "state_out"); + } + + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { if (item.Condition <= 0.0f) return; @@ -41,7 +44,7 @@ namespace Barotrauma.Items.Components if (connection.Name.Contains("_in")) { - if (!IsActive) return; + if (!IsOn) return; string outConnection = connection.Name.Contains("power_in") ? "power_out" : "signal_out"; @@ -50,15 +53,15 @@ namespace Barotrauma.Items.Components if (connectionNumber > 0) outConnection += connectionNumber; - item.SendSignal(signal, outConnection, power); + item.SendSignal(stepsTaken, signal, outConnection, power); } else if (connection.Name == "toggle") { - IsActive = !IsActive; + IsOn = !IsOn; } else if (connection.Name == "set_state") { - IsActive = signal == "1"; + IsOn = signal != "0"; } } diff --git a/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs b/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs index 11e31d43a..b2e4133d9 100644 --- a/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs @@ -27,12 +27,12 @@ namespace Barotrauma.Items.Components { } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { switch (connection.Name) { case "signal_in": - item.SendSignal((signal == targetSignal) ? output : "0", "signal_out"); + item.SendSignal(stepsTaken, (signal == targetSignal) ? output : "0", "signal_out"); break; case "set_output": diff --git a/Subsurface/Source/Items/Components/Signal/WaterDetector.cs b/Subsurface/Source/Items/Components/Signal/WaterDetector.cs index 9bd7de3f3..43487d317 100644 --- a/Subsurface/Source/Items/Components/Signal/WaterDetector.cs +++ b/Subsurface/Source/Items/Components/Signal/WaterDetector.cs @@ -12,7 +12,7 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { - item.SendSignal(item.InWater ? "1" : "0", "signal_out"); + item.SendSignal(0, item.InWater ? "1" : "0", "signal_out"); } } } diff --git a/Subsurface/Source/Items/Components/Signal/WifiComponent.cs b/Subsurface/Source/Items/Components/Signal/WifiComponent.cs index 263a59616..5211d7d29 100644 --- a/Subsurface/Source/Items/Components/Signal/WifiComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/WifiComponent.cs @@ -28,7 +28,7 @@ namespace Barotrauma.Items.Components list.Add(this); } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) { //prevent an ininite loop of wificomponents sending messages between each other if (sender.GetComponent()!=null) return; @@ -39,7 +39,7 @@ namespace Barotrauma.Items.Components foreach (WifiComponent wifiComp in list) { if (wifiComp == this || wifiComp.channel != channel) continue; - wifiComp.item.SendSignal(signal, "signal_out"); + wifiComp.item.SendSignal(stepsTaken, signal, "signal_out"); } break; } diff --git a/Subsurface/Source/Items/Components/Turret.cs b/Subsurface/Source/Items/Components/Turret.cs index 606ce8b26..f9a8bfdc0 100644 --- a/Subsurface/Source/Items/Components/Turret.cs +++ b/Subsurface/Source/Items/Components/Turret.cs @@ -327,7 +327,7 @@ namespace Barotrauma.Items.Components return projectiles; } - public override void ReceiveSignal(string signal, Connection connection, Item sender, float power) + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power) { switch (connection.Name) { diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index d2dbacb29..ef7b6d4ff 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -986,18 +986,42 @@ namespace Barotrauma return connectedComponents; } - public void SendSignal(string signal, string connectionName, float power = 0.0f) + public void SendSignal(int stepsTaken, string signal, string connectionName, float power = 0.0f) { + stepsTaken++; + ConnectionPanel panel = GetComponent(); if (panel == null) return; foreach (Connection c in panel.Connections) { if (c.Name != connectionName) continue; - - c.SendSignal(signal, this, power); + + if (stepsTaken > 10) + { + //use a coroutine to prevent infinite loops by creating a one + //frame delay if the "signal chain" gets too long + CoroutineManager.StartCoroutine(SendSignal(signal, c, power)); + } + else + { + c.SendSignal(stepsTaken, signal, this, power); + } } } + private IEnumerable SendSignal(string signal, Connection connection, float power = 0.0f) + { + //wait one frame + yield return CoroutineStatus.Running; + + ConnectionPanel panel = GetComponent(); + if (panel == null) yield return CoroutineStatus.Success; + + connection.SendSignal(0, signal, this, power); + + yield return CoroutineStatus.Success; + } + /// Position of the Character doing the pick, only items that are close enough to this are checked /// the item closest to pickPosition is returned /// If a hull is specified, only items within that hull are checked