2 using System.Collections.Generic;
3 using System.Collections.Immutable;
12 private const int DefaultMaxWires = 5;
20 public readonly
string Name;
23 private readonly HashSet<Wire> wires;
24 public IReadOnlyCollection<Wire>
Wires => wires;
35 private bool enumeratingWires;
36 private readonly HashSet<Wire> removedWires =
new HashSet<Wire>();
38 private readonly
Item item;
42 public readonly List<StatusEffect>
Effects;
44 public readonly List<(ushort wireId,
int? connectionIndex)>
LoadedWires;
61 private bool recipientsDirty =
true;
62 private readonly List<Connection> recipients =
new List<Connection>();
67 if (recipientsDirty) { RefreshRecipients(); }
85 return "Connection (" + item.Name +
", " +
Name +
")";
92 if (connector ==
null)
94 connector = GUIStyle.GetComponentStyle(
"ConnectionPanelConnector").GetDefaultSprite();
95 wireVertical = GUIStyle.GetComponentStyle(
"ConnectionPanelWire").GetDefaultSprite();
96 connectionSprite = GUIStyle.GetComponentStyle(
"ConnectionPanelConnection").GetDefaultSprite();
97 connectionSpriteHighlight = GUIStyle.GetComponentStyle(
"ConnectionPanelConnection").GetSprite(GUIComponent.ComponentState.Hover);
98 screwSprites = GUIStyle.GetComponentStyle(
"ConnectionPanelScrew").Sprites[GUIComponent.ComponentState.None].Select(s => s.Sprite).ToList();
102 item = connectionPanel.
Item;
105 MaxWires = Math.Max(element.
Elements().Count(e => e.Name.ToString().Equals(
"link", StringComparison.OrdinalIgnoreCase)),
MaxWires);
108 wires =
new HashSet<Wire>();
113 string displayNameTag =
"", fallbackTag =
"";
117 foreach (var subElement
in item.Prefab.ConfigElement.Elements())
119 if (!subElement.Name.ToString().Equals(
"connectionpanel", StringComparison.OrdinalIgnoreCase)) {
continue; }
121 foreach (XElement connectionElement
in subElement.Elements())
123 string prefabConnectionName = connectionElement.GetAttributeString(
"name",
null);
124 string[] aliases = connectionElement.GetAttributeStringArray(
"aliases", Array.Empty<
string>());
125 if (prefabConnectionName ==
Name || aliases.Contains(
Name))
127 displayNameTag = connectionElement.GetAttributeString(
"displayname",
"");
128 fallbackTag = connectionElement.GetAttributeString(
"fallbackdisplayname",
"");
139 if (!
string.IsNullOrEmpty(displayNameTag))
142 string tagWithoutVariables = displayNameTag?.Split(
'~')?.FirstOrDefault();
143 string fallbackTagWithoutVariables = fallbackTag?.Split(
'~')?.FirstOrDefault();
145 if (TextManager.ContainsTag(tagWithoutVariables))
147 DisplayName = TextManager.GetServerMessage(displayNameTag);
149 else if (TextManager.ContainsTag(fallbackTagWithoutVariables))
151 DisplayName = TextManager.GetServerMessage(fallbackTag);
158 DebugConsole.ThrowError($
"Could not find a display name for the connection {Name} in the item {item.Name} (submarine: {item.Submarine?.Info?.Name ?? "none
"})");
166 LoadedWires =
new List<(ushort wireId, int? connectionIndex)>();
167 foreach (var subElement
in element.Elements())
169 switch (subElement.Name.ToString().ToLowerInvariant())
172 int id = subElement.GetAttributeInt(
"w", 0);
174 if (subElement.GetAttribute(
"i") !=
null)
176 i = subElement.GetAttributeInt(
"i", 0);
178 if (
id < 0) {
id = 0; }
182 Effects ??=
new List<StatusEffect>();
197 recipientsDirty =
true;
201 private void RefreshRecipients()
204 foreach (var wire
in wires)
206 Connection recipient = wire.OtherConnection(
this);
207 if (recipient !=
null) { recipients.Add(recipient); }
209 recipientsDirty =
false;
213 =>
Wires.FirstOrDefault(w => w.Item == it);
221 || wires.Contains(wire)
232 if (wire ==
null || !wires.Contains(wire)) {
return; }
235 if (prevOtherConnection !=
null)
238 if (
IsPower && prevOtherConnection.IsPower &&
Grid !=
null)
241 if (prevOtherConnection.recipients.Count > 1 && recipients.Count > 1)
246 else if (recipients.Count > 1)
249 prevOtherConnection.Grid?.RemoveConnection(prevOtherConnection);
250 prevOtherConnection.Grid =
null;
252 else if (prevOtherConnection.recipients.Count > 1)
262 prevOtherConnection.Grid =
null;
265 prevOtherConnection.recipientsDirty =
true;
267 if (enumeratingWires)
269 removedWires.Add(wire);
275 recipientsDirty =
true;
280 if (wire ==
null || !
TryAddLink(wire)) {
return; }
283 if (otherConnection !=
null)
288 if (
Grid ==
null && otherConnection.Grid !=
null)
291 Grid = otherConnection.Grid;
293 else if (
Grid !=
null && otherConnection.Grid ==
null)
296 otherConnection.Grid =
Grid;
306 otherConnection.recipientsDirty =
true;
308 recipientsDirty =
true;
314 enumeratingWires =
true;
315 foreach (var wire
in wires)
317 Connection recipient = wire.OtherConnection(
this);
318 if (recipient ==
null) {
continue; }
319 if (recipient.item ==
this.item || signal.source?.
LastSentSignalRecipients.LastOrDefault() == recipient) {
continue; }
321 signal.source?.LastSentSignalRecipients.Add(recipient);
323 wire.RegisterSignal(signal, source:
this);
332 connection.ReceiveSignal(signal);
334 GameMain.
LuaCs.
Hook.
Call(
"signalReceived." + connection.Connection.Item.Prefab.Identifier, signal, connection);
336 enumeratingWires =
false;
337 foreach (var removedWire
in removedWires)
339 wires.Remove(removedWire);
341 removedWires.Clear();
353 if (conn.Effects ==
null || signal.value ==
"0") {
return; }
357 conn.Item.ApplyStatusEffect(effect,
ActionType.OnUse, (
float)Timing.Step);
371 foreach (var wire
in wires)
373 wire.RemoveConnection(
this);
374 recipientsDirty =
true;
377 if (enumeratingWires)
379 foreach (var wire
in wires)
381 removedWires.Add(wire);
394 foreach ((ushort wireId,
int? connectionIndex) in
LoadedWires)
398 var wire = wireItem.GetComponent<
Wire>();
402 if (connectionIndex.HasValue)
404 wire.Connect(
this, connectionIndex.Value, addNode:
false, sendNetworkEvent:
false);
408 wire.TryConnect(
this, addNode:
false, sendNetworkEvent:
false);
411 recipientsDirty =
true;
418 public void Save(XElement parentElement)
420 XElement newElement =
new XElement(
IsOutput ?
"output" :
"input",
new XAttribute(
"name",
Name));
422 foreach (var wire
in wires.OrderBy(w => w.Item.ID))
424 newElement.Add(
new XElement(
"link",
425 new XAttribute(
"w", wire.Item.ID.ToString()),
426 new XAttribute(
"i", wire.Connections[0] ==
this ? 0 : 1)));
429 parentElement.Add(newElement);
string? GetAttributeString(string key, string? def)
IEnumerable< ContentXElement > Elements()
int GetAttributeInt(string key, int def)
XAttribute? GetAttribute(string name)
static Entity FindEntityByID(ushort ID)
Find an entity based on the ID
List< ItemComponent > Components
List< Connection > LastSentSignalRecipients
A list of connections the last signal sent by this item went through
static void SendSignalIntoConnection(Signal signal, Connection conn)
Wire FindWireByItem(Item it)
bool IsConnectedToSomething()
Checks if the the connection is connected to a wire or a circuit box connection
IReadOnlyCollection< Wire > Wires
readonly List< StatusEffect > Effects
void SendSignal(Signal signal)
void DisconnectWire(Wire wire)
bool TryAddLink(Wire wire)
bool WireSlotsAvailable()
readonly List<(ushort wireId, int? connectionIndex)> LoadedWires
readonly LocalizedString DisplayName
List< CircuitBoxConnection > CircuitBoxConnections
Circuit box input and output connections that are linked to this connection.
void ConnectWire(Wire wire)
void SetRecipientsDirty()
List< Connection > Recipients
void Save(XElement parentElement)
override string ToString()
Signal LastReceivedSignal
readonly int MaxPlayerConnectableWires
Connection(ContentXElement element, ConnectionPanel connectionPanel, IdRemap idRemap)
void InitializeFromLoaded()
readonly HashSet< Wire > DisconnectedWires
Wires that have been disconnected from the panel, but not removed completely (visible at the bottom o...
void RemoveConnection(Connection c)
void AddConnection(Connection c)
readonly List< Connection > Connections
The base class for components holding the different functionalities of the item
virtual void ReceiveSignal(Signal signal, Connection connection)
static readonly Dictionary< int, GridInfo > Grids
static readonly HashSet< Connection > ChangedConnections
static bool ValidPowerConnection(Connection conn1, Connection conn2)
Connection OtherConnection(Connection connection)
object Call(string name, params object[] args)
readonly Identifier Identifier
StatusEffects can be used to execute various kinds of effects: modifying the state of some entity in ...
static StatusEffect Load(ContentXElement element, string parentDebugName)
PowerPriority
Order in which power sources will provide to a grid, lower number is higher priority
ActionType
ActionTypes define when a StatusEffect is executed.