From dfa6e05380156eb1b9b0e6b130130ae8be3a8191 Mon Sep 17 00:00:00 2001 From: Crauzer Date: Tue, 14 Apr 2026 10:30:14 +0200 Subject: [PATCH] feat(ltk_mod_project, ltk_fantome, ltk_modpkg, ltk_overlay): add display_name to mod project layer struct --- crates/league-mod/src/commands/info.rs | 23 ++++++++++++------- crates/ltk_fantome/src/lib.rs | 7 ++++++ crates/ltk_mod_project/src/lib.rs | 10 ++++++++ .../ltk_mod_project/test-data/mod.config.json | 1 + .../ltk_mod_project/test-data/mod.config.toml | 1 + crates/ltk_modpkg/src/metadata.rs | 9 ++++++++ crates/ltk_modpkg/src/project.rs | 3 +++ crates/ltk_overlay/src/builder/metadata.rs | 1 + crates/ltk_overlay/src/modpkg_content.rs | 1 + 9 files changed, 48 insertions(+), 8 deletions(-) diff --git a/crates/league-mod/src/commands/info.rs b/crates/league-mod/src/commands/info.rs index 944f56f..32833ce 100644 --- a/crates/league-mod/src/commands/info.rs +++ b/crates/league-mod/src/commands/info.rs @@ -37,25 +37,32 @@ pub fn info_mod_package(args: InfoModPackageArgs) -> miette::Result<()> { println_pad!("\n{}", "🏗️ Layers:".bright_magenta().bold()); for layer in modpkg.layers.values() { - // Try to find a matching layer metadata entry (to show description, if present). - let layer_description = metadata - .layers - .iter() - .find(|lm| lm.name == layer.name) - .and_then(|lm| lm.description.as_deref()); + // Try to find a matching layer metadata entry (to show display_name/description). + let layer_meta = metadata.layers.iter().find(|lm| lm.name == layer.name); + let layer_display_name = layer_meta.and_then(|lm| lm.display_name.as_deref()); + let layer_description = layer_meta.and_then(|lm| lm.description.as_deref()); + + let name_display = match layer_display_name { + Some(display_name) => format!( + "{} ({})", + display_name.bright_cyan().bold(), + layer.name.dimmed() + ), + None => format!("{}", layer.name.bright_cyan().bold()), + }; match layer_description { Some(desc) => println_pad!( " {} {} {} - {}", "•".bright_cyan(), - layer.name.bright_cyan().bold(), + name_display, format!("(priority: {})", layer.priority).dimmed(), desc.bright_white() ), None => println_pad!( " {} {} {}", "•".bright_cyan(), - layer.name.bright_cyan().bold(), + name_display, format!("(priority: {})", layer.priority).dimmed() ), } diff --git a/crates/ltk_fantome/src/lib.rs b/crates/ltk_fantome/src/lib.rs index f0bf53a..3603da8 100644 --- a/crates/ltk_fantome/src/lib.rs +++ b/crates/ltk_fantome/src/lib.rs @@ -46,6 +46,12 @@ pub struct FantomeInfo { pub struct FantomeLayerInfo { #[serde(rename = "Name")] pub name: String, + #[serde( + rename = "DisplayName", + default, + skip_serializing_if = "Option::is_none" + )] + pub display_name: Option, #[serde(rename = "Priority")] pub priority: i32, /// String overrides for this layer, organized by locale. @@ -245,6 +251,7 @@ fn build_fantome_layers(mod_project: &ModProject) -> HashMap, + /// The priority of the layer /// Higher priority layers override lower priority layers when they modify the same files /// Default is 0 for the base layer @@ -215,6 +221,7 @@ impl ModProjectLayer { pub fn base() -> Self { Self { name: "base".to_string(), + display_name: None, priority: 0, description: Some("Base layer of the mod".to_string()), string_overrides: HashMap::new(), @@ -226,6 +233,7 @@ impl ModProjectLayer { pub fn default_layers() -> Vec { vec![ModProjectLayer { name: "base".to_string(), + display_name: None, priority: 0, description: Some("Base layer of the mod".to_string()), string_overrides: HashMap::new(), @@ -264,12 +272,14 @@ mod tests { layers: vec![ ModProjectLayer { name: "base".to_string(), + display_name: None, priority: 0, description: Some("Base layer of the mod".to_string()), string_overrides: HashMap::new(), }, ModProjectLayer { name: "chroma1".to_string(), + display_name: Some("Chroma 1".to_string()), priority: 20, description: Some("Chroma 1".to_string()), string_overrides: HashMap::new(), diff --git a/crates/ltk_mod_project/test-data/mod.config.json b/crates/ltk_mod_project/test-data/mod.config.json index 136d592..f9a9470 100644 --- a/crates/ltk_mod_project/test-data/mod.config.json +++ b/crates/ltk_mod_project/test-data/mod.config.json @@ -21,6 +21,7 @@ }, { "name": "chroma1", + "display_name": "Chroma 1", "priority": 20, "description": "Chroma 1" } diff --git a/crates/ltk_mod_project/test-data/mod.config.toml b/crates/ltk_mod_project/test-data/mod.config.toml index dd2206a..488ea71 100644 --- a/crates/ltk_mod_project/test-data/mod.config.toml +++ b/crates/ltk_mod_project/test-data/mod.config.toml @@ -18,5 +18,6 @@ description = "Base layer of the mod" [[layers]] name = "chroma1" +display_name = "Chroma 1" priority = 20 description = "Chroma 1" diff --git a/crates/ltk_modpkg/src/metadata.rs b/crates/ltk_modpkg/src/metadata.rs index 0502088..0796bcb 100644 --- a/crates/ltk_modpkg/src/metadata.rs +++ b/crates/ltk_modpkg/src/metadata.rs @@ -88,6 +88,7 @@ impl DistributorInfo { /// /// let layer = ModpkgLayerMetadata { /// name: "base".to_string(), +/// display_name: None, /// priority: 0, /// description: Some("Base layer".to_string()), /// string_overrides: HashMap::from([ @@ -103,6 +104,9 @@ impl DistributorInfo { pub struct ModpkgLayerMetadata { /// The name of the layer (e.g. "base", "chroma1"). pub name: String, + /// Optional human-readable display name for the layer. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub display_name: Option, /// The priority of the layer as stored in the modpkg header. pub priority: i32, /// Optional human-readable description of the layer. @@ -435,6 +439,7 @@ mod tests { fn test_layer_string_overrides_roundtrip() { let layer = ModpkgLayerMetadata { name: "base".to_string(), + display_name: None, priority: 0, description: Some("Base layer".to_string()), string_overrides: HashMap::from([( @@ -455,6 +460,7 @@ mod tests { fn test_layer_empty_overrides_skipped_in_serialization() { let layer = ModpkgLayerMetadata { name: "base".to_string(), + display_name: None, priority: 0, description: None, string_overrides: HashMap::new(), @@ -487,6 +493,7 @@ mod tests { maps: vec![], layers: vec![ModpkgLayerMetadata { name: "base".to_string(), + display_name: None, priority: 0, description: None, string_overrides: HashMap::new(), @@ -522,6 +529,7 @@ mod tests { layers: vec![ ModpkgLayerMetadata { name: "base".to_string(), + display_name: None, priority: 0, description: None, string_overrides: HashMap::from([( @@ -531,6 +539,7 @@ mod tests { }, ModpkgLayerMetadata { name: "chroma1".to_string(), + display_name: Some("Pink chroma".to_string()), priority: 10, description: Some("Pink chroma".to_string()), string_overrides: HashMap::from([( diff --git a/crates/ltk_modpkg/src/project.rs b/crates/ltk_modpkg/src/project.rs index ff525fa..d5a3bfe 100644 --- a/crates/ltk_modpkg/src/project.rs +++ b/crates/ltk_modpkg/src/project.rs @@ -250,6 +250,7 @@ fn build_metadata_layers(mod_project: &ModProject) -> Vec { // Base layer: always present, even if omitted from config let base_from_config = mod_project.layers.iter().find(|l| l.name == "base"); + let base_display_name = base_from_config.and_then(|l| l.display_name.clone()); let base_description = base_from_config .and_then(|l| l.description.clone()) .or_else(|| Some("Base layer of the mod".to_string())); @@ -259,6 +260,7 @@ fn build_metadata_layers(mod_project: &ModProject) -> Vec { layers.push(ModpkgLayerMetadata { name: "base".to_string(), + display_name: base_display_name, priority: 0, description: base_description, string_overrides: base_string_overrides, @@ -268,6 +270,7 @@ fn build_metadata_layers(mod_project: &ModProject) -> Vec { for layer in mod_project.layers.iter().filter(|l| l.name != "base") { layers.push(ModpkgLayerMetadata { name: layer.name.clone(), + display_name: layer.display_name.clone(), priority: layer.priority, description: layer.description.clone(), string_overrides: layer.string_overrides.clone(), diff --git a/crates/ltk_overlay/src/builder/metadata.rs b/crates/ltk_overlay/src/builder/metadata.rs index a1da46b..3007ff4 100644 --- a/crates/ltk_overlay/src/builder/metadata.rs +++ b/crates/ltk_overlay/src/builder/metadata.rs @@ -421,6 +421,7 @@ mod tests { .enumerate() .map(|(i, name)| ModProjectLayer { name: name.to_string(), + display_name: None, priority: i as i32, description: None, string_overrides: HashMap::new(), diff --git a/crates/ltk_overlay/src/modpkg_content.rs b/crates/ltk_overlay/src/modpkg_content.rs index 3b69949..4e0fce3 100644 --- a/crates/ltk_overlay/src/modpkg_content.rs +++ b/crates/ltk_overlay/src/modpkg_content.rs @@ -48,6 +48,7 @@ impl ModContentProvider for ModpkgContent { let meta_layer = metadata.layers.iter().find(|ml| ml.name == l.name); ModProjectLayer { name: l.name.clone(), + display_name: meta_layer.and_then(|ml| ml.display_name.clone()), priority: l.priority, description: meta_layer.and_then(|ml| ml.description.clone()), string_overrides: meta_layer