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