Fix: 运行中修改系统数据后客户端无法同步

问题:
服务器只在启动时把 datas/Database/System.db 读入 DbSystemFile / DbSystemFileHash,用于和客户端比对并下发。运行中通过后台或 GM 修改装备、物品等系统数据并保存后,磁盘文件已更新,但这两个内存缓存不会刷新,客户端登录时仍按“启动时的旧哈希”判断为已最新,导致一直同步不到更新,只有重启服务器才生效。

修复:
  - SEnvir 新增 DbSystemFileTime 与 RefreshDbSystemFileIfChanged(),按文件最后写入时间判断,文件变更时重新读取 DbSystemFile 并重算哈希;
  - SConnection.Process(C.CheckClientDb) 在比对哈希前调用该刷新,使后台保存后客户端下次登录即可检测到变化并下载新的 System.db。

Signed-off-by: 秦凡东 <shell_way@foxmail.com>
This commit is contained in:
秦凡东
2026-09-19 13:25:07 +08:00
parent f657ad0fe5
commit c750f57a0e
2 changed files with 31 additions and 0 deletions
+4
View File
@@ -664,6 +664,10 @@ namespace Server.Envir
{
if (string.IsNullOrEmpty(p.Hash)) return;
// 运行中修改装备/物品等系统数据并保存后,文件已变,这里刷新缓存,
// 否则下发的仍是服务器启动时的旧库,客户端会一直同步不到更新。
SEnvir.RefreshDbSystemFileIfChanged();
if (p.Hash == SEnvir.DbSystemFileHash)
Enqueue(new S.CheckClientDb()
{
+27
View File
@@ -616,6 +616,8 @@ namespace Server.Envir
public static byte[]? DbSystemFile { get; private set; } = null;
public static string DbSystemFileHash { get; private set; } = string.Empty;
//客户端 System.db 缓存对应的文件最后写入时间,用于文件变更后刷新缓存
private static DateTime DbSystemFileTime = DateTime.MinValue;
public static DBCollection<AutoFightConfig> AutoFightConfList { get; set; }
@@ -847,6 +849,7 @@ namespace Server.Envir
//@"./datas/Database/"
DbSystemFile = File.ReadAllBytes(@"./datas/Database/System.db");
DbSystemFileHash = Functions.CalcMD5(DbSystemFile);
DbSystemFileTime = File.GetLastWriteTimeUtc(@"./datas/Database/System.db");
Random = new Random();
@@ -4636,6 +4639,30 @@ namespace Server.Envir
public static void SaveSystem() { Session.ForceSaveSystem(); }
public static void SaveUserDatas() { Session.Save(true); }
// 文件变更时刷新发给客户端的 System.db 缓存,
// 否则运行中修改的装备/物品等数据要等服务器重启才会同步给客户端。
public static void RefreshDbSystemFileIfChanged()
{
try
{
string path = @"./datas/Database/System.db";
if (!File.Exists(path)) return;
DateTime time = File.GetLastWriteTimeUtc(path);
if (time == DbSystemFileTime && DbSystemFile != null) return;
DbSystemFile = File.ReadAllBytes(path);
DbSystemFileHash = Functions.CalcMD5(DbSystemFile);
DbSystemFileTime = time;
}
catch (Exception e)
{
Log($"刷新客户端数据库缓存失败:{e.Message}");
}
}
#region Password Encryption
private const int Iterations = 1354;
private const int SaltSize = 16;