use std::{ffi::OsStr, fs::read_to_string, path::PathBuf}; use thiserror::Error; use crate::{ identifier::Identifier, registry::{Registries, Registry}, }; pub struct Datapack { pub name: String, path: PathBuf, } impl Datapack { pub fn new(path: PathBuf) -> Self { // TODO: Load name (and other info) from pack.mcmeta let name = path.file_name().unwrap().to_str().unwrap().to_string(); Self { name, path } } pub fn load(&self, registries: &mut Registries) -> Result<(), DatapackError> { println!("Loading datapack: {}", self.name); self.load_registry(&mut registries.trim_materials, "trim_material")?; self.load_registry(&mut registries.trim_patterns, "trim_pattern")?; self.load_registry(&mut registries.banner_patterns, "banner_pattern")?; self.load_registry(&mut registries.worldgen.biomes, "worldgen/biome")?; self.load_registry(&mut registries.damage_types, "damage_type")?; self.load_registry(&mut registries.dimension_types, "dimension_type")?; self.load_registry(&mut registries.wolf_variants, "wolf_variant")?; self.load_registry(&mut registries.painting_variants, "painting_variant")?; self.load_registry(&mut registries.chat_types, "chat_type")?; Ok(()) } fn load_registry( &self, registry: &mut Registry, path: &str, ) -> Result<(), DatapackError> { let namespaces: Vec<_> = self .path .join("data") .read_dir() .unwrap() .map(|f| f.unwrap().path()) .filter(|p| p.is_dir()) .collect(); for namespace in namespaces { let namespace_str = namespace .file_name() .and_then(OsStr::to_str) .ok_or(DatapackError::Utf8)?; let path = namespace.join(path); if let Ok(files) = std::fs::read_dir(path) { for file in files { let file = file?.path(); let name = file .file_stem() .and_then(OsStr::to_str) .ok_or(DatapackError::Utf8)?; let identfiier = Identifier::new_str(namespace_str, name); let data: T = serde_json::from_str(&read_to_string(file)?)?; registry.insert(identfiier, data); } } } Ok(()) } } #[derive(Debug, Error)] pub enum DatapackError { #[error("IO error while reading datapack: {0}")] Io(#[from] std::io::Error), #[error("Error while parsing JSON in datapack: {0}")] Json(#[from] serde_json::Error), #[error("Invalid UTF-8 in datapack")] Utf8, }