Exemplo n.º 1
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            NetEntityEvent.Type eventType =
                (NetEntityEvent.Type)msg.ReadRangedInteger(0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);

            c.KickAFKTimer = 0.0f;

            switch (eventType)
            {
            case NetEntityEvent.Type.ComponentState:
                int componentIndex = msg.ReadRangedInteger(0, components.Count - 1);
                (components[componentIndex] as IClientSerializable).ServerRead(type, msg, c);
                break;

            case NetEntityEvent.Type.InventoryState:
                int containerIndex = msg.ReadRangedInteger(0, components.Count - 1);
                (components[containerIndex] as ItemContainer).Inventory.ServerRead(type, msg, c);
                break;

            case NetEntityEvent.Type.Treatment:
                if (c.Character == null || !c.Character.CanInteractWith(this))
                {
                    return;
                }

                UInt16 characterID = msg.ReadUInt16();
                byte   limbIndex   = msg.ReadByte();

                Character targetCharacter = FindEntityByID(characterID) as Character;
                if (targetCharacter == null)
                {
                    break;
                }
                if (targetCharacter != c.Character && c.Character.SelectedCharacter != targetCharacter)
                {
                    break;
                }

                Limb targetLimb = limbIndex < targetCharacter.AnimController.Limbs.Length ? targetCharacter.AnimController.Limbs[limbIndex] : null;

                if (ContainedItems == null || ContainedItems.All(i => i == null))
                {
                    GameServer.Log(c.Character.LogName + " used item " + Name, ServerLog.MessageType.ItemInteraction);
                }
                else
                {
                    GameServer.Log(
                        c.Character.LogName + " used item " + Name + " (contained items: " + string.Join(", ", ContainedItems.Select(i => i.Name)) + ")",
                        ServerLog.MessageType.ItemInteraction);
                }

                ApplyTreatment(c.Character, targetCharacter, targetLimb);

                break;

            case NetEntityEvent.Type.ChangeProperty:
                ReadPropertyChange(msg, true, c);
                break;
            }
        }
Exemplo n.º 2
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            int itemIndex = msg.ReadRangedInteger(-1, fabricableItems.Count - 1);

            item.CreateServerEvent(this);

            if (!item.CanClientAccess(c))
            {
                return;
            }

            if (itemIndex == -1)
            {
                CancelFabricating(c.Character);
            }
            else
            {
                //if already fabricating the selected item, return
                if (fabricatedItem != null && fabricableItems.IndexOf(fabricatedItem) == itemIndex)
                {
                    return;
                }
                if (itemIndex < 0 || itemIndex >= fabricableItems.Count)
                {
                    return;
                }

                StartFabricating(fabricableItems[itemIndex], c.Character);
            }
        }
Exemplo n.º 3
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            int     nodeCount   = msg.ReadByte();
            Vector2 lastNodePos = Vector2.Zero;

            if (nodeCount > 0)
            {
                lastNodePos = new Vector2(msg.ReadSingle(), msg.ReadSingle());
            }

            if (!item.CanClientAccess(c))
            {
                return;
            }

            if (nodes.Count > nodeCount)
            {
                nodes.RemoveRange(nodeCount, nodes.Count - nodeCount);
            }
            if (nodeCount > 0)
            {
                if (nodeCount > nodes.Count)
                {
                    nodes.Add(lastNodePos);
                }
                else
                {
                    nodes[nodes.Count - 1] = lastNodePos;
                }
            }
            CreateNetworkEvent();
        }
Exemplo n.º 4
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            if (c.Character == null)
            {
                return;
            }
            var requestedFixAction = (FixActions)msg.ReadRangedInteger(0, 2);

            if (requestedFixAction != FixActions.None)
            {
                if (!c.Character.IsTraitor && requestedFixAction == FixActions.Sabotage)
                {
                    if (GameSettings.VerboseLogging)
                    {
                        DebugConsole.Log($"Non traitor \"{c.Character.Name}\" attempted to sabotage item.");
                    }
                    requestedFixAction = FixActions.Repair;
                }

                if (CurrentFixer == null || CurrentFixer == c.Character && requestedFixAction != currentFixerAction)
                {
                    StartRepairing(c.Character, requestedFixAction);
                    item.CreateServerEvent(this);
                }
            }
        }
Exemplo n.º 5
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            bool  autoTemp     = msg.ReadBoolean();
            float shutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 15);
            float coolingRate  = msg.ReadRangedSingle(0.0f, 100.0f, 8);
            float fissionRate  = msg.ReadRangedSingle(0.0f, 100.0f, 8);

            if (!item.CanClientAccess(c))
            {
                return;
            }

            AutoTemp     = autoTemp;
            ShutDownTemp = shutDownTemp;

            CoolingRate = coolingRate;
            FissionRate = fissionRate;

            lastUser = c.Character;
            if (nextServerLogWriteTime == null)
            {
                nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
            }

            //need to create a server event to notify all clients of the changed state
            unsentChanges = true;
        }
