use crate::prelude::*;
#[derive(Clone)]
pub struct World {
pub resources: Resources,
pub components: ComponentStores,
}
impl std::fmt::Debug for World {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("World").finish()
}
}
impl Default for World {
fn default() -> Self {
let resources = Resources::new();
resources.insert(Entities::default());
Self {
resources,
components: Default::default(),
}
}
}
impl World {
pub fn new() -> Self {
Self::default()
}
pub fn with_entities(entities: AtomicResource<Entities>) -> Self {
let resources = Resources::new();
resources
.untyped()
.insert_cell(entities.into_untyped())
.unwrap();
World {
resources,
components: default(),
}
}
pub fn maintain(&self) {
let mut entities = self.resource_mut::<Entities>();
for components in self.components.components.read_only_view().values() {
let mut components = components.borrow_mut();
let killed = entities.killed();
for &entity in killed {
unsafe {
components.remove_raw(entity, None);
}
}
}
entities.clear_killed();
}
pub fn run_system<'system, R, In, Out, S>(&self, system: S, input: In) -> Out
where
In: 'system,
Out: 'system,
S: IntoSystem<R, In, Out>,
S::Sys: 'system,
{
let mut s = system.system();
s.run(self, input)
}
pub fn entity_components<Q: QueryItem>(
&self,
entity: Entity,
query: Q,
) -> <Q::Iter as Iterator>::Item {
self.get_entity_components(entity, query).unwrap()
}
pub fn get_entity_components<Q: QueryItem>(
&self,
entity: Entity,
query: Q,
) -> Option<<Q::Iter as Iterator>::Item> {
let mut bitset = BitSetVec::default();
if self.resource::<Entities>().bitset().contains(entity) {
bitset.set(entity);
}
query.apply_bitset(&mut bitset);
match query.get_single_with_bitset(bitset.into()) {
Ok(components) => Some(components),
Err(QuerySingleError::NoEntities) => None,
Err(QuerySingleError::MultipleEntities) => {
panic!(
"Query returned a MultipleEntities error for a bitset that \
contains at most one enabled bit"
)
}
}
}
pub fn init_resource<R: HasSchema + FromWorld>(&mut self) -> RefMut<R> {
if unlikely(!self.resources.contains::<R>()) {
let value = R::from_world(self);
self.resources.insert(value);
}
self.resource_mut()
}
pub fn insert_resource<R: HasSchema>(&mut self, resource: R) -> Option<R> {
self.resources.insert(resource)
}
#[track_caller]
pub fn resource<T: HasSchema>(&self) -> Ref<T> {
match self.resources.get::<T>() {
Some(r) => r,
None => panic!(
"Requested resource {} does not exist in the `World`. \
Did you forget to add it using `world.insert_resource` / `world.init_resource`?",
std::any::type_name::<T>()
),
}
}
#[track_caller]
pub fn resource_mut<T: HasSchema>(&self) -> RefMut<T> {
match self.resources.get_mut::<T>() {
Some(r) => r,
None => panic!(
"Requested resource {} does not exist in the `World`. \
Did you forget to add it using `world.insert_resource` / `world.init_resource`?",
std::any::type_name::<T>()
),
}
}
pub fn get_resource<T: HasSchema>(&self) -> Option<Ref<T>> {
self.resources.get()
}
pub fn get_resource_mut<T: HasSchema>(&mut self) -> Option<RefMut<T>> {
self.resources.get_mut()
}
#[track_caller]
pub fn component<T: HasSchema>(&self) -> Ref<ComponentStore<T>> {
self.components.get::<T>().borrow()
}
#[track_caller]
pub fn component_mut<T: HasSchema>(&self) -> RefMut<ComponentStore<T>> {
self.components.get::<T>().borrow_mut()
}
pub fn load_snapshot(&mut self, snapshot: World) {
self.components = snapshot.components;
self.resources = snapshot.resources;
}
}
pub trait FromWorld {
fn from_world(world: &World) -> Self;
}
impl<T: Default> FromWorld for T {
fn from_world(_world: &World) -> Self {
T::default()
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use super::FromWorld;
#[derive(Clone, Copy, HasSchema, Debug, Eq, PartialEq, Default)]
#[repr(C)]
struct C(u32);
#[derive(Clone, HasSchema, Debug, Eq, PartialEq, Default)]
#[repr(C)]
struct Pos(i32, i32);
#[derive(Clone, HasSchema, Debug, Eq, PartialEq, Default)]
#[repr(C)]
struct Vel(i32, i32);
#[derive(Clone, HasSchema, Debug, Eq, PartialEq, Default)]
struct Marker;
fn setup_world(
mut entities: ResMut<Entities>,
mut pos_comps: CompMut<Pos>,
mut vel_comps: CompMut<Vel>,
mut marker_comps: CompMut<Marker>,
) {
let ent1 = entities.create();
pos_comps.insert(ent1, Pos(0, 100));
vel_comps.insert(ent1, Vel(0, -1));
let ent2 = entities.create();
pos_comps.insert(ent2, Pos(0, 0));
vel_comps.insert(ent2, Vel(1, 1));
marker_comps.insert(ent2, Marker);
}
fn pos_vel_system(entities: Res<Entities>, mut pos: CompMut<Pos>, vel: Comp<Vel>) {
for (_, (pos, vel)) in entities.iter_with((&mut pos, &vel)) {
pos.0 += vel.0;
pos.1 += vel.1;
}
}
fn test_after_setup_state(
entities: Res<Entities>,
pos: Comp<Pos>,
vel: Comp<Vel>,
marker: Comp<Marker>,
) {
let mut i = 0;
for (entity, (pos, vel)) in entities.iter_with((&pos, &vel)) {
let marker = marker.get(entity);
match (i, pos, vel, marker) {
(0, Pos(0, 100), Vel(0, -1), None) | (1, Pos(0, 0), Vel(1, 1), Some(Marker)) => (),
x => unreachable!("{:?}", x),
}
i += 1;
}
assert_eq!(i, 2);
}
fn test_pos_vel_1_run(
entities: Res<Entities>,
pos: Comp<Pos>,
vel: Comp<Vel>,
marker: Comp<Marker>,
) {
let mut i = 0;
for (entity, (pos, vel)) in entities.iter_with((&pos, &vel)) {
let marker = marker.get(entity);
match (i, pos, vel, marker) {
(0, Pos(0, 99), Vel(0, -1), None) | (1, Pos(1, 1), Vel(1, 1), Some(Marker)) => (),
x => unreachable!("{:?}", x),
}
i += 1;
}
assert_eq!(i, 2);
}
#[test]
fn sanity_check() {
let world = World::new();
world.run_system(setup_world, ());
let test = || {};
world.run_system(test, ());
world.run_system(pos_vel_system, ());
world.run_system(test_pos_vel_1_run, ());
}
#[test]
fn snapshot() {
let world1 = World::new();
world1.run_system(setup_world, ());
let snap = world1.clone();
snap.run_system(test_after_setup_state, ());
world1.run_system(pos_vel_system, ());
world1.run_system(test_pos_vel_1_run, ());
snap.run_system(test_after_setup_state, ());
snap.run_system(pos_vel_system, ());
world1.run_system(test_pos_vel_1_run, ());
}
#[test]
fn world_is_send() {
fn send<T: Send>(_: T) {}
send(World::new())
}
#[test]
fn get_entity_components() {
let w = World::default();
let (e1, e2) = {
let mut entities = w.resource_mut::<Entities>();
(entities.create(), entities.create())
};
let state = w.components.get::<C>();
let mut comp = state.borrow_mut();
let c2 = C(2);
comp.insert(e2, c2);
assert_eq!(w.get_entity_components(e1, &comp), None);
assert_eq!(w.get_entity_components(e2, &comp), Some(&c2));
}
#[derive(Clone, HasSchema, Default)]
struct TestResource(u32);
#[derive(Clone, HasSchema)]
#[schema(opaque, no_default)]
struct TestFromWorld(u32);
impl FromWorld for TestFromWorld {
fn from_world(world: &World) -> Self {
let b = world.resource::<TestResource>();
Self(b.0)
}
}
#[test]
fn init_resource_does_not_overwrite() {
let mut w = World::default();
w.insert_resource(TestResource(0));
w.init_resource::<TestFromWorld>();
w.insert_resource(TestResource(1));
let resource = w.resource::<TestFromWorld>();
assert_eq!(resource.0, 0);
}
}