예제 #1
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            List <Wire>[] wires = new List <Wire> [Connections.Count];

            //read wire IDs for each connection
            for (int i = 0; i < Connections.Count; i++)
            {
                wires[i] = new List <Wire>();
                for (int j = 0; j < Connection.MaxLinked; j++)
                {
                    ushort wireId = msg.ReadUInt16();

                    if (!(Entity.FindEntityByID(wireId) is Item wireItem))
                    {
                        continue;
                    }

                    Wire wireComponent = wireItem.GetComponent <Wire>();
                    if (wireComponent != null)
                    {
                        wires[i].Add(wireComponent);
                    }
                }
            }


            List <Wire> clientSideDisconnectedWires = new List <Wire>();
            ushort      disconnectedWireCount       = msg.ReadUInt16();

            for (int i = 0; i < disconnectedWireCount; i++)
            {
                ushort wireId = msg.ReadUInt16();
                if (!(Entity.FindEntityByID(wireId) is Item wireItem))
                {
                    continue;
                }
                Wire wireComponent = wireItem.GetComponent <Wire>();
                if (wireComponent == null)
                {
                    continue;
                }
                clientSideDisconnectedWires.Add(wireComponent);
            }

            //don't allow rewiring locked panels
            if (Locked || !GameMain.NetworkMember.ServerSettings.AllowRewiring)
            {
                return;
            }

            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)) && !DisconnectedWires.Contains(wire))
                    {
                        if (!wire.Item.CanClientAccess(c))
                        {
                            return;
                        }
                    }
                }
            }

            //go through existing wire links
            for (int i = 0; i < Connections.Count; i++)
            {
                int j = -1;
                foreach (Wire existingWire in Connections[i].Wires)
                {
                    j++;
                    if (existingWire == null)
                    {
                        continue;
                    }

                    //existing wire not in the list of new wires -> disconnect it
                    if (!wires[i].Contains(existingWire))
                    {
                        if (existingWire.Locked)
                        {
                            //this should not be possible unless the client is running a modified version of the game
                            GameServer.Log(c.Character.LogName + " attempted to disconnect a locked wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.Error);
                            continue;
                        }

                        existingWire.RemoveConnection(item);
                        item.GetComponent <ConnectionPanel>()?.DisconnectedWires.Add(existingWire);

                        GameMain.Server.KarmaManager.OnWireDisconnected(c.Character, existingWire);

                        if (existingWire.Connections[0] == null && existingWire.Connections[1] == null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.ItemInteraction);

                            if (!clientSideDisconnectedWires.Contains(existingWire))
                            {
                                existingWire.Item.Drop(c.Character);
                            }
                        }
                        else if (existingWire.Connections[0] != null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")", ServerLog.MessageType.ItemInteraction);

                            //wires that are not in anyone's inventory (i.e. not currently being rewired)
                            //can never be connected to only one connection
                            // -> the client must have dropped the wire from the connection panel

                            /*if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                             * {
                             *  //let other clients know the item was also disconnected from the other connection
                             *  existingWire.Connections[0].Item.CreateServerEvent(existingWire.Connections[0].Item.GetComponent<ConnectionPanel>());
                             *  existingWire.Item.Drop(c.Character);
                             * }*/
                        }
                        else if (existingWire.Connections[1] != null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);

                            /*if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                             * {
                             *  //let other clients know the item was also disconnected from the other connection
                             *  existingWire.Connections[1].Item.CreateServerEvent(existingWire.Connections[1].Item.GetComponent<ConnectionPanel>());
                             *  existingWire.Item.Drop(c.Character);
                             * }*/
                        }

                        Connections[i].SetWire(j, null);
                    }
                }
            }

            foreach (Wire disconnectedWire in DisconnectedWires.ToList())
            {
                if (disconnectedWire.Connections[0] == null &&
                    disconnectedWire.Connections[1] == null &&
                    !clientSideDisconnectedWires.Contains(disconnectedWire))
                {
                    disconnectedWire.Item.Drop(c.Character);
                    GameServer.Log(c.Character.LogName + " dropped " + disconnectedWire.Name, ServerLog.MessageType.Inventory);
                }
            }

            //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.LogName + " connected a wire to " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ")",
                                       ServerLog.MessageType.ItemInteraction);
                    }
                    else
                    {
                        GameServer.Log(c.Character.LogName + " connected a wire from " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ") to " +
                                       (otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"),
                                       ServerLog.MessageType.ItemInteraction);
                    }
                }
            }
        }
예제 #2
0
        private void ApplyRemoteState(IReadMessage msg)
        {
            List <Wire> prevWires = Connections.SelectMany(c => c.Wires.Where(w => w != null)).ToList();
            List <Wire> newWires  = new List <Wire>();

            ushort userID = msg.ReadUInt16();

            if (userID == 0)
            {
                user = null;
            }
            else
            {
                user          = Entity.FindEntityByID(userID) as Character;
                base.IsActive = true;
            }

            foreach (Connection connection in Connections)
            {
                connection.ClearConnections();
            }

            foreach (Connection connection in Connections)
            {
                for (int i = 0; i < connection.MaxWires; i++)
                {
                    ushort wireId = msg.ReadUInt16();

                    if (!(Entity.FindEntityByID(wireId) is Item wireItem))
                    {
                        continue;
                    }
                    Wire wireComponent = wireItem.GetComponent <Wire>();
                    if (wireComponent == null)
                    {
                        continue;
                    }

                    newWires.Add(wireComponent);

                    connection.SetWire(i, wireComponent);
                    wireComponent.Connect(connection, false);
                }
            }

            List <Wire> previousDisconnectedWires = new List <Wire>(DisconnectedWires);

            DisconnectedWires.Clear();
            ushort disconnectedWireCount = msg.ReadUInt16();

            for (int i = 0; i < disconnectedWireCount; i++)
            {
                ushort wireId = msg.ReadUInt16();
                if (!(Entity.FindEntityByID(wireId) is Item wireItem))
                {
                    continue;
                }
                Wire wireComponent = wireItem.GetComponent <Wire>();
                if (wireComponent == null)
                {
                    continue;
                }
                DisconnectedWires.Add(wireComponent);
                base.IsActive = true;
            }

            foreach (Wire wire in prevWires)
            {
                bool connected = wire.Connections[0] != null || wire.Connections[1] != null;
                if (!connected)
                {
                    foreach (Item item in Item.ItemList)
                    {
                        var connectionPanel = item.GetComponent <ConnectionPanel>();
                        if (connectionPanel != null && connectionPanel.DisconnectedWires.Contains(wire))
                        {
                            connected = true;
                            break;
                        }
                    }
                }
                if (wire.Item.ParentInventory == null && !connected)
                {
                    wire.Item.Drop(null);
                }
            }

            foreach (Wire disconnectedWire in previousDisconnectedWires)
            {
                if (disconnectedWire.Connections[0] == null &&
                    disconnectedWire.Connections[1] == null &&
                    !DisconnectedWires.Contains(disconnectedWire))
                {
                    disconnectedWire.Item.Drop(dropper: null);
                }
            }
        }
