Skip to content

Commit

Permalink
Scp3114 Transpiler (#2266)
Browse files Browse the repository at this point in the history
* TryUseBody Transpiler + fix

* Disguising Transpiler

* Revealing + RevealingKey Transpiler

* Fix

* Edit doc

---------

Co-authored-by: Yamato <[email protected]>
  • Loading branch information
BoltonDev and louis1706 authored Dec 18, 2023
1 parent f179203 commit a8f7cea
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 99 deletions.
8 changes: 3 additions & 5 deletions Exiled.Events/EventArgs/Scp3114/DisguisedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ namespace Exiled.Events.EventArgs.Scp3114
using Exiled.API.Features.Roles;
using Interfaces;

using PlayerRoles.Ragdolls;

/// <summary>
/// Contains all information after SCP-3114 disguised.
/// </summary>
Expand All @@ -27,11 +25,11 @@ public class DisguisedEventArgs : IScp3114Event, IRagdollEvent
/// <param name="ragdoll">
/// <inheritdoc cref="Ragdoll" />
/// </param>
public DisguisedEventArgs(ReferenceHub player, DynamicRagdoll ragdoll)
public DisguisedEventArgs(Player player, Ragdoll ragdoll)
{
Player = Player.Get(player);
Player = player;
Scp3114 = Player.Role.As<Scp3114Role>();
Ragdoll = Ragdoll.Get(ragdoll);
Ragdoll = ragdoll;
}

/// <inheritdoc/>
Expand Down
14 changes: 8 additions & 6 deletions Exiled.Events/EventArgs/Scp3114/DisguisingEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ namespace Exiled.Events.EventArgs.Scp3114
using Exiled.API.Features.Roles;
using Interfaces;

using PlayerRoles.Ragdolls;

/// <summary>
/// Contains all information before SCP-3114 disguises to a new role.
/// </summary>
Expand All @@ -27,15 +25,19 @@ public class DisguisingEventArgs : IScp3114Event, IDeniableEvent, IRagdollEvent
/// <param name="ragdoll">
/// <inheritdoc cref="Ragdoll" />
/// </param>
public DisguisingEventArgs(ReferenceHub player, DynamicRagdoll ragdoll)
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// </param>
public DisguisingEventArgs(Player player, Ragdoll ragdoll, bool isAllowed = true)
{
Player = Player.Get(player);
Player = player;
Scp3114 = Player.Role.As<Scp3114Role>();
Ragdoll = Ragdoll.Get(ragdoll);
Ragdoll = ragdoll;
IsAllowed = isAllowed;
}

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

/// <inheritdoc/>
public Player Player { get; }
Expand Down
13 changes: 11 additions & 2 deletions Exiled.Events/EventArgs/Scp3114/RevealedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,25 @@ public class RevealedEventArgs : IScp3114Event
/// <param name="player">
/// <inheritdoc cref="Player" />
/// </param>
public RevealedEventArgs(ReferenceHub player)
/// <param name="isManualReveal">
/// <inheritdoc cref="IsManualReveal" />
/// </param>
public RevealedEventArgs(Player player, bool isManualReveal)
{
Player = Player.Get(player);
Player = player;
Scp3114 = Player.Role.As<Scp3114Role>();
IsManualReveal = isManualReveal;
}

/// <inheritdoc/>
public Player Player { get; }

/// <inheritdoc/>
public Scp3114Role Scp3114 { get; }

/// <summary>
/// Gets a value indicating whether the reveal is manual or not.
/// </summary>
public bool IsManualReveal { get; }
}
}
13 changes: 11 additions & 2 deletions Exiled.Events/EventArgs/Scp3114/RevealingEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ public class RevealingEventArgs : IScp3114Event, IDeniableEvent
/// <param name="player">
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="isManualReveal">
/// <inheritdoc cref="IsManualReveal" />
/// </param>
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// </param>
public RevealingEventArgs(ReferenceHub player, bool isAllowed = true)
public RevealingEventArgs(Player player, bool isManualReveal, bool isAllowed = true)
{
Player = Player.Get(player);
Player = player;
Scp3114 = Player.Role.As<Scp3114Role>();
IsManualReveal = isManualReveal;
IsAllowed = isAllowed;
}

Expand All @@ -40,5 +44,10 @@ public RevealingEventArgs(ReferenceHub player, bool isAllowed = true)

/// <inheritdoc/>
public Scp3114Role Scp3114 { get; }

/// <summary>
/// Gets a value indicating whether the reveal is manual or not.
/// </summary>
public bool IsManualReveal { get; }
}
}
7 changes: 3 additions & 4 deletions Exiled.Events/EventArgs/Scp3114/TryUseBodyEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace Exiled.Events.EventArgs.Scp3114
using API.Features;
using Exiled.API.Features.Roles;
using Interfaces;
using PlayerRoles.Ragdolls;

/// <summary>
/// Contains all information before SCP-3114 tries to use a body.
Expand All @@ -29,11 +28,11 @@ public class TryUseBodyEventArgs : IScp3114Event, IDeniableEvent, IRagdollEvent
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// </param>
public TryUseBodyEventArgs(ReferenceHub player, BasicRagdoll ragdoll, bool isAllowed = true)
public TryUseBodyEventArgs(Player player, Ragdoll ragdoll, bool isAllowed = true)
{
Player = Player.Get(player);
Player = player;
Scp3114 = Player.Role.As<Scp3114Role>();
Ragdoll = Ragdoll.Get(ragdoll);
Ragdoll = ragdoll;
IsAllowed = isAllowed;
}

Expand Down
12 changes: 6 additions & 6 deletions Exiled.Events/EventArgs/Scp3114/VoiceLinesEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ namespace Exiled.Events.EventArgs.Scp3114
using static PlayerRoles.PlayableScps.Scp3114.Scp3114VoiceLines;

/// <summary>
/// Contains all information prior to sending voiceline SCP-3114.
/// Contains all information prior to sending voiceline SCP-3114.
/// </summary>
public class VoiceLinesEventArgs : IScp3114Event, IDeniableEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="VoiceLinesEventArgs" /> class.
/// Initializes a new instance of the <see cref="VoiceLinesEventArgs" /> class.
/// </summary>
/// <param name="player">
/// <inheritdoc cref="Player" />
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="voiceLine">
/// <inheritdoc cref="VoiceLine" />
/// <inheritdoc cref="VoiceLine" />
/// </param>
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// <inheritdoc cref="IsAllowed" />
/// </param>
public VoiceLinesEventArgs(ReferenceHub player, VoiceLinesDefinition voiceLine, bool isAllowed = true)
{
Expand All @@ -45,7 +45,7 @@ public VoiceLinesEventArgs(ReferenceHub player, VoiceLinesDefinition voiceLine,
public Scp3114Role Scp3114 { get; }

/// <summary>
/// Gets or sets the <see cref="VoiceLinesDefinition" />.
/// Gets or sets the <see cref="VoiceLinesDefinition" />.
/// </summary>
public VoiceLinesDefinition VoiceLine { get; set; }

Expand Down
82 changes: 66 additions & 16 deletions Exiled.Events/Patches/Events/Scp3114/Disguising.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@

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

using Exiled.API.Features.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Scp3114;
using Exiled.Events.Handlers;

#pragma warning disable SA1313 // Parameter names should begin with lower-case letter

using HarmonyLib;
using Mirror;

using PlayerRoles.PlayableScps.Scp3114;
using PlayerRoles.PlayableScps.Subroutines;
using PlayerRoles.Ragdolls;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches <see cref="Scp3114Disguise.ServerComplete()" />.
/// Adds the <see cref="Scp3114.Disguising" /> and <see cref="Scp3114.Disguised" /> events.
Expand All @@ -28,24 +31,71 @@ namespace Exiled.Events.Patches.Events.Scp3114
[HarmonyPatch(typeof(Scp3114Disguise), nameof(Scp3114Disguise.ServerComplete))]
internal class Disguising
{
private static bool Prefix(Scp3114Disguise __instance)
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
if (__instance.CurRagdoll != null && __instance.CurRagdoll is DynamicRagdoll ragdoll)
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label retLabel = generator.DefineLabel();

LocalBuilder player = generator.DeclareLocal(typeof(API.Features.Player));
LocalBuilder ragdoll = generator.DeclareLocal(typeof(API.Features.Ragdoll));

newInstructions.InsertRange(0, new CodeInstruction[]
{
DisguisingEventArgs disguising = new(__instance.Owner, ragdoll);
Scp3114.OnDisguising(disguising);
// Player.Get(this.Owner);
new(OpCodes.Ldarg_0),
new(OpCodes.Callvirt, PropertyGetter(typeof(Scp3114Disguise), nameof(Scp3114Disguise.Owner))),
new(OpCodes.Call, Method(typeof(API.Features.Player), nameof(API.Features.Player.Get), new[] { typeof(ReferenceHub) })),
new(OpCodes.Dup),
new(OpCodes.Stloc_S, player.LocalIndex),

// Ragdoll.Get(this.CurRagdoll);
new(OpCodes.Ldarg_0),
new(OpCodes.Callvirt, PropertyGetter(typeof(Scp3114Disguise), nameof(Scp3114Disguise.CurRagdoll))),
new(OpCodes.Call, Method(typeof(API.Features.Ragdoll), nameof(API.Features.Ragdoll.Get), new[] { typeof(BasicRagdoll) })),
new(OpCodes.Dup),
new(OpCodes.Stloc_S, ragdoll.LocalIndex),

// true
new(OpCodes.Ldc_I4_1),

// DisguisingEventArgs ev = new DisguisingEventArgs(Player, Ragdoll, bool)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(DisguisingEventArgs))[0]),
new(OpCodes.Dup),

// Handlers.Scp3114.OnDisguising(ev);
new(OpCodes.Call, Method(typeof(Handlers.Scp3114), nameof(Handlers.Scp3114.OnDisguising))),

// if (!ev.IsAllowed)
// return;
new(OpCodes.Callvirt, PropertyGetter(typeof(TryUseBodyEventArgs), nameof(TryUseBodyEventArgs.IsAllowed))),
new(OpCodes.Brfalse_S, retLabel),
});

const int offset = 0;
int index = newInstructions.FindLastIndex(instruction => instruction.opcode == OpCodes.Ret) + offset;

newInstructions.InsertRange(index, new CodeInstruction[]
{
// player
new(OpCodes.Ldloc_S, player.LocalIndex),

// ragdoll
new(OpCodes.Ldloc_S, ragdoll.LocalIndex),

// DisguisedEventArgs ev = new DisguisedEventArgs(Player, Ragdoll);
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(DisguisedEventArgs))[0]),

if (!disguising.IsAllowed)
return false;
// Handlers.Scp3114.OnDisguised(ev);
new(OpCodes.Call, Method(typeof(Handlers.Scp3114), nameof(Handlers.Scp3114.OnDisguised))),
});

__instance.CastRole.Disguised = true;
Scp3114RagdollToBonesConverter.ServerConvertNew(__instance.CastRole, ragdoll);
newInstructions[newInstructions.Count - 1].WithLabels(retLabel);

DisguisedEventArgs disguised = new(__instance.Owner, ragdoll);
Scp3114.OnDisguised(disguised);
}
for (int z = 0; z < newInstructions.Count; z++)
yield return newInstructions[z];

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

0 comments on commit a8f7cea

Please sign in to comment.