diff --git a/EXILED/Exiled.Events/EventArgs/Scp079/RecontainingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp079/RecontainingEventArgs.cs new file mode 100644 index 000000000..11d88c3f1 --- /dev/null +++ b/EXILED/Exiled.Events/EventArgs/Scp079/RecontainingEventArgs.cs @@ -0,0 +1,42 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.EventArgs.Scp079 +{ + using Exiled.API.Features; + using Exiled.Events.EventArgs.Interfaces; + + /// + /// Contains information before SCP-079 gets recontained. + /// + public class RecontainingEventArgs : IDeniableEvent, IPlayerEvent + { + /// + /// Initializes a new instance of the class. + /// + /// The instance. + public RecontainingEventArgs(BreakableWindow recontainer) + { + Player = Player.Get(recontainer.LastAttacker.Hub); + IsAutomatic = recontainer.LastAttacker.IsSet; + } + + /// + /// Gets the Player that started the recontainment process.

+ /// Can be null if is true. + ///
+ public Player Player { get; } + + /// + public bool IsAllowed { get; set; } = true; + + /// + /// Gets a value indicating whether or not the recontained has been made automatically or by triggering the proccess. + /// + public bool IsAutomatic { get; } + } +} diff --git a/EXILED/Exiled.Events/Handlers/Scp079.cs b/EXILED/Exiled.Events/Handlers/Scp079.cs index 85da2da7e..b272defea 100644 --- a/EXILED/Exiled.Events/Handlers/Scp079.cs +++ b/EXILED/Exiled.Events/Handlers/Scp079.cs @@ -57,6 +57,11 @@ public static class Scp079 /// public static Event ChangingSpeakerStatus { get; set; } = new(); + /// + /// Invoked before SCP-079 recontainment. + /// + public static Event Recontaining { get; set; } = new(); + /// /// Invoked after SCP-079 recontainment. /// @@ -125,6 +130,12 @@ public static class Scp079 /// The instance. public static void OnChangingSpeakerStatus(ChangingSpeakerStatusEventArgs ev) => ChangingSpeakerStatus.InvokeSafely(ev); + /// + /// Called before SCP-079 is recontained. + /// + /// The instance. + public static void OnRecontaining(RecontainingEventArgs ev) => Recontaining.InvokeSafely(ev); + /// /// Called after SCP-079 is recontained. /// diff --git a/EXILED/Exiled.Events/Patches/Events/Scp079/Recontaining.cs b/EXILED/Exiled.Events/Patches/Events/Scp079/Recontaining.cs new file mode 100644 index 000000000..82e924fbc --- /dev/null +++ b/EXILED/Exiled.Events/Patches/Events/Scp079/Recontaining.cs @@ -0,0 +1,67 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.Patches.Events.Scp079 +{ + using System.Collections.Generic; + using System.Reflection.Emit; + + using Exiled.API.Features.Pools; + using Exiled.Events.Attributes; + using Exiled.Events.EventArgs.Scp079; + using Exiled.Events.Handlers; + + using HarmonyLib; + + using PlayerRoles.PlayableScps.Scp079; + + using static HarmonyLib.AccessTools; + + /// + /// Patches . + /// Adds the event. + /// + [EventPatch(typeof(Scp079), nameof(Scp079.Recontaining))] + [HarmonyPatch(typeof(Scp079Recontainer), nameof(Scp079Recontainer.Recontain))] + internal class Recontaining + { + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) + { + int index = 0; + List newInstructions = ListPool.Pool.Get(instructions); + + LocalBuilder ev = generator.DeclareLocal(typeof(RecontainingEventArgs)); + + Label returnLabel = generator.DefineLabel(); + + newInstructions.InsertRange(index, new CodeInstruction[] + { + // RecontainingEventArgs ev = new(this._activatorGlass) + new(OpCodes.Ldarg_0), + new(OpCodes.Ldfld, PropertyGetter(typeof(Scp079Recontainer), nameof(Scp079Recontainer._activatorGlass))), + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(RecontainingEventArgs))[0]), + new(OpCodes.Stloc_S, ev.LocalIndex), + + // Scp079.OnRecontaining(ev) + new(OpCodes.Ldloc_S, ev.LocalIndex), + new(OpCodes.Call, Method(typeof(Scp079), nameof(Scp079.OnRecontaining))), + + // if (!ev.IsAllowed) return; + new(OpCodes.Ldloc_S, ev.LocalIndex), + new(OpCodes.Callvirt, Method(typeof(RecontainingEventArgs), nameof(RecontainingEventArgs.IsAllowed))), + new(OpCodes.Brfalse_S, returnLabel), + }); + + newInstructions[newInstructions.Count - 1].WithLabels(returnLabel); + + for (int z = 0; z < newInstructions.Count; z++) + yield return newInstructions[z]; + + ListPool.Pool.Return(newInstructions); + } + } +}