Client LuaCsForBarotrauma
BarotraumaShared/SharedSource/CircuitBox/CircuitBoxWire.cs
1 #nullable enable
2 
3 using System.Xml.Linq;
5 using Microsoft.Xna.Framework;
6 
7 namespace Barotrauma
8 {
9  internal partial class CircuitBoxWire : CircuitBoxSelectable, ICircuitBoxIdentifiable
10  {
11  public CircuitBoxConnection From, To;
12  public readonly Option<Item> BackingWire;
13 
14  public readonly Color Color;
15  public readonly ItemPrefab UsedItemPrefab;
16 
17  public ushort ID { get; }
18 
19  public CircuitBoxWire(CircuitBox circuitBox, ushort Id, Option<Item> backingItem, CircuitBoxConnection from, CircuitBoxConnection to, ItemPrefab prefab)
20  {
21  ID = Id;
22  From = from;
23  To = to;
24  BackingWire = backingItem;
25  Color = prefab.SpriteColor;
26  UsedItemPrefab = prefab;
27 #if CLIENT
28  Renderer = new CircuitBoxWireRenderer(Option.Some(this), to.AnchorPoint, from.AnchorPoint, Color, circuitBox.WireSprite);
29 #endif
30  EnsureWireConnected();
31  }
32 
33  public XElement Save()
34  {
35  XElement element = new XElement("Wire",
36  new XAttribute("id", ID),
37  new XAttribute("backingitemid", BackingWire.TryUnwrap(out var item) ? ItemSlotIndexPair.Serialize(item) : string.Empty),
38  new XAttribute("prefab", UsedItemPrefab.Identifier));
39 
40  XElement fromElement = CircuitBoxConnectorIdentifier.FromConnection(From).Save("From"),
41  toElement = CircuitBoxConnectorIdentifier.FromConnection(To).Save("To");
42 
43  element.Add(fromElement);
44  element.Add(toElement);
45 
46  return element;
47  }
48 
49  public static Option<CircuitBoxWire> TryLoadFromXML(ContentXElement element, CircuitBox circuitBox)
50  {
51  ushort id = element.GetAttributeUInt16("id", ICircuitBoxIdentifiable.NullComponentID);
52  var backingItemIdOption = ItemSlotIndexPair.TryDeserializeFromXML(element, "backingitemid");
53  Identifier usedPrefabIdentifier = element.GetAttributeIdentifier("prefab", Identifier.Empty);
54 
55  if (!ItemPrefab.Prefabs.TryGet(usedPrefabIdentifier, out var itemPrefab))
56  {
57  DebugConsole.ThrowErrorAndLogToGA("CircuitBoxWire.TryLoadFromXML:PrefabNotFound",
58  $"Failed to find prefab used to create wire with identifier {usedPrefabIdentifier} for CircuitBoxWire with ID {id}");
59  return Option.None;
60  }
61 
62  Option<Item> backingItem = Option.None;
63  if (backingItemIdOption.TryUnwrap(out var backingItemIdPair))
64  {
65  if (backingItemIdPair.FindItemInContainer(circuitBox.WireContainer) is { } item)
66  {
67  backingItem = Option.Some(item);
68  }
69  else
70  {
71  DebugConsole.ThrowErrorAndLogToGA("CircuitBoxWire.TryLoadFromXML:IdNotFound",
72  $"Failed to find item with ID {backingItemIdPair} for CircuitBoxWire with ID {id}");
73  return Option.None;
74  }
75  }
76 
77  Option<CircuitBoxConnection> From = Option.None,
78  To = Option.None;
79 
80  foreach (ContentXElement subElement in element.Elements())
81  {
82  switch (subElement.Name.ToString().ToLowerInvariant())
83  {
84  case "from":
85  var fromIdentifier = CircuitBoxConnectorIdentifier.Load(subElement);
86  if (fromIdentifier.FindConnection(circuitBox).TryUnwrap(out var fromConnection))
87  {
88  From = Option.Some(fromConnection);
89  }
90  break;
91  case "to":
92  var toIdentifier = CircuitBoxConnectorIdentifier.Load(subElement);
93  if (toIdentifier.FindConnection(circuitBox).TryUnwrap(out var toConnection))
94  {
95  To = Option.Some(toConnection);
96  }
97  break;
98  }
99  }
100 
101  if (From.TryUnwrap(out var from) && To.TryUnwrap(out var to))
102  {
103  return Option.Some(new CircuitBoxWire(circuitBox, id, backingItem, from, to, itemPrefab));
104  }
105 
106  DebugConsole.ThrowErrorAndLogToGA("CircuitBoxWire.TryLoadFromXML:MissingFromOrTo",
107  $"Failed to load CircuitBoxWire with ID {id}, missing \"From\" or \"To\" connection.");
108 
109  return Option.None;
110  }
111 
112  public void EnsureWireConnected()
113  {
114  EnsureExternalConnection(From, To);
115  EnsureExternalConnection(To, From);
116 
117  if (!BackingWire.TryUnwrap(out var item) || item.GetComponent<Wire>() is not { } wire) { return; }
118 
119  wire.DropOnConnect = false;
120 
121  From.Connection.ConnectWire(wire);
122  To.Connection.ConnectWire(wire);
123 
124  wire.Connect(From.Connection, 0, addNode: false, sendNetworkEvent: false);
125  wire.Connect(To.Connection, 1, addNode: false, sendNetworkEvent: false);
126 
127  static void EnsureExternalConnection(CircuitBoxConnection one, CircuitBoxConnection two)
128  {
129  switch (one)
130  {
131  case CircuitBoxInputConnection input:
132  {
133  if (input.ExternallyConnectedTo.Contains(two)) { break; }
134  input.ExternallyConnectedTo.Add(two);
135  break;
136  }
137  case CircuitBoxOutputConnection output:
138  {
139  if (output.ExternallyConnectedFrom.Contains(two)) { break; }
140  output.ExternallyConnectedFrom.Add(two);
141  break;
142  }
143  case CircuitBoxNodeConnection node when two is CircuitBoxOutputConnection output:
144  {
145  if (node.Connection.CircuitBoxConnections.Contains(output)) { break; }
146  node.Connection.CircuitBoxConnections.Add(output);
147  break;
148  }
149  case CircuitBoxNodeConnection node when two is CircuitBoxInputConnection input:
150  {
151  if (!node.Connection.CircuitBoxConnections.Contains(input))
152  {
153  node.Connection.CircuitBoxConnections.Add(input);
154  }
155  if (!node.ExternallyConnectedFrom.Contains(input))
156  {
157  node.ExternallyConnectedFrom.Add(input);
158  }
159  break;
160  }
161  }
162  }
163  }
164 
165  public void Remove()
166  {
167  // client should not remove wires
168  if (GameMain.NetworkMember is { IsClient: true }) { return; }
169 
170  if (!BackingWire.TryUnwrap(out var wireItem)) { return; }
171 
172  if (Entity.Spawner is { } spawner && Screen.Selected is not { IsEditor: true })
173  {
174  spawner.AddEntityToRemoveQueue(wireItem);
175  return;
176  }
177 
178  Wire? wire = wireItem.GetComponent<Wire>();
179  if (wire is not null)
180  {
181  From.Connection.DisconnectWire(wire);
182  To.Connection.DisconnectWire(wire);
183  }
184  // if EntitySpawner is not available
185  wireItem.Remove();
186  }
187 
188  public static ItemPrefab DefaultWirePrefab => ItemPrefab.Prefabs[Tags.RedWire];
189  public static ItemPrefab SelectedWirePrefab = DefaultWirePrefab;
190  public static readonly Color DefaultWireColor = DefaultWirePrefab.SpriteColor;
191  }
192 }