diff --git a/Exiled.API/Features/Player.cs b/Exiled.API/Features/Player.cs index 4f29095ab8..bebe8e131a 100644 --- a/Exiled.API/Features/Player.cs +++ b/Exiled.API/Features/Player.cs @@ -1965,7 +1965,8 @@ public bool RemoveItem(Item item, bool destroy = true) Inventory.NetworkCurItem = ItemIdentifier.None; Inventory.UserInventory.Items.Remove(item.Serial); - ItemsValue.Remove(item); + typeof(InventoryExtensions).InvokeStaticEvent(nameof(InventoryExtensions.OnItemRemoved), new object[] { ReferenceHub, item.Base, null }); + Inventory.SendItemsNextFrame = true; } @@ -2590,8 +2591,6 @@ public Item AddItem(ItemBase itemBase, Item item = null) typeof(InventoryExtensions).InvokeStaticEvent(nameof(InventoryExtensions.OnItemAdded), new object[] { ReferenceHub, itemBase, null }); - ItemsValue.Add(item); - Inventory.SendItemsNextFrame = true; return item; } diff --git a/Exiled.Events/Events.cs b/Exiled.Events/Events.cs index fee31f0c9d..178071bb73 100644 --- a/Exiled.Events/Events.cs +++ b/Exiled.Events/Events.cs @@ -104,6 +104,7 @@ public override void OnDisabled() CharacterClassManager.OnRoundStarted -= Handlers.Server.OnRoundStarted; InventorySystem.InventoryExtensions.OnItemAdded -= Handlers.Player.OnItemAdded; + InventorySystem.InventoryExtensions.OnItemRemoved -= Handlers.Player.OnItemRemoved; RagdollManager.OnRagdollSpawned -= Handlers.Internal.RagdollList.OnSpawnedRagdoll; RagdollManager.OnRagdollRemoved -= Handlers.Internal.RagdollList.OnRemovedRagdoll; diff --git a/Exiled.Events/Handlers/Player.cs b/Exiled.Events/Handlers/Player.cs index 2bf468a020..8f45023d7b 100644 --- a/Exiled.Events/Handlers/Player.cs +++ b/Exiled.Events/Handlers/Player.cs @@ -7,6 +7,7 @@ namespace Exiled.Events.Handlers { + using Exiled.API.Features.Pickups; #pragma warning disable IDE0079 #pragma warning disable IDE0060 #pragma warning disable SA1623 // Property summary documentation should match accessors @@ -941,7 +942,15 @@ public class Player /// The added . /// The the originated from, or if the item was not picked up. public static void OnItemAdded(ReferenceHub referenceHub, InventorySystem.Items.ItemBase itemBase, InventorySystem.Items.Pickups.ItemPickupBase pickupBase) - => ItemAdded.InvokeSafely(new ItemAddedEventArgs(referenceHub, itemBase, pickupBase)); + { + ItemAddedEventArgs ev = new(referenceHub, itemBase, pickupBase); + + ev.Item.ReadPickupInfo(ev.Pickup); + + ev.Player.ItemsValue.Add(ev.Item); + + ItemAdded.InvokeSafely(ev); + } /// /// Called after a has an item removed from their inventory. @@ -950,7 +959,14 @@ public static void OnItemAdded(ReferenceHub referenceHub, InventorySystem.Items. /// The removed . /// The the originated from, or if the item was not picked up. public static void OnItemRemoved(ReferenceHub referenceHub, InventorySystem.Items.ItemBase itemBase, InventorySystem.Items.Pickups.ItemPickupBase pickupBase) - => ItemRemoved.InvokeSafely(new ItemRemovedEventArgs(referenceHub, itemBase, pickupBase)); + { + ItemRemovedEventArgs ev = new(referenceHub, itemBase, pickupBase); + ItemRemoved.InvokeSafely(ev); + + ev.Player.ItemsValue.Remove(ev.Item); + + API.Features.Items.Item.BaseToItem.Remove(itemBase); + } /// /// Called before a enters in an environmental hazard. diff --git a/Exiled.Events/Patches/Fixes/FixOnAddedBeingCallAfterOnRemoved.cs b/Exiled.Events/Patches/Fixes/FixOnAddedBeingCallAfterOnRemoved.cs new file mode 100644 index 0000000000..942abf4f7d --- /dev/null +++ b/Exiled.Events/Patches/Fixes/FixOnAddedBeingCallAfterOnRemoved.cs @@ -0,0 +1,65 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.Patches.Fixes +{ + using System; + using System.Collections.Generic; + using System.Reflection.Emit; + + using API.Features.Pools; + using Exiled.API.Features; + using HarmonyLib; + using InventorySystem; + using InventorySystem.Items; + using InventorySystem.Items.Pickups; + + using static HarmonyLib.AccessTools; + + /// + /// Patches . + /// Fix than NW call before for AmmoItem. + /// + [HarmonyPatch(typeof(InventoryExtensions), nameof(InventoryExtensions.ServerAddItem))] + internal class FixOnAddedBeingCallAfterOnRemoved + { + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) + { + List newInstructions = ListPool.Pool.Get(instructions); + /* + // Modify this + itemBase2.OnAdded(pickup); + Action onItemAdded = InventoryExtensions.OnItemAdded; + if (onItemAdded != null) + { + onItemAdded(inv._hub, itemBase2, pickup); + } + // To this + Action onItemAdded = InventoryExtensions.OnItemAdded; + if (onItemAdded != null) + { + onItemAdded(inv._hub, itemBase2, pickup); + } + itemBase2.OnAdded(pickup); + */ + int opCodesToMove = 3; + int offset = -2; + int indexOnAdded = newInstructions.FindIndex(instruction => instruction.Calls(Method(typeof(ItemBase), nameof(ItemBase.OnAdded)))) + offset; + + offset = 1; + int indexInvoke = newInstructions.FindIndex(instruction => instruction.Calls(Method(typeof(Action), nameof(Action.Invoke)))) + offset; + + newInstructions.InsertRange(indexInvoke, newInstructions.GetRange(indexOnAdded, opCodesToMove)); + newInstructions[indexInvoke].MoveLabelsFrom(newInstructions[indexInvoke + opCodesToMove]); + newInstructions.RemoveRange(indexOnAdded, opCodesToMove); + + for (int z = 0; z < newInstructions.Count; z++) + yield return newInstructions[z]; + ListPool.Pool.Return(newInstructions); + } + } +} diff --git a/Exiled.Events/Patches/Fixes/FixPickupPreviousOwner.cs b/Exiled.Events/Patches/Fixes/FixPickupPreviousOwner.cs index 304fc41243..22f5a2db78 100644 --- a/Exiled.Events/Patches/Fixes/FixPickupPreviousOwner.cs +++ b/Exiled.Events/Patches/Fixes/FixPickupPreviousOwner.cs @@ -16,7 +16,6 @@ namespace Exiled.Events.Patches.Fixes using InventorySystem; using InventorySystem.Items.Firearms.Ammo; using InventorySystem.Items.Pickups; - using VoiceChat; using static HarmonyLib.AccessTools; diff --git a/Exiled.Events/Patches/Generic/InventoryControlPatch.cs b/Exiled.Events/Patches/Generic/InventoryControlPatch.cs deleted file mode 100644 index 6651d46dd4..0000000000 --- a/Exiled.Events/Patches/Generic/InventoryControlPatch.cs +++ /dev/null @@ -1,168 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) Exiled Team. All rights reserved. -// Licensed under the CC BY-SA 3.0 license. -// -// ----------------------------------------------------------------------- - -namespace Exiled.Events.Patches.Generic -{ -#pragma warning disable SA1402 -#pragma warning disable SA1649 - using System.Collections.Generic; - using System.Reflection; - using System.Reflection.Emit; - - using API.Features; - using API.Features.Items; - using API.Features.Pools; - using Exiled.API.Features.Pickups; - using HarmonyLib; - - using InventorySystem; - using InventorySystem.Items; - using InventorySystem.Items.Pickups; - - using MEC; - - using static HarmonyLib.AccessTools; - - using Inventory = InventorySystem.Inventory; - - /// - /// Patches to help manage . - /// - [HarmonyPatch(typeof(InventoryExtensions), nameof(InventoryExtensions.ServerAddItem))] - internal static class InventoryControlAddPatch - { - private static IEnumerable Transpiler( - IEnumerable instructions, - ILGenerator generator) - { - List newInstructions = ListPool.Pool.Get(instructions); - - const int offset = -2; - int index = newInstructions.FindIndex( - i => - (i.opcode == OpCodes.Callvirt) && - ((MethodInfo)i.operand == Method(typeof(ItemBase), nameof(ItemBase.OnAdded)))) + offset; - - // AddItem(Player.Get(inv._hub), itemInstance) - newInstructions.InsertRange( - index, - new CodeInstruction[] - { - // Player.Get(inv._hub) - new(OpCodes.Ldarg_0), - new(OpCodes.Ldfld, Field(typeof(Inventory), nameof(Inventory._hub))), - new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), - - // itemInstance - new(OpCodes.Ldloc_1), - - // pickup - new(OpCodes.Ldarg_3), - - // AddItem(player, itemInstance, pickup) - new(OpCodes.Call, Method(typeof(InventoryControlAddPatch), nameof(AddItem))), - }); - - for (int z = 0; z < newInstructions.Count; z++) - yield return newInstructions[z]; - - ListPool.Pool.Return(newInstructions); - } - - private static void AddItem(Player player, ItemBase itemBase, ItemPickupBase itemPickupBase) - { - Item item = Item.Get(itemBase); - Pickup pickup = Pickup.Get(itemPickupBase); - - item.ReadPickupInfo(pickup); - - player?.ItemsValue.Add(item); - } - } - - /// - /// Patches to help manage . - /// - [HarmonyPatch(typeof(InventoryExtensions), nameof(InventoryExtensions.ServerRemoveItem))] - internal static class InventoryControlRemovePatch - { - private static IEnumerable Transpiler( - IEnumerable instructions, - ILGenerator generator) - { - List newInstructions = ListPool.Pool.Get(instructions); - const int offset = 1; - int index = newInstructions.FindIndex(i => i.opcode == OpCodes.Throw) + offset; - - // RemoveItem(Player.Get(inv._hub), itemSerial) - newInstructions.InsertRange( - index, - new[] - { - // Player.Get(inv._hub) - new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(newInstructions[index]), - new(OpCodes.Ldfld, Field(typeof(Inventory), nameof(Inventory._hub))), - new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), - - // itemSerial - new(OpCodes.Ldarg_1), - - // RemoveItem(Player.Get(inv._hub), itemSerial) - new(OpCodes.Call, Method(typeof(InventoryControlRemovePatch), nameof(RemoveItem))), - }); - - for (int z = 0; z < newInstructions.Count; z++) - yield return newInstructions[z]; - - ListPool.Pool.Return(newInstructions); - } - - private static void RemoveItem(Player player, ushort serial) - { -#if DEBUG - Log.Debug($"Removing item ({serial}) from a player (before null check)"); -#endif - if (player is null) - { -#if DEBUG - Log.Debug("Attempted to remove item from null player, returning."); -#endif - return; - } - - if (!player.Inventory.UserInventory.Items.ContainsKey(serial)) - { -#if DEBUG - Log.Debug("Attempted to remove an item the player doesn't own, returning."); -#endif - return; - } -#if DEBUG - Log.Debug( - $"Inventory Info (before): {player.Nickname} - {player.Items.Count} ({player.Inventory.UserInventory.Items.Count})"); - foreach (Item item in player.Items) - Log.Debug($"{item})"); -#endif - ItemBase itemBase = player.Inventory.UserInventory.Items[serial]; - - player.ItemsValue.Remove(Item.Get(itemBase)); - - Item.BaseToItem.Remove(itemBase); - - Timing.CallDelayed(0.15f, () => - { -#if DEBUG - Log.Debug($"Item ({serial}) removed from {player.Nickname}"); - Log.Debug($"Inventory Info (after): {player.Nickname} - {player.Items.Count} ({player.Inventory.UserInventory.Items.Count})"); - - foreach (Item item in player.Items) - Log.Debug($"{item})"); -#endif - }); - } - } -} \ No newline at end of file