diff --git a/EXILED/Exiled.Events/EventArgs/Server/UnbannedEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/UnbannedEventArgs.cs new file mode 100644 index 0000000000..f1181a3b9e --- /dev/null +++ b/EXILED/Exiled.Events/EventArgs/Server/UnbannedEventArgs.cs @@ -0,0 +1,36 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.EventArgs.Server +{ + /// + /// Contains all information after a player gets unbanned. + /// + public class UnbannedEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// + /// + public UnbannedEventArgs(string details, BanHandler.BanType banType) + { + BanDetails = BanHandler.ProcessBanItem(details, banType); + BanType = banType; + } + + /// + /// Gets the ban details. + /// + public BanDetails BanDetails { get; } + + /// + /// Gets the ban type. + /// + public BanHandler.BanType BanType { get; } + } +} \ No newline at end of file diff --git a/EXILED/Exiled.Events/EventArgs/Server/UnbanningEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/UnbanningEventArgs.cs new file mode 100644 index 0000000000..aa23690e63 --- /dev/null +++ b/EXILED/Exiled.Events/EventArgs/Server/UnbanningEventArgs.cs @@ -0,0 +1,43 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.EventArgs.Server +{ + using Exiled.Events.EventArgs.Interfaces; + + /// + /// Contains all information before player is unbanned. + /// + public class UnbanningEventArgs : IDeniableEvent + { + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + public UnbanningEventArgs(string banDetails, BanHandler.BanType banType, bool isAllowed = true) + { + BanDetails = BanHandler.ProcessBanItem(banDetails, banType); + BanType = banType; + IsAllowed = isAllowed; + } + + /// + /// Gets or sets the ban details. + /// + public BanDetails BanDetails { get; set; } + + /// + /// Gets the ban type. + /// + public BanHandler.BanType BanType { get; } + + /// + public bool IsAllowed { get; set; } + } +} \ No newline at end of file diff --git a/EXILED/Exiled.Events/Handlers/Server.cs b/EXILED/Exiled.Events/Handlers/Server.cs index 75be4d81cd..3f5b71e63e 100644 --- a/EXILED/Exiled.Events/Handlers/Server.cs +++ b/EXILED/Exiled.Events/Handlers/Server.cs @@ -111,6 +111,16 @@ public static class Server /// public static Event ReloadedPermissions { get; set; } = new(); + /// + /// Invoked before player is being unbanned. + /// + public static Event Unbanning { get; set; } = new(); + + /// + /// Invoked after player is being unbanned. + /// + public static Event Unbanned { get; set; } = new(); + /// /// Called before waiting for players. /// @@ -210,5 +220,17 @@ public static class Server /// /// The instance. public static void OnSelectingRespawnTeam(SelectingRespawnTeamEventArgs ev) => SelectingRespawnTeam.InvokeSafely(ev); + + /// + /// Called before player is being unbanned. + /// + /// The instance. + public static void OnUnbanning(UnbanningEventArgs ev) => Unbanning.InvokeSafely(ev); + + /// + /// Called after player is being unbanned. + /// + /// The instance. + public static void OnUnbanned(UnbannedEventArgs ev) => Unbanned.InvokeSafely(ev); } } \ No newline at end of file diff --git a/EXILED/Exiled.Events/Patches/Events/Server/Unban.cs b/EXILED/Exiled.Events/Patches/Events/Server/Unban.cs new file mode 100644 index 0000000000..5eb89d224e --- /dev/null +++ b/EXILED/Exiled.Events/Patches/Events/Server/Unban.cs @@ -0,0 +1,92 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.Patches.Events.Server +{ + using System.Collections.Generic; + using System.Reflection.Emit; + + using Exiled.API.Features.Pools; + using Exiled.Events.Attributes; + using Exiled.Events.EventArgs.Server; + using HarmonyLib; + + using static HarmonyLib.AccessTools; + + /// + /// Patches + /// to add and events. + /// + [HarmonyPatch(typeof(BanHandler), nameof(BanHandler.RemoveBan))] + [EventPatch(typeof(Handlers.Server), nameof(Handlers.Server.Unbanning))] + [EventPatch(typeof(Handlers.Server), nameof(Handlers.Server.Unbanned))] + internal class Unban + { + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) + { + List newInstructions = ListPool.Pool.Get(instructions); + + LocalBuilder ev = generator.DeclareLocal(typeof(UnbanningEventArgs)); + + Label continueLabel = generator.DefineLabel(); + + newInstructions.InsertRange(0, new CodeInstruction[] + { + // id + new(OpCodes.Ldarg_0), + + // type + new(OpCodes.Ldarg_1), + + // true + new(OpCodes.Ldc_I4_1), + + // UnbanningEventArgs ev = new(string, BanHandler.BanType, true); + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(UnbanningEventArgs))[0]), + new(OpCodes.Dup), + new(OpCodes.Dup), + new(OpCodes.Stloc_S, ev.LocalIndex), + + // Handlers.Server.OnUnbanning(ev); + new(OpCodes.Call, Method(typeof(Handlers.Server), nameof(Handlers.Server.OnUnbanning))), + + // if (!ev.IsAllowed) + // return; + new(OpCodes.Callvirt, PropertyGetter(typeof(UnbanningEventArgs), nameof(UnbanningEventArgs.IsAllowed))), + new(OpCodes.Brtrue_S, continueLabel), + + new(OpCodes.Ret), + + // id = ev.BanDetails.ToString(); + new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex).WithLabels(continueLabel), + new(OpCodes.Callvirt, PropertyGetter(typeof(UnbanningEventArgs), nameof(UnbanningEventArgs.BanDetails))), + new(OpCodes.Call, Method(typeof(BanDetails), nameof(BanDetails.ToString))), + new(OpCodes.Starg_S, 1), + }); + + newInstructions.InsertRange(newInstructions.Count - 1, new CodeInstruction[] + { + // id + new(OpCodes.Ldarg_0), + + // type + new(OpCodes.Ldarg_1), + + // UnbannedEventArgs ev2 = new(string, BanHandler.BanType); + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(UnbannedEventArgs))[0]), + + // Handlers.Server.OnUnbanned(ev2); + new(OpCodes.Call, Method(typeof(Handlers.Server), nameof(Handlers.Server.OnUnbanned))), + }); + + for (int z = 0; z < newInstructions.Count; z++) + yield return newInstructions[z]; + + ListPool.Pool.Return(newInstructions); + } + } +} \ No newline at end of file