From 1cba7db9b602d768b5e2248816ada58ad6d72d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 25 Jun 2021 18:47:03 +0200 Subject: [PATCH] Update `assets_manager` to 0.5 --- Cargo.lock | 5 +- assets/voxygen/i18n/PL/_manifest.ron | 3 - assets/voxygen/i18n/cz_CZ/_manifest.ron | 1 - assets/voxygen/i18n/de_DE/_manifest.ron | 3 - assets/voxygen/i18n/en/_manifest.ron | 3 - assets/voxygen/i18n/es_ES/_manifest.ron | 3 - assets/voxygen/i18n/es_la/_manifest.ron | 1 - assets/voxygen/i18n/fr_FR/_manifest.ron | 3 - assets/voxygen/i18n/it_IT/_manifest.ron | 3 - assets/voxygen/i18n/ja_JP/_manifest.ron | 3 - assets/voxygen/i18n/nl/_manifest.ron | 1 - assets/voxygen/i18n/no_nb/_manifest.ron | 1 - assets/voxygen/i18n/pt_BR/_manifest.ron | 3 - assets/voxygen/i18n/pt_PT/_manifest.ron | 1 - assets/voxygen/i18n/ru_RU/_manifest.ron | 1 - assets/voxygen/i18n/sv/_manifest.ron | 3 - assets/voxygen/i18n/tr_TR/_manifest.ron | 3 - assets/voxygen/i18n/uk_UA/_manifest.ron | 3 - assets/voxygen/i18n/vi_VI/_manifest.ron | 1 - assets/voxygen/i18n/zh_CN/_manifest.ron | 3 - assets/voxygen/i18n/zh_TW/_manifest.ron | 1 - common/assets/Cargo.toml | 2 +- common/assets/src/lib.rs | 85 ++++++++------------ common/src/comp/inventory/item/mod.rs | 29 ++----- common/src/comp/inventory/loadout_builder.rs | 31 ++----- common/src/generation.rs | 25 +----- common/src/lottery.rs | 29 +------ common/src/skillset_builder.rs | 36 ++------- voxygen/i18n/src/analysis.rs | 17 ++-- voxygen/i18n/src/data.rs | 81 +++++++++---------- voxygen/i18n/src/verification.rs | 31 ++----- voxygen/src/audio/ambient.rs | 18 ++--- voxygen/src/audio/mod.rs | 24 +++--- voxygen/src/audio/music.rs | 9 +-- voxygen/src/audio/sfx/mod.rs | 19 ++--- voxygen/src/audio/soundcache.rs | 22 +++-- voxygen/src/main.rs | 1 - world/Cargo.toml | 1 - 38 files changed, 165 insertions(+), 344 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43527b3c08..67d386a314 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,9 +214,9 @@ dependencies = [ [[package]] name = "assets_manager" -version = "0.4.4" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "792c2eca2af86c76ffd3e72ca564c33b5a5551d5ac3f4f87dce8c0b7c6434061" +checksum = "f17769d44fe3eee8cdc255520183fee4e76b30f105de6431cd034e1d7a6f0499" dependencies = [ "ahash 0.7.4", "bincode", @@ -6143,7 +6143,6 @@ name = "veloren-world" version = "0.10.0" dependencies = [ "arr_macro", - "assets_manager", "bincode", "bitvec", "criterion", diff --git a/assets/voxygen/i18n/PL/_manifest.ron b/assets/voxygen/i18n/PL/_manifest.ron index b37f17729e..204f497d07 100644 --- a/assets/voxygen/i18n/PL/_manifest.ron +++ b/assets/voxygen/i18n/PL/_manifest.ron @@ -27,9 +27,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { }, diff --git a/assets/voxygen/i18n/cz_CZ/_manifest.ron b/assets/voxygen/i18n/cz_CZ/_manifest.ron index e44acdd7f5..d5a6c1bef5 100644 --- a/assets/voxygen/i18n/cz_CZ/_manifest.ron +++ b/assets/voxygen/i18n/cz_CZ/_manifest.ron @@ -27,7 +27,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [], string_map: { // Texts used in multiple locations with the same formatting "common.username": "jméno", diff --git a/assets/voxygen/i18n/de_DE/_manifest.ron b/assets/voxygen/i18n/de_DE/_manifest.ron index 6af2f586b5..fc78584caf 100644 --- a/assets/voxygen/i18n/de_DE/_manifest.ron +++ b/assets/voxygen/i18n/de_DE/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/en/_manifest.ron b/assets/voxygen/i18n/en/_manifest.ron index 2be067818b..087c8d13ef 100644 --- a/assets/voxygen/i18n/en/_manifest.ron +++ b/assets/voxygen/i18n/en/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/es_ES/_manifest.ron b/assets/voxygen/i18n/es_ES/_manifest.ron index ae76138733..0af09c90cb 100644 --- a/assets/voxygen/i18n/es_ES/_manifest.ron +++ b/assets/voxygen/i18n/es_ES/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/es_la/_manifest.ron b/assets/voxygen/i18n/es_la/_manifest.ron index fb8c8b4659..f746bc9812 100644 --- a/assets/voxygen/i18n/es_la/_manifest.ron +++ b/assets/voxygen/i18n/es_la/_manifest.ron @@ -41,7 +41,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [], string_map: { /// Start Common section // Texts used in multiple locations with the same formatting diff --git a/assets/voxygen/i18n/fr_FR/_manifest.ron b/assets/voxygen/i18n/fr_FR/_manifest.ron index 5178158aa9..f7c3372ce9 100644 --- a/assets/voxygen/i18n/fr_FR/_manifest.ron +++ b/assets/voxygen/i18n/fr_FR/_manifest.ron @@ -27,9 +27,6 @@ scale_ratio: 0.9, ), }, - sub_directories: [ - "hud" - ], string_map: { }, diff --git a/assets/voxygen/i18n/it_IT/_manifest.ron b/assets/voxygen/i18n/it_IT/_manifest.ron index 2a367ddb1d..99f5180143 100644 --- a/assets/voxygen/i18n/it_IT/_manifest.ron +++ b/assets/voxygen/i18n/it_IT/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/ja_JP/_manifest.ron b/assets/voxygen/i18n/ja_JP/_manifest.ron index 65e8766c39..94b254a111 100644 --- a/assets/voxygen/i18n/ja_JP/_manifest.ron +++ b/assets/voxygen/i18n/ja_JP/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 0.9, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/nl/_manifest.ron b/assets/voxygen/i18n/nl/_manifest.ron index 0083dfd577..b6324abc02 100644 --- a/assets/voxygen/i18n/nl/_manifest.ron +++ b/assets/voxygen/i18n/nl/_manifest.ron @@ -41,7 +41,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [], string_map: { /// Start Common section // Texts used in multiple locations with the same formatting diff --git a/assets/voxygen/i18n/no_nb/_manifest.ron b/assets/voxygen/i18n/no_nb/_manifest.ron index 7af0ed0755..d414498d62 100644 --- a/assets/voxygen/i18n/no_nb/_manifest.ron +++ b/assets/voxygen/i18n/no_nb/_manifest.ron @@ -41,7 +41,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [], string_map: { /// Start Common section // Texts used in multiple locations with the same formatting diff --git a/assets/voxygen/i18n/pt_BR/_manifest.ron b/assets/voxygen/i18n/pt_BR/_manifest.ron index f7bf9aff47..8378a9c84b 100644 --- a/assets/voxygen/i18n/pt_BR/_manifest.ron +++ b/assets/voxygen/i18n/pt_BR/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/pt_PT/_manifest.ron b/assets/voxygen/i18n/pt_PT/_manifest.ron index ca05077318..6bdc0835b9 100644 --- a/assets/voxygen/i18n/pt_PT/_manifest.ron +++ b/assets/voxygen/i18n/pt_PT/_manifest.ron @@ -27,7 +27,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [], string_map: { /// Start Common section // Texts used in multiple locations with the same formatting diff --git a/assets/voxygen/i18n/ru_RU/_manifest.ron b/assets/voxygen/i18n/ru_RU/_manifest.ron index 25d1d25c93..dc396f3f6c 100644 --- a/assets/voxygen/i18n/ru_RU/_manifest.ron +++ b/assets/voxygen/i18n/ru_RU/_manifest.ron @@ -29,7 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [], string_map: { diff --git a/assets/voxygen/i18n/sv/_manifest.ron b/assets/voxygen/i18n/sv/_manifest.ron index 30c7b109a5..2355e0b493 100644 --- a/assets/voxygen/i18n/sv/_manifest.ron +++ b/assets/voxygen/i18n/sv/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/tr_TR/_manifest.ron b/assets/voxygen/i18n/tr_TR/_manifest.ron index ce936b22c3..4584b27293 100644 --- a/assets/voxygen/i18n/tr_TR/_manifest.ron +++ b/assets/voxygen/i18n/tr_TR/_manifest.ron @@ -41,9 +41,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/uk_UA/_manifest.ron b/assets/voxygen/i18n/uk_UA/_manifest.ron index 6db06f78b0..760c92db7b 100644 --- a/assets/voxygen/i18n/uk_UA/_manifest.ron +++ b/assets/voxygen/i18n/uk_UA/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/vi_VI/_manifest.ron b/assets/voxygen/i18n/vi_VI/_manifest.ron index 8db88e3e55..b5ee1a57d1 100644 --- a/assets/voxygen/i18n/vi_VI/_manifest.ron +++ b/assets/voxygen/i18n/vi_VI/_manifest.ron @@ -29,7 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [], string_map: { /// Start Common section diff --git a/assets/voxygen/i18n/zh_CN/_manifest.ron b/assets/voxygen/i18n/zh_CN/_manifest.ron index 7377f7cdc2..f6fa399ab6 100644 --- a/assets/voxygen/i18n/zh_CN/_manifest.ron +++ b/assets/voxygen/i18n/zh_CN/_manifest.ron @@ -29,9 +29,6 @@ scale_ratio: 1.0, ), }, - sub_directories: [ - "hud" - ], string_map: { diff --git a/assets/voxygen/i18n/zh_TW/_manifest.ron b/assets/voxygen/i18n/zh_TW/_manifest.ron index e60aea17cb..fa00cc01f4 100644 --- a/assets/voxygen/i18n/zh_TW/_manifest.ron +++ b/assets/voxygen/i18n/zh_TW/_manifest.ron @@ -27,7 +27,6 @@ scale_ratio: 0.75, ), }, - sub_directories: [], string_map: { /// Start Common section // Texts used in multiple locations with the same formatting diff --git a/common/assets/Cargo.toml b/common/assets/Cargo.toml index e4e67aed29..4eb316a64c 100644 --- a/common/assets/Cargo.toml +++ b/common/assets/Cargo.toml @@ -7,7 +7,7 @@ version = "0.10.0" [dependencies] lazy_static = "1.4.0" -assets_manager = {version = "0.4.2", features = ["bincode", "ron", "json", "hot-reloading"]} +assets_manager = {version = "0.5.0", features = ["bincode", "ron", "json", "hot-reloading"]} ron = { version = "0.6", default-features = false } dot_vox = "4.0" image = { version = "0.23.12", default-features = false, features = ["png"] } diff --git a/common/assets/src/lib.rs b/common/assets/src/lib.rs index e8807680e2..886670a11a 100644 --- a/common/assets/src/lib.rs +++ b/common/assets/src/lib.rs @@ -3,19 +3,15 @@ use dot_vox::DotVoxData; use image::DynamicImage; use lazy_static::lazy_static; -use std::{ - borrow::Cow, - fs, io, - path::{Path, PathBuf}, - sync::Arc, -}; +use std::{borrow::Cow, path::PathBuf, sync::Arc}; pub use assets_manager::{ - asset::Ron, + asset::{DirLoadable, Ron}, loader::{ self, BincodeLoader, BytesLoader, JsonLoader, LoadFrom, Loader, RonLoader, StringLoader, }, - source, Asset, AssetCache, BoxedError, Compound, Error, + source::{self, Source}, + Asset, AssetCache, BoxedError, Compound, Error, SharedString, }; lazy_static! { @@ -28,7 +24,7 @@ pub fn start_hot_reloading() { ASSETS.enhance_hot_reloading(); } pub type AssetHandle = assets_manager::Handle<'static, T>; pub type AssetGuard = assets_manager::AssetGuard<'static, T>; -pub type AssetDir = assets_manager::DirReader<'static, T, source::FileSystem>; +pub type AssetDirHandle = assets_manager::DirHandle<'static, T, source::FileSystem>; /// The Asset trait, which is implemented by all structures that have their data /// stored in the filesystem. @@ -51,6 +47,13 @@ pub trait AssetExt: Sized + Send + Sync + 'static { Self::load(specifier).map(AssetHandle::cloned) } + fn load_or_insert_with( + specifier: &str, + default: impl FnOnce(Error) -> Self, + ) -> AssetHandle { + Self::load(specifier).unwrap_or_else(|err| Self::get_or_insert(specifier, default(err))) + } + /// Function used to load essential assets from the filesystem or the cache. /// It will panic if the asset is not found. Example usage: /// ```no_run @@ -79,16 +82,31 @@ pub trait AssetExt: Sized + Send + Sync + 'static { } fn load_owned(specifier: &str) -> Result; + + fn get_or_insert(specifier: &str, default: Self) -> AssetHandle; } -pub fn load_dir(specifier: &str) -> Result, Error> { - Ok(ASSETS.load_dir(specifier)?) +pub fn load_dir( + specifier: &str, + recursive: bool, +) -> Result, Error> { + let specifier = specifier.strip_suffix(".*").unwrap_or(specifier); + ASSETS.load_dir(specifier, recursive) +} + +#[track_caller] +pub fn load_expect_dir(specifier: &str, recursive: bool) -> AssetDirHandle { + load_dir(specifier, recursive).expect("Failed loading directory") } impl AssetExt for T { fn load(specifier: &str) -> Result, Error> { ASSETS.load(specifier) } fn load_owned(specifier: &str) -> Result { ASSETS.load_owned(specifier) } + + fn get_or_insert(specifier: &str, default: Self) -> AssetHandle { + ASSETS.get_or_insert(specifier, default) + } } pub struct Image(pub Arc); @@ -223,52 +241,19 @@ lazy_static! { /// Returns the actual path of the specifier with the extension. /// /// For directories, give `""` as extension. -pub fn path_of(specifier: &str, ext: &str) -> PathBuf { ASSETS.source().path_of(specifier, ext) } - -fn get_dir_files(files: &mut Vec, path: &Path, specifier: &str) -> io::Result<()> { - for entry in (fs::read_dir(path)?).flatten() { - let path = entry.path(); - let maybe_stem = path.file_stem().and_then(|stem| stem.to_str()); - - if let Some(stem) = maybe_stem { - let specifier = format!("{}.{}", specifier, stem); - - if path.is_dir() { - get_dir_files(files, &path, &specifier)?; - } else { - files.push(specifier); - } - } - } - - Ok(()) -} - -pub struct Directory(Vec); - -impl Directory { - pub fn iter(&self) -> impl Iterator { self.0.iter() } -} - -impl Compound for Directory { - fn load(_: &AssetCache, specifier: &str) -> Result { - let specifier = specifier.strip_suffix(".*").unwrap_or(specifier); - let root = ASSETS.source().path_of(specifier, ""); - let mut files = Vec::new(); - - get_dir_files(&mut files, &root, specifier)?; - - Ok(Directory(files)) - } +pub fn path_of(specifier: &str, ext: &str) -> PathBuf { + ASSETS + .source() + .path_of(source::DirEntry::File(specifier, ext)) } #[warn(clippy::pedantic)] #[cfg(feature = "asset_tweak")] pub mod asset_tweak { - // Return path to repository by searching 10 directories back - use super::{find_root, fs, Asset, AssetExt, Path, RonLoader}; + use super::{find_root, Asset, AssetExt, RonLoader}; use ron::ser::{to_writer_pretty, PrettyConfig}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; + use std::{fs, path::Path}; #[derive(Clone, Deserialize, Serialize)] struct AssetTweakWrapper(T); diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index d246a16039..9130d1c90b 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -514,9 +514,10 @@ impl assets::Compound for ItemDef { ) -> Result { // load from the filesystem first, but if the file doesn't exist, see if it's a // programmaticly-generated asset - let raw = cache - .load_owned::(specifier) - .or_else(|e| modular::synthesize_modular_asset(specifier).ok_or(e))?; + let raw = match cache.load::(specifier) { + Ok(handle) => handle.cloned(), + Err(e) => modular::synthesize_modular_asset(specifier).ok_or(e)?, + }; let RawItemDef { name, @@ -569,24 +570,6 @@ impl assets::Asset for RawItemDef { #[derive(Debug)] pub struct OperationFailure; -#[derive(Clone)] -struct ItemList(Vec); -impl assets::Compound for ItemList { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { - let list = cache - .load::(specifier)? - .read() - .iter() - .map(|spec| Item::new_from_asset(spec)) - .collect::>()?; - - Ok(ItemList(list)) - } -} - impl Item { // TODO: consider alternatives such as default abilities that can be added to a // loadout when no weapon is present @@ -634,7 +617,9 @@ impl Item { /// Creates a Vec containing one of each item that matches the provided /// asset glob pattern pub fn new_from_asset_glob(asset_glob: &str) -> Result, Error> { - Ok(ItemList::load_cloned(asset_glob)?.0) + let specifier = asset_glob.strip_suffix(".*").unwrap_or(asset_glob); + let defs = assets::load_dir::(specifier, true)?; + defs.ids().map(Item::new_from_asset).collect() } /// Creates a new instance of an `Item from the provided asset identifier if diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 2eb0a990d7..2fbb27f818 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -716,10 +716,7 @@ impl LoadoutBuilder { #[cfg(test)] mod tests { use super::*; - use crate::{ - assets::{AssetExt, Error}, - comp::{self, Body}, - }; + use crate::comp::{self, Body}; use rand::thread_rng; use strum::IntoEnumIterator; @@ -788,31 +785,13 @@ mod tests { #[test] fn test_all_loadout_assets() { - #[derive(Clone)] - struct LoadoutList(Vec); - impl assets::Compound for LoadoutList { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { - let list = cache - .load::(specifier)? - .read() - .iter() - .map(|spec| LoadoutSpec::load_cloned(spec)) - .collect::>()?; - - Ok(Self(list)) - } - } - // It just load everything that could // TODO: add some checks, e.g. that Armor(Head) key correspond // to Item with ItemKind Head(_) - let loadouts = LoadoutList::load_expect_cloned("common.loadout.*").0; - for loadout in loadouts { - let spec = loadout.0; - for (key, entry) in spec { + let loadouts = assets::load_expect_dir::("common.loadout", true); + for loadout in loadouts.iter() { + let spec = loadout.read(); + for (&key, entry) in &spec.0 { entry.validate(key); } } diff --git a/common/src/generation.rs b/common/src/generation.rs index 4994a93702..035b42f68d 100644 --- a/common/src/generation.rs +++ b/common/src/generation.rs @@ -308,31 +308,12 @@ pub fn get_npc_name< mod tests { use super::*; use crate::{comp::inventory::slot::EquipSlot, SkillSetBuilder}; - use assets::Error; #[test] fn test_all_entity_assets() { - #[derive(Clone)] - struct EntityList(Vec); - impl assets::Compound for EntityList { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { - let list = cache - .load::(specifier)? - .read() - .iter() - .map(|spec| EntityConfig::load_cloned(spec)) - .collect::>()?; - - Ok(Self(list)) - } - } - // It just load everything that could - let entity_configs = EntityList::load_expect_cloned("common.entity.*").0; - for config in entity_configs { + let entity_configs = assets::load_expect_dir::("common.entity", true); + for config in entity_configs.iter() { let EntityConfig { main_tool, second_tool, @@ -341,7 +322,7 @@ mod tests { name: _name, body, loot, - } = config; + } = config.cloned(); if let Some(main_tool) = main_tool { main_tool.validate(EquipSlot::ActiveMainhand); diff --git a/common/src/lottery.rs b/common/src/lottery.rs index b110d4b5e3..84731c034e 100644 --- a/common/src/lottery.rs +++ b/common/src/lottery.rs @@ -111,31 +111,10 @@ impl LootSpec { #[cfg(test)] mod tests { use super::*; - use crate::{ - assets::{AssetExt, Error}, - comp::Item, - }; + use crate::{assets, comp::Item}; #[test] fn test_loot_tables() { - #[derive(Clone)] - struct LootTableList(Vec>); - impl assets::Compound for LootTableList { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { - let list = cache - .load::(specifier)? - .read() - .iter() - .map(|spec| Lottery::::load_cloned(spec)) - .collect::>()?; - - Ok(LootTableList(list)) - } - } - fn validate_table_contents(table: Lottery) { for (_, item) in table.iter() { match item { @@ -165,9 +144,9 @@ mod tests { } } - let loot_tables = LootTableList::load_expect_cloned("common.loot_tables.*").0; - for loot_table in loot_tables { - validate_table_contents(loot_table); + let loot_tables = assets::load_expect_dir::>("common.loot_tables", true); + for loot_table in loot_tables.iter() { + validate_table_contents(loot_table.cloned()); } } } diff --git a/common/src/skillset_builder.rs b/common/src/skillset_builder.rs index 4f5726b1d2..5cdab8377c 100644 --- a/common/src/skillset_builder.rs +++ b/common/src/skillset_builder.rs @@ -29,13 +29,13 @@ enum SkillNode { #[must_use] fn skills_from_asset_expect(asset_specifier: &str) -> Vec<(Skill, Option)> { - let nodes = SkillSetTree::load_expect(asset_specifier).read().0.clone(); + let nodes = SkillSetTree::load_expect(asset_specifier).read(); - skills_from_nodes(nodes) + skills_from_nodes(&nodes.0) } #[must_use] -fn skills_from_nodes(nodes: Vec) -> Vec<(Skill, Option)> { +fn skills_from_nodes(nodes: &[SkillNode]) -> Vec<(Skill, Option)> { let mut skills = Vec::new(); for node in nodes { match node { @@ -43,10 +43,10 @@ fn skills_from_nodes(nodes: Vec) -> Vec<(Skill, Option)> { skills.append(&mut skills_from_asset_expect(&asset)); }, SkillNode::Skill(req) => { - skills.push(req); + skills.push(*req); }, SkillNode::Group(group) => { - skills.push((Skill::UnlockGroup(group), None)); + skills.push((Skill::UnlockGroup(*group), None)); }, } } @@ -148,34 +148,14 @@ fn skill_is_applied(skill_set: &SkillSet, skill: Skill, level: Option) -> b #[cfg(test)] mod tests { use super::*; - use assets::Error; #[test] fn test_all_skillset_assets() { - #[derive(Clone)] - struct SkillSetList(Vec); - - impl assets::Compound for SkillSetList { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { - let list = cache - .load::(specifier)? - .read() - .iter() - .map(|spec| SkillSetTree::load_cloned(spec)) - .collect::>()?; - - Ok(Self(list)) - } - } - - let skillsets = SkillSetList::load_expect_cloned("common.skillset.*").0; - for skillset in skillsets { + let skillsets = assets::load_expect_dir::("common.skillset", true); + for skillset in skillsets.iter() { std::mem::drop({ let mut skillset_builder = SkillSetBuilder::default(); - let nodes = skillset.0; + let nodes = &*skillset.read().0; let tree = skills_from_nodes(nodes); for (skill, level) in tree { skillset_builder = skillset_builder.with_skill(skill, level); diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index 50887955fd..6a58de7b8c 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -222,7 +222,7 @@ fn complete_key_versions<'a>( ) { //TODO: review unwraps in this file - // For each file (if it's not a directory) in directory + // For each file in directory for i18n_file in root_dir.join(&lang_dir).read_dir().unwrap().flatten() { if let Ok(file_type) = i18n_file.file_type() { if file_type.is_file() { @@ -240,6 +240,15 @@ fn complete_key_versions<'a>( ) }); i18n_key_versions.extend(generate_key_version(&repo, &i18n, &path, &i18n_blob)); + } else if file_type.is_dir() { + // If it's a directory, recursively check it + complete_key_versions( + repo, + head_ref, + i18n_key_versions, + root_dir, + &i18n_file.path(), + ); } } } @@ -265,12 +274,6 @@ fn gather_state( // Gathering info about keys from language complete_key_versions(repo, head_ref, &mut i18n_map, root_dir, lang_dir); - // read HEAD for the subfolders - for sub_directory in loc.sub_directories.iter() { - let subdir_path = &lang_dir.join(sub_directory); - complete_key_versions(repo, head_ref, &mut i18n_map, root_dir, subdir_path); - } - i18n_map } diff --git a/voxygen/i18n/src/data.rs b/voxygen/i18n/src/data.rs index 6bee98faca..7e5e3b090c 100644 --- a/voxygen/i18n/src/data.rs +++ b/voxygen/i18n/src/data.rs @@ -1,9 +1,9 @@ -use crate::assets::{self, AssetExt, AssetGuard, AssetHandle}; +use crate::assets::{self, source::DirEntry, AssetExt, AssetGuard, AssetHandle}; use deunicode::deunicode; use hashbrown::{HashMap, HashSet}; use serde::{Deserialize, Serialize}; use std::{ - fs, + fs, io, path::{Path, PathBuf}, }; use tracing::warn; @@ -52,7 +52,6 @@ pub type Fonts = HashMap; /// See `Language` for more info on each attributes #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] pub(crate) struct RawLocalization { - pub(crate) sub_directories: Vec, pub(crate) convert_utf8_to_ascii: bool, pub(crate) fonts: Fonts, pub(crate) metadata: LanguageMetadata, @@ -63,9 +62,6 @@ pub(crate) struct RawLocalization { /// Store internationalization data #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Language { - /// A list of subdirectories to lookup for localization files - pub(crate) sub_directories: Vec, - /// A map storing the localized texts /// /// Localized content can be accessed using a String key. @@ -127,7 +123,6 @@ impl Language { impl Default for Language { fn default() -> Self { Self { - sub_directories: Vec::default(), string_map: HashMap::default(), vector_map: HashMap::default(), ..Default::default() @@ -138,7 +133,6 @@ impl Default for Language { impl From for Language { fn from(raw: RawLocalization) -> Self { Self { - sub_directories: raw.sub_directories, string_map: raw.string_map, vector_map: raw.vector_map, convert_utf8_to_ascii: raw.convert_utf8_to_ascii, @@ -179,7 +173,10 @@ impl assets::Compound for Language { // Walk through files in the folder, collecting localization fragment to merge // inside the asked_localization - for localization_asset in cache.load_dir::(asset_key)?.iter() { + for localization_asset in cache + .load_dir::(asset_key, true)? + .iter() + { localization .string_map .extend(localization_asset.read().string_map.clone()); @@ -188,21 +185,6 @@ impl assets::Compound for Language { .extend(localization_asset.read().vector_map.clone()); } - // Use the localization's subdirectory list to load fragments from there - for sub_directory in localization.sub_directories.iter() { - for localization_asset in cache - .load_dir::(&[asset_key, ".", sub_directory].concat())? - .iter() - { - localization - .string_map - .extend(localization_asset.read().string_map.clone()); - localization - .vector_map - .extend(localization_asset.read().vector_map.clone()); - } - } - // Update the text if UTF-8 to ASCII conversion is enabled if localization.convert_utf8_to_ascii { for value in localization.string_map.values_mut() { @@ -353,28 +335,48 @@ impl LocalizationHandle { pub fn reloaded(&mut self) -> bool { self.active.reloaded() } } +struct FindManifests; + +impl assets::Compound for FindManifests { + fn load(_: &assets::AssetCache, _: &str) -> Result { + Ok(Self) + } +} + +impl assets::DirLoadable for FindManifests { + fn select_ids( + source: &S, + specifier: &str, + ) -> io::Result> { + let mut specifiers = Vec::new(); + + source.read_dir(specifier, &mut |entry| { + if let DirEntry::Directory(spec) = entry { + let manifest_spec = [spec, ".", LANG_MANIFEST_FILE].concat(); + if source.exists(DirEntry::File(&manifest_spec, "ron")) { + specifiers.push(manifest_spec.into()); + } + } + })?; + + Ok(specifiers) + } +} + #[derive(Clone, Debug)] struct LocalizationList(Vec); impl assets::Compound for LocalizationList { - fn load( + fn load( cache: &assets::AssetCache, specifier: &str, ) -> Result { // List language directories - let mut languages = vec![]; - - let i18n_root = assets::path_of(specifier, ""); - for i18n_entry in (std::fs::read_dir(&i18n_root)?).flatten() { - if let Some(i18n_key) = i18n_entry.file_name().to_str() { - // load the root file of all the subdirectories - if let Ok(localization) = cache.load::( - &[specifier, ".", i18n_key, ".", LANG_MANIFEST_FILE].concat(), - ) { - languages.push(localization.read().metadata.clone()); - } - } - } + let languages = assets::load_expect_dir::(specifier, false) + .ids() + .filter_map(|spec| cache.load::(spec).ok()) + .map(|localization| localization.read().metadata.clone()) + .collect(); Ok(LocalizationList(languages)) } @@ -385,9 +387,6 @@ pub fn list_localizations() -> Vec { LocalizationList::load_expect_cloned("voxygen.i18n").0 } -/// Start hot reloading of i18n assets -pub fn start_hot_reloading() { assets::start_hot_reloading(); } - /// List localization directories as a `PathBuf` vector pub fn i18n_directories(i18n_dir: &Path) -> Vec { fs::read_dir(i18n_dir) diff --git a/voxygen/i18n/src/verification.rs b/voxygen/i18n/src/verification.rs index 066ee51980..ad7897c386 100644 --- a/voxygen/i18n/src/verification.rs +++ b/voxygen/i18n/src/verification.rs @@ -1,9 +1,7 @@ use ron::de::from_reader; use std::{fs, path::Path}; -use crate::data::{ - i18n_directories, LocalizationFragment, RawLocalization, LANG_MANIFEST_FILE, REFERENCE_LANG, -}; +use crate::data::{i18n_directories, LocalizationFragment, LANG_MANIFEST_FILE, REFERENCE_LANG}; fn verify_localization_directory(root_dir: &Path, directory_path: &Path) { // Walk through each file in the directory @@ -11,10 +9,7 @@ fn verify_localization_directory(root_dir: &Path, directory_path: &Path) { if let Ok(file_type) = i18n_file.file_type() { // Skip folders and the manifest file (which does not contain the same struct we // want to load) - if file_type.is_file() - && i18n_file.file_name().to_string_lossy() - != (LANG_MANIFEST_FILE.to_string() + ".ron") - { + if file_type.is_file() { let full_path = i18n_file.path(); println!("-> {:?}", full_path.strip_prefix(&root_dir).unwrap()); let f = fs::File::open(&full_path).expect("Failed opening file"); @@ -28,6 +23,8 @@ fn verify_localization_directory(root_dir: &Path, directory_path: &Path) { ); }, }; + } else if file_type.is_dir() { + verify_localization_directory(root_dir, &i18n_file.path()); } } } @@ -60,29 +57,11 @@ pub fn verify_all_localizations(root_dir: &Path, asset_path: &Path) { folder is empty?" ); for i18n_directory in i18n_directories { - // Attempt to load the manifest file - let manifest_path = i18n_directory.join(LANG_MANIFEST_FILE.to_string() + ".ron"); println!( "verifying {:?}", - manifest_path.strip_prefix(&root_dir).unwrap() + i18n_directory.strip_prefix(&root_dir).unwrap() ); - let f = fs::File::open(&manifest_path).expect("Failed opening file"); - let raw_localization: RawLocalization = match from_reader(f) { - Ok(v) => v, - Err(e) => { - panic!( - "Could not parse {} RON file, error: {}", - i18n_directory.to_string_lossy(), - e - ); - }, - }; // Walk through each files and try to load them verify_localization_directory(root_dir, &i18n_directory); - // Walk through each subdirectories and try to load files in them - for sub_directory in raw_localization.sub_directories.iter() { - let subdir_path = &i18n_directory.join(sub_directory); - verify_localization_directory(root_dir, &subdir_path); - } } } diff --git a/voxygen/src/audio/ambient.rs b/voxygen/src/audio/ambient.rs index f23d41902a..1c3941216b 100644 --- a/voxygen/src/audio/ambient.rs +++ b/voxygen/src/audio/ambient.rs @@ -127,8 +127,13 @@ impl AmbientMgr { } fn load_soundtrack_items() -> AssetHandle { - // Cannot fail: A default value is always provided - AmbientCollection::load_expect("voxygen.audio.ambient") + AmbientCollection::load_or_insert_with("voxygen.audio.ambient", |error| { + warn!( + "Error reading ambience config file, ambience will not be available: {:#?}", + error + ); + AmbientCollection::default() + }) } } @@ -136,13 +141,4 @@ impl assets::Asset for AmbientCollection { type Loader = assets::RonLoader; const EXTENSION: &'static str = "ron"; - - fn default_value(_: &str, error: assets::Error) -> Result { - warn!( - "Error reading ambience config file, ambience will not be available: {:#?}", - error - ); - - Ok(AmbientCollection::default()) - } } diff --git a/voxygen/src/audio/mod.rs b/voxygen/src/audio/mod.rs index e6f50f9e9f..aa217129b0 100644 --- a/voxygen/src/audio/mod.rs +++ b/voxygen/src/audio/mod.rs @@ -11,7 +11,7 @@ use channel::{AmbientChannel, AmbientChannelTag, MusicChannel, MusicChannelTag, use fader::Fader; use music::MusicTransitionManifest; use sfx::{SfxEvent, SfxTriggerItem}; -use soundcache::OggSound; +use soundcache::load_ogg; use std::time::Duration; use tracing::{debug, error, warn}; @@ -101,6 +101,15 @@ impl AudioFrontend { /// Construct in `no-audio` mode for debugging pub fn no_audio() -> Self { + let audio_manifest = "voxygen.audio.music_transition_manifest"; + let mtm = MusicTransitionManifest::load_or_insert_with(audio_manifest, |err| { + warn!( + "Error loading MusicTransitionManifest {:?}: {:?}", + audio_manifest, err + ); + MusicTransitionManifest::default() + }); + Self { // The following is for the disabled device switcher //device: "".to_string(), @@ -115,9 +124,7 @@ impl AudioFrontend { music_volume: 1.0, master_volume: 1.0, listener: Listener::default(), - // This expect should be fine, since `::default_value` - // is specified - mtm: AssetExt::load_expect("voxygen.audio.music_transition_manifest"), + mtm, } } @@ -264,10 +271,7 @@ impl AudioFrontend { underwater: bool, ) -> Result<(), rodio::decoder::DecoderError> { if self.audio_stream.is_some() { - let sound = OggSound::load_expect(sound) - .read() - .to_source() - .amplify(vol.unwrap_or(1.0)); + let sound = load_ogg(sound).amplify(vol.unwrap_or(1.0)); let listener = self.listener.clone(); if let Some(channel) = self.get_sfx_channel() { @@ -291,7 +295,7 @@ impl AudioFrontend { ) { if self.audio_stream.is_some() { if let Some(channel) = self.get_ambient_channel(channel_tag, volume_multiplier) { - channel.play(OggSound::load_expect(sound).read().to_source()); + channel.play(load_ogg(sound)); } } } @@ -347,7 +351,7 @@ impl AudioFrontend { fn play_music(&mut self, sound: &str, channel_tag: MusicChannelTag) { if self.music_enabled() { if let Some(channel) = self.get_music_channel(channel_tag) { - channel.play(OggSound::load_expect(sound).read().to_source(), channel_tag); + channel.play(load_ogg(sound), channel_tag); } } } diff --git a/voxygen/src/audio/music.rs b/voxygen/src/audio/music.rs index 502bb61ced..c1d25b598b 100644 --- a/voxygen/src/audio/music.rs +++ b/voxygen/src/audio/music.rs @@ -191,11 +191,6 @@ impl assets::Asset for MusicTransitionManifest { type Loader = assets::RonLoader; const EXTENSION: &'static str = "ron"; - - fn default_value(id: &str, e: assets::Error) -> Result { - warn!("Error loading MusicTransitionManifest {:?}: {:?}", id, e); - Ok(MusicTransitionManifest::default()) - } } impl Default for MusicMgr { @@ -429,10 +424,10 @@ impl assets::Compound for SoundtrackCollection { id: &str, ) -> Result { let inner = || -> Result<_, assets::Error> { - let manifest: AssetHandle>> = + let manifest: AssetHandle> = AssetExt::load(id)?; let mut soundtracks = SoundtrackCollection::default(); - for item in manifest.read().0.tracks.iter().cloned() { + for item in manifest.read().tracks.iter().cloned() { match item { RawSoundtrackItem::Individual(track) => soundtracks.tracks.push(track), RawSoundtrackItem::Segmented { diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index 061cd592ca..b918b013cd 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -558,8 +558,14 @@ impl SfxMgr { } fn load_sfx_items() -> AssetHandle { - // Cannot fail: A default value is always provided - SfxTriggers::load_expect("voxygen.audio.sfx") + SfxTriggers::load_or_insert_with("voxygen.audio.sfx", |error| { + warn!( + "Error reading sfx config file, sfx will not be available: {:#?}", + error + ); + + SfxTriggers::default() + }) } } @@ -567,13 +573,4 @@ impl assets::Asset for SfxTriggers { type Loader = assets::RonLoader; const EXTENSION: &'static str = "ron"; - - fn default_value(_: &str, error: assets::Error) -> Result { - warn!( - "Error reading sfx config file, sfx will not be available: {:#?}", - error - ); - - Ok(SfxTriggers::default()) - } } diff --git a/voxygen/src/audio/soundcache.rs b/voxygen/src/audio/soundcache.rs index f08a4bdab6..76b6ec2dcd 100644 --- a/voxygen/src/audio/soundcache.rs +++ b/voxygen/src/audio/soundcache.rs @@ -1,6 +1,6 @@ //! Handles caching and retrieval of decoded `.ogg` sfx sound data, eliminating //! the need to decode files on each playback -use common::assets::{self, Loader}; +use common::assets::{self, AssetExt, Loader}; use rodio::{source::Buffered, Decoder, Source}; use std::{borrow::Cow, io}; use tracing::warn; @@ -8,14 +8,13 @@ use tracing::warn; // Implementation of sound taken from this github issue: // https://github.com/RustAudio/rodio/issues/141 -pub struct SoundLoader; - +struct SoundLoader; #[derive(Clone)] -pub struct OggSound(Buffered>>>); +struct OggSound(Buffered>>>); impl Loader for SoundLoader { fn load(content: Cow<[u8]>, _: &str) -> Result { - let source = Decoder::new(io::Cursor::new(content.into_owned()))?.buffered(); + let source = Decoder::new_vorbis(io::Cursor::new(content.into_owned()))?.buffered(); Ok(OggSound(source)) } } @@ -34,13 +33,20 @@ impl assets::Asset for OggSound { /// Wrapper for decoded audio data impl OggSound { - pub fn to_source(&self) -> impl Source + Iterator { self.0.clone() } - pub fn empty() -> OggSound { SoundLoader::load( Cow::Borrowed(include_bytes!("../../../assets/voxygen/audio/null.ogg")), - "empty", + "ogg", ) .unwrap() } } + +pub fn load_ogg(specifier: &str) -> impl Source + Iterator { + OggSound::load_or_insert_with(specifier, |error| { + warn!(?specifier, ?error, "Failed to load sound"); + OggSound::empty() + }) + .cloned() + .0 +} diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 10e7742d10..6193b37337 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -144,7 +144,6 @@ fn main() { })); assets::start_hot_reloading(); - i18n::start_hot_reloading(); // Initialise watcher for animation hotreloading #[cfg(feature = "hot-anim")] diff --git a/world/Cargo.toml b/world/Cargo.toml index 7b8a288040..db64fc3724 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -34,7 +34,6 @@ packed_simd = { package = "packed_simd_2", version = "0.3.5" } rayon = "1.5" serde = { version = "1.0.110", features = ["derive"] } ron = { version = "0.6", default-features = false } -assets_manager = {version = "0.4.3", features = ["ron"]} # inline_tweak = "1.0.2" # compression benchmarks