From adef9bf37b854b65b9df3cb3071d215daf6bd454 Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 24 Apr 2025 20:55:58 -0330 Subject: always insert Swarm before any systems can start running --- azalea-client/src/client.rs | 24 ++++++++++++++---------- azalea/src/swarm/mod.rs | 6 +++++- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index c6530e75..6937348d 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -1,7 +1,7 @@ use std::{ collections::HashMap, fmt::Debug, - io, + io, mem, net::SocketAddr, sync::Arc, thread, @@ -130,7 +130,8 @@ impl<'a> StartClientOpts<'a> { let mut app = App::new(); app.add_plugins(DefaultPlugins); - let ecs_lock = start_ecs_runner(app); + let (ecs_lock, start_running_systems) = start_ecs_runner(app); + start_running_systems(); Self { ecs_lock, @@ -663,12 +664,14 @@ impl Plugin for AzaleaPlugin { } } -/// Start running the ECS loop! +/// Create the ECS world, and return a function that begins running systems. +/// This exists to allow you to make last-millisecond updates to the world +/// before any systems start running. /// /// You can create your app with `App::new()`, but don't forget to add /// [`DefaultPlugins`]. #[doc(hidden)] -pub fn start_ecs_runner(mut app: App) -> Arc> { +pub fn start_ecs_runner(mut app: App) -> (Arc>, impl FnOnce()) { // this block is based on Bevy's default runner: // https://github.com/bevyengine/bevy/blob/390877cdae7a17095a75c8f9f1b4241fe5047e83/crates/bevy_app/src/schedule_runner.rs#L77-L85 if app.plugins_state() != PluginsState::Cleaned { @@ -686,14 +689,15 @@ pub fn start_ecs_runner(mut app: App) -> Arc> { // all resources should have been added by now so we can take the ecs from the // app - let ecs = Arc::new(Mutex::new(std::mem::take(app.world_mut()))); + let ecs = Arc::new(Mutex::new(mem::take(app.world_mut()))); - tokio::spawn(run_schedule_loop( - ecs.clone(), - *app.main().update_schedule.as_ref().unwrap(), - )); + let ecs_clone = ecs.clone(); + let outer_schedule_label = *app.main().update_schedule.as_ref().unwrap(); + let start_running_systems = move || { + tokio::spawn(run_schedule_loop(ecs_clone, outer_schedule_label)); + }; - ecs + (ecs, start_running_systems) } async fn run_schedule_loop(ecs: Arc>, outer_schedule_label: InternedScheduleLabel) { diff --git a/azalea/src/swarm/mod.rs b/azalea/src/swarm/mod.rs index 6ecf4d32..9be5d7ea 100644 --- a/azalea/src/swarm/mod.rs +++ b/azalea/src/swarm/mod.rs @@ -396,7 +396,7 @@ where let main_schedule_label = self.app.main().update_schedule.unwrap(); - let ecs_lock = start_ecs_runner(self.app); + let (ecs_lock, start_running_systems) = start_ecs_runner(self.app); let swarm = Swarm { ecs_lock: ecs_lock.clone(), @@ -420,6 +420,10 @@ where ecs.clear_trackers(); } + // only do this after we inserted the Swarm and state resources to avoid errors + // where Res is inaccessible + start_running_systems(); + // SwarmBuilder (self) isn't Send so we have to take all the things we need out // of it let swarm_clone = swarm.clone(); -- cgit v1.2.3