Skip to content

Commit

Permalink
fix!: fix the way resources are handled in snapshots. (#280)
Browse files Browse the repository at this point in the history
This change makes sure that shared resources are shared across snapshots
instead of having their contents duplicated when a world is cloned.

It also makes `Entities` a non-shared resource, so that worlds can have
their entities snapshotted properly.
  • Loading branch information
zicklag committed Dec 17, 2023
1 parent 831a7d8 commit 6771dea
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 15 deletions.
34 changes: 23 additions & 11 deletions framework_crates/bones_ecs/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,27 +100,38 @@ impl UntypedResource {
#[derive(Default)]
pub struct UntypedResources {
resources: OnceMap<SchemaId, AtomicUntypedResource>,
shared_resources: OnceMap<SchemaId, Box<()>>,
}

impl Clone for UntypedResources {
fn clone(&self) -> Self {
let binding = self.resources.read_only_view();
let resources = binding.iter().map(|(_, v)| (v.schema, v.clone_data()));
let resources = binding.iter().map(|(_, v)| (v.schema, v));

let new_resources = OnceMap::default();
for (schema, resource) in resources {
new_resources.map_insert(
schema.id(),
|_| Arc::new(UntypedResource::empty(schema)),
|_, cell| {
if let Some(resource) = resource {
cell.insert(resource).unwrap();
}
},
);
let new_shared_resources = OnceMap::default();
for (schema, resource_cell) in resources {
let is_shared = self.shared_resources.contains_key(&schema.id());

if !is_shared {
let resource = resource_cell.clone_data();
new_resources.map_insert(
schema.id(),
|_| Arc::new(UntypedResource::empty(schema)),
|_, cell| {
if let Some(resource) = resource {
cell.insert(resource).unwrap();
}
},
);
} else {
new_shared_resources.insert(schema.id(), |_| Box::new(()));
new_resources.insert(schema.id(), |_| resource_cell.clone());
}
}
Self {
resources: new_resources,
shared_resources: new_shared_resources,
}
}
}
Expand Down Expand Up @@ -170,6 +181,7 @@ impl UntypedResources {
Err(CellAlreadyPresentError)
} else {
self.resources.insert(schema.id(), |_| cell);
self.shared_resources.insert(schema.id(), |_| Box::new(()));
Ok(())
}
}
Expand Down
13 changes: 9 additions & 4 deletions framework_crates/bones_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ impl std::fmt::Debug for Session {

impl Session {
/// Create an empty [`Session`].
pub fn new(entities: AtomicResource<Entities>) -> Self {
pub fn new() -> Self {
Self {
world: {
let mut w = World::with_entities(entities);
let mut w = World::default();
w.init_resource::<Time>();
w
},
Expand Down Expand Up @@ -95,6 +95,12 @@ impl Session {
}
}

impl Default for Session {
fn default() -> Self {
Self::new()
}
}

/// Trait for plugins that can be installed into a [`Session`].
pub trait SessionPlugin {
/// Install the plugin into the [`Session`].
Expand Down Expand Up @@ -495,7 +501,6 @@ impl GameSystems {
/// Each session shares the same [`Entities`].
#[derive(HasSchema, Default, Debug)]
pub struct Sessions {
entities: AtomicResource<Entities>,
map: UstrMap<Session>,
}

Expand All @@ -520,7 +525,7 @@ impl Sessions {
{
let name = name.try_into().unwrap();
// Create a blank session
let mut session = Session::new(self.entities.clone());
let mut session = Session::new();

// Initialize the sessions resource in the session so it will be available in [`Game::step()`].
session.world.init_resource::<Sessions>();
Expand Down

0 comments on commit 6771dea

Please sign in to comment.