diff --git a/Tools/ResourceFiddler/Cargo.lock b/Tools/ResourceFiddler/Cargo.lock index 56eedfd..393962c 100755 --- a/Tools/ResourceFiddler/Cargo.lock +++ b/Tools/ResourceFiddler/Cargo.lock @@ -208,14 +208,23 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.3" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.19.1" @@ -425,9 +434,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ "darling_core", "darling_macro", @@ -435,11 +444,10 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", "quote", @@ -449,22 +457,52 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", "syn 2.0.114", ] +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.18", +] + [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", "serde_core", ] @@ -478,6 +516,27 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.60.2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -503,9 +562,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "ecow" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78e4f79b296fbaab6ce2e22d52cb4c7f010fe0ebe7a32e34fa25885fd797bd02" +checksum = "62bac48c16a993694c703f2991527d422d9efb8ec5625756004ba30e97683720" dependencies = [ "serde", ] @@ -540,6 +599,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "fast-md5" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d5eae88ed9322ba43db8f1ce3214050d9dea7730f44b2de0769604526b8d584" + [[package]] name = "find-msvc-tools" version = "0.1.7" @@ -654,6 +719,27 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "glacier-commons" +version = "0.1.0" +source = "git+https://github.com/atampy25/glacier-commons.git#c76255459d2f7e17532b26e53b85dfb064103c5f" +dependencies = [ + "arc-swap", + "brotli-decompressor", + "dirs", + "ecow", + "fast-md5", + "identity-hash", + "papaya", + "regex", + "serde", + "serde-smile", + "serde_with", + "static_init", + "thiserror 2.0.18", + "tryvial", +] + [[package]] name = "glacier-ini" version = "0.1.0" @@ -712,25 +798,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hitman-commons" -version = "0.1.0" -source = "git+https://github.com/atampy25/hitman-commons.git#3fea336da68380f1537eddf64c8915a808452d9f" -dependencies = [ - "arc-swap", - "brotli-decompressor", - "ecow", - "identity-hash", - "md5", - "papaya", - "serde", - "serde-smile", - "serde_with", - "static_init", - "thiserror 1.0.69", - "tryvial", -] - [[package]] name = "http" version = "1.4.0" @@ -1032,6 +1099,59 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jiff" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link", +] + +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", +] + +[[package]] +name = "jiff-static" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "jni" version = "0.21.1" @@ -1103,6 +1223,15 @@ version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +[[package]] +name = "libredox" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" +dependencies = [ + "libc", +] + [[package]] name = "litemap" version = "0.8.1" @@ -1155,12 +1284,6 @@ dependencies = [ "digest", ] -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - [[package]] name = "memchr" version = "2.7.6" @@ -1201,9 +1324,9 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-traits" @@ -1232,6 +1355,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "owo-colors" version = "4.2.3" @@ -1301,6 +1430,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -1463,6 +1607,17 @@ dependencies = [ "bitflags 2.10.0", ] +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + [[package]] name = "ref-cast" version = "1.0.25" @@ -1485,9 +1640,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -1497,9 +1652,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -1508,9 +1663,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" @@ -1558,7 +1713,7 @@ version = "1.0.0" dependencies = [ "clap", "crc32fast", - "hitman-commons", + "glacier-commons", "parking_lot", "paste", "rayon", @@ -1799,9 +1954,9 @@ dependencies = [ [[package]] name = "serde-smile" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20d059ecdf2585e7d7a1780b55b4a77683e79670cb9b23861d519ea48283e29" +checksum = "c26ffb558e2886c4c03799123e3236309644275c626e058d8657132598ab22de" dependencies = [ "indexmap 2.14.0", "itoa", @@ -1855,15 +2010,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" dependencies = [ "base64", + "bs58", "chrono", "hex", "indexmap 1.9.3", "indexmap 2.14.0", + "jiff", "schemars 0.9.0", "schemars 1.2.0", "serde_core", @@ -1874,9 +2031,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" dependencies = [ "darling", "proc-macro2", @@ -2078,12 +2235,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.45" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde_core", @@ -2093,15 +2249,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.25" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ "num-conv", "time-core", diff --git a/Tools/ResourceFiddler/Cargo.toml b/Tools/ResourceFiddler/Cargo.toml index 9106958..c95fa5f 100755 --- a/Tools/ResourceFiddler/Cargo.toml +++ b/Tools/ResourceFiddler/Cargo.toml @@ -9,7 +9,7 @@ thiserror = "2.0.17" rayon = "1.10" serde_json = "1.0.149" crc32fast = "1.5" -hitman-commons = { git = "https://github.com/atampy25/hitman-commons.git", features = ["hash_list"] } +glacier-commons = { git = "https://github.com/atampy25/glacier-commons.git", features = ["hash-list"] } reqwest = { version = "0.13.1", features = [ "blocking" ] } parking_lot = "0.12.5" paste = "1.0" diff --git a/Tools/ResourceFiddler/src/main.rs b/Tools/ResourceFiddler/src/main.rs index 8878474..32fc212 100755 --- a/Tools/ResourceFiddler/src/main.rs +++ b/Tools/ResourceFiddler/src/main.rs @@ -4,6 +4,7 @@ mod dump; mod extract; mod paths; mod pins; +mod propertyaliases; mod resource_lib; mod scan; mod test; @@ -73,6 +74,20 @@ enum Mode { crc_output: Option, }, + /// Walk all TBLU resources and dump unique property names found using property aliases. + PropertyAliases { + properties_path: PathBuf, + custom_properties_path: PathBuf, + /// The file to output the new custom properties txt to, defaults to the path + /// supplied previously if not specified. + #[arg(long, short = 'o')] + output: Option, + + /// Comma separated property names to also include in the output (if they're not already in the properties file). + #[arg(long, short = 'p', value_delimiter = ',')] + properties: Vec, + }, + /// Convert a single resource to JSON and print it to stdout. Extract { /// Resource hash (hex). @@ -117,23 +132,23 @@ fn parse_rrid(hash: &str) -> RuntimeResourceID { fn main() { let cli_args: Vec = env::args().collect(); - let hardcoded_args: Option<&str> = None; + let hardcoded_args: Option<&[&str]> = None; // Hardcoded fallback used when running from an IDE with no extra arguments. - //let hardcoded_args = [ + //let hardcoded_args = Some(&[ // "resource_fiddler", "-r", "C:/Games/HITMAN3/Retail", "-g", "HM3", "pins", - //]; - //let hardcoded_args = [ + //]); + //let hardcoded_args = Some(&[ // "resource_fiddler", // "-r", "/home/orfeasz/.local/share/Steam/steamapps/common/007 First Light/Retail", // "-g", "KNT", "extract", "0193ED6078F99215", - //]; - //let hardcoded_args = [ + //]); + //let hardcoded_args = Some(&[ // "resource_fiddler", // "-r", "/home/orfeasz/Games/HITMAN3/Retail", // "-g", "HM3", "paths" - //]; - //let hardcoded_args = Some([ + //]); + //let hardcoded_args = Some(&[ // "resource_fiddler", // "-r", "/home/orfeasz/.local/share/Steam/steamapps/common/007 First Light/Retail", // "-g", "KNT", "pins", "-o", "pins.json" @@ -159,6 +174,19 @@ fn main() { test::run(partition_manager, game, filter) } Mode::Pins { crc_output } => pins::run(partition_manager, game, crc_output.as_deref()), + Mode::PropertyAliases { + properties_path, + custom_properties_path, + output, + properties, + } => propertyaliases::run( + partition_manager, + game, + &properties_path, + &custom_properties_path.clone(), + &output.unwrap_or(custom_properties_path), + &properties, + ), Mode::Extract { hash } => extract::run(partition_manager, game, parse_rrid(&hash)), Mode::Scan { needle } => scan::run(&partition_manager, game, &needle), Mode::Types => types::run(&partition_manager), diff --git a/Tools/ResourceFiddler/src/pins.rs b/Tools/ResourceFiddler/src/pins.rs index 28312ae..9ea4b86 100644 --- a/Tools/ResourceFiddler/src/pins.rs +++ b/Tools/ResourceFiddler/src/pins.rs @@ -1,5 +1,5 @@ -use hitman_commons::hash_list::HashList; -use hitman_commons::metadata::RuntimeID; +use glacier_commons::hash_list::HashList; +use glacier_commons::metadata::RuntimeID; use rayon::prelude::*; use rpkg_rs::resource::partition_manager::PartitionManager; use rpkg_rs::resource::resource_info::ResourceInfo; diff --git a/Tools/ResourceFiddler/src/propertyaliases.rs b/Tools/ResourceFiddler/src/propertyaliases.rs new file mode 100644 index 0000000..7628b4f --- /dev/null +++ b/Tools/ResourceFiddler/src/propertyaliases.rs @@ -0,0 +1,164 @@ +use rayon::prelude::*; +use rpkg_rs::resource::partition_manager::PartitionManager; +use std::collections::HashSet; +use std::path::Path; +use std::sync::Mutex; + +use crate::resource_lib; + +pub fn run( + partition_manager: PartitionManager, + game: resource_lib::Game, + properties_path: &Path, + custom_properties_path: &Path, + output_path: &Path, + user_properties: &[String], +) { + // Property names gathered from CodeGen. + let known_properties = read_property_names(properties_path); + + println!( + "Loaded {} known property names from {}.", + known_properties.len(), + properties_path.display() + ); + + // User-specified properties, only added if they're not known already. + let user_properties: Vec = user_properties + .iter() + .map(|name| name.trim().to_string()) + .filter(|name| !name.is_empty() && !known_properties.contains(name)) + .collect(); + + if !user_properties.is_empty() { + println!( + "Including {} user-specified property names.", + user_properties.len() + ); + } + + let work_items: Vec<_> = partition_manager + .partitions + .iter() + .flat_map(|partition| { + partition + .latest_resources() + .into_iter() + .filter_map(|(resource, _)| { + if resource.data_type() != "TBLU" { + return None; + } + + Some((partition, resource)) + }) + .collect::>() + }) + .collect(); + + let resource_count = work_items.len(); + println!( + "Extracting property aliases from {} resources...", + resource_count + ); + + let property_aliases = Mutex::new(HashSet::<(String, String)>::new()); + + // Process resources in parallel. + work_items.par_iter().for_each(|(partition, resource)| { + let resource_type = resource.data_type(); + let rid = resource.rrid(); + + let resource_data = partition.read_resource(rid).unwrap(); + let converter = resource_lib::Converter::get(game, &resource_type).unwrap(); + let json_data = converter.memory_to_string(&resource_data).unwrap(); + + let json: serde_json::Value = serde_json::from_str(json_data.as_str().unwrap()).unwrap(); + + let local: Vec<(String, String)> = { + let mut seen = HashSet::new(); + + json["subEntities"] + .as_array() + .unwrap() + .iter() + .filter_map(|x| x["propertyAliases"].as_array()) + .flatten() + .map(|alias| { + ( + alias["sAliasName"].as_str().unwrap().to_string(), + alias["sPropertyName"].as_str().unwrap().to_string(), + ) + }) + .filter(|pair| seen.insert(pair.clone())) + .collect() + }; + + property_aliases.lock().unwrap().extend(local); + }); + + let mut property_aliases: Vec<_> = property_aliases.into_inner().unwrap().into_iter().collect(); + property_aliases.sort(); + + println!( + "Collected {} unique property aliases.", + property_aliases.len() + ); + + // Custom property names we have already named, one per line. + let custom_properties = read_property_names(custom_properties_path); + + println!( + "Loaded {} custom property names from {}.", + custom_properties.len(), + custom_properties_path.display() + ); + + // Combine the existing custom property names with the ones gathered from aliases. + // Aliases can carry an empty property name (somehow...?), these are filtered out. + let all_custom_properties: HashSet = custom_properties + .into_iter() + .chain(property_aliases.iter().flat_map(|(alias_name, property_name)| { + [alias_name.clone(), property_name.clone()] + })) + .chain(user_properties) + .map(|name| name.trim().to_string()) + .filter(|name| !name.is_empty()) + .collect(); + + // Right now, we don't filter custom properties for those already in the generated properties file. This is in case they're removed in a future update. + //let mut all_custom_properties: Vec<_> = all_custom_properties.into_iter().filter(|prop| !known_properties.contains(prop)).collect(); + let mut all_custom_properties: Vec<_> = all_custom_properties.into_iter().collect(); + all_custom_properties.sort(); + + // Match the line endings of the output file if it exists. + let line_ending = match std::fs::read_to_string(output_path) { + Ok(existing) if existing.contains("\r\n") => "\r\n", + _ => "\n", + }; + + let output = all_custom_properties.join(line_ending); + + std::fs::write(output_path, output).unwrap_or_else(|e| { + eprintln!("failed to write {}: {}", output_path.display(), e); + std::process::exit(1); + }); + + println!( + "\nWrote {} custom property names to {}.\n!!! Don't forget to run the bundler!", + all_custom_properties.len(), + output_path.display() + ); +} + +fn read_property_names(path: &Path) -> HashSet { + std::fs::read_to_string(path) + .unwrap_or_else(|e| { + eprintln!("failed to read {}: {}", path.display(), e); + std::process::exit(1); + }) + .lines() + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + .map(|line| line.to_string()) + .collect() +} diff --git a/Tools/ResourceFiddler/src/utils.rs b/Tools/ResourceFiddler/src/utils.rs index b821bf3..b0f3e29 100644 --- a/Tools/ResourceFiddler/src/utils.rs +++ b/Tools/ResourceFiddler/src/utils.rs @@ -1,5 +1,5 @@ use crate::resource_lib::Game; -use hitman_commons::metadata::RuntimeID; +use glacier_commons::metadata::RuntimeID; use rpkg_rs::GlacierGame; use rpkg_rs::resource::partition_manager::PartitionManager; use rpkg_rs::resource::pdefs::bond_parser::BondParser; @@ -53,7 +53,7 @@ pub fn print_json_diff(before: &str, after: &str) { } } -/// Convert a rpkg-rs RuntimeResourceID to a hitman_commons RuntimeID. +/// Convert a rpkg-rs RuntimeResourceID to a glacier_commons RuntimeID. pub fn rrid_to_rid(rrid: &RuntimeResourceID, game: Game) -> Option { let mask = match game { Game::FirstLight007 => 0x01FFFFFFFFFFFFFF,