use bevy::asset::io::Reader;
use bevy::asset::{AssetLoader, LoadContext};
use bevy::reflect::TypePath;
use bevy_map_core::{EditorProject, MapProject};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum MapLoadError {
#[error("Failed to read file: {0}")]
Io(#[from] std::io::Error),
#[error("Failed to parse JSON: {0}")]
Json(#[from] serde_json::Error),
#[error("Invalid map format: {0}")]
InvalidFormat(String),
}
#[derive(Default, TypePath)]
pub struct MapProjectLoader;
impl AssetLoader for MapProjectLoader {
type Asset = MapProject;
type Settings = ();
type Error = MapLoadError;
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?;
if let Ok(editor_project) = serde_json::from_slice::<EditorProject>(&bytes) {
return editor_project
.to_map_project()
.ok_or_else(|| MapLoadError::InvalidFormat("No levels in project".to_string()));
}
let project: MapProject = serde_json::from_slice(&bytes)?;
project.validate().map_err(MapLoadError::InvalidFormat)?;
Ok(project)
}
fn extensions(&self) -> &[&str] {
&["map.json"]
}
}
pub fn load_level_from_str(json: &str) -> Result<bevy_map_core::Level, serde_json::Error> {
serde_json::from_str(json)
}
pub fn load_level_from_reader<R: std::io::Read>(
reader: R,
) -> Result<bevy_map_core::Level, serde_json::Error> {
serde_json::from_reader(reader)
}
pub fn load_level_from_bytes(bytes: &[u8]) -> Result<bevy_map_core::Level, serde_json::Error> {
serde_json::from_slice(bytes)
}
pub fn load_project_from_str(json: &str) -> Result<MapProject, serde_json::Error> {
serde_json::from_str(json)
}
pub fn load_project_from_bytes(bytes: &[u8]) -> Result<MapProject, serde_json::Error> {
serde_json::from_slice(bytes)
}