fix hot reloading of combined manifests

This commit is contained in:
Christof Petig 2024-01-27 12:37:21 +01:00
parent bab8c713fb
commit cc93474c2f
5 changed files with 47 additions and 18 deletions

View File

@ -122,24 +122,42 @@ pub trait AssetExt: Sized + Send + Sync + 'static {
/// Extension to AssetExt to combine Ron files from filesystem and plugins /// Extension to AssetExt to combine Ron files from filesystem and plugins
pub trait AssetCombined: AssetExt { pub trait AssetCombined: AssetExt {
fn load_and_combine(specifier: &str) -> Result<AssetHandle<Self>, Error>; fn load_and_combine(
reloading_cache: AnyCache<'static>,
specifier: &str,
) -> Result<AssetHandle<Self>, Error>;
/// Load combined table without hot-reload support
fn load_and_combine_static(specifier: &str) -> Result<AssetHandle<Self>, Error> {
Self::load_and_combine(ASSETS.filesystem_cache(), specifier)
}
#[track_caller] #[track_caller]
fn load_expect_combined(specifier: &str) -> AssetHandle<Self> { fn load_expect_combined(
reloading_cache: AnyCache<'static>,
specifier: &str,
) -> AssetHandle<Self> {
// Avoid using `unwrap_or_else` to avoid breaking `#[track_caller]` // Avoid using `unwrap_or_else` to avoid breaking `#[track_caller]`
match Self::load_and_combine(specifier) { match Self::load_and_combine(reloading_cache, specifier) {
Ok(handle) => handle, Ok(handle) => handle,
Err(err) => { Err(err) => {
panic!("Failed loading essential combined asset: {specifier} (error={err:?})") panic!("Failed loading essential combined asset: {specifier} (error={err:?})")
}, },
} }
} }
/// Load combined table without hot-reload support, panic on error
#[track_caller]
fn load_expect_combined_static(specifier: &str) -> AssetHandle<Self> {
Self::load_expect_combined(ASSETS.filesystem_cache(), specifier)
}
} }
/// Extension to AnyCache to combine Ron files from filesystem and plugins /// Extension to AnyCache to combine Ron files from filesystem and plugins
pub trait CacheCombined<'a> { pub trait CacheCombined<'a> {
fn load_and_combine<A: Compound + Concatenate>( fn load_and_combine<A: Compound + Concatenate>(
self, self,
// reloading_cache: AnyCache,
id: &str, id: &str,
) -> Result<&'a assets_manager::Handle<A>, Error>; ) -> Result<&'a assets_manager::Handle<A>, Error>;
} }
@ -170,6 +188,7 @@ impl<T: Compound> AssetExt for T {
impl<'a> CacheCombined<'a> for AnyCache<'a> { impl<'a> CacheCombined<'a> for AnyCache<'a> {
fn load_and_combine<A: Compound + Concatenate>( fn load_and_combine<A: Compound + Concatenate>(
self, self,
// reloading_cache: AnyCache,
specifier: &str, specifier: &str,
) -> Result<&'a assets_manager::Handle<A>, Error> { ) -> Result<&'a assets_manager::Handle<A>, Error> {
#[cfg(feature = "plugins")] #[cfg(feature = "plugins")]
@ -178,7 +197,7 @@ impl<'a> CacheCombined<'a> for AnyCache<'a> {
|| { || {
tracing::info!("combine {specifier}"); tracing::info!("combine {specifier}");
let data: Result<A, _> = let data: Result<A, _> =
ASSETS.combine(|cache: AnyCache| cache.load_owned::<A>(specifier)); ASSETS.combine(self, |cache: AnyCache| cache.load_owned::<A>(specifier));
data.map(|data| self.get_or_insert(specifier, data)) data.map(|data| self.get_or_insert(specifier, data))
}, },
Ok, Ok,
@ -191,9 +210,13 @@ impl<'a> CacheCombined<'a> for AnyCache<'a> {
} }
} }
// this function bypasses hot-reloading!
impl<T: Compound + Concatenate> AssetCombined for T { impl<T: Compound + Concatenate> AssetCombined for T {
fn load_and_combine(specifier: &str) -> Result<AssetHandle<Self>, Error> { fn load_and_combine(
ASSETS.as_any_cache().load_and_combine(specifier) reloading_cache: AnyCache<'static>,
specifier: &str,
) -> Result<AssetHandle<Self>, Error> {
reloading_cache.load_and_combine(specifier)
} }
} }
@ -290,9 +313,12 @@ impl<T> Compound for MultiRon<T>
where where
T: for<'de> serde::Deserialize<'de> + Send + Sync + 'static + Concatenate, T: for<'de> serde::Deserialize<'de> + Send + Sync + 'static + Concatenate,
{ {
fn load(_cache: AnyCache, id: &SharedString) -> Result<Self, BoxedError> { // the passed cache registers with hot reloading
fn load(reloading_cache: AnyCache, id: &SharedString) -> Result<Self, BoxedError> {
ASSETS ASSETS
.combine(|cache: AnyCache| cache.load_owned::<Ron<T>>(id).map(|ron| ron.into_inner())) .combine(reloading_cache, |cache: AnyCache| {
cache.load_owned::<Ron<T>>(id).map(|ron| ron.into_inner())
})
.map(MultiRon) .map(MultiRon)
.map_err(Into::<BoxedError>::into) .map_err(Into::<BoxedError>::into)
} }

View File

@ -132,12 +132,18 @@ impl CombinedCache {
CombinedSource::new().map(|combined_source| Self(AssetCache::with_source(combined_source))) CombinedSource::new().map(|combined_source| Self(AssetCache::with_source(combined_source)))
} }
#[doc(hidden)]
// when not using a compound
pub(crate) fn filesystem_cache(&self) -> AnyCache<'_> { self.0.raw_source().fs.as_any_cache() }
/// Combine objects from filesystem and plugins /// Combine objects from filesystem and plugins
pub fn combine<T: Concatenate>( pub fn combine<T: Concatenate>(
&self, &self,
// this cache registers with hot reloading
reloading_cache: AnyCache,
mut load_from: impl FnMut(AnyCache) -> Result<T, assets_manager::Error>, mut load_from: impl FnMut(AnyCache) -> Result<T, assets_manager::Error>,
) -> Result<T, assets_manager::Error> { ) -> Result<T, assets_manager::Error> {
let mut result = load_from(self.0.raw_source().fs.as_any_cache()); let mut result = load_from(reloading_cache);
// Report a severe error from the filesystem asset even if later overwritten by // Report a severe error from the filesystem asset even if later overwritten by
// an Ok value from a plugin // an Ok value from a plugin
if let Err(ref fs_error) = result { if let Err(ref fs_error) = result {
@ -222,7 +228,4 @@ impl CombinedCache {
pub fn load_owned<A: Compound>(&self, id: &str) -> Result<A, assets_manager::Error> { pub fn load_owned<A: Compound>(&self, id: &str) -> Result<A, assets_manager::Error> {
self.0.load_owned(id) self.0.load_owned(id)
} }
#[inline]
pub fn as_any_cache(&self) -> AnyCache { self.0.as_any_cache() }
} }

View File

@ -242,7 +242,7 @@ lazy_static! {
}; };
pub static ref KITS: Vec<String> = { pub static ref KITS: Vec<String> = {
let mut kits = if let Ok(kits) = KitManifest::load_and_combine(KIT_MANIFEST_PATH) { let mut kits = if let Ok(kits) = KitManifest::load_and_combine_static(KIT_MANIFEST_PATH) {
let mut kits = kits.read().0.keys().cloned().collect::<Vec<String>>(); let mut kits = kits.read().0.keys().cloned().collect::<Vec<String>>();
kits.sort(); kits.sort();
kits kits
@ -255,7 +255,7 @@ lazy_static! {
}; };
static ref PRESETS: HashMap<String, Vec<(Skill, u8)>> = { static ref PRESETS: HashMap<String, Vec<(Skill, u8)>> = {
if let Ok(presets) = SkillPresetManifest::load_and_combine(PRESET_MANIFEST_PATH) { if let Ok(presets) = SkillPresetManifest::load_and_combine_static(PRESET_MANIFEST_PATH) {
presets.read().0.clone() presets.read().0.clone()
} else { } else {
warn!("Error while loading presets"); warn!("Error while loading presets");
@ -1304,12 +1304,12 @@ mod tests {
#[test] #[test]
fn test_loading_skill_presets() { fn test_loading_skill_presets() {
SkillPresetManifest::load_expect_combined(PRESET_MANIFEST_PATH); SkillPresetManifest::load_expect_combined_static(PRESET_MANIFEST_PATH);
} }
#[test] #[test]
fn test_load_kits() { fn test_load_kits() {
let kits = KitManifest::load_expect_combined(KIT_MANIFEST_PATH).read(); let kits = KitManifest::load_expect_combined_static(KIT_MANIFEST_PATH).read();
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
for kit in kits.0.values() { for kit in kits.0.values() {
for (item_id, _) in kit.iter() { for (item_id, _) in kit.iter() {

View File

@ -282,7 +282,7 @@ impl Concatenate for ResourceExperienceManifest {
lazy_static! { lazy_static! {
static ref RESOURCE_EXPERIENCE_MANIFEST: assets::AssetHandle<ResourceExperienceManifest> = static ref RESOURCE_EXPERIENCE_MANIFEST: assets::AssetHandle<ResourceExperienceManifest> =
assets::AssetCombined::load_expect_combined( assets::AssetCombined::load_expect_combined_static(
"server.manifests.resource_experience_manifest" "server.manifests.resource_experience_manifest"
); );
} }

View File

@ -76,7 +76,7 @@ pub struct ItemImgs {
impl ItemImgs { impl ItemImgs {
pub fn new(ui: &mut Ui, not_found: Id) -> Self { pub fn new(ui: &mut Ui, not_found: Id) -> Self {
let manifest = ItemImagesSpec::load_expect_combined("voxygen.item_image_manifest"); let manifest = ItemImagesSpec::load_expect_combined_static("voxygen.item_image_manifest");
let map = manifest let map = manifest
.read() .read()
.0 .0