aboutsummaryrefslogtreecommitdiff
path: root/azalea-client
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-client')
-rw-r--r--azalea-client/Cargo.toml9
-rwxr-xr-xazalea-client/src/chat.rs24
-rw-r--r--azalea-client/src/client.rs102
-rw-r--r--azalea-client/src/disconnect.rs29
-rw-r--r--azalea-client/src/entity_query.rs12
-rw-r--r--azalea-client/src/events.rs12
-rw-r--r--azalea-client/src/lib.rs1
-rw-r--r--azalea-client/src/local_player.rs15
-rw-r--r--azalea-client/src/movement.rs37
-rw-r--r--azalea-client/src/packet_handling.rs66
-rwxr-xr-xazalea-client/src/player.rs4
-rw-r--r--azalea-client/src/task_pool.rs26
12 files changed, 182 insertions, 155 deletions
diff --git a/azalea-client/Cargo.toml b/azalea-client/Cargo.toml
index 6bb31069..f25aa290 100644
--- a/azalea-client/Cargo.toml
+++ b/azalea-client/Cargo.toml
@@ -16,14 +16,15 @@ azalea-block = { path = "../azalea-block", version = "0.6.0" }
azalea-chat = { path = "../azalea-chat", version = "0.6.0" }
azalea-core = { path = "../azalea-core", version = "0.6.0" }
azalea-crypto = { path = "../azalea-crypto", version = "0.6.0" }
-azalea-ecs = { path = "../azalea-ecs", version = "0.6.0" }
azalea-physics = { path = "../azalea-physics", version = "0.6.0" }
azalea-protocol = { path = "../azalea-protocol", version = "0.6.0" }
azalea-registry = { path = "../azalea-registry", version = "0.6.0" }
azalea-world = { path = "../azalea-world", version = "0.6.0" }
-bevy_log = "0.9.1"
-bevy_tasks = "0.9.1"
-bevy_time = "0.9.1"
+bevy_app = "0.10.0"
+bevy_ecs = "0.10.0"
+bevy_log = "0.10.0"
+bevy_tasks = "0.10.0"
+bevy_time = "0.10.0"
derive_more = { version = "0.99.17", features = ["deref", "deref_mut"] }
futures = "0.3.25"
log = "0.4.17"
diff --git a/azalea-client/src/chat.rs b/azalea-client/src/chat.rs
index e127f0d7..0ae0250a 100755
--- a/azalea-client/src/chat.rs
+++ b/azalea-client/src/chat.rs
@@ -1,18 +1,18 @@
//! Implementations of chat-related features.
use azalea_chat::FormattedText;
-use azalea_ecs::{
- app::{App, Plugin},
- entity::Entity,
- event::{EventReader, EventWriter},
- schedule::IntoSystemDescriptor,
-};
use azalea_protocol::packets::game::{
clientbound_player_chat_packet::ClientboundPlayerChatPacket,
clientbound_system_chat_packet::ClientboundSystemChatPacket,
serverbound_chat_command_packet::ServerboundChatCommandPacket,
serverbound_chat_packet::{LastSeenMessagesUpdate, ServerboundChatPacket},
};
+use bevy_app::{App, Plugin};
+use bevy_ecs::{
+ entity::Entity,
+ event::{EventReader, EventWriter},
+ schedule::{IntoSystemConfig, IntoSystemConfigs},
+};
use std::{
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
@@ -159,12 +159,12 @@ impl Plugin for ChatPlugin {
app.add_event::<SendChatEvent>()
.add_event::<SendChatKindEvent>()
.add_event::<ChatReceivedEvent>()
- .add_system(handle_send_chat_event.label("handle_send_chat_event"))
- .add_system(
- handle_send_chat_kind_event
- .label("handle_send_chat_kind_event")
- .after(handle_send_chat_event)
- .after(handle_send_packet_event),
+ .add_systems(
+ (
+ handle_send_chat_event,
+ handle_send_chat_kind_event.after(handle_send_packet_event),
+ )
+ .chain(),
);
}
}
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index 661858db..79501fd4 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -6,25 +6,16 @@ use crate::{
death_event, handle_send_packet_event, update_in_loaded_chunk, GameProfileComponent,
LocalPlayer, PhysicsState, SendPacketEvent,
},
- movement::{local_player_ai_step, send_position, sprint_listener, walk_listener},
+ movement::PlayerMovePlugin,
packet_handling::{self, PacketHandlerPlugin, PacketReceiver},
player::retroactively_add_game_profile_component,
task_pool::TaskPoolPlugin,
- Account, PlayerInfo, StartSprintEvent, StartWalkEvent,
+ Account, PlayerInfo,
};
use azalea_auth::{game_profile::GameProfile, sessionserver::ClientSessionServerError};
use azalea_chat::FormattedText;
-use azalea_ecs::{
- app::{App, Plugin, PluginGroup, PluginGroupBuilder},
- bundle::Bundle,
- component::Component,
- entity::Entity,
- schedule::{IntoSystemDescriptor, ReportExecutionOrderAmbiguities, Schedule, Stage, SystemSet},
- AppTickExt,
-};
-use azalea_ecs::{ecs::Ecs, TickPlugin};
-use azalea_physics::PhysicsPlugin;
+use azalea_physics::{PhysicsPlugin, PhysicsSet};
use azalea_protocol::{
connect::{Connection, ConnectionError},
packets::{
@@ -46,13 +37,23 @@ use azalea_protocol::{
resolver, ServerAddress,
};
use azalea_world::{
- entity::{EntityPlugin, Local, WorldName},
- PartialWorld, World, WorldContainer,
+ entity::{EntityPlugin, EntityUpdateSet, Local, WorldName},
+ Instance, PartialWorld, WorldContainer,
+};
+use bevy_app::{App, CoreSchedule, Plugin, PluginGroup, PluginGroupBuilder};
+use bevy_ecs::{
+ bundle::Bundle,
+ component::Component,
+ entity::Entity,
+ schedule::IntoSystemConfig,
+ schedule::{LogLevel, ScheduleBuildSettings, ScheduleLabel},
+ world::World,
};
use bevy_log::LogPlugin;
+use bevy_time::{prelude::FixedTime, TimePlugin};
use log::{debug, error};
use parking_lot::{Mutex, RwLock};
-use std::{collections::HashMap, fmt::Debug, io, net::SocketAddr, sync::Arc};
+use std::{collections::HashMap, fmt::Debug, io, net::SocketAddr, sync::Arc, time::Duration};
use thiserror::Error;
use tokio::{sync::mpsc, time};
use uuid::Uuid;
@@ -86,7 +87,7 @@ pub struct Client {
/// The entity component system. You probably don't need to access this
/// directly. Note that if you're using a shared world (i.e. a swarm), this
/// will contain all entities in all worlds.
- pub ecs: Arc<Mutex<Ecs>>,
+ pub ecs: Arc<Mutex<World>>,
/// Use this to force the client to run the schedule outside of a tick.
pub run_schedule_sender: mpsc::UnboundedSender<()>,
@@ -120,7 +121,7 @@ impl Client {
pub fn new(
profile: GameProfile,
entity: Entity,
- ecs: Arc<Mutex<Ecs>>,
+ ecs: Arc<Mutex<World>>,
run_schedule_sender: mpsc::UnboundedSender<()>,
) -> Self {
Self {
@@ -180,7 +181,7 @@ impl Client {
/// Create a [`Client`] when you already have the ECS made with
/// [`start_ecs`]. You'd usually want to use [`Self::join`] instead.
pub async fn start_client(
- ecs_lock: Arc<Mutex<Ecs>>,
+ ecs_lock: Arc<Mutex<World>>,
account: &Account,
address: &ServerAddress,
resolved_address: &SocketAddr,
@@ -226,7 +227,7 @@ impl Client {
packet_writer_sender,
// default to an empty world, it'll be set correctly later when we
// get the login packet
- Arc::new(RwLock::new(World::default())),
+ Arc::new(RwLock::new(Instance::default())),
read_packets_task,
write_packets_task,
);
@@ -382,13 +383,13 @@ impl Client {
});
}
- pub fn local_player<'a>(&'a self, ecs: &'a mut Ecs) -> &'a LocalPlayer {
+ pub fn local_player<'a>(&'a self, ecs: &'a mut World) -> &'a LocalPlayer {
self.query::<&LocalPlayer>(ecs)
}
pub fn local_player_mut<'a>(
&'a self,
- ecs: &'a mut Ecs,
- ) -> azalea_ecs::ecs::Mut<'a, LocalPlayer> {
+ ecs: &'a mut World,
+ ) -> bevy_ecs::world::Mut<'a, LocalPlayer> {
self.query::<&mut LocalPlayer>(ecs)
}
@@ -416,7 +417,7 @@ impl Client {
/// client, then it'll be the same as the world the client has loaded.
/// If the client using a shared world, then the shared world will be a
/// superset of the client's world.
- pub fn world(&self) -> Arc<RwLock<World>> {
+ pub fn world(&self) -> Arc<RwLock<Instance>> {
let world_name = self.component::<WorldName>();
let ecs = self.ecs.lock();
let world_container = ecs.resource::<WorldContainer>();
@@ -493,33 +494,20 @@ pub struct JoinedClientBundle {
pub struct AzaleaPlugin;
impl Plugin for AzaleaPlugin {
fn build(&self, app: &mut App) {
- app.add_event::<StartWalkEvent>()
- .add_event::<StartSprintEvent>();
-
- app.add_tick_system_set(
- SystemSet::new()
- .with_system(send_position.after("ai_step"))
- .with_system(update_in_loaded_chunk.before(send_position).after("travel"))
- .with_system(
- local_player_ai_step
- .before(azalea_physics::ai_step)
- .label("ai_step"),
- ),
+ // Minecraft ticks happen every 50ms
+ app.insert_resource(FixedTime::new(Duration::from_millis(50)));
+
+ app.add_system(
+ update_in_loaded_chunk
+ .after(PhysicsSet)
+ .after(handle_send_packet_event),
);
// fire the Death event when the player dies.
app.add_system(death_event);
- // walk and sprint event listeners
- app.add_system(walk_listener.label("walk_listener"))
- .add_system(
- sprint_listener
- .label("sprint_listener")
- .before("walk_listener"),
- );
-
// add GameProfileComponent when we get an AddPlayerEvent
- app.add_system(retroactively_add_game_profile_component.after("update_indexes"));
+ app.add_system(retroactively_add_game_profile_component.after(EntityUpdateSet::Index));
app.add_event::<SendPacketEvent>()
.add_system(handle_send_packet_event);
@@ -544,7 +532,12 @@ pub fn init_ecs_app() -> App {
let mut app = App::new();
- app.insert_resource(ReportExecutionOrderAmbiguities);
+ app.edit_schedule(CoreSchedule::Main, |schedule| {
+ schedule.set_build_settings(ScheduleBuildSettings {
+ ambiguity_detection: LogLevel::Warn,
+ ..Default::default()
+ });
+ });
app.add_plugins(DefaultPlugins);
app
@@ -554,17 +547,19 @@ pub fn init_ecs_app() -> App {
/// first.
#[doc(hidden)]
pub fn start_ecs(
- app: App,
+ mut app: App,
run_schedule_receiver: mpsc::UnboundedReceiver<()>,
run_schedule_sender: mpsc::UnboundedSender<()>,
-) -> Arc<Mutex<Ecs>> {
+) -> Arc<Mutex<World>> {
+ app.setup();
+
// all resources should have been added by now so we can take the ecs from the
// app
let ecs = Arc::new(Mutex::new(app.world));
tokio::spawn(run_schedule_loop(
ecs.clone(),
- app.schedule,
+ app.outer_schedule_label,
run_schedule_receiver,
));
tokio::spawn(tick_run_schedule_loop(run_schedule_sender));
@@ -573,14 +568,16 @@ pub fn start_ecs(
}
async fn run_schedule_loop(
- ecs: Arc<Mutex<Ecs>>,
- mut schedule: Schedule,
+ ecs: Arc<Mutex<World>>,
+ outer_schedule_label: Box<dyn ScheduleLabel>,
mut run_schedule_receiver: mpsc::UnboundedReceiver<()>,
) {
loop {
// whenever we get an event from run_schedule_receiver, run the schedule
run_schedule_receiver.recv().await;
- schedule.run(&mut ecs.lock());
+ let mut ecs = ecs.lock();
+ ecs.run_schedule_ref(&*outer_schedule_label);
+ ecs.clear_trackers();
}
}
@@ -609,7 +606,7 @@ impl PluginGroup for DefaultPlugins {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>()
.add(LogPlugin::default())
- .add(TickPlugin::default())
+ .add(TimePlugin::default())
.add(PacketHandlerPlugin)
.add(AzaleaPlugin)
.add(EntityPlugin)
@@ -618,5 +615,6 @@ impl PluginGroup for DefaultPlugins {
.add(TaskPoolPlugin::default())
.add(ChatPlugin)
.add(DisconnectPlugin)
+ .add(PlayerMovePlugin)
}
}
diff --git a/azalea-client/src/disconnect.rs b/azalea-client/src/disconnect.rs
index 9fd57e57..3b8d133e 100644
--- a/azalea-client/src/disconnect.rs
+++ b/azalea-client/src/disconnect.rs
@@ -1,30 +1,30 @@
//! Disconnect a client from the server.
-use azalea_ecs::{
- app::{App, CoreStage, Plugin},
+use bevy_app::{App, CoreSet, Plugin};
+use bevy_ecs::{
component::Component,
entity::Entity,
event::{EventReader, EventWriter},
query::Changed,
- schedule::IntoSystemDescriptor,
+ schedule::IntoSystemConfigs,
system::{Commands, Query},
- AppTickExt,
};
use derive_more::Deref;
-use crate::{client::JoinedClientBundle, movement::send_position, LocalPlayer};
+use crate::{client::JoinedClientBundle, LocalPlayer};
pub struct DisconnectPlugin;
impl Plugin for DisconnectPlugin {
fn build(&self, app: &mut App) {
- app.add_event::<DisconnectEvent>()
- .add_system_to_stage(CoreStage::PostUpdate, handle_disconnect)
- .add_tick_system(
- update_read_packets_task_running_component
- .before(disconnect_on_read_packets_ended)
- .before(send_position),
+ app.add_event::<DisconnectEvent>().add_systems(
+ (
+ update_read_packets_task_running_component,
+ disconnect_on_read_packets_ended,
+ remove_components_from_disconnected_players,
)
- .add_tick_system(disconnect_on_read_packets_ended);
+ .in_base_set(CoreSet::PostUpdate)
+ .chain(),
+ );
}
}
@@ -35,7 +35,10 @@ pub struct DisconnectEvent {
/// System that removes the [`JoinedClientBundle`] from the entity when it
/// receives a [`DisconnectEvent`].
-pub fn handle_disconnect(mut commands: Commands, mut events: EventReader<DisconnectEvent>) {
+pub fn remove_components_from_disconnected_players(
+ mut commands: Commands,
+ mut events: EventReader<DisconnectEvent>,
+) {
for DisconnectEvent { entity } in events.iter() {
commands.entity(*entity).remove::<JoinedClientBundle>();
}
diff --git a/azalea-client/src/entity_query.rs b/azalea-client/src/entity_query.rs
index e39a7d2f..8fe94659 100644
--- a/azalea-client/src/entity_query.rs
+++ b/azalea-client/src/entity_query.rs
@@ -1,10 +1,10 @@
use std::sync::Arc;
-use azalea_ecs::{
+use bevy_ecs::{
component::Component,
- ecs::Ecs,
entity::Entity,
query::{ROQueryItem, ReadOnlyWorldQuery, WorldQuery},
+ world::World,
};
use parking_lot::Mutex;
@@ -22,7 +22,7 @@ impl Client {
/// .is_some();
/// # }
/// ```
- pub fn query<'w, Q: WorldQuery>(&self, ecs: &'w mut Ecs) -> <Q as WorldQuery>::Item<'w> {
+ pub fn query<'w, Q: WorldQuery>(&self, ecs: &'w mut World) -> <Q as WorldQuery>::Item<'w> {
ecs.query::<Q>()
.get_mut(ecs, self.entity)
.expect("Our client is missing a required component.")
@@ -38,7 +38,7 @@ impl Client {
/// Note that this will very likely change in the future.
/// ```
/// use azalea_client::{Client, GameProfileComponent};
- /// use azalea_ecs::query::With;
+ /// use bevy_ecs::query::With;
/// use azalea_world::entity::{Position, metadata::Player};
///
/// # fn example(mut bot: Client, sender_name: String) {
@@ -74,7 +74,7 @@ impl Client {
}
pub trait EntityPredicate<Q: ReadOnlyWorldQuery, Filter: ReadOnlyWorldQuery> {
- fn find(&self, ecs_lock: Arc<Mutex<Ecs>>) -> Option<Entity>;
+ fn find(&self, ecs_lock: Arc<Mutex<World>>) -> Option<Entity>;
}
impl<F, Q, Filter> EntityPredicate<(Q,), Filter> for F
where
@@ -82,7 +82,7 @@ where
Q: ReadOnlyWorldQuery,
Filter: ReadOnlyWorldQuery,
{
- fn find(&self, ecs_lock: Arc<Mutex<Ecs>>) -> Option<Entity> {
+ fn find(&self, ecs_lock: Arc<Mutex<World>>) -> Option<Entity> {
let mut ecs = ecs_lock.lock();
let mut query = ecs.query_filtered::<(Entity, Q), Filter>();
let entity = query.iter(&ecs).find(|(_, q)| (self)(q)).map(|(e, _)| e);
diff --git a/azalea-client/src/events.rs b/azalea-client/src/events.rs
index 085f5368..c7ff20aa 100644
--- a/azalea-client/src/events.rs
+++ b/azalea-client/src/events.rs
@@ -3,18 +3,12 @@
use std::sync::Arc;
-use azalea_ecs::{
- app::{App, Plugin},
- component::Component,
- event::EventReader,
- query::Added,
- system::Query,
- AppTickExt,
-};
use azalea_protocol::packets::game::{
clientbound_player_combat_kill_packet::ClientboundPlayerCombatKillPacket, ClientboundGamePacket,
};
use azalea_world::entity::MinecraftEntityId;
+use bevy_app::{App, CoreSchedule, IntoSystemAppConfig, Plugin};
+use bevy_ecs::{component::Component, event::EventReader, query::Added, system::Query};
use derive_more::{Deref, DerefMut};
use tokio::sync::mpsc;
@@ -115,7 +109,7 @@ impl Plugin for EventPlugin {
.add_system(remove_player_listener)
.add_system(death_listener)
.add_system(keepalive_listener)
- .add_tick_system(tick_listener);
+ .add_system(tick_listener.in_schedule(CoreSchedule::FixedUpdate));
}
}
diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs
index 8e119c0e..44a4db6b 100644
--- a/azalea-client/src/lib.rs
+++ b/azalea-client/src/lib.rs
@@ -26,7 +26,6 @@ mod player;
pub mod task_pool;
pub use account::Account;
-pub use azalea_ecs as ecs;
pub use client::{init_ecs_app, start_ecs, Client, ClientInformation, JoinError};
pub use events::Event;
pub use local_player::{GameProfileComponent, LocalPlayer};
diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs
index d31f840f..be847e78 100644
--- a/azalea-client/src/local_player.rs
+++ b/azalea-client/src/local_player.rs
@@ -2,14 +2,13 @@ use std::{collections::HashMap, io, sync::Arc};
use azalea_auth::game_profile::GameProfile;
use azalea_core::ChunkPos;
-use azalea_ecs::component::Component;
-use azalea_ecs::entity::Entity;
-use azalea_ecs::event::EventReader;
-use azalea_ecs::{query::Added, system::Query};
use azalea_protocol::packets::game::ServerboundGamePacket;
use azalea_world::{
entity::{self, Dead},
- PartialWorld, World,
+ Instance, PartialWorld,
+};
+use bevy_ecs::{
+ component::Component, entity::Entity, event::EventReader, query::Added, system::Query,
};
use derive_more::{Deref, DerefMut};
use parking_lot::RwLock;
@@ -44,7 +43,7 @@ pub struct LocalPlayer {
pub partial_world: Arc<RwLock<PartialWorld>>,
/// The world is the combined [`PartialWorld`]s of all clients in the same
/// world. (Only relevant if you're using a shared world, i.e. a swarm)
- pub world: Arc<RwLock<World>>,
+ pub world: Arc<RwLock<Instance>>,
/// A task that reads packets from the server. The client is disconnected
/// when this task ends.
@@ -88,7 +87,7 @@ impl LocalPlayer {
pub fn new(
entity: Entity,
packet_writer: mpsc::UnboundedSender<ServerboundGamePacket>,
- world: Arc<RwLock<World>>,
+ world: Arc<RwLock<Instance>>,
read_packets_task: JoinHandle<()>,
write_packets_task: JoinHandle<()>,
) -> Self {
@@ -129,7 +128,7 @@ impl Drop for LocalPlayer {
/// Update the [`LocalPlayerInLoadedChunk`] component for all [`LocalPlayer`]s.
pub fn update_in_loaded_chunk(
- mut commands: azalea_ecs::system::Commands,
+ mut commands: bevy_ecs::system::Commands,
query: Query<(Entity, &LocalPlayer, &entity::Position)>,
) {
for (entity, local_player, position) in &query {
diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs
index f379501c..f6123c70 100644
--- a/azalea-client/src/movement.rs
+++ b/azalea-client/src/movement.rs
@@ -1,7 +1,8 @@
use crate::client::Client;
-use crate::local_player::{LocalPlayer, LocalPlayerInLoadedChunk, PhysicsState};
-use azalea_ecs::entity::Entity;
-use azalea_ecs::{event::EventReader, query::With, system::Query};
+use crate::local_player::{
+ update_in_loaded_chunk, LocalPlayer, LocalPlayerInLoadedChunk, PhysicsState,
+};
+use azalea_physics::{force_jump_listener, PhysicsSet};
use azalea_protocol::packets::game::serverbound_player_command_packet::ServerboundPlayerCommandPacket;
use azalea_protocol::packets::game::{
serverbound_move_player_pos_packet::ServerboundMovePlayerPosPacket,
@@ -13,6 +14,14 @@ use azalea_world::{
entity::{self, metadata::Sprinting, Attributes, Jumping, MinecraftEntityId},
MoveEntityError,
};
+use bevy_app::{App, CoreSchedule, IntoSystemAppConfigs, Plugin};
+use bevy_ecs::{
+ entity::Entity,
+ event::EventReader,
+ query::With,
+ schedule::{IntoSystemConfig, IntoSystemConfigs},
+ system::Query,
+};
use std::backtrace::Backtrace;
use thiserror::Error;
@@ -34,6 +43,28 @@ impl From<MoveEntityError> for MovePlayerError {
}
}
+pub struct PlayerMovePlugin;
+
+impl Plugin for PlayerMovePlugin {
+ fn build(&self, app: &mut App) {
+ app.add_event::<StartWalkEvent>()
+ .add_event::<StartSprintEvent>()
+ .add_systems(
+ (sprint_listener, walk_listener)
+ .chain()
+ .before(force_jump_listener),
+ )
+ .add_systems(
+ (
+ local_player_ai_step.in_set(PhysicsSet),
+ send_position.after(update_in_loaded_chunk),
+ )
+ .chain()
+ .in_schedule(CoreSchedule::FixedUpdate),
+ );
+ }
+}
+
impl Client {
/// Set whether we're jumping. This acts as if you held space in
/// vanilla. If you want to jump once, use the `jump` function.
diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs
index 9f8c5f1a..76e6ee41 100644
--- a/azalea-client/src/packet_handling.rs
+++ b/azalea-client/src/packet_handling.rs
@@ -1,15 +1,6 @@
use std::{collections::HashSet, io::Cursor, sync::Arc};
use azalea_core::{ChunkPos, ResourceLocation, Vec3};
-use azalea_ecs::{
- app::{App, CoreStage, Plugin},
- component::Component,
- ecs::Ecs,
- entity::Entity,
- event::{EventReader, EventWriter, Events},
- schedule::{StageLabel, SystemStage},
- system::{Commands, Query, ResMut, SystemState},
-};
use azalea_protocol::{
connect::{ReadConnection, WriteConnection},
packets::game::{
@@ -25,12 +16,21 @@ use azalea_protocol::{
use azalea_world::{
entity::{
metadata::{apply_metadata, Health, PlayerMetadataBundle},
- set_rotation, Dead, EntityBundle, EntityKind, LastSentPosition, MinecraftEntityId, Physics,
- PlayerBundle, Position, WorldName,
+ set_rotation, Dead, EntityBundle, EntityKind, EntityUpdateSet, LastSentPosition,
+ MinecraftEntityId, Physics, PlayerBundle, Position, WorldName,
},
entity::{LoadedBy, RelativeEntityUpdate},
PartialWorld, WorldContainer,
};
+use bevy_app::{App, CoreSet, Plugin};
+use bevy_ecs::{
+ component::Component,
+ entity::Entity,
+ event::{EventReader, EventWriter, Events},
+ schedule::IntoSystemConfig,
+ system::{Commands, Query, ResMut, SystemState},
+ world::World,
+};
use log::{debug, error, trace, warn};
use parking_lot::Mutex;
use tokio::sync::mpsc;
@@ -46,7 +46,7 @@ use crate::{
/// ```
/// # use azalea_client::packet_handling::PacketEvent;
/// # use azalea_protocol::packets::game::ClientboundGamePacket;
-/// # use azalea_ecs::event::EventReader;
+/// # use bevy_ecs::event::EventReader;
///
/// fn handle_packets(mut events: EventReader<PacketEvent>) {
/// for PacketEvent {
@@ -72,25 +72,22 @@ pub struct PacketEvent {
pub struct PacketHandlerPlugin;
-#[derive(StageLabel)]
-pub struct SendPacketEventsStage;
-
impl Plugin for PacketHandlerPlugin {
fn build(&self, app: &mut App) {
- app.add_stage_before(
- CoreStage::PreUpdate,
- SendPacketEventsStage,
- SystemStage::parallel(),
- )
- .add_system_to_stage(SendPacketEventsStage, send_packet_events)
- .add_system_to_stage(CoreStage::PreUpdate, process_packet_events)
- .init_resource::<Events<PacketEvent>>()
- .add_event::<AddPlayerEvent>()
- .add_event::<RemovePlayerEvent>()
- .add_event::<UpdatePlayerEvent>()
- .add_event::<ChatReceivedEvent>()
- .add_event::<DeathEvent>()
- .add_event::<KeepAliveEvent>();
+ app.add_system(send_packet_events.in_base_set(CoreSet::First))
+ .add_system(
+ process_packet_events
+ .in_base_set(CoreSet::PreUpdate)
+ // we want to index and deindex right after
+ .before(EntityUpdateSet::Deindex),
+ )
+ .init_resource::<Events<PacketEvent>>()
+ .add_event::<AddPlayerEvent>()
+ .add_event::<RemovePlayerEvent>()
+ .add_event::<UpdatePlayerEvent>()
+ .add_event::<ChatReceivedEvent>()
+ .add_event::<DeathEvent>()
+ .add_event::<KeepAliveEvent>();
}
}
@@ -168,7 +165,7 @@ pub fn send_packet_events(
}
}
-fn process_packet_events(ecs: &mut Ecs) {
+fn process_packet_events(ecs: &mut World) {
let mut events_owned = Vec::new();
let mut system_state: SystemState<EventReader<PacketEvent>> = SystemState::new(ecs);
let mut events = system_state.get_mut(ecs);
@@ -715,8 +712,7 @@ fn process_packet_events(ecs: &mut Ecs) {
if let Some(entity) = entity {
let new_position = p.position;
- commands.add(RelativeEntityUpdate {
- entity,
+ commands.entity(entity).add(RelativeEntityUpdate {
partial_world: local_player.partial_world.clone(),
update: Box::new(move |entity| {
let mut position = entity.get_mut::<Position>().unwrap();
@@ -747,8 +743,7 @@ fn process_packet_events(ecs: &mut Ecs) {
if let Some(entity) = entity {
let delta = p.delta.clone();
- commands.add(RelativeEntityUpdate {
- entity,
+ commands.entity(entity).add(RelativeEntityUpdate {
partial_world: local_player.partial_world.clone(),
update: Box::new(move |entity_mut| {
let mut position = entity_mut.get_mut::<Position>().unwrap();
@@ -776,8 +771,7 @@ fn process_packet_events(ecs: &mut Ecs) {
if let Some(entity) = entity {
let delta = p.delta.clone();
- commands.add(RelativeEntityUpdate {
- entity,
+ commands.entity(entity).add(RelativeEntityUpdate {
partial_world: local_player.partial_world.clone(),
update: Box::new(move |entity_mut| {
let mut position = entity_mut.get_mut::<Position>().unwrap();
diff --git a/azalea-client/src/player.rs b/azalea-client/src/player.rs
index 3680e2d0..c2c8a94e 100755
--- a/azalea-client/src/player.rs
+++ b/azalea-client/src/player.rs
@@ -1,11 +1,11 @@
use azalea_auth::game_profile::GameProfile;
use azalea_chat::FormattedText;
use azalea_core::GameType;
-use azalea_ecs::{
+use azalea_world::entity::EntityInfos;
+use bevy_ecs::{
event::EventReader,
system::{Commands, Res},
};
-use azalea_world::entity::EntityInfos;
use uuid::Uuid;
use crate::{packet_handling::AddPlayerEvent, GameProfileComponent};
diff --git a/azalea-client/src/task_pool.rs b/azalea-client/src/task_pool.rs
index 59f70487..8df554f0 100644
--- a/azalea-client/src/task_pool.rs
+++ b/azalea-client/src/task_pool.rs
@@ -1,11 +1,16 @@
//! Borrowed from `bevy_core`.
-use azalea_ecs::{
- app::{App, Plugin},
- schedule::IntoSystemDescriptor,
- system::Resource,
+use std::marker::PhantomData;
+
+use bevy_app::{App, CoreSet, Plugin};
+use bevy_ecs::{
+ schedule::IntoSystemConfig,
+ system::{NonSend, Resource},
+};
+use bevy_tasks::{
+ tick_global_task_pools_on_main_thread, AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool,
+ TaskPoolBuilder,
};
-use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder};
/// Setup of default task pools: `AsyncComputeTaskPool`, `ComputeTaskPool`,
/// `IoTaskPool`.
@@ -22,13 +27,16 @@ impl Plugin for TaskPoolPlugin {
self.task_pool_options.create_default_pools();
#[cfg(not(target_arch = "wasm32"))]
- app.add_system_to_stage(
- azalea_ecs::app::CoreStage::Last,
- bevy_tasks::tick_global_task_pools_on_main_thread.at_end(),
- );
+ app.add_system(tick_global_task_pools.in_base_set(CoreSet::Last));
}
}
+pub struct NonSendMarker(PhantomData<*mut ()>);
+#[cfg(not(target_arch = "wasm32"))]
+fn tick_global_task_pools(_main_thread_marker: Option<NonSend<NonSendMarker>>) {
+ tick_global_task_pools_on_main_thread();
+}
+
/// Helper for configuring and creating the default task pools. For end-users
/// who want full control, set up [`TaskPoolPlugin`](TaskPoolPlugin)
#[derive(Clone, Resource)]