using Barotrauma.Networking; using Lidgren.Network; using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; namespace Barotrauma.Items.Components { partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable { public static Wire HighlightedWire; public List Connections; Character user; public ConnectionPanel(Item item, XElement element) : base(item, element) { Connections = new List(); foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString()) { case "input": Connections.Add(new Connection(subElement, item)); break; case "output": Connections.Add(new Connection(subElement, item)); break; } } IsActive = true; } public override void OnMapLoaded() { foreach (Connection c in Connections) { c.ConnectLinked(); } } public override void Update(float deltaTime, Camera cam) { if (user != null && user.SelectedConstruction != item) user = null; } public override bool Select(Character picker) { //attaching wires to items with a body is not allowed //(signal items remove their bodies when attached to a wall) if (item.body != null) { return false; } user = picker; IsActive = true; return true; } public override bool Use(float deltaTime, Character character = null) { if (character == null || character!=user) return false; var powered = item.GetComponent(); if (powered != null) { if (powered.Voltage < 0.1f) return false; } float degreeOfSuccess = DegreeOfSuccess(character); if (Rand.Range(0.0f, 50.0f) < degreeOfSuccess) return false; character.SetStun(5.0f); item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character); return true; } public override void Load(XElement element) { base.Load(element); List loadedConnections = new List(); foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString()) { case "input": loadedConnections.Add(new Connection(subElement, item)); break; case "output": loadedConnections.Add(new Connection(subElement, item)); break; } } for (int i = 0; i w != null); msg.WriteRangedInteger(0, Connection.MaxLinked, wires.Length); for (int i = 0; i < wires.Length; i++) { msg.Write(wires[i].Item.ID); } } } public void ServerRead(ClientNetObject type, NetBuffer msg, Client c) { List[] wires = new List[Connections.Count]; //read wire IDs for each connection for (int i = 0; i < Connections.Count; i++) { wires[i] = new List(); int wireCount = msg.ReadRangedInteger(0, Connection.MaxLinked); for (int j = 0; j < wireCount; j++) { ushort wireId = msg.ReadUInt16(); Item wireItem = Entity.FindEntityByID(wireId) as Item; if (wireItem == null) continue; Wire wireComponent = wireItem.GetComponent(); if (wireComponent != null) { wires[i].Add(wireComponent); } } } item.CreateServerEvent(this); //check if the character can access this connectionpanel //and all the wires they're trying to connect if (!item.CanClientAccess(c)) return; for (int i = 0; i < Connections.Count; i++) { foreach (Wire wire in wires[i]) { //wire not found in any of the connections yet (client is trying to connect a new wire) // -> we need to check if the client has access to it if (!Connections.Any(connection => connection.Wires.Contains(wire))) { if (!wire.Item.CanClientAccess(c)) return; } } } //go through existing wire links for (int i = 0; i < Connections.Count; i++) { for (int j = 0; j < Connection.MaxLinked; j++) { Wire existingWire = Connections[i].Wires[j]; if (existingWire == null) continue; //existing wire not in the list of new wires -> disconnect it if (!wires[i].Contains(existingWire)) { existingWire.RemoveConnection(item); if (existingWire.Connections[0] == null && existingWire.Connections[1] == null) { GameServer.Log(c.Character.Name + " disconnected a wire from " + Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.ItemInteraction); } else if (existingWire.Connections[0] != null) { GameServer.Log(c.Character.Name + " disconnected a wire from " + Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")", ServerLog.MessageType.ItemInteraction); } else if (existingWire.Connections[1] != null) { GameServer.Log(c.Character.Name + " disconnected a wire from " + Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")", ServerLog.MessageType.ItemInteraction); } Connections[i].Wires[j] = null; } } } //go through new wires for (int i = 0; i < Connections.Count; i++) { foreach (Wire newWire in wires[i]) { //already connected, no need to do anything if (Connections[i].Wires.Contains(newWire)) continue; Connections[i].TryAddLink(newWire); newWire.Connect(Connections[i], true, true); var otherConnection = newWire.OtherConnection(Connections[i]); if (otherConnection == null) { GameServer.Log(c.Character.Name + " connected a wire to " + Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.ItemInteraction); } else { GameServer.Log(c.Character.Name + " connected a wire from " + Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + (otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"), ServerLog.MessageType.ItemInteraction); } } } } public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null) { ClientWrite(msg, extraData); } public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) { foreach (Connection connection in Connections) { connection.ClearConnections(); int wireCount = msg.ReadRangedInteger(0, Connection.MaxLinked); for (int i = 0; i < wireCount; i++) { ushort wireId = msg.ReadUInt16(); Item wireItem = MapEntity.FindEntityByID(wireId) as Item; if (wireItem == null) continue; Wire wireComponent = wireItem.GetComponent(); if (wireComponent == null) continue; connection.Wires[i] = wireComponent; wireComponent.Connect(connection, false); } } } } }