aboutsummaryrefslogtreecommitdiff
path: root/azalea/src
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2025-12-28 14:31:41 +0500
committermat <git@matdoes.dev>2025-12-28 14:31:41 +0500
commit7ab3b8924f64f7eadb6b8928b6fae73cb06e4c2f (patch)
tree5add5d27fd7c2638ebe6fab9bd7adcdae28a358d /azalea/src
parent9513f42e87f64c409cdb2a100500a50e5a713bac (diff)
downloadazalea-drasl-7ab3b8924f64f7eadb6b8928b6fae73cb06e4c2f.tar.xz
move Event and auto_reconnect to the azalea crate
Diffstat (limited to 'azalea/src')
-rw-r--r--azalea/src/auto_reconnect.rs134
-rw-r--r--azalea/src/bot.rs6
-rw-r--r--azalea/src/builder.rs2
-rw-r--r--azalea/src/client_impl/mod.rs12
-rw-r--r--azalea/src/client_impl/movement.rs2
-rw-r--r--azalea/src/events.rs316
-rw-r--r--azalea/src/lib.rs9
-rw-r--r--azalea/src/prelude.rs4
-rw-r--r--azalea/src/swarm/builder.rs7
-rw-r--r--azalea/src/swarm/mod.rs10
10 files changed, 479 insertions, 23 deletions
diff --git a/azalea/src/auto_reconnect.rs b/azalea/src/auto_reconnect.rs
new file mode 100644
index 00000000..dd353b7a
--- /dev/null
+++ b/azalea/src/auto_reconnect.rs
@@ -0,0 +1,134 @@
+//! Auto-reconnect to the server when the client is kicked.
+//!
+//! See [`AutoReconnectPlugin`] for more information.
+
+use std::time::{Duration, Instant};
+
+use bevy_app::prelude::*;
+use bevy_ecs::prelude::*;
+
+use super::{
+ disconnect::DisconnectEvent,
+ join::{ConnectOpts, ConnectionFailedEvent, StartJoinServerEvent},
+};
+use crate::Account;
+
+/// The default delay that Azalea will use for reconnecting our clients.
+///
+/// See [`AutoReconnectPlugin`] for more information.
+pub const DEFAULT_RECONNECT_DELAY: Duration = Duration::from_secs(5);
+
+/// A default plugin that makes clients automatically rejoin the server when
+/// they're disconnected.
+///
+/// The reconnect delay is configurable globally or per-client with the
+/// [`AutoReconnectDelay`] resource/component. Auto reconnecting can be disabled
+/// by removing the resource from the ECS.
+///
+/// The delay defaults to [`DEFAULT_RECONNECT_DELAY`].
+pub struct AutoReconnectPlugin;
+impl Plugin for AutoReconnectPlugin {
+ fn build(&self, app: &mut App) {
+ app.insert_resource(AutoReconnectDelay::new(DEFAULT_RECONNECT_DELAY))
+ .add_systems(
+ Update,
+ (start_rejoin_on_disconnect, rejoin_after_delay)
+ .chain()
+ .before(super::join::handle_start_join_server_event),
+ );
+ }
+}
+
+pub fn start_rejoin_on_disconnect(
+ mut commands: Commands,
+ mut disconnect_events: MessageReader<DisconnectEvent>,
+ mut connection_failed_events: MessageReader<ConnectionFailedEvent>,
+ auto_reconnect_delay_res: Option<Res<AutoReconnectDelay>>,
+ auto_reconnect_delay_query: Query<&AutoReconnectDelay>,
+) {
+ for entity in disconnect_events
+ .read()
+ .map(|e| e.entity)
+ .chain(connection_failed_events.read().map(|e| e.entity))
+ {
+ let Some(delay) = get_delay(
+ &auto_reconnect_delay_res,
+ auto_reconnect_delay_query,
+ entity,
+ ) else {
+ // no auto reconnect
+ continue;
+ };
+
+ let reconnect_after = Instant::now() + delay;
+ commands.entity(entity).insert(InternalReconnectAfter {
+ instant: reconnect_after,
+ });
+ }
+}
+
+fn get_delay(
+ auto_reconnect_delay_res: &Option<Res<AutoReconnectDelay>>,
+ auto_reconnect_delay_query: Query<&AutoReconnectDelay>,
+ entity: Entity,
+) -> Option<Duration> {
+ let delay = if let Ok(c) = auto_reconnect_delay_query.get(entity) {
+ Some(c.delay)
+ } else {
+ auto_reconnect_delay_res.as_ref().map(|r| r.delay)
+ };
+
+ if delay == Some(Duration::MAX) {
+ // if the duration is set to max, treat that as autoreconnect being disabled
+ return None;
+ }
+ delay
+}
+
+pub fn rejoin_after_delay(
+ mut commands: Commands,
+ mut join_events: MessageWriter<StartJoinServerEvent>,
+ query: Query<(Entity, &InternalReconnectAfter, &Account, &ConnectOpts)>,
+) {
+ for (entity, reconnect_after, account, connect_opts) in query.iter() {
+ if Instant::now() >= reconnect_after.instant {
+ // don't keep trying to reconnect
+ commands.entity(entity).remove::<InternalReconnectAfter>();
+
+ // our Entity will be reused since the account has the same uuid
+ join_events.write(StartJoinServerEvent {
+ account: account.clone(),
+ connect_opts: connect_opts.clone(),
+ start_join_callback_tx: None,
+ });
+ }
+ }
+}
+
+/// A resource *and* component that indicates how long to wait before
+/// reconnecting when we're kicked.
+///
+/// Initially, it's a resource in the ECS set to 5 seconds. You can modify
+/// the resource to update the global reconnect delay, or insert it as a
+/// component to set the individual delay for a single client.
+///
+/// You can also remove this resource from the ECS to disable the default
+/// auto-reconnecting behavior. Inserting the resource/component again will not
+/// make clients that were already disconnected automatically reconnect.
+#[derive(Clone, Component, Debug, Resource)]
+pub struct AutoReconnectDelay {
+ pub delay: Duration,
+}
+impl AutoReconnectDelay {
+ pub fn new(delay: Duration) -> Self {
+ Self { delay }
+ }
+}
+
+/// This is inserted when we're disconnected and indicates when we'll reconnect.
+///
+/// This is set based on [`AutoReconnectDelay`].
+#[derive(Clone, Component, Debug)]
+pub struct InternalReconnectAfter {
+ pub instant: Instant,
+}
diff --git a/azalea/src/bot.rs b/azalea/src/bot.rs
index 6f39c2fe..73b225b2 100644
--- a/azalea/src/bot.rs
+++ b/azalea/src/bot.rs
@@ -130,9 +130,7 @@ impl Client {
/// Mine a block.
///
/// This won't turn the bot's head towards the block, so if that's necessary
- /// you'll have to do that yourself with [`look_at`].
- ///
- /// [`look_at`]: crate::prelude::BotClientExt::look_at
+ /// you'll have to do that yourself with [`look_at`](Client::look_at).
pub async fn mine(&self, position: BlockPos) {
self.start_mining(position);
@@ -211,5 +209,7 @@ impl PluginGroup for DefaultBotPlugins {
.add(crate::auto_respawn::AutoRespawnPlugin)
.add(crate::accept_resource_packs::AcceptResourcePacksPlugin)
.add(crate::tick_broadcast::TickBroadcastPlugin)
+ .add(crate::events::EventsPlugin)
+ .add(crate::auto_reconnect::AutoReconnectPlugin)
}
}
diff --git a/azalea/src/builder.rs b/azalea/src/builder.rs
index 91fb9d5e..8151b3a1 100644
--- a/azalea/src/builder.rs
+++ b/azalea/src/builder.rs
@@ -150,7 +150,7 @@ where
/// If this function isn't called, then our client will reconnect after
/// [`DEFAULT_RECONNECT_DELAY`].
///
- /// [`DEFAULT_RECONNECT_DELAY`]: azalea_client::auto_reconnect::DEFAULT_RECONNECT_DELAY
+ /// [`DEFAULT_RECONNECT_DELAY`]: crate::auto_reconnect::DEFAULT_RECONNECT_DELAY
#[must_use]
pub fn reconnect_after(mut self, delay: impl Into<Option<Duration>>) -> Self {
self.swarm.reconnect_after = delay.into();
diff --git a/azalea/src/client_impl/mod.rs b/azalea/src/client_impl/mod.rs
index 2f5fbf7d..36995656 100644
--- a/azalea/src/client_impl/mod.rs
+++ b/azalea/src/client_impl/mod.rs
@@ -2,7 +2,7 @@ use std::{collections::HashMap, sync::Arc};
use azalea_auth::game_profile::GameProfile;
use azalea_client::{
- Account, DefaultPlugins, Event,
+ Account, DefaultPlugins,
connection::RawConnection,
disconnect::DisconnectEvent,
join::{ConnectOpts, StartJoinServerEvent},
@@ -40,6 +40,8 @@ use parking_lot::{Mutex, RwLock};
use tokio::sync::mpsc;
use uuid::Uuid;
+use crate::events::{Event, LocalPlayerEvents};
+
pub mod attack;
pub mod chat;
pub mod client_information;
@@ -210,7 +212,6 @@ impl Client {
ecs_lock.lock().write_message(StartJoinServerEvent {
account,
connect_opts,
- event_sender,
start_join_callback_tx: Some(start_join_callback_tx),
});
@@ -218,6 +219,13 @@ impl Client {
"start_join_callback should not be dropped before sending a message, this is a bug in Azalea",
);
+ if let Some(event_sender) = event_sender {
+ ecs_lock
+ .lock()
+ .entity_mut(entity)
+ .insert(LocalPlayerEvents(event_sender));
+ }
+
Client::new(entity, ecs_lock)
}
diff --git a/azalea/src/client_impl/movement.rs b/azalea/src/client_impl/movement.rs
index 08624263..b47da9a7 100644
--- a/azalea/src/client_impl/movement.rs
+++ b/azalea/src/client_impl/movement.rs
@@ -28,7 +28,7 @@ impl Client {
/// Whether the client is currently trying to sneak.
///
- /// You may want to check the [`Pose`] instead.
+ /// You may want to check the [`Pose`](azalea_entity::Pose) instead.
pub fn crouching(&self) -> bool {
self.query_self::<&PhysicsState, _>(|p| p.trying_to_crouch)
}
diff --git a/azalea/src/events.rs b/azalea/src/events.rs
new file mode 100644
index 00000000..0920dbd8
--- /dev/null
+++ b/azalea/src/events.rs
@@ -0,0 +1,316 @@
+//! Defines the [`enum@Event`] enum and makes those events trigger when they're
+//! sent in the ECS.
+
+use std::sync::Arc;
+
+use azalea_chat::FormattedText;
+use azalea_core::{position::ChunkPos, tick::GameTick};
+use azalea_entity::{Dead, InLoadedChunk};
+use azalea_protocol::packets::game::c_player_combat_kill::ClientboundPlayerCombatKill;
+use azalea_world::{InstanceName, MinecraftEntityId};
+use bevy_app::{App, Plugin, PreUpdate, Update};
+use bevy_ecs::prelude::*;
+use derive_more::{Deref, DerefMut};
+use tokio::sync::mpsc;
+
+use crate::{
+ chat::{ChatPacket, ChatReceivedEvent},
+ chunks::ReceiveChunkEvent,
+ disconnect::DisconnectEvent,
+ packet::game::{
+ AddPlayerEvent, DeathEvent, KeepAliveEvent, RemovePlayerEvent, UpdatePlayerEvent,
+ },
+ player::PlayerInfo,
+};
+
+// (for contributors):
+// HOW TO ADD A NEW (packet based) EVENT:
+// - Add it as an ECS event first:
+// - Make a struct that contains an entity field and some data fields (look
+// in packet/game/events.rs for examples. These structs should always have
+// their names end with "Event".
+// - (the `entity` field is the local player entity that's receiving the
+// event)
+// - In the GamePacketHandler, you always have a `player` field that you can
+// use.
+// - Add the event struct in PacketPlugin::build
+// - (in the `impl Plugin for PacketPlugin`)
+// - To get the event writer, you have to get an MessageWriter<ThingEvent>.
+// Look at other packets in packet/game/mod.rs for examples.
+//
+// At this point, you've created a new ECS event. That's annoying for bots to
+// use though, so you might wanna add it to the Event enum too:
+// - In this file, add a new variant to that Event enum with the same name
+// as your event (without the "Event" suffix).
+// - Create a new system function like the other ones here, and put that
+// system function in the `impl Plugin for EventsPlugin`
+
+/// Something that happened in-game, such as a tick passing or chat message
+/// being sent.
+///
+/// Note: Events are sent before they're processed, so for example game ticks
+/// happen at the beginning of a tick before anything has happened.
+#[derive(Clone, Debug)]
+#[non_exhaustive]
+pub enum Event {
+ /// Happens right after the bot switches into the Game state, but before
+ /// it's actually spawned.
+ ///
+ /// This can be useful for setting the client information with
+ /// [`Client::set_client_information`], so the packet doesn't have to be
+ /// sent twice.
+ ///
+ /// You may want to use [`Event::Spawn`] instead to wait for the bot to be
+ /// in the world.
+ ///
+ /// [`Client::set_client_information`]: crate::Client::set_client_information
+ Init,
+ /// Fired when we receive a login packet, which is after [`Event::Init`] but
+ /// before [`Event::Spawn`]. You usually want [`Event::Spawn`] instead.
+ ///
+ /// Your position may be [`Vec3::ZERO`] immediately after you receive this
+ /// event, but it'll be ready by the time you get [`Event::Spawn`].
+ ///
+ /// It's possible for this event to be sent multiple times per client if a
+ /// server sends multiple login packets (like when switching worlds).
+ ///
+ /// [`Vec3::ZERO`]: azalea_core::position::Vec3::ZERO
+ Login,
+ /// Fired when the player fully spawns into the world (is in a loaded chunk)
+ /// and is ready to interact with it.
+ ///
+ /// This is usually the event you should listen for when waiting for the bot
+ /// to be ready.
+ ///
+ /// This event will be sent every time the client respawns or switches
+ /// worlds, as long as the server sends chunks to the client.
+ Spawn,
+ /// A chat message was sent in the game chat.
+ Chat(ChatPacket),
+ /// Happens 20 times per second, but only when the world is loaded.
+ Tick,
+ #[cfg(feature = "packet-event")]
+ /// We received a packet from the server.
+ ///
+ /// ```
+ /// # use azalea::Event;
+ /// # use azalea_protocol::packets::game::ClientboundGamePacket;
+ /// # async fn example(event: Event) {
+ /// # match event {
+ /// Event::Packet(packet) => match &*packet {
+ /// ClientboundGamePacket::Login(_) => {
+ /// println!("login packet");
+ /// }
+ /// _ => {}
+ /// },
+ /// # _ => {}
+ /// # }
+ /// # }
+ /// ```
+ Packet(Arc<azalea_protocol::packets::game::ClientboundGamePacket>),
+ /// A player joined the game (or more specifically, was added to the tab
+ /// list).
+ AddPlayer(PlayerInfo),
+ /// A player left the game (or maybe is still in the game and was just
+ /// removed from the tab list).
+ RemovePlayer(PlayerInfo),
+ /// A player was updated in the tab list (gamemode, display
+ /// name, or latency changed).
+ UpdatePlayer(PlayerInfo),
+ /// The client player died in-game.
+ Death(Option<Arc<ClientboundPlayerCombatKill>>),
+ /// A `KeepAlive` packet was sent by the server.
+ KeepAlive(u64),
+ /// The client disconnected from the server.
+ Disconnect(Option<FormattedText>),
+ ReceiveChunk(ChunkPos),
+}
+
+/// A component that contains an event sender for events that are only
+/// received by local players.
+///
+/// The receiver for this is returned by
+/// [`Client::start_client`](crate::Client::start_client).
+#[derive(Component, Deref, DerefMut)]
+pub struct LocalPlayerEvents(pub mpsc::UnboundedSender<Event>);
+
+pub struct EventsPlugin;
+impl Plugin for EventsPlugin {
+ fn build(&self, app: &mut App) {
+ app.add_systems(
+ Update,
+ (
+ chat_listener,
+ login_listener,
+ spawn_listener,
+ #[cfg(feature = "packet-event")]
+ packet_listener,
+ add_player_listener,
+ update_player_listener,
+ remove_player_listener,
+ keepalive_listener,
+ death_listener.after(azalea_client::packet::death_event_on_0_health),
+ disconnect_listener,
+ receive_chunk_listener,
+ ),
+ )
+ .add_systems(
+ PreUpdate,
+ init_listener.before(super::connection::read_packets),
+ )
+ .add_systems(GameTick, tick_listener);
+ }
+}
+
+// when LocalPlayerEvents is added, it means the client just started
+pub fn init_listener(query: Query<&LocalPlayerEvents, Added<LocalPlayerEvents>>) {
+ for local_player_events in &query {
+ let _ = local_player_events.send(Event::Init);
+ }
+}
+
+// when MinecraftEntityId is added, it means the player is now in the world
+pub fn login_listener(
+ query: Query<(Entity, &LocalPlayerEvents), Added<MinecraftEntityId>>,
+ mut commands: Commands,
+) {
+ for (entity, local_player_events) in &query {
+ let _ = local_player_events.send(Event::Login);
+ commands.entity(entity).remove::<SentSpawnEvent>();
+ }
+}
+
+/// A unit struct component that indicates that the entity has sent
+/// [`Event::Spawn`].
+///
+/// This is just used internally by the [`spawn_listener`] system to avoid
+/// sending the event twice if we stop being in an unloaded chunk. It's removed
+/// when we receive a login packet.
+#[derive(Component)]
+pub struct SentSpawnEvent;
+#[allow(clippy::type_complexity)]
+pub fn spawn_listener(
+ query: Query<(Entity, &LocalPlayerEvents), (Added<InLoadedChunk>, Without<SentSpawnEvent>)>,
+ mut commands: Commands,
+) {
+ for (entity, local_player_events) in &query {
+ let _ = local_player_events.send(Event::Spawn);
+ commands.entity(entity).insert(SentSpawnEvent);
+ }
+}
+
+pub fn chat_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<ChatReceivedEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::Chat(event.packet.clone()));
+ }
+ }
+}
+
+// only tick if we're in a world
+pub fn tick_listener(query: Query<&LocalPlayerEvents, With<InstanceName>>) {
+ for local_player_events in &query {
+ let _ = local_player_events.send(Event::Tick);
+ }
+}
+
+#[cfg(feature = "packet-event")]
+pub fn packet_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<super::packet::game::ReceiveGamePacketEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::Packet(event.packet.clone()));
+ }
+ }
+}
+
+pub fn add_player_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<AddPlayerEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::AddPlayer(event.info.clone()));
+ }
+ }
+}
+
+pub fn update_player_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<UpdatePlayerEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::UpdatePlayer(event.info.clone()));
+ }
+ }
+}
+
+pub fn remove_player_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<RemovePlayerEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::RemovePlayer(event.info.clone()));
+ }
+ }
+}
+
+pub fn death_listener(query: Query<&LocalPlayerEvents>, mut events: MessageReader<DeathEvent>) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::Death(event.packet.clone().map(|p| p.into())));
+ }
+ }
+}
+
+/// Send the "Death" event for [`LocalEntity`]s that died with no reason.
+///
+/// [`LocalEntity`]: azalea_entity::LocalEntity
+pub fn dead_component_listener(query: Query<&LocalPlayerEvents, Added<Dead>>) {
+ for local_player_events in &query {
+ local_player_events.send(Event::Death(None)).unwrap();
+ }
+}
+
+pub fn keepalive_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<KeepAliveEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::KeepAlive(event.id));
+ }
+ }
+}
+
+pub fn disconnect_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<DisconnectEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::Disconnect(event.reason.clone()));
+ }
+ }
+}
+
+pub fn receive_chunk_listener(
+ query: Query<&LocalPlayerEvents>,
+ mut events: MessageReader<ReceiveChunkEvent>,
+) {
+ for event in events.read() {
+ if let Ok(local_player_events) = query.get(event.entity) {
+ let _ = local_player_events.send(Event::ReceiveChunk(ChunkPos::new(
+ event.packet.x,
+ event.packet.z,
+ )));
+ }
+ }
+}
diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs
index 2105daee..351c956a 100644
--- a/azalea/src/lib.rs
+++ b/azalea/src/lib.rs
@@ -2,12 +2,14 @@
#![feature(type_changing_struct_update)]
pub mod accept_resource_packs;
+pub mod auto_reconnect;
pub mod auto_respawn;
pub mod auto_tool;
pub mod bot;
mod builder;
mod client_impl;
pub mod container;
+pub mod events;
mod join_opts;
pub mod nearest_entity;
pub mod pathfinder;
@@ -51,11 +53,10 @@ pub use builder::ClientBuilder;
use futures::future::BoxFuture;
pub use join_opts::JoinOpts;
-pub use crate::client_impl::Client;
+pub use crate::{client_impl::Client, events::Event};
-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;
+pub type BoxHandleFn<S, R> = Box<dyn Fn(Client, Event, S) -> BoxFuture<'static, R> + Send>;
+pub type HandleFn<S, Fut> = fn(Client, Event, S) -> Fut;
/// A marker that can be used in place of a State in [`ClientBuilder`] or
/// [`SwarmBuilder`].
diff --git a/azalea/src/prelude.rs b/azalea/src/prelude.rs
index 2675c8f5..d39e50c4 100644
--- a/azalea/src/prelude.rs
+++ b/azalea/src/prelude.rs
@@ -1,14 +1,14 @@
//! The Azalea prelude. Things that are necessary for a bare-bones bot are
//! re-exported here.
-pub use azalea_client::{Account, Event};
+pub use azalea_client::Account;
pub use azalea_core::tick::GameTick;
pub use bevy_app::AppExit;
// this is necessary to make the macros that reference bevy_ecs work
pub use crate::ecs as bevy_ecs;
pub use crate::{
- Client, ClientBuilder,
+ Client, ClientBuilder, Event,
ecs::{component::Component, resource::Resource},
pathfinder::PathfinderClientExt,
};
diff --git a/azalea/src/swarm/builder.rs b/azalea/src/swarm/builder.rs
index 4eae7eab..860e47be 100644
--- a/azalea/src/swarm/builder.rs
+++ b/azalea/src/swarm/builder.rs
@@ -8,11 +8,7 @@ use std::{
time::Duration,
};
-use azalea_client::{
- Account, DefaultPlugins,
- auto_reconnect::{AutoReconnectDelay, DEFAULT_RECONNECT_DELAY},
- start_ecs_runner,
-};
+use azalea_client::{Account, DefaultPlugins, start_ecs_runner};
use azalea_protocol::address::{ResolvableAddr, ResolvedAddr};
use azalea_world::InstanceContainer;
use bevy_app::{App, AppExit, Plugins, SubApp};
@@ -24,6 +20,7 @@ use tracing::{debug, error, warn};
use crate::{
BoxHandleFn, HandleFn, JoinOpts, NoState,
+ auto_reconnect::{AutoReconnectDelay, DEFAULT_RECONNECT_DELAY},
bot::DefaultBotPlugins,
swarm::{
BoxSwarmHandleFn, DefaultSwarmPlugins, NoSwarmState, Swarm, SwarmEvent, SwarmHandleFn,
diff --git a/azalea/src/swarm/mod.rs b/azalea/src/swarm/mod.rs
index c0f9cbca..48ac20a3 100644
--- a/azalea/src/swarm/mod.rs
+++ b/azalea/src/swarm/mod.rs
@@ -12,7 +12,7 @@ use std::sync::{
atomic::{self, AtomicBool},
};
-use azalea_client::{Account, Event, chat::ChatPacket, join::ConnectOpts};
+use azalea_client::{Account, chat::ChatPacket, join::ConnectOpts};
use azalea_entity::LocalEntity;
use azalea_protocol::address::ResolvedAddr;
use azalea_world::InstanceContainer;
@@ -45,7 +45,7 @@ pub struct Swarm {
pub instance_container: Arc<RwLock<InstanceContainer>>,
/// This is used internally to make the client handler function work.
- pub(crate) bots_tx: mpsc::UnboundedSender<(Option<Event>, Client)>,
+ pub(crate) bots_tx: mpsc::UnboundedSender<(Option<crate::Event>, Client)>,
/// This is used internally to make the swarm handler function work.
pub(crate) swarm_tx: mpsc::UnboundedSender<SwarmEvent>,
}
@@ -207,9 +207,9 @@ impl Swarm {
/// Copy the events from a client's receiver into bots_tx, until the bot is
/// removed from the ECS.
async fn event_copying_task(
- mut rx: mpsc::UnboundedReceiver<Event>,
+ mut rx: mpsc::UnboundedReceiver<crate::Event>,
swarm_tx: mpsc::UnboundedSender<SwarmEvent>,
- bots_tx: mpsc::UnboundedSender<(Option<Event>, Client)>,
+ bots_tx: mpsc::UnboundedSender<(Option<crate::Event>, Client)>,
bot: Client,
join_opts: JoinOpts,
) {
@@ -246,7 +246,7 @@ impl Swarm {
}
}
- if let Event::Disconnect(_) = event {
+ if let crate::Event::Disconnect(_) = event {
debug!(
"Sending SwarmEvent::Disconnect due to receiving an Event::Disconnect from client {}",
bot.entity