From 43f82814862472e704ad3146d2188b115996358f Mon Sep 17 00:00:00 2001 From: FangkuaiYa <2683748223@qq.com> Date: Thu, 20 Aug 2026 15:17:46 +0800 Subject: [PATCH] Fix playerlog --- .../Net/Manager/ClientManager.cs | 10 ++++- src/Empostor.Server/Program.cs | 2 + src/Empostor.Server/Service/ClientIdStore.cs | 42 +++++++++++++++++++ .../Service/Stat/PlayerLogStore.cs | 6 +++ 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/Empostor.Server/Service/ClientIdStore.cs diff --git a/src/Empostor.Server/Net/Manager/ClientManager.cs b/src/Empostor.Server/Net/Manager/ClientManager.cs index d7106c9..9f5c491 100644 --- a/src/Empostor.Server/Net/Manager/ClientManager.cs +++ b/src/Empostor.Server/Net/Manager/ClientManager.cs @@ -10,9 +10,10 @@ using Empostor.Api.Config; using Empostor.Api.Events.Managers; using Empostor.Api.Net; using Empostor.Api.Net.Manager; +using Empostor.Api.Service; using Empostor.Server.Events.Client; using Empostor.Server.Net.Factories; -using Empostor.Api.Service; +using Empostor.Server.Service; using Empostor.Server.Service.Admin.Reactor; using Empostor.Server.Service.Auth; using Empostor.Server.Utils; @@ -36,6 +37,7 @@ namespace Empostor.Server.Net.Manager private readonly AuthApiConfig _authApiConfig; private readonly PortPoolService _portPool; private readonly IpGeolocationService _ipGeo; + private readonly ClientIdStore _clientIdStore; private int _idLast; public ClientManager( @@ -49,7 +51,8 @@ namespace Empostor.Server.Net.Manager IHttpClientFactory httpClientFactory, IOptions authApiConfig, PortPoolService portPool, - IpGeolocationService ipGeo) + IpGeolocationService ipGeo, + ClientIdStore clientIdStore) { _logger = logger; _eventManager = eventManager; @@ -63,6 +66,8 @@ namespace Empostor.Server.Net.Manager _authApiConfig = authApiConfig.Value; _portPool = portPool; _ipGeo = ipGeo; + _clientIdStore = clientIdStore; + _idLast = checked((int)_clientIdStore.GetLastId()); if (_compatibilityConfig.AllowFutureGameVersions) { @@ -91,6 +96,7 @@ namespace Empostor.Server.Net.Manager { var clientId = Interlocked.Increment(ref _idLast); if (clientId < 1) { _idLast = 0; clientId = Interlocked.Increment(ref _idLast); } + _clientIdStore.SetLastId(clientId); return clientId; } diff --git a/src/Empostor.Server/Program.cs b/src/Empostor.Server/Program.cs index 88fb881..e83d8f1 100644 --- a/src/Empostor.Server/Program.cs +++ b/src/Empostor.Server/Program.cs @@ -45,6 +45,7 @@ using Next.Hazel.Extensions; using Serilog; using Serilog.Events; using Serilog.Settings.Configuration; +using Empostor.Server.Service; namespace Empostor.Server { @@ -164,6 +165,7 @@ namespace Empostor.Server services.AddSingleton(); services.AddSingleton(ModuleTagRegistry.Instance); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(p => p.GetRequiredService()); diff --git a/src/Empostor.Server/Service/ClientIdStore.cs b/src/Empostor.Server/Service/ClientIdStore.cs new file mode 100644 index 0000000..a59eebc --- /dev/null +++ b/src/Empostor.Server/Service/ClientIdStore.cs @@ -0,0 +1,42 @@ +using Empostor.Api.Service; +using Empostor.Server.Service.Stat; +using Microsoft.Extensions.Logging; + +namespace Empostor.Server.Service; + +/// +/// Persists the last-assigned client ID so that client IDs are never +/// reused across server restarts. Client IDs are used as the stable +/// identity for persisted per-player data (e.g. the player log). Without +/// persistence the ID counter resets to 1 on every restart, which makes +/// old and new log entries that share the same ID belong to different +/// players. +/// +public sealed class ClientIdStore : JsonDataStore +{ + private long _lastId; + + public ClientIdStore(ILogger logger, PlayerLogStore playerLogs) + : base(logger) + { + Load(); + + _lastId = System.Math.Max(_lastId, playerLogs.GetMaxClientId()); + if (_lastId > 0) + { + SaveFireAndForget(); + } + } + + public long GetLastId() => _lastId; + + public void SetLastId(long id) + { + _lastId = id; + SaveFireAndForget(); + } + + protected override long GetSnapshot() => _lastId; + + protected override void ApplySnapshot(long data) => _lastId = data; +} diff --git a/src/Empostor.Server/Service/Stat/PlayerLogStore.cs b/src/Empostor.Server/Service/Stat/PlayerLogStore.cs index 1debac1..a2fbdd1 100644 --- a/src/Empostor.Server/Service/Stat/PlayerLogStore.cs +++ b/src/Empostor.Server/Service/Stat/PlayerLogStore.cs @@ -71,6 +71,12 @@ public sealed class PlayerLogStore : JsonDataStore> public List GetLoggedClientIds() => _entries.Where(e => e.ClientId.HasValue).Select(e => e.ClientId!.Value).Distinct().ToList(); + public int GetMaxClientId() => + _entries.Where(e => e.ClientId.HasValue) + .Select(e => e.ClientId!.Value) + .DefaultIfEmpty(0) + .Max(); + /// /// Returns the most recent non-empty player name recorded for a client. /// Used by the admin panel so disconnected players still show their