From 85cd67725fc476c7fa696d586ff6eb4229e6bef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Mon, 11 May 2026 18:59:19 +0300 Subject: [PATCH 1/7] idk --- .../Patches/Events/Player/Spawning.cs | 100 ++++++++++++------ 1 file changed, 68 insertions(+), 32 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs index af8b3a6c20..69f8547d5f 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs @@ -13,11 +13,17 @@ namespace Exiled.Events.Patches.Events.Player using Exiled.API.Features; using Exiled.API.Features.Pools; + using Exiled.API.Features.Roles; using Exiled.Events.Attributes; using Exiled.Events.EventArgs.Player; + using HarmonyLib; + using MEC; + + using PlayerRoles.FirstPersonControl; using PlayerRoles.FirstPersonControl.Spawnpoints; + using UnityEngine; using static HarmonyLib.AccessTools; @@ -31,54 +37,84 @@ namespace Exiled.Events.Patches.Events.Player [HarmonyPatch(typeof(RoleSpawnpointManager), nameof(RoleSpawnpointManager.SetPosition))] internal static class Spawning { + /// + /// fghdv. + /// + /// dfs. + /// sdf. + internal static void ApplyRotation(IFpcRole fpcRole, float horizontalRotation) + { + if (fpcRole == null || fpcRole.FpcModule == null) + return; + + Timing.RunCoroutine(WaitForMouseLookAndApply(fpcRole.FpcModule, horizontalRotation)); + } + + private static IEnumerator WaitForMouseLookAndApply(FirstPersonMovementModule fpcModule, float rotation) + { + while (fpcModule != null) + { + yield return Timing.WaitUntilFalse(() => fpcModule.MouseLook == null); + + yield return Timing.WaitForOneFrame; + fpcModule.ServerOverrideRotation(new Vector2(0f, rotation)); + + yield break; + } + } + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) { List newInstructions = ListPool.Pool.Get(instructions); - int offset = -1; + LocalBuilder ev = generator.DeclareLocal(typeof(SpawningEventArgs)); - // Locate the call to `Transform.position` setter to determine where to insert new instructions. + int offset = -1; int index = newInstructions.FindIndex(instr => instr.Calls(PropertySetter(typeof(Transform), nameof(Transform.position)))) + offset; - // Declare the `SpawningEventArgs` local variable. - LocalBuilder ev = generator.DeclareLocal(typeof(SpawningEventArgs)); - - newInstructions.InsertRange( - index, - new[] + newInstructions.InsertRange(index, new CodeInstruction[] { - // Load `ReferenceHub` (argument 0) and get `Player`. - new CodeInstruction(OpCodes.Ldarg_0), // Load `hub` (first argument passed to the method). - new CodeInstruction(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), // Call Player.Get(hub) to get the Player instance. + // Player.Get(hub); + new(OpCodes.Ldarg_0), + new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), - // Load `position` (local variable 2). - new CodeInstruction(OpCodes.Ldloc_2), + // spawnLocation + new(OpCodes.Ldloc_2), - // Load `rotation` (local variable 3). - new CodeInstruction(OpCodes.Ldloc_3), + // horizontalRotation + new(OpCodes.Ldloc_3), - // Load `newRole` (argument 1). - new CodeInstruction(OpCodes.Ldarg_1), // Load `newRole` from argument 1. + // newRole + new(OpCodes.Ldarg_1), - // Create a new instance of `SpawningEventArgs`. - new CodeInstruction(OpCodes.Newobj, GetDeclaredConstructors(typeof(SpawningEventArgs))[0]), + // SpawningEventArg ev = new SpawningEventArgs(player, spawnLocation, horizontalRotation, newRole); + new(OpCodes.Newobj, GetDeclaredConstructors(typeof(SpawningEventArgs))[0]), + new(OpCodes.Dup), + new(OpCodes.Stloc, ev.LocalIndex), - // Duplicate the object to store it and pass it around. - new CodeInstruction(OpCodes.Dup), // Duplicate the `SpawningEventArgs` object. - new CodeInstruction(OpCodes.Stloc, ev.LocalIndex), // Store the duplicated object in a local variable. + // Handlers.Player.OnSpawning(ev); + new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnSpawning))), - // Call `Handlers.Player.OnSpawning`. - new CodeInstruction(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnSpawning))), + // spawnLocation = ev.Position; + new(OpCodes.Ldloc, ev.LocalIndex), + new(OpCodes.Call, PropertyGetter(typeof(SpawningEventArgs), nameof(SpawningEventArgs.Position))), + new(OpCodes.Stloc_2), - // Modify `position` from `ev.Position`. - new CodeInstruction(OpCodes.Ldloc, ev.LocalIndex), // Load the `SpawningEventArgs` object stored in the local variable. - new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(SpawningEventArgs), nameof(SpawningEventArgs.Position))), // Get the `Position` property from `SpawningEventArgs`. - new CodeInstruction(OpCodes.Stloc_2), // Store the position value back in the local variable 2 (`position`). + // horizontalRotation = ev.HorizontalRotation; + new(OpCodes.Ldloc, ev.LocalIndex), + new(OpCodes.Call, PropertyGetter(typeof(SpawningEventArgs), nameof(SpawningEventArgs.HorizontalRotation))), + new(OpCodes.Stloc_3), + }); - // Modify `rotation` from `ev.HorizontalRotation`. - new CodeInstruction(OpCodes.Ldloc, ev.LocalIndex), // Load the `SpawningEventArgs` object again. - new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(SpawningEventArgs), nameof(SpawningEventArgs.HorizontalRotation))), // Get the `HorizontalRotation` property from `SpawningEventArgs`. - new CodeInstruction(OpCodes.Stloc_3), // Store the rotation value back in the local variable 3 (`rotation`). + offset = 1; + index = newInstructions.FindIndex(instr => instr.Calls(PropertySetter(typeof(Transform), nameof(Transform.position)))) + offset; + + newInstructions.InsertRange(index, new CodeInstruction[] + { + // ApplyRotation(fpcRole, horizontalRotation) + new(OpCodes.Ldloc_0), + new(OpCodes.Ldloc_3), + new(OpCodes.Call, Method(typeof(Spawning), nameof(ApplyRotation))), }); for (int z = 0; z < newInstructions.Count; z++) From 64c494193ccf98aa26f277c4c85d417890eb62b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Mon, 11 May 2026 19:12:35 +0300 Subject: [PATCH 2/7] shit i forget revert my other try --- EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs index 69f8547d5f..cbec251c10 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs @@ -104,13 +104,7 @@ private static IEnumerable Transpiler(IEnumerable instr.Calls(PropertySetter(typeof(Transform), nameof(Transform.position)))) + offset; - newInstructions.InsertRange(index, new CodeInstruction[] - { // ApplyRotation(fpcRole, horizontalRotation) new(OpCodes.Ldloc_0), new(OpCodes.Ldloc_3), From a8fb36d972f4a65691e2ba5b99b8e9eb8669e364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sun, 24 May 2026 17:58:42 +0300 Subject: [PATCH 3/7] fix risk corutine leak & add vector2 support for spawning & add IsRotationModified for performance --- .../EventArgs/Player/SpawningEventArgs.cs | 29 ++++++++++------ .../Patches/Events/Player/Spawning.cs | 34 ++++++++----------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs index 785ff5a3cc..ab04a9dfa6 100644 --- a/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs +++ b/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs @@ -7,12 +7,12 @@ namespace Exiled.Events.EventArgs.Player { - using System; - using Exiled.API.Features; using Exiled.API.Features.Roles; using Exiled.Events.EventArgs.Interfaces; + using PlayerRoles; + using UnityEngine; /// @@ -20,6 +20,8 @@ namespace Exiled.Events.EventArgs.Player /// public class SpawningEventArgs : IPlayerEvent { + private Vector2 spawningRotation; + /// /// Initializes a new instance of the class. /// @@ -30,7 +32,7 @@ public class SpawningEventArgs : IPlayerEvent /// /// /// - /// + /// /// /// /// the spawned player's new role. @@ -39,7 +41,7 @@ public SpawningEventArgs(Player player, Vector3 position, float rotation, Player { Player = player; Position = position; - HorizontalRotation = rotation; + spawningRotation = new Vector2(0, rotation); NewRole = Role.Create(newRole); } @@ -62,17 +64,24 @@ public SpawningEventArgs(Player player, Vector3 position, float rotation, Player /// /// Rotation will apply only for . /// - public float HorizontalRotation { get; set; } + public Vector2 SpawningRotation + { + get => spawningRotation; + set + { + spawningRotation = value; + IsRotationModified = true; + } + } /// - /// Gets the player's old role. + /// Gets the player's new role. /// - [Obsolete("Removed because the method is no longer provide OldRole since version 14.0. Use Player.Role instead")] - public Role OldRole => Player.Role; + public Role NewRole { get; } /// - /// Gets the player's new role. + /// Gets a value indicating whether the spawning rotation was modified. /// - public Role NewRole { get; } + public bool IsRotationModified { get; private set; } } } diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs index cbec251c10..8b90374e49 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs @@ -37,30 +37,23 @@ namespace Exiled.Events.Patches.Events.Player [HarmonyPatch(typeof(RoleSpawnpointManager), nameof(RoleSpawnpointManager.SetPosition))] internal static class Spawning { - /// - /// fghdv. - /// - /// dfs. - /// sdf. - internal static void ApplyRotation(IFpcRole fpcRole, float horizontalRotation) + private static void ApplyRotation(IFpcRole fpcRole, SpawningEventArgs ev) { - if (fpcRole == null || fpcRole.FpcModule == null) + if (!ev.IsRotationModified || fpcRole == null || fpcRole.FpcModule == null) return; - Timing.RunCoroutine(WaitForMouseLookAndApply(fpcRole.FpcModule, horizontalRotation)); + Timing.RunCoroutine(WaitForMouseLookAndApply(fpcRole.FpcModule, ev.SpawningRotation), fpcRole.FpcModule.gameObject); } - private static IEnumerator WaitForMouseLookAndApply(FirstPersonMovementModule fpcModule, float rotation) + private static IEnumerator WaitForMouseLookAndApply(FirstPersonMovementModule fpcModule, Vector2 rotation) { - while (fpcModule != null) - { - yield return Timing.WaitUntilFalse(() => fpcModule.MouseLook == null); - - yield return Timing.WaitForOneFrame; - fpcModule.ServerOverrideRotation(new Vector2(0f, rotation)); + yield return Timing.WaitUntilFalse(() => fpcModule != null && fpcModule.MouseLook == null); + if (fpcModule == null) yield break; - } + + yield return Timing.WaitForOneFrame; + fpcModule.ServerOverrideRotation(rotation); } private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) @@ -100,14 +93,15 @@ private static IEnumerable Transpiler(IEnumerable Date: Sun, 24 May 2026 18:05:59 +0300 Subject: [PATCH 4/7] remove unused usings --- EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs index 8b90374e49..41d44d4da1 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs @@ -8,12 +8,10 @@ namespace Exiled.Events.Patches.Events.Player { using System.Collections.Generic; - using System.Reflection; using System.Reflection.Emit; using Exiled.API.Features; using Exiled.API.Features.Pools; - using Exiled.API.Features.Roles; using Exiled.Events.Attributes; using Exiled.Events.EventArgs.Player; From e8d3496333903a7057d45bd48de331eab1a7b514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sun, 24 May 2026 18:25:55 +0300 Subject: [PATCH 5/7] remeove useless opcodes --- EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs index 41d44d4da1..eec3891242 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs @@ -91,12 +91,6 @@ private static IEnumerable Transpiler(IEnumerable Date: Sun, 24 May 2026 18:36:38 +0300 Subject: [PATCH 6/7] reorder methos --- .../Patches/Events/Player/Spawning.cs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs index eec3891242..e3078ce382 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs @@ -35,25 +35,6 @@ namespace Exiled.Events.Patches.Events.Player [HarmonyPatch(typeof(RoleSpawnpointManager), nameof(RoleSpawnpointManager.SetPosition))] internal static class Spawning { - private static void ApplyRotation(IFpcRole fpcRole, SpawningEventArgs ev) - { - if (!ev.IsRotationModified || fpcRole == null || fpcRole.FpcModule == null) - return; - - Timing.RunCoroutine(WaitForMouseLookAndApply(fpcRole.FpcModule, ev.SpawningRotation), fpcRole.FpcModule.gameObject); - } - - private static IEnumerator WaitForMouseLookAndApply(FirstPersonMovementModule fpcModule, Vector2 rotation) - { - yield return Timing.WaitUntilFalse(() => fpcModule != null && fpcModule.MouseLook == null); - - if (fpcModule == null) - yield break; - - yield return Timing.WaitForOneFrame; - fpcModule.ServerOverrideRotation(rotation); - } - private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) { List newInstructions = ListPool.Pool.Get(instructions); @@ -102,5 +83,24 @@ private static IEnumerable Transpiler(IEnumerable.Pool.Return(newInstructions); } + + private static void ApplyRotation(IFpcRole fpcRole, SpawningEventArgs ev) + { + if (!ev.IsRotationModified || fpcRole == null || fpcRole.FpcModule == null) + return; + + Timing.RunCoroutine(WaitForMouseLookAndApply(fpcRole.FpcModule, ev.SpawningRotation), fpcRole.FpcModule.gameObject); + } + + private static IEnumerator WaitForMouseLookAndApply(FirstPersonMovementModule fpcModule, Vector2 rotation) + { + yield return Timing.WaitUntilFalse(() => fpcModule != null && fpcModule.MouseLook == null); + + if (fpcModule == null) + yield break; + + yield return Timing.WaitForOneFrame; + fpcModule.ServerOverrideRotation(rotation); + } } } From 3e4f24b5e0763efe225cda1210ae164cd81ea90c Mon Sep 17 00:00:00 2001 From: MS-crew <100300664+MS-crew@users.noreply.github.com> Date: Mon, 25 May 2026 12:27:24 +0300 Subject: [PATCH 7/7] Update Spawning.cs --- EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs index 218a12a966..d37c44dde7 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Spawning.cs @@ -72,7 +72,7 @@ private static IEnumerable Transpiler(IEnumerable