예제 #3
0
        public static void UpdateEditing(List <Wire> wires)
        {
            //dragging a node of some wire
            if (draggingWire != null)
            {
                if (Character.Controlled != null)
                {
                    Character.Controlled.FocusedItem   = null;
                    Character.Controlled.ResetInteract = true;
                    Character.Controlled.ClearInputs();
                }
                //cancel dragging
                if (!PlayerInput.LeftButtonHeld())
                {
                    draggingWire      = null;
                    selectedNodeIndex = null;
                }
                //update dragging
                else
                {
                    MapEntity.DisableSelect = true;

                    Submarine sub = null;
                    if (draggingWire.connections[0] != null && draggingWire.connections[0].Item.Submarine != null)
                    {
                        sub = draggingWire.connections[0].Item.Submarine;
                    }
                    if (draggingWire.connections[1] != null && draggingWire.connections[1].Item.Submarine != null)
                    {
                        sub = draggingWire.connections[1].Item.Submarine;
                    }

                    Vector2 nodeWorldPos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition) - sub.HiddenSubPosition - sub.Position;// Nodes[(int)selectedNodeIndex];

                    if (selectedNodeIndex.HasValue)
                    {
                        nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f);
                        nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f);

                        draggingWire.nodes[(int)selectedNodeIndex] = nodeWorldPos;
                        draggingWire.UpdateSections();
                    }
                    else
                    {
                        if (Vector2.DistanceSquared(nodeWorldPos, draggingWire.nodes[(int)highlightedNodeIndex]) > Submarine.GridSize.X * Submarine.GridSize.X)
                        {
                            selectedNodeIndex = highlightedNodeIndex;
                        }
                    }


                    MapEntity.SelectEntity(draggingWire.item);
                }

                return;
            }

            //a wire has been selected -> check if we should start dragging one of the nodes
            float nodeSelectDist = 10, sectionSelectDist = 5;

            highlightedNodeIndex = null;
            if (MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList[0] is Item)
            {
                Wire selectedWire = ((Item)MapEntity.SelectedList[0]).GetComponent <Wire>();

                if (selectedWire != null)
                {
                    Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
                    if (selectedWire.item.Submarine != null)
                    {
                        mousePos -= (selectedWire.item.Submarine.Position + selectedWire.item.Submarine.HiddenSubPosition);
                    }

                    //left click while holding ctrl -> check if the cursor is on a wire section,
                    //and add a new node if it is
                    if (PlayerInput.KeyDown(Keys.RightControl) || PlayerInput.KeyDown(Keys.LeftControl))
                    {
                        if (PlayerInput.LeftButtonClicked())
                        {
                            if (Character.Controlled != null)
                            {
                                Character.Controlled.ResetInteract = true;
                                Character.Controlled.ClearInputs();
                            }
                            int closestSectionIndex = selectedWire.GetClosestSectionIndex(mousePos, sectionSelectDist, out _);
                            if (closestSectionIndex > -1)
                            {
                                selectedWire.nodes.Insert(closestSectionIndex + 1, mousePos);
                                selectedWire.UpdateSections();
                            }
                        }
                    }
                    else
                    {
                        //check if close enough to a node
                        int closestIndex = selectedWire.GetClosestNodeIndex(mousePos, nodeSelectDist, out _);
                        if (closestIndex > -1)
                        {
                            highlightedNodeIndex = closestIndex;
                            //start dragging the node
                            if (PlayerInput.LeftButtonHeld())
                            {
                                if (Character.Controlled != null)
                                {
                                    Character.Controlled.ResetInteract = true;
                                    Character.Controlled.ClearInputs();
                                }
                                draggingWire = selectedWire;
                                //selectedNodeIndex = closestIndex;
                                return;
                            }
                            //remove the node
                            else if (PlayerInput.RightButtonClicked() && closestIndex > 0 && closestIndex < selectedWire.nodes.Count - 1)
                            {
                                selectedWire.nodes.RemoveAt(closestIndex);
                                selectedWire.UpdateSections();
                            }
                        }
                    }
                }
            }

            Wire highlighted = null;

            //check which wire is highlighted with the cursor
            if (GUI.MouseOn == null)
            {
                float closestDist = float.PositiveInfinity;
                foreach (Wire w in wires)
                {
                    Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
                    if (w.item.Submarine != null)
                    {
                        mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition);
                    }

                    int highlightedNode = w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out float dist);
                    if (highlightedNode > -1)
                    {
                        if (dist < closestDist)
                        {
                            highlightedNodeIndex = highlightedNode;
                            highlighted          = w;
                            closestDist          = dist;
                        }
                    }

                    if (w.GetClosestSectionIndex(mousePos, highlighted == null ? sectionSelectDist : closestDist, out dist) > -1)
                    {
                        //prefer nodes over sections
                        if (dist + nodeSelectDist * 0.5f < closestDist)
                        {
                            highlightedNodeIndex = null;
                            highlighted          = w;
                            closestDist          = dist + nodeSelectDist * 0.5f;
                        }
                    }
                }
            }

            if (highlighted != null)
            {
                highlighted.item.IsHighlighted = true;
                if (PlayerInput.LeftButtonClicked())
                {
                    MapEntity.DisableSelect = true;
                    MapEntity.SelectEntity(highlighted.item);
                }
            }
        }
        private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Vector2 end, Vector2 start, Wire equippedWire, ConnectionPanel panel, string label)
        {
            int textX = (int)start.X;

            if (start.X < end.X)
            {
                textX -= 10;
            }
            else
            {
                textX += 10;
            }

            bool canDrag = equippedWire == null || equippedWire == wire;

            float alpha = canDrag ? 1.0f : 0.5f;

            bool mouseOn =
                canDrag &&
                ((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
                  PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
                  MathUtils.LineToPointDistanceSquared(start, end, PlayerInput.MousePosition) < 36) ||
                 Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
                 new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));

            if (!string.IsNullOrEmpty(label))
            {
                if (start.Y > panel.GuiFrame.Rect.Bottom - 1.0f)
                {
                    //wire at the bottom of the panel -> draw the text below the panel, tilted 45 degrees
                    GUI.Font.DrawString(spriteBatch, label, start + Vector2.UnitY * 20 * GUI.Scale, Color.White, 45.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
                }
                else
                {
                    GUI.DrawString(spriteBatch,
                                   new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
                                   label,
                                   wire.Locked ? GUI.Style.TextColorDim : (mouseOn ? Wire.higlightColor : GUI.Style.TextColor), Color.Black * 0.9f,
                                   3, GUI.SmallFont);
                }
            }

            var wireEnd = end + Vector2.Normalize(start - end) * 30.0f * panel.Scale;

            float dist = Vector2.Distance(start, wireEnd);

            float wireWidth = 12 * panel.Scale;
            float highlight = 5 * panel.Scale;

            if (mouseOn)
            {
                spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point((int)(wireWidth + highlight), (int)dist)), wireVertical.SourceRect,
                                 Wire.higlightColor,
                                 MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
                                 new Vector2(wireVertical.size.X / 2, 0), // point in line about which to rotate
                                 SpriteEffects.None,
                                 0.0f);
            }
            spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point((int)wireWidth, (int)dist)), wireVertical.SourceRect,
                             wire.Item.Color * alpha,
                             MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
                             new Vector2(wireVertical.size.X / 2, 0), // point in line about which to rotate
                             SpriteEffects.None,
                             0.0f);

            float connectorScale = wireWidth / (float)wireVertical.SourceRect.Width;

            connector.Draw(spriteBatch, end, Color.White, connector.Origin, MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, scale: connectorScale);

            if (DraggingConnected == null && canDrag)
            {
                if (mouseOn)
                {
                    ConnectionPanel.HighlightedWire = wire;

                    bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring || panel.AlwaysAllowRewiring;
                    if (allowRewiring && (!wire.Locked && !panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
                    {
                        //start dragging the wire
                        if (PlayerInput.PrimaryMouseButtonHeld())
                        {
                            DraggingConnected = wire;
                        }
                    }
                }
            }
        }
예제 #5
0
 public void SetWire(int index, Wire wire)
 {
     wires[index]    = wire;
     recipientsDirty = true;
 }
예제 #6
0
        private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire, ConnectionPanel panel, string label)
        {
            if (draggingConnected == wire)
            {
                if (!mouseIn)
                {
                    return;
                }
                end     = PlayerInput.MousePosition;
                start.X = (start.X + end.X) / 2.0f;
            }

            int textX = (int)start.X;

            if (start.X < end.X)
            {
                textX -= 10;
            }
            else
            {
                textX += 10;
            }

            bool canDrag = equippedWire == null || equippedWire == wire;

            float alpha = canDrag ? 1.0f : 0.5f;

            bool mouseOn =
                canDrag &&
                ((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
                  PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
                  MathUtils.LineToPointDistance(start, end, PlayerInput.MousePosition) < 6) ||
                 Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
                 new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));

            if (!string.IsNullOrEmpty(label))
            {
                GUI.DrawString(spriteBatch,
                               new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
                               label,
                               (mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f,
                               3, GUI.SmallFont);
            }

            var wireEnd = end + Vector2.Normalize(start - end) * 30.0f;

            float dist = Vector2.Distance(start, wireEnd);

            if (mouseOn)
            {
                spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(18, (int)dist)), wireVertical.SourceRect,
                                 Color.Gold,
                                 MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, //angle of line (calulated above)
                                 new Vector2(6, 0),                                         // point in line about which to rotate
                                 SpriteEffects.None,
                                 0.0f);
            }
            spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(12, (int)dist)), wireVertical.SourceRect,
                             wire.Item.Color * alpha,
                             MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, //angle of line (calulated above)
                             new Vector2(6, 0),                                         // point in line about which to rotate
                             SpriteEffects.None,
                             0.0f);

            connector.Draw(spriteBatch, end, Color.White, new Vector2(10.0f, 10.0f), MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2);

            if (draggingConnected == null && canDrag)
            {
                if (mouseOn)
                {
                    ConnectionPanel.HighlightedWire = wire;

                    if (!wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
                    {
                        //start dragging the wire
                        if (PlayerInput.LeftButtonHeld())
                        {
                            draggingConnected = wire;
                        }
                    }
                }
            }
        }
