use bevy_ecs::{prelude::*, query::FilteredAccess};
use bevy_reflect::Reflect;
use serde::Deserialize;
use crate::prelude::{ModSchedules, Sandbox};
#[derive(Reflect, Debug, Eq, PartialEq, Hash, Clone, Copy, Deserialize, Default)]
pub enum ModAccess {
#[default]
World,
Sandbox(Entity),
}
impl ModAccess {
pub fn schedules(&self, world: &World) -> ModSchedules {
match self {
Self::Sandbox(entity) => world
.get::<Sandbox>(*entity)
.map(|sandbox| sandbox.schedules().clone())
.unwrap_or_else(ModSchedules::empty),
Self::World => world
.get_resource::<ModSchedules>()
.cloned()
.expect("ModSchedules be registered"),
}
}
pub fn filtered_access(&self, world: &World) -> FilteredAccess {
match self {
Self::Sandbox(entity) => world
.get::<Sandbox>(*entity)
.map(|sandbox| sandbox.access().clone())
.unwrap_or_else(FilteredAccess::matches_nothing),
Self::World => Sandbox::access_non_sandboxed(world),
}
}
pub fn validate(&self, world: &World) -> Result<(), String> {
if let ModAccess::Sandbox(entity) = self
&& world.get::<Sandbox>(*entity).is_none()
{
let display = self.display(world);
Err(format!("ModAccess {display} is not valid"))
} else {
Ok(())
}
}
pub fn display(&self, world: &World) -> String {
match self {
ModAccess::World => "Main World".into(),
ModAccess::Sandbox(entity) => match world.get(*entity).map(Name::as_str) {
Some(name) => format!("Sandbox \"{name}\""),
None => format!("Sandbox ({entity})"),
},
}
}
}