aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2023-09-16 22:30:28 -0500
committermat <git@matdoes.dev>2023-09-16 22:30:28 -0500
commit61e63c08968f7b0f451c4c3b07ea8d4927b14a2f (patch)
treef7b489bedde2a3bb9f703aa542c6863191f00ced
parenta920359c9a8f254bbfb6c1d04f2bda6365c09c6b (diff)
downloadazalea-drasl-61e63c08968f7b0f451c4c3b07ea8d4927b14a2f.tar.xz
don't apply metadata updates multiple times in swarms
-rw-r--r--azalea-client/src/client.rs24
-rw-r--r--azalea-client/src/packet_handling.rs35
-rw-r--r--azalea-client/src/task_pool.rs2
3 files changed, 49 insertions, 12 deletions
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index 0cf01582..6b2dba57 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -87,6 +87,8 @@ pub struct Client {
/// This is immutable; the server cannot change it. To get the username and
/// skin the server chose for you, get your player from the [`TabList`]
/// component.
+ ///
+ /// This as also available from the ECS as [`GameProfileComponent`].
pub profile: GameProfile,
/// The entity for this client in the ECS.
pub entity: Entity,
@@ -580,6 +582,28 @@ impl Client {
pub fn hunger(&self) -> Hunger {
self.component::<Hunger>().to_owned()
}
+
+ /// Get the username of this client.
+ ///
+ /// This is a shortcut for
+ /// `bot.component::<GameProfileComponent>().name.clone()`.
+ pub fn username(&self) -> String {
+ self.component::<GameProfileComponent>().name.clone()
+ }
+
+ /// Get the Minecraft UUID of this client.
+ ///
+ /// This is a shortcut for `bot.component::<GameProfileComponent>().uuid`.
+ pub fn uuid(&self) -> Uuid {
+ self.component::<GameProfileComponent>().uuid
+ }
+
+ /// Get a map of player UUIDs to their information in the tab list.
+ ///
+ /// This is a shortcut for `bot.component::<TabList>().0`.
+ pub fn tab_list(&self) -> HashMap<Uuid, PlayerInfo> {
+ self.component::<TabList>().0
+ }
}
/// A bundle for the components that are present on a local player that received
diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs
index de88665e..0522d7e5 100644
--- a/azalea-client/src/packet_handling.rs
+++ b/azalea-client/src/packet_handling.rs
@@ -634,11 +634,11 @@ pub fn process_packet_events(ecs: &mut World) {
let mut system_state: SystemState<(
Commands,
- Query<&EntityIdIndex>,
+ Query<(&EntityIdIndex, &LocalPlayer)>,
Query<&EntityKind>,
)> = SystemState::new(ecs);
let (mut commands, mut query, entity_kind_query) = system_state.get_mut(ecs);
- let entity_id_index = query.get_mut(player_entity).unwrap();
+ let (entity_id_index, local_player) = query.get_mut(player_entity).unwrap();
let entity = entity_id_index.get(&MinecraftEntityId(p.id));
@@ -646,15 +646,28 @@ pub fn process_packet_events(ecs: &mut World) {
warn!("Server sent an entity data packet for an entity id ({}) that we don't know about", p.id);
continue;
};
- let entity_kind = entity_kind_query.get(entity).unwrap();
- let mut entity_commands = commands.entity(entity);
- if let Err(e) = apply_metadata(
- &mut entity_commands,
- **entity_kind,
- (*p.packed_items).clone(),
- ) {
- warn!("{e}");
- }
+ let entity_kind = *entity_kind_query.get(entity).unwrap();
+
+ // we use RelativeEntityUpdate because it makes sure changes aren't made
+ // multiple times
+ commands.entity(entity).add(RelativeEntityUpdate {
+ partial_world: local_player.partial_instance.clone(),
+ update: Box::new(move |entity| {
+ let entity_id = entity.id();
+ entity.world_scope(|world| {
+ let mut commands_system_state = SystemState::<Commands>::new(world);
+ let mut commands = commands_system_state.get_mut(world);
+ let mut entity_comands = commands.entity(entity_id);
+ if let Err(e) = apply_metadata(
+ &mut entity_comands,
+ *entity_kind,
+ (*p.packed_items).clone(),
+ ) {
+ warn!("{e}");
+ }
+ });
+ }),
+ });
system_state.apply(ecs);
}
diff --git a/azalea-client/src/task_pool.rs b/azalea-client/src/task_pool.rs
index 982c3396..32c74c6f 100644
--- a/azalea-client/src/task_pool.rs
+++ b/azalea-client/src/task_pool.rs
@@ -35,7 +35,7 @@ fn tick_global_task_pools(_main_thread_marker: Option<NonSend<NonSendMarker>>) {
}
/// Helper for configuring and creating the default task pools. For end-users
-/// who want full control, set up [`TaskPoolPlugin`](TaskPoolPlugin)
+/// who want full control, set up [`TaskPoolPlugin`]
#[derive(Clone, Resource)]
pub struct TaskPoolOptions {
/// If the number of physical cores is less than min_total_threads, force