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

Added the SCP-079 Recontaining event #21

Merged
merged 13 commits into from
Aug 15, 2024
42 changes: 42 additions & 0 deletions EXILED/Exiled.Events/EventArgs/Scp079/RecontainingEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// -----------------------------------------------------------------------
// <copyright file="RecontainingEventArgs.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.EventArgs.Scp079
{
using Exiled.API.Features;
using Exiled.Events.EventArgs.Interfaces;

/// <summary>
/// Contains information before SCP-079 gets recontained.
/// </summary>
public class RecontainingEventArgs : IDeniableEvent

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add IPlayerEvent

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do it tomorrow

louis1706 marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// Initializes a new instance of the <see cref="RecontainingEventArgs" /> class.
/// </summary>
/// <param name="recontainer">The <see cref="BreakableWindow"/> instance.</param>
public RecontainingEventArgs(BreakableWindow recontainer)
{
Recontainer = Player.Get(recontainer.LastAttacker.Hub);
louis1706 marked this conversation as resolved.
Show resolved Hide resolved
IsAutomatic = recontainer.LastAttacker.IsSet;
}

/// <summary>
/// Gets the Player that started the recontainment process.<br></br>
/// Can be null if <see cref="IsAutomatic"/> is true.
/// </summary>
public Player Recontainer { get; }
louis1706 marked this conversation as resolved.
Show resolved Hide resolved

/// <inheritdoc/>
public bool IsAllowed { get; set; } = true;

/// <summary>
/// Gets a value indicating whether or not the recontained has been made automatically or by triggering the proccess.
/// </summary>
public bool IsAutomatic { get; }
}
}
11 changes: 11 additions & 0 deletions EXILED/Exiled.Events/Handlers/Scp079.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public static class Scp079
/// </summary>
public static Event<ChangingSpeakerStatusEventArgs> ChangingSpeakerStatus { get; set; } = new();

/// <summary>
/// Invoked before SCP-079 recontainment.
/// </summary>
public static Event<RecontainingEventArgs> Recontaining { get; set; } = new();

/// <summary>
/// Invoked after SCP-079 recontainment.
/// </summary>
Expand Down Expand Up @@ -125,6 +130,12 @@ public static class Scp079
/// <param name="ev">The <see cref="ChangingSpeakerStatusEventArgs" /> instance.</param>
public static void OnChangingSpeakerStatus(ChangingSpeakerStatusEventArgs ev) => ChangingSpeakerStatus.InvokeSafely(ev);

/// <summary>
/// Called before SCP-079 is recontained.
/// </summary>
/// <param name="ev">The <see cref="RecontainingEventArgs" /> instance.</param>
public static void OnRecontaining(RecontainingEventArgs ev) => Recontaining.InvokeSafely(ev);

/// <summary>
/// Called after SCP-079 is recontained.
/// </summary>
Expand Down
67 changes: 67 additions & 0 deletions EXILED/Exiled.Events/Patches/Events/Scp079/Recontaining.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// -----------------------------------------------------------------------
// <copyright file="Recontaining.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

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;

/// <summary>
/// Patches <see cref="Scp079Recontainer.Recontain" />.
/// Adds the <see cref="Scp079.Recontaining" /> event.
/// </summary>
[EventPatch(typeof(Scp079), nameof(Scp079.Recontaining))]
[HarmonyPatch(typeof(Scp079Recontainer), nameof(Scp079Recontainer.Recontain))]
internal class Recontaining
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
int index = 0;
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.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.Starg_S, ev.LocalIndex),
louis1706 marked this conversation as resolved.
Show resolved Hide resolved

// Scp079.OnRecontaining(ev)
new(OpCodes.Ldarg_S, ev.LocalIndex),
louis1706 marked this conversation as resolved.
Show resolved Hide resolved
new(OpCodes.Call, Method(typeof(Scp079), nameof(Scp079.OnRecontaining))),

// if (!ev.IsAllowed) return;
new(OpCodes.Ldarg_S, ev.LocalIndex),
louis1706 marked this conversation as resolved.
Show resolved Hide resolved
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<CodeInstruction>.Pool.Return(newInstructions);
}
}
}
Loading