From ee9b318172bf50fadd90e0cfc364330fb85f778a Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Fri, 3 Jul 2026 16:58:17 +0400 Subject: fix(stage2): preserve byte-exact prototype identities --- crates/fparkan-assets/src/lib.rs | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'crates/fparkan-assets/src') diff --git a/crates/fparkan-assets/src/lib.rs b/crates/fparkan-assets/src/lib.rs index 26244ee..b128822 100644 --- a/crates/fparkan-assets/src/lib.rs +++ b/crates/fparkan-assets/src/lib.rs @@ -570,7 +570,7 @@ pub fn prepare_mission_assets_with_repository( #[derive(Clone, Debug, Eq, PartialEq)] enum PreparedVisualSignature { Mesh { - archive: String, + archive: Vec, name: Vec, type_id: Option, dependency_count: usize, @@ -583,7 +583,7 @@ enum PreparedVisualSignature { fn prepared_visual_signature(proto: &EffectivePrototype) -> PreparedVisualSignature { match &proto.geometry { PrototypeGeometry::Mesh(key) => PreparedVisualSignature::Mesh { - archive: key.archive.as_str().to_string(), + archive: key.archive.identity_bytes().to_vec(), name: key.name.0.clone(), type_id: key.type_id, dependency_count: proto.dependencies.len(), @@ -1160,7 +1160,7 @@ fn stable_visual_id(proto: &EffectivePrototype) -> u64 { match &proto.geometry { PrototypeGeometry::Mesh(key) => { 1_u8.hash(&mut hasher); - key.archive.as_str().hash(&mut hasher); + key.archive.identity_bytes().hash(&mut hasher); key.name.0.hash(&mut hasher); key.type_id.hash(&mut hasher); } @@ -1269,6 +1269,35 @@ mod tests { assert!(matches!(err, AssetError::Texture(_))); } + #[test] + fn stable_visual_id_uses_archive_identity_bytes() { + let first = EffectivePrototype { + key: fparkan_prototype::PrototypeKey(resource_name(b"mesh")), + geometry: PrototypeGeometry::Mesh(ResourceKey { + archive: normalize_relative(b"DATA/\xFF.lib", PathPolicy::HostCompatible) + .expect("archive"), + name: resource_name(b"mesh.msh"), + type_id: Some(0x4853_454D), + }), + source: fparkan_prototype::PrototypeSource::DirectArchive, + dependencies: Vec::new(), + }; + let second = EffectivePrototype { + key: fparkan_prototype::PrototypeKey(resource_name(b"mesh")), + geometry: PrototypeGeometry::Mesh(ResourceKey { + archive: normalize_relative(b"DATA/\xFE.lib", PathPolicy::HostCompatible) + .expect("archive"), + name: resource_name(b"mesh.msh"), + type_id: Some(0x4853_454D), + }), + source: fparkan_prototype::PrototypeSource::DirectArchive, + dependencies: Vec::new(), + }; + + assert_ne!(stable_visual_id(&first), stable_visual_id(&second)); + assert_ne!(prepared_visual_signature(&first), prepared_visual_signature(&second)); + } + #[test] #[ignore = "requires licensed corpus"] fn prepares_real_unit_asset_plan() { -- cgit v1.2.3