Skip to content

Commit

Permalink
Merge branch 'refs/heads/scp244spawning-transpiler' into feat/scp244-…
Browse files Browse the repository at this point in the history
…spawning-event

# Conflicts:
#	Exiled.Events/Handlers/Map.cs
  • Loading branch information
BoltonDev committed Jun 2, 2024
2 parents 68b8acb + 07015dd commit d7680b5
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
49 changes: 49 additions & 0 deletions Exiled.Events/EventArgs/Map/Scp244SpawningEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// -----------------------------------------------------------------------
// <copyright file="Scp244SpawningEventArgs.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.Map
{
using API.Features;
using Exiled.API.Features.Pickups;
using Interfaces;

/// <summary>
/// Contains all information up to spawning Scp244.
/// </summary>
public class Scp244SpawningEventArgs : IRoomEvent, IDeniableEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="Scp244SpawningEventArgs" /> class.
/// </summary>
/// <param name="room">
/// <inheritdoc cref="Room" />
/// </param>
/// <param name="scp244Pickup">
/// <inheritdoc cref="Pickup" />
/// </param>
public Scp244SpawningEventArgs(Room room, Pickup scp244Pickup)
{
Room = room;
Pickup = scp244Pickup.As<Scp244Pickup>();
}

/// <summary>
/// Gets the room in which the Pickup will be spawning.
/// </summary>
public Room Room { get; }

/// <summary>
/// Gets a value indicating the pickup being spawning.
/// </summary>
public Scp244Pickup Pickup { get; }

/// <summary>
/// Gets or sets a value indicating whether or not the item can be spawning.
/// </summary>
public bool IsAllowed { get; set; } = true;
}
}
11 changes: 11 additions & 0 deletions Exiled.Events/Handlers/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ public static class Map
/// </summary>
public static Event<SpawningTeamVehicleEventArgs> SpawningTeamVehicle { get; set; } = new();

/// <summary>
/// Called before spawning Scp244.
/// </summary>
public static Event<Scp244SpawningEventArgs> Scp244Spawning { get; set; } = new();

/// <summary>
/// Called before dealing damage to the door.
/// </summary>
Expand Down Expand Up @@ -254,6 +259,12 @@ public static class Map
/// <param name="ev">The <see cref="DamagingDoorEventArgs"/> instance.</param>
public static void OnDoorDamaging(DamagingDoorEventArgs ev) => DoorDamaging.InvokeSafely(ev);

/// <summary>
/// Called before spawning Scp244.
/// </summary>
/// <param name="ev">The <see cref="Scp244SpawningEventArgs"/> instance.</param>
public static void OnScp244Spawning(Scp244SpawningEventArgs ev) => Scp244Spawning.InvokeSafely(ev);

/// <summary>
/// Called before an item is dropped in the pocket dimension.
/// </summary>
Expand Down
90 changes: 90 additions & 0 deletions Exiled.Events/Patches/Events/Map/Scp244Spawning.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// -----------------------------------------------------------------------
// <copyright file="Scp244Spawning.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.Map
{
using System.Collections.Generic;
using System.Reflection.Emit;

using Exiled.API.Features.Core.Generic.Pools;
using Exiled.API.Features.Pickups;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Map;
using MapGeneration;
using UnityEngine;

#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
using HarmonyLib;
using InventorySystem.Items.Pickups;
using InventorySystem.Items.Usables.Scp244;
using Mirror;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches <see cref="Scp244Spawner.SpawnScp244" />.
/// Adds the <see cref="Handlers.Map.Scp244Spawning" /> event.
/// </summary>
[EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.Scp244Spawning))]
[HarmonyPatch(typeof(Scp244Spawner), nameof(Scp244Spawner.SpawnScp244))]
internal static class Scp244Spawning
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label continueLabel = generator.DefineLabel();

LocalBuilder pickup = generator.DeclareLocal(typeof(ItemPickupBase));

int index = newInstructions.FindLastIndex(i => i.opcode == OpCodes.Dup);

newInstructions.RemoveRange(index, 1);

int offset = 1;
index = newInstructions.FindIndex(i => i.opcode == OpCodes.Dup) + offset;
newInstructions.InsertRange(index, new CodeInstruction[]
{
new(OpCodes.Dup),
new(OpCodes.Stloc_S, pickup.LocalIndex),
});

offset = -2;
index = newInstructions.FindIndex(i => i.Calls(Method(typeof(NetworkServer), nameof(NetworkServer.Spawn), new[] { typeof(GameObject), typeof(NetworkConnection) }))) + offset;

newInstructions.InsertRange(index, new[]
{
new CodeInstruction(OpCodes.Ldsfld, Field(typeof(Scp244Spawner), nameof(Scp244Spawner.CompatibleRooms))).MoveLabelsFrom(newInstructions[index]),
new(OpCodes.Ldloc_0),
new(OpCodes.Callvirt, PropertyGetter(typeof(List<RoomIdentifier>), "Item")),

new(OpCodes.Ldloc_S, pickup.LocalIndex),
new(OpCodes.Call, Method(typeof(Pickup), nameof(Pickup.Get), new[] { typeof(ItemPickupBase) })),

new(OpCodes.Newobj, GetDeclaredConstructors(typeof(Scp244SpawningEventArgs))[0]),
new(OpCodes.Dup),
new(OpCodes.Call, Method(typeof(Handlers.Map), nameof(Handlers.Map.OnScp244Spawning))),

new(OpCodes.Call, PropertyGetter(typeof(Scp244SpawningEventArgs), nameof(Scp244SpawningEventArgs.IsAllowed))),
new(OpCodes.Brtrue_S, continueLabel),

new(OpCodes.Ldloc_S, pickup.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(ItemPickupBase), nameof(ItemPickupBase.gameObject))),
new(OpCodes.Call, Method(typeof(NetworkServer), nameof(NetworkServer.Destroy))),
new(OpCodes.Ret),

new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel),
new(OpCodes.Ldloc_S, pickup.LocalIndex),
});

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

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

0 comments on commit d7680b5

Please sign in to comment.