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(
"Missing display name in connection " + item.Name +
": " +
Name);
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
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.