예제 #7
0
        public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
        {
            int width = 400, height = 200;
            int x = GameMain.GraphicsWidth / 2 - width / 2, y = GameMain.GraphicsHeight - height;

            Rectangle panelRect = new Rectangle(x, y, width, height);

            spriteBatch.Draw(panelTexture, panelRect, new Rectangle(0, 512 - height, width, height), Color.White);

            //GUI.DrawRectangle(spriteBatch, panelRect, Color.Black, true);

            bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);

            int totalWireCount = 0;

            foreach (Connection c in panel.Connections)
            {
                totalWireCount += c.Wires.Count(w => w != null);
            }

            Wire equippedWire = null;

            //if the Character using the panel has a wire item equipped
            //and the wire hasn't been connected yet, draw it on the panel
            for (int i = 0; i < character.SelectedItems.Length; i++)
            {
                Item selectedItem = character.SelectedItems[i];

                if (selectedItem == null)
                {
                    continue;
                }

                Wire wireComponent = selectedItem.GetComponent <Wire>();
                if (wireComponent != null)
                {
                    equippedWire = wireComponent;
                }
            }

            Vector2 rightPos = new Vector2(x + width - 130, y + 50);
            Vector2 leftPos  = new Vector2(x + 130, y + 50);

            Vector2 rightWirePos = new Vector2(x + width - 5, y + 30);

            Vector2 leftWirePos = new Vector2(x + 5, y + 30);

            int wireInterval = (height - 20) / Math.Max(totalWireCount, 1);

            foreach (Connection c in panel.Connections)
            {
                //if dragging a wire, let the Inventory know so that the wire can be
                //dropped or dragged from the panel to the players inventory
                if (draggingConnected != null)
                {
                    int linkIndex = c.FindWireIndex(draggingConnected.Item);
                    if (linkIndex > -1)
                    {
                        Inventory.draggingItem = c.Wires[linkIndex].Item;
                    }
                }

                //outputs are drawn at the right side of the panel, inputs at the left
                if (c.IsOutput)
                {
                    c.Draw(spriteBatch, panel.Item, rightPos,
                           new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.Name).X - 20, rightPos.Y + 3),
                           rightWirePos,
                           mouseInRect, equippedWire,
                           wireInterval);

                    rightPos.Y     += 30;
                    rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                }
                else
                {
                    c.Draw(spriteBatch, panel.Item, leftPos,
                           new Vector2(leftPos.X + 20, leftPos.Y - 12),
                           leftWirePos,
                           mouseInRect, equippedWire,
                           wireInterval);

                    leftPos.Y     += 30;
                    leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                    //leftWireX -= wireInterval;
                }
            }

            if (draggingConnected != null)
            {
                DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, null);

                if (!PlayerInput.LeftButtonHeld())
                {
                    if (GameMain.Client != null)
                    {
                        panel.Item.CreateClientEvent <ConnectionPanel>(panel);
                    }
                    else if (GameMain.Server != null)
                    {
                        panel.Item.CreateServerEvent <ConnectionPanel>(panel);
                    }

                    draggingConnected = null;
                }
            }

            //if the Character using the panel has a wire item equipped
            //and the wire hasn't been connected yet, draw it on the panel
            if (equippedWire != null)
            {
                if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
                {
                    DrawWire(spriteBatch, equippedWire, equippedWire.Item,
                             new Vector2(x + width / 2, y + height - 100),
                             new Vector2(x + width / 2, y + height), mouseInRect, null);

                    if (draggingConnected == equippedWire)
                    {
                        Inventory.draggingItem = equippedWire.Item;
                    }
                }
            }

            //stop dragging a wire item if cursor is outside the panel
            if (mouseInRect)
            {
                Inventory.draggingItem = null;
            }


            spriteBatch.Draw(panelTexture, panelRect, new Rectangle(0, 0, width, height), Color.White);
        }
예제 #8
0
        public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
        {
            Rectangle panelRect = panel.GuiFrame.Rect;
            int       x = panelRect.X, y = panelRect.Y;
            int       width = panelRect.Width, height = panelRect.Height;

            bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);

            int totalWireCount = 0;

            foreach (Connection c in panel.Connections)
            {
                totalWireCount += c.Wires.Count(w => w != null);
            }

            Wire equippedWire = null;

            bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring;

            if (allowRewiring && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
            {
                //if the Character using the panel has a wire item equipped
                //and the wire hasn't been connected yet, draw it on the panel
                for (int i = 0; i < character.SelectedItems.Length; i++)
                {
                    Item selectedItem = character.SelectedItems[i];

                    if (selectedItem == null)
                    {
                        continue;
                    }

                    Wire wireComponent = selectedItem.GetComponent <Wire>();
                    if (wireComponent != null)
                    {
                        equippedWire = wireComponent;
                    }
                }
            }

            Vector2 rightPos = new Vector2(x + width - 110 * GUI.xScale, y + 80 * GUI.yScale);
            Vector2 leftPos  = new Vector2(x + 110 * GUI.xScale, y + 80 * GUI.yScale);

            Vector2 rightWirePos = new Vector2(x + width - 5 * GUI.xScale, y + 30 * GUI.yScale);
            Vector2 leftWirePos  = new Vector2(x + 5 * GUI.xScale, y + 30 * GUI.yScale);

            int wireInterval           = (height - (int)(20 * GUI.yScale)) / Math.Max(totalWireCount, 1);
            int connectorIntervalLeft  = (height - (int)(100 * GUI.yScale)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
            int connectorIntervalRight = (height - (int)(100 * GUI.yScale)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);

            foreach (Connection c in panel.Connections)
            {
                //if dragging a wire, let the Inventory know so that the wire can be
                //dropped or dragged from the panel to the players inventory
                if (draggingConnected != null)
                {
                    //the wire can only be dragged out if it's not connected to anything at the other end
                    if (Screen.Selected == GameMain.SubEditorScreen ||
                        (draggingConnected.Connections[0] == null && draggingConnected.Connections[1] == null) ||
                        (draggingConnected.Connections.Contains(c) && draggingConnected.Connections.Contains(null)))
                    {
                        int linkIndex = c.FindWireIndex(draggingConnected.Item);
                        if (linkIndex > -1 || panel.DisconnectedWires.Contains(draggingConnected))
                        {
                            Inventory.draggingItem = draggingConnected.Item;
                        }
                    }
                }

                //outputs are drawn at the right side of the panel, inputs at the left
                if (c.IsOutput)
                {
                    c.Draw(spriteBatch, panel, rightPos,
                           new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName).X - 20 * GUI.xScale, rightPos.Y + 3 * GUI.yScale),
                           rightWirePos,
                           mouseInRect, equippedWire,
                           wireInterval);

                    rightPos.Y     += connectorIntervalLeft;
                    rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                }
                else
                {
                    c.Draw(spriteBatch, panel, leftPos,
                           new Vector2(leftPos.X + 20 * GUI.xScale, leftPos.Y - 12 * GUI.yScale),
                           leftWirePos,
                           mouseInRect, equippedWire,
                           wireInterval);

                    leftPos.Y     += connectorIntervalRight;
                    leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                    //leftWireX -= wireInterval;
                }
            }

            if (draggingConnected != null)
            {
                if (mouseInRect)
                {
                    DrawWire(spriteBatch, draggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, "");
                }
                panel.TriggerRewiringSound();

                if (!PlayerInput.LeftButtonHeld())
                {
                    if (draggingConnected.Connections[0]?.ConnectionPanel == panel ||
                        draggingConnected.Connections[1]?.ConnectionPanel == panel)
                    {
                        draggingConnected.RemoveConnection(panel.Item);
                        panel.DisconnectedWires.Add(draggingConnected);
                    }

                    if (GameMain.Client != null)
                    {
                        panel.Item.CreateClientEvent(panel);
                    }

                    draggingConnected = null;
                }
            }

            //if the Character using the panel has a wire item equipped
            //and the wire hasn't been connected yet, draw it on the panel
            if (equippedWire != null && (draggingConnected != equippedWire || !mouseInRect))
            {
                if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
                {
                    DrawWire(spriteBatch, equippedWire, new Vector2(x + width / 2, y + height - 150 * GUI.Scale),
                             new Vector2(x + width / 2, y + height),
                             null, panel, "");

                    if (draggingConnected == equippedWire)
                    {
                        Inventory.draggingItem = equippedWire.Item;
                    }
                }
            }


            float step = (width * 0.75f) / panel.DisconnectedWires.Count();

            x = (int)(x + width / 2 - step * (panel.DisconnectedWires.Count() - 1) / 2);
            foreach (Wire wire in panel.DisconnectedWires)
            {
                if (wire == draggingConnected && mouseInRect)
                {
                    continue;
                }

                Connection recipient = wire.OtherConnection(null);
                string     label     = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
                if (wire.Locked)
                {
                    label += "\n" + TextManager.Get("ConnectionLocked");
                }
                DrawWire(spriteBatch, wire, new Vector2(x, y + height - 100 * GUI.Scale),
                         new Vector2(x, y + height),
                         null, panel, label);
                x += (int)step;
            }

            //stop dragging a wire item if the cursor is within any connection panel
            //(so we don't drop the item when dropping the wire on a connection)
            if (mouseInRect || GUI.MouseOn?.UserData is ConnectionPanel)
            {
                Inventory.draggingItem = null;
            }
        }
