Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements more patches for RemovingHandcuffs event and adding RemovedHandcuffs event #3

Merged
merged 6 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
12 changes: 6 additions & 6 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,27 @@ Scripts: # Add the 'Scripts' label

regarding-events: # Add the 'Events' label
- changed-files:
- any-glob-to-any-file: Exiled.Events/** # Any Modifications to events
- any-glob-to-any-file: EXILED/Exiled.Events/** # Any Modifications to events

regarding-api: # Add the 'API' label
- changed-files:
- any-glob-to-any-file: Exiled.API/** # Any modifications to the API
- any-glob-to-any-file: EXILED/Exiled.API/** # Any modifications to the API

regarding-transpiler: # Add the 'transpiler' label
- changed-files:
- any-glob-to-any-file: Exiled.Events/Patches/**/* # Any modifications to transpiler files
- any-glob-to-any-file: EXILED/Exiled.Events/Patches/**/* # Any modifications to transpiler files

CustomModules: # Add the 'CustomModules' label
- changed-files:
- any-glob-to-any-file: Exiled.CustomModules/** # Any modifications to CustomModules
- any-glob-to-any-file: EXILED/Exiled.CustomModules/** # Any modifications to CustomModules

Installer: # Add the 'Installer' label
- changed-files:
- any-glob-to-any-file: Exiled.Installer/** # Any modifications to the Installer
- any-glob-to-any-file: EXILED/Exiled.Installer/** # Any modifications to the Installer

Localization: # Add the 'Localization' label
- changed-files:
- any-glob-to-any-file: Localization/** # Any modifications to Localization
- any-glob-to-any-file: EXILED/Localization/** # Any modifications to Localization

GitHub_Actions: # Add the 'GitHub' label
- changed-files:
Expand Down
30 changes: 30 additions & 0 deletions EXILED/Exiled.API/Enums/UncuffReason.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// -----------------------------------------------------------------------
// <copyright file="UncuffReason.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.API.Enums
{
/// <summary>
/// Reasons that player gets uncuffed.
/// </summary>
public enum UncuffReason
{
/// <summary>
/// Uncuffed by a player.
/// </summary>
Player,

/// <summary>
/// Uncuffed due to the distance between cuffer and target.
/// </summary>
OutOfRange,

/// <summary>
/// Uncuffed due to the cuffer no longer alive.
/// </summary>
CufferDied,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Exiled.Events.EventArgs.Player
{
using API.Enums;
using API.Features;
using Exiled.Events.EventArgs.Interfaces;

Expand All @@ -20,11 +21,13 @@ public class RemovingHandcuffsEventArgs : IPlayerEvent, IDeniableEvent
/// </summary>
/// <param name="cuffer">The cuffer player.</param>
/// <param name="target">The target player to be uncuffed.</param>
/// <param name="uncuffReason">The reason of removing handcuffs.</param>
/// <param name="isAllowed">Indicates whether the event can be executed or not.</param>
public RemovingHandcuffsEventArgs(Player cuffer, Player target, bool isAllowed = true)
public RemovingHandcuffsEventArgs(Player cuffer, Player target, UncuffReason uncuffReason, bool isAllowed = true)
{
Player = cuffer;
Target = target;
UncuffReason = uncuffReason;
IsAllowed = isAllowed;
}

Expand All @@ -42,5 +45,10 @@ public RemovingHandcuffsEventArgs(Player cuffer, Player target, bool isAllowed =
/// Gets the cuffer player.
/// </summary>
public Player Player { get; }

/// <summary>
/// Gets the reason of removing handcuffs.
/// </summary>
public UncuffReason UncuffReason { get; }
}
}
133 changes: 132 additions & 1 deletion EXILED/Exiled.Events/Patches/Events/Player/ProcessDisarmMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Exiled.Events.Patches.Events.Player
{
#pragma warning disable SA1402 // File may only contain a single type
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
Expand Down Expand Up @@ -55,10 +56,13 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new(OpCodes.Ldfld, Field(typeof(DisarmMessage), nameof(DisarmMessage.PlayerToDisarm))),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// UncuffReason.Player
new(OpCodes.Ldc_I4_0),

// true
new(OpCodes.Ldc_I4_1),

// RemovingHandcuffsEventArgs ev = new(Player, Player, true)
// RemovingHandcuffsEventArgs ev = new(Player, Player, UncuffReason.Player, true)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(RemovingHandcuffsEventArgs))[0]),
new(OpCodes.Dup),

Expand Down Expand Up @@ -112,4 +116,131 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
ListPool<CodeInstruction>.Pool.Return(newInstructions);
}
}

/// <summary>
/// Patches <see cref="DisarmedPlayers.ValidateEntry(DisarmedPlayers.DisarmedEntry)" />.
/// Invokes <see cref="Handlers.Player.RemovingHandcuffs" /> event.
/// </summary>
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.RemovingHandcuffs))]
[HarmonyPatch(typeof(DisarmedPlayers), nameof(DisarmedPlayers.ValidateEntry))]
internal static class Uncuff
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);
Label returnLabel = generator.DefineLabel();

int offset = 2;
int index = newInstructions.FindLastIndex(
instruction => instruction.Calls(Method(typeof(ReferenceHub), nameof(ReferenceHub.TryGetHubNetID)))) + offset;

newInstructions.InsertRange(
index,
new[]
{
// Player.Get(Cuffer)
new CodeInstruction(OpCodes.Ldloc_1),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// Player.Get(Target)
new(OpCodes.Ldloc_0),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// UncuffReason.CufferDied
new(OpCodes.Ldc_I4_2),

// true
new(OpCodes.Ldc_I4_1),

// RemovingHandcuffsEventArgs ev = new(Cuffer, Target, UncuffReason.CufferDied, true)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(RemovingHandcuffsEventArgs))[0]),
new(OpCodes.Dup),

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

// if (!ev.IsAllowed)
// return true;
new(OpCodes.Callvirt, PropertyGetter(typeof(RemovingHandcuffsEventArgs), nameof(RemovingHandcuffsEventArgs.IsAllowed))),
new(OpCodes.Brfalse_S, returnLabel),
});

offset = 5;
index = newInstructions.FindLastIndex(
instruction => instruction.Calls(PropertyGetter(typeof(PlayerRoles.PlayerRoleManager), nameof(PlayerRoles.PlayerRoleManager.CurrentRole)))) + offset;

newInstructions.InsertRange(
index,
new[]
{
// Player.Get(Cuffer)
new CodeInstruction(OpCodes.Ldloc_1),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// Player.Get(Target)
new(OpCodes.Ldloc_0),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// UncuffReason.CufferDied
new(OpCodes.Ldc_I4_2),

// true
new(OpCodes.Ldc_I4_1),

// RemovingHandcuffsEventArgs ev = new(Cuffer, Target, UncuffReason.CufferDied, true)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(RemovingHandcuffsEventArgs))[0]),
new(OpCodes.Dup),

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

// if (!ev.IsAllowed)
// return true;
new(OpCodes.Callvirt, PropertyGetter(typeof(RemovingHandcuffsEventArgs), nameof(RemovingHandcuffsEventArgs.IsAllowed))),
new(OpCodes.Brfalse_S, returnLabel),
});

offset = 3;
index = newInstructions.FindLastIndex(
instruction => instruction.Calls(PropertyGetter(typeof(UnityEngine.Vector3), nameof(UnityEngine.Vector3.sqrMagnitude)))) + offset;

newInstructions.InsertRange(
index,
new[]
{
// Player.Get(Cuffer)
new CodeInstruction(OpCodes.Ldloc_1),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// Player.Get(Target)
new(OpCodes.Ldloc_0),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// UncuffReason.OutOfRange
new(OpCodes.Ldc_I4_1),

// true
new(OpCodes.Ldc_I4_1),

// RemovingHandcuffsEventArgs ev = new(Cuffer, Target, UncuffReason.OutOfRange, true)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(RemovingHandcuffsEventArgs))[0]),
new(OpCodes.Dup),

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

// if (!ev.IsAllowed)
// return true;
new(OpCodes.Callvirt, PropertyGetter(typeof(RemovingHandcuffsEventArgs), nameof(RemovingHandcuffsEventArgs.IsAllowed))),
new(OpCodes.Brfalse_S, returnLabel),
});

newInstructions[newInstructions.Count - 2].labels.Add(returnLabel);

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

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