Exemplo n.º 6
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            float newFlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f;
            bool  newIsActive       = msg.ReadBoolean();

            if (item.CanClientAccess(c))
            {
                if (newFlowPercentage != FlowPercentage)
                {
                    GameServer.Log(GameServer.CharacterLogName(c.Character) + " set the pumping speed of " + item.Name + " to " + (int)(newFlowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
                }
                if (newIsActive != IsActive)
                {
                    GameServer.Log(GameServer.CharacterLogName(c.Character) + (newIsActive ? " turned on " : " turned off ") + item.Name, ServerLog.MessageType.ItemInteraction);
                }
                if (pumpSpeedLockTimer <= 0.0f)
                {
                    TargetLevel = null;
                }

                FlowPercentage = newFlowPercentage;
                IsActive       = newIsActive;
            }

            //notify all clients of the changed state
            item.CreateServerEvent(this);
        }
Exemplo n.º 7
0
        public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c)
        {
            bool    autoPilot         = msg.ReadBoolean();
            Vector2 newTargetVelocity = targetVelocity;
            bool    maintainPos       = false;
            Vector2?newPosToMaintain  = null;
            bool    headingToStart    = false;

            if (autoPilot)
            {
                maintainPos = msg.ReadBoolean();
                if (maintainPos)
                {
                    newPosToMaintain = new Vector2(
                        msg.ReadFloat(),
                        msg.ReadFloat());
                }
                else
                {
                    headingToStart = msg.ReadBoolean();
                }
            }
            else
            {
                newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat());
            }

            if (!item.CanClientAccess(c))
            {
                return;
            }

            AutoPilot = autoPilot;

            if (!AutoPilot)
            {
                targetVelocity = newTargetVelocity;
            }
            else
            {
                MaintainPos   = newPosToMaintain != null;
                posToMaintain = newPosToMaintain;

                if (posToMaintain == null)
                {
                    LevelStartSelected = headingToStart;
                    LevelEndSelected   = !headingToStart;
                    UpdatePath();
                }
                else
                {
                    LevelStartSelected = false;
                    LevelEndSelected   = false;
                }
            }

            //notify all clients of the changed state
            unsentChanges = true;
        }
Exemplo n.º 8
0
 public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
 {
     if (c.Character == null)
     {
         return;
     }
     StartRepairing(c.Character);
 }
Exemplo n.º 9
0
        //used when clients use the water/fire console commands
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            float newWaterVolume = msg.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;

            bool           hasFireSources  = msg.ReadBoolean();
            int            fireSourceCount = 0;
            List <Vector3> newFireSources  = new List <Vector3>();

            if (hasFireSources)
            {
                fireSourceCount = msg.ReadRangedInteger(0, 16);
                for (int i = 0; i < fireSourceCount; i++)
                {
                    newFireSources.Add(new Vector3(
                                           MathHelper.Clamp(msg.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                           MathHelper.Clamp(msg.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
                                           msg.ReadRangedSingle(0.0f, 1.0f, 8)));
                }
            }

            if (!c.HasPermission(ClientPermissions.ConsoleCommands) ||
                !c.PermittedConsoleCommands.Any(command => command.names.Contains("fire") || command.names.Contains("editfire")))
            {
                return;
            }

            WaterVolume = newWaterVolume;

            for (int i = 0; i < fireSourceCount; i++)
            {
                Vector2 pos = new Vector2(
                    rect.X + rect.Width * newFireSources[i].X,
                    rect.Y - rect.Height + (rect.Height * newFireSources[i].Y));
                float size = newFireSources[i].Z * rect.Width;

                var newFire = i < FireSources.Count ?
                              FireSources[i] :
                              new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true);
                newFire.Position = pos;
                newFire.Size     = new Vector2(size, newFire.Size.Y);

                //ignore if the fire wasn't added to this room (invalid position)?
                if (!FireSources.Contains(newFire))
                {
                    newFire.Remove();
                    continue;
                }
            }

            for (int i = FireSources.Count - 1; i >= fireSourceCount; i--)
            {
                FireSources[i].Remove();
                if (i < FireSources.Count)
                {
                    FireSources.RemoveAt(i);
                }
            }
        }
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            bool[]   elementStates = new bool[customInterfaceElementList.Count];
            string[] elementValues = new string[customInterfaceElementList.Count];
            for (int i = 0; i < customInterfaceElementList.Count; i++)
            {
                if (customInterfaceElementList[i].HasPropertyName)
                {
                    elementValues[i] = msg.ReadString();
                }
                else
                {
                    elementStates[i] = msg.ReadBoolean();
                }
            }

            CustomInterfaceElement clickedButton = null;

            if ((c.Character != null && DrawHudWhenEquipped && item.ParentInventory?.Owner == c.Character) || item.CanClientAccess(c))
            {
                for (int i = 0; i < customInterfaceElementList.Count; i++)
                {
                    if (customInterfaceElementList[i].HasPropertyName)
                    {
                        if (!customInterfaceElementList[i].IsIntegerInput)
                        {
                            TextChanged(customInterfaceElementList[i], elementValues[i]);
                        }
                        else
                        {
                            int.TryParse(elementValues[i], out int value);
                            ValueChanged(customInterfaceElementList[i], value);
                        }
                    }
                    else if (customInterfaceElementList[i].ContinuousSignal)
                    {
                        TickBoxToggled(customInterfaceElementList[i], elementStates[i]);
                    }
                    else if (elementStates[i])
                    {
                        clickedButton = customInterfaceElementList[i];
                        ButtonClicked(customInterfaceElementList[i]);
                    }
                }
            }

            //notify all clients of the new state
            GameMain.Server.CreateEntityEvent(item, new object[]
            {
                NetEntityEvent.Type.ComponentState,
                item.GetComponentIndex(this),
                clickedButton
            });

            item.CreateServerEvent(this);
        }
