Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
Expand All @@ -21,11 +25,10 @@ public class ChangedStatusEventArgs : IScp1344Event, IPlayerEvent, IDeniableEven
/// </summary>
/// <param name="item"><inheritdoc cref="Item"/></param>
/// <param name="scp1344Status"><inheritdoc cref="InventorySystem.Items.Usables.Scp1344.Scp1344Status"/></param>
public ChangedStatusEventArgs(Item item, Scp1344Status scp1344Status)
public ChangedStatusEventArgs(ItemBase item, Scp1344Status scp1344Status)
{
Item = item;
Scp1344 = item as Scp1344;
Player = item.Owner;
Scp1344 = Item.Get<Scp1344>(item);
Player = Scp1344.Owner;
Scp1344Status = scp1344Status;
}

Expand All @@ -37,7 +40,7 @@ public ChangedStatusEventArgs(Item item, Scp1344Status scp1344Status)
/// <summary>
/// Gets the item.
/// </summary>
public Item Item { get; }
public Item Item => Scp1344;

/// <summary>
/// Gets the player in owner of the item.
Expand All @@ -50,6 +53,7 @@ public ChangedStatusEventArgs(Item item, Scp1344Status scp1344Status)
public Scp1344 Scp1344 { get; }

/// <inheritdoc/>
[Obsolete("Please use ChangingStatusEventArgs::IsAllowed instead of this", true)]
public bool IsAllowed { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
Expand All @@ -23,11 +24,10 @@ public class ChangingStatusEventArgs : IPlayerEvent, IScp1344Event, IDeniableEve
/// <param name="scp1344StatusNew"><inheritdoc cref="Scp1344StatusNew"/></param>
/// <param name="scp1344StatusOld"><inheritdoc cref="Scp1344StatusOld"/></param>
/// <param name="isAllowed"><inheritdoc cref="IsAllowed"/></param>
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<Scp1344>(item);
Player = Scp1344.Owner;
Scp1344StatusNew = scp1344StatusNew;
Scp1344StatusOld = scp1344StatusOld;
IsAllowed = isAllowed;
Expand All @@ -46,7 +46,7 @@ public ChangingStatusEventArgs(Item item, Scp1344Status scp1344StatusNew, Scp134
/// <summary>
/// Gets the item.
/// </summary>
public Item Item { get; }
public Item Item => Scp1344;

/// <summary>
/// Gets the player in owner of the item.
Expand Down
97 changes: 83 additions & 14 deletions EXILED/Exiled.Events/Patches/Events/Scp1344/Status.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@
// </copyright>
// -----------------------------------------------------------------------

#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;

/// <summary>
/// Patches <see cref="Scp1344Item.Status"/>.
/// Adds the <see cref="Handlers.Scp1344.ChangingStatus" /> event and
Expand All @@ -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<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
ChangingStatusEventArgs ev = new(Item.Get(__instance), value, __instance._status);
Handlers.Scp1344.OnChangingStatus(ev);
value = ev.Scp1344StatusNew;
return ev.IsAllowed;
}
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.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<CodeInstruction>.Pool.Return(newInstructions);
}
}
}
}