diff options
| -rw-r--r-- | azalea-client/src/client.rs | 8 | ||||
| -rw-r--r-- | azalea/src/lib.rs | 4 | ||||
| -rw-r--r-- | azalea/src/swarm/mod.rs | 20 |
3 files changed, 20 insertions, 12 deletions
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 4d803994..2ebf44b5 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -30,7 +30,7 @@ use azalea_protocol::{ resolver, }; use azalea_world::{Instance, InstanceContainer, InstanceName, MinecraftEntityId, PartialInstance}; -use bevy_app::{App, Plugin, PluginsState, Update}; +use bevy_app::{App, Plugin, PluginsState, SubApp, Update}; use bevy_ecs::{ prelude::*, schedule::{InternedScheduleLabel, LogLevel, ScheduleBuildSettings}, @@ -126,7 +126,7 @@ impl<'a> StartClientOpts<'a> { let mut app = App::new(); app.add_plugins(DefaultPlugins); - let (ecs_lock, start_running_systems) = start_ecs_runner(app); + let (ecs_lock, start_running_systems) = start_ecs_runner(app.main_mut()); start_running_systems(); Self { @@ -667,7 +667,7 @@ impl Plugin for AzaleaPlugin { /// 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<Mutex<World>>, impl FnOnce()) { +pub fn start_ecs_runner(app: &mut SubApp) -> (Arc<Mutex<World>>, 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 { @@ -688,7 +688,7 @@ pub fn start_ecs_runner(mut app: App) -> (Arc<Mutex<World>>, impl FnOnce()) { let ecs = Arc::new(Mutex::new(mem::take(app.world_mut()))); let ecs_clone = ecs.clone(); - let outer_schedule_label = *app.main().update_schedule.as_ref().unwrap(); + let outer_schedule_label = *app.update_schedule.as_ref().unwrap(); let start_running_systems = move || { tokio::spawn(run_schedule_loop(ecs_clone, outer_schedule_label)); }; diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs index 0a8300b1..d63ea6c3 100644 --- a/azalea/src/lib.rs +++ b/azalea/src/lib.rs @@ -43,7 +43,8 @@ use protocol::{ServerAddress, resolver::ResolverError}; use swarm::SwarmBuilder; use thiserror::Error; -pub type BoxHandleFn<S, R> = Box<dyn Fn(Client, azalea_client::Event, S) -> BoxFuture<'static, R>>; +pub type BoxHandleFn<S, R> = + Box<dyn Fn(Client, azalea_client::Event, S) -> BoxFuture<'static, R> + Send>; pub type HandleFn<S, Fut> = fn(Client, azalea_client::Event, S) -> Fut; #[derive(Error, Debug)] @@ -76,6 +77,7 @@ pub struct ClientBuilder<S, R> where S: Default + Send + Sync + Clone + Component + 'static, R: Send + 'static, + Self: Send, { /// Internally, ClientBuilder is just a wrapper over SwarmBuilder since it's /// technically just a subset of it so we can avoid duplicating code this diff --git a/azalea/src/swarm/mod.rs b/azalea/src/swarm/mod.rs index 2e33148e..4fd5120a 100644 --- a/azalea/src/swarm/mod.rs +++ b/azalea/src/swarm/mod.rs @@ -9,6 +9,7 @@ pub mod prelude; use std::{ collections::{HashMap, hash_map}, future::Future, + mem, net::SocketAddr, sync::{ Arc, @@ -23,7 +24,7 @@ use azalea_client::{ }; use azalea_protocol::{ServerAddress, resolver}; use azalea_world::InstanceContainer; -use bevy_app::{App, PluginGroup, PluginGroupBuilder, Plugins}; +use bevy_app::{App, PluginGroup, PluginGroupBuilder, Plugins, SubApp}; use bevy_ecs::prelude::*; use futures::future::{BoxFuture, join_all}; use parking_lot::{Mutex, RwLock}; @@ -70,8 +71,10 @@ pub struct SwarmBuilder<S, SS, R, SR> where S: Send + Sync + Clone + Component + 'static, SS: Default + Send + Sync + Clone + Resource + 'static, + Self: Send, { - pub(crate) app: App, + // SubApp is used instead of App to make it Send + pub(crate) app: SubApp, /// The accounts and proxies that are going to join the server. pub(crate) accounts: Vec<(Account, JoinOpts)>, /// The individual bot states. This must be the same length as `accounts`, @@ -131,7 +134,10 @@ impl SwarmBuilder<NoState, NoSwarmState, (), ()> { SwarmBuilder { // we create the app here so plugins can add onto it. // the schedules won't run until [`Self::start`] is called. - app: App::new(), + + // `App::new()` is used instead of `SubApp::new()` so the necessary resources are + // initialized + app: mem::take(App::new().main_mut()), accounts: Vec::new(), states: Vec::new(), swarm_state: NoSwarmState, @@ -361,7 +367,7 @@ where /// Do the same as [`Self::start`], but allow passing in default join /// options for the bots. pub async fn start_with_default_opts( - self, + mut self, address: impl TryInto<ServerAddress>, default_join_opts: JoinOpts, ) -> Result<!, StartError> { @@ -394,9 +400,9 @@ where swarm_tx.send(SwarmEvent::Init).unwrap(); - let main_schedule_label = self.app.main().update_schedule.unwrap(); + let main_schedule_label = self.app.update_schedule.unwrap(); - let (ecs_lock, start_running_systems) = start_ecs_runner(self.app); + let (ecs_lock, start_running_systems) = start_ecs_runner(&mut self.app); let swarm = Swarm { ecs_lock: ecs_lock.clone(), @@ -559,7 +565,7 @@ pub enum SwarmEvent { pub type SwarmHandleFn<SS, Fut> = fn(Swarm, SwarmEvent, SS) -> Fut; pub type BoxSwarmHandleFn<SS, R> = - Box<dyn Fn(Swarm, SwarmEvent, SS) -> BoxFuture<'static, R> + Send>; + Box<dyn Fn(Swarm, SwarmEvent, SS) -> BoxFuture<'static, R> + Send + Sync>; /// Make a bot [`Swarm`]. /// |