예제 #9
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            int[] wireCounts = new int[Connections.Count];
            Wire[,] wires = new Wire[Connections.Count, Connection.MaxLinked];

            //read wire IDs for each connection
            for (int i = 0; i < Connections.Count; i++)
            {
                wireCounts[i] = msg.ReadRangedInteger(0, Connection.MaxLinked);
                for (int j = 0; j < wireCounts[i]; j++)
                {
                    ushort wireId = msg.ReadUInt16();

                    Item wireItem = Entity.FindEntityByID(wireId) as Item;
                    if (wireItem == null)
                    {
                        continue;
                    }

                    Wire wireComponent = wireItem.GetComponent <Wire>();
                    if (wireComponent != null)
                    {
                        wires[i, j] = 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;
            }
            foreach (Wire wire in wires)
            {
                if (wire != null)
                {
                    //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;
                        }
                    }
                }
            }

            //update the connections
            for (int i = 0; i < Connections.Count; i++)
            {
                Wire[] prevWires = new Wire[Connections[i].Wires.Length];
                Array.Copy(Connections[i].Wires, prevWires, prevWires.Length);

                Connections[i].ClearConnections();

                for (int j = 0; j < wireCounts[i]; j++)
                {
                    if (wires[i, j] == null)
                    {
                        if (prevWires[j] != null)
                        {
                            if (prevWires[j].Connections[0] != null && prevWires[j].Connections[1] != null)
                            {
                                GameServer.Log(c.Character.Name + " disconnected a wire from " +
                                               prevWires[j].Connections[0].Item.Name + " (" + prevWires[j].Connections[0].Name + ") to " +
                                               prevWires[j].Connections[1].Item.Name + " (" + prevWires[j].Connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);
                            }
                            else if (prevWires[j].Connections[0] != null)
                            {
                                GameServer.Log(c.Character.Name + " disconnected a wire from " +
                                               prevWires[j].Connections[0].Item.Name + " (" + prevWires[j].Connections[0].Name + ")", ServerLog.MessageType.ItemInteraction);
                            }
                            else if (prevWires[j].Connections[1] != null)
                            {
                                GameServer.Log(c.Character.Name + " disconnected a wire from " +
                                               prevWires[j].Connections[1].Item.Name + " (" + prevWires[j].Connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);
                            }
                        }
                        continue;
                    }

                    //already connected, no need to do anything
                    if (wires[i, j] == prevWires[j])
                    {
                        continue;
                    }

                    Connections[i].Wires[j] = wires[i, j];
                    wires[i, j].Connect(Connections[i], true);

                    var otherConnection = Connections[i].Wires[j].OtherConnection(Connections[i]);

                    GameServer.Log(item.Name + " rewired by " + c.Character.Name + ": " +
                                   Connections[i].Name + " -> " +
                                   (otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"), ServerLog.MessageType.ItemInteraction);
                }
            }
        }
예제 #10
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            List <Wire>[] wires = new List <Wire> [Connections.Count];

            //read wire IDs for each connection
            for (int i = 0; i < Connections.Count; i++)
            {
                wires[i] = new List <Wire>();

                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 <Wire>();
                    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))
                    {
                        if (existingWire.Locked)
                        {
                            //this should not be possible unless the client is running a modified version of the game
                            GameServer.Log(c.Character.LogName + " attempted to disconnect a locked wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.Error);
                            continue;
                        }

                        existingWire.RemoveConnection(item);

                        if (existingWire.Connections[0] == null && existingWire.Connections[1] == null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.ItemInteraction);
                        }
                        else if (existingWire.Connections[0] != null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")", ServerLog.MessageType.ItemInteraction);

                            //wires that are not in anyone's inventory (i.e. not currently being rewired)
                            //can never be connected to only one connection
                            // -> the client must have dropped the wire from the connection panel
                            if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                            {
                                //let other clients know the item was also disconnected from the other connection
                                existingWire.Connections[0].Item.CreateServerEvent(existingWire.Connections[0].Item.GetComponent <ConnectionPanel>());
                                existingWire.Item.Drop(c.Character);
                            }
                        }
                        else if (existingWire.Connections[1] != null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);

                            if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                            {
                                //let other clients know the item was also disconnected from the other connection
                                existingWire.Connections[1].Item.CreateServerEvent(existingWire.Connections[1].Item.GetComponent <ConnectionPanel>());
                                existingWire.Item.Drop(c.Character);
                            }
                        }

                        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.LogName + " connected a wire to " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ")",
                                       ServerLog.MessageType.ItemInteraction);
                    }
                    else
                    {
                        GameServer.Log(c.Character.LogName + " connected a wire from " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ") to " +
                                       (otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"),
                                       ServerLog.MessageType.ItemInteraction);
                    }
                }
            }
        }
예제 #11
0
        private void Draw(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
        {
            GUI.DrawString(spriteBatch, labelPos, DisplayName, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);

            connectionSprite.Draw(spriteBatch, position);

            for (int i = 0; i < MaxLinked; i++)
            {
                if (wires[i] == null || wires[i].Hidden || (draggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen)))
                {
                    continue;
                }

                Connection recipient = wires[i].OtherConnection(this);
                string     label     = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
                if (wires[i].Locked)
                {
                    label += "\n" + TextManager.Get("ConnectionLocked");
                }
                DrawWire(spriteBatch, wires[i], position, wirePosition, equippedWire, panel, label);

                wirePosition.Y += wireInterval;
            }

            if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < (20.0f * GUI.Scale))
            {
                connectionSpriteHighlight.Draw(spriteBatch, position);

                if (!PlayerInput.LeftButtonHeld())
                {
                    //find an empty cell for the new connection
                    int index = FindEmptyIndex();
                    if (index > -1 && !Wires.Contains(draggingConnected))
                    {
                        bool alreadyConnected = draggingConnected.IsConnectedTo(panel.Item);
                        draggingConnected.RemoveConnection(panel.Item);
                        if (draggingConnected.Connect(this, !alreadyConnected, true))
                        {
                            var otherConnection = draggingConnected.OtherConnection(this);
                            SetWire(index, draggingConnected);
                        }
                    }
                    if (GameMain.Client != null)
                    {
                        panel.Item.CreateClientEvent(panel);
                    }
                    draggingConnected = null;
                }
            }

            if (flashTimer > 0.0f)
            {
                //the number of flashes depends on the duration, 1 flash per 1 full second
                int   flashCycleCount    = (int)Math.Max(flashDuration, 1);
                float flashCycleDuration = flashDuration / flashCycleCount;

                //MathHelper.Pi * 0.8f -> the curve goes from 144 deg to 0,
                //i.e. quickly bumps up from almost full brightness to full and then fades out
                connectionSpriteHighlight.Draw(spriteBatch, position, flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f));
            }

            if (Wires.Any(w => w != null && w != draggingConnected))
            {
                int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
                screwSprites[screwIndex].Draw(spriteBatch, position);
            }
        }
예제 #12
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            List <Wire>[] wires = new List <Wire> [Connections.Count];

            //read wire IDs for each connection
            for (int i = 0; i < Connections.Count; i++)
            {
                wires[i] = new List <Wire>();

                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 <Wire>();
                    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);
                    }
                }
            }
        }
예제 #13
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            List <Wire>[] wires = new List <Wire> [Connections.Count];

            //read wire IDs for each connection
            for (int i = 0; i < Connections.Count; i++)
            {
                wires[i] = new List <Wire>();

                for (int j = 0; j < Connection.MaxLinked; j++)
                {
                    ushort wireId = msg.ReadUInt16();

                    Item wireItem = Entity.FindEntityByID(wireId) as Item;
                    if (wireItem == null)
                    {
                        continue;
                    }

                    Wire wireComponent = wireItem.GetComponent <Wire>();
                    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;
                    }
                    //NilMod Deny changes to locked wiring
                    //if (existingWire.Locked == true) continue;

                    //existing wire not in the list of new wires -> disconnect it
                    if (!wires[i].Contains(existingWire))
                    {
                        if (existingWire.Locked || c.Character?.SpawnRewireWaitTimer > 0)
                        {
                            if (!GameMain.NilMod.CanRewireMainSubs && c.Character?.SpawnRewireWaitTimer <= 0f)
                            {
                                //this should not be possible unless the client is running a modified version of the game
                                GameServer.Log(c.Character.LogName + " attempted to disconnect a locked wire from " +
                                               Connections[i].Item.Name + " (" + Connections[i].Name + ") - Could be a modified client.", ServerLog.MessageType.Rewire);
                            }
                            else if (c.Character?.SpawnRewireWaitTimer > 0f)
                            {
                                //this is simply the rewire protection from CanRewireMainSubs
                                GameServer.Log(c.Character.LogName + " attempted to disconnect a locked wire from " +
                                               Connections[i].Item.Name + " (" + Connections[i].Name + ") - but SpawnRewireWaitTimer Prevented it.", ServerLog.MessageType.Rewire);
                            }
                            else
                            {
                                //this is simply the rewire protection from CanRewireMainSubs
                                GameServer.Log(c.Character.LogName + " attempted to disconnect a locked wire from " +
                                               Connections[i].Item.Name + " (" + Connections[i].Name + ") - but CanRewireMainSubs Prevented it.", ServerLog.MessageType.Rewire);
                            }
                            continue;
                        }

                        existingWire.RemoveConnection(item);

                        if (existingWire.Connections[0] == null && existingWire.Connections[1] == null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.Rewire);
                        }
                        else if (existingWire.Connections[0] != null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")", ServerLog.MessageType.Rewire);

                            if (GameMain.NilMod.EnableGriefWatcher)
                            {
                                for (int z = 0; z < NilMod.NilModGriefWatcher.GWListWireKeyDevices.Count; z++)
                                {
                                    if (NilMod.NilModGriefWatcher.GWListWireKeyDevices[z] == Connections[i].Item.Name || NilMod.NilModGriefWatcher.GWListWireKeyDevices[z] == existingWire.Connections[0].Item.Name)
                                    {
                                        NilMod.NilModGriefWatcher.SendWarning(c.Character.LogName + " Modified a wire from "
                                                                              + Connections[i].Item.Name + " (" + Connections[i].Name
                                                                              + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")" + ".", c);
                                    }
                                }

                                if (NilMod.NilModGriefWatcher.GWListWireJunctions.Contains(Connections[i].Item.Name) && NilMod.NilModGriefWatcher.GWListWireJunctions.Contains(existingWire.Connections[0].Item.Name))
                                {
                                    NilMod.NilModGriefWatcher.SendWarning(c.Character.LogName + " Modified a wire from "
                                                                          + Connections[i].Item.Name + " (" + Connections[i].Name
                                                                          + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")" + ".", c);
                                }
                            }

                            //wires that are not in anyone's inventory (i.e. not currently being rewired)
                            //can never be connected to only one connection
                            // -> the client must have dropped the wire from the connection panel
                            if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                            {
                                //let other clients know the item was also disconnected from the other connection
                                existingWire.Connections[0].Item.CreateServerEvent(existingWire.Connections[0].Item.GetComponent <ConnectionPanel>());
                                existingWire.Item.Drop(c.Character);
                            }
                        }
                        else if (existingWire.Connections[1] != null)
                        {
                            GameServer.Log(c.Character.LogName + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")", ServerLog.MessageType.Rewire);

                            if (GameMain.NilMod.EnableGriefWatcher)
                            {
                                for (int z = 0; z < NilMod.NilModGriefWatcher.GWListWireKeyDevices.Count - 1; z++)
                                {
                                    if (NilMod.NilModGriefWatcher.GWListWireKeyDevices[z] == Connections[i].Item.Name || NilMod.NilModGriefWatcher.GWListWireKeyDevices[z] == existingWire.Connections[1].Item.Name)
                                    {
                                        NilMod.NilModGriefWatcher.SendWarning(c.Character.LogName + " Modified a wire from "
                                                                              + Connections[i].Item.Name + " (" + Connections[i].Name
                                                                              + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")" + ".", c);
                                    }
                                }

                                if (NilMod.NilModGriefWatcher.GWListWireJunctions.Contains(Connections[i].Item.Name) && NilMod.NilModGriefWatcher.GWListWireJunctions.Contains(existingWire.Connections[1].Item.Name))
                                {
                                    NilMod.NilModGriefWatcher.SendWarning(c.Character.LogName + " Modified a wire from "
                                                                          + Connections[i].Item.Name + " (" + Connections[i].Name
                                                                          + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")" + ".", c);
                                }
                            }

                            if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                            {
                                //let other clients know the item was also disconnected from the other connection
                                existingWire.Connections[1].Item.CreateServerEvent(existingWire.Connections[1].Item.GetComponent <ConnectionPanel>());
                                existingWire.Item.Drop(c.Character);
                            }
                        }

                        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;
                    }
                    //NilMod Deny changes to locked wiring
                    if (newWire.Locked || c.Character?.SpawnRewireWaitTimer > 0f)
                    {
                        continue;
                    }

                    Connections[i].TryAddLink(newWire);
                    newWire.Connect(Connections[i], true, true);

                    var otherConnection = newWire.OtherConnection(Connections[i]);

                    if (otherConnection == null)
                    {
                        GameServer.Log(c.Character.LogName + " connected a wire to " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ")",
                                       ServerLog.MessageType.Rewire);
                    }
                    else
                    {
                        GameServer.Log(c.Character.LogName + " connected a wire from " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ") to " +
                                       (otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"),
                                       ServerLog.MessageType.Rewire);
                    }
                }
            }
        }
