Keep the baked bot navigation when only weapon or class data changes

The baked walk graph is reused in memory and cached on disk under the
world's content_digest, which also folds in the weapon tables (combat,
penetration, admission, camouflage, equipment) and the class catalog.
The walk never reads those: it traces clip geometry and script-model
collision from the spawns and objectives. So any weapon or class change,
including installing or removing a game that donates weapons, sent every
map back through a cold bake on its next load, one of the longest steps
of a first map load.

The graph is now keyed on the `map` (spawns and clip brushes) and
`models` (script-model collision) content components only, and
NAV_SCHEMA goes to 9 so graphs cached under the old key are not
reused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
JohnM
2026-10-10 00:12:45 +08:00
parent d934e6ea33
commit e6a658bf33
2 changed files with 11 additions and 3 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ use sim::{ClientId, SimBrush};
use crate::observation::ModeObjective;
use crate::query::{HullTrace, QueryResult, QuerySubsystem, SightSample, WalkSample, WorldQuery};
pub const NAV_SCHEMA: u32 = 8;
pub const NAV_SCHEMA: u32 = 9;
pub const GRID_IN: f32 = 48.0;
pub const SNAP_IN: f32 = 256.0;
pub const STEP_Z_IN: f32 = 18.0;
+10 -2
View File
@@ -612,7 +612,7 @@ fn prepare_navigation(
}
fn refresh_nav(world: &SimWorld, nav: &mut BotNav, load: Option<&assets::MapLoadProcess>) -> bool {
let digest = world.content_digest();
let digest = nav_digest(world);
if nav.graph.digest == digest && nav.graph.schema == NAV_SCHEMA && nav.graph.hull == NAV_HULL {
return true;
}
@@ -659,6 +659,14 @@ fn refresh_nav(world: &SimWorld, nav: &mut BotNav, load: Option<&assets::MapLoad
const NAV_CACHE_KIND: &str = "nav";
fn nav_digest(world: &SimWorld) -> u64 {
let parts = world.content_components();
assets::fnv1a64_more(
assets::fnv1a64(&parts.map.to_le_bytes()),
&parts.models.to_le_bytes(),
)
}
/// The digest, schema and hull that decide in-memory reuse are the whole key,
/// so the same map read back from disk is the same graph the walk would bake.
fn nav_cache_key(digest: u64) -> String {
@@ -701,7 +709,7 @@ fn navigation_for(world: &mut SimWorld, digest: u64) -> NavGraph {
}
fn bake_navigation(world: &mut SimWorld, graph: &mut NavGraph) {
let digest = world.content_digest();
let digest = nav_digest(world);
if graph.digest == digest && graph.schema == NAV_SCHEMA && graph.hull == NAV_HULL {
return;
}