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
new file mode 100644
index 0000000..c2d39ce
--- /dev/null
+++ b/XPSystem/BuiltInProviders/Display/NickEventXPDisplayProvider.cs
@@ -0,0 +1,124 @@
+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;
+ 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;
+ 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);
+ protected override void RefreshOfDisabled(BaseXPPlayer player) => Refresh(player);
+ private void Refresh(BaseXPPlayer player)
+ {
+ if (player is not XPPlayer)
+ return;
+
+ UpdateNick(player);
+ }
+
+ private void UpdateNick(BaseXPPlayer player, string? customNick = null)
+ {
+ if (!player.IsReady)
+ return;
+ if (CheckRecursion())
+ return;
+ _updateNickUnsafe(player, customNick);
+ }
+ private void _updateNickUnsafe(BaseXPPlayer player, string? customNick)
+ {
+ if (!XPPlayer.TryGetXP(player, out XPPlayer? xpPlayer))
+ return;
+
+ 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?")]
+ 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 @@
+