예제 #14
0
        private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
        {
            //spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White);
            GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);

            GUI.DrawRectangle(spriteBatch, new Rectangle((int)position.X - 10, (int)position.Y - 10, 20, 20), Color.White);
            spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(64, 256, 32, 32), Color.White);

            for (int i = 0; i < MaxLinked; i++)
            {
                if (Wires[i] == null || Wires[i].Hidden || draggingConnected == Wires[i])
                {
                    continue;
                }

                Connection recipient = Wires[i].OtherConnection(this);

                DrawWire(spriteBatch, Wires[i], (recipient == null) ? Wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire);

                wirePosition.Y += wireInterval;
            }

            if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < 13.0f)
            {
                spriteBatch.Draw(panelTexture, position - new Vector2(21.5f, 21.5f), new Rectangle(106, 250, 43, 43), Color.White);

                if (!PlayerInput.LeftButtonHeld())
                {
                    //find an empty cell for the new connection
                    int index = FindWireIndex(null);

                    if (index > -1 && !Wires.Contains(draggingConnected))
                    {
                        bool alreadyConnected = draggingConnected.IsConnectedTo(item);

                        draggingConnected.RemoveConnection(item);

                        if (draggingConnected.Connect(this, !alreadyConnected, true))
                        {
                            var otherConnection = draggingConnected.OtherConnection(this);
                            if (otherConnection == null)
                            {
                                GameServer.Log(Character.Controlled + " connected a wire to " +
                                               Item.Name + " (" + Name + ")", ServerLog.MessageType.ItemInteraction);
                            }
                            else
                            {
                                GameServer.Log(Character.Controlled + " connected a wire from " +
                                               Item.Name + " (" + Name + ") to " + otherConnection.item.Name + " (" + otherConnection.Name + ")", ServerLog.MessageType.ItemInteraction);
                            }

                            Wires[index] = draggingConnected;
                        }
                    }
                }
            }

            int screwIndex = (position.Y % 60 < 30) ? 0 : 1;

            if (Wires.Any(w => w != null && w != draggingConnected))
            {
                spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(screwIndex * 32, 256, 32, 32), Color.White);
            }
        }
