fix(pathfinding): stop opening every .swb twice at boot
MovementPath.Configure() explicitly called PathCacheCommands.Configure()
and CacheEvictionTimer.Configure(). Both are types with a public static
parameterless Configure(), so AssemblyHandler.Invoke("Configure") already
discovered and called them once each. PathCacheCommands.Configure() ran
twice, and with it AutoLoadAtStartup(), so every map's .swb was opened,
indexed and logged twice. PathCacheCommands.Configure() called
PathfindRecorder.Configure() the same way.
Consolidate the cache lifecycle into Initialize:
- Configure() keeps only settings and command registration.
- Initialize() opens the readers once, then prebakes only maps that still
lack one.
- The post-bake reopen is per-map instead of a blanket AutoLoadAtStartup(),
which on a partial bake would close and reopen the readers already open.
Initialize is the correct phase: Configure runs before LoadTileMatrix() and
World.Load(), so opening a .swb there forced the lazy Map.Tiles property and
built every TileMatrix ahead of the loader that owns it, possibly before
TileMatrix.Configure() settled Pre6000ClientSupport. Both sit at the default
call priority and the phase sort is unstable. Moving pathfinding out leaves
nothing in Configure that touches Map.Tiles.
Also demote the per-map "opened ... chunks indexed" line to Debug. Opening
is the expected case; BakeMap already logs a rebuild at Information.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c39454137e
commit
313fe4bdb0
4 changed files with 28 additions and 21 deletions
|
|
@ -285,7 +285,8 @@ public sealed class StepCache
|
|||
}
|
||||
_lazyReaders[mapId] = reader;
|
||||
|
||||
logger.Information(
|
||||
// Debug: opening is the expected case. A rebuild is the interesting one, and BakeMap logs it.
|
||||
logger.Debug(
|
||||
"StepCache: opened {Path} ({ChunkCount} chunks indexed) for map {MapId}",
|
||||
path, reader.IndexedChunkCount, mapId
|
||||
);
|
||||
|
|
|
|||
|
|
@ -60,8 +60,6 @@ public sealed class MovementPath
|
|||
public static void Configure()
|
||||
{
|
||||
CommandSystem.Register("Path", AccessLevel.GameMaster, Path_OnCommand);
|
||||
CacheEvictionTimer.Configure();
|
||||
PathCacheCommands.Configure();
|
||||
}
|
||||
|
||||
[Usage("Path")]
|
||||
|
|
|
|||
|
|
@ -39,15 +39,12 @@ public static class PathCacheCommands
|
|||
8192
|
||||
);
|
||||
|
||||
PathfindRecorder.Configure();
|
||||
|
||||
CommandSystem.Register("PathCacheStats", AccessLevel.Administrator, OnPathCacheStats);
|
||||
CommandSystem.Register("PathCacheClear", AccessLevel.Administrator, OnPathCacheClear);
|
||||
CommandSystem.Register("PathBake", AccessLevel.Administrator, OnPathBake);
|
||||
CommandSystem.Register("PathCacheSave", AccessLevel.Administrator, OnPathCacheSave);
|
||||
CommandSystem.Register("PathCacheLoad", AccessLevel.Administrator, OnPathCacheLoad);
|
||||
CommandSystem.Register("PathRecord", AccessLevel.Administrator, OnPathRecord);
|
||||
AutoLoadAtStartup();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -80,18 +77,23 @@ public static class PathCacheCommands
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bakes any map whose <c>.swb</c> is missing or stale, when <see cref="PrebakeSetting"/> is
|
||||
/// set. Runs in the Initialize phase, once the tile matrix and world are loaded. An up-to-date
|
||||
/// cache makes it a no-op, so the cost lands only on a first boot or after a client or map
|
||||
/// update moves the fingerprint.
|
||||
/// Opens the existing <c>.swb</c> files, then — when <see cref="PrebakeSetting"/> is set —
|
||||
/// bakes any that are missing or stale. An up-to-date cache makes the bake a no-op, so the cost
|
||||
/// lands only on a first boot or after a client or map update moves the fingerprint.
|
||||
///
|
||||
/// A map is judged up-to-date by whether it has an open reader. <see cref="AutoLoadAtStartup"/>
|
||||
/// already ran in the earlier Configure phase and only opens a reader for a .swb whose
|
||||
/// fingerprint validates, so an open reader is proof of a good bake — no need to fingerprint
|
||||
/// the map a second time here.
|
||||
/// Both halves run here rather than in Configure: the fingerprint hashes the map files, so
|
||||
/// opening a .swb forces the lazy <see cref="Map.Tiles"/> property. In Configure that would
|
||||
/// build every TileMatrix ahead of <c>TileMatrixLoader</c>, possibly before
|
||||
/// <c>TileMatrix.Configure()</c> settles <c>Pre6000ClientSupport</c> — both sit at the default
|
||||
/// call priority and the phase sort is unstable.
|
||||
///
|
||||
/// A reader only opens once its fingerprint validates, so an open reader is proof of a good
|
||||
/// bake and the map is skipped without fingerprinting it again.
|
||||
/// </summary>
|
||||
public static void Initialize()
|
||||
{
|
||||
AutoLoadAtStartup();
|
||||
|
||||
if (!ServerConfiguration.GetSetting(PrebakeSetting, false))
|
||||
{
|
||||
return;
|
||||
|
|
@ -119,13 +121,15 @@ public static class PathCacheCommands
|
|||
);
|
||||
StepCache.Instance.BakeMap(map.MapID, path);
|
||||
StepCache.Instance.ClearResidentChunks();
|
||||
|
||||
// Just this map: a blanket AutoLoadAtStartup() would reopen every reader already open.
|
||||
StepCache.Instance.TryOpenLazyReader(path, map.MapID);
|
||||
baked++;
|
||||
}
|
||||
|
||||
if (baked > 0)
|
||||
{
|
||||
logger.Information("PathBake: pre-bake complete ({Count} map(s) written).", baked);
|
||||
AutoLoadAtStartup(); // reopen what we just wrote
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue