From e6a658bf334e61655ac769123771bef7ae686817 Mon Sep 17 00:00:00 2001 From: JohnM <234386938+treuenten@users.noreply.github.com> Date: Sat, 10 Oct 2026 00:12:45 +0800 Subject: [PATCH] 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 --- crates/bots/src/nav.rs | 2 +- crates/bots/src/plugin.rs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/bots/src/nav.rs b/crates/bots/src/nav.rs index 59a807b..236d446 100644 --- a/crates/bots/src/nav.rs +++ b/crates/bots/src/nav.rs @@ -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; diff --git a/crates/bots/src/plugin.rs b/crates/bots/src/plugin.rs index ba87809..fcba285 100644 --- a/crates/bots/src/plugin.rs +++ b/crates/bots/src/plugin.rs @@ -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; }