use crate::protocol::{ItemIndex, TileIndex}; use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)] #[serde(rename_all = "snake_case")] pub enum Action { #[default] Never, Passive(f32), Active(f32), Instant, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Recipe { pub tile: T, #[serde(default)] pub inputs: Vec, #[serde(default)] pub outputs: Vec, #[serde(default)] pub action: Action, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Gamedata { pub recipes: Vec, pub item_names: Vec, pub tile_names: Vec, } pub fn build_gamedata(recipes_in: Vec>) -> Gamedata { let mut item_names = Vec::new(); let mut tile_names = Vec::new(); let mut recipes = Vec::new(); for r in recipes_in { recipes.push(Recipe { action: r.action, tile: register(&mut tile_names, r.tile.clone()), inputs: r .inputs .clone() .into_iter() .map(|e| register(&mut item_names, e)) .collect(), outputs: r .outputs .clone() .into_iter() .map(|e| register(&mut item_names, e)) .collect(), }) } Gamedata { recipes, item_names, tile_names, } } fn register(db: &mut Vec, name: String) -> usize { if let Some(index) = db.iter().position(|e| e == &name) { index } else { let index = db.len(); db.push(name); index } } impl Gamedata { pub fn get_tile(&self, name: &str) -> Option { self.tile_names.iter().position(|t| t == name) } } impl Action { pub fn duration(&self) -> f32 { match self { Action::Instant | Action::Never => 0., Action::Passive(x) | Action::Active(x) => *x, } } }