Define ZoneSpec, CultureProfile, and NpcBlueprint structs with serde/RON deserialization. Ship example RON files as schema contract for the copy team (#609, #610). Add validate-ron CLI for copy team to lint their files without compiling the server. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
85 lines
2.6 KiB
Rust
85 lines
2.6 KiB
Rust
//! RON content validator CLI (#611).
|
|
//!
|
|
//! Deserializes a RON file into the actual Rust structs and prints errors.
|
|
//! This is the copy team's lint tool — run it to check RON files without
|
|
//! needing to compile the full server.
|
|
//!
|
|
//! # Usage
|
|
//!
|
|
//! ```sh
|
|
//! # Via wrapper script (recommended):
|
|
//! tooling/validate-ron content/global/zone-identity-spec.example.ron zone
|
|
//! tooling/validate-ron content/global/culture-krenn.example.ron culture
|
|
//!
|
|
//! # Direct:
|
|
//! cargo run --bin validate_ron -- <file.ron> <zone|culture>
|
|
//! ```
|
|
|
|
use std::process;
|
|
|
|
use clap::Parser;
|
|
|
|
use settled_reach_server::npc::blueprint::{CultureProfile, ZoneSpec};
|
|
|
|
#[derive(Parser)]
|
|
#[command(
|
|
name = "validate_ron",
|
|
about = "Validate RON content files against Rust struct schemas"
|
|
)]
|
|
struct Args {
|
|
/// Path to the RON file to validate.
|
|
file: String,
|
|
/// Schema type: "zone" (ZoneSpec) or "culture" (CultureProfile).
|
|
schema: String,
|
|
}
|
|
|
|
fn main() {
|
|
let args = Args::parse();
|
|
|
|
let content = match std::fs::read_to_string(&args.file) {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
eprintln!("Error reading {}: {}", args.file, e);
|
|
process::exit(1);
|
|
}
|
|
};
|
|
|
|
match args.schema.as_str() {
|
|
"zone" => match ron::from_str::<ZoneSpec>(&content) {
|
|
Ok(spec) => {
|
|
println!("Valid ZoneSpec: {} ({})", spec.label, spec.zone_type);
|
|
println!(" {} roles, {} social sites", spec.roles.len(), spec.social_sites.len());
|
|
}
|
|
Err(e) => {
|
|
eprintln!("Invalid ZoneSpec in {}:", args.file);
|
|
eprintln!(" {}", e);
|
|
process::exit(1);
|
|
}
|
|
},
|
|
"culture" => match ron::from_str::<CultureProfile>(&content) {
|
|
Ok(profile) => {
|
|
println!("Valid CultureProfile: {} ({})", profile.name, profile.id);
|
|
println!(
|
|
" {} given names, {} family names",
|
|
profile.naming.given_names.len(),
|
|
profile.naming.family_names.len()
|
|
);
|
|
println!(
|
|
" {} filler words, {} favored traits",
|
|
profile.speech.filler_words.len(),
|
|
profile.values.favored_traits.len()
|
|
);
|
|
}
|
|
Err(e) => {
|
|
eprintln!("Invalid CultureProfile in {}:", args.file);
|
|
eprintln!(" {}", e);
|
|
process::exit(1);
|
|
}
|
|
},
|
|
other => {
|
|
eprintln!("Unknown schema type: '{}'. Use 'zone' or 'culture'.", other);
|
|
process::exit(1);
|
|
}
|
|
}
|
|
}
|