use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; #[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)] pub struct Config { pub name: String, #[serde(default = "default_version")] pub version: String, #[serde(default)] pub authors: Vec, pub script: String, pub available_cards: HashMap, pub piles: HashMap, pub player_piles: HashMap, } fn default_version() -> String { "0.0.0".into() } #[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)] pub struct Card { pub image: PathBuf, #[serde(flatten)] pub other: HashMap, } #[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)] pub struct Pile { #[serde(default)] pub cards: Vec, #[serde(flatten)] pub other: HashMap, } impl Pile { pub fn from_rhai_map(map: rhai::Map) -> Result> { // println!("{}", map.get("cards") // .ok_or("Pile doesn't have property cards")?.type_name()); let cards: Vec = rhai::serde::from_dynamic(map.get("cards").ok_or("Pile doesn't have property cards")?)?; let other_fallible: Vec>> = map.into_iter() .map(|(x, v)| (x.to_string(), v)) .filter(|(s, _)| s != &"cards".to_string()) .map(|(k, v)| Ok((k, rhai::serde::from_dynamic::(&v)?))) .collect(); let mut other = HashMap::new(); for x in other_fallible { let (k, v) = x?; other.insert(k, v); } Ok(Self { cards, other }) } } impl Config { pub fn load + std::fmt::Debug>(file: P) -> Self { serde_json::from_reader(std::fs::File::open(&file).unwrap()) .map_err(|e| { log::error!( "Malformed game defintion file @ {}", file.as_ref().display() ); log::error!("JSON Error: {}", e); panic!() }) .unwrap() } } pub fn setup() { if cfg!(debug_assertions) { if let Ok(e) = std::env::var("CARGO_MANIFEST_DIR") { std::fs::write( AsRef::::as_ref(&e) .join("schema") .join("game-config.json"), serde_json::to_string_pretty(&schemars::schema_for!(Config)).unwrap(), ) .unwrap() } } }