예제 #15
0
        private void Draw(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
        {
            //spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White);
            GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);

            connectionSprite.Draw(spriteBatch, position);

            for (int i = 0; i < MaxLinked; i++)
            {
                if (wires[i] == null || wires[i].Hidden || draggingConnected == wires[i])
                {
                    continue;
                }

                Connection recipient = wires[i].OtherConnection(this);

                string label = recipient == null ? "" :
                               wires[i].Locked ? recipient.item.Name + "\n" + TextManager.Get("ConnectionLocked") : recipient.item.Name;
                DrawWire(spriteBatch, wires[i], (recipient == null) ? wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire, panel, label);

                wirePosition.Y += wireInterval;
            }

            if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < 13.0f)
            {
                connectionSpriteHighlight.Draw(spriteBatch, position);

                if (!PlayerInput.LeftButtonHeld())
                {
                    //find an empty cell for the new connection
                    int index = FindEmptyIndex();
                    if (index > -1 && !Wires.Contains(draggingConnected))
                    {
                        bool alreadyConnected = draggingConnected.IsConnectedTo(panel.Item);

                        draggingConnected.RemoveConnection(panel.Item);

                        if (draggingConnected.Connect(this, !alreadyConnected, true))
                        {
                            var otherConnection = draggingConnected.OtherConnection(this);
#if SERVER
                            //TODO: ffs
                            if (otherConnection == null)
                            {
                                GameServer.Log(Character.Controlled.LogName + " connected a wire to " +
                                               Item.Name + " (" + Name + ")", ServerLog.MessageType.ItemInteraction);
                            }
                            else
                            {
                                GameServer.Log(Character.Controlled.LogName + " connected a wire from " +
                                               Item.Name + " (" + Name + ") to " + otherConnection.item.Name + " (" + otherConnection.Name + ")", ServerLog.MessageType.ItemInteraction);
                            }
#endif

                            SetWire(index, draggingConnected);
                        }
                    }
                }
            }

            if (Wires.Any(w => w != null && w != draggingConnected))
            {
                int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
                screwSprites[screwIndex].Draw(spriteBatch, position);
            }
        }
        private void DrawWires(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
        {
            float connectorSpriteScale = (35.0f / connectionSprite.SourceRect.Width) * panel.Scale;

            for (int i = 0; i < MaxWires; i++)
            {
                if (wires[i] == null || wires[i].Hidden || (DraggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen)))
                {
                    continue;
                }
                if (wires[i].HiddenInGame && Screen.Selected == GameMain.GameScreen)
                {
                    continue;
                }

                Connection recipient = wires[i].OtherConnection(this);
                string     label     = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
                if (wires[i].Locked)
                {
                    label += "\n" + TextManager.Get("ConnectionLocked");
                }
                DrawWire(spriteBatch, wires[i], position, wirePosition, equippedWire, panel, label);

                wirePosition.Y += wireInterval;
            }

            if (DraggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < (20.0f * GUI.Scale))
            {
                connectionSpriteHighlight.Draw(spriteBatch, position, scale: connectorSpriteScale);

                if (!PlayerInput.PrimaryMouseButtonHeld())
                {
                    if (GameMain.NetworkMember != null || panel.CheckCharacterSuccess(Character.Controlled))
                    {
                        //find an empty cell for the new connection
                        int index = FindEmptyIndex();
                        if (index > -1 && !Wires.Contains(DraggingConnected))
                        {
                            bool alreadyConnected = DraggingConnected.IsConnectedTo(panel.Item);
                            DraggingConnected.RemoveConnection(panel.Item);
                            if (DraggingConnected.Connect(this, !alreadyConnected, true))
                            {
                                var otherConnection = DraggingConnected.OtherConnection(this);
                                SetWire(index, DraggingConnected);
                            }
                        }
                    }

                    if (GameMain.Client != null)
                    {
                        panel.Item.CreateClientEvent(panel);
                    }
                    DraggingConnected = null;
                }
            }

            if (FlashTimer > 0.0f)
            {
                //the number of flashes depends on the duration, 1 flash per 1 full second
                int   flashCycleCount    = (int)Math.Max(flashDuration, 1);
                float flashCycleDuration = flashDuration / flashCycleCount;

                //MathHelper.Pi * 0.8f -> the curve goes from 144 deg to 0,
                //i.e. quickly bumps up from almost full brightness to full and then fades out
                connectionSpriteHighlight.Draw(spriteBatch, position,
                                               flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
            }

            if (Wires.Any(w => w != null && w != DraggingConnected && !w.Hidden && (!w.HiddenInGame || Screen.Selected != GameMain.GameScreen)))
            {
                int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
                screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
            }
        }
예제 #17
0
        public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
        {
            Rectangle panelRect = panel.GuiFrame.Rect;
            int       x = panelRect.X, y = panelRect.Y;
            int       width = panelRect.Width, height = panelRect.Height;

            bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);

            int totalWireCount = 0;

            foreach (Connection c in panel.Connections)
            {
                totalWireCount += c.Wires.Count(w => w != null);
            }

            Wire equippedWire = null;

            if (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen)
            {
                //if the Character using the panel has a wire item equipped
                //and the wire hasn't been connected yet, draw it on the panel
                for (int i = 0; i < character.SelectedItems.Length; i++)
                {
                    Item selectedItem = character.SelectedItems[i];

                    if (selectedItem == null)
                    {
                        continue;
                    }

                    Wire wireComponent = selectedItem.GetComponent <Wire>();
                    if (wireComponent != null)
                    {
                        equippedWire = wireComponent;
                    }
                }
            }

            Vector2 rightPos = new Vector2(x + width - 130, y + 80);
            Vector2 leftPos  = new Vector2(x + 130, y + 80);

            Vector2 rightWirePos = new Vector2(x + width - 5, y + 30);
            Vector2 leftWirePos  = new Vector2(x + 5, y + 30);

            int wireInterval           = (height - 20) / Math.Max(totalWireCount, 1);
            int connectorIntervalLeft  = (height - 100) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
            int connectorIntervalRight = (height - 100) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);

            foreach (Connection c in panel.Connections)
            {
                //if dragging a wire, let the Inventory know so that the wire can be
                //dropped or dragged from the panel to the players inventory
                if (draggingConnected != null)
                {
                    int linkIndex = c.FindWireIndex(draggingConnected.Item);
                    if (linkIndex > -1)
                    {
                        Inventory.draggingItem = c.wires[linkIndex].Item;
                    }
                }

                //outputs are drawn at the right side of the panel, inputs at the left
                if (c.IsOutput)
                {
                    c.Draw(spriteBatch, panel, rightPos,
                           new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.Name).X - 20, rightPos.Y + 3),
                           rightWirePos,
                           mouseInRect, equippedWire,
                           wireInterval);

                    rightPos.Y     += connectorIntervalLeft;
                    rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                }
                else
                {
                    c.Draw(spriteBatch, panel, leftPos,
                           new Vector2(leftPos.X + 20, leftPos.Y - 12),
                           leftWirePos,
                           mouseInRect, equippedWire,
                           wireInterval);

                    leftPos.Y     += connectorIntervalRight;
                    leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                    //leftWireX -= wireInterval;
                }
            }

            if (draggingConnected != null)
            {
                DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), mouseInRect, null, panel, "");

                if (!PlayerInput.LeftButtonHeld())
                {
                    if (GameMain.Client != null)
                    {
                        panel.Item.CreateClientEvent(panel);
                    }

                    draggingConnected = null;
                }
            }

            //if the Character using the panel has a wire item equipped
            //and the wire hasn't been connected yet, draw it on the panel
            if (equippedWire != null)
            {
                if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
                {
                    DrawWire(spriteBatch, equippedWire, equippedWire.Item,
                             new Vector2(x + width / 2, y + height - 100),
                             new Vector2(x + width / 2, y + height), mouseInRect, null, panel, "");

                    if (draggingConnected == equippedWire)
                    {
                        Inventory.draggingItem = equippedWire.Item;
                    }
                }
            }

            //stop dragging a wire item if the cursor is within any connection panel
            //(so we don't drop the item when dropping the wire on a connection)
            if (mouseInRect || GUI.MouseOn?.UserData is ConnectionPanel)
            {
                Inventory.draggingItem = null;
            }
        }
        public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
        {
            Rectangle panelRect = panel.GuiFrame.Rect;
            int       x = panelRect.X, y = panelRect.Y;
            int       width = panelRect.Width, height = panelRect.Height;

            Vector2 scale = new Vector2(GUI.Scale);

            if (panel.GuiFrame.RectTransform.MaxSize.X < int.MaxValue)
            {
                scale.X = panel.GuiFrame.RectTransform.MaxSize.X / panel.GuiFrame.Rect.Width;
            }
            if (panel.GuiFrame.RectTransform.MaxSize.Y < int.MaxValue)
            {
                scale.Y = panel.GuiFrame.RectTransform.MaxSize.Y / panel.GuiFrame.Rect.Height;
            }

            bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);

            int totalWireCount = 0;

            foreach (Connection c in panel.Connections)
            {
                totalWireCount += c.Wires.Count(w => w != null);
            }

            Wire equippedWire = null;

            bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring || panel.AlwaysAllowRewiring;

            if (allowRewiring && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
            {
                //if the Character using the panel has a wire item equipped
                //and the wire hasn't been connected yet, draw it on the panel
                foreach (Item item in character.HeldItems)
                {
                    Wire wireComponent = item.GetComponent <Wire>();
                    if (wireComponent != null)
                    {
                        equippedWire = wireComponent;
                    }
                }
            }

            //two passes: first the connector, then the wires to get the wires to render in front
            for (int i = 0; i < 2; i++)
            {
                Vector2 rightPos = new Vector2(x + width - 80 * scale.X, y + 60 * scale.Y);
                Vector2 leftPos  = new Vector2(x + 80 * scale.X, y + 60 * scale.Y);

                Vector2 rightWirePos = new Vector2(x + width - 5 * scale.X, y + 30 * scale.Y);
                Vector2 leftWirePos  = new Vector2(x + 5 * scale.X, y + 30 * scale.Y);

                int wireInterval           = (height - (int)(20 * scale.Y)) / Math.Max(totalWireCount, 1);
                int connectorIntervalLeft  = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
                int connectorIntervalRight = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);

                foreach (Connection c in panel.Connections)
                {
                    //if dragging a wire, let the Inventory know so that the wire can be
                    //dropped or dragged from the panel to the players inventory
                    if (DraggingConnected != null && i == 1)
                    {
                        //the wire can only be dragged out if it's not connected to anything at the other end
                        if (Screen.Selected == GameMain.SubEditorScreen ||
                            (DraggingConnected.Connections[0] == null && DraggingConnected.Connections[1] == null) ||
                            (DraggingConnected.Connections.Contains(c) && DraggingConnected.Connections.Contains(null)))
                        {
                            int linkIndex = c.FindWireIndex(DraggingConnected.Item);
                            if (linkIndex > -1 || panel.DisconnectedWires.Contains(DraggingConnected))
                            {
                                Inventory.DraggingItems.Clear();
                                Inventory.DraggingItems.Add(DraggingConnected.Item);
                            }
                        }
                    }

                    //outputs are drawn at the right side of the panel, inputs at the left
                    if (c.IsOutput)
                    {
                        if (i == 0)
                        {
                            c.DrawConnection(spriteBatch, panel, rightPos,
                                             new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).X - 25 * panel.Scale, rightPos.Y + 5 * panel.Scale),
                                             scale);
                        }
                        else
                        {
                            c.DrawWires(spriteBatch, panel, rightPos, rightWirePos, mouseInRect, equippedWire, wireInterval);
                        }

                        rightPos.Y     += connectorIntervalLeft;
                        rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                    }
                    else
                    {
                        if (i == 0)
                        {
                            c.DrawConnection(spriteBatch, panel, leftPos,
                                             new Vector2(leftPos.X + 25 * panel.Scale, leftPos.Y - 5 * panel.Scale - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).Y),
                                             scale);
                        }
                        else
                        {
                            c.DrawWires(spriteBatch, panel, leftPos, leftWirePos, mouseInRect, equippedWire, wireInterval);
                        }

                        leftPos.Y     += connectorIntervalRight;
                        leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
                    }
                }
            }


            if (DraggingConnected != null)
            {
                if (mouseInRect)
                {
                    DrawWire(spriteBatch, DraggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, "");
                }
                panel.TriggerRewiringSound();

                if (!PlayerInput.PrimaryMouseButtonHeld())
                {
                    if (GameMain.NetworkMember != null || panel.CheckCharacterSuccess(character))
                    {
                        if (DraggingConnected.Connections[0]?.ConnectionPanel == panel ||
                            DraggingConnected.Connections[1]?.ConnectionPanel == panel)
                        {
                            DraggingConnected.RemoveConnection(panel.Item);
                            if (DraggingConnected.Item.ParentInventory == null)
                            {
                                panel.DisconnectedWires.Add(DraggingConnected);
                            }
                            else if (DraggingConnected.Connections[0] == null && DraggingConnected.Connections[1] == null)
                            {
                                DraggingConnected.ClearConnections(user: Character.Controlled);
                            }
                        }
                    }

                    if (GameMain.Client != null)
                    {
                        panel.Item.CreateClientEvent(panel);
                    }

                    DraggingConnected = null;
                }
            }

            //if the Character using the panel has a wire item equipped
            //and the wire hasn't been connected yet, draw it on the panel
            if (equippedWire != null && (DraggingConnected != equippedWire || !mouseInRect))
            {
                if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
                {
                    DrawWire(spriteBatch, equippedWire, new Vector2(x + width / 2, y + height - 150 * GUI.Scale),
                             new Vector2(x + width / 2, y + height),
                             null, panel, "");

                    if (DraggingConnected == equippedWire)
                    {
                        Inventory.DraggingItems.Clear();
                        Inventory.DraggingItems.Add(equippedWire.Item);
                    }
                }
            }


            float step = (width * 0.75f) / panel.DisconnectedWires.Count();

            x = (int)(x + width / 2 - step * (panel.DisconnectedWires.Count() - 1) / 2);
            foreach (Wire wire in panel.DisconnectedWires)
            {
                if (wire == DraggingConnected && mouseInRect)
                {
                    continue;
                }
                if (wire.HiddenInGame && Screen.Selected == GameMain.GameScreen)
                {
                    continue;
                }

                Connection recipient = wire.OtherConnection(null);
                string     label     = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
                if (wire.Locked)
                {
                    label += "\n" + TextManager.Get("ConnectionLocked");
                }
                DrawWire(spriteBatch, wire, new Vector2(x, y + height - 100 * GUI.Scale),
                         new Vector2(x, y + height),
                         null, panel, label);
                x += (int)step;
            }

            //stop dragging a wire item if the cursor is within any connection panel
            //(so we don't drop the item when dropping the wire on a connection)
            if (mouseInRect || (GUI.MouseOn?.UserData is ConnectionPanel && GUI.MouseOn.MouseRect.Contains(PlayerInput.MousePosition)))
            {
                Inventory.DraggingItems.Clear();
            }
        }
 public void AddLink(int index, Wire wire)
 {
     Wires[index] = wire;
 }
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            List <Wire>[] wires = new List <Wire> [Connections.Count];

            //read wire IDs for each connection
            for (int i = 0; i < Connections.Count; i++)
            {
                wires[i] = new List <Wire>();
                for (int j = 0; j < Connections[i].MaxWires; j++)
                {
                    ushort wireId = msg.ReadUInt16();

                    if (!(Entity.FindEntityByID(wireId) is Item wireItem))
                    {
                        continue;
                    }

                    Wire wireComponent = wireItem.GetComponent <Wire>();
                    if (wireComponent != null)
                    {
                        wires[i].Add(wireComponent);
                    }
                }
            }

            List <Wire> clientSideDisconnectedWires = new List <Wire>();
            ushort      disconnectedWireCount       = msg.ReadUInt16();

            for (int i = 0; i < disconnectedWireCount; i++)
            {
                ushort wireId = msg.ReadUInt16();
                if (!(Entity.FindEntityByID(wireId) is Item wireItem))
                {
                    continue;
                }
                Wire wireComponent = wireItem.GetComponent <Wire>();
                if (wireComponent == null)
                {
                    continue;
                }
                clientSideDisconnectedWires.Add(wireComponent);
            }

            //don't allow rewiring locked panels
            if (Locked || !GameMain.NetworkMember.ServerSettings.AllowRewiring)
            {
                return;
            }

            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)) && !DisconnectedWires.Contains(wire))
                    {
                        if (!wire.Item.CanClientAccess(c))
                        {
                            return;
                        }
                    }
                }
            }

            if (!CheckCharacterSuccess(c.Character))
            {
                item.CreateServerEvent(this);
                c.Character.Inventory?.CreateNetworkEvent();
                foreach (Item heldItem in c.Character.HeldItems)
                {
                    var selectedWire = heldItem?.GetComponent <Wire>();
                    if (selectedWire == null)
                    {
                        continue;
                    }

                    selectedWire.CreateNetworkEvent();
                    var panel1 = selectedWire.Connections[0]?.ConnectionPanel;
                    if (panel1 != null && panel1 != this)
                    {
                        panel1.item.CreateServerEvent(panel1);
                    }
                    var panel2 = selectedWire.Connections[1]?.ConnectionPanel;
                    if (panel2 != null && panel2 != this)
                    {
                        panel2.item.CreateServerEvent(panel2);
                    }

                    CoroutineManager.InvokeAfter(() =>
                    {
                        item.CreateServerEvent(this);
                        if (panel1 != null && panel1 != this)
                        {
                            panel1.item.CreateServerEvent(panel1);
                        }
                        if (panel2 != null && panel2 != this)
                        {
                            panel2.item.CreateServerEvent(panel2);
                        }
                        if (!selectedWire.Item.Removed)
                        {
                            selectedWire.CreateNetworkEvent();
                        }
                    }, 1.0f);
                }
                GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFailure, this, c.Character.ID });
                return;
            }

            //go through existing wire links
            for (int i = 0; i < Connections.Count; i++)
            {
                int j = -1;
                foreach (Wire existingWire in Connections[i].Wires)
                {
                    j++;
                    if (existingWire == null)
                    {
                        continue;
                    }

                    //existing wire not in the list of new wires -> disconnect it
                    if (!wires[i].Contains(existingWire))
                    {
                        if (existingWire.Locked)
                        {
                            //this should not be possible unless the client is running a modified version of the game
                            GameServer.Log(GameServer.CharacterLogName(c.Character) + " attempted to disconnect a locked wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.Error);
                            continue;
                        }

                        existingWire.RemoveConnection(item);
                        if (existingWire.Item.ParentInventory == null)
                        {
                            item.GetComponent <ConnectionPanel>()?.DisconnectedWires.Add(existingWire);
                        }

                        if (!wires.Any(w => w.Contains(existingWire)))
                        {
                            GameMain.Server.KarmaManager.OnWireDisconnected(c.Character, existingWire);
                        }

                        if (existingWire.Connections[0] == null && existingWire.Connections[1] == null)
                        {
                            GameServer.Log(GameServer.CharacterLogName(c.Character) + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.Wiring);

                            if (existingWire.Item.ParentInventory != null)
                            {
                                //in an inventory and not connected to anything -> the wire cannot have any nodes
                                existingWire.ClearConnections();
                            }
                            else if (!clientSideDisconnectedWires.Contains(existingWire))
                            {
                                //not in an inventory, not connected to anything, not hanging loose from any panel -> must be dropped
                                existingWire.Item.Drop(c.Character);
                            }
                        }
                        else if (existingWire.Connections[0] != null)
                        {
                            GameServer.Log(GameServer.CharacterLogName(c.Character) + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")", ServerLog.MessageType.Wiring);

                            //wires that are not in anyone's inventory (i.e. not currently being rewired)
                            //can never be connected to only one connection
                            // -> the client must have dropped the wire from the connection panel

                            /*if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                             * {
                             *  //let other clients know the item was also disconnected from the other connection
                             *  existingWire.Connections[0].Item.CreateServerEvent(existingWire.Connections[0].Item.GetComponent<ConnectionPanel>());
                             *  existingWire.Item.Drop(c.Character);
                             * }*/
                        }
                        else if (existingWire.Connections[1] != null)
                        {
                            GameServer.Log(GameServer.CharacterLogName(c.Character) + " disconnected a wire from " +
                                           Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")", ServerLog.MessageType.Wiring);

                            /*if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
                             * {
                             *  //let other clients know the item was also disconnected from the other connection
                             *  existingWire.Connections[1].Item.CreateServerEvent(existingWire.Connections[1].Item.GetComponent<ConnectionPanel>());
                             *  existingWire.Item.Drop(c.Character);
                             * }*/
                        }

                        Connections[i].SetWire(j, null);
                    }
                }
            }

            foreach (Wire disconnectedWire in DisconnectedWires.ToList())
            {
                if (disconnectedWire.Connections[0] == null &&
                    disconnectedWire.Connections[1] == null &&
                    !clientSideDisconnectedWires.Contains(disconnectedWire) &&
                    disconnectedWire.Item.ParentInventory == null)
                {
                    disconnectedWire.Item.Drop(c.Character);
                    GameServer.Log(GameServer.CharacterLogName(c.Character) + " dropped " + disconnectedWire.Name, ServerLog.MessageType.Inventory);
                }
            }

            //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(GameServer.CharacterLogName(c.Character) + " connected a wire to " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ")",
                                       ServerLog.MessageType.Wiring);
                    }
                    else
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " connected a wire from " +
                                       Connections[i].Item.Name + " (" + Connections[i].Name + ") to " +
                                       (otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"),
                                       ServerLog.MessageType.Wiring);
                    }
                }
            }
        }