diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs index 11afddf79c..c5c772529f 100644 --- a/EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs +++ b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs @@ -7,8 +7,12 @@ namespace Exiled.Events.EventArgs.Scp1344 { + using System; + using Exiled.API.Features.Items; using Exiled.Events.EventArgs.Interfaces; + + using InventorySystem.Items; using InventorySystem.Items.Usables.Scp1344; /// @@ -21,11 +25,10 @@ public class ChangedStatusEventArgs : IScp1344Event, IPlayerEvent, IDeniableEven /// /// /// - public ChangedStatusEventArgs(Item item, Scp1344Status scp1344Status) + public ChangedStatusEventArgs(ItemBase item, Scp1344Status scp1344Status) { - Item = item; - Scp1344 = item as Scp1344; - Player = item.Owner; + Scp1344 = Item.Get(item); + Player = Scp1344.Owner; Scp1344Status = scp1344Status; } @@ -37,7 +40,7 @@ public ChangedStatusEventArgs(Item item, Scp1344Status scp1344Status) /// /// Gets the item. /// - public Item Item { get; } + public Item Item => Scp1344; /// /// Gets the player in owner of the item. @@ -50,6 +53,7 @@ public ChangedStatusEventArgs(Item item, Scp1344Status scp1344Status) public Scp1344 Scp1344 { get; } /// + [Obsolete("Please use ChangingStatusEventArgs::IsAllowed instead of this", true)] public bool IsAllowed { get; set; } } } diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/ChangingStatusEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangingStatusEventArgs.cs index 89329e0730..6cf7449e99 100644 --- a/EXILED/Exiled.Events/EventArgs/Scp1344/ChangingStatusEventArgs.cs +++ b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangingStatusEventArgs.cs @@ -9,6 +9,7 @@ namespace Exiled.Events.EventArgs.Scp1344 { using Exiled.API.Features.Items; using Exiled.Events.EventArgs.Interfaces; + using InventorySystem.Items; using InventorySystem.Items.Usables.Scp1344; /// @@ -23,11 +24,10 @@ public class ChangingStatusEventArgs : IPlayerEvent, IScp1344Event, IDeniableEve /// /// /// - public ChangingStatusEventArgs(Item item, Scp1344Status scp1344StatusNew, Scp1344Status scp1344StatusOld, bool isAllowed = true) + public ChangingStatusEventArgs(ItemBase item, Scp1344Status scp1344StatusNew, Scp1344Status scp1344StatusOld, bool isAllowed = true) { - Item = item; - Scp1344 = item as Scp1344; - Player = item.Owner; + Scp1344 = Item.Get(item); + Player = Scp1344.Owner; Scp1344StatusNew = scp1344StatusNew; Scp1344StatusOld = scp1344StatusOld; IsAllowed = isAllowed; @@ -46,7 +46,7 @@ public ChangingStatusEventArgs(Item item, Scp1344Status scp1344StatusNew, Scp134 /// /// Gets the item. /// - public Item Item { get; } + public Item Item => Scp1344; /// /// Gets the player in owner of the item. diff --git a/EXILED/Exiled.Events/Patches/Events/Scp1344/Status.cs b/EXILED/Exiled.Events/Patches/Events/Scp1344/Status.cs index bfe734986c..b4db23211a 100644 --- a/EXILED/Exiled.Events/Patches/Events/Scp1344/Status.cs +++ b/EXILED/Exiled.Events/Patches/Events/Scp1344/Status.cs @@ -5,16 +5,22 @@ // // ----------------------------------------------------------------------- -#pragma warning disable SA1313 // Parameter names should begin with lower-case letter - namespace Exiled.Events.Patches.Events.Scp1344 { - using Exiled.API.Features.Items; + using System; + using System.Collections.Generic; + using System.Reflection; + using System.Reflection.Emit; + + using Exiled.API.Features.Pools; using Exiled.Events.Attributes; using Exiled.Events.EventArgs.Scp1344; using HarmonyLib; + using InventorySystem.Items.Usables.Scp1344; + using static HarmonyLib.AccessTools; + /// /// Patches . /// Adds the event and @@ -25,18 +31,81 @@ namespace Exiled.Events.Patches.Events.Scp1344 [HarmonyPatch(typeof(Scp1344Item), nameof(Scp1344Item.Status), MethodType.Setter)] internal static class Status { - private static bool Prefix(Scp1344Item __instance, ref Scp1344Status value) + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) { - ChangingStatusEventArgs ev = new(Item.Get(__instance), value, __instance._status); - Handlers.Scp1344.OnChangingStatus(ev); - value = ev.Scp1344StatusNew; - return ev.IsAllowed; - } + List newInstructions = ListPool.Pool.Get(instructions); - private static void Postfix(Scp1344Item __instance, ref Scp1344Status value) - { - ChangedStatusEventArgs ev = new(Item.Get(__instance), value); - Handlers.Scp1344.OnChangedStatus(ev); + // Declare local variable for ChangingStatusEventArgs + LocalBuilder ev = generator.DeclareLocal(typeof(ChangingStatusEventArgs)); + + // Continue label for isAllowed check + Label continueLabel = generator.DefineLabel(); + + newInstructions.InsertRange(0, new CodeInstruction[] + { + // this.Scp1344Item + new(OpCodes.Ldarg_0), + + // value to be set + new(OpCodes.Ldarg_1), + + // this._status + new(OpCodes.Ldarg_0), + new(OpCodes.Ldfld, Field(typeof(Scp1344Item), nameof(Scp1344Item._status))), + + // true (IsAllowed) + new(OpCodes.Ldc_I4_1), + + // ChangingStatusEventArgs ev = new(this.Item, value, this._status, isallowed) + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangingStatusEventArgs))[0]), + new(OpCodes.Dup), + new(OpCodes.Stloc_S, ev.LocalIndex), + + // Handlers.Scp1344.OnChangingStatus(ev) + new(OpCodes.Call, Method(typeof(Handlers.Scp1344), nameof(Handlers.Scp1344.OnChangingStatus))), + + // if (!ev.IsAllowed) return; + new(OpCodes.Ldloc_S, ev.LocalIndex), + new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingStatusEventArgs), nameof(ChangingStatusEventArgs.IsAllowed))), + new(OpCodes.Brtrue_S, continueLabel), + + // Return; + new(OpCodes.Ret), + + // continue label + new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel), + + // value = ev.Scp1344StatusNew; + new(OpCodes.Ldloc_S, ev.LocalIndex), + new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingStatusEventArgs), nameof(ChangingStatusEventArgs.Scp1344StatusNew))), + new(OpCodes.Starg_S, 1), + }); + + // this.ServerChangeStatus(value) index + MethodInfo changeStatusMethod = Method(typeof(Scp1344Item), nameof(Scp1344Item.ServerChangeStatus)); + int offset = 1; + int index = newInstructions.FindIndex(i => i.opcode == OpCodes.Call && i.operand is MethodInfo method && method == changeStatusMethod) + offset; + + newInstructions.InsertRange(index, new CodeInstruction[] + { + // this.Scp1344Item + new(OpCodes.Ldarg_0), + + // value to be set + new(OpCodes.Ldarg_1), + + // ChangedStatusEventArgs ev = new(this.Item, value) + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangedStatusEventArgs))[0]), + + // Handlers.Scp1344.OnChangedStatus(ev) + new(OpCodes.Call, Method(typeof(Handlers.Scp1344), nameof(Handlers.Scp1344.OnChangedStatus))), + }); + + // Return the new instructions + foreach (CodeInstruction newcode in newInstructions) + yield return newcode; + + ListPool.Pool.Return(newInstructions); } } -} \ No newline at end of file +}