diff --git a/EXILED/Exiled.Events/EventArgs/Player/RoomChangedEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/RoomChangedEventArgs.cs index 57f17a3eda..c640b78217 100644 --- a/EXILED/Exiled.Events/EventArgs/Player/RoomChangedEventArgs.cs +++ b/EXILED/Exiled.Events/EventArgs/Player/RoomChangedEventArgs.cs @@ -8,6 +8,7 @@ namespace Exiled.Events.EventArgs.Player { using Exiled.API.Features; using Exiled.Events.EventArgs.Interfaces; + using MapGeneration; /// @@ -19,7 +20,7 @@ public class RoomChangedEventArgs : IPlayerEvent /// Initializes a new instance of the class. /// /// The player whose room has changed. - /// The room identifier before the change (Can be null on round start). + /// The room identifier before the change. /// The room identifier after the change. public RoomChangedEventArgs(ReferenceHub player, RoomIdentifier oldRoom, RoomIdentifier newRoom) { diff --git a/EXILED/Exiled.Events/EventArgs/Player/ZoneChangedEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ZoneChangedEventArgs.cs new file mode 100644 index 0000000000..3e6d998ed9 --- /dev/null +++ b/EXILED/Exiled.Events/EventArgs/Player/ZoneChangedEventArgs.cs @@ -0,0 +1,59 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.EventArgs.Player +{ + using Exiled.API.Enums; + using Exiled.API.Features; + using Exiled.Events.EventArgs.Interfaces; + + /// + /// Contains the information when a player changes zones. + /// + public class ZoneChangedEventArgs : IPlayerEvent + { + /// + /// Initializes a new instance of the class. + /// + /// The player whose zone has changed. + /// The previous room the player was in. + /// The new room the player entered. + /// The previous zone the player was in. + /// The new zone the player entered. + public ZoneChangedEventArgs(Player player, Room oldRoom, Room newRoom, ZoneType oldZone, ZoneType newZone) + { + Player = player; + OldRoom = oldRoom; + NewRoom = newRoom; + OldZone = oldZone; + NewZone = newZone; + } + + /// + public Player Player { get; } + + /// + /// Gets the previous zone the player was in. + /// + public ZoneType OldZone { get; } + + /// + /// Gets the new zone the player entered. + /// + public ZoneType NewZone { get; } + + /// + /// Gets the previous room the player was in. + /// + public Room OldRoom { get; } + + /// + /// Gets the new room the player entered. + /// + public Room NewRoom { get; } + } +} \ No newline at end of file diff --git a/EXILED/Exiled.Events/Features/Event.cs b/EXILED/Exiled.Events/Features/Event.cs index bbbc638401..7db233c910 100644 --- a/EXILED/Exiled.Events/Features/Event.cs +++ b/EXILED/Exiled.Events/Features/Event.cs @@ -45,8 +45,6 @@ private record AsyncRegistration(CustomAsyncEventHandler handler, int priority); private readonly List innerAsyncEvent = new(); - private bool patched; - /// /// Initializes a new instance of the class. /// @@ -60,6 +58,11 @@ public Event() /// public static IReadOnlyList List => EventsValue; + /// + /// Gets a value indicating whether the Harmony patch for this event has been applied. + /// + public bool Patched { get; private set; } = !Events.Instance.Config.UseDynamicPatching; + /// /// Subscribes a to the inner event, and checks patches if dynamic patching is enabled. /// @@ -124,10 +127,10 @@ public void Subscribe(CustomEventHandler handler, int priority) { Log.Assert(Events.Instance is not null, $"{nameof(Events.Instance)} is null, please ensure you have exiled_events enabled!"); - if (Events.Instance.Config.UseDynamicPatching && !patched) + if (Events.Instance.Config.UseDynamicPatching && !Patched) { Events.Instance.Patcher.Patch(this); - patched = true; + Patched = true; } if (handler == null) @@ -163,10 +166,10 @@ public void Subscribe(CustomAsyncEventHandler handler, int priority) { Log.Assert(Events.Instance is not null, $"{nameof(Events.Instance)} is null, please ensure you have exiled_events enabled!"); - if (Events.Instance.Config.UseDynamicPatching && !patched) + if (Events.Instance.Config.UseDynamicPatching && !Patched) { Events.Instance.Patcher.Patch(this); - patched = true; + Patched = true; } if (handler == null) diff --git a/EXILED/Exiled.Events/Features/Event{T}.cs b/EXILED/Exiled.Events/Features/Event{T}.cs index 2d6252b91e..847adc883d 100644 --- a/EXILED/Exiled.Events/Features/Event{T}.cs +++ b/EXILED/Exiled.Events/Features/Event{T}.cs @@ -50,8 +50,6 @@ private record AsyncRegistration(CustomAsyncEventHandler handler, int priorit private readonly List innerAsyncEvent = new(); - private bool patched; - /// /// Initializes a new instance of the class. /// @@ -65,6 +63,11 @@ public Event() /// public static IReadOnlyDictionary> Dictionary => TypeToEvent; + /// + /// Gets a value indicating whether the Harmony patch for this event has been applied. + /// + public bool Patched { get; private set; } = !Events.Instance.Config.UseDynamicPatching; + /// /// Subscribes a target to the inner event and checks if patching is possible, if dynamic patching is enabled. /// @@ -129,10 +132,10 @@ public void Subscribe(CustomEventHandler handler, int priority) { Log.Assert(Events.Instance is not null, $"{nameof(Events.Instance)} is null, please ensure you have exiled_events enabled!"); - if (Events.Instance.Config.UseDynamicPatching && !patched) + if (Events.Instance.Config.UseDynamicPatching && !Patched) { Events.Instance.Patcher.Patch(this); - patched = true; + Patched = true; } if (handler == null) @@ -168,10 +171,10 @@ public void Subscribe(CustomAsyncEventHandler handler, int priority) { Log.Assert(Events.Instance is not null, $"{nameof(Events.Instance)} is null, please ensure you have exiled_events enabled!"); - if (Events.Instance.Config.UseDynamicPatching && !patched) + if (Events.Instance.Config.UseDynamicPatching && !Patched) { Events.Instance.Patcher.Patch(this); - patched = true; + Patched = true; } if (handler == null) diff --git a/EXILED/Exiled.Events/Handlers/Player.cs b/EXILED/Exiled.Events/Handlers/Player.cs index 998b54f813..49dc14f00f 100644 --- a/EXILED/Exiled.Events/Handlers/Player.cs +++ b/EXILED/Exiled.Events/Handlers/Player.cs @@ -9,6 +9,9 @@ namespace Exiled.Events.Handlers { using System; + using Exiled.API.Enums; + using Exiled.API.Features; + #pragma warning disable IDE0079 #pragma warning disable IDE0060 #pragma warning disable SA1623 // Property summary documentation should match accessors @@ -16,6 +19,7 @@ namespace Exiled.Events.Handlers using Exiled.Events.EventArgs.Player; using Exiled.Events.Features; + using LabApi.Events.Arguments.PlayerEvents; /// @@ -505,6 +509,11 @@ public class Player /// public static Event RoomChanged { get; set; } = new(); + /// + /// Invoked when a changes zones. + /// + public static Event ZoneChanged { get; set; } = new(); + /// /// Invoked before a toggles the NoClip mode. /// @@ -835,7 +844,25 @@ public class Player /// Called when a changes rooms. /// /// The instance. - public static void OnRoomChanged(RoomChangedEventArgs ev) => RoomChanged.InvokeSafely(ev); + public static void OnRoomChanged(RoomChangedEventArgs ev) + { + RoomChanged.InvokeSafely(ev); + + if (!ZoneChanged.Patched) + return; + + ZoneType oldZone = ev.OldRoom?.Zone ?? ZoneType.Unspecified; + ZoneType newZone = ev.NewRoom?.Zone ?? ZoneType.Unspecified; + + if (oldZone != newZone) + OnZoneChanged(new ZoneChangedEventArgs(ev.Player, ev.OldRoom, ev.NewRoom, oldZone, newZone)); + } + + /// + /// Called when a changes zones. + /// + /// The instance. + public static void OnZoneChanged(ZoneChangedEventArgs ev) => ZoneChanged.InvokeSafely(ev); /// /// Called before a escapes. diff --git a/EXILED/Exiled.Events/Patches/Events/Player/ChangedRoom.cs b/EXILED/Exiled.Events/Patches/Events/Player/ChangedRoom.cs index 376587b14e..071e1c5fe1 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/ChangedRoom.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/ChangedRoom.cs @@ -25,6 +25,7 @@ namespace Exiled.Events.Patches.Events.Player /// Patches to add the event. /// [EventPatch(typeof(Player), nameof(Player.RoomChanged))] + [EventPatch(typeof(Player), nameof(Player.ZoneChanged))] [HarmonyPatch(typeof(CurrentRoomPlayerCache), nameof(CurrentRoomPlayerCache.ValidateCache))] internal class ChangedRoom { @@ -40,7 +41,7 @@ private static IEnumerable Transpiler(IEnumerable