use std::io;
use crate::ldtk::{loaded_level::LoadedLevel, Level};
use bevy::{
asset::{io::Reader, AssetLoader, LoadContext},
prelude::*,
};
use thiserror::Error;
#[derive(Clone, Debug, PartialEq, Reflect, Asset)]
pub struct LdtkExternalLevel {
data: Level,
}
impl LdtkExternalLevel {
#[cfg(test)]
pub fn new(data: Level) -> LdtkExternalLevel {
LdtkExternalLevel { data }
}
pub fn data(&self) -> LoadedLevel<'_> {
LoadedLevel::try_from(&self.data)
.expect("construction of LdtkExternalLevel should guarantee that the level is loaded.")
}
}
#[derive(Debug, Error)]
pub enum LdtkExternalLevelLoaderError {
#[error("encountered IO error reading LDtk level: {0}")]
Io(#[from] io::Error),
#[error("unable to deserialize LDtk level: {0}")]
Deserialize(#[from] serde_json::Error),
#[error("external LDtk level should contain all level data, but some level has null layers")]
NullLayers,
}
#[derive(Default, TypePath)]
pub struct LdtkExternalLevelLoader;
impl AssetLoader for LdtkExternalLevelLoader {
type Asset = LdtkExternalLevel;
type Settings = ();
type Error = LdtkExternalLevelLoaderError;
async fn load(
&self,
reader: &mut dyn Reader,
_settings: &Self::Settings,
_load_context: &mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let data: Level = serde_json::from_slice(&bytes)?;
if data.layer_instances.is_none() {
Err(LdtkExternalLevelLoaderError::NullLayers)?;
}
let ldtk_level = LdtkExternalLevel { data };
Ok(ldtk_level)
}
fn extensions(&self) -> &[&str] {
&["ldtkl"]
}
}
#[cfg(test)]
mod tests {
use fake::{Fake, Faker};
use crate::ldtk::fake::UnloadedLevelFaker;
use super::*;
#[test]
fn data_accessor_for_loaded_level_succeeds() {
let level: Level = Faker.fake();
let ldtk_external_level = LdtkExternalLevel::new(level.clone());
assert_eq!(ldtk_external_level.data().raw(), &level);
}
#[test]
#[should_panic]
fn data_accessor_for_unloaded_level_panics() {
let level: Level = UnloadedLevelFaker.fake();
let ldtk_external_level = LdtkExternalLevel::new(level.clone());
let _should_panic = ldtk_external_level.data();
}
}