Skip to content
This repository has been archived by the owner on Jan 19, 2025. It is now read-only.

Added RoundStartingEventArgs #2797

Closed
wants to merge 9 commits into from
Closed
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
31 changes: 31 additions & 0 deletions Exiled.Events/EventArgs/Server/RoundStartingEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// -----------------------------------------------------------------------
// <copyright file="RoundStartingEventArgs.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.Server
{
/// <summary>
/// Contains all information before the start of the round.
/// </summary>
public class RoundStartingEventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="RoundStartingEventArgs" /> class.
/// </summary>
/// <param name="isAllowed">
/// <inheritdoc cref="IsAllowed" />
/// </param>
public RoundStartingEventArgs(bool isAllowed = true)
{
IsAllowed = isAllowed;
}

/// <summary>
/// Gets or sets a value indicating whether the round can start or not.
/// </summary>
public bool IsAllowed { get; set; }
}
}
13 changes: 12 additions & 1 deletion Exiled.Events/Handlers/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ public static class Server
/// </summary>
public static Event ReloadedPermissions { get; set; } = new();

/// <summary>
/// Invoked before the round starts.
/// </summary>
public static Event<RoundStartingEventArgs> RoundStarting { get; set; } = new();

/// <summary>
/// Called before waiting for players.
/// </summary>
Expand Down Expand Up @@ -195,5 +200,11 @@ public static class Server
/// </summary>
/// <param name="ev">The <see cref="SelectingRespawnTeamEventArgs"/> instance.</param>
public static void OnSelectingRespawnTeam(SelectingRespawnTeamEventArgs ev) => SelectingRespawnTeam.InvokeSafely(ev);

/// <summary>
/// Called before round started.
/// </summary>
/// <param name="ev">The <see cref="RoundStartingEventArgs"/> instance.</param>
public static void OnRoundStarting(RoundStartingEventArgs ev) => RoundStarting.InvokeSafely(ev);
}
}
}
78 changes: 78 additions & 0 deletions Exiled.Events/Patches/Events/Server/RoundStarting.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// -----------------------------------------------------------------------
// <copyright file="RoundStarting.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.Server
{
using System.Collections.Generic;
using System.Reflection.Emit;

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

using GameCore;

using HarmonyLib;

using static HarmonyLib.AccessTools;

/// <summary>
/// Patch the <see cref="RoundStart.NetworkTimer" />.
/// Adds the <see cref="Server.RoundStarting" /> event.
/// </summary>
[EventPatch(typeof(Server), nameof(Server.RoundStarting))]
[HarmonyPatch(typeof(RoundStart), nameof(RoundStart.NetworkTimer), MethodType.Setter)]
internal static class RoundStarting
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

Label ret = generator.DefineLabel();
Label contlabel = generator.DefineLabel();

newInstructions[newInstructions.Count - 1].labels.Add(ret);
LocalBuilder ev = generator.DeclareLocal(typeof(RoundStartingEventArgs));

newInstructions.InsertRange(
0,
new CodeInstruction[]
{
// Getting a old value
new CodeInstruction(OpCodes.Ldarg_1),

// Getting a new value
new CodeInstruction(OpCodes.Ldc_I4, -1),

// If the value is not equal, jump
new CodeInstruction(OpCodes.Bne_Un, contlabel),

// RoundStartingEventArgs ev = new
new CodeInstruction(OpCodes.Newobj, GetDeclaredConstructors(typeof(RoundStartingEventArgs))[0]),
new CodeInstruction(OpCodes.Dup),
new CodeInstruction(OpCodes.Stloc_S, ev.LocalIndex),

// Handlers.Server.OnRoundStarting(ev)
new CodeInstruction(OpCodes.Call, Method(typeof(Server), nameof(Server.OnRoundStarting))),
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),

// If isallowed = false
new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(RoundStartingEventArgs), nameof(RoundStartingEventArgs.IsAllowed))),
new CodeInstruction(OpCodes.Brfalse_S, ret),

// Empty opcode for jump
new CodeInstruction(OpCodes.Nop).WithLabels(contlabel),
});

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

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