From 08c778febfd28310faff163d66c09d466b1ea4ce Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 14 Aug 2025 04:15:15 +0800 Subject: [PATCH 1/7] start implementing sneaking --- azalea-client/src/client.rs | 4 +- azalea-client/src/local_player.rs | 29 --- azalea-client/src/plugins/interact/mod.rs | 19 +- azalea-client/src/plugins/inventory.rs | 5 +- azalea-client/src/plugins/mining.rs | 4 +- azalea-client/src/plugins/movement.rs | 47 +++- azalea-client/src/plugins/packet/game/mod.rs | 4 +- azalea-core/src/cursor3d.rs | 6 +- azalea-core/src/math.rs | 4 + azalea-entity/src/attributes.rs | 2 + azalea-entity/src/lib.rs | 29 ++- azalea-physics/src/collision/mod.rs | 227 ++++++++++++++---- azalea-physics/src/lib.rs | 93 +++---- azalea-physics/src/travel.rs | 222 +++++++---------- .../src/packets/game/c_player_abilities.rs | 17 +- azalea/examples/testbot/commands/movement.rs | 16 ++ azalea/src/pathfinder/simulation.rs | 2 +- 17 files changed, 417 insertions(+), 313 deletions(-) diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 9481ba2df..67b527476 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -14,7 +14,7 @@ use azalea_core::{ tick::GameTick, }; use azalea_entity::{ - EntityUpdateSet, EyeHeight, Position, + EntityUpdateSet, EyeHeight, PlayerAbilities, Position, Sneaking, indexing::{EntityIdIndex, EntityUuidIndex}, metadata::Health, }; @@ -55,7 +55,7 @@ use crate::{ interact::BlockStatePredictionHandler, inventory::Inventory, join::{ConnectOpts, StartJoinServerEvent}, - local_player::{Hunger, InstanceHolder, PermissionLevel, PlayerAbilities, TabList}, + local_player::{Hunger, InstanceHolder, PermissionLevel, TabList}, mining::{self}, movement::{LastSentLookDirection, PhysicsState}, packet::game::SendPacketEvent, diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs index 4a937ec72..ef44b7fbf 100644 --- a/azalea-client/src/local_player.rs +++ b/azalea-client/src/local_player.rs @@ -5,7 +5,6 @@ use std::{ }; use azalea_core::game_type::GameMode; -use azalea_protocol::packets::game::c_player_abilities::ClientboundPlayerAbilities; use azalea_world::{Instance, PartialInstance}; use bevy_ecs::{component::Component, prelude::*}; use derive_more::{Deref, DerefMut}; @@ -55,34 +54,6 @@ impl From for LocalGameMode { } } -/// A component that contains the abilities the player has, like flying -/// or instantly breaking blocks. This is only present on local players. -#[derive(Clone, Debug, Component, Default)] -pub struct PlayerAbilities { - pub invulnerable: bool, - pub flying: bool, - pub can_fly: bool, - /// Whether the player can instantly break blocks and can duplicate blocks - /// in their inventory. - pub instant_break: bool, - - pub flying_speed: f32, - /// Used for the fov - pub walking_speed: f32, -} -impl From<&ClientboundPlayerAbilities> for PlayerAbilities { - fn from(packet: &ClientboundPlayerAbilities) -> Self { - Self { - invulnerable: packet.flags.invulnerable, - flying: packet.flags.flying, - can_fly: packet.flags.can_fly, - instant_break: packet.flags.instant_break, - flying_speed: packet.flying_speed, - walking_speed: packet.walking_speed, - } - } -} - /// Level must be 0..=4 #[derive(Component, Clone, Default, Deref, DerefMut)] pub struct PermissionLevel(pub u8); diff --git a/azalea-client/src/plugins/interact/mod.rs b/azalea-client/src/plugins/interact/mod.rs index 634d492c9..3aede1ea3 100644 --- a/azalea-client/src/plugins/interact/mod.rs +++ b/azalea-client/src/plugins/interact/mod.rs @@ -11,7 +11,7 @@ use azalea_core::{ tick::GameTick, }; use azalea_entity::{ - Attributes, LocalEntity, LookDirection, + Attributes, LocalEntity, LookDirection, PlayerAbilities, Sneaking, attributes::{ creative_block_interaction_range_modifier, creative_entity_interaction_range_modifier, }, @@ -36,7 +36,7 @@ use crate::{ attack::handle_attack_event, interact::pick::{HitResultComponent, update_hit_result_component}, inventory::{Inventory, InventorySet}, - local_player::{LocalGameMode, PermissionLevel, PlayerAbilities}, + local_player::{LocalGameMode, PermissionLevel}, movement::MoveEventsSet, packet::game::SendPacketEvent, respawn::perform_respawn, @@ -250,12 +250,20 @@ pub fn handle_start_use_item_queued( &mut BlockStatePredictionHandler, &HitResultComponent, &LookDirection, + &Sneaking, Option<&Mining>, )>, entity_id_query: Query<&MinecraftEntityId>, ) { - for (entity, start_use_item, mut prediction_handler, hit_result, look_direction, mining) in - query + for ( + entity, + start_use_item, + mut prediction_handler, + hit_result, + look_direction, + sneaking, + mining, + ) in query { commands.entity(entity).remove::(); @@ -332,8 +340,7 @@ pub fn handle_start_use_item_queued( location: r.location, hand: InteractionHand::MainHand, }, - // TODO: sneaking - using_secondary_action: false, + using_secondary_action: **sneaking, }, )); } diff --git a/azalea-client/src/plugins/inventory.rs b/azalea-client/src/plugins/inventory.rs index 732e11547..ecc8e8262 100644 --- a/azalea-client/src/plugins/inventory.rs +++ b/azalea-client/src/plugins/inventory.rs @@ -4,6 +4,7 @@ use std::{ }; use azalea_chat::FormattedText; +use azalea_entity::PlayerAbilities; pub use azalea_inventory::*; use azalea_inventory::{ item::MaxStackSizeExt, @@ -23,9 +24,7 @@ use bevy_app::{App, Plugin, Update}; use bevy_ecs::prelude::*; use tracing::{error, warn}; -use crate::{ - Client, local_player::PlayerAbilities, packet::game::SendPacketEvent, respawn::perform_respawn, -}; +use crate::{Client, packet::game::SendPacketEvent, respawn::perform_respawn}; pub struct InventoryPlugin; impl Plugin for InventoryPlugin { diff --git a/azalea-client/src/plugins/mining.rs b/azalea-client/src/plugins/mining.rs index 2ee476aed..43aae004c 100644 --- a/azalea-client/src/plugins/mining.rs +++ b/azalea-client/src/plugins/mining.rs @@ -1,6 +1,6 @@ use azalea_block::{BlockState, BlockTrait, fluid_state::FluidState}; use azalea_core::{direction::Direction, game_type::GameMode, position::BlockPos, tick::GameTick}; -use azalea_entity::{FluidOnEyes, Physics, Position, mining::get_mine_progress}; +use azalea_entity::{FluidOnEyes, Physics, PlayerAbilities, Position, mining::get_mine_progress}; use azalea_inventory::ItemStack; use azalea_physics::{PhysicsSet, collision::BlockWithShape}; use azalea_protocol::packets::game::s_player_action::{self, ServerboundPlayerAction}; @@ -17,7 +17,7 @@ use crate::{ check_is_interaction_restricted, pick::HitResultComponent, }, inventory::{Inventory, InventorySet}, - local_player::{InstanceHolder, LocalGameMode, PermissionLevel, PlayerAbilities}, + local_player::{InstanceHolder, LocalGameMode, PermissionLevel}, movement::MoveEventsSet, packet::game::SendPacketEvent, }; diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index c9b3b070e..c6a36f40d 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -6,7 +6,7 @@ use azalea_core::{ }; use azalea_entity::{ Attributes, HasClientLoaded, Jumping, LastSentPosition, LookDirection, Physics, Position, - metadata::Sprinting, + Sneaking, metadata::Sprinting, }; use azalea_physics::{PhysicsSet, ai_step}; use azalea_protocol::{ @@ -97,6 +97,16 @@ impl Client { *self.component::() } + pub fn set_sneaking(&self, sneaking: bool) { + let mut ecs = self.ecs.lock(); + let mut jumping_mut = self.query::<&mut Sneaking>(&mut ecs); + **jumping_mut = sneaking; + } + + pub fn sneaking(&self) -> bool { + *self.component::() + } + /// Sets the direction the client is looking. `y_rot` is yaw (looking to the /// side), `x_rot` is pitch (looking up and down). You can get these /// numbers from the vanilla f3 screen. @@ -254,10 +264,16 @@ pub fn send_position( #[derive(Debug, Default, Component, Clone, PartialEq, Eq)] pub struct LastSentInput(pub ServerboundPlayerInput); pub fn send_player_input_packet( - mut query: Query<(Entity, &PhysicsState, &Jumping, Option<&LastSentInput>)>, + mut query: Query<( + Entity, + &PhysicsState, + &Jumping, + &Sneaking, + Option<&LastSentInput>, + )>, mut commands: Commands, ) { - for (entity, physics_state, jumping, last_sent_input) in query.iter_mut() { + for (entity, physics_state, jumping, sneaking, last_sent_input) in query.iter_mut() { let dir = physics_state.move_direction; type D = WalkDirection; let input = ServerboundPlayerInput { @@ -266,8 +282,7 @@ pub fn send_player_input_packet( left: matches!(dir, D::Left | D::ForwardLeft | D::BackwardLeft), right: matches!(dir, D::Right | D::ForwardRight | D::BackwardRight), jump: **jumping, - // TODO: implement sneaking - shift: false, + shift: **sneaking, sprint: physics_state.trying_to_sprint, }; @@ -347,16 +362,28 @@ pub(crate) fn tick_controls(mut query: Query<&mut PhysicsState>) { /// automatically by the client. pub fn local_player_ai_step( mut query: Query< - (&PhysicsState, &mut Physics, &mut Sprinting, &mut Attributes), + ( + &PhysicsState, + &Sneaking, + &mut Physics, + &mut Sprinting, + &mut Attributes, + ), With, >, ) { - for (physics_state, mut physics, mut sprinting, mut attributes) in query.iter_mut() { + for (physics_state, sneaking, mut physics, mut sprinting, mut attributes) in query.iter_mut() { // server ai step - // TODO: replace those booleans when using items, passengers, and sneaking are - // properly implemented - let move_vector = modify_input(physics_state.move_vector, false, false, false, &attributes); + // TODO: replace those booleans when using items and passengers are properly + // implemented + let move_vector = modify_input( + physics_state.move_vector, + false, + false, + **sneaking, + &attributes, + ); physics.x_acceleration = move_vector.x; physics.z_acceleration = move_vector.y; diff --git a/azalea-client/src/plugins/packet/game/mod.rs b/azalea-client/src/plugins/packet/game/mod.rs index 26d831958..495230023 100644 --- a/azalea-client/src/plugins/packet/game/mod.rs +++ b/azalea-client/src/plugins/packet/game/mod.rs @@ -8,7 +8,7 @@ use azalea_core::{ }; use azalea_entity::{ Dead, EntityBundle, EntityKindComponent, HasClientLoaded, LoadedBy, LocalEntity, LookDirection, - Physics, Position, RelativeEntityUpdate, + Physics, PlayerAbilities, Position, RelativeEntityUpdate, indexing::{EntityIdIndex, EntityUuidIndex}, metadata::{Health, apply_metadata}, }; @@ -33,7 +33,7 @@ use crate::{ inventory::{ ClientSideCloseContainerEvent, Inventory, MenuOpenedEvent, SetContainerContentEvent, }, - local_player::{Hunger, InstanceHolder, LocalGameMode, PlayerAbilities, TabList}, + local_player::{Hunger, InstanceHolder, LocalGameMode, TabList}, movement::{KnockbackEvent, KnockbackType}, packet::as_system, player::{GameProfileComponent, PlayerInfo}, diff --git a/azalea-core/src/cursor3d.rs b/azalea-core/src/cursor3d.rs index dc96d890d..91a14000e 100644 --- a/azalea-core/src/cursor3d.rs +++ b/azalea-core/src/cursor3d.rs @@ -71,13 +71,13 @@ impl Cursor3d { pub fn new(origin: BlockPos, end: BlockPos) -> Self { let width = (end.x - origin.x + 1) .try_into() - .expect("Impossible width."); + .unwrap_or_else(|_| panic!("Impossible width, origin: {origin:?}, end: {end:?}")); let height = (end.y - origin.y + 1) .try_into() - .expect("Impossible height."); + .unwrap_or_else(|_| panic!("Impossible height, origin: {origin:?}, end: {end:?}")); let depth = (end.z - origin.z + 1) .try_into() - .expect("Impossible depth."); + .unwrap_or_else(|_| panic!("Impossible depth, origin: {origin:?}, end: {end:?}")); Self { index: 0, diff --git a/azalea-core/src/math.rs b/azalea-core/src/math.rs index 105069efc..e62a3d234 100644 --- a/azalea-core/src/math.rs +++ b/azalea-core/src/math.rs @@ -92,6 +92,10 @@ pub fn sign_as_int(num: f64) -> i32 { if num == 0. { 0 } else { num.signum() as i32 } } +pub fn equal(a: f64, b: f64) -> bool { + (b - a).abs() < 1.0e-5 +} + #[cfg(test)] mod tests { use super::*; diff --git a/azalea-entity/src/attributes.rs b/azalea-entity/src/attributes.rs index c2a22e9b9..647625f8b 100644 --- a/azalea-entity/src/attributes.rs +++ b/azalea-entity/src/attributes.rs @@ -16,6 +16,8 @@ pub struct Attributes { pub block_interaction_range: AttributeInstance, pub entity_interaction_range: AttributeInstance, + + pub step_height: AttributeInstance, } #[derive(Clone, Debug)] diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 645a55345..3a75b4862 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -369,8 +369,7 @@ pub struct Physics { pub lava_fluid_height: f64, pub was_touching_water: bool, - // TODO: implement fall_distance - pub fall_distance: f32, + pub fall_distance: f64, // TODO: implement remaining_fire_ticks pub remaining_fire_ticks: i32, } @@ -514,6 +513,7 @@ pub struct EntityBundle { pub eye_height: EyeHeight, pub attributes: Attributes, pub jumping: Jumping, + pub sneaking: Sneaking, pub fluid_on_eyes: FluidOnEyes, pub on_climbable: OnClimbable, } @@ -547,6 +547,7 @@ impl EntityBundle { attributes: default_attributes(EntityKind::Player), jumping: Jumping(false), + sneaking: Sneaking(false), fluid_on_eyes: FluidOnEyes(FluidKind::Empty), on_climbable: OnClimbable(false), } @@ -563,6 +564,7 @@ pub fn default_attributes(_entity_kind: EntityKind) -> Attributes { water_movement_efficiency: AttributeInstance::new(0.0), block_interaction_range: AttributeInstance::new(4.5), entity_interaction_range: AttributeInstance::new(3.0), + step_height: AttributeInstance::new(0.6), } } @@ -586,3 +588,26 @@ impl FluidOnEyes { #[derive(Component, Clone, Copy, Debug, PartialEq, Deref, DerefMut)] pub struct OnClimbable(bool); + +/// A component that indicates whether the entity is currently trying to sneak. +/// +/// This is distinct from [`metadata::ShiftKeyDown`], which is a metadata value +/// controlled by the server. +#[derive(Component, Clone, Copy, Deref, DerefMut, Default)] +pub struct Sneaking(bool); + +/// A component that contains the abilities the player has, like flying +/// or instantly breaking blocks. This is only present on local players. +#[derive(Clone, Debug, Component, Default)] +pub struct PlayerAbilities { + pub invulnerable: bool, + pub flying: bool, + pub can_fly: bool, + /// Whether the player can instantly break blocks and can duplicate blocks + /// in their inventory. + pub instant_break: bool, + + pub flying_speed: f32, + /// Used for the fov + pub walking_speed: f32, +} diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index dc439f7b0..24db8359c 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -11,9 +11,13 @@ use azalea_block::{BlockState, fluid_state::FluidState}; use azalea_core::{ aabb::AABB, direction::Axis, - math::EPSILON, + math::{self, EPSILON}, position::{BlockPos, Vec3}, }; +use azalea_entity::{ + Attributes, Jumping, LookDirection, OnClimbable, Physics, PlayerAbilities, Pose, Position, + Sneaking, metadata::Sprinting, +}; use azalea_world::{ChunkStorage, Instance, MoveEntityError}; use bevy_ecs::{entity::Entity, world::Mut}; pub use blocks::BlockWithShape; @@ -23,6 +27,7 @@ pub use shape::*; use tracing::warn; use self::world_collisions::get_block_collisions; +use crate::travel::no_collision; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MoverType { @@ -34,22 +39,16 @@ pub enum MoverType { } // Entity.collide -fn collide( - movement: Vec3, - world: &Instance, - physics: &azalea_entity::Physics, - source_entity: Option, - physics_query: &PhysicsQuery, - collidable_entity_query: &CollidableEntityQuery, -) -> Vec3 { - let entity_bounding_box = physics.bounding_box; +fn collide(ctx: &MoveCtx, movement: Vec3) -> Vec3 { + let entity_bounding_box = ctx.physics.bounding_box; let entity_collisions = get_entity_collisions( - world, + ctx.world, &entity_bounding_box.expand_towards(movement), - source_entity, - physics_query, - collidable_entity_query, + Some(ctx.source_entity), + ctx.physics_query, + ctx.collidable_entity_query, ); + let world = ctx.world; let collided_delta = if movement.length_squared() == 0.0 { movement } else { @@ -60,7 +59,7 @@ fn collide( let y_collision = movement.y != collided_delta.y; let z_collision = movement.z != collided_delta.z; - let on_ground = physics.on_ground() || y_collision && movement.y < 0.; + let on_ground = ctx.physics.on_ground() || y_collision && movement.y < 0.; let max_up_step = 0.6; if max_up_step > 0. && on_ground && (x_collision || z_collision) { @@ -106,20 +105,30 @@ fn collide( collided_delta } +pub struct MoveCtx<'world, 'state, 'a, 'b> { + pub mover_type: MoverType, + pub world: &'a Instance, + pub position: Mut<'a, Position>, + pub physics: &'a mut Physics, + pub source_entity: Entity, + pub physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + pub collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, + pub sneaking: Sneaking, + pub attributes: &'a Attributes, + pub abilities: Option<&'a PlayerAbilities>, + + pub direction: LookDirection, + pub sprinting: Sprinting, + pub on_climbable: OnClimbable, + pub pose: Option, + pub jumping: Jumping, +} + /// Move an entity by a given delta, checking for collisions. /// /// In Mojmap, this is `Entity.move`. #[allow(clippy::too_many_arguments)] -pub fn move_colliding( - _mover_type: MoverType, - movement: Vec3, - world: &Instance, - position: &mut Mut, - physics: &mut azalea_entity::Physics, - source_entity: Option, - physics_query: &PhysicsQuery, - collidable_entity_query: &CollidableEntityQuery, -) -> Result<(), MoveEntityError> { +pub fn move_colliding(ctx: &mut MoveCtx, mut movement: Vec3) -> Result<(), MoveEntityError> { // TODO: do all these // if self.no_physics { @@ -139,20 +148,16 @@ pub fn move_colliding( // this.setDeltaMovement(Vec3.ZERO); // } - // movement = this.maybeBackOffFromEdge(movement, moverType); + movement = maybe_back_off_from_edge(ctx, movement); + let collide_result = collide(ctx, movement); - let collide_result = collide( - movement, - world, - physics, - source_entity, - physics_query, - collidable_entity_query, - ); + let move_distance_sqr = collide_result.length_squared(); - let move_distance = collide_result.length_squared(); + let position = &mut ctx.position; + let physics = &mut *ctx.physics; + let world = ctx.world; - if move_distance > EPSILON { + if move_distance_sqr > EPSILON || movement.length_squared() - move_distance_sqr < EPSILON { // TODO: fall damage let new_pos = { @@ -168,8 +173,8 @@ pub fn move_colliding( } } - let x_collision = movement.x != collide_result.x; - let z_collision = movement.z != collide_result.z; + let x_collision = math::equal(movement.x, collide_result.x); + let z_collision = math::equal(movement.z, collide_result.z); let horizontal_collision = x_collision || z_collision; physics.horizontal_collision = horizontal_collision; @@ -180,14 +185,15 @@ pub fn move_colliding( // TODO: minecraft checks for a "minor" horizontal collision here - let _block_pos_below = azalea_entity::on_pos_legacy(&world.chunks, **position); - // let _block_state_below = self - // .world - // .get_block_state(&block_pos_below) - // .expect("Couldn't get block state below"); + let block_pos_below = azalea_entity::on_pos_legacy(&world.chunks, **position); + let block_state_below = world.get_block_state(block_pos_below).unwrap_or_default(); - // self.check_fall_damage(collide_result.y, on_ground, block_state_below, - // block_pos_below); + check_fall_damage( + physics, + collide_result.y, + block_state_below, + block_pos_below, + ); // if self.isRemoved() { return; } @@ -238,6 +244,137 @@ pub fn move_colliding( Ok(()) } +fn check_fall_damage( + physics: &mut Physics, + delta_y: f64, + _block_state_below: BlockState, + _block_pos_below: BlockPos, +) { + if !physics.is_in_water() && delta_y < 0. { + physics.fall_distance -= delta_y as f32 as f64; + } + + if physics.on_ground() { + // vanilla calls block.fallOn here but it's not relevant for us + + physics.fall_distance = 0.; + } +} + +fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 { + let is_staying_on_ground_surface = *move_ctx.sneaking; + let max_up_step = get_max_up_step(move_ctx.attributes); + + let mut fall_ctx = CanFallAtLeastCtx { + physics: move_ctx.physics, + world: move_ctx.world, + source_entity: move_ctx.source_entity, + physics_query: move_ctx.physics_query, + collidable_entity_query: move_ctx.collidable_entity_query, + }; + + let Some(abilities) = move_ctx.abilities else { + return movement; + }; + + let is_backing_off = !abilities.flying + && movement.y <= 0. + && matches!(move_ctx.mover_type, MoverType::Own | MoverType::Player) + && is_staying_on_ground_surface + && is_above_ground(&mut fall_ctx, max_up_step); + if !is_backing_off { + return movement; + } + println!("backing off from edge"); + + let min_movement = 0.05; + let min_movement_x = movement.x.signum() * min_movement; + let min_movement_z = movement.z.signum() * min_movement; + + while movement.x != 0. && can_fall_at_least(&mut fall_ctx, movement.x, 0., max_up_step as f64) { + if movement.x.abs() < min_movement { + movement.x = 0.; + break; + } + + movement.x -= min_movement_x + } + while movement.z != 0. && can_fall_at_least(&mut fall_ctx, 0., movement.z, max_up_step as f64) { + if movement.z.abs() < min_movement { + movement.z = 0.; + break; + } + + movement.z -= min_movement_z + } + while movement.x != 0.0 + && movement.z != 0.0 + && can_fall_at_least(&mut fall_ctx, movement.x, movement.z, max_up_step as f64) + { + if movement.x.abs() <= min_movement { + movement.x = 0.; + } else { + movement.x -= min_movement_x; + } + if movement.z.abs() <= min_movement { + movement.z = 0.; + } else { + movement.z -= min_movement_z; + } + } + + movement +} + +fn get_max_up_step(attributes: &Attributes) -> f32 { + // this would be different if we were riding an entity + attributes.step_height.calculate() as f32 +} + +fn is_above_ground(ctx: &mut CanFallAtLeastCtx, max_up_step: f32) -> bool { + ctx.physics.on_ground() + && ctx.physics.fall_distance < max_up_step as f64 + && !can_fall_at_least(ctx, 0., 0., max_up_step as f64 - ctx.physics.fall_distance) +} + +pub struct CanFallAtLeastCtx<'world, 'state, 'a, 'b> { + physics: &'a mut Physics, + world: &'a Instance, + source_entity: Entity, + physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, +} + +fn can_fall_at_least( + ctx: &mut CanFallAtLeastCtx, + delta_x: f64, + delta_z: f64, + max_up_step: f64, +) -> bool { + let aabb = ctx.physics.bounding_box; + let aabb = AABB { + min: Vec3 { + x: aabb.min.x + EPSILON + delta_x, + y: aabb.min.y - max_up_step - EPSILON, + z: aabb.min.z + EPSILON + delta_z, + }, + max: Vec3 { + x: aabb.max.x - EPSILON + delta_x, + y: aabb.min.y, + z: aabb.max.z - EPSILON + delta_z, + }, + }; + no_collision( + ctx.world, + Some(ctx.source_entity), + ctx.physics_query, + ctx.collidable_entity_query, + &mut ctx.physics, + &aabb, + false, + ) +} + fn collide_bounding_box( movement: Vec3, entity_bounding_box: &AABB, diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 27250f618..7bef61577 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -23,11 +23,9 @@ use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_app::{App, Plugin}; use bevy_ecs::prelude::*; use clip::box_traverse_blocks; -use collision::{ - BLOCK_SHAPE, BlockWithShape, MoverType, VoxelShape, - entity_collisions::{CollidableEntityQuery, PhysicsQuery}, - move_colliding, -}; +use collision::{BLOCK_SHAPE, BlockWithShape, VoxelShape, move_colliding}; + +use crate::collision::MoveCtx; /// A Bevy [`SystemSet`] for running physics that makes entities do things. #[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] @@ -367,63 +365,27 @@ fn get_block_pos_below_that_affects_movement(position: Position) -> BlockPos { ) } -/// Options for [`handle_relative_friction_and_calculate_movement`] -struct HandleRelativeFrictionAndCalculateMovementOpts<'a, 'b, 'world, 'state> { - block_friction: f32, - world: &'a Instance, - physics: &'a mut Physics, - direction: LookDirection, - position: Mut<'a, Position>, - attributes: &'a Attributes, - is_sprinting: bool, - on_climbable: OnClimbable, - pose: Option, - jumping: Jumping, - entity: Entity, - physics_query: &'a PhysicsQuery<'world, 'state, 'b>, - collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, -} -fn handle_relative_friction_and_calculate_movement( - HandleRelativeFrictionAndCalculateMovementOpts { - block_friction, - world, - physics, - direction, - mut position, - attributes, - is_sprinting, - on_climbable, - pose, - jumping, - entity, - physics_query, - collidable_entity_query, - }: HandleRelativeFrictionAndCalculateMovementOpts<'_, '_, '_, '_>, -) -> Vec3 { +fn handle_relative_friction_and_calculate_movement(ctx: &mut MoveCtx, block_friction: f32) -> Vec3 { move_relative( - physics, - direction, - get_friction_influenced_speed(physics, attributes, block_friction, is_sprinting), + ctx.physics, + ctx.direction, + get_friction_influenced_speed(ctx.physics, ctx.attributes, block_friction, ctx.sprinting), Vec3::new( - physics.x_acceleration as f64, - physics.y_acceleration as f64, - physics.z_acceleration as f64, + ctx.physics.x_acceleration as f64, + ctx.physics.y_acceleration as f64, + ctx.physics.z_acceleration as f64, ), ); - physics.velocity = handle_on_climbable(physics.velocity, on_climbable, *position, world, pose); - - move_colliding( - MoverType::Own, - physics.velocity, - world, - &mut position, - physics, - Some(entity), - physics_query, - collidable_entity_query, - ) - .expect("Entity should exist"); + ctx.physics.velocity = handle_on_climbable( + ctx.physics.velocity, + ctx.on_climbable, + *ctx.position, + ctx.world, + ctx.pose, + ); + + move_colliding(ctx, ctx.physics.velocity).expect("Entity should exist"); // let delta_movement = entity.delta; // ladders // if ((entity.horizontalCollision || entity.jumping) && (entity.onClimbable() @@ -431,19 +393,20 @@ fn handle_relative_friction_and_calculate_movement( // PowderSnowBlock.canEntityWalkOnPowderSnow(entity))) { var3 = new // Vec3(var3.x, 0.2D, var3.z); } - if physics.horizontal_collision || *jumping { - let block_at_feet: Block = world + if ctx.physics.horizontal_collision || *ctx.jumping { + let block_at_feet: Block = ctx + .world .chunks - .get_block_state((*position).into()) + .get_block_state(BlockPos::from(*ctx.position)) .unwrap_or_default() .into(); - if *on_climbable || block_at_feet == Block::PowderSnow { - physics.velocity.y = 0.2; + if *ctx.on_climbable || block_at_feet == Block::PowderSnow { + ctx.physics.velocity.y = 0.2; } } - physics.velocity + ctx.physics.velocity } fn handle_on_climbable( @@ -488,7 +451,7 @@ fn get_friction_influenced_speed( physics: &Physics, attributes: &Attributes, friction: f32, - is_sprinting: bool, + sprinting: Sprinting, ) -> f32 { // TODO: have speed & flying_speed fields in entity if physics.on_ground() { @@ -496,7 +459,7 @@ fn get_friction_influenced_speed( speed * (0.21600002f32 / (friction * friction * friction)) } else { // entity.flying_speed - if is_sprinting { 0.025999999f32 } else { 0.02 } + if *sprinting { 0.025999999f32 } else { 0.02 } } } diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs index 80c289d9a..6ffb76a37 100644 --- a/azalea-physics/src/travel.rs +++ b/azalea-physics/src/travel.rs @@ -4,18 +4,18 @@ use azalea_core::{ position::{BlockPos, Vec3}, }; use azalea_entity::{ - Attributes, HasClientLoaded, Jumping, LocalEntity, LookDirection, OnClimbable, Physics, Pose, - Position, metadata::Sprinting, move_relative, + Attributes, HasClientLoaded, Jumping, LocalEntity, LookDirection, OnClimbable, Physics, + PlayerAbilities, Pose, Position, Sneaking, metadata::Sprinting, move_relative, }; use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_ecs::prelude::*; use crate::{ - HandleRelativeFrictionAndCalculateMovementOpts, collision::{ - MoverType, Shapes, + MoveCtx, MoverType, Shapes, entity_collisions::{CollidableEntityQuery, PhysicsQuery, get_entity_collisions}, move_colliding, + world_collisions::{get_block_and_liquid_collisions, get_block_collisions}, }, get_block_pos_below_that_affects_movement, handle_relative_friction_and_calculate_movement, }; @@ -36,6 +36,8 @@ pub fn travel( &InstanceName, &OnClimbable, &Jumping, + &Sneaking, + Option<&PlayerAbilities>, ), (With, With), >, @@ -54,6 +56,8 @@ pub fn travel( world_name, on_climbable, jumping, + sneaking, + abilities, ) in &mut query { let Some(world_lock) = instance_container.get(world_name) else { @@ -65,92 +69,57 @@ pub fn travel( // TODO: elytras - if physics.is_in_water() || physics.is_in_lava() { + let mut ctx = MoveCtx { + mover_type: MoverType::Own, + world: &world, + position, + physics: &mut physics, + source_entity: entity, + physics_query: &physics_query, + collidable_entity_query: &collidable_entity_query, + sneaking: *sneaking, + attributes, + abilities, + direction: *direction, + sprinting, + on_climbable: *on_climbable, + pose: pose.copied(), + jumping: *jumping, + }; + + if ctx.physics.is_in_water() || ctx.physics.is_in_lava() { // minecraft also checks for `this.isAffectedByFluids() && // !this.canStandOnFluid(fluidAtBlock)` here but it doesn't matter // for players - travel_in_fluid( - &world, - entity, - &mut physics, - *direction, - position, - attributes, - sprinting, - on_climbable, - &physics_query, - &collidable_entity_query, - ); + travel_in_fluid(&mut ctx); } else { - travel_in_air( - &world, - entity, - &mut physics, - *direction, - position, - attributes, - sprinting, - *on_climbable, - pose, - *jumping, - &physics_query, - &collidable_entity_query, - ); + travel_in_air(&mut ctx); } } } /// The usual movement when we're not in water or using an elytra. -#[allow(clippy::too_many_arguments)] -fn travel_in_air( - world: &Instance, - entity: Entity, - physics: &mut Physics, - direction: LookDirection, - position: Mut, - attributes: &Attributes, - sprinting: Sprinting, - on_climbable: OnClimbable, - pose: Option<&Pose>, - jumping: Jumping, - physics_query: &PhysicsQuery, - collidable_entity_query: &CollidableEntityQuery, -) { +fn travel_in_air(ctx: &mut MoveCtx) { let gravity = get_effective_gravity(); - let block_pos_below = get_block_pos_below_that_affects_movement(*position); + let block_pos_below = get_block_pos_below_that_affects_movement(*ctx.position); - let block_state_below = world + let block_state_below = ctx + .world .chunks .get_block_state(block_pos_below) .unwrap_or(BlockState::AIR); let block_below: Box = block_state_below.into(); let block_friction = block_below.behavior().friction; - let inertia = if physics.on_ground() { + let inertia = if ctx.physics.on_ground() { block_friction * 0.91 } else { 0.91 }; // this applies the current delta - let mut movement = handle_relative_friction_and_calculate_movement( - HandleRelativeFrictionAndCalculateMovementOpts { - block_friction, - world, - physics, - direction, - position, - attributes, - is_sprinting: *sprinting, - on_climbable, - pose: pose.copied(), - jumping, - entity, - physics_query, - collidable_entity_query, - }, - ); + let mut movement = handle_relative_friction_and_calculate_movement(ctx, block_friction); movement.y -= gravity; @@ -162,126 +131,97 @@ fn travel_in_air( // if should_discard_friction(self) { if false { - physics.velocity = movement; + ctx.physics.velocity = movement; } else { - physics.velocity = Vec3 { + ctx.physics.velocity = Vec3 { x: movement.x * inertia as f64, y: movement.y * 0.9800000190734863f64, z: movement.z * inertia as f64, }; } + + println!("set velocity to {:?}", ctx.physics.velocity); } -#[allow(clippy::too_many_arguments)] -fn travel_in_fluid( - world: &Instance, - entity: Entity, - physics: &mut Physics, - direction: LookDirection, - mut position: Mut, - attributes: &Attributes, - sprinting: Sprinting, - on_climbable: &OnClimbable, - physics_query: &PhysicsQuery, - collidable_entity_query: &CollidableEntityQuery, -) { - let moving_down = physics.velocity.y <= 0.; - let y = position.y; +fn travel_in_fluid(ctx: &mut MoveCtx) { + let moving_down = ctx.physics.velocity.y <= 0.; + let y = ctx.position.y; let gravity = get_effective_gravity(); let acceleration = Vec3::new( - physics.x_acceleration as f64, - physics.y_acceleration as f64, - physics.z_acceleration as f64, + ctx.physics.x_acceleration as f64, + ctx.physics.y_acceleration as f64, + ctx.physics.z_acceleration as f64, ); - if physics.was_touching_water { - let mut water_movement_speed = if *sprinting { 0.9 } else { 0.8 }; + if ctx.physics.was_touching_water { + let mut water_movement_speed = if *ctx.sprinting { 0.9 } else { 0.8 }; let mut speed = 0.02; - let mut water_efficiency_modifier = attributes.water_movement_efficiency.calculate() as f32; - if !physics.on_ground() { + let mut water_efficiency_modifier = + ctx.attributes.water_movement_efficiency.calculate() as f32; + if !ctx.physics.on_ground() { water_efficiency_modifier *= 0.5; } if water_efficiency_modifier > 0. { water_movement_speed += (0.54600006 - water_movement_speed) * water_efficiency_modifier; - speed += (attributes.speed.calculate() as f32 - speed) * water_efficiency_modifier; + speed += (ctx.attributes.speed.calculate() as f32 - speed) * water_efficiency_modifier; } // if (this.hasEffect(MobEffects.DOLPHINS_GRACE)) { // waterMovementSpeed = 0.96F; // } - move_relative(physics, direction, speed, acceleration); - move_colliding( - MoverType::Own, - physics.velocity, - world, - &mut position, - physics, - Some(entity), - physics_query, - collidable_entity_query, - ) - .expect("Entity should exist"); + move_relative(ctx.physics, ctx.direction, speed, acceleration); + move_colliding(ctx, ctx.physics.velocity).expect("Entity should exist"); - let mut new_velocity = physics.velocity; - if physics.horizontal_collision && **on_climbable { + let mut new_velocity = ctx.physics.velocity; + if ctx.physics.horizontal_collision && *ctx.on_climbable { // underwater ladders new_velocity.y = 0.2; } new_velocity.x *= water_movement_speed as f64; new_velocity.y *= 0.8; new_velocity.z *= water_movement_speed as f64; - physics.velocity = - get_fluid_falling_adjusted_movement(gravity, moving_down, new_velocity, sprinting); + ctx.physics.velocity = + get_fluid_falling_adjusted_movement(gravity, moving_down, new_velocity, ctx.sprinting); } else { - move_relative(physics, direction, 0.02, acceleration); - move_colliding( - MoverType::Own, - physics.velocity, - world, - &mut position, - physics, - Some(entity), - physics_query, - collidable_entity_query, - ) - .expect("Entity should exist"); + move_relative(ctx.physics, ctx.direction, 0.02, acceleration); + move_colliding(ctx, ctx.physics.velocity).expect("Entity should exist"); - if physics.lava_fluid_height <= fluid_jump_threshold() { - physics.velocity.x *= 0.5; - physics.velocity.y *= 0.8; - physics.velocity.z *= 0.5; + if ctx.physics.lava_fluid_height <= fluid_jump_threshold() { + ctx.physics.velocity.x *= 0.5; + ctx.physics.velocity.y *= 0.8; + ctx.physics.velocity.z *= 0.5; let new_velocity = get_fluid_falling_adjusted_movement( gravity, moving_down, - physics.velocity, - sprinting, + ctx.physics.velocity, + ctx.sprinting, ); - physics.velocity = new_velocity; + ctx.physics.velocity = new_velocity; } else { - physics.velocity *= 0.5; + ctx.physics.velocity *= 0.5; } if gravity != 0.0 { - physics.velocity.y -= gravity / 4.0; + ctx.physics.velocity.y -= gravity / 4.0; } } - let velocity = physics.velocity; - if physics.horizontal_collision + let velocity = ctx.physics.velocity; + if ctx.physics.horizontal_collision && is_free( - world, - entity, - physics_query, - collidable_entity_query, - physics, - physics.bounding_box, - velocity.up(0.6).down(position.y).up(y), + ctx.world, + ctx.source_entity, + ctx.physics_query, + ctx.collidable_entity_query, + ctx.physics, + ctx.physics.bounding_box, + velocity.up(0.6).down(ctx.position.y).up(y), ) { - physics.velocity.y = 0.3; + ctx.physics.velocity.y = 0.3; } } @@ -333,7 +273,7 @@ fn is_free( ) && !contains_any_liquid(world, bounding_box) } -fn no_collision( +pub fn no_collision( world: &Instance, source_entity: Option, physics_query: &PhysicsQuery, @@ -343,9 +283,9 @@ fn no_collision( include_liquid_collisions: bool, ) -> bool { let collisions = if include_liquid_collisions { - crate::collision::world_collisions::get_block_and_liquid_collisions(world, aabb) + get_block_and_liquid_collisions(world, aabb) } else { - crate::collision::world_collisions::get_block_collisions(world, aabb) + get_block_collisions(world, aabb) }; for collision in collisions { diff --git a/azalea-protocol/src/packets/game/c_player_abilities.rs b/azalea-protocol/src/packets/game/c_player_abilities.rs index 3f4e1024d..8f7bbf20a 100644 --- a/azalea-protocol/src/packets/game/c_player_abilities.rs +++ b/azalea-protocol/src/packets/game/c_player_abilities.rs @@ -1,8 +1,8 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, BufReadError}; -use azalea_buf::{AzaleaRead, AzaleaWrite}; +use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; use azalea_core::bitset::FixedBitSet; +use azalea_entity::PlayerAbilities; use azalea_protocol_macros::ClientboundGamePacket; #[derive(Clone, Debug, AzBuf, ClientboundGamePacket)] @@ -51,3 +51,16 @@ impl AzaleaWrite for PlayerAbilitiesFlags { set.azalea_write(buf) } } + +impl From<&ClientboundPlayerAbilities> for PlayerAbilities { + fn from(packet: &ClientboundPlayerAbilities) -> Self { + Self { + invulnerable: packet.flags.invulnerable, + flying: packet.flags.flying, + can_fly: packet.flags.can_fly, + instant_break: packet.flags.instant_break, + flying_speed: packet.flying_speed, + walking_speed: packet.walking_speed, + } + } +} diff --git a/azalea/examples/testbot/commands/movement.rs b/azalea/examples/testbot/commands/movement.rs index 89be3d0c8..a33b79e2d 100644 --- a/azalea/examples/testbot/commands/movement.rs +++ b/azalea/examples/testbot/commands/movement.rs @@ -200,6 +200,22 @@ pub fn register(commands: &mut CommandDispatcher>) { })), ); + commands.register( + literal("sneak") + .executes(|ctx: &Ctx| { + let source = ctx.source.lock(); + source.bot.set_sneaking(!source.bot.sneaking()); + source.reply("ok"); + 1 + }) + .then(argument("enabled", bool()).executes(|ctx: &Ctx| { + let sneaking = get_bool(ctx, "enabled").unwrap(); + let source = ctx.source.lock(); + source.bot.set_sneaking(sneaking); + 1 + })), + ); + commands.register(literal("stop").executes(|ctx: &Ctx| { let source = ctx.source.lock(); source.bot.stop_pathfinding(); diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs index 8f198ce8c..4734aa3ed 100644 --- a/azalea/src/pathfinder/simulation.rs +++ b/azalea/src/pathfinder/simulation.rs @@ -112,7 +112,7 @@ fn create_simulation_player_complete_bundle( MineBundle::default(), BlockStatePredictionHandler::default(), azalea_client::local_player::PermissionLevel::default(), - azalea_client::local_player::PlayerAbilities::default(), + azalea_entity::PlayerAbilities::default(), ) } From 247576c8687cb4566976b24265ae8aab0e85e979 Mon Sep 17 00:00:00 2001 From: mat Date: Wed, 13 Aug 2025 07:34:00 -1300 Subject: [PATCH 2/7] fix horizontal_collision being inverted and cleanup --- azalea-physics/src/collision/mod.rs | 5 ++--- azalea-physics/src/travel.rs | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index 24db8359c..b4d20f3a4 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -173,8 +173,8 @@ pub fn move_colliding(ctx: &mut MoveCtx, mut movement: Vec3) -> Result<(), MoveE } } - let x_collision = math::equal(movement.x, collide_result.x); - let z_collision = math::equal(movement.z, collide_result.z); + let x_collision = !math::equal(movement.x, collide_result.x); + let z_collision = !math::equal(movement.z, collide_result.z); let horizontal_collision = x_collision || z_collision; physics.horizontal_collision = horizontal_collision; @@ -285,7 +285,6 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 if !is_backing_off { return movement; } - println!("backing off from edge"); let min_movement = 0.05; let min_movement_x = movement.x.signum() * min_movement; diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs index 6ffb76a37..dd8cef87c 100644 --- a/azalea-physics/src/travel.rs +++ b/azalea-physics/src/travel.rs @@ -139,8 +139,6 @@ fn travel_in_air(ctx: &mut MoveCtx) { z: movement.z * inertia as f64, }; } - - println!("set velocity to {:?}", ctx.physics.velocity); } fn travel_in_fluid(ctx: &mut MoveCtx) { From ac4daec2d6703e260659082cc9cec93c10564086 Mon Sep 17 00:00:00 2001 From: mat Date: Wed, 13 Aug 2025 17:08:20 -0330 Subject: [PATCH 3/7] clippy --- azalea-client/src/client.rs | 2 +- azalea-physics/src/collision/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 67b527476..82524b51d 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -14,7 +14,7 @@ use azalea_core::{ tick::GameTick, }; use azalea_entity::{ - EntityUpdateSet, EyeHeight, PlayerAbilities, Position, Sneaking, + EntityUpdateSet, EyeHeight, PlayerAbilities, Position, indexing::{EntityIdIndex, EntityUuidIndex}, metadata::Health, }; diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index b4d20f3a4..be36e0ed3 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -368,7 +368,7 @@ fn can_fall_at_least( Some(ctx.source_entity), ctx.physics_query, ctx.collidable_entity_query, - &mut ctx.physics, + ctx.physics, &aabb, false, ) From 76f57a77dace450a5097b9b50a7568303b7622be Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 14 Aug 2025 10:22:37 +0930 Subject: [PATCH 4/7] change dimensions and eye height based on pose --- CHANGELOG.md | 4 +- azalea-client/src/client.rs | 16 +- azalea-client/src/plugins/attack.rs | 10 +- azalea-client/src/plugins/interact/mod.rs | 8 +- azalea-client/src/plugins/interact/pick.rs | 9 +- azalea-client/src/plugins/mining.rs | 1 - azalea-client/src/plugins/movement.rs | 129 +++++- azalea-entity/src/data.rs | 12 +- azalea-entity/src/dimensions.rs | 242 ++++++---- azalea-entity/src/lib.rs | 68 +-- azalea-entity/src/metadata.rs | 458 +++++++++++-------- azalea-entity/src/plugin/mod.rs | 38 +- azalea-physics/src/collision/mod.rs | 22 +- azalea-physics/src/lib.rs | 21 +- azalea-physics/src/travel.rs | 10 +- azalea/examples/nearest_entity.rs | 11 +- azalea/examples/testbot/commands/debug.rs | 7 + azalea/examples/testbot/commands/movement.rs | 11 +- azalea/src/bot.rs | 14 +- azalea/src/pathfinder/simulation.rs | 4 +- codegen/lib/code/entity.py | 15 +- 21 files changed, 684 insertions(+), 426 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5850f181d..413e24005 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ is breaking anyways, semantic versioning is not followed. - Local clients now have a `TicksConnected` component. (@Kumpelinus) - There is now a `azalea_inventory::default_components::get_default_component` function to get the default value of a component for a registry item. - `ItemStack` now has a `get_component` function that supports default components. -- Add `Client::nearest_entity_by`. +- `Client::nearest_entity_by`. +- Clients are now able to crouch/sneak using the new `Crouching` component or `Client::set_crouching`. ### Changed @@ -26,6 +27,7 @@ is breaking anyways, semantic versioning is not followed. - `ItemStackData::components` was renamed to `component_patch`. - The fields in `LookDirection` have been replaced with getters. - Renamed `Client::entity_by` to `any_entity_by`, and `Client::entities_by` to `nearest_entities_by`. +- `EyeHeight` was moved into `EntityDimensions`, and `EntityDimensions` is now its own component. ### Fixed diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 82524b51d..50bbc6061 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -14,7 +14,8 @@ use azalea_core::{ tick::GameTick, }; use azalea_entity::{ - EntityUpdateSet, EyeHeight, PlayerAbilities, Position, + EntityUpdateSet, PlayerAbilities, Position, + dimensions::EntityDimensions, indexing::{EntityIdIndex, EntityUuidIndex}, metadata::Health, }; @@ -427,12 +428,21 @@ impl Client { ) } + /// Get the bounding box dimensions for our client, including our eye + /// height. + /// + /// This is a shortcut for + /// `self.component::()`. + pub fn dimensions(&self) -> EntityDimensions { + self.component::() + } + /// Get the position of this client's eyes. /// /// This is a shortcut for - /// `bot.position().up(bot.component::())`. + /// `bot.position().up(bot.dimensions().eye_height)`. pub fn eye_position(&self) -> Vec3 { - self.position().up((*self.component::()) as f64) + self.position().up(self.dimensions().eye_height as f64) } /// Get the health of this client. diff --git a/azalea-client/src/plugins/attack.rs b/azalea-client/src/plugins/attack.rs index ec4337e5b..7d730bb7a 100644 --- a/azalea-client/src/plugins/attack.rs +++ b/azalea-client/src/plugins/attack.rs @@ -1,8 +1,6 @@ use azalea_core::{game_type::GameMode, tick::GameTick}; use azalea_entity::{ - Attributes, Physics, - indexing::EntityIdIndex, - metadata::{ShiftKeyDown, Sprinting}, + Attributes, Crouching, Physics, indexing::EntityIdIndex, metadata::Sprinting, update_bounding_box, }; use azalea_physics::PhysicsSet; @@ -100,7 +98,7 @@ pub fn handle_attack_queued( &mut Sprinting, &AttackQueued, &LocalGameMode, - &ShiftKeyDown, + &Crouching, &EntityIdIndex, )>, ) { @@ -111,7 +109,7 @@ pub fn handle_attack_queued( mut sprinting, attack_queued, game_mode, - sneaking, + crouching, entity_id_index, ) in &mut query { @@ -128,7 +126,7 @@ pub fn handle_attack_queued( ServerboundInteract { entity_id: target_entity_id, action: s_interact::ActionType::Attack, - using_secondary_action: **sneaking, + using_secondary_action: **crouching, }, )); commands.trigger(SwingArmEvent { diff --git a/azalea-client/src/plugins/interact/mod.rs b/azalea-client/src/plugins/interact/mod.rs index 3aede1ea3..0275ca974 100644 --- a/azalea-client/src/plugins/interact/mod.rs +++ b/azalea-client/src/plugins/interact/mod.rs @@ -11,7 +11,7 @@ use azalea_core::{ tick::GameTick, }; use azalea_entity::{ - Attributes, LocalEntity, LookDirection, PlayerAbilities, Sneaking, + Attributes, Crouching, LocalEntity, LookDirection, PlayerAbilities, attributes::{ creative_block_interaction_range_modifier, creative_entity_interaction_range_modifier, }, @@ -250,7 +250,7 @@ pub fn handle_start_use_item_queued( &mut BlockStatePredictionHandler, &HitResultComponent, &LookDirection, - &Sneaking, + &Crouching, Option<&Mining>, )>, entity_id_query: Query<&MinecraftEntityId>, @@ -261,7 +261,7 @@ pub fn handle_start_use_item_queued( mut prediction_handler, hit_result, look_direction, - sneaking, + crouching, mining, ) in query { @@ -340,7 +340,7 @@ pub fn handle_start_use_item_queued( location: r.location, hand: InteractionHand::MainHand, }, - using_secondary_action: **sneaking, + using_secondary_action: **crouching, }, )); } diff --git a/azalea-client/src/plugins/interact/pick.rs b/azalea-client/src/plugins/interact/pick.rs index cebbf9055..a0a759102 100644 --- a/azalea-client/src/plugins/interact/pick.rs +++ b/azalea-client/src/plugins/interact/pick.rs @@ -5,7 +5,8 @@ use azalea_core::{ position::Vec3, }; use azalea_entity::{ - Attributes, Dead, EyeHeight, LocalEntity, LookDirection, Physics, Position, + Attributes, Dead, LocalEntity, LookDirection, Physics, Position, + dimensions::EntityDimensions, metadata::{ArmorStandMarker, Marker}, view_vector, }; @@ -31,7 +32,7 @@ pub fn update_hit_result_component( Entity, Option<&mut HitResultComponent>, &Position, - &EyeHeight, + &EntityDimensions, &LookDirection, &InstanceName, &Physics, @@ -47,7 +48,7 @@ pub fn update_hit_result_component( entity, hit_result_ref, position, - eye_height, + dimensions, look_direction, world_name, physics, @@ -57,7 +58,7 @@ pub fn update_hit_result_component( let block_pick_range = attributes.block_interaction_range.calculate(); let entity_pick_range = attributes.entity_interaction_range.calculate(); - let eye_position = position.up(eye_height.into()); + let eye_position = position.up(dimensions.eye_height.into()); let Some(world_lock) = instance_container.get(world_name) else { continue; diff --git a/azalea-client/src/plugins/mining.rs b/azalea-client/src/plugins/mining.rs index 43aae004c..0ad1840ca 100644 --- a/azalea-client/src/plugins/mining.rs +++ b/azalea-client/src/plugins/mining.rs @@ -55,7 +55,6 @@ impl Plugin for MiningPlugin { .in_set(MiningSet) .after(InventorySet) .after(MoveEventsSet) - .before(azalea_entity::update_bounding_box) .after(azalea_entity::update_fluid_on_eyes) .after(crate::interact::pick::update_hit_result_component) .after(crate::attack::handle_attack_event) diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index c6a36f40d..a844f0170 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -1,14 +1,19 @@ use std::{backtrace::Backtrace, io}; use azalea_core::{ + game_type::GameMode, position::{Vec2, Vec3}, tick::GameTick, }; use azalea_entity::{ - Attributes, HasClientLoaded, Jumping, LastSentPosition, LookDirection, Physics, Position, - Sneaking, metadata::Sprinting, + Attributes, Crouching, HasClientLoaded, Jumping, LastSentPosition, LookDirection, Physics, + Pose, Position, dimensions::calculate_dimensions, metadata::Sprinting, update_bounding_box, +}; +use azalea_physics::{ + PhysicsSet, ai_step, + collision::entity_collisions::{CollidableEntityQuery, PhysicsQuery}, + travel::no_collision, }; -use azalea_physics::{PhysicsSet, ai_step}; use azalea_protocol::{ common::movements::MoveFlags, packets::{ @@ -22,12 +27,17 @@ use azalea_protocol::{ }, }, }; -use azalea_world::{MinecraftEntityId, MoveEntityError}; +use azalea_registry::EntityKind; +use azalea_world::{Instance, MinecraftEntityId, MoveEntityError}; use bevy_app::{App, Plugin, Update}; use bevy_ecs::prelude::*; use thiserror::Error; -use crate::{client::Client, packet::game::SendPacketEvent}; +use crate::{ + client::Client, + local_player::{InstanceHolder, LocalGameMode}, + packet::game::SendPacketEvent, +}; #[derive(Error, Debug)] pub enum MovePlayerError { @@ -58,12 +68,13 @@ impl Plugin for MovementPlugin { Update, (handle_sprint, handle_walk, handle_knockback) .chain() - .in_set(MoveEventsSet), + .in_set(MoveEventsSet) + .after(update_bounding_box), ) .add_systems( GameTick, ( - (tick_controls, local_player_ai_step) + (tick_controls, local_player_ai_step, update_pose) .chain() .in_set(PhysicsSet) .before(ai_step) @@ -97,14 +108,17 @@ impl Client { *self.component::() } - pub fn set_sneaking(&self, sneaking: bool) { + pub fn set_crouching(&self, crouching: bool) { let mut ecs = self.ecs.lock(); - let mut jumping_mut = self.query::<&mut Sneaking>(&mut ecs); - **jumping_mut = sneaking; + let mut crouching_mut = self.query::<&mut Crouching>(&mut ecs); + **crouching_mut = crouching; } - pub fn sneaking(&self) -> bool { - *self.component::() + /// Whether the client is currently trying to sneak. + /// + /// You may want to check the [`Pose`] instead. + pub fn crouching(&self) -> bool { + *self.component::() } /// Sets the direction the client is looking. `y_rot` is yaw (looking to the @@ -268,7 +282,7 @@ pub fn send_player_input_packet( Entity, &PhysicsState, &Jumping, - &Sneaking, + &Crouching, Option<&LastSentInput>, )>, mut commands: Commands, @@ -364,7 +378,7 @@ pub fn local_player_ai_step( mut query: Query< ( &PhysicsState, - &Sneaking, + &Crouching, &mut Physics, &mut Sprinting, &mut Attributes, @@ -372,7 +386,7 @@ pub fn local_player_ai_step( With, >, ) { - for (physics_state, sneaking, mut physics, mut sprinting, mut attributes) in query.iter_mut() { + for (physics_state, crouching, mut physics, mut sprinting, mut attributes) in query.iter_mut() { // server ai step // TODO: replace those booleans when using items and passengers are properly @@ -381,7 +395,7 @@ pub fn local_player_ai_step( physics_state.move_vector, false, false, - **sneaking, + **crouching, &attributes, ); physics.x_acceleration = move_vector.x; @@ -641,3 +655,86 @@ impl From for WalkDirection { } } } + +pub fn update_pose( + mut query: Query<( + Entity, + &mut Pose, + &Physics, + &Crouching, + &LocalGameMode, + &InstanceHolder, + &Position, + )>, + physics_query: PhysicsQuery, + collidable_entity_query: CollidableEntityQuery, +) { + for (entity, mut pose, physics, crouching, game_mode, instance_holder, position) in + query.iter_mut() + { + let world = instance_holder.instance.read(); + let world = &*world; + let ctx = CanPlayerFitCtx { + world, + entity, + position: *position, + physics_query: &physics_query, + collidable_entity_query: &collidable_entity_query, + physics, + }; + + if !can_player_fit_within_blocks_and_entities_when(&ctx, Pose::Swimming) { + continue; + } + + // TODO: implement everything else from getDesiredPose: sleeping, swimming, + // fallFlying, spinAttack + let desired_pose = if **crouching { + Pose::Crouching + } else { + Pose::Standing + }; + + // TODO: passengers + let is_passenger = false; + + // canPlayerFitWithinBlocksAndEntitiesWhen + let new_pose = if game_mode.current == GameMode::Spectator + || is_passenger + || can_player_fit_within_blocks_and_entities_when(&ctx, desired_pose) + { + desired_pose + } else if can_player_fit_within_blocks_and_entities_when(&ctx, Pose::Crouching) { + Pose::Crouching + } else { + Pose::Swimming + }; + + // avoid triggering change detection + if new_pose != *pose { + *pose = new_pose; + } + } +} + +struct CanPlayerFitCtx<'world, 'state, 'a, 'b> { + world: &'a Instance, + entity: Entity, + position: Position, + physics_query: &'a PhysicsQuery<'world, 'state, 'b>, + collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, + physics: &'a Physics, +} +fn can_player_fit_within_blocks_and_entities_when(ctx: &CanPlayerFitCtx, pose: Pose) -> bool { + // return this.level().noCollision(this, + // this.getDimensions(var1).makeBoundingBox(this.position()).deflate(1.0E-7)); + no_collision( + ctx.world, + Some(ctx.entity), + ctx.physics_query, + ctx.collidable_entity_query, + ctx.physics, + &calculate_dimensions(EntityKind::Player, pose).make_bounding_box(*ctx.position), + false, + ) +} diff --git a/azalea-entity/src/data.rs b/azalea-entity/src/data.rs index 436c6571f..35e8b4c50 100644 --- a/azalea-entity/src/data.rs +++ b/azalea-entity/src/data.rs @@ -152,9 +152,19 @@ pub enum Pose { Sleeping, Swimming, SpinAttack, - Sneaking, + Crouching, LongJumping, Dying, + Croaking, + UsingTongue, + Sitting, + Roaring, + Sniffing, + Emerging, + Digging, + Sliding, + Shooting, + Inhaling, } #[derive(Debug, Clone, AzBuf)] diff --git a/azalea-entity/src/dimensions.rs b/azalea-entity/src/dimensions.rs index 68e9903d5..92c03e612 100644 --- a/azalea-entity/src/dimensions.rs +++ b/azalea-entity/src/dimensions.rs @@ -1,15 +1,43 @@ use azalea_core::{aabb::AABB, position::Vec3}; use azalea_registry::EntityKind; +use bevy_ecs::component::Component; -#[derive(Debug, Default, Clone)] +use crate::Pose; + +/// A component that contains the size of an entity and their eye height. +#[derive(Component, Debug, Default, Clone)] pub struct EntityDimensions { pub width: f32, pub height: f32, + /// The offset of the entity's eyes from their coordinates. + /// + /// This is used to calculate the camera position for players, when + /// spectating an entity, and when raycasting from the entity. + /// + /// The default eye height for a player is 1.62 blocks. + pub eye_height: f32, + /// Whether the entity isn't allowed to be scaled. + pub fixed: bool, } impl EntityDimensions { - pub fn new(width: f32, height: f32) -> Self { - Self { width, height } + pub const fn new(width: f32, height: f32) -> Self { + Self { + width, + height, + eye_height: default_eye_height(height), + fixed: false, + } + } + pub const fn fixed(self) -> Self { + Self { + fixed: true, + ..self + } + } + + pub const fn eye_height(self, eye_height: f32) -> Self { + Self { eye_height, ..self } } pub fn make_bounding_box(&self, pos: Vec3) -> AABB { @@ -22,55 +50,59 @@ impl EntityDimensions { } } +const fn default_eye_height(height: f32) -> f32 { + height * 0.85 +} + impl From for EntityDimensions { fn from(entity: EntityKind) -> Self { // this match statement is automatically generated by codegen/genentities.py, // don't edit it manually! match entity { - EntityKind::AcaciaBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::AcaciaChestBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::Allay => EntityDimensions::new(0.35, 0.6), + EntityKind::AcaciaBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::AcaciaChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::Allay => EntityDimensions::new(0.35, 0.6).eye_height(0.36), EntityKind::AreaEffectCloud => EntityDimensions::new(6.0, 0.5), - EntityKind::Armadillo => EntityDimensions::new(0.7, 0.65), - EntityKind::ArmorStand => EntityDimensions::new(0.5, 1.975), - EntityKind::Arrow => EntityDimensions::new(0.5, 0.5), - EntityKind::Axolotl => EntityDimensions::new(0.75, 0.42), - EntityKind::BambooChestRaft => EntityDimensions::new(1.375, 0.5625), - EntityKind::BambooRaft => EntityDimensions::new(1.375, 0.5625), - EntityKind::Bat => EntityDimensions::new(0.5, 0.9), - EntityKind::Bee => EntityDimensions::new(0.7, 0.6), - EntityKind::BirchBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::BirchChestBoat => EntityDimensions::new(1.375, 0.5625), + EntityKind::Armadillo => EntityDimensions::new(0.7, 0.65).eye_height(0.26), + EntityKind::ArmorStand => EntityDimensions::new(0.5, 1.975).eye_height(1.7775), + EntityKind::Arrow => EntityDimensions::new(0.5, 0.5).eye_height(0.13), + EntityKind::Axolotl => EntityDimensions::new(0.75, 0.42).eye_height(0.2751), + EntityKind::BambooChestRaft => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::BambooRaft => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::Bat => EntityDimensions::new(0.5, 0.9).eye_height(0.45), + EntityKind::Bee => EntityDimensions::new(0.7, 0.6).eye_height(0.3), + EntityKind::BirchBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::BirchChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), EntityKind::Blaze => EntityDimensions::new(0.6, 1.8), EntityKind::BlockDisplay => EntityDimensions::new(0.0, 0.0), - EntityKind::Bogged => EntityDimensions::new(0.6, 1.99), - EntityKind::Breeze => EntityDimensions::new(0.6, 1.77), - EntityKind::BreezeWindCharge => EntityDimensions::new(0.3125, 0.3125), - EntityKind::Camel => EntityDimensions::new(1.7, 2.375), - EntityKind::Cat => EntityDimensions::new(0.6, 0.7), - EntityKind::CaveSpider => EntityDimensions::new(0.7, 0.5), - EntityKind::CherryBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::CherryChestBoat => EntityDimensions::new(1.375, 0.5625), + EntityKind::Bogged => EntityDimensions::new(0.6, 1.99).eye_height(1.74), + EntityKind::Breeze => EntityDimensions::new(0.6, 1.77).eye_height(1.3452), + EntityKind::BreezeWindCharge => EntityDimensions::new(0.3125, 0.3125).eye_height(0.0), + EntityKind::Camel => EntityDimensions::new(1.7, 2.375).eye_height(2.275), + EntityKind::Cat => EntityDimensions::new(0.6, 0.7).eye_height(0.35), + EntityKind::CaveSpider => EntityDimensions::new(0.7, 0.5).eye_height(0.45), + EntityKind::CherryBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::CherryChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), EntityKind::ChestMinecart => EntityDimensions::new(0.98, 0.7), - EntityKind::Chicken => EntityDimensions::new(0.4, 0.7), - EntityKind::Cod => EntityDimensions::new(0.5, 0.3), + EntityKind::Chicken => EntityDimensions::new(0.4, 0.7).eye_height(0.644), + EntityKind::Cod => EntityDimensions::new(0.5, 0.3).eye_height(0.195), EntityKind::CommandBlockMinecart => EntityDimensions::new(0.98, 0.7), - EntityKind::Cow => EntityDimensions::new(0.9, 1.4), - EntityKind::Creaking => EntityDimensions::new(0.9, 2.7), + EntityKind::Cow => EntityDimensions::new(0.9, 1.4).eye_height(1.3), + EntityKind::Creaking => EntityDimensions::new(0.9, 2.7).eye_height(2.3), EntityKind::Creeper => EntityDimensions::new(0.6, 1.7), - EntityKind::DarkOakBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::DarkOakChestBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::Dolphin => EntityDimensions::new(0.9, 0.6), - EntityKind::Donkey => EntityDimensions::new(1.39648, 1.5), + EntityKind::DarkOakBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::DarkOakChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::Dolphin => EntityDimensions::new(0.9, 0.6).eye_height(0.3), + EntityKind::Donkey => EntityDimensions::new(1.39648, 1.5).eye_height(1.425), EntityKind::DragonFireball => EntityDimensions::new(1.0, 1.0), - EntityKind::Drowned => EntityDimensions::new(0.6, 1.95), + EntityKind::Drowned => EntityDimensions::new(0.6, 1.95).eye_height(1.74), EntityKind::Egg => EntityDimensions::new(0.25, 0.25), - EntityKind::ElderGuardian => EntityDimensions::new(1.9975, 1.9975), + EntityKind::ElderGuardian => EntityDimensions::new(1.9975, 1.9975).eye_height(0.99875), EntityKind::EndCrystal => EntityDimensions::new(2.0, 2.0), EntityKind::EnderDragon => EntityDimensions::new(16.0, 8.0), EntityKind::EnderPearl => EntityDimensions::new(0.25, 0.25), - EntityKind::Enderman => EntityDimensions::new(0.6, 2.9), - EntityKind::Endermite => EntityDimensions::new(0.4, 0.3), + EntityKind::Enderman => EntityDimensions::new(0.6, 2.9).eye_height(2.55), + EntityKind::Endermite => EntityDimensions::new(0.4, 0.3).eye_height(0.13), EntityKind::Evoker => EntityDimensions::new(0.6, 1.95), EntityKind::EvokerFangs => EntityDimensions::new(0.5, 0.8), EntityKind::ExperienceBottle => EntityDimensions::new(0.25, 0.25), @@ -80,104 +112,120 @@ impl From for EntityDimensions { EntityKind::Fireball => EntityDimensions::new(1.0, 1.0), EntityKind::FireworkRocket => EntityDimensions::new(0.25, 0.25), EntityKind::FishingBobber => EntityDimensions::new(0.25, 0.25), - EntityKind::Fox => EntityDimensions::new(0.6, 0.7), + EntityKind::Fox => EntityDimensions::new(0.6, 0.7).eye_height(0.4), EntityKind::Frog => EntityDimensions::new(0.5, 0.5), EntityKind::FurnaceMinecart => EntityDimensions::new(0.98, 0.7), - EntityKind::Ghast => EntityDimensions::new(4.0, 4.0), - EntityKind::Giant => EntityDimensions::new(3.6, 12.0), - EntityKind::GlowItemFrame => EntityDimensions::new(0.5, 0.5), - EntityKind::GlowSquid => EntityDimensions::new(0.8, 0.8), + EntityKind::Ghast => EntityDimensions::new(4.0, 4.0).eye_height(2.6), + EntityKind::Giant => EntityDimensions::new(3.6, 12.0).eye_height(10.44), + EntityKind::GlowItemFrame => EntityDimensions::new(0.5, 0.5).eye_height(0.0), + EntityKind::GlowSquid => EntityDimensions::new(0.8, 0.8).eye_height(0.4), EntityKind::Goat => EntityDimensions::new(0.9, 1.3), - EntityKind::Guardian => EntityDimensions::new(0.85, 0.85), - EntityKind::HappyGhast => EntityDimensions::new(4.0, 4.0), + EntityKind::Guardian => EntityDimensions::new(0.85, 0.85).eye_height(0.425), + EntityKind::HappyGhast => EntityDimensions::new(4.0, 4.0).eye_height(2.6), EntityKind::Hoglin => EntityDimensions::new(1.39648, 1.4), EntityKind::HopperMinecart => EntityDimensions::new(0.98, 0.7), - EntityKind::Horse => EntityDimensions::new(1.39648, 1.6), - EntityKind::Husk => EntityDimensions::new(0.6, 1.95), + EntityKind::Horse => EntityDimensions::new(1.39648, 1.6).eye_height(1.52), + EntityKind::Husk => EntityDimensions::new(0.6, 1.95).eye_height(1.74), EntityKind::Illusioner => EntityDimensions::new(0.6, 1.95), EntityKind::Interaction => EntityDimensions::new(0.0, 0.0), EntityKind::IronGolem => EntityDimensions::new(1.4, 2.7), - EntityKind::Item => EntityDimensions::new(0.25, 0.25), + EntityKind::Item => EntityDimensions::new(0.25, 0.25).eye_height(0.2125), EntityKind::ItemDisplay => EntityDimensions::new(0.0, 0.0), - EntityKind::ItemFrame => EntityDimensions::new(0.5, 0.5), - EntityKind::JungleBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::JungleChestBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::LeashKnot => EntityDimensions::new(0.375, 0.5), + EntityKind::ItemFrame => EntityDimensions::new(0.5, 0.5).eye_height(0.0), + EntityKind::JungleBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::JungleChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::LeashKnot => EntityDimensions::new(0.375, 0.5).eye_height(0.0625), EntityKind::LightningBolt => EntityDimensions::new(0.0, 0.0), EntityKind::LingeringPotion => EntityDimensions::new(0.25, 0.25), - EntityKind::Llama => EntityDimensions::new(0.9, 1.87), + EntityKind::Llama => EntityDimensions::new(0.9, 1.87).eye_height(1.7765), EntityKind::LlamaSpit => EntityDimensions::new(0.25, 0.25), - EntityKind::MagmaCube => EntityDimensions::new(0.52, 0.52), - EntityKind::MangroveBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::MangroveChestBoat => EntityDimensions::new(1.375, 0.5625), + EntityKind::MagmaCube => EntityDimensions::new(0.52, 0.52).eye_height(0.325), + EntityKind::MangroveBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::MangroveChestBoat => { + EntityDimensions::new(1.375, 0.5625).eye_height(0.5625) + } EntityKind::Marker => EntityDimensions::new(0.0, 0.0), EntityKind::Minecart => EntityDimensions::new(0.98, 0.7), - EntityKind::Mooshroom => EntityDimensions::new(0.9, 1.4), - EntityKind::Mule => EntityDimensions::new(1.39648, 1.6), - EntityKind::OakBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::OakChestBoat => EntityDimensions::new(1.375, 0.5625), + EntityKind::Mooshroom => EntityDimensions::new(0.9, 1.4).eye_height(1.3), + EntityKind::Mule => EntityDimensions::new(1.39648, 1.6).eye_height(1.52), + EntityKind::OakBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::OakChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), EntityKind::Ocelot => EntityDimensions::new(0.6, 0.7), EntityKind::OminousItemSpawner => EntityDimensions::new(0.25, 0.25), EntityKind::Painting => EntityDimensions::new(0.5, 0.5), - EntityKind::PaleOakBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::PaleOakChestBoat => EntityDimensions::new(1.375, 0.5625), + EntityKind::PaleOakBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::PaleOakChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), EntityKind::Panda => EntityDimensions::new(1.3, 1.25), - EntityKind::Parrot => EntityDimensions::new(0.5, 0.9), - EntityKind::Phantom => EntityDimensions::new(0.9, 0.5), + EntityKind::Parrot => EntityDimensions::new(0.5, 0.9).eye_height(0.54), + EntityKind::Phantom => EntityDimensions::new(0.9, 0.5).eye_height(0.175), EntityKind::Pig => EntityDimensions::new(0.9, 0.9), - EntityKind::Piglin => EntityDimensions::new(0.6, 1.95), - EntityKind::PiglinBrute => EntityDimensions::new(0.6, 1.95), + EntityKind::Piglin => EntityDimensions::new(0.6, 1.95).eye_height(1.79), + EntityKind::PiglinBrute => EntityDimensions::new(0.6, 1.95).eye_height(1.79), EntityKind::Pillager => EntityDimensions::new(0.6, 1.95), - EntityKind::Player => EntityDimensions::new(0.6, 1.8), + EntityKind::Player => EntityDimensions::new(0.6, 1.8).eye_height(1.62), EntityKind::PolarBear => EntityDimensions::new(1.4, 1.4), - EntityKind::Pufferfish => EntityDimensions::new(0.7, 0.7), + EntityKind::Pufferfish => EntityDimensions::new(0.7, 0.7).eye_height(0.455), EntityKind::Rabbit => EntityDimensions::new(0.4, 0.5), EntityKind::Ravager => EntityDimensions::new(1.95, 2.2), - EntityKind::Salmon => EntityDimensions::new(0.7, 0.4), - EntityKind::Sheep => EntityDimensions::new(0.9, 1.3), - EntityKind::Shulker => EntityDimensions::new(1.0, 1.0), + EntityKind::Salmon => EntityDimensions::new(0.7, 0.4).eye_height(0.26), + EntityKind::Sheep => EntityDimensions::new(0.9, 1.3).eye_height(1.235), + EntityKind::Shulker => EntityDimensions::new(1.0, 1.0).eye_height(0.5), EntityKind::ShulkerBullet => EntityDimensions::new(0.3125, 0.3125), - EntityKind::Silverfish => EntityDimensions::new(0.4, 0.3), - EntityKind::Skeleton => EntityDimensions::new(0.6, 1.99), - EntityKind::SkeletonHorse => EntityDimensions::new(1.39648, 1.6), - EntityKind::Slime => EntityDimensions::new(0.52, 0.52), + EntityKind::Silverfish => EntityDimensions::new(0.4, 0.3).eye_height(0.13), + EntityKind::Skeleton => EntityDimensions::new(0.6, 1.99).eye_height(1.74), + EntityKind::SkeletonHorse => EntityDimensions::new(1.39648, 1.6).eye_height(1.52), + EntityKind::Slime => EntityDimensions::new(0.52, 0.52).eye_height(0.325), EntityKind::SmallFireball => EntityDimensions::new(0.3125, 0.3125), - EntityKind::Sniffer => EntityDimensions::new(1.9, 1.75), - EntityKind::SnowGolem => EntityDimensions::new(0.7, 1.9), + EntityKind::Sniffer => EntityDimensions::new(1.9, 1.75).eye_height(1.05), + EntityKind::SnowGolem => EntityDimensions::new(0.7, 1.9).eye_height(1.7), EntityKind::Snowball => EntityDimensions::new(0.25, 0.25), EntityKind::SpawnerMinecart => EntityDimensions::new(0.98, 0.7), - EntityKind::SpectralArrow => EntityDimensions::new(0.5, 0.5), - EntityKind::Spider => EntityDimensions::new(1.4, 0.9), + EntityKind::SpectralArrow => EntityDimensions::new(0.5, 0.5).eye_height(0.13), + EntityKind::Spider => EntityDimensions::new(1.4, 0.9).eye_height(0.65), EntityKind::SplashPotion => EntityDimensions::new(0.25, 0.25), - EntityKind::SpruceBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::SpruceChestBoat => EntityDimensions::new(1.375, 0.5625), - EntityKind::Squid => EntityDimensions::new(0.8, 0.8), - EntityKind::Stray => EntityDimensions::new(0.6, 1.99), + EntityKind::SpruceBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::SpruceChestBoat => EntityDimensions::new(1.375, 0.5625).eye_height(0.5625), + EntityKind::Squid => EntityDimensions::new(0.8, 0.8).eye_height(0.4), + EntityKind::Stray => EntityDimensions::new(0.6, 1.99).eye_height(1.74), EntityKind::Strider => EntityDimensions::new(0.9, 1.7), - EntityKind::Tadpole => EntityDimensions::new(0.4, 0.3), + EntityKind::Tadpole => EntityDimensions::new(0.4, 0.3).eye_height(0.195), EntityKind::TextDisplay => EntityDimensions::new(0.0, 0.0), - EntityKind::Tnt => EntityDimensions::new(0.98, 0.98), + EntityKind::Tnt => EntityDimensions::new(0.98, 0.98).eye_height(0.15), EntityKind::TntMinecart => EntityDimensions::new(0.98, 0.7), - EntityKind::TraderLlama => EntityDimensions::new(0.9, 1.87), - EntityKind::Trident => EntityDimensions::new(0.5, 0.5), - EntityKind::TropicalFish => EntityDimensions::new(0.5, 0.4), + EntityKind::TraderLlama => EntityDimensions::new(0.9, 1.87).eye_height(1.7765), + EntityKind::Trident => EntityDimensions::new(0.5, 0.5).eye_height(0.13), + EntityKind::TropicalFish => EntityDimensions::new(0.5, 0.4).eye_height(0.26), EntityKind::Turtle => EntityDimensions::new(1.2, 0.4), - EntityKind::Vex => EntityDimensions::new(0.4, 0.8), - EntityKind::Villager => EntityDimensions::new(0.6, 1.95), + EntityKind::Vex => EntityDimensions::new(0.4, 0.8).eye_height(0.51875), + EntityKind::Villager => EntityDimensions::new(0.6, 1.95).eye_height(1.62), EntityKind::Vindicator => EntityDimensions::new(0.6, 1.95), - EntityKind::WanderingTrader => EntityDimensions::new(0.6, 1.95), + EntityKind::WanderingTrader => EntityDimensions::new(0.6, 1.95).eye_height(1.62), EntityKind::Warden => EntityDimensions::new(0.9, 2.9), - EntityKind::WindCharge => EntityDimensions::new(0.3125, 0.3125), - EntityKind::Witch => EntityDimensions::new(0.6, 1.95), + EntityKind::WindCharge => EntityDimensions::new(0.3125, 0.3125).eye_height(0.0), + EntityKind::Witch => EntityDimensions::new(0.6, 1.95).eye_height(1.62), EntityKind::Wither => EntityDimensions::new(0.9, 3.5), - EntityKind::WitherSkeleton => EntityDimensions::new(0.7, 2.4), + EntityKind::WitherSkeleton => EntityDimensions::new(0.7, 2.4).eye_height(2.1), EntityKind::WitherSkull => EntityDimensions::new(0.3125, 0.3125), - EntityKind::Wolf => EntityDimensions::new(0.6, 0.85), + EntityKind::Wolf => EntityDimensions::new(0.6, 0.85).eye_height(0.68), EntityKind::Zoglin => EntityDimensions::new(1.39648, 1.4), - EntityKind::Zombie => EntityDimensions::new(0.6, 1.95), - EntityKind::ZombieHorse => EntityDimensions::new(1.39648, 1.6), - EntityKind::ZombieVillager => EntityDimensions::new(0.6, 1.95), - EntityKind::ZombifiedPiglin => EntityDimensions::new(0.6, 1.95), + EntityKind::Zombie => EntityDimensions::new(0.6, 1.95).eye_height(1.74), + EntityKind::ZombieHorse => EntityDimensions::new(1.39648, 1.6).eye_height(1.52), + EntityKind::ZombieVillager => EntityDimensions::new(0.6, 1.95).eye_height(1.74), + EntityKind::ZombifiedPiglin => EntityDimensions::new(0.6, 1.95).eye_height(1.79), } } } + +/// Calculate the dimensions that an entity with the given kind and pose would +/// have.i +pub fn calculate_dimensions(kind: EntityKind, pose: Pose) -> EntityDimensions { + match (kind, pose) { + (_, Pose::Sleeping) => EntityDimensions::new(0.2, 0.2).fixed().eye_height(0.2), + (EntityKind::Player, Pose::FallFlying) => EntityDimensions::new(0.6, 0.6).eye_height(0.4), + (EntityKind::Player, Pose::Swimming) => EntityDimensions::new(0.6, 0.6).eye_height(0.4), + (EntityKind::Player, Pose::SpinAttack) => EntityDimensions::new(0.6, 0.6).eye_height(0.4), + (EntityKind::Player, Pose::Crouching) => EntityDimensions::new(0.6, 1.5).eye_height(1.27), + (EntityKind::Player, Pose::Dying) => EntityDimensions::new(0.2, 1.2).eye_height(1.62), + _ => EntityDimensions::from(kind), + } +} diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 3a75b4862..9f292b9c3 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -2,7 +2,7 @@ pub mod attributes; mod data; -mod dimensions; +pub mod dimensions; mod effects; mod enchantments; pub mod metadata; @@ -31,12 +31,12 @@ use azalea_world::{ChunkStorage, InstanceName}; use bevy_ecs::{bundle::Bundle, component::Component}; pub use data::*; use derive_more::{Deref, DerefMut}; -pub use dimensions::EntityDimensions; use plugin::indexing::EntityChunkPos; use uuid::Uuid; use vec_delta_codec::VecDeltaCodec; use self::attributes::AttributeInstance; +use crate::dimensions::EntityDimensions; pub use crate::plugin::*; pub fn move_relative( @@ -353,8 +353,6 @@ pub struct Physics { /// and sets to 0 if we're not trying to jump. pub no_jump_delay: u32, - /// The width and height of the entity. - pub dimensions: EntityDimensions, /// The bounding box of the entity. This is more than just width and height, /// unlike dimensions. pub bounding_box: AABB, @@ -375,7 +373,7 @@ pub struct Physics { } impl Physics { - pub fn new(dimensions: EntityDimensions, pos: Vec3) -> Self { + pub fn new(dimensions: &EntityDimensions, pos: Vec3) -> Self { Self { velocity: Vec3::ZERO, vec_delta_codec: VecDeltaCodec::new(pos), @@ -392,7 +390,6 @@ impl Physics { no_jump_delay: 0, bounding_box: dimensions.make_bounding_box(pos), - dimensions, has_impulse: false, @@ -454,41 +451,6 @@ impl Physics { #[derive(Component, Copy, Clone, Default)] pub struct Dead; -/// A component that contains the offset of the entity's eyes from the entity -/// coordinates. -/// -/// This is used to calculate the camera position for players, when spectating -/// an entity, and when raycasting from the entity. -/// -/// The default eye height for a player is 1.62 blocks. -#[derive(Component, Clone, Copy, Debug, PartialEq, Deref, DerefMut)] -pub struct EyeHeight(f32); -impl EyeHeight { - pub fn new(height: f32) -> Self { - Self(height) - } -} -impl From for f32 { - fn from(value: EyeHeight) -> Self { - value.0 - } -} -impl From for f64 { - fn from(value: EyeHeight) -> Self { - value.0 as f64 - } -} -impl From<&EyeHeight> for f32 { - fn from(value: &EyeHeight) -> Self { - value.0 - } -} -impl From<&EyeHeight> for f64 { - fn from(value: &EyeHeight) -> Self { - value.0 as f64 - } -} - /// A component NewType for [`azalea_registry::EntityKind`]. /// /// Most of the time, you should be using `azalea_registry::EntityKind` @@ -510,10 +472,10 @@ pub struct EntityBundle { pub physics: Physics, pub direction: LookDirection, - pub eye_height: EyeHeight, + pub dimensions: EntityDimensions, pub attributes: Attributes, pub jumping: Jumping, - pub sneaking: Sneaking, + pub crouching: Crouching, pub fluid_on_eyes: FluidOnEyes, pub on_climbable: OnClimbable, } @@ -526,12 +488,6 @@ impl EntityBundle { world_name: ResourceLocation, ) -> Self { let dimensions = EntityDimensions::from(kind); - let eye_height = match kind { - // TODO: codegen hardcoded eye heights, search withEyeHeight with mojmap - // also, eye height should change depending on pose (like sneaking, swimming, etc) - azalea_registry::EntityKind::Player => 1.62, - _ => dimensions.height * 0.85, - }; Self { kind: EntityKindComponent(kind), @@ -540,14 +496,14 @@ impl EntityBundle { position: Position(pos), chunk_pos: EntityChunkPos(ChunkPos::from(&pos)), last_sent_position: LastSentPosition(pos), - physics: Physics::new(dimensions, pos), - eye_height: EyeHeight(eye_height), + physics: Physics::new(&dimensions, pos), + dimensions, direction: LookDirection::default(), attributes: default_attributes(EntityKind::Player), jumping: Jumping(false), - sneaking: Sneaking(false), + crouching: Crouching(false), fluid_on_eyes: FluidOnEyes(FluidKind::Empty), on_climbable: OnClimbable(false), } @@ -589,12 +545,12 @@ impl FluidOnEyes { #[derive(Component, Clone, Copy, Debug, PartialEq, Deref, DerefMut)] pub struct OnClimbable(bool); -/// A component that indicates whether the entity is currently trying to sneak. +/// A component that indicates whether the player is currently trying to sneak. /// -/// This is distinct from [`metadata::ShiftKeyDown`], which is a metadata value -/// controlled by the server. +/// This is distinct from [`metadata::AbstractEntityShiftKeyDown`], which is a +/// metadata value that is controlled by the server. #[derive(Component, Clone, Copy, Deref, DerefMut, Default)] -pub struct Sneaking(bool); +pub struct Crouching(bool); /// A component that contains the abilities the player has, like flying /// or instantly breaking blocks. This is only present on local players. diff --git a/azalea-entity/src/metadata.rs b/azalea-entity/src/metadata.rs index 422eabd85..6ccbad1a0 100644 --- a/azalea-entity/src/metadata.rs +++ b/azalea-entity/src/metadata.rs @@ -35,7 +35,7 @@ impl From for UpdateMetadataError { #[derive(Component, Deref, DerefMut, Clone, Copy)] pub struct OnFire(pub bool); #[derive(Component, Deref, DerefMut, Clone, Copy)] -pub struct ShiftKeyDown(pub bool); +pub struct AbstractEntityShiftKeyDown(pub bool); #[derive(Component, Deref, DerefMut, Clone, Copy)] pub struct Sprinting(pub bool); #[derive(Component, Deref, DerefMut, Clone, Copy)] @@ -101,7 +101,7 @@ impl Default for AcaciaBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -158,7 +158,7 @@ impl Default for AcaciaChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -251,7 +251,7 @@ impl Default for AllayMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -328,7 +328,7 @@ impl Default for AreaEffectCloudMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -394,7 +394,9 @@ impl Default for ArmadilloMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -514,7 +516,7 @@ impl Default for ArmorStandMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -594,7 +596,7 @@ impl Default for ArrowMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -673,7 +675,9 @@ impl Default for AxolotlMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -742,7 +746,7 @@ impl Default for BambooChestRaftMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -799,7 +803,7 @@ impl Default for BambooRaftMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -863,7 +867,7 @@ impl Default for BatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -953,7 +957,9 @@ impl Default for BeeMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1023,7 +1029,7 @@ impl Default for BirchBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1080,7 +1086,7 @@ impl Default for BirchChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1148,7 +1154,7 @@ impl Default for BlazeMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1247,7 +1253,7 @@ impl Default for BlockDisplayMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1342,7 +1348,7 @@ impl Default for BoggedMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1411,7 +1417,7 @@ impl Default for BreezeMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1471,7 +1477,7 @@ impl Default for BreezeWindChargeMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1548,7 +1554,9 @@ impl Default for CamelMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1659,7 +1667,9 @@ impl Default for CatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1741,7 +1751,9 @@ impl Default for CaveSpiderMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1807,7 +1819,7 @@ impl Default for CherryBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1864,7 +1876,7 @@ impl Default for CherryChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1925,7 +1937,7 @@ impl Default for ChestMinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -1993,7 +2005,9 @@ impl Default for ChickenMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2066,7 +2080,7 @@ impl Default for CodMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2143,7 +2157,7 @@ impl Default for CommandBlockMinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2213,7 +2227,9 @@ impl Default for CowMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2308,7 +2324,7 @@ impl Default for CreakingMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2398,7 +2414,7 @@ impl Default for CreeperMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2465,7 +2481,7 @@ impl Default for DarkOakBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2522,7 +2538,7 @@ impl Default for DarkOakChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2595,7 +2611,7 @@ impl Default for DolphinMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2674,7 +2690,8 @@ impl Default for DonkeyMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: + AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2745,7 +2762,7 @@ impl Default for DragonFireballMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2806,7 +2823,9 @@ impl Default for DrownedMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2874,7 +2893,7 @@ impl Default for EggMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -2937,7 +2956,9 @@ impl Default for ElderGuardianMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3012,7 +3033,7 @@ impl Default for EndCrystalMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3069,7 +3090,7 @@ impl Default for EnderDragonMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3130,7 +3151,7 @@ impl Default for EnderPearlMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3205,7 +3226,7 @@ impl Default for EndermanMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3276,7 +3297,7 @@ impl Default for EndermiteMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3352,7 +3373,9 @@ impl Default for EvokerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3416,7 +3439,7 @@ impl Default for EvokerFangsMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3463,7 +3486,7 @@ impl Default for ExperienceBottleMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3518,7 +3541,7 @@ impl Default for ExperienceOrbMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3570,7 +3593,7 @@ impl Default for EyeOfEnderMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3622,7 +3645,7 @@ impl Default for FallingBlockMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3674,7 +3697,7 @@ impl Default for FireballMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3738,7 +3761,7 @@ impl Default for FireworkRocketMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3798,7 +3821,7 @@ impl Default for FishingBobberMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3831,7 +3854,7 @@ pub struct Sleeping(pub bool); #[derive(Component, Deref, DerefMut, Clone, Copy)] pub struct Pouncing(pub bool); #[derive(Component, Deref, DerefMut, Clone, Copy)] -pub struct Crouching(pub bool); +pub struct FoxCrouching(pub bool); #[derive(Component, Deref, DerefMut, Clone, Copy)] pub struct FoxInterested(pub bool); #[derive(Component, Deref, DerefMut, Clone)] @@ -3857,7 +3880,7 @@ impl Fox { entity.insert(Defending(bitfield & 0x80 != 0)); entity.insert(Sleeping(bitfield & 0x20 != 0)); entity.insert(Pouncing(bitfield & 0x10 != 0)); - entity.insert(Crouching(bitfield & 0x4 != 0)); + entity.insert(FoxCrouching(bitfield & 0x4 != 0)); entity.insert(FoxInterested(bitfield & 0x8 != 0)); } 19 => { @@ -3882,7 +3905,7 @@ pub struct FoxMetadataBundle { defending: Defending, sleeping: Sleeping, pouncing: Pouncing, - crouching: Crouching, + fox_crouching: FoxCrouching, fox_interested: FoxInterested, trusted_id_0: TrustedId0, trusted_id_1: TrustedId1, @@ -3904,7 +3927,9 @@ impl Default for FoxMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -3941,7 +3966,7 @@ impl Default for FoxMetadataBundle { defending: Defending(false), sleeping: Sleeping(false), pouncing: Pouncing(false), - crouching: Crouching(false), + fox_crouching: FoxCrouching(false), fox_interested: FoxInterested(false), trusted_id_0: TrustedId0(None), trusted_id_1: TrustedId1(None), @@ -3998,7 +4023,9 @@ impl Default for FrogMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4072,7 +4099,7 @@ impl Default for FurnaceMinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4135,7 +4162,7 @@ impl Default for GhastMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4202,7 +4229,7 @@ impl Default for GiantMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4270,7 +4297,7 @@ impl Default for GlowItemFrameMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4335,7 +4362,9 @@ impl Default for GlowSquidMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4426,7 +4455,9 @@ impl Default for GoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4507,7 +4538,7 @@ impl Default for GuardianMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4591,7 +4622,9 @@ impl Default for HappyGhastMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4671,7 +4704,9 @@ impl Default for HoglinMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4738,7 +4773,7 @@ impl Default for HopperMinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4808,7 +4843,9 @@ impl Default for HorseMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4886,7 +4923,9 @@ impl Default for HuskMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -4962,7 +5001,9 @@ impl Default for IllusionerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5044,7 +5085,7 @@ impl Default for InteractionMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5105,7 +5146,7 @@ impl Default for IronGolemMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5171,7 +5212,7 @@ impl Default for ItemMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5231,7 +5272,7 @@ impl Default for ItemDisplayMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5325,7 +5366,7 @@ impl Default for ItemFrameMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5377,7 +5418,7 @@ impl Default for JungleBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5434,7 +5475,7 @@ impl Default for JungleChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5487,7 +5528,7 @@ impl Default for LeashKnotMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5532,7 +5573,7 @@ impl Default for LightningBoltMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5579,7 +5620,7 @@ impl Default for LingeringPotionMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5654,7 +5695,8 @@ impl Default for LlamaMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: + AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5727,7 +5769,7 @@ impl Default for LlamaSpitMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5780,7 +5822,7 @@ impl Default for MagmaCubeMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5844,7 +5886,7 @@ impl Default for MangroveBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5901,7 +5943,7 @@ impl Default for MangroveChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -5954,7 +5996,7 @@ impl Default for MarkerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6003,7 +6045,7 @@ impl Default for MinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6071,7 +6113,9 @@ impl Default for MooshroomMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6148,7 +6192,8 @@ impl Default for MuleMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: + AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6223,7 +6268,7 @@ impl Default for OakBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6280,7 +6325,7 @@ impl Default for OakChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6349,7 +6394,9 @@ impl Default for OcelotMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6418,7 +6465,7 @@ impl Default for OminousItemSpawnerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6476,7 +6523,7 @@ impl Default for PaintingMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6527,7 +6574,7 @@ impl Default for PaleOakBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6584,7 +6631,7 @@ impl Default for PaleOakChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6696,7 +6743,9 @@ impl Default for PandaMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6785,7 +6834,9 @@ impl Default for ParrotMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6862,7 +6913,7 @@ impl Default for PhantomMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -6943,7 +6994,9 @@ impl Default for PigMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7037,7 +7090,9 @@ impl Default for PiglinMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7112,7 +7167,9 @@ impl Default for PiglinBruteMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7190,7 +7247,9 @@ impl Default for PillagerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7291,7 +7350,7 @@ impl Default for PlayerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7367,7 +7426,9 @@ impl Default for PolarBearMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7448,7 +7509,7 @@ impl Default for PufferfishMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7525,7 +7586,9 @@ impl Default for RabbitMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7598,7 +7661,9 @@ impl Default for RavagerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7674,7 +7739,7 @@ impl Default for SalmonMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7753,7 +7818,9 @@ impl Default for SheepMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7840,7 +7907,7 @@ impl Default for ShulkerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7902,7 +7969,7 @@ impl Default for ShulkerBulletMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -7955,7 +8022,7 @@ impl Default for SilverfishMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8029,7 +8096,7 @@ impl Default for SkeletonMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8102,7 +8169,9 @@ impl Default for SkeletonHorseMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8177,7 +8246,7 @@ impl Default for SlimeMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8242,7 +8311,7 @@ impl Default for SmallFireballMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8310,7 +8379,9 @@ impl Default for SnifferMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8387,7 +8458,7 @@ impl Default for SnowGolemMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8449,7 +8520,7 @@ impl Default for SnowballMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8502,7 +8573,7 @@ impl Default for SpawnerMinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8556,7 +8627,7 @@ impl Default for SpectralArrowMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8619,7 +8690,7 @@ impl Default for SpiderMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8682,7 +8753,7 @@ impl Default for SplashPotionMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8735,7 +8806,7 @@ impl Default for SpruceBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8792,7 +8863,7 @@ impl Default for SpruceChestBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8853,7 +8924,7 @@ impl Default for SquidMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -8922,7 +8993,7 @@ impl Default for StrayMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9004,7 +9075,9 @@ impl Default for StriderMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9080,7 +9153,7 @@ impl Default for TadpoleMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9172,7 +9245,7 @@ impl Default for TextDisplayMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9269,7 +9342,7 @@ impl Default for TntMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9320,7 +9393,7 @@ impl Default for TntMinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9388,7 +9461,8 @@ impl Default for TraderLlamaMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: + AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9478,7 +9552,7 @@ impl Default for TridentMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9544,7 +9618,7 @@ impl Default for TropicalFishMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9628,7 +9702,9 @@ impl Default for TurtleMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9706,7 +9782,7 @@ impl Default for VexMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9785,7 +9861,9 @@ impl Default for VillagerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9863,7 +9941,9 @@ impl Default for VindicatorMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -9935,7 +10015,9 @@ impl Default for WanderingTraderMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10012,7 +10094,7 @@ impl Default for WardenMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10073,7 +10155,7 @@ impl Default for WindChargeMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10134,7 +10216,9 @@ impl Default for WitchMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10229,7 +10313,7 @@ impl Default for WitherMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10301,7 +10385,7 @@ impl Default for WitherSkeletonMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10367,7 +10451,7 @@ impl Default for WitherSkullMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10455,7 +10539,9 @@ impl Default for WolfMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10540,7 +10626,7 @@ impl Default for ZoglinMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10621,7 +10707,7 @@ impl Default for ZombieMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10696,7 +10782,9 @@ impl Default for ZombieHorseMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10785,7 +10873,9 @@ impl Default for ZombieVillagerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10865,7 +10955,9 @@ impl Default for ZombifiedPiglinMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -10939,7 +11031,7 @@ impl Default for AbstractAgeableMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11007,7 +11099,7 @@ impl Default for AbstractAnimalMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11083,7 +11175,7 @@ impl Default for AbstractArrowMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11146,7 +11238,7 @@ impl Default for AbstractBoatMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11214,7 +11306,9 @@ impl Default for AbstractChestedHorseMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11286,7 +11380,7 @@ impl Default for AbstractCreatureMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11406,7 +11500,7 @@ impl Default for AbstractDisplayMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11469,7 +11563,7 @@ impl AbstractEntity { 0 => { let bitfield = d.value.into_byte()?; entity.insert(OnFire(bitfield & 0x1 != 0)); - entity.insert(ShiftKeyDown(bitfield & 0x2 != 0)); + entity.insert(AbstractEntityShiftKeyDown(bitfield & 0x2 != 0)); entity.insert(Sprinting(bitfield & 0x8 != 0)); entity.insert(Swimming(bitfield & 0x10 != 0)); entity.insert(CurrentlyGlowing(bitfield & 0x40 != 0)); @@ -11507,7 +11601,7 @@ impl AbstractEntity { pub struct AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire, - shift_key_down: ShiftKeyDown, + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown, sprinting: Sprinting, swimming: Swimming, currently_glowing: CurrentlyGlowing, @@ -11526,7 +11620,7 @@ impl Default for AbstractEntityMetadataBundle { Self { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11580,7 +11674,7 @@ impl Default for AbstractFishMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11661,7 +11755,9 @@ impl Default for AbstractHorseMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11738,7 +11834,7 @@ impl Default for AbstractInsentientMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11826,7 +11922,7 @@ impl Default for AbstractLivingMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11889,7 +11985,7 @@ impl Default for AbstractMinecartMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -11946,7 +12042,7 @@ impl Default for AbstractMonsterMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -12017,7 +12113,7 @@ impl Default for AbstractPiglinMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -12090,7 +12186,7 @@ impl Default for AbstractRaiderMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -12165,7 +12261,9 @@ impl Default for AbstractSpellcasterIllagerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -12249,7 +12347,9 @@ impl Default for AbstractTameableMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown( + false, + ), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -12320,7 +12420,7 @@ impl Default for AbstractThrownItemProjectileMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -12380,7 +12480,7 @@ impl Default for AbstractVehicleMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), @@ -12440,7 +12540,7 @@ impl Default for AbstractVillagerMetadataBundle { parent: AbstractEntityMetadataBundle { _marker: AbstractEntity, on_fire: OnFire(false), - shift_key_down: ShiftKeyDown(false), + abstract_entity_shift_key_down: AbstractEntityShiftKeyDown(false), sprinting: Sprinting(false), swimming: Swimming(false), currently_glowing: CurrentlyGlowing(false), diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs index ee6bca612..17ebaf179 100644 --- a/azalea-entity/src/plugin/mod.rs +++ b/azalea-entity/src/plugin/mod.rs @@ -17,7 +17,9 @@ pub use relative_updates::RelativeEntityUpdate; use tracing::debug; use crate::{ - Dead, EyeHeight, FluidOnEyes, LocalEntity, LookDirection, OnClimbable, Physics, Position, + Dead, EntityKindComponent, FluidOnEyes, LocalEntity, LookDirection, OnClimbable, Physics, Pose, + Position, + dimensions::{EntityDimensions, calculate_dimensions}, metadata::Health, }; @@ -56,12 +58,11 @@ impl Plugin for EntityPlugin { debug_new_entity, add_dead, clamp_look_direction, - update_fluid_on_eyes, update_on_climbable, + (update_dimensions, update_bounding_box, update_fluid_on_eyes).chain(), ), ), ) - .add_systems(Update, update_bounding_box) .add_systems(GameTick, update_in_loaded_chunk) .init_resource::(); } @@ -91,15 +92,20 @@ pub fn add_dead(mut commands: Commands, query: Query<(Entity, &Health), Changed< } pub fn update_fluid_on_eyes( - mut query: Query<(&mut FluidOnEyes, &Position, &EyeHeight, &InstanceName)>, + mut query: Query<( + &mut FluidOnEyes, + &Position, + &EntityDimensions, + &InstanceName, + )>, instance_container: Res, ) { - for (mut fluid_on_eyes, position, eye_height, instance_name) in query.iter_mut() { + for (mut fluid_on_eyes, position, dimensions, instance_name) in query.iter_mut() { let Some(instance) = instance_container.get(instance_name) else { continue; }; - let adjusted_eye_y = position.y + (**eye_height as f64) - 0.1111111119389534; + let adjusted_eye_y = position.y + (dimensions.eye_height as f64) - 0.1111111119389534; let eye_block_pos = BlockPos::from(Vec3::new(position.x, adjusted_eye_y, position.z)); let fluid_at_eye = instance .read() @@ -201,13 +207,27 @@ pub fn apply_clamp_look_direction(mut look_direction: LookDirection) -> LookDire /// /// # Safety /// Cached position in the world must be updated. -pub fn update_bounding_box(mut query: Query<(&Position, &mut Physics), Changed>) { - for (position, mut physics) in query.iter_mut() { - let bounding_box = physics.dimensions.make_bounding_box(**position); +pub fn update_bounding_box( + mut query: Query<(&mut Physics, &Position, &EntityDimensions), Changed>, +) { + for (mut physics, position, dimensions) in query.iter_mut() { + let bounding_box = dimensions.make_bounding_box(**position); physics.bounding_box = bounding_box; } } +#[allow(clippy::type_complexity)] +pub fn update_dimensions( + mut query: Query< + (&mut EntityDimensions, &EntityKindComponent, &Pose), + Or<(Changed, Changed)>, + >, +) { + for (mut dimensions, kind, pose) in query.iter_mut() { + *dimensions = calculate_dimensions(**kind, *pose); + } +} + /// Marks an entity that's in a loaded chunk. This is updated at the beginning /// of every tick. /// diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index be36e0ed3..968bfad0f 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -15,8 +15,8 @@ use azalea_core::{ position::{BlockPos, Vec3}, }; use azalea_entity::{ - Attributes, Jumping, LookDirection, OnClimbable, Physics, PlayerAbilities, Pose, Position, - Sneaking, metadata::Sprinting, + Attributes, Crouching, Jumping, LookDirection, OnClimbable, Physics, PlayerAbilities, Pose, + Position, metadata::Sprinting, }; use azalea_world::{ChunkStorage, Instance, MoveEntityError}; use bevy_ecs::{entity::Entity, world::Mut}; @@ -113,7 +113,7 @@ pub struct MoveCtx<'world, 'state, 'a, 'b> { pub source_entity: Entity, pub physics_query: &'a PhysicsQuery<'world, 'state, 'b>, pub collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, - pub sneaking: Sneaking, + pub sneaking: Crouching, pub attributes: &'a Attributes, pub abilities: Option<&'a PlayerAbilities>, @@ -265,7 +265,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 let is_staying_on_ground_surface = *move_ctx.sneaking; let max_up_step = get_max_up_step(move_ctx.attributes); - let mut fall_ctx = CanFallAtLeastCtx { + let fall_ctx = CanFallAtLeastCtx { physics: move_ctx.physics, world: move_ctx.world, source_entity: move_ctx.source_entity, @@ -281,7 +281,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 && movement.y <= 0. && matches!(move_ctx.mover_type, MoverType::Own | MoverType::Player) && is_staying_on_ground_surface - && is_above_ground(&mut fall_ctx, max_up_step); + && is_above_ground(&fall_ctx, max_up_step); if !is_backing_off { return movement; } @@ -290,7 +290,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 let min_movement_x = movement.x.signum() * min_movement; let min_movement_z = movement.z.signum() * min_movement; - while movement.x != 0. && can_fall_at_least(&mut fall_ctx, movement.x, 0., max_up_step as f64) { + while movement.x != 0. && can_fall_at_least(&fall_ctx, movement.x, 0., max_up_step as f64) { if movement.x.abs() < min_movement { movement.x = 0.; break; @@ -298,7 +298,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 movement.x -= min_movement_x } - while movement.z != 0. && can_fall_at_least(&mut fall_ctx, 0., movement.z, max_up_step as f64) { + while movement.z != 0. && can_fall_at_least(&fall_ctx, 0., movement.z, max_up_step as f64) { if movement.z.abs() < min_movement { movement.z = 0.; break; @@ -308,7 +308,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 } while movement.x != 0.0 && movement.z != 0.0 - && can_fall_at_least(&mut fall_ctx, movement.x, movement.z, max_up_step as f64) + && can_fall_at_least(&fall_ctx, movement.x, movement.z, max_up_step as f64) { if movement.x.abs() <= min_movement { movement.x = 0.; @@ -330,14 +330,14 @@ fn get_max_up_step(attributes: &Attributes) -> f32 { attributes.step_height.calculate() as f32 } -fn is_above_ground(ctx: &mut CanFallAtLeastCtx, max_up_step: f32) -> bool { +fn is_above_ground(ctx: &CanFallAtLeastCtx, max_up_step: f32) -> bool { ctx.physics.on_ground() && ctx.physics.fall_distance < max_up_step as f64 && !can_fall_at_least(ctx, 0., 0., max_up_step as f64 - ctx.physics.fall_distance) } pub struct CanFallAtLeastCtx<'world, 'state, 'a, 'b> { - physics: &'a mut Physics, + physics: &'a Physics, world: &'a Instance, source_entity: Entity, physics_query: &'a PhysicsQuery<'world, 'state, 'b>, @@ -345,7 +345,7 @@ pub struct CanFallAtLeastCtx<'world, 'state, 'a, 'b> { } fn can_fall_at_least( - ctx: &mut CanFallAtLeastCtx, + ctx: &CanFallAtLeastCtx, delta_x: f64, delta_z: f64, max_up_step: f64, diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 7bef61577..2e0912d67 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -16,7 +16,8 @@ use azalea_core::{ }; use azalea_entity::{ Attributes, EntityKindComponent, HasClientLoaded, Jumping, LocalEntity, LookDirection, - OnClimbable, Physics, Pose, Position, metadata::Sprinting, move_relative, + OnClimbable, Physics, Pose, Position, dimensions::EntityDimensions, metadata::Sprinting, + move_relative, }; use azalea_registry::{Block, EntityKind}; use azalea_world::{Instance, InstanceContainer, InstanceName}; @@ -159,12 +160,12 @@ fn jump_in_liquid(physics: &mut Physics) { #[allow(clippy::type_complexity)] pub fn apply_effects_from_blocks( mut query: Query< - (&mut Physics, &Position, &InstanceName), + (&mut Physics, &Position, &EntityDimensions, &InstanceName), (With, With), >, instance_container: Res, ) { - for (mut physics, position, world_name) in &mut query { + for (mut physics, position, dimensions, world_name) in &mut query { let Some(world_lock) = instance_container.get(world_name) else { continue; }; @@ -187,12 +188,13 @@ pub fn apply_effects_from_blocks( to: **position, }]; - check_inside_blocks(&mut physics, &world, &movement_this_tick); + check_inside_blocks(&mut physics, dimensions, &world, &movement_this_tick); } } fn check_inside_blocks( physics: &mut Physics, + dimensions: &EntityDimensions, world: &Instance, movements: &[EntityMovement], ) -> Vec { @@ -200,8 +202,7 @@ fn check_inside_blocks( let mut visited_blocks = HashSet::::new(); for movement in movements { - let bounding_box_at_target = physics - .dimensions + let bounding_box_at_target = dimensions .make_bounding_box(movement.to) .deflate_all(1.0E-5); @@ -240,7 +241,7 @@ fn check_inside_blocks( movement.to, traversed_block, entity_inside_collision_shape, - physics, + dimensions, ) { continue; @@ -260,9 +261,9 @@ fn collided_with_shape_moving_from( to: Vec3, traversed_block: BlockPos, entity_inside_collision_shape: &VoxelShape, - physics: &Physics, + dimensions: &EntityDimensions, ) -> bool { - let bounding_box_from = physics.dimensions.make_bounding_box(from); + let bounding_box_from = dimensions.make_bounding_box(from); let delta = to - from; bounding_box_from.collided_along_vector( delta, @@ -430,7 +431,7 @@ fn handle_on_climbable( // sneaking on ladders/vines if y < 0.0 - && pose == Some(Pose::Sneaking) + && pose == Some(Pose::Crouching) && azalea_registry::Block::from( world .chunks diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs index dd8cef87c..005492b1b 100644 --- a/azalea-physics/src/travel.rs +++ b/azalea-physics/src/travel.rs @@ -4,8 +4,8 @@ use azalea_core::{ position::{BlockPos, Vec3}, }; use azalea_entity::{ - Attributes, HasClientLoaded, Jumping, LocalEntity, LookDirection, OnClimbable, Physics, - PlayerAbilities, Pose, Position, Sneaking, metadata::Sprinting, move_relative, + Attributes, Crouching, HasClientLoaded, Jumping, LocalEntity, LookDirection, OnClimbable, + Physics, PlayerAbilities, Pose, Position, metadata::Sprinting, move_relative, }; use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_ecs::prelude::*; @@ -36,7 +36,7 @@ pub fn travel( &InstanceName, &OnClimbable, &Jumping, - &Sneaking, + &Crouching, Option<&PlayerAbilities>, ), (With, With), @@ -254,7 +254,7 @@ fn is_free( source_entity: Entity, physics_query: &PhysicsQuery, collidable_entity_query: &CollidableEntityQuery, - entity_physics: &mut Physics, + entity_physics: &Physics, bounding_box: AABB, delta: Vec3, ) -> bool { @@ -276,7 +276,7 @@ pub fn no_collision( source_entity: Option, physics_query: &PhysicsQuery, collidable_entity_query: &CollidableEntityQuery, - entity_physics: &mut Physics, + entity_physics: &Physics, aabb: &AABB, include_liquid_collisions: bool, ) -> bool { diff --git a/azalea/examples/nearest_entity.rs b/azalea/examples/nearest_entity.rs index 8774829e1..e859751e8 100644 --- a/azalea/examples/nearest_entity.rs +++ b/azalea/examples/nearest_entity.rs @@ -2,7 +2,8 @@ use azalea::{Bot, ClientBuilder, LookAtEvent, nearest_entity::EntityFinder}; use azalea_client::Account; use azalea_core::tick::GameTick; use azalea_entity::{ - EyeHeight, LocalEntity, Position, + LocalEntity, Position, + dimensions::EntityDimensions, metadata::{ItemItem, Player}, }; use bevy_app::Plugin; @@ -33,7 +34,7 @@ impl Plugin for LookAtStuffPlugin { fn look_at_everything( bots: Query, With)>, entities: EntityFinder, - entity_positions: Query<(&Position, Option<&EyeHeight>)>, + entity_positions: Query<(&Position, Option<&EntityDimensions>)>, mut look_at_event: EventWriter, ) { for bot_id in bots.iter() { @@ -41,11 +42,11 @@ fn look_at_everything( continue; }; - let (position, eye_height) = entity_positions.get(entity).unwrap(); + let (position, dimensions) = entity_positions.get(entity).unwrap(); let mut look_target = **position; - if let Some(eye_height) = eye_height { - look_target.y += **eye_height as f64; + if let Some(dimensions) = dimensions { + look_target.y += dimensions.eye_height as f64; } look_at_event.write(LookAtEvent { diff --git a/azalea/examples/testbot/commands/debug.rs b/azalea/examples/testbot/commands/debug.rs index 46f1ed33b..b3a8b4198 100644 --- a/azalea/examples/testbot/commands/debug.rs +++ b/azalea/examples/testbot/commands/debug.rs @@ -205,6 +205,13 @@ pub fn register(commands: &mut CommandDispatcher>) { 1 })); + commands.register(literal("dimensions").executes(|ctx: &Ctx| { + let source = ctx.source.lock(); + let bot_dimensions = source.bot.dimensions(); + source.reply(format!("{bot_dimensions:?}")); + 1 + })); + commands.register(literal("debugecsleak").executes(|ctx: &Ctx| { let source = ctx.source.lock(); diff --git a/azalea/examples/testbot/commands/movement.rs b/azalea/examples/testbot/commands/movement.rs index a33b79e2d..7c777e8e7 100644 --- a/azalea/examples/testbot/commands/movement.rs +++ b/azalea/examples/testbot/commands/movement.rs @@ -3,10 +3,11 @@ use std::time::Duration; use azalea::{ BlockPos, SprintDirection, WalkDirection, brigadier::prelude::*, - entity::{EyeHeight, Position}, + entity::Position, pathfinder::goals::{BlockPosGoal, RadiusGoal, XZGoal}, prelude::*, }; +use azalea_entity::dimensions::EntityDimensions; use parking_lot::Mutex; use super::{CommandSource, Ctx}; @@ -103,8 +104,8 @@ pub fn register(commands: &mut CommandDispatcher>) { }; let eye_height = source .bot - .get_entity_component::(entity) - .map(|h| *h) + .get_entity_component::(entity) + .map(|h| h.eye_height) .unwrap_or_default(); source.bot.look_at(position.up(eye_height as f64)); 1 @@ -204,14 +205,14 @@ pub fn register(commands: &mut CommandDispatcher>) { literal("sneak") .executes(|ctx: &Ctx| { let source = ctx.source.lock(); - source.bot.set_sneaking(!source.bot.sneaking()); + source.bot.set_crouching(!source.bot.crouching()); source.reply("ok"); 1 }) .then(argument("enabled", bool()).executes(|ctx: &Ctx| { let sneaking = get_bool(ctx, "enabled").unwrap(); let source = ctx.source.lock(); - source.bot.set_sneaking(sneaking); + source.bot.set_crouching(sneaking); 1 })), ); diff --git a/azalea/src/bot.rs b/azalea/src/bot.rs index 8784cb318..b037ed142 100644 --- a/azalea/src/bot.rs +++ b/azalea/src/bot.rs @@ -9,8 +9,8 @@ use azalea_core::{ tick::GameTick, }; use azalea_entity::{ - EyeHeight, Jumping, LocalEntity, LookDirection, Position, clamp_look_direction, - metadata::Player, + Jumping, LocalEntity, LookDirection, Position, clamp_look_direction, + dimensions::EntityDimensions, metadata::Player, update_dimensions, }; use azalea_physics::PhysicsSet; use bevy_app::Update; @@ -43,7 +43,9 @@ impl Plugin for BotPlugin { Update, ( insert_bot, - look_at_listener.before(clamp_look_direction), + look_at_listener + .before(clamp_look_direction) + .after(update_dimensions), jump_listener, ), ) @@ -224,12 +226,12 @@ pub struct LookAtEvent { } fn look_at_listener( mut events: EventReader, - mut query: Query<(&Position, &EyeHeight, &mut LookDirection)>, + mut query: Query<(&Position, &EntityDimensions, &mut LookDirection)>, ) { for event in events.read() { - if let Ok((position, eye_height, mut look_direction)) = query.get_mut(event.entity) { + if let Ok((position, dimensions, mut look_direction)) = query.get_mut(event.entity) { let new_look_direction = - direction_looking_at(position.up(eye_height.into()), event.position); + direction_looking_at(position.up(dimensions.eye_height.into()), event.position); trace!("look at {} (currently at {})", event.position, **position); look_direction.update(new_look_direction); diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs index 4734aa3ed..89a8b3c40 100644 --- a/azalea/src/pathfinder/simulation.rs +++ b/azalea/src/pathfinder/simulation.rs @@ -10,7 +10,7 @@ use azalea_core::{ game_type::GameMode, position::Vec3, resource_location::ResourceLocation, tick::GameTick, }; use azalea_entity::{ - Attributes, EntityDimensions, LookDirection, Physics, Position, default_attributes, + Attributes, LookDirection, Physics, Position, default_attributes, dimensions::EntityDimensions, }; use azalea_registry::EntityKind; use azalea_world::{ChunkStorage, Instance, InstanceContainer, MinecraftEntityId, PartialInstance}; @@ -35,7 +35,7 @@ impl SimulatedPlayerBundle { SimulatedPlayerBundle { position: Position::new(position), - physics: Physics::new(dimensions, position), + physics: Physics::new(&dimensions, position), physics_state: PhysicsState::default(), look_direction: LookDirection::default(), attributes: default_attributes(EntityKind::Player), diff --git a/codegen/lib/code/entity.py b/codegen/lib/code/entity.py index d4b43d589..31cf71a8d 100644 --- a/codegen/lib/code/entity.py +++ b/codegen/lib/code/entity.py @@ -152,6 +152,10 @@ def generate_entity_metadata(burger_entities_data: dict, mappings: Mappings): # some generic names... we don't like these duplicate_field_names.add("state") # SnifferState instead of State + duplicate_field_names.add("crouching") # FoxCrouching instead of Crouching + + # make this one longer to avoid accidental use -- AbstractEntityShiftKeyDown instead of ShiftKeydown + duplicate_field_names.add("shift_key_down") for entity_id in burger_entity_metadata.keys(): field_name_map[entity_id] = {} @@ -626,7 +630,7 @@ def generate_fields(this_entity_id: str): def generate_entity_dimensions(burger_entities_data: dict): # lines look like - # EntityKind::Player => EntityDimensions::new(0.6, 1.8), + # EntityKind::Player => EntityDimensions::new(0.6, 1.8).eye_height(1.62), new_match_lines = [] for entity_id, entity_data in burger_entities_data["entity"].items(): if entity_id.startswith("~"): @@ -635,9 +639,10 @@ def generate_entity_dimensions(burger_entities_data: dict): variant_name: str = upper_first_letter(to_camel_case(entity_id)) width = entity_data["width"] height = entity_data["height"] - new_match_lines.append( - f" EntityKind::{variant_name} => EntityDimensions::new({width}, {height})," - ) + expr = f"EntityDimensions::new({width}, {height})" + if "eye_height" in entity_data: + expr += f".eye_height({entity_data['eye_height']})" + new_match_lines.append(f" EntityKind::{variant_name} => {expr},") with open(DIMENSIONS_RS_DIR, "r") as f: lines = f.read().split("\n") @@ -650,7 +655,7 @@ def generate_entity_dimensions(burger_entities_data: dict): if line.strip() == "match entity {": in_match = True else: - if line.strip() == "}": + if line == " }": new_lines.extend(new_match_lines) new_lines.extend(lines[i:]) break From ab5d23c8825cae9ab4047082015da713ce8f02b2 Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 14 Aug 2025 01:41:53 -0400 Subject: [PATCH 5/7] proper support for automatically crouching in certain cases --- CHANGELOG.md | 2 +- .../src/builder/argument_builder.rs | 13 ++- azalea-client/src/plugins/movement.rs | 80 +++++++++++++++++-- azalea-entity/src/lib.rs | 10 ++- azalea-entity/src/plugin/mod.rs | 21 ++++- azalea-physics/src/collision/mod.rs | 4 +- azalea-physics/src/travel.rs | 4 +- azalea/examples/testbot/commands/movement.rs | 29 ++++--- 8 files changed, 128 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 413e24005..b026309e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ is breaking anyways, semantic versioning is not followed. - There is now a `azalea_inventory::default_components::get_default_component` function to get the default value of a component for a registry item. - `ItemStack` now has a `get_component` function that supports default components. - `Client::nearest_entity_by`. -- Clients are now able to crouch/sneak using the new `Crouching` component or `Client::set_crouching`. +- Sneaking/crouching. ### Changed diff --git a/azalea-brigadier/src/builder/argument_builder.rs b/azalea-brigadier/src/builder/argument_builder.rs index 5fbdaca56..945f7fcbd 100644 --- a/azalea-brigadier/src/builder/argument_builder.rs +++ b/azalea-brigadier/src/builder/argument_builder.rs @@ -30,7 +30,6 @@ impl Clone for ArgumentBuilderType { } /// A node that hasn't yet been built. -#[derive(Clone)] pub struct ArgumentBuilder { arguments: CommandNode, @@ -196,3 +195,15 @@ impl Debug for ArgumentBuilder { .finish() } } +impl Clone for ArgumentBuilder { + fn clone(&self) -> Self { + Self { + arguments: self.arguments.clone(), + command: self.command.clone(), + requirement: self.requirement.clone(), + target: self.target.clone(), + forks: self.forks, + modifier: self.modifier.clone(), + } + } +} diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index a844f0170..7771e07c6 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -6,8 +6,11 @@ use azalea_core::{ tick::GameTick, }; use azalea_entity::{ - Attributes, Crouching, HasClientLoaded, Jumping, LastSentPosition, LookDirection, Physics, - Pose, Position, dimensions::calculate_dimensions, metadata::Sprinting, update_bounding_box, + Attributes, Crouching, HasClientLoaded, Jumping, LastSentPosition, LocalEntity, LookDirection, + Physics, PlayerAbilities, Pose, Position, + dimensions::calculate_dimensions, + metadata::{self, Sprinting}, + update_bounding_box, }; use azalea_physics::{ PhysicsSet, ai_step, @@ -110,15 +113,17 @@ impl Client { pub fn set_crouching(&self, crouching: bool) { let mut ecs = self.ecs.lock(); - let mut crouching_mut = self.query::<&mut Crouching>(&mut ecs); - **crouching_mut = crouching; + let mut physics_state = self.query::<&mut PhysicsState>(&mut ecs); + physics_state.trying_to_crouch = crouching; } /// Whether the client is currently trying to sneak. /// /// You may want to check the [`Pose`] instead. pub fn crouching(&self) -> bool { - *self.component::() + let mut ecs = self.ecs.lock(); + let physics_state = self.query::<&PhysicsState>(&mut ecs); + physics_state.trying_to_crouch } /// Sets the direction the client is looking. `y_rot` is yaw (looking to the @@ -163,6 +168,17 @@ pub struct PhysicsState { // holding down ctrl for a tick. pub trying_to_sprint: bool, + /// Whether our player is currently trying to sneak. + /// + /// This is distinct from + /// [`AbstractEntityShiftKeyDown`](azalea_entity::metadata::AbstractEntityShiftKeyDown), + /// which is a metadata value that is controlled by the server and affects + /// how the nametags of other entities are displayed. + /// + /// To check whether we're actually sneaking, you can check the + /// [`Crouching`] or [`Pose`] components. + pub trying_to_crouch: bool, + pub move_direction: WalkDirection, pub move_vector: Vec2, } @@ -374,21 +390,69 @@ pub(crate) fn tick_controls(mut query: Query<&mut PhysicsState>) { /// Makes the bot do one physics tick. Note that this is already handled /// automatically by the client. +#[allow(clippy::type_complexity)] pub fn local_player_ai_step( mut query: Query< ( + Entity, &PhysicsState, - &Crouching, + &PlayerAbilities, + &metadata::Swimming, + &metadata::SleepingPos, + &InstanceHolder, + &Position, &mut Physics, &mut Sprinting, + &mut Crouching, &mut Attributes, ), - With, + (With, With), >, + physics_query: PhysicsQuery, + collidable_entity_query: CollidableEntityQuery, ) { - for (physics_state, crouching, mut physics, mut sprinting, mut attributes) in query.iter_mut() { + for ( + entity, + physics_state, + abilities, + swimming, + sleeping_pos, + instance_holder, + position, + mut physics, + mut sprinting, + mut crouching, + mut attributes, + ) in query.iter_mut() + { // server ai step + let is_swimming = **swimming; + // TODO: implement passengers + let is_passenger = false; + let is_sleeping = sleeping_pos.is_some(); + + let world = instance_holder.instance.read(); + let ctx = CanPlayerFitCtx { + world: &world, + entity, + position: *position, + physics_query: &physics_query, + collidable_entity_query: &collidable_entity_query, + physics: &physics, + }; + + let new_crouching = !abilities.flying + && !is_swimming + && !is_passenger + && can_player_fit_within_blocks_and_entities_when(&ctx, Pose::Crouching) + && (physics_state.trying_to_crouch + || !is_sleeping + && !can_player_fit_within_blocks_and_entities_when(&ctx, Pose::Standing)); + if **crouching != new_crouching { + **crouching = new_crouching; + } + // TODO: replace those booleans when using items and passengers are properly // implemented let move_vector = modify_input( diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 9f292b9c3..343810167 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -545,10 +545,14 @@ impl FluidOnEyes { #[derive(Component, Clone, Copy, Debug, PartialEq, Deref, DerefMut)] pub struct OnClimbable(bool); -/// A component that indicates whether the player is currently trying to sneak. +/// A component that indicates whether the player is currently sneaking. /// -/// This is distinct from [`metadata::AbstractEntityShiftKeyDown`], which is a -/// metadata value that is controlled by the server. +/// If the entity 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` +/// instead. #[derive(Component, Clone, Copy, Deref, DerefMut, Default)] pub struct Crouching(bool); diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs index 17ebaf179..95fcb93f1 100644 --- a/azalea-entity/src/plugin/mod.rs +++ b/azalea-entity/src/plugin/mod.rs @@ -17,8 +17,8 @@ pub use relative_updates::RelativeEntityUpdate; use tracing::debug; use crate::{ - Dead, EntityKindComponent, FluidOnEyes, LocalEntity, LookDirection, OnClimbable, Physics, Pose, - Position, + Crouching, Dead, EntityKindComponent, FluidOnEyes, LocalEntity, LookDirection, OnClimbable, + Physics, Pose, Position, dimensions::{EntityDimensions, calculate_dimensions}, metadata::Health, }; @@ -60,6 +60,7 @@ impl Plugin for EntityPlugin { clamp_look_direction, update_on_climbable, (update_dimensions, update_bounding_box, update_fluid_on_eyes).chain(), + update_crouching, ), ), ) @@ -207,8 +208,12 @@ pub fn apply_clamp_look_direction(mut look_direction: LookDirection) -> LookDire /// /// # Safety /// Cached position in the world must be updated. +#[allow(clippy::type_complexity)] pub fn update_bounding_box( - mut query: Query<(&mut Physics, &Position, &EntityDimensions), Changed>, + mut query: Query< + (&mut Physics, &Position, &EntityDimensions), + Or<(Changed, Changed)>, + >, ) { for (mut physics, position, dimensions) in query.iter_mut() { let bounding_box = dimensions.make_bounding_box(**position); @@ -228,6 +233,16 @@ pub fn update_dimensions( } } +pub fn update_crouching(query: Query<(&mut Crouching, &Pose), Without>) { + for (mut crouching, pose) in query { + let new_crouching = *pose == Pose::Crouching; + // avoid triggering change detection + if **crouching != new_crouching { + **crouching = new_crouching; + } + } +} + /// Marks an entity that's in a loaded chunk. This is updated at the beginning /// of every tick. /// diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index 968bfad0f..5462d4306 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -113,7 +113,7 @@ pub struct MoveCtx<'world, 'state, 'a, 'b> { pub source_entity: Entity, pub physics_query: &'a PhysicsQuery<'world, 'state, 'b>, pub collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, - pub sneaking: Crouching, + pub crouching: Crouching, pub attributes: &'a Attributes, pub abilities: Option<&'a PlayerAbilities>, @@ -262,7 +262,7 @@ fn check_fall_damage( } fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 { - let is_staying_on_ground_surface = *move_ctx.sneaking; + let is_staying_on_ground_surface = *move_ctx.crouching; let max_up_step = get_max_up_step(move_ctx.attributes); let fall_ctx = CanFallAtLeastCtx { diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs index 005492b1b..20203a7f4 100644 --- a/azalea-physics/src/travel.rs +++ b/azalea-physics/src/travel.rs @@ -56,7 +56,7 @@ pub fn travel( world_name, on_climbable, jumping, - sneaking, + crouching, abilities, ) in &mut query { @@ -77,7 +77,7 @@ pub fn travel( source_entity: entity, physics_query: &physics_query, collidable_entity_query: &collidable_entity_query, - sneaking: *sneaking, + crouching: *crouching, attributes, abilities, direction: *direction, diff --git a/azalea/examples/testbot/commands/movement.rs b/azalea/examples/testbot/commands/movement.rs index 7c777e8e7..a4ffbc73f 100644 --- a/azalea/examples/testbot/commands/movement.rs +++ b/azalea/examples/testbot/commands/movement.rs @@ -201,21 +201,20 @@ pub fn register(commands: &mut CommandDispatcher>) { })), ); - commands.register( - literal("sneak") - .executes(|ctx: &Ctx| { - let source = ctx.source.lock(); - source.bot.set_crouching(!source.bot.crouching()); - source.reply("ok"); - 1 - }) - .then(argument("enabled", bool()).executes(|ctx: &Ctx| { - let sneaking = get_bool(ctx, "enabled").unwrap(); - let source = ctx.source.lock(); - source.bot.set_crouching(sneaking); - 1 - })), - ); + let sneak = |ctx: &Ctx| { + let source = ctx.source.lock(); + source.bot.set_crouching(!source.bot.crouching()); + source.reply("ok"); + 1 + }; + let sneak_enabled = argument("enabled", bool()).executes(|ctx: &Ctx| { + let sneaking = get_bool(ctx, "enabled").unwrap(); + let source = ctx.source.lock(); + source.bot.set_crouching(sneaking); + 1 + }); + commands.register(literal("sneak").executes(sneak).then(sneak_enabled.clone())); + commands.register(literal("crouch").executes(sneak).then(sneak_enabled)); commands.register(literal("stop").executes(|ctx: &Ctx| { let source = ctx.source.lock(); From 1d61b7d82df3c5778a49a9a7e4457d7583df7de7 Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 15 Aug 2025 00:02:15 -0100 Subject: [PATCH 6/7] fix anticheat issues --- azalea-client/src/client.rs | 3 +- azalea-client/src/lib.rs | 5 +- azalea-client/src/local_player.rs | 9 + azalea-client/src/plugins/movement.rs | 186 ++++++++---------- azalea-client/tests/correct_sneak_movement.rs | 135 +++++++++++++ .../tests/correct_sprint_sneak_movement.rs | 153 ++++++++++++++ azalea-entity/src/attributes.rs | 32 +-- azalea-entity/src/lib.rs | 6 +- azalea-physics/src/collision/mod.rs | 14 +- azalea-physics/src/lib.rs | 3 +- azalea-physics/src/local_player.rs | 67 +++++++ azalea-physics/src/travel.rs | 34 ++-- azalea/examples/testbot/commands/movement.rs | 2 +- 13 files changed, 498 insertions(+), 151 deletions(-) create mode 100644 azalea-client/tests/correct_sneak_movement.rs create mode 100644 azalea-client/tests/correct_sprint_sneak_movement.rs create mode 100644 azalea-physics/src/local_player.rs diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 50bbc6061..023828165 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -19,6 +19,7 @@ use azalea_entity::{ indexing::{EntityIdIndex, EntityUuidIndex}, metadata::Health, }; +use azalea_physics::local_player::PhysicsState; use azalea_protocol::{ ServerAddress, common::client_information::ClientInformation, @@ -58,7 +59,7 @@ use crate::{ join::{ConnectOpts, StartJoinServerEvent}, local_player::{Hunger, InstanceHolder, PermissionLevel, TabList}, mining::{self}, - movement::{LastSentLookDirection, PhysicsState}, + movement::LastSentLookDirection, packet::game::SendPacketEvent, player::{GameProfileComponent, PlayerInfo, retroactively_add_game_profile_component}, }; diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs index 19e13253a..c818d96ab 100644 --- a/azalea-client/src/lib.rs +++ b/azalea-client/src/lib.rs @@ -21,6 +21,7 @@ mod plugins; pub mod test_utils; pub use account::{Account, AccountOpts}; +pub use azalea_physics::local_player::{PhysicsState, SprintDirection, WalkDirection}; pub use azalea_protocol::common::client_information::ClientInformation; // Re-export bevy-tasks so plugins can make sure that they're using the same // version. @@ -30,7 +31,5 @@ pub use client::{ StartClientOpts, start_ecs_runner, }; pub use events::Event; -pub use movement::{ - PhysicsState, SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection, -}; +pub use movement::{StartSprintEvent, StartWalkEvent}; pub use plugins::*; diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs index ef44b7fbf..09232d128 100644 --- a/azalea-client/src/local_player.rs +++ b/azalea-client/src/local_player.rs @@ -98,6 +98,15 @@ impl Default for Hunger { } } } +impl Hunger { + /// Returns true if we have enough food level to sprint. + /// + /// Note that this doesn't consider our gamemode or passenger status. + pub fn is_enough_to_sprint(&self) -> bool { + // hasEnoughFoodToSprint + self.food >= 6 + } +} impl InstanceHolder { /// Create a new `InstanceHolder` for the given entity. diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index 7771e07c6..ad6779fa1 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -15,7 +15,8 @@ use azalea_entity::{ use azalea_physics::{ PhysicsSet, ai_step, collision::entity_collisions::{CollidableEntityQuery, PhysicsQuery}, - travel::no_collision, + local_player::{PhysicsState, SprintDirection, WalkDirection}, + travel::{no_collision, travel}, }; use azalea_protocol::{ common::movements::MoveFlags, @@ -38,7 +39,7 @@ use thiserror::Error; use crate::{ client::Client, - local_player::{InstanceHolder, LocalGameMode}, + local_player::{Hunger, InstanceHolder, LocalGameMode}, packet::game::SendPacketEvent, }; @@ -83,7 +84,9 @@ impl Plugin for MovementPlugin { .before(ai_step) .before(azalea_physics::fluids::update_in_water_state_and_do_fluid_pushing), send_player_input_packet, - send_sprinting_if_needed.after(azalea_entity::update_in_loaded_chunk), + send_sprinting_if_needed + .after(azalea_entity::update_in_loaded_chunk) + .after(travel), send_position.after(PhysicsSet), ) .chain(), @@ -154,35 +157,6 @@ pub struct LastSentLookDirection { pub y_rot: f32, } -/// Component for entities that can move and sprint. Usually only in -/// [`LocalEntity`]s. -/// -/// [`LocalEntity`]: azalea_entity::LocalEntity -#[derive(Default, Component, Clone)] -pub struct PhysicsState { - /// Minecraft only sends a movement packet either after 20 ticks or if the - /// player moved enough. This is that tick counter. - pub position_remainder: u32, - pub was_sprinting: bool, - // Whether we're going to try to start sprinting this tick. Equivalent to - // holding down ctrl for a tick. - pub trying_to_sprint: bool, - - /// Whether our player is currently trying to sneak. - /// - /// This is distinct from - /// [`AbstractEntityShiftKeyDown`](azalea_entity::metadata::AbstractEntityShiftKeyDown), - /// which is a metadata value that is controlled by the server and affects - /// how the nametags of other entities are displayed. - /// - /// To check whether we're actually sneaking, you can check the - /// [`Crouching`] or [`Pose`] components. - pub trying_to_crouch: bool, - - pub move_direction: WalkDirection, - pub move_vector: Vec2, -} - #[allow(clippy::type_complexity)] pub fn send_position( mut query: Query< @@ -294,16 +268,10 @@ pub fn send_position( #[derive(Debug, Default, Component, Clone, PartialEq, Eq)] pub struct LastSentInput(pub ServerboundPlayerInput); pub fn send_player_input_packet( - mut query: Query<( - Entity, - &PhysicsState, - &Jumping, - &Crouching, - Option<&LastSentInput>, - )>, + mut query: Query<(Entity, &PhysicsState, &Jumping, Option<&LastSentInput>)>, mut commands: Commands, ) { - for (entity, physics_state, jumping, sneaking, last_sent_input) in query.iter_mut() { + for (entity, physics_state, jumping, last_sent_input) in query.iter_mut() { let dir = physics_state.move_direction; type D = WalkDirection; let input = ServerboundPlayerInput { @@ -312,7 +280,7 @@ pub fn send_player_input_packet( left: matches!(dir, D::Left | D::ForwardLeft | D::BackwardLeft), right: matches!(dir, D::Right | D::ForwardRight | D::BackwardRight), jump: **jumping, - shift: **sneaking, + shift: physics_state.trying_to_crouch, sprint: physics_state.trying_to_sprint, }; @@ -401,6 +369,8 @@ pub fn local_player_ai_step( &metadata::SleepingPos, &InstanceHolder, &Position, + Option<&Hunger>, + Option<&LastSentInput>, &mut Physics, &mut Sprinting, &mut Crouching, @@ -419,6 +389,8 @@ pub fn local_player_ai_step( sleeping_pos, instance_holder, position, + hunger, + last_sent_input, mut physics, mut sprinting, mut crouching, @@ -446,13 +418,66 @@ pub fn local_player_ai_step( && !is_swimming && !is_passenger && can_player_fit_within_blocks_and_entities_when(&ctx, Pose::Crouching) - && (physics_state.trying_to_crouch + && (last_sent_input.is_some_and(|i| i.0.shift) || !is_sleeping && !can_player_fit_within_blocks_and_entities_when(&ctx, Pose::Standing)); if **crouching != new_crouching { **crouching = new_crouching; } + // TODO: food data and abilities + // let has_enough_food_to_sprint = self.food_data().food_level || + // self.abilities().may_fly; + let has_enough_food_to_sprint = hunger.is_none_or(Hunger::is_enough_to_sprint); + + // TODO: double tapping w to sprint i think + + let trying_to_sprint = physics_state.trying_to_sprint; + + // TODO: swimming + let is_underwater = false; + let is_in_water = physics.is_in_water(); + // TODO: elytra + let is_fall_flying = false; + // TODO: passenger + let is_passenger = false; + // TODO: using items + let using_item = false; + // TODO: status effects + let has_blindness = false; + + let has_enough_impulse = has_enough_impulse_to_start_sprinting(physics_state); + + // LocalPlayer.canStartSprinting + let can_start_sprinting = !**sprinting + && has_enough_impulse + && has_enough_food_to_sprint + && !using_item + && !has_blindness + && (!is_passenger || is_underwater) + && (!is_fall_flying || is_underwater) + && (!is_moving_slowly(&crouching) || is_underwater) + && (!is_in_water || is_underwater); + if trying_to_sprint && can_start_sprinting { + set_sprinting(true, &mut sprinting, &mut attributes); + } + + if **sprinting { + // TODO: swimming + + let vehicle_can_sprint = false; + // shouldStopRunSprinting + let should_stop_sprinting = has_blindness + || (is_passenger && !vehicle_can_sprint) + || !has_enough_impulse + || !has_enough_food_to_sprint + || (physics.horizontal_collision && !physics.minor_horizontal_collision) + || (is_in_water && !is_underwater); + if should_stop_sprinting { + set_sprinting(false, &mut sprinting, &mut attributes); + } + } + // TODO: replace those booleans when using items and passengers are properly // implemented let move_vector = modify_input( @@ -464,32 +489,13 @@ pub fn local_player_ai_step( ); physics.x_acceleration = move_vector.x; physics.z_acceleration = move_vector.y; - - // TODO: food data and abilities - // let has_enough_food_to_sprint = self.food_data().food_level || - // self.abilities().may_fly; - let has_enough_food_to_sprint = true; - - // TODO: double tapping w to sprint i think - - let trying_to_sprint = physics_state.trying_to_sprint; - - if !**sprinting - && ( - // !self.is_in_water() - // || self.is_underwater() && - has_enough_impulse_to_start_sprinting(physics_state) - && has_enough_food_to_sprint - // && !self.using_item() - // && !self.has_effect(MobEffects.BLINDNESS) - && trying_to_sprint - ) - { - set_sprinting(true, &mut sprinting, &mut attributes); - } } } +fn is_moving_slowly(crouching: &Crouching) -> bool { + **crouching +} + // LocalPlayer.modifyInput fn modify_input( mut move_vector: Vec2, @@ -628,8 +634,12 @@ pub fn handle_sprint( } /// Change whether we're sprinting by adding an attribute modifier to the -/// player. You should use the [`walk`] and [`sprint`] methods instead. -/// Returns if the operation was successful. +/// player. +/// +/// You should use the [`Client::walk`] and [`Client::sprint`] functions +/// instead. +/// +/// Returns true if the operation was successful. fn set_sprinting( sprinting: bool, currently_sprinting: &mut Sprinting, @@ -638,12 +648,12 @@ fn set_sprinting( **currently_sprinting = sprinting; if sprinting { attributes - .speed + .movement_speed .try_insert(azalea_entity::attributes::sprinting_modifier()) .is_ok() } else { attributes - .speed + .movement_speed .remove(&azalea_entity::attributes::sprinting_modifier().id) .is_none() } @@ -688,44 +698,12 @@ pub fn handle_knockback(mut query: Query<&mut Physics>, mut events: EventReader< } } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub enum WalkDirection { - #[default] - None, - Forward, - Backward, - Left, - Right, - ForwardRight, - ForwardLeft, - BackwardRight, - BackwardLeft, -} - -/// The directions that we can sprint in. It's a subset of [`WalkDirection`]. -#[derive(Clone, Copy, Debug)] -pub enum SprintDirection { - Forward, - ForwardRight, - ForwardLeft, -} - -impl From for WalkDirection { - fn from(d: SprintDirection) -> Self { - match d { - SprintDirection::Forward => WalkDirection::Forward, - SprintDirection::ForwardRight => WalkDirection::ForwardRight, - SprintDirection::ForwardLeft => WalkDirection::ForwardLeft, - } - } -} - pub fn update_pose( mut query: Query<( Entity, &mut Pose, &Physics, - &Crouching, + &PhysicsState, &LocalGameMode, &InstanceHolder, &Position, @@ -733,7 +711,7 @@ pub fn update_pose( physics_query: PhysicsQuery, collidable_entity_query: CollidableEntityQuery, ) { - for (entity, mut pose, physics, crouching, game_mode, instance_holder, position) in + for (entity, mut pose, physics, physics_state, game_mode, instance_holder, position) in query.iter_mut() { let world = instance_holder.instance.read(); @@ -753,7 +731,7 @@ pub fn update_pose( // TODO: implement everything else from getDesiredPose: sleeping, swimming, // fallFlying, spinAttack - let desired_pose = if **crouching { + let desired_pose = if physics_state.trying_to_crouch { Pose::Crouching } else { Pose::Standing diff --git a/azalea-client/tests/correct_sneak_movement.rs b/azalea-client/tests/correct_sneak_movement.rs new file mode 100644 index 000000000..cf1d17b57 --- /dev/null +++ b/azalea-client/tests/correct_sneak_movement.rs @@ -0,0 +1,135 @@ +use azalea_client::{PhysicsState, StartWalkEvent, WalkDirection, test_utils::prelude::*}; +use azalea_core::{ + position::{BlockPos, ChunkPos, Vec3}, + resource_location::ResourceLocation, +}; +use azalea_entity::LookDirection; +use azalea_protocol::{ + common::movements::{PositionMoveRotation, RelativeMovements}, + packets::{ + ConnectionProtocol, + config::{ClientboundFinishConfiguration, ClientboundRegistryData}, + game::{ + ClientboundBlockUpdate, ClientboundPlayerPosition, ServerboundGamePacket, + ServerboundPlayerInput, + }, + }, +}; +use azalea_registry::{Block, DataRegistry, DimensionType}; +use simdnbt::owned::{NbtCompound, NbtTag}; + +#[test] +fn test_correct_sneak_movement() { + init_tracing(); + + let mut simulation = Simulation::new(ConnectionProtocol::Configuration); + let sent_packets = SentPackets::new(&mut simulation); + + simulation.receive_packet(ClientboundRegistryData { + registry_id: ResourceLocation::new("minecraft:dimension_type"), + entries: vec![( + ResourceLocation::new("minecraft:overworld"), + Some(NbtCompound::from_values(vec![ + ("height".into(), NbtTag::Int(384)), + ("min_y".into(), NbtTag::Int(-64)), + ])), + )] + .into_iter() + .collect(), + }); + simulation.tick(); + simulation.receive_packet(ClientboundFinishConfiguration); + simulation.tick(); + + simulation.receive_packet(make_basic_login_packet( + DimensionType::new_raw(0), // overworld + ResourceLocation::new("minecraft:overworld"), + )); + simulation.tick(); + + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.receive_packet(make_basic_empty_chunk(ChunkPos::new(0, 0), (384 + 64) / 16)); + simulation.receive_packet(ClientboundBlockUpdate { + pos: BlockPos::new(0, 119, 0), + block_state: Block::Stone.into(), + }); + simulation.receive_packet(ClientboundBlockUpdate { + pos: BlockPos::new(0, 119, 1), + block_state: Block::Stone.into(), + }); + simulation.receive_packet(ClientboundPlayerPosition { + id: 1, + change: PositionMoveRotation { + pos: Vec3::new(0.5, 120., 0.5), + delta: Vec3::ZERO, + look_direction: LookDirection::default(), + }, + relative: RelativeMovements::all_absolute(), + }); + simulation.tick(); + simulation.tick(); + simulation.tick(); + sent_packets.clear(); + + simulation.with_component_mut::(|p| p.trying_to_crouch = true); + simulation.tick(); + sent_packets.expect("PlayerInput", |p| { + matches!( + p, + ServerboundGamePacket::PlayerInput(p) + if *p == ServerboundPlayerInput { shift: true, ..Default::default() } + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.tick(); + simulation.send_event(StartWalkEvent { + entity: simulation.entity, + direction: WalkDirection::Forward, + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.tick(); + sent_packets.expect("PlayerInput", |p| { + matches!( + p, + ServerboundGamePacket::PlayerInput(p) + if *p == ServerboundPlayerInput { forward: true, shift: true, ..Default::default() } + ) + }); + sent_packets.expect("MovePlayerPos { z: 0.5294000033944846 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 0.5294000033944846) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.tick(); + sent_packets.expect("MovePlayerPos { z: 0.5748524105068866 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 0.5748524105068866) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.tick(); + sent_packets.expect("MovePlayerPos: { z: 0.6290694310673044 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 0.6290694310673044) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); +} diff --git a/azalea-client/tests/correct_sprint_sneak_movement.rs b/azalea-client/tests/correct_sprint_sneak_movement.rs new file mode 100644 index 000000000..5b26a8a3d --- /dev/null +++ b/azalea-client/tests/correct_sprint_sneak_movement.rs @@ -0,0 +1,153 @@ +use azalea_client::{PhysicsState, SprintDirection, StartSprintEvent, test_utils::prelude::*}; +use azalea_core::{ + position::{BlockPos, ChunkPos, Vec3}, + resource_location::ResourceLocation, +}; +use azalea_entity::LookDirection; +use azalea_protocol::{ + common::movements::{PositionMoveRotation, RelativeMovements}, + packets::{ + ConnectionProtocol, + config::{ClientboundFinishConfiguration, ClientboundRegistryData}, + game::{ + ClientboundBlockUpdate, ClientboundPlayerPosition, ServerboundGamePacket, + ServerboundPlayerInput, + }, + }, +}; +use azalea_registry::{Block, DataRegistry, DimensionType}; +use simdnbt::owned::{NbtCompound, NbtTag}; + +#[test] +fn test_correct_sprint_sneak_movement() { + init_tracing(); + + let mut simulation = Simulation::new(ConnectionProtocol::Configuration); + let sent_packets = SentPackets::new(&mut simulation); + + simulation.receive_packet(ClientboundRegistryData { + registry_id: ResourceLocation::new("minecraft:dimension_type"), + entries: vec![( + ResourceLocation::new("minecraft:overworld"), + Some(NbtCompound::from_values(vec![ + ("height".into(), NbtTag::Int(384)), + ("min_y".into(), NbtTag::Int(-64)), + ])), + )] + .into_iter() + .collect(), + }); + simulation.tick(); + simulation.receive_packet(ClientboundFinishConfiguration); + simulation.tick(); + + simulation.receive_packet(make_basic_login_packet( + DimensionType::new_raw(0), // overworld + ResourceLocation::new("minecraft:overworld"), + )); + simulation.tick(); + + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.receive_packet(make_basic_empty_chunk(ChunkPos::new(0, 0), (384 + 64) / 16)); + simulation.receive_packet(ClientboundBlockUpdate { + pos: BlockPos::new(0, 119, 0), + block_state: Block::Stone.into(), + }); + simulation.receive_packet(ClientboundBlockUpdate { + pos: BlockPos::new(0, 119, 1), + block_state: Block::Stone.into(), + }); + simulation.receive_packet(ClientboundPlayerPosition { + id: 1, + change: PositionMoveRotation { + pos: Vec3::new(0.5, 120., 0.5), + delta: Vec3::ZERO, + look_direction: LookDirection::default(), + }, + relative: RelativeMovements::all_absolute(), + }); + simulation.tick(); + simulation.tick(); + simulation.tick(); + sent_packets.clear(); + + // start sprinting + simulation.send_event(StartSprintEvent { + entity: simulation.entity, + direction: SprintDirection::Forward, + }); + simulation.tick(); + sent_packets.expect("PlayerInput", |p| { + matches!( + p, + ServerboundGamePacket::PlayerInput(p) + if *p == ServerboundPlayerInput { forward: true, sprint: true, ..Default::default() } + ) + }); + sent_packets.expect("PlayerCommand", |p| { + matches!(p, ServerboundGamePacket::PlayerCommand(_)) + }); + sent_packets.expect("MovePlayerPos { z: 0.6274000124096872 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 0.6274000124096872) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.tick(); + sent_packets.expect("MovePlayerPos { z: 0.8243604396746886 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 0.8243604396746886) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + simulation.with_component_mut::(|p| p.trying_to_crouch = true); + + simulation.tick(); + sent_packets.expect("PlayerInput", |p| { + matches!( + p, + ServerboundGamePacket::PlayerInput(p) + if *p == ServerboundPlayerInput { forward: true, sprint: true, shift: true, ..Default::default() } + ) + }); + sent_packets.expect("MovePlayerPos { z: 1.0593008578621674 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 1.0593008578621674) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.tick(); + sent_packets.expect("MovePlayerPos { z: 1.2257983479146455 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 1.2257983479146455) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); + + simulation.tick(); + sent_packets.expect("MovePlayerPos: { z: 1.3549259948648078 }", |p| { + matches!( + p, + ServerboundGamePacket::MovePlayerPos(p) + if p.pos == Vec3::new(0.5, 120., 1.3549259948648078) + ) + }); + sent_packets.expect_tick_end(); + sent_packets.expect_empty(); +} diff --git a/azalea-entity/src/attributes.rs b/azalea-entity/src/attributes.rs index 647625f8b..021fcd56d 100644 --- a/azalea-entity/src/attributes.rs +++ b/azalea-entity/src/attributes.rs @@ -9,7 +9,7 @@ use thiserror::Error; #[derive(Clone, Debug, Component)] pub struct Attributes { - pub speed: AttributeInstance, + pub movement_speed: AttributeInstance, pub sneaking_speed: AttributeInstance, pub attack_speed: AttributeInstance, pub water_movement_efficiency: AttributeInstance, @@ -24,10 +24,11 @@ pub struct Attributes { pub struct AttributeInstance { pub base: f64, modifiers_by_id: HashMap, + // TODO: add cache } #[derive(Clone, Debug, Error)] -#[error("A modifier with this UUID is already present.")] +#[error("A modifier with this ID is already present.")] pub struct AlreadyPresentError; impl AttributeInstance { @@ -42,13 +43,12 @@ impl AttributeInstance { let mut total = self.base; for modifier in self.modifiers_by_id.values() { match modifier.operation { - AttributeModifierOperation::Addition => total += modifier.amount, - AttributeModifierOperation::MultiplyBase => total += self.base * modifier.amount, - _ => {} - } - if let AttributeModifierOperation::MultiplyTotal = modifier.operation { - total *= 1.0 + modifier.amount; - } + AttributeModifierOperation::AddValue => total += modifier.amount, + AttributeModifierOperation::AddMultipliedBase => { + total += modifier.amount * self.base + } + AttributeModifierOperation::AddMultipliedTotal => total *= 1. + modifier.amount, + }; } total } @@ -87,30 +87,30 @@ pub struct AttributeModifier { #[derive(Clone, Debug, Copy, AzBuf)] pub enum AttributeModifierOperation { - Addition, - MultiplyBase, - MultiplyTotal, + AddValue, + AddMultipliedBase, + AddMultipliedTotal, } pub fn sprinting_modifier() -> AttributeModifier { AttributeModifier { id: ResourceLocation::new("sprinting"), amount: 0.3f32 as f64, - operation: AttributeModifierOperation::MultiplyTotal, + operation: AttributeModifierOperation::AddMultipliedTotal, } } pub fn base_attack_speed_modifier(amount: f64) -> AttributeModifier { AttributeModifier { id: ResourceLocation::new("base_attack_speed"), amount, - operation: AttributeModifierOperation::Addition, + operation: AttributeModifierOperation::AddValue, } } pub fn creative_block_interaction_range_modifier() -> AttributeModifier { AttributeModifier { id: ResourceLocation::new("creative_mode_block_range"), amount: 0.5, - operation: AttributeModifierOperation::Addition, + operation: AttributeModifierOperation::AddValue, } } @@ -118,6 +118,6 @@ pub fn creative_entity_interaction_range_modifier() -> AttributeModifier { AttributeModifier { id: ResourceLocation::new("creative_mode_entity_range"), amount: 2.0, - operation: AttributeModifierOperation::Addition, + operation: AttributeModifierOperation::AddValue, } } diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 343810167..30e00ccb8 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -360,7 +360,8 @@ pub struct Physics { pub has_impulse: bool, pub horizontal_collision: bool, - // pub minor_horizontal_collision: bool, + // TODO: implement minor_horizontal_collision + pub minor_horizontal_collision: bool, pub vertical_collision: bool, pub water_fluid_height: f64, @@ -394,6 +395,7 @@ impl Physics { has_impulse: false, horizontal_collision: false, + minor_horizontal_collision: false, vertical_collision: false, water_fluid_height: 0., @@ -514,7 +516,7 @@ pub fn default_attributes(_entity_kind: EntityKind) -> Attributes { // TODO: do the correct defaults for everything, some // entities have different defaults Attributes { - speed: AttributeInstance::new(0.1), + movement_speed: AttributeInstance::new(0.1f32 as f64), sneaking_speed: AttributeInstance::new(0.3), attack_speed: AttributeInstance::new(4.0), water_movement_efficiency: AttributeInstance::new(0.0), diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index 5462d4306..d8ac3a957 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -15,8 +15,8 @@ use azalea_core::{ position::{BlockPos, Vec3}, }; use azalea_entity::{ - Attributes, Crouching, Jumping, LookDirection, OnClimbable, Physics, PlayerAbilities, Pose, - Position, metadata::Sprinting, + Attributes, Jumping, LookDirection, OnClimbable, Physics, PlayerAbilities, Pose, Position, + metadata::Sprinting, }; use azalea_world::{ChunkStorage, Instance, MoveEntityError}; use bevy_ecs::{entity::Entity, world::Mut}; @@ -27,7 +27,7 @@ pub use shape::*; use tracing::warn; use self::world_collisions::get_block_collisions; -use crate::travel::no_collision; +use crate::{local_player::PhysicsState, travel::no_collision}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MoverType { @@ -113,7 +113,7 @@ pub struct MoveCtx<'world, 'state, 'a, 'b> { pub source_entity: Entity, pub physics_query: &'a PhysicsQuery<'world, 'state, 'b>, pub collidable_entity_query: &'a CollidableEntityQuery<'world, 'state>, - pub crouching: Crouching, + pub physics_state: Option<&'a PhysicsState>, pub attributes: &'a Attributes, pub abilities: Option<&'a PlayerAbilities>, @@ -262,7 +262,7 @@ fn check_fall_damage( } fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 { - let is_staying_on_ground_surface = *move_ctx.crouching; + let is_staying_on_ground_surface = move_ctx.physics_state.is_some_and(|s| s.trying_to_crouch); let max_up_step = get_max_up_step(move_ctx.attributes); let fall_ctx = CanFallAtLeastCtx { @@ -291,7 +291,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 let min_movement_z = movement.z.signum() * min_movement; while movement.x != 0. && can_fall_at_least(&fall_ctx, movement.x, 0., max_up_step as f64) { - if movement.x.abs() < min_movement { + if movement.x.abs() <= min_movement { movement.x = 0.; break; } @@ -299,7 +299,7 @@ fn maybe_back_off_from_edge(move_ctx: &mut MoveCtx, mut movement: Vec3) -> Vec3 movement.x -= min_movement_x } while movement.z != 0. && can_fall_at_least(&fall_ctx, 0., movement.z, max_up_step as f64) { - if movement.z.abs() < min_movement { + if movement.z.abs() <= min_movement { movement.z = 0.; break; } diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 2e0912d67..fb62b48b0 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -4,6 +4,7 @@ pub mod clip; pub mod collision; pub mod fluids; +pub mod local_player; pub mod travel; use std::collections::HashSet; @@ -456,7 +457,7 @@ fn get_friction_influenced_speed( ) -> f32 { // TODO: have speed & flying_speed fields in entity if physics.on_ground() { - let speed: f32 = attributes.speed.calculate() as f32; + let speed = attributes.movement_speed.calculate() as f32; speed * (0.21600002f32 / (friction * friction * friction)) } else { // entity.flying_speed diff --git a/azalea-physics/src/local_player.rs b/azalea-physics/src/local_player.rs new file mode 100644 index 000000000..6ce196b66 --- /dev/null +++ b/azalea-physics/src/local_player.rs @@ -0,0 +1,67 @@ +use azalea_core::position::Vec2; +use bevy_ecs::component::Component; + +/// Component for entities that can move and sprint. Usually only in +/// [`LocalEntity`]s. +/// +/// [`LocalEntity`]: azalea_entity::LocalEntity +#[derive(Default, Component, Clone)] +pub struct PhysicsState { + /// Minecraft only sends a movement packet either after 20 ticks or if the + /// player moved enough. This is that tick counter. + pub position_remainder: u32, + pub was_sprinting: bool, + // Whether we're going to try to start sprinting this tick. Equivalent to + // holding down ctrl for a tick. + pub trying_to_sprint: bool, + + /// Whether our player is currently trying to sneak. + /// + /// This is distinct from + /// [`AbstractEntityShiftKeyDown`](azalea_entity::metadata::AbstractEntityShiftKeyDown), + /// which is a metadata value that is controlled by the server and affects + /// how the nametags of other entities are displayed. + /// + /// To check whether we're actually sneaking, you can check the + /// [`Crouching`] or [`Pose`] components. + pub trying_to_crouch: bool, + + pub move_direction: WalkDirection, + pub move_vector: Vec2, +} + +/// A direction that a player can walk in, including none. +/// +/// Superset of [`SprintDirection`]. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum WalkDirection { + #[default] + None, + Forward, + Backward, + Left, + Right, + ForwardRight, + ForwardLeft, + BackwardRight, + BackwardLeft, +} + +/// The directions that a player can sprint in. It's a subset of +/// [`WalkDirection`]. +#[derive(Clone, Copy, Debug)] +pub enum SprintDirection { + Forward, + ForwardRight, + ForwardLeft, +} + +impl From for WalkDirection { + fn from(d: SprintDirection) -> Self { + match d { + SprintDirection::Forward => WalkDirection::Forward, + SprintDirection::ForwardRight => WalkDirection::ForwardRight, + SprintDirection::ForwardLeft => WalkDirection::ForwardLeft, + } + } +} diff --git a/azalea-physics/src/travel.rs b/azalea-physics/src/travel.rs index 20203a7f4..1c473a45f 100644 --- a/azalea-physics/src/travel.rs +++ b/azalea-physics/src/travel.rs @@ -4,8 +4,8 @@ use azalea_core::{ position::{BlockPos, Vec3}, }; use azalea_entity::{ - Attributes, Crouching, HasClientLoaded, Jumping, LocalEntity, LookDirection, OnClimbable, - Physics, PlayerAbilities, Pose, Position, metadata::Sprinting, move_relative, + Attributes, HasClientLoaded, Jumping, LocalEntity, LookDirection, OnClimbable, Physics, + PlayerAbilities, Pose, Position, metadata::Sprinting, move_relative, }; use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_ecs::prelude::*; @@ -18,6 +18,7 @@ use crate::{ world_collisions::{get_block_and_liquid_collisions, get_block_collisions}, }, get_block_pos_below_that_affects_movement, handle_relative_friction_and_calculate_movement, + local_player::PhysicsState, }; /// Move the entity with the given acceleration while handling friction, @@ -27,17 +28,17 @@ pub fn travel( mut query: Query< ( Entity, - &mut Physics, - &mut LookDirection, - &mut Position, - Option<&Sprinting>, - Option<&Pose>, &Attributes, &InstanceName, &OnClimbable, &Jumping, - &Crouching, + Option<&PhysicsState>, + Option<&Sprinting>, + Option<&Pose>, Option<&PlayerAbilities>, + &mut Physics, + &mut LookDirection, + &mut Position, ), (With, With), >, @@ -47,17 +48,17 @@ pub fn travel( ) { for ( entity, - mut physics, - direction, - position, - sprinting, - pose, attributes, world_name, on_climbable, jumping, - crouching, + physics_state, + sprinting, + pose, abilities, + mut physics, + direction, + position, ) in &mut query { let Some(world_lock) = instance_container.get(world_name) else { @@ -77,7 +78,7 @@ pub fn travel( source_entity: entity, physics_query: &physics_query, collidable_entity_query: &collidable_entity_query, - crouching: *crouching, + physics_state, attributes, abilities, direction: *direction, @@ -163,7 +164,8 @@ fn travel_in_fluid(ctx: &mut MoveCtx) { if water_efficiency_modifier > 0. { water_movement_speed += (0.54600006 - water_movement_speed) * water_efficiency_modifier; - speed += (ctx.attributes.speed.calculate() as f32 - speed) * water_efficiency_modifier; + speed += (ctx.attributes.movement_speed.calculate() as f32 - speed) + * water_efficiency_modifier; } // if (this.hasEffect(MobEffects.DOLPHINS_GRACE)) { diff --git a/azalea/examples/testbot/commands/movement.rs b/azalea/examples/testbot/commands/movement.rs index a4ffbc73f..a4ac787a0 100644 --- a/azalea/examples/testbot/commands/movement.rs +++ b/azalea/examples/testbot/commands/movement.rs @@ -156,7 +156,7 @@ pub fn register(commands: &mut CommandDispatcher>) { tokio::time::sleep(Duration::from_secs_f32(seconds)).await; bot.walk(WalkDirection::None); }); - source.reply(format!("ok, spriting for {seconds} seconds")); + source.reply(format!("ok, sprinting for {seconds} seconds")); 1 })), ); From 6c8f7381ecc26bbaca5d78dc2dca9844e7881314 Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 15 Aug 2025 13:14:10 +1200 Subject: [PATCH 7/7] add line to changelog and update a comment --- CHANGELOG.md | 1 + azalea-client/src/client.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b026309e0..c52119c19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ is breaking anyways, semantic versioning is not followed. - Clients no longer send invalid look directions if the server teleports us with one. - Look directions are now rounded based on the default Minecraft sensitivity, which may help avoid flagging anticheats. - Movement code was updated with the changes from 1.21.5, so it no longer flags Grim. +- Clients can no longer sprint if their food level is too low. - `azalea-chat` now handles arrays of integers in the `with` field. (@qwqawawow) - `azalea-chat` no longer incorrectly persists styles of components in the "extra" field. - Inventories now use the correct max stack sizes. diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 023828165..be9c8e992 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -429,8 +429,8 @@ impl Client { ) } - /// Get the bounding box dimensions for our client, including our eye - /// height. + /// Get the bounding box dimensions for our client, which contains our + /// width, height, and eye height. /// /// This is a shortcut for /// `self.component::()`.