use std::fs::write;
use std::mem::forget;
use std::path::PathBuf;
use anyhow::{Result, bail};
use clap::Parser;
use serde_json::{Value, json, to_string_pretty};
use strum::IntoEnumIterator;
use tiger_lib::{Everything, FileKind, Game, Item, ModFile};
#[derive(Parser)]
struct Cli {
modpath: PathBuf,
#[clap(short, long)]
output: PathBuf,
}
fn main() -> Result<()> {
let mut args = Cli::parse();
eprintln!("This scanner was made for Crusader Kings version 1.15 (Crown).");
eprintln!("If you are using a newer version of Crusader Kings, it may be inaccurate.");
eprintln!("The scanner does not find 100% of types of items in the mod.");
Game::set(Game::Ck3)?;
if args.modpath.is_dir() {
args.modpath.push("descriptor.mod");
}
let modfile = ModFile::read(&args.modpath)?;
let modpath = modfile.modpath();
if !modpath.exists() {
eprintln!("Looking for mod in {}", modpath.display());
bail!("Cannot find mod directory. Please make sure the .mod file is correct.");
}
eprintln!("Using mod directory: {}", modpath.display());
let mut everything =
Everything::new(None, None, None, None, &modpath, modfile.replace_paths())?;
everything.load_all();
let mut grand_json = json!({});
for itype in Item::iter() {
let mut vec = Vec::new();
for token in everything.iter_keys(itype).filter(|token| token.loc.kind == FileKind::Mod) {
let json = json!({
"key": token.to_string(),
"file": token.loc.pathname(),
"line": if token.loc.line == 0 { None } else { Some(token.loc.line) },
"column": if token.loc.column == 0 { None } else { Some(token.loc.column) },
});
vec.push(json);
}
if !vec.is_empty() {
grand_json[itype.to_string()] = Value::Array(vec);
}
}
let output = to_string_pretty(&grand_json)?;
eprintln!("Writing to {}", args.output.display());
write(&args.output, output)?;
forget(everything);
Ok(())
}