Exemplo n.º 11
0
        public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Client c)
        {
            float newFlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f;
            bool  newIsActive       = msg.ReadBoolean();

            if (item.CanClientAccess(c))
            {
                if (newFlowPercentage != FlowPercentage)
                {
                    GameServer.Log(c.Character.LogName + " set the pumping speed of " + item.Name + " to " + (int)(newFlowPercentage) + " %", ServerLog.MessageType.ItemInteraction);

                    if (GameMain.NilMod.EnableGriefWatcher && NilMod.NilModGriefWatcher.PumpPositive && newFlowPercentage > FlowPercentage && newFlowPercentage > 0)
                    {
                        //Only blame one client at a time - they started it first.
                        if (!CoroutineManager.IsCoroutineRunning("WarnPump_" + item.ID))
                        {
                            CoroutineManager.StartCoroutine(WarnPump(c), "WarnPump_" + item.ID);
                        }

                        /*
                         * NilMod.NilModGriefWatcher.SendWarning(c.Character.LogName
                         + " Set " + item.Name + " to pump in at "
                         + (int)(newFlowPercentage) + " %"
                         + (newIsActive ? " (On) " : " (Off) "), c);
                         */
                    }
                }
                if (newIsActive != IsActive)
                {
                    GameServer.Log(c.Character.LogName + (newIsActive ? " turned on " : " turned off ") + item.Name, ServerLog.MessageType.ItemInteraction);

                    if (GameMain.NilMod.EnableGriefWatcher && NilMod.NilModGriefWatcher.PumpOff && IsActive)
                    {
                        //Only blame one client at a time - they started it first.
                        if (!CoroutineManager.IsCoroutineRunning("WarnPump_" + item.ID))
                        {
                            CoroutineManager.StartCoroutine(WarnPump(c), "WarnPump_" + item.ID);
                        }

                        /*
                         * NilMod.NilModGriefWatcher.SendWarning(c.Character.LogName
                         + " turned off " + item.Name
                         + " (" + (int)(newFlowPercentage) + " % Speed)", c);
                         */
                    }
                }

                FlowPercentage = newFlowPercentage;
                IsActive       = newIsActive;
            }

            //notify all clients of the changed state
            item.CreateServerEvent(this);
        }
Exemplo n.º 12
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            bool active = msg.ReadBoolean();

            item.CreateServerEvent(this);

            if (item.CanClientAccess(c))
            {
                SetActive(active, c.Character);
            }
        }
Exemplo n.º 13
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            float newRechargeSpeed = msg.ReadRangedInteger(0, 10) / 10.0f * maxRechargeSpeed;

            if (item.CanClientAccess(c))
            {
                RechargeSpeed = newRechargeSpeed;
                GameServer.Log(c.Character.LogName + " set the recharge speed of " + item.Name + " to " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", ServerLog.MessageType.ItemInteraction);
            }

            item.CreateServerEvent(this);
        }
Exemplo n.º 14
0
        public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c)
        {
            bool isActive = msg.ReadBoolean();

            if (!item.CanClientAccess(c))
            {
                return;
            }

            IsActive = isActive;
            isActiveTickBox.Selected = IsActive;

            item.CreateServerEvent(this);
        }
Exemplo n.º 15
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            int signalIndex = msg.ReadRangedInteger(0, Signals.Length - 1);

            if (!item.CanClientAccess(c))
            {
                return;
            }
            if (!SendSignal(signalIndex))
            {
                return;
            }
            GameServer.Log($"{GameServer.CharacterLogName(c.Character)} sent a signal \"{Signals[signalIndex]}\" from {item.Name}", ServerLog.MessageType.ItemInteraction);
            item.CreateServerEvent(this, new object[] { signalIndex });
        }
Exemplo n.º 16
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            bool[] elementStates = new bool[customInterfaceElementList.Count];
            string[] elementValues = new string[customInterfaceElementList.Count];
            for (int i = 0; i < customInterfaceElementList.Count; i++)
            {
                if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
                {
                    elementValues[i] = msg.ReadString();
                }
                else
                {
                    elementStates[i] = msg.ReadBoolean();
                }
            }

            CustomInterfaceElement clickedButton = null;
            if (item.CanClientAccess(c))
            {
                for (int i = 0; i < customInterfaceElementList.Count; i++)
                {
                    if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
                    {
                        TextChanged(customInterfaceElementList[i], elementValues[i]);
                    }
                    else if (customInterfaceElementList[i].ContinuousSignal)
                    {
                        TickBoxToggled(customInterfaceElementList[i], elementStates[i]);
                    }
                    else if (elementStates[i])
                    {
                        clickedButton = customInterfaceElementList[i];
                        ButtonClicked(customInterfaceElementList[i]);
                    }
                }
            }

            //notify all clients of the new state
            GameMain.Server.CreateEntityEvent(item, new object[]
            {
                NetEntityEvent.Type.ComponentState,
                item.GetComponentIndex(this),
                clickedButton
            });

            item.CreateServerEvent(this);
        }
Exemplo n.º 17
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            float newTargetForce = msg.ReadRangedInteger(-10, 10) * 10.0f;

            if (item.CanClientAccess(c))
            {
                if (Math.Abs(newTargetForce - targetForce) > 0.01f)
                {
                    GameServer.Log(c.Character.LogName + " set the force of " + item.Name + " to " + (int)(newTargetForce) + " %", ServerLog.MessageType.ItemInteraction);
                }

                targetForce = newTargetForce;
            }

            //notify all clients of the changed state
            item.CreateServerEvent(this);
        }
Exemplo n.º 18
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            string newOutputValue = msg.ReadString();

            if (item.CanClientAccess(c))
            {
                if (newOutputValue.Length > MaxMessageLength)
                {
                    newOutputValue = newOutputValue.Substring(0, MaxMessageLength);
                }
                GameServer.Log(GameServer.CharacterLogName(c.Character) + " entered \"" + newOutputValue + "\" on " + item.Name,
                               ServerLog.MessageType.ItemInteraction);
                OutputValue = newOutputValue;
                item.SendSignal(0, newOutputValue, "signal_out", null);
                item.CreateServerEvent(this);
            }
        }
Exemplo n.º 19
0
        public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Client c)
        {
            bool  isActive = msg.ReadBoolean();
            bool  directionalPing = useDirectionalPing;
            float zoomT = zoom, pingDirectionT = 0.0f;

            if (isActive)
            {
                zoomT           = msg.ReadRangedSingle(0.0f, 1.0f, 8);
                directionalPing = msg.ReadBoolean();
                if (directionalPing)
                {
                    pingDirectionT = msg.ReadRangedSingle(0.0f, 1.0f, 8);
                }
            }

            if (!item.CanClientAccess(c))
            {
                return;
            }

            IsActive = isActive;

            //TODO: cleanup
#if CLIENT
            activeTickBox.Selected = IsActive;
#endif
            if (isActive)
            {
                zoom = MathHelper.Lerp(MinZoom, MaxZoom, zoomT);
                useDirectionalPing = directionalPing;
                if (useDirectionalPing)
                {
                    float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, pingDirectionT);
                    pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle));
                }
#if CLIENT
                zoomSlider.BarScroll        = zoomT;
                directionalTickBox.Selected = useDirectionalPing;
                directionalSlider.BarScroll = pingDirectionT;
#endif
            }
#if SERVER
            item.CreateServerEvent(this);
#endif
        }
Exemplo n.º 20
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            bool  autoTemp      = msg.ReadBoolean();
            bool  powerOn       = msg.ReadBoolean();
            float fissionRate   = msg.ReadRangedSingle(0.0f, 100.0f, 8);
            float turbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8);

            if (!item.CanClientAccess(c))
            {
                return;
            }

            IsActive = true;

            if (!autoTemp && AutoTemp)
            {
                blameOnBroken = c;
            }
            if (turbineOutput < targetTurbineOutput)
            {
                blameOnBroken = c;
            }
            if (fissionRate > targetFissionRate)
            {
                blameOnBroken = c;
            }
            if (!_powerOn && powerOn)
            {
                blameOnBroken = c;
            }

            AutoTemp            = autoTemp;
            _powerOn            = powerOn;
            targetFissionRate   = fissionRate;
            targetTurbineOutput = turbineOutput;

            LastUser = c.Character;
            if (nextServerLogWriteTime == null)
            {
                nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
            }

            //need to create a server event to notify all clients of the changed state
            unsentChanges = true;
        }
Exemplo n.º 21
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());

            if (!item.CanClientAccess(c) || !Attachable || attached || !MathUtils.IsValid(simPosition))
            {
                return;
            }

            Vector2 offset = simPosition - c.Character.SimPosition;

            offset      = offset.ClampLength(MaxAttachDistance * 1.5f);
            simPosition = c.Character.SimPosition + offset;

            Drop(false, null);
            item.SetTransform(simPosition, 0.0f);
            AttachToWall();

            item.CreateServerEvent(this);
            GameServer.Log(GameServer.CharacterLogName(c.Character) + " attached " + item.Name + " to a wall", ServerLog.MessageType.ItemInteraction);
        }
Exemplo n.º 22
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Barotrauma.Networking.Client c)
        {
            List <Item> prevItems = new List <Item>(Items);

            ushort[] newItemIDs = new ushort[capacity];

            for (int i = 0; i < capacity; i++)
            {
                newItemIDs[i] = msg.ReadUInt16();
            }

            if (c == null || c.Character == null)
            {
                return;
            }

            if (!c.Character.CanAccessInventory(this))
            {
                //create a network event to correct the client's inventory state
                //otherwise they may have an item in their inventory they shouldn't have been able to pick up,
                //and receiving an event for that inventory later will cause the item to be dropped
                CreateNetworkEvent();
                for (int i = 0; i < capacity; i++)
                {
                    var item = Entity.FindEntityByID(newItemIDs[i]) as Item;
                    if (item == null)
                    {
                        continue;
                    }
                    if (item.ParentInventory != null && item.ParentInventory != this)
                    {
                        item.ParentInventory.CreateNetworkEvent();
                    }
                }
                return;
            }

            List <Inventory> prevItemInventories = new List <Inventory>(Items.Select(i => i?.ParentInventory));

            for (int i = 0; i < capacity; i++)
            {
                Item newItem = newItemIDs[i] == 0 ? null : Entity.FindEntityByID(newItemIDs[i]) as Item;
                prevItemInventories.Add(newItem?.ParentInventory);

                if (newItemIDs[i] == 0 || (newItem != Items[i]))
                {
                    if (Items[i] != null)
                    {
                        Items[i].Drop();
                    }
                    System.Diagnostics.Debug.Assert(Items[i] == null);
                }
            }

            for (int i = 0; i < capacity; i++)
            {
                if (newItemIDs[i] > 0)
                {
                    var item = Entity.FindEntityByID(newItemIDs[i]) as Item;
                    if (item == null || item == Items[i])
                    {
                        continue;
                    }

                    if (GameMain.Server != null)
                    {
                        var holdable = item.GetComponent <Holdable>();
                        if (holdable != null && !holdable.CanBeDeattached())
                        {
                            continue;
                        }

                        if (!item.CanClientAccess(c))
                        {
                            continue;
                        }
                    }
                    TryPutItem(item, i, true, true, c.Character, false);
                }
            }

            CreateNetworkEvent();
            foreach (Inventory prevInventory in prevItemInventories.Distinct())
            {
                if (prevInventory != this)
                {
                    prevInventory?.CreateNetworkEvent();
                }
            }

            foreach (Item item in Items.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!prevItems.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(c.Character.LogName + " picked up " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(c.Character.LogName + " placed " + item.Name + " in " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
            foreach (Item item in prevItems.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!Items.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(c.Character.LogName + " dropped " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(c.Character.LogName + " removed " + item.Name + " from " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
        }
        public virtual void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            if (GameMain.Server == null)
            {
                return;
            }

            switch (type)
            {
            case ClientNetObject.CHARACTER_INPUT:

                if (c.Character != this)
                {
#if DEBUG
                    DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                    return;
                }

                UInt16 networkUpdateID = msg.ReadUInt16();
                byte   inputCount      = msg.ReadByte();

                if (AllowInput)
                {
                    Enabled = true;
                }

                for (int i = 0; i < inputCount; i++)
                {
                    InputNetFlags newInput    = (InputNetFlags)msg.ReadRangedInteger(0, (int)InputNetFlags.MaxVal);
                    UInt16        newAim      = 0;
                    UInt16        newInteract = 0;

                    if (newInput != InputNetFlags.None && newInput != InputNetFlags.FacingLeft)
                    {
                        c.KickAFKTimer = 0.0f;
                    }
                    else if (AnimController.Dir < 0.0f != newInput.HasFlag(InputNetFlags.FacingLeft))
                    {
                        //character changed the direction they're facing
                        c.KickAFKTimer = 0.0f;
                    }

                    newAim = msg.ReadUInt16();
                    if (newInput.HasFlag(InputNetFlags.Select) ||
                        newInput.HasFlag(InputNetFlags.Deselect) ||
                        newInput.HasFlag(InputNetFlags.Use) ||
                        newInput.HasFlag(InputNetFlags.Health) ||
                        newInput.HasFlag(InputNetFlags.Grab))
                    {
                        newInteract = msg.ReadUInt16();
                    }

                    if (NetIdUtils.IdMoreRecent((ushort)(networkUpdateID - i), LastNetworkUpdateID) && (i < 60))
                    {
                        if ((i > 0 && memInput[i - 1].intAim != newAim))
                        {
                            c.KickAFKTimer = 0.0f;
                        }
                        NetInputMem newMem = new NetInputMem
                        {
                            states          = newInput,
                            intAim          = newAim,
                            interact        = newInteract,
                            networkUpdateID = (ushort)(networkUpdateID - i)
                        };
                        memInput.Insert(i, newMem);
                        LastInputTime = Timing.TotalTime;
                    }
                }

                if (NetIdUtils.IdMoreRecent(networkUpdateID, LastNetworkUpdateID))
                {
                    LastNetworkUpdateID = networkUpdateID;
                }
                else if (NetIdUtils.Difference(networkUpdateID, LastNetworkUpdateID) > 500)
                {
#if DEBUG || UNSTABLE
                    DebugConsole.AddWarning($"Large disrepancy between a client character's network update ID server-side and client-side (client: {networkUpdateID}, server: {LastNetworkUpdateID}). Resetting the ID.");
#endif
                    LastNetworkUpdateID = networkUpdateID;
                }
                if (memInput.Count > 60)
                {
                    //deleting inputs from the queue here means the server is way behind and data needs to be dropped
                    //we'll make the server drop down to 30 inputs for good measure
                    memInput.RemoveRange(30, memInput.Count - 30);
                }
                break;

            case ClientNetObject.ENTITY_STATE:
                int eventType = msg.ReadRangedInteger(0, 3);
                switch (eventType)
                {
                case 0:
                    Inventory.ServerRead(type, msg, c);
                    break;

                case 1:
                    bool doingCPR = msg.ReadBoolean();
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }

                    AnimController.Anim = doingCPR ? AnimController.Animation.CPR : AnimController.Animation.None;
                    break;

                case 2:
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }

                    if (IsIncapacitated)
                    {
                        var causeOfDeath = CharacterHealth.GetCauseOfDeath();
                        Kill(causeOfDeath.First, causeOfDeath.Second);
                    }
                    break;
                }
                break;
            }
            msg.ReadPadBits();
        }
Exemplo n.º 24
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            List <Item> prevItems = new List <Item>(Items);

            byte itemCount = msg.ReadByte();

            ushort[] newItemIDs = new ushort[itemCount];
            for (int i = 0; i < itemCount; i++)
            {
                newItemIDs[i] = msg.ReadUInt16();
            }

            if (c == null || c.Character == null)
            {
                return;
            }

            bool accessible = c.Character.CanAccessInventory(this);

            if (this is CharacterInventory && accessible)
            {
                if (Owner == null || !(Owner is Character))
                {
                    accessible = false;
                }
                else if (!((CharacterInventory)this).AccessibleWhenAlive && !((Character)Owner).IsDead)
                {
                    accessible = false;
                }
            }

            if (!accessible)
            {
                //create a network event to correct the client's inventory state
                //otherwise they may have an item in their inventory they shouldn't have been able to pick up,
                //and receiving an event for that inventory later will cause the item to be dropped
                CreateNetworkEvent();
                for (int i = 0; i < capacity; i++)
                {
                    if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item))
                    {
                        continue;
                    }
                    item.PositionUpdateInterval = 0.0f;
                    if (item.ParentInventory != null && item.ParentInventory != this)
                    {
                        item.ParentInventory.CreateNetworkEvent();
                    }
                }
                return;
            }

            List <Inventory> prevItemInventories = new List <Inventory>(Items.Select(i => i?.ParentInventory));

            for (int i = 0; i < capacity; i++)
            {
                Item newItem = newItemIDs[i] == 0 ? null : Entity.FindEntityByID(newItemIDs[i]) as Item;
                prevItemInventories.Add(newItem?.ParentInventory);

                if (newItemIDs[i] == 0 || (newItem != Items[i]))
                {
                    if (Items[i] != null)
                    {
                        Item   droppedItem = Items[i];
                        Entity prevOwner   = Owner;
                        droppedItem.Drop(null);

                        var previousInventory = prevOwner switch
                        {
                            Item itemInventory => (itemInventory.FindParentInventory(inventory => inventory is CharacterInventory) as CharacterInventory),
                            Character character => character.Inventory,
                            _ => null
                        };

                        if (previousInventory != null && previousInventory != c.Character?.Inventory)
                        {
                            GameMain.Server?.KarmaManager.OnItemTakenFromPlayer(previousInventory, c, droppedItem);
                        }

                        if (droppedItem.body != null && prevOwner != null)
                        {
                            droppedItem.body.SetTransform(prevOwner.SimPosition, 0.0f);
                        }
                    }
                    System.Diagnostics.Debug.Assert(Items[i] == null);
                }
            }

            for (int i = 0; i < capacity; i++)
            {
                if (newItemIDs[i] > 0)
                {
                    if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item) || item == Items[i])
                    {
                        continue;
                    }

                    if (GameMain.Server != null)
                    {
                        var holdable = item.GetComponent <Holdable>();
                        if (holdable != null && !holdable.CanBeDeattached())
                        {
                            continue;
                        }

                        if (!prevItems.Contains(item) && !item.CanClientAccess(c))
                        {
#if DEBUG || UNSTABLE
                            DebugConsole.NewMessage($"Client {c.Name} failed to pick up item \"{item}\" (parent inventory: {(item.ParentInventory?.Owner.ToString() ?? "null")}). No access.", Color.Yellow);
#endif
                            if (item.body != null && !c.PendingPositionUpdates.Contains(item))
                            {
                                c.PendingPositionUpdates.Enqueue(item);
                            }
                            item.PositionUpdateInterval = 0.0f;
                            continue;
                        }
                    }
                    TryPutItem(item, i, true, true, c.Character, false);
                    for (int j = 0; j < capacity; j++)
                    {
                        if (Items[j] == item && newItemIDs[j] != item.ID)
                        {
                            Items[j] = null;
                        }
                    }
                }
            }

            CreateNetworkEvent();
            foreach (Inventory prevInventory in prevItemInventories.Distinct())
            {
                if (prevInventory != this)
                {
                    prevInventory?.CreateNetworkEvent();
                }
            }

            foreach (Item item in Items.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!prevItems.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " picked up " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " placed " + item.Name + " in " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
            foreach (Item item in prevItems.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!Items.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " dropped " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " removed " + item.Name + " from " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
        }
Exemplo n.º 25
0
        public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c)
        {
            bool    autoPilot         = msg.ReadBoolean();
            Vector2 newTargetVelocity = targetVelocity;
            bool    maintainPos       = false;
            Vector2?newPosToMaintain  = null;
            bool    headingToStart    = false;

            if (autoPilot)
            {
                maintainPos = msg.ReadBoolean();
                if (maintainPos)
                {
                    newPosToMaintain = new Vector2(
                        msg.ReadFloat(),
                        msg.ReadFloat());
                }
                else
                {
                    headingToStart = msg.ReadBoolean();
                }
            }
            else
            {
                newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat());
            }

            if (lastuser == null)
            {
                lastuser = c.Character;
            }

            if (!item.CanClientAccess(c))
            {
                return;
            }

            if (lastuser != c.Character)
            {
                if (!CoroutineManager.IsCoroutineRunning("warnislocked_" + item.ID + "_" + c.Character.ID))
                {
                    CoroutineManager.StartCoroutine(Warnislocked(c, item), "warnislocked_" + item.ID + "_" + c.Character.ID);
                }
                return;
            }

            AutoPilot = autoPilot;

            if (!AutoPilot)
            {
                targetVelocity = newTargetVelocity;
            }
            else
            {
                MaintainPos   = newPosToMaintain != null;
                posToMaintain = newPosToMaintain;

                if (posToMaintain == null)
                {
                    LevelStartSelected = headingToStart;
                    LevelEndSelected   = !headingToStart;
                    UpdatePath();
                }
                else
                {
                    LevelStartSelected = false;
                    LevelEndSelected   = false;
                }
            }

            //notify all clients of the changed state
            unsentChanges = true;
        }
Exemplo n.º 26
0
        public virtual void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            if (GameMain.Server == null)
            {
                return;
            }

            switch (type)
            {
            case ClientNetObject.CHARACTER_INPUT:

                if (c.Character != this)
                {
#if DEBUG
                    DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                    return;
                }

                UInt16 networkUpdateID = msg.ReadUInt16();
                byte   inputCount      = msg.ReadByte();

                if (AllowInput)
                {
                    Enabled = true;
                }

                for (int i = 0; i < inputCount; i++)
                {
                    InputNetFlags newInput    = (InputNetFlags)msg.ReadRangedInteger(0, (int)InputNetFlags.MaxVal);
                    UInt16        newAim      = 0;
                    UInt16        newInteract = 0;

                    if (newInput.HasFlag(InputNetFlags.Aim))
                    {
                        newAim = msg.ReadUInt16();
                    }
                    if (newInput.HasFlag(InputNetFlags.Select) || newInput.HasFlag(InputNetFlags.Use))
                    {
                        newInteract = msg.ReadUInt16();
                    }

                    //if (AllowInput)
                    //{
                    if (NetIdUtils.IdMoreRecent((ushort)(networkUpdateID - i), LastNetworkUpdateID) && (i < 60))
                    {
                        NetInputMem newMem = new NetInputMem();
                        newMem.states   = newInput;
                        newMem.intAim   = newAim;
                        newMem.interact = newInteract;

                        newMem.networkUpdateID = (ushort)(networkUpdateID - i);

                        memInput.Insert(i, newMem);
                    }
                    //}
                }

                if (NetIdUtils.IdMoreRecent(networkUpdateID, LastNetworkUpdateID))
                {
                    LastNetworkUpdateID = networkUpdateID;
                }
                if (memInput.Count > 60)
                {
                    //deleting inputs from the queue here means the server is way behind and data needs to be dropped
                    //we'll make the server drop down to 30 inputs for good measure
                    memInput.RemoveRange(30, memInput.Count - 30);
                }
                break;

            case ClientNetObject.ENTITY_STATE:
                int eventType = msg.ReadRangedInteger(0, 3);
                switch (eventType)
                {
                case 0:
                    inventory.ServerRead(type, msg, c);
                    break;

                case 1:
                    bool doingCPR = msg.ReadBoolean();
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }

                    AnimController.Anim = doingCPR ? AnimController.Animation.CPR : AnimController.Animation.None;
                    break;

                case 2:
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }

                    if (IsUnconscious)
                    {
                        Kill(lastAttackCauseOfDeath);
                    }
                    break;

                case 3:
                    LimbType grabLimb = (LimbType)msg.ReadUInt16();
                    if (c.Character != this)
                    {
#if DEBUG
                        DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
                        return;
                    }
                    AnimController.GrabLimb = grabLimb;
                    break;
                }
                break;
            }
            msg.ReadPadBits();
        }
Exemplo n.º 27
0
        public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c)
        {
            bool    autoPilot            = msg.ReadBoolean();
            bool    dockingButtonClicked = msg.ReadBoolean();
            Vector2 newSteeringInput     = targetVelocity;
            bool    maintainPos          = false;
            Vector2?newPosToMaintain     = null;
            bool    headingToStart       = false;

            if (autoPilot)
            {
                maintainPos = msg.ReadBoolean();
                if (maintainPos)
                {
                    newPosToMaintain = new Vector2(
                        msg.ReadFloat(),
                        msg.ReadFloat());
                }
                else
                {
                    headingToStart = msg.ReadBoolean();
                }
            }
            else
            {
                newSteeringInput = new Vector2(msg.ReadFloat(), msg.ReadFloat());
            }

            if (!item.CanClientAccess(c))
            {
                return;
            }

            user      = c.Character;
            AutoPilot = autoPilot;

            if (dockingButtonClicked)
            {
                item.SendSignal(0, "1", "toggle_docking", sender: Character.Controlled);
            }

            if (!AutoPilot)
            {
                steeringInput       = newSteeringInput;
                steeringAdjustSpeed = MathHelper.Lerp(0.2f, 1.0f, c.Character.GetSkillLevel("helm") / 100.0f);
            }
            else
            {
                MaintainPos   = newPosToMaintain != null;
                posToMaintain = newPosToMaintain;

                if (posToMaintain == null)
                {
                    LevelStartSelected = headingToStart;
                    LevelEndSelected   = !headingToStart;
                    UpdatePath();
                }
                else
                {
                    LevelStartSelected = false;
                    LevelEndSelected   = false;
                }
            }

            //notify all clients of the changed state
            unsentChanges = true;
        }
Exemplo n.º 28
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Barotrauma.Networking.Client c)
        {
            List <Item> prevItems = new List <Item>(Items);

            ushort[] newItemIDs = new ushort[capacity];

            for (int i = 0; i < capacity; i++)
            {
                newItemIDs[i] = msg.ReadUInt16();
            }

            if (c == null || c.Character == null || !c.Character.CanAccessInventory(this))
            {
                return;
            }

            for (int i = 0; i < capacity; i++)
            {
                if (newItemIDs[i] == 0)
                {
                    if (Items[i] != null)
                    {
                        Items[i].Drop(c.Character);
                    }
                    System.Diagnostics.Debug.Assert(Items[i] == null);
                }
                else
                {
                    var item = Entity.FindEntityByID(newItemIDs[i]) as Item;
                    if (item == null || item == Items[i])
                    {
                        continue;
                    }

                    if (GameMain.Server != null)
                    {
                        if (!item.CanClientAccess(c))
                        {
                            continue;
                        }
                    }
                    TryPutItem(item, i, true, false);
                }
            }

            GameMain.Server.CreateEntityEvent(Owner as IServerSerializable, new object[] { NetEntityEvent.Type.InventoryState });

            foreach (Item item in Items.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!prevItems.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(c.Character + " picked up " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(c.Character + " placed " + item.Name + " in " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
            foreach (Item item in prevItems.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!Items.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(c.Character + " dropped " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(c.Character + " removed " + item.Name + " from " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
        }
Exemplo n.º 29
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 = MapEntity.FindEntityByID(wireId) as Item;
                    if (wireItem == null)
                    {
                        continue;
                    }

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

            item.CreateServerEvent <ConnectionPanel>(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;
                        }
                    }
                }
            }

            Networking.GameServer.Log(item.Name + " rewired by " + c.Character.Name, ServerLog.MessageType.ItemInteraction);

            //update the connections
            for (int i = 0; i < Connections.Count; i++)
            {
                Connections[i].ClearConnections();

                for (int j = 0; j < wireCounts[i]; j++)
                {
                    if (wires[i, j] == null)
                    {
                        continue;
                    }

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

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

                    Networking.GameServer.Log(
                        item.Name + " (" + Connections[i].Name + ") -> " +
                        (otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"), ServerLog.MessageType.ItemInteraction);
                }
            }
        }
Exemplo n.º 30
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);
                    }
                }
            }
        }