From ff6e231035dd941df8f4615dac36fcfb3a1f5e28 Mon Sep 17 00:00:00 2001 From: moddedmcplayer <76910334+moddedmcplayer@users.noreply.github.com> Date: Sun, 1 Feb 2026 18:27:21 +0100 Subject: [PATCH 1/2] new default provider --- .../Display/NickEventXPDisplayProvider.cs | 62 +++++++++++++++++++ .../Patch/NickPatchXPDisplayProvider.cs | 2 +- XPSystem/Main.cs | 6 +- XPSystem/XPSystem.csproj | 1 + 4 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs diff --git a/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs new file mode 100644 index 0000000..4570c80 --- /dev/null +++ b/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs @@ -0,0 +1,62 @@ +namespace XPSystem.BuiltInProviders.Display +{ + using System.Collections.Generic; + using System.ComponentModel; + using LabApi.Events.Arguments.PlayerEvents; + using XPSystem.API; + using XPSystem.API.Player; + using XPSystem.API.StorageProviders; + + public class NickEventXPDisplayProvider : XPDisplayProvider + { + private Dictionary DisplayNameOverrides { get; } = new(); + + public override void Enable() + { + base.Enable(); + LabApi.Events.Handlers.PlayerEvents.ChangingNickname += OnChangingNickname; + } + + public override void Disable() + { + base.Disable(); + LabApi.Events.Handlers.PlayerEvents.ChangingNickname -= OnChangingNickname; + } + + protected override void RefreshOfEnabled(BaseXPPlayer player, PlayerInfoWrapper? playerInfo) => Refresh(player); + protected override void RefreshOfDisabled(BaseXPPlayer player) => Refresh(player); + private void Refresh(BaseXPPlayer player) + { + if (player is not XPPlayer) + return; + + player.Hub.nicknameSync.DisplayName = player.Nickname; + } + + private void OnChangingNickname(PlayerChangingNicknameEventArgs ev) + { + if (!Config.Enabled) + return; + + if (!XPPlayer.TryGetXP(ev.Player.ReferenceHub, out XPPlayer? player)) + return; + + string name = Config.UseEvNewNick ? (ev.NewNickname ?? player.Nickname) : player.Nickname; + ev.NewNickname = Config.NickStructure + .Replace("%lvl%", XPAPI.GetPlayerInfo(player).Level.ToString()) + .Replace("%name%", name); + } + + public class NickConfig : IXPDisplayProviderConfig + { + [Description("Enable nick modifications?")] + public bool Enabled { get; set; } = true; + + [Description("Use the NewNickname of the EventArgs instead of MyNick for %name%.")] + public bool UseEvNewNick { get; set; } = true; + + [Description("The structure of the player nick. Variables: %lvl% - the level. %name% - the players nickname/name")] + public string NickStructure { get; set; } = "LVL %lvl% | %name%"; + } + } +} \ No newline at end of file diff --git a/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs index 0439ba3..92d3d0a 100644 --- a/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs +++ b/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs @@ -9,7 +9,7 @@ public class NickPatchXPDisplayProvider : XPDisplayProvider { - public Dictionary DisplayNameOverrides { get; } = new(); + private Dictionary DisplayNameOverrides { get; } = new(); protected override void RefreshOfEnabled(BaseXPPlayer player, PlayerInfoWrapper? playerInfo) => Refresh(player); protected override void RefreshOfDisabled(BaseXPPlayer player) => Refresh(player); diff --git a/XPSystem/Main.cs b/XPSystem/Main.cs index 3744372..77d6bee 100644 --- a/XPSystem/Main.cs +++ b/XPSystem/Main.cs @@ -9,7 +9,7 @@ using XPSystem.API; using XPSystem.API.Legacy; using XPSystem.API.StorageProviders; - using XPSystem.BuiltInProviders.Display.Patch; + using XPSystem.BuiltInProviders.Display; using XPSystem.Commands.Client; using XPSystem.Config; using XPSystem.Config.Events; @@ -25,7 +25,7 @@ public class Main : LabApi.Loader.Features.Plugins.Plugin #endif { - public const string VersionString = "2.1.1"; + public const string VersionString = "2.1.2"; /// /// This number is increased every time the plugin is reloaded. @@ -80,7 +80,7 @@ public override void Enable() Harmony = new Harmony($"XPSystem - {DateTime.Now.Ticks}"); Harmony.PatchAll(); - DisplayProviders.Add(new NickPatchXPDisplayProvider()); + DisplayProviders.Add(new NickEventXPDisplayProvider()); DisplayProviders.Add(new RankXPDisplayProvider()); MessagingProvider = MessagingProviders.Get(Config.DisplayMode); XPECLimitTracker.Initialize(); diff --git a/XPSystem/XPSystem.csproj b/XPSystem/XPSystem.csproj index ed2883f..dbd03b8 100644 --- a/XPSystem/XPSystem.csproj +++ b/XPSystem/XPSystem.csproj @@ -205,6 +205,7 @@ + From 05c6ed637c94ea43264ac9da4531af088c194f53 Mon Sep 17 00:00:00 2001 From: moddedmcplayer <76910334+moddedmcplayer@users.noreply.github.com> Date: Sun, 15 Mar 2026 21:22:32 +0100 Subject: [PATCH 2/2] improve nickevent --- XPSystem/API/Player/BaseXPPlayer.cs | 11 +++ XPSystem/API/XPAPI.cs | 2 +- .../Display/NickEventXPDisplayProvider.cs | 80 ++++++++++++++++--- 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/XPSystem/API/Player/BaseXPPlayer.cs b/XPSystem/API/Player/BaseXPPlayer.cs index ddc321e..9d42f70 100644 --- a/XPSystem/API/Player/BaseXPPlayer.cs +++ b/XPSystem/API/Player/BaseXPPlayer.cs @@ -1,6 +1,7 @@ namespace XPSystem.API.Player { using System; + using CentralAuth; using Hints; using Mirror; using PlayerRoles; @@ -23,6 +24,11 @@ public class BaseXPPlayer /// public string UserId => Hub.authManager.UserId; + /// + /// Gets the player's player ID (per-round, per-server, with dedicated server always being 1). + /// + public int PlayerServerId => Hub.PlayerId; + /// /// Gets the player's variables. /// @@ -53,6 +59,11 @@ public class BaseXPPlayer /// public bool IsConnected => Hub && Hub.gameObject; + /// + /// Gets whether or not the player object is ready (fully initialized). + /// + public bool IsReady => Hub.authManager.InstanceMode != ClientInstanceMode.Unverified && Hub.nicknameSync.NickSet; + /// /// Gets whether or not the player is a NPC. /// diff --git a/XPSystem/API/XPAPI.cs b/XPSystem/API/XPAPI.cs index b87c2ce..4041bd1 100644 --- a/XPSystem/API/XPAPI.cs +++ b/XPSystem/API/XPAPI.cs @@ -232,7 +232,7 @@ public static void UpdateNickname(XPPlayer player, PlayerInfoWrapper? playerInfo playerInfo.PlayerInfo.Nickname = player.DisplayedName; StorageProvider!.SetPlayerInfo(playerInfo); - LogDebug("Updated nick of " + player.PlayerId + " to " + player.DisplayedName); + LogDebug("Updated stored nick of " + player.PlayerId + " to " + player.DisplayedName); } #endif diff --git a/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs index 4570c80..c2d39ce 100644 --- a/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs +++ b/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs @@ -1,7 +1,10 @@ namespace XPSystem.BuiltInProviders.Display { + using System; using System.Collections.Generic; using System.ComponentModel; + using System.Diagnostics; + using System.Reflection; using LabApi.Events.Arguments.PlayerEvents; using XPSystem.API; using XPSystem.API.Player; @@ -9,18 +12,22 @@ public class NickEventXPDisplayProvider : XPDisplayProvider { - private Dictionary DisplayNameOverrides { get; } = new(); + private Dictionary DisplayNameOverrides { get; } = new(); public override void Enable() { base.Enable(); LabApi.Events.Handlers.PlayerEvents.ChangingNickname += OnChangingNickname; + LabApi.Events.Handlers.PlayerEvents.Joined += OnPlayerJoined; + LabApi.Events.Handlers.PlayerEvents.Left += OnPlayerLeft; } public override void Disable() { base.Disable(); LabApi.Events.Handlers.PlayerEvents.ChangingNickname -= OnChangingNickname; + LabApi.Events.Handlers.PlayerEvents.Joined -= OnPlayerJoined; + LabApi.Events.Handlers.PlayerEvents.Left -= OnPlayerLeft; } protected override void RefreshOfEnabled(BaseXPPlayer player, PlayerInfoWrapper? playerInfo) => Refresh(player); @@ -30,23 +37,78 @@ private void Refresh(BaseXPPlayer player) if (player is not XPPlayer) return; - player.Hub.nicknameSync.DisplayName = player.Nickname; + UpdateNick(player); } - private void OnChangingNickname(PlayerChangingNicknameEventArgs ev) + private void UpdateNick(BaseXPPlayer player, string? customNick = null) { - if (!Config.Enabled) + if (!player.IsReady) return; - - if (!XPPlayer.TryGetXP(ev.Player.ReferenceHub, out XPPlayer? player)) + if (CheckRecursion()) + return; + _updateNickUnsafe(player, customNick); + } + private void _updateNickUnsafe(BaseXPPlayer player, string? customNick) + { + if (!XPPlayer.TryGetXP(player, out XPPlayer? xpPlayer)) return; - string name = Config.UseEvNewNick ? (ev.NewNickname ?? player.Nickname) : player.Nickname; - ev.NewNickname = Config.NickStructure - .Replace("%lvl%", XPAPI.GetPlayerInfo(player).Level.ToString()) + string name; + if (Config.UseEvNewNick) + { + if (!string.IsNullOrEmpty(customNick)) + { + name = customNick!; + DisplayNameOverrides[player.PlayerServerId] = customNick!; + } + else + { + name = DisplayNameOverrides.TryGetValue(player.PlayerServerId, out string cached) + ? cached + : xpPlayer.Nickname; + } + } + else + { + name = xpPlayer.Nickname; + } + + player.Hub.nicknameSync.DisplayName = Config.NickStructure + .Replace("%lvl%", XPAPI.GetPlayerInfo(xpPlayer).Level.ToString()) .Replace("%name%", name); } + private MethodBase? _updateMethod; + private bool CheckRecursion() + { + if (_updateMethod == null) + _updateMethod = typeof(NickEventXPDisplayProvider).GetMethod(nameof(_updateNickUnsafe), BindingFlags.NonPublic | BindingFlags.Instance); + + StackTrace stackTrace = new StackTrace(); + foreach (StackFrame frame in stackTrace.GetFrames() ?? Array.Empty()) + { + if (frame.GetMethod() == _updateMethod) + return true; + } + + return false; + } + + private void OnPlayerJoined(PlayerJoinedEventArgs ev) + { + UpdateNick(new BaseXPPlayer(ev.Player.ReferenceHub)); + } + + private void OnChangingNickname(PlayerChangingNicknameEventArgs ev) + { + UpdateNick(new BaseXPPlayer(ev.Player.ReferenceHub), ev.NewNickname); + } + + private void OnPlayerLeft(PlayerLeftEventArgs ev) + { + DisplayNameOverrides.Remove(ev.Player.PlayerId); + } + public class NickConfig : IXPDisplayProviderConfig { [Description("Enable nick modifications?")]