Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
44 changes: 44 additions & 0 deletions EXILED/Exiled.Events/EventArgs/Player/PlayingAudioLogEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// -----------------------------------------------------------------------
// <copyright file="PlayingAudioLogEventArgs.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.Player
{
using API.Features;

using Interfaces;

/// <summary>
/// Contains all information before a player plays the AudioLog.
/// </summary>
public class PlayingAudioLogEventArgs : IPlayerEvent, IDeniableEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="PlayingAudioLogEventArgs" /> class.
/// </summary>
/// <param name="player">
/// <inheritdoc cref="Player" />
/// </param>
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// </param>
public PlayingAudioLogEventArgs(Player player, bool isAllowed = true)
{
Player = player;
IsAllowed = isAllowed;
}

/// <summary>
/// Gets or sets a value indicating whether or not the audio will start.
/// </summary>
public bool IsAllowed { get; set; }

/// <summary>
/// Gets the player who started the AudioLog.
/// </summary>
public Player Player { get; }
}
}
11 changes: 11 additions & 0 deletions EXILED/Exiled.Events/Handlers/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ public class Player
/// </summary>
public static Event<DroppingNothingEventArgs> DroppingNothing { get; set; } = new();

/// <summary>
/// Invoked before playing an AudioLog.
/// </summary>
public static Event<PlayingAudioLogEventArgs> PlayingAudioLog { get; set; } = new();

/// <summary>
/// Invoked before picking up an <see cref="API.Features.Items.Item"/>.
/// </summary>
Expand Down Expand Up @@ -691,6 +696,12 @@ public class Player
/// <param name="ev">The <see cref="DroppingNothingEventArgs"/> instance.</param>
public static void OnDroppingNothing(DroppingNothingEventArgs ev) => DroppingNothing.InvokeSafely(ev);

/// <summary>
/// Called before a <see cref="API.Features.Player"/> plays an AudioLog.
/// </summary>
/// <param name="ev">The <see cref="PlayingAudioLogEventArgs"/> instance.</param>
public static void OnPlayingAudioLog(PlayingAudioLogEventArgs ev) => PlayingAudioLog.InvokeSafely(ev);

/// <summary>
/// Called before a <see cref="API.Features.Player"/> picks up an item.
/// </summary>
Expand Down
68 changes: 68 additions & 0 deletions EXILED/Exiled.Events/Patches/Events/Player/PlayingAudioLog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// -----------------------------------------------------------------------
// <copyright file="PlayingAudioLog.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.Player
{
using System.Collections.Generic;
using System.Reflection.Emit;

using API.Features;
using API.Features.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Player;
using HarmonyLib;
using MapGeneration.Spawnables;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patch the <see cref="AudioLog.ServerInteract" />.
/// Adds the <see cref="Handlers.Player.PlayingAudioLog" /> event.
/// </summary>
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.PlayingAudioLog))]
[HarmonyPatch(typeof(AudioLog), nameof(AudioLog.ServerInteract))]
internal static class PlayingAudioLog
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label retLabel = generator.DefineLabel();

newInstructions.InsertRange(
0,
new CodeInstruction[]
{
// Player player = Player.Get(ReferenceHub);
new(OpCodes.Ldarg_1),
new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

// true
new(OpCodes.Ldc_I4_1),

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

// Handlers.Player.OnPlayingAudioLog(ev)
new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnPlayingAudioLog))),

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

newInstructions[newInstructions.Count - 1].labels.Add(retLabel);

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

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