diff --git a/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs b/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs index 9ffc74290..037a80876 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs @@ -20,7 +20,7 @@ namespace Barotrauma public bool Locked; private ushort[] receivedItemIDs; - private float syncItemsDelay; + protected float syncItemsDelay; private CoroutineHandle syncItemsCoroutine; public Inventory(Entity owner, int capacity, Vector2? centerPos = null, int slotsPerRow=5) @@ -116,6 +116,8 @@ namespace Barotrauma { if (Owner == null) return; + Inventory prevInventory = item.ParentInventory; + if (removeItem) { item.Drop(user); @@ -137,6 +139,8 @@ namespace Barotrauma if (createNetworkEvent) { CreateNetworkEvent(); + //also delay syncing the inventory the item was inside + if (prevInventory != null && prevInventory != this) prevInventory.syncItemsDelay = 1.0f; } } @@ -148,7 +152,8 @@ namespace Barotrauma } #if CLIENT else if (GameMain.Client != null) - { + { + syncItemsDelay = 1.0f; GameMain.Client.CreateEntityEvent(Owner as IClientSerializable, new object[] { NetEntityEvent.Type.InventoryState }); } #endif @@ -189,8 +194,6 @@ namespace Barotrauma public void ClientWrite(NetBuffer msg, object[] extraData = null) { ServerWrite(msg, null); - - syncItemsDelay = 1.0f; } public void ServerRead(ClientNetObject type, NetBuffer msg, Barotrauma.Networking.Client c) @@ -203,18 +206,40 @@ namespace Barotrauma newItemIDs[i] = msg.ReadUInt16(); } - if (c == null || c.Character == null || !c.Character.CanAccessInventory(this)) return; + 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 prevItemInventories = new List(Items.Select(i => i?.ParentInventory)); for (int i = 0; i < capacity; i++) { - if (newItemIDs[i] == 0 || (Entity.FindEntityByID(newItemIDs[i]) as Item != Items[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) @@ -234,6 +259,10 @@ namespace Barotrauma } CreateNetworkEvent(); + foreach (Inventory prevInventory in prevItemInventories.Distinct()) + { + if (prevInventory != this) prevInventory?.CreateNetworkEvent(); + } foreach (Item item in Items.Distinct()) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs index eb6039bc6..71e12115b 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs @@ -101,6 +101,7 @@ namespace Barotrauma #if CLIENT else if (GameMain.Client != null) { + syncItemsDelay = 1.0f; GameMain.Client.CreateEntityEvent(Owner as IClientSerializable, new object[] { NetEntityEvent.Type.InventoryState, componentIndex }); } #endif