Skip to content

Commit

Permalink
unloading + refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
IRacle1 committed Dec 26, 2024
1 parent 38b409b commit a895412
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,16 @@ public class ReloadingWeaponEventArgs : IPlayerEvent, IFirearmEvent, IDeniableEv
/// <param name="firearm">
/// <inheritdoc cref="Firearm" />
/// </param>
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// </param>
public ReloadingWeaponEventArgs(InventorySystem.Items.Firearms.Firearm firearm, bool isAllowed = true)
public ReloadingWeaponEventArgs(InventorySystem.Items.Firearms.Firearm firearm)
{
Firearm = Item.Get<Firearm>(firearm);
Player = Firearm.Owner;
IsAllowed = isAllowed;
}

/// <summary>
/// Gets or sets a value indicating whether the weapon can be reloaded.
/// </summary>
public bool IsAllowed { get; set; }
public bool IsAllowed { get; set; } = false;

/// <summary>
/// Gets the <see cref="API.Features.Items.Firearm" /> being reloaded.
Expand Down
13 changes: 3 additions & 10 deletions EXILED/Exiled.Events/EventArgs/Player/UnloadingWeaponEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,19 @@ public class UnloadingWeaponEventArgs : IPlayerEvent, IFirearmEvent, IDeniableEv
/// <summary>
/// Initializes a new instance of the <see cref="UnloadingWeaponEventArgs" /> class.
/// </summary>
/// <param name="player">
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="firearm">
/// <inheritdoc cref="Firearm" />
/// </param>
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// </param>
public UnloadingWeaponEventArgs(Player player, Firearm firearm, bool isAllowed = true)
public UnloadingWeaponEventArgs(Firearm firearm)
{
Firearm = firearm;
Player = player;
IsAllowed = isAllowed;
Player = firearm.Owner;
}

/// <summary>
/// Gets or sets a value indicating whether the weapon can be unloaded.
/// </summary>
public bool IsAllowed { get; set; }
public bool IsAllowed { get; set; } = true;

/// <summary>
/// Gets the <see cref="API.Features.Items.Firearm" /> being unloaded.
Expand Down
9 changes: 4 additions & 5 deletions EXILED/Exiled.Events/Patches/Events/Player/ReloadingWeapon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace Exiled.Events.Patches.Events.Player
using System.Reflection.Emit;

using API.Features.Pools;

using Exiled.API.Extensions;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Player;
using HarmonyLib;
Expand All @@ -31,7 +33,7 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

int offset = 2;
int index = newInstructions.FindIndex(x => x.operand == (object)Method(typeof(IReloadUnloadValidatorModule), nameof(IReloadUnloadValidatorModule.ValidateReload))) + offset;
int index = newInstructions.FindIndex(x => x.Calls(Method(typeof(IReloadUnloadValidatorModule), nameof(IReloadUnloadValidatorModule.ValidateReload)))) + offset;

Label skip = (Label)newInstructions[index - 1].operand;
newInstructions.InsertRange(
Expand All @@ -42,10 +44,7 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new CodeInstruction(OpCodes.Ldarg_0),
new(OpCodes.Callvirt, PropertyGetter(typeof(AnimatorReloaderModuleBase), nameof(AnimatorReloaderModuleBase.Firearm))),

// true
new(OpCodes.Ldc_I4_1),

// ReloadingWeaponEventArgs ev = new(firearm, bool)
// ReloadingWeaponEventArgs ev = new(firearm)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ReloadingWeaponEventArgs))[0]),
new(OpCodes.Dup),

Expand Down
66 changes: 66 additions & 0 deletions EXILED/Exiled.Events/Patches/Events/Player/UnloadingWeapon.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// -----------------------------------------------------------------------
// <copyright file="UnloadingWeapon.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.Patches.Events.Player
{
using System.Collections.Generic;
using System.Reflection.Emit;

using API.Features.Pools;

using Exiled.API.Extensions;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Player;
using HarmonyLib;
using InventorySystem.Items.Firearms.Modules;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches <see cref="AnimatorReloaderModuleBase.ServerProcessCmd" />.
/// Adds the <see cref="Handlers.Player.UnloadingWeapon" /> event.
/// </summary>
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.UnloadingWeapon))]
[HarmonyPatch(typeof(AnimatorReloaderModuleBase), nameof(AnimatorReloaderModuleBase.ServerProcessCmd))]
internal static class UnloadingWeapon
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

int offset = 2;
int index = newInstructions.FindIndex(x => x.Calls(Method(typeof(IReloadUnloadValidatorModule), nameof(IReloadUnloadValidatorModule.ValidateUnload)))) + offset;

Label skip = (Label)newInstructions[index - 1].operand;
newInstructions.InsertRange(
index,
new[]
{
// player
new CodeInstruction(OpCodes.Ldarg_0),
new(OpCodes.Callvirt, PropertyGetter(typeof(AnimatorReloaderModuleBase), nameof(AnimatorReloaderModuleBase.Firearm))),

// UnloadingWeaponEventArgs ev = new(firearm)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(UnloadingWeaponEventArgs))[0]),
new(OpCodes.Dup),

// Player.OnUnloadingWeapon(ev)
new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnUnloadingWeapon))),

// if (!ev.IsAllowed)
// goto skip;
new(OpCodes.Callvirt, PropertyGetter(typeof(UnloadingWeaponEventArgs), nameof(UnloadingWeaponEventArgs.IsAllowed))),
new(OpCodes.Brfalse, skip),
});

for (int z = 0; z < newInstructions.Count; z++)
yield return newInstructions[z];

ListPool<CodeInstruction>.Pool.Return(newInstructions);
}
}
}

0 comments on commit a895412

Please sign in to comment.