MONKEY (reviewfix): make skybox path lookup deterministic
Co-Authored-By: GPT-5.6 Sol (Codex)
This commit is contained in:
co-authored by
GPT-5.6 Sol (Codex)
parent
0eb9e1c022
commit
4b692177ae
@@ -181,6 +181,9 @@ pub struct LightCatalog {
|
||||
/// other rows are MOSB skyboxes. MONKEY (skybox): flags and the celestial model ride along
|
||||
/// ([`SkyboxDef`]), read from either table layout.
|
||||
skyboxes: HashMap<u32, SkyboxDef>,
|
||||
/// MONKEY (reviewfix): normalised model path в†’ lowest matching `LightSkybox` id. Some patched
|
||||
/// tables alias a model with different flags; path lookup must not depend on `HashMap` order.
|
||||
skybox_by_path: HashMap<String, u32>,
|
||||
}
|
||||
|
||||
fn light_schema() -> Schema {
|
||||
@@ -328,6 +331,7 @@ impl LightCatalog {
|
||||
};
|
||||
// MONKEY (skybox): both layouts, keyed by the header's field count.
|
||||
let skyboxes = skybox::load_skyboxes(chain, LIGHT_SKYBOX)?;
|
||||
let skybox_by_path = skybox::index_paths(&skyboxes);
|
||||
Ok(LightCatalog {
|
||||
lights,
|
||||
int_bands,
|
||||
@@ -337,6 +341,7 @@ impl LightCatalog {
|
||||
light_params_water_alpha,
|
||||
light_params_skybox,
|
||||
skyboxes,
|
||||
skybox_by_path,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,19 @@ pub(super) fn load_skyboxes(chain: &mut Chain, file: &str) -> Result<HashMap<u32
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
/// MONKEY (reviewfix): build the deterministic reverse index used by WMO and ghost path lookups.
|
||||
/// The lowest id wins when patched tables alias one model with multiple rows.
|
||||
pub(super) fn index_paths(skyboxes: &HashMap<u32, SkyboxDef>) -> HashMap<String, u32> {
|
||||
let mut by_path = HashMap::with_capacity(skyboxes.len());
|
||||
for (&id, def) in skyboxes {
|
||||
by_path
|
||||
.entry(def.path.to_ascii_lowercase())
|
||||
.and_modify(|old: &mut u32| *old = (*old).min(id))
|
||||
.or_insert(id);
|
||||
}
|
||||
by_path
|
||||
}
|
||||
|
||||
/// The modern collector's step: dedupe by model with the larger alpha, then scale every other
|
||||
/// entry by `1 − alpha` (`addSkyBox` steps 1 and 4).
|
||||
pub(super) fn collect(list: &mut Vec<ZoneSkybox>, id: u32, alpha: f32) {
|
||||
@@ -126,9 +139,10 @@ impl LightCatalog {
|
||||
|
||||
/// The row whose model is `path`, for a MOSB skybox the table also names.
|
||||
pub fn skybox_def_by_path(&self, path: &str) -> Option<&SkyboxDef> {
|
||||
self.skyboxes
|
||||
.values()
|
||||
.find(|d| d.path.eq_ignore_ascii_case(path))
|
||||
let path = crate::models::model_path(path).to_ascii_lowercase();
|
||||
self.skybox_by_path
|
||||
.get(&path)
|
||||
.and_then(|id| self.skyboxes.get(id))
|
||||
}
|
||||
|
||||
/// The skybox the slot's param names; a weather slot without one falls back to the clear
|
||||
@@ -234,6 +248,23 @@ mod tests {
|
||||
assert_eq!(l, vec![ZoneSkybox { id: 1, weight: 1.0 }]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_paths_resolve_to_the_lowest_id() {
|
||||
let def = |path: &str| SkyboxDef {
|
||||
path: path.into(),
|
||||
flags: 0,
|
||||
celestial: None,
|
||||
};
|
||||
let skyboxes = HashMap::from([
|
||||
(17, def(r"environments\stars\shared.m2")),
|
||||
(3, def(r"ENVIRONMENTS\STARS\SHARED.M2")),
|
||||
(9, def(r"environments\stars\other.m2")),
|
||||
]);
|
||||
let paths = index_paths(&skyboxes);
|
||||
assert_eq!(paths.get(r"environments\stars\shared.m2"), Some(&3));
|
||||
assert_eq!(paths.get(r"environments\stars\other.m2"), Some(&9));
|
||||
}
|
||||
|
||||
/// The installed chain loads in either layout.
|
||||
#[test]
|
||||
fn the_installed_table_loads() {
|
||||
|
||||
Reference in New Issue
Block a user