aboutsummaryrefslogtreecommitdiff
path: root/azalea-entity/src
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-entity/src')
-rw-r--r--azalea-entity/src/lib.rs4
-rw-r--r--azalea-entity/src/plugin/components.rs4
-rw-r--r--azalea-entity/src/plugin/mod.rs52
-rw-r--r--azalea-entity/src/plugin/relative_updates.rs115
4 files changed, 34 insertions, 141 deletions
diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs
index fa4feffb..aacc3f54 100644
--- a/azalea-entity/src/lib.rs
+++ b/azalea-entity/src/lib.rs
@@ -424,6 +424,10 @@ pub struct PlayerAbilities {
/// The type of fluid that is at an entity's eye position, while also accounting
/// for fluid height.
+///
+/// This is only updated for [`AbstractLiving`] entities.
+///
+/// [`AbstractLiving`]: metadata::AbstractLiving
#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))]
#[derive(Clone, Copy, Debug, Deref, DerefMut, PartialEq)]
pub struct FluidOnEyes(FluidKind);
diff --git a/azalea-entity/src/plugin/components.rs b/azalea-entity/src/plugin/components.rs
index 4698a808..eaeeb0d0 100644
--- a/azalea-entity/src/plugin/components.rs
+++ b/azalea-entity/src/plugin/components.rs
@@ -94,8 +94,8 @@ pub struct OnClimbable(bool);
/// A component that indicates whether the player is currently sneaking.
///
-/// If the entity isn't a local player, then this is just a shortcut for
-/// checking if the [`Pose`] is `Crouching`.
+/// If the entity is a player but isn't a local player, then this is just a
+/// shortcut for checking if the [`Pose`] is `Crouching`.
///
/// If you need to modify this value, use
/// `azalea_client::PhysicsState::trying_to_crouch` or `Client::set_crouching`
diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs
index e40c24f2..b86c6b7d 100644
--- a/azalea-entity/src/plugin/mod.rs
+++ b/azalea-entity/src/plugin/mod.rs
@@ -1,6 +1,5 @@
mod components;
pub mod indexing;
-mod relative_updates;
use std::collections::HashSet;
@@ -17,13 +16,12 @@ use bevy_ecs::prelude::*;
pub use components::*;
use derive_more::{Deref, DerefMut};
use indexing::EntityUuidIndex;
-pub use relative_updates::RelativeEntityUpdate;
use tracing::debug;
use crate::{
FluidOnEyes, LookDirection, Physics, Pose, Position,
dimensions::{EntityDimensions, calculate_dimensions},
- metadata::Health,
+ metadata::{self, Health, Player},
};
/// A Bevy [`SystemSet`] for various types of entity updates.
@@ -57,7 +55,6 @@ impl Plugin for EntityPlugin {
.chain()
.in_set(EntityUpdateSystems::Index),
(
- relative_updates::debug_detect_updates_received_on_local_entities,
debug_new_entity,
add_dead,
clamp_look_direction,
@@ -97,27 +94,32 @@ pub fn add_dead(mut commands: Commands, query: Query<(Entity, &Health), Changed<
}
pub fn update_fluid_on_eyes(
- mut query: Query<(&mut FluidOnEyes, &Position, &EntityDimensions, &WorldName)>,
+ mut query: Query<
+ (&mut FluidOnEyes, &Position, &EntityDimensions, &WorldName),
+ With<metadata::AbstractLiving>,
+ >,
worlds: Res<Worlds>,
) {
- for (mut fluid_on_eyes, position, dimensions, world_name) in query.iter_mut() {
- let Some(world) = worlds.get(world_name) else {
- continue;
- };
-
- let adjusted_eye_y = position.y + (dimensions.eye_height as f64) - 0.1111111119389534;
- let eye_block_pos = BlockPos::from(position.with_y(adjusted_eye_y));
- let fluid_at_eye = world
- .read()
- .get_fluid_state(eye_block_pos)
- .unwrap_or_default();
- let fluid_cutoff_y = (eye_block_pos.y as f32 + fluid_at_eye.height()) as f64;
- if fluid_cutoff_y > adjusted_eye_y {
- **fluid_on_eyes = fluid_at_eye.kind;
- } else {
- **fluid_on_eyes = FluidKind::Empty;
- }
- }
+ query
+ .par_iter_mut()
+ .for_each(|(mut fluid_on_eyes, position, dimensions, world_name)| {
+ let Some(world) = worlds.get(world_name) else {
+ return;
+ };
+
+ let adjusted_eye_y = position.y + (dimensions.eye_height as f64) - 0.1111111119389534;
+ let eye_block_pos = BlockPos::from(position.with_y(adjusted_eye_y));
+ let fluid_at_eye = world
+ .read()
+ .get_fluid_state(eye_block_pos)
+ .unwrap_or_default();
+ let fluid_cutoff_y = (eye_block_pos.y as f32 + fluid_at_eye.height()) as f64;
+ if fluid_cutoff_y > adjusted_eye_y {
+ **fluid_on_eyes = fluid_at_eye.kind;
+ } else {
+ **fluid_on_eyes = FluidKind::Empty;
+ }
+ });
}
pub fn update_on_climbable(
@@ -229,7 +231,9 @@ pub fn update_dimensions(
}
}
-pub fn update_crouching(query: Query<(&mut Crouching, &Pose), Without<LocalEntity>>) {
+pub fn update_crouching(
+ query: Query<(&mut Crouching, &Pose), (Without<LocalEntity>, With<Player>)>,
+) {
for (mut crouching, pose) in query {
let new_crouching = *pose == Pose::Crouching;
// avoid triggering change detection
diff --git a/azalea-entity/src/plugin/relative_updates.rs b/azalea-entity/src/plugin/relative_updates.rs
deleted file mode 100644
index 53eb4c95..00000000
--- a/azalea-entity/src/plugin/relative_updates.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-// How entity updates are processed (to avoid issues with shared worlds)
-// - each bot contains a map of { entity id: updates received }
-// - the shared world also contains a canonical "true" updates received for each
-// entity
-// - when a client loads an entity, its "updates received" is set to the same as
-// the global "updates received"
-// - when the shared world sees an entity for the first time, the "updates
-// received" is set to 1.
-// - clients can force the shared "updates received" to 0 to make it so certain
-// entities (i.e. other bots in our swarm) don't get confused and updated by
-// other bots
-// - when a client gets an update to an entity, we check if our "updates
-// received" is the same as the shared world's "updates received": if it is,
-// then process the update and increment the client's and shared world's
-// "updates received" if not, then we simply increment our local "updates
-// received" and do nothing else
-
-use std::sync::Arc;
-
-use azalea_core::entity_id::MinecraftEntityId;
-use azalea_world::PartialWorld;
-use bevy_ecs::prelude::*;
-use derive_more::{Deref, DerefMut};
-use parking_lot::RwLock;
-use tracing::warn;
-
-use crate::LocalEntity;
-
-/// An [`EntityCommand`] that applies a "relative update" to an entity, which
-/// means this update won't be run multiple times by different clients in the
-/// same world.
-///
-/// This is used to avoid a bug where when there's multiple clients in the same
-/// world and an entity sends a relative move packet to all clients, its
-/// position gets desynced since the relative move is applied multiple times.
-///
-/// Don't use this unless you actually got an entity update packet that all
-/// other clients within render distance will get too. You usually don't need
-/// this when the change isn't relative either.
-pub struct RelativeEntityUpdate {
- pub partial_world: Arc<RwLock<PartialWorld>>,
- // a function that takes the entity and updates it
- pub update: Box<dyn FnOnce(&mut EntityWorldMut) + Send + Sync>,
-}
-impl RelativeEntityUpdate {
- pub fn new(
- partial_world: Arc<RwLock<PartialWorld>>,
- update: impl FnOnce(&mut EntityWorldMut) + Send + Sync + 'static,
- ) -> Self {
- Self {
- partial_world,
- update: Box::new(update),
- }
- }
-}
-
-/// A component that counts the number of times this entity has been modified.
-///
-/// This is used for making sure two clients don't do the same relative update
-/// on an entity.
-///
-/// If an entity is local (i.e. it's a client/LocalEntity), this component
-/// should NOT be present in the entity.
-#[derive(Component, Debug, Deref, DerefMut)]
-pub struct UpdatesReceived(u32);
-
-impl EntityCommand for RelativeEntityUpdate {
- fn apply(self, mut entity: EntityWorldMut) {
- let partial_entity_infos = &mut self.partial_world.write().entity_infos;
-
- if Some(entity.id()) == partial_entity_infos.owner_entity {
- // if the entity owns this partial world, it's always allowed to update itself
- (self.update)(&mut entity);
- return;
- };
-
- let entity_id = *entity.get::<MinecraftEntityId>().unwrap();
- if entity.contains::<LocalEntity>() {
- // a client tried to update another client, which isn't allowed
- return;
- }
-
- let this_client_updates_received = partial_entity_infos
- .updates_received
- .get(&entity_id)
- .copied();
-
- let can_update = if let Some(updates_received) = entity.get::<UpdatesReceived>() {
- this_client_updates_received.unwrap_or(1) == **updates_received
- } else {
- // no UpdatesReceived means the entity was just spawned
- true
- };
- if can_update {
- let new_updates_received = this_client_updates_received.unwrap_or(0) + 1;
- partial_entity_infos
- .updates_received
- .insert(entity_id, new_updates_received);
-
- entity.insert(UpdatesReceived(new_updates_received));
-
- (self.update)(&mut entity);
- }
- }
-}
-
-/// A system that logs a warning if an entity has both [`UpdatesReceived`]
-/// and [`LocalEntity`].
-pub fn debug_detect_updates_received_on_local_entities(
- query: Query<Entity, (With<LocalEntity>, With<UpdatesReceived>)>,
-) {
- for entity in &query {
- warn!("Entity {entity:?} has both LocalEntity and UpdatesReceived");
- }
-}