use crate::protocol::{ItemIndex, TileIndex}; use glam::IVec2; use log::debug; use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[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, Deserialize)] pub struct InitialMap { map: Vec, tiles: HashMap, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Gamedata { pub recipes: Vec, pub item_names: Vec, pub tile_names: Vec, #[serde(skip)] pub initial_map: HashMap, } pub fn build_gamedata(recipes_in: Vec>, map_in: InitialMap) -> 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(), }) } let mut initial_map = HashMap::new(); for (y, line) in map_in.map.iter().enumerate() { for (x, tile) in line.trim().char_indices() { debug!("{tile:?}"); let tile = register(&mut tile_names, map_in.tiles[&tile.to_string()].clone()); initial_map.insert(IVec2::new(x as i32, y as i32), tile); } } Gamedata { recipes, initial_map, 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, } } }