Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// -----------------------------------------------------------------------
// <copyright file="SpawningRoomConnectorEventArgs.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.EventArgs.Map
{
using Exiled.Events.EventArgs.Interfaces;
using MapGeneration.RoomConnectors;

/// <summary>
/// Contains all information before spawning the connector between rooms.
/// </summary>
public class SpawningRoomConnectorEventArgs : IDeniableEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="SpawningRoomConnectorEventArgs" /> class.
/// </summary>
/// <param name="connectorType">The connector type the game is trying to spawn.</param>
public SpawningRoomConnectorEventArgs(SpawnableRoomConnectorType connectorType)
{
ConnectorType = connectorType;
}

/// <summary>
/// Gets or sets which Connector the game should spawn.
/// </summary>
public SpawnableRoomConnectorType ConnectorType { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the connector can be spawned.
/// </summary>
public bool IsAllowed { get; set; } = true;
}
}
11 changes: 11 additions & 0 deletions EXILED/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<PickupDestroyedEventArgs> PickupDestroyed { get; set; } = new();

/// <summary>
/// Invoked before a room connector spawns.
/// </summary>
public static Event<SpawningRoomConnectorEventArgs> SpawningRoomConnector { get; set; } = new();

/// <summary>
/// Invoked before a team vehicle is spawned.
/// </summary>
Expand Down Expand Up @@ -221,6 +226,12 @@ public static class Map
/// <param name="ev">The <see cref="PickupDestroyedEventArgs"/> instance.</param>
public static void OnPickupDestroyed(PickupDestroyedEventArgs ev) => PickupDestroyed.InvokeSafely(ev);

/// <summary>
/// Invoked before a room connector spawns.
/// </summary>
/// <param name="ev">The <see cref="SpawningRoomConnectorEventArgs"/> instance.</param>
public static void OnSpawningRoomConnector(SpawningRoomConnectorEventArgs ev) => SpawningRoomConnector.InvokeSafely(ev);

/// <summary>
/// Invoked before a team vehicle is spawned.
/// </summary>
Expand Down
70 changes: 70 additions & 0 deletions EXILED/Exiled.Events/Patches/Events/Map/SpawningRoomConnector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// -----------------------------------------------------------------------
// <copyright file="SpawningRoomConnector.cs" company="ExMod Team">
// Copyright (c) ExMod 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.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Map;
using HarmonyLib;
using MapGeneration.RoomConnectors;
using Respawning;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patches <see cref="RoomConnectorDistributorSettings.TryGetTemplate"/>.
/// Adds the <see cref="Handlers.Map.OnSpawningRoomConnector"/> event.
/// </summary>
[EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.SpawningRoomConnector))]
[HarmonyPatch(typeof(RoomConnectorDistributorSettings), nameof(RoomConnectorDistributorSettings.TryGetTemplate))]
internal static class SpawningRoomConnector
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);
LocalBuilder ev = generator.DeclareLocal(typeof(SpawningRoomConnectorEventArgs));

Label retLabel = generator.DefineLabel();

newInstructions.InsertRange(0, new[]
{
// type
new CodeInstruction(OpCodes.Ldarg_0),

// SpawningRoomConnectorEventArgs ev = new SpawningRoomConnectorEventArgs(type)
new CodeInstruction(OpCodes.Newobj, AccessTools.Constructor(typeof(SpawningRoomConnectorEventArgs), new[] { typeof(SpawnableRoomConnectorType) })),
new CodeInstruction(OpCodes.Dup),
new CodeInstruction(OpCodes.Stloc, ev.LocalIndex),

// Handlers.Map.OnSpawningRoomConnector(ev);
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Handlers.Map), nameof(Handlers.Map.OnSpawningRoomConnector))),

// if (!ev.IsAllowed)
// return;
new CodeInstruction(OpCodes.Ldloc, ev.LocalIndex),
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(SpawningRoomConnectorEventArgs), nameof(SpawningRoomConnectorEventArgs.IsAllowed))),
new CodeInstruction(OpCodes.Brfalse_S, retLabel),

// type = ev.ConnectorType
new CodeInstruction(OpCodes.Ldloc, ev.LocalIndex),
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(SpawningRoomConnectorEventArgs), nameof(SpawningRoomConnectorEventArgs.ConnectorType))),
new CodeInstruction(OpCodes.Starg_S, 0),
});

newInstructions[newInstructions.Count - 1].WithLabels(retLabel);

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

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