|
| 1 | +// ----------------------------------------------------------------------- |
| 2 | +// <copyright file="ConsumingItem.cs" company="ExMod Team"> |
| 3 | +// Copyright (c) ExMod Team. All rights reserved. |
| 4 | +// Licensed under the CC BY-SA 3.0 license. |
| 5 | +// </copyright> |
| 6 | +// ----------------------------------------------------------------------- |
| 7 | + |
| 8 | +namespace Exiled.Events.Patches.Events.Player |
| 9 | +{ |
| 10 | + using System.Collections.Generic; |
| 11 | + using System.Reflection.Emit; |
| 12 | + |
| 13 | + using Exiled.API.Features.Pools; |
| 14 | + using Exiled.Events.Attributes; |
| 15 | + using Exiled.Events.EventArgs.Player; |
| 16 | + |
| 17 | + using HarmonyLib; |
| 18 | + |
| 19 | + using InventorySystem.Items.Usables; |
| 20 | + |
| 21 | + using static HarmonyLib.AccessTools; |
| 22 | + |
| 23 | + /// <summary> |
| 24 | + /// Patches <see cref="Consumable.ActivateEffects" />. |
| 25 | + /// Adds the <see cref="Handlers.Player.ConsumingItem" /> event. |
| 26 | + /// </summary> |
| 27 | + [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ConsumingItem))] |
| 28 | + [HarmonyPatch(typeof(Consumable), nameof(Consumable.ActivateEffects))] |
| 29 | + internal static class ConsumingItem |
| 30 | + { |
| 31 | + private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) |
| 32 | + { |
| 33 | + List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions); |
| 34 | + |
| 35 | + Label skip = generator.DefineLabel(); |
| 36 | + |
| 37 | + int offset = -1; |
| 38 | + int index = newInstructions.FindIndex(instruction => instruction.Calls(Method(typeof(Consumable), nameof(Consumable.OnEffectsActivated)))) + offset; |
| 39 | + |
| 40 | + List<Label> mainLabels = newInstructions[index].ExtractLabels(); |
| 41 | + newInstructions[index].WithLabels(skip); |
| 42 | + |
| 43 | + newInstructions.InsertRange(0, new CodeInstruction[] |
| 44 | + { |
| 45 | + // this.Owner; |
| 46 | + new CodeInstruction(OpCodes.Ldarg_0).WithLabels(mainLabels), |
| 47 | + new(OpCodes.Callvirt, PropertyGetter(typeof(Consumable), nameof(Consumable.Owner))), |
| 48 | + |
| 49 | + // this; |
| 50 | + new(OpCodes.Ldarg_0), |
| 51 | + |
| 52 | + // ConsumingItemEventArgs ev = new(this.Owner, this); |
| 53 | + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ConsumingItemEventArgs))[0]), |
| 54 | + new(OpCodes.Dup), |
| 55 | + |
| 56 | + // Player.OnConsumingItem(ev); |
| 57 | + new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnConsumingItem))), |
| 58 | + |
| 59 | + // if (!ev.IsAllowed) |
| 60 | + // this._alreadyActivated = true; |
| 61 | + // return; |
| 62 | + new(OpCodes.Callvirt, PropertyGetter(typeof(ConsumingItemEventArgs), nameof(ConsumingItemEventArgs.IsAllowed))), |
| 63 | + new(OpCodes.Brtrue_S, skip), |
| 64 | + |
| 65 | + new(OpCodes.Ldarg_0), |
| 66 | + new(OpCodes.Ldc_I4_1), |
| 67 | + new(OpCodes.Stfld, Field(typeof(Consumable), nameof(Consumable._alreadyActivated))), |
| 68 | + |
| 69 | + new(OpCodes.Ret), |
| 70 | + }); |
| 71 | + |
| 72 | + for (int z = 0; z < newInstructions.Count; z++) |
| 73 | + yield return newInstructions[z]; |
| 74 | + |
| 75 | + ListPool<CodeInstruction>.Pool.Return(newInstructions); |
| 76 | + } |
| 77 | + } |
| 78 | +} |
0 commit comments