diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2026-01-12 02:09:41 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-12 02:09:41 -0600 |
| commit | 1accbac964168af5fa0d87cb170389f0a9d01363 (patch) | |
| tree | 1509b26c19beaa23a492289f6bf00d3958be44d5 /azalea-entity/src | |
| parent | 58339b9d229592dee40e15b8648fe4075cc391f4 (diff) | |
| download | azalea-drasl-1accbac964168af5fa0d87cb170389f0a9d01363.tar.xz | |
Make Bevy dependencies optional in azalea-protocol (#303)
* Make Bevy dependencies optional in azalea-protocol
* derive serde traits on Direction again
* update docs for types that may not have Component
Diffstat (limited to 'azalea-entity/src')
| -rw-r--r-- | azalea-entity/src/attributes.rs | 6 | ||||
| -rw-r--r-- | azalea-entity/src/data.rs | 4 | ||||
| -rw-r--r-- | azalea-entity/src/dimensions.rs | 6 | ||||
| -rw-r--r-- | azalea-entity/src/effects.rs | 6 | ||||
| -rw-r--r-- | azalea-entity/src/inventory.rs | 7 | ||||
| -rw-r--r-- | azalea-entity/src/lib.rs | 229 | ||||
| -rw-r--r-- | azalea-entity/src/particle.rs | 7 | ||||
| -rw-r--r-- | azalea-entity/src/plugin/components.rs | 151 | ||||
| -rw-r--r-- | azalea-entity/src/plugin/indexing.rs | 4 | ||||
| -rw-r--r-- | azalea-entity/src/plugin/mod.rs | 61 | ||||
| -rw-r--r-- | azalea-entity/src/plugin/relative_updates.rs | 3 |
11 files changed, 256 insertions, 228 deletions
diff --git a/azalea-entity/src/attributes.rs b/azalea-entity/src/attributes.rs index b26f61ba..69e98a7b 100644 --- a/azalea-entity/src/attributes.rs +++ b/azalea-entity/src/attributes.rs @@ -7,14 +7,14 @@ use std::collections::{HashMap, hash_map}; use azalea_core::attribute_modifier_operation::AttributeModifierOperation; use azalea_inventory::components::AttributeModifier; use azalea_registry::{builtin::Attribute, identifier::Identifier}; -use bevy_ecs::component::Component; use thiserror::Error; -/// A component that contains the current attribute values for an entity. +/// The current attribute values for an entity. /// /// Each attribute can have multiple modifiers, and these modifiers are the /// result of things like sprinting or enchantments. -#[derive(Clone, Component, Debug)] +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Debug)] pub struct Attributes { pub movement_speed: AttributeInstance, pub sneaking_speed: AttributeInstance, diff --git a/azalea-entity/src/data.rs b/azalea-entity/src/data.rs index c9e98b0d..0b973bcb 100644 --- a/azalea-entity/src/data.rs +++ b/azalea-entity/src/data.rs @@ -13,7 +13,6 @@ use azalea_core::{ }; use azalea_inventory::{ItemStack, components}; use azalea_registry::builtin::{VillagerKind, VillagerProfession}; -use bevy_ecs::component::Component; use derive_more::Deref; use enum_as_inner::EnumAsInner; use uuid::Uuid; @@ -154,7 +153,8 @@ pub struct Rotations { pub z: f32, } -#[derive(AzBuf, Clone, Component, Copy, Debug, Default, Eq, PartialEq)] +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(AzBuf, Clone, Copy, Debug, Default, Eq, PartialEq)] pub enum Pose { #[default] Standing = 0, diff --git a/azalea-entity/src/dimensions.rs b/azalea-entity/src/dimensions.rs index 87eced8a..6c527ab6 100644 --- a/azalea-entity/src/dimensions.rs +++ b/azalea-entity/src/dimensions.rs @@ -1,11 +1,11 @@ use azalea_core::{aabb::Aabb, position::Vec3}; use azalea_registry::builtin::EntityKind; -use bevy_ecs::component::Component; use crate::Pose; -/// A component that contains the size of an entity and their eye height. -#[derive(Clone, Component, Debug, Default)] +/// The size of an entity and its eye height. +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Debug, Default)] pub struct EntityDimensions { pub width: f32, pub height: f32, diff --git a/azalea-entity/src/effects.rs b/azalea-entity/src/effects.rs index ae7ae8a1..39074ebd 100644 --- a/azalea-entity/src/effects.rs +++ b/azalea-entity/src/effects.rs @@ -6,7 +6,6 @@ use std::{ use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; use azalea_core::bitset::FixedBitSet; use azalea_registry::builtin::MobEffect; -use bevy_ecs::component::Component; /// Data about an active mob effect. #[derive(AzBuf, Clone, Debug, Default, PartialEq)] @@ -63,8 +62,9 @@ impl AzaleaWrite for MobEffectFlags { } } -/// An ECS component that stores the active mob effects on an entity. -#[derive(Clone, Component, Debug, Default)] +/// The active mob effects on an entity. +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Debug, Default)] pub struct ActiveEffects(pub HashMap<MobEffect, MobEffectData>); impl ActiveEffects { pub fn insert(&mut self, effect: MobEffect, data: MobEffectData) { diff --git a/azalea-entity/src/inventory.rs b/azalea-entity/src/inventory.rs index aa13865e..fe3921ef 100644 --- a/azalea-entity/src/inventory.rs +++ b/azalea-entity/src/inventory.rs @@ -10,12 +10,13 @@ use azalea_inventory::{ QuickCraftStatusKind, QuickMoveClick, ThrowClick, }, }; -use bevy_ecs::prelude::*; use crate::PlayerAbilities; -/// A component present on all local players that have an inventory. -#[derive(Clone, Component, Debug)] +/// A local player's inventory and related data, including the container that +/// they may have opened. +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Debug)] pub struct Inventory { /// The player's inventory menu. This is guaranteed to be a `Menu::Player`. /// diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 40f80930..87e249c1 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -6,9 +6,11 @@ mod data; pub mod dimensions; mod effects; pub mod inventory; +#[cfg(feature = "bevy_ecs")] pub mod metadata; pub mod mining; pub mod particle; +#[cfg(feature = "bevy_ecs")] mod plugin; pub mod vec_delta_codec; @@ -19,25 +21,23 @@ use std::{ }; pub use attributes::Attributes; -use azalea_block::{BlockState, fluid_state::FluidKind}; +use azalea_block::fluid_state::FluidKind; use azalea_buf::AzBuf; use azalea_core::{ aabb::Aabb, math, position::{BlockPos, ChunkPos, Vec3}, }; -use azalea_registry::{builtin::EntityKind, identifier::Identifier}; -use azalea_world::{ChunkStorage, InstanceName}; -use bevy_ecs::{bundle::Bundle, component::Component}; +use azalea_registry::builtin::EntityKind; pub use data::*; use derive_more::{Deref, DerefMut}; pub use effects::{ActiveEffects, MobEffectData}; -use plugin::indexing::EntityChunkPos; use uuid::Uuid; use vec_delta_codec::VecDeltaCodec; use self::attributes::AttributeInstance; use crate::dimensions::EntityDimensions; +#[cfg(feature = "bevy_ecs")] pub use crate::plugin::*; pub fn move_relative( @@ -84,53 +84,12 @@ pub fn view_vector(look_direction: LookDirection) -> Vec3 { } } -/// Get the position of the block below the entity, but a little lower. -pub fn on_pos_legacy(chunk_storage: &ChunkStorage, position: Position) -> BlockPos { - on_pos(0.2, chunk_storage, position) -} - -// int x = Mth.floor(this.position.x); -// int y = Mth.floor(this.position.y - (double)var1); -// int z = Mth.floor(this.position.z); -// BlockPos var5 = new BlockPos(x, y, z); -// if (this.level.getBlockState(var5).isAir()) { -// BlockPos var6 = var5.below(); -// BlockState var7 = this.level.getBlockState(var6); -// if (var7.is(BlockTags.FENCES) || var7.is(BlockTags.WALLS) || -// var7.getBlock() instanceof FenceGateBlock) { return var6; -// } -// } -// return var5; -pub fn on_pos(offset: f32, chunk_storage: &ChunkStorage, pos: Position) -> BlockPos { - let x = pos.x.floor() as i32; - let y = (pos.y - offset as f64).floor() as i32; - let z = pos.z.floor() as i32; - let pos = BlockPos { x, y, z }; - - // TODO: check if block below is a fence, wall, or fence gate - let block_pos = pos.down(1); - let block_state = chunk_storage.get_block_state(block_pos); - if block_state == Some(BlockState::AIR) { - let block_pos_below = block_pos.down(1); - let block_state_below = chunk_storage.get_block_state(block_pos_below); - if let Some(_block_state_below) = block_state_below { - // if block_state_below.is_fence() - // || block_state_below.is_wall() - // || block_state_below.is_fence_gate() - // { - // return block_pos_below; - // } - } - } - - pos -} - /// The Minecraft UUID of the entity. /// /// For players, this is their actual player UUID, and for other entities it's /// just random. -#[derive(Clone, Component, Copy, Default, Deref, DerefMut, PartialEq)] +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Copy, Default, Deref, DerefMut, PartialEq)] pub struct EntityUuid(Uuid); impl EntityUuid { pub fn new(uuid: Uuid) -> Self { @@ -145,12 +104,13 @@ impl Debug for EntityUuid { /// The position of the entity right now. /// -/// You are free to change the value of this component; there's systems that -/// update the indexes automatically. +/// If this is being used as an ECS component then you are free to modify it, +/// because there are systems that will update the indexes automatically. /// /// Its value is set to a default of [`Vec3::ZERO`] when it receives the login /// packet, its true position may be set ticks later. -#[derive(Clone, Component, Copy, Debug, Default, Deref, DerefMut, PartialEq)] +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Copy, Debug, Default, Deref, DerefMut, PartialEq)] pub struct Position(Vec3); impl Position { pub fn new(pos: Vec3) -> Self { @@ -183,50 +143,12 @@ impl From<&Position> for BlockPos { } } -/// The second most recent position of the entity that was sent over the -/// network. -/// -/// This is currently only updated for our own local player entities. -#[derive(Clone, Component, Copy, Debug, Default, Deref, DerefMut, PartialEq)] -pub struct LastSentPosition(Vec3); -impl From<&LastSentPosition> for Vec3 { - fn from(value: &LastSentPosition) -> Self { - value.0 - } -} -impl From<LastSentPosition> for ChunkPos { - fn from(value: LastSentPosition) -> Self { - ChunkPos::from(&value.0) - } -} -impl From<LastSentPosition> for BlockPos { - fn from(value: LastSentPosition) -> Self { - BlockPos::from(&value.0) - } -} -impl From<&LastSentPosition> for ChunkPos { - fn from(value: &LastSentPosition) -> Self { - ChunkPos::from(value.0) - } -} -impl From<&LastSentPosition> for BlockPos { - fn from(value: &LastSentPosition) -> Self { - BlockPos::from(value.0) - } -} - -/// A component for entities that can jump. -/// -/// If this is true, the entity will try to jump every tick. It's equivalent to -/// the space key being held in vanilla. -#[derive(Clone, Component, Copy, Debug, Default, Deref, DerefMut, Eq, PartialEq)] -pub struct Jumping(pub bool); - -/// A component that contains the direction an entity is looking, in degrees. +/// The direction that an entity is looking, in degrees. /// /// To avoid flagging anticheats, consider using [`Self::update`] when updating /// the values of this struct. -#[derive(AzBuf, Clone, Component, Copy, Debug, Default, PartialEq)] +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)] pub struct LookDirection { /// Left and right. AKA yaw. In degrees. y_rot: f32, @@ -237,7 +159,7 @@ pub struct LookDirection { impl LookDirection { /// Create a new look direction and clamp the `x_rot` to the allowed values. pub fn new(y_rot: f32, x_rot: f32) -> Self { - apply_clamp_look_direction(Self { y_rot, x_rot }) + Self { y_rot, x_rot }.clamped() } /// Returns yaw (left and right) in degrees. /// @@ -303,6 +225,14 @@ impl LookDirection { self.y_rot += delta_y_rot; self.x_rot += delta_x_rot; } + + /// Force the [`Self::x_rot`] to be between -90 and 90 degrees, and return + /// the new look direction. + #[must_use] + pub fn clamped(mut self) -> Self { + self.x_rot = self.x_rot.clamp(-90., 90.); + self + } } impl From<LookDirection> for (f32, f32) { @@ -326,7 +256,8 @@ impl Eq for LookDirection {} /// The physics data relating to the entity, such as position, velocity, and /// bounding box. -#[derive(Clone, Component, Debug, Default)] +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Debug, Default)] pub struct Physics { /// How fast the entity is moving. Sometimes referred to as the delta /// movement. @@ -454,69 +385,6 @@ impl Physics { } } -/// Marker component for entities that are dead. -/// -/// "Dead" means that the entity has 0 health. -#[derive(Clone, Component, Copy, Default)] -pub struct Dead; - -/// A component NewType for [`EntityKind`]. -/// -/// Most of the time, you should be using `azalea_registry::EntityKind` -/// directly instead. -#[derive(Clone, Component, Copy, Debug, Deref, PartialEq)] -pub struct EntityKindComponent(pub EntityKind); - -/// A bundle of components that every entity has. -/// -/// This doesn't contain metadata; that has to be added separately. -#[derive(Bundle)] -pub struct EntityBundle { - pub kind: EntityKindComponent, - pub uuid: EntityUuid, - pub world_name: InstanceName, - pub position: Position, - pub last_sent_position: LastSentPosition, - - pub chunk_pos: EntityChunkPos, - - pub physics: Physics, - pub direction: LookDirection, - pub dimensions: EntityDimensions, - pub attributes: Attributes, - pub jumping: Jumping, - pub crouching: Crouching, - pub fluid_on_eyes: FluidOnEyes, - pub on_climbable: OnClimbable, - pub active_effects: ActiveEffects, -} - -impl EntityBundle { - pub fn new(uuid: Uuid, pos: Vec3, kind: EntityKind, world_name: Identifier) -> Self { - let dimensions = EntityDimensions::from(kind); - - Self { - kind: EntityKindComponent(kind), - uuid: EntityUuid(uuid), - world_name: InstanceName(world_name), - position: Position(pos), - chunk_pos: EntityChunkPos(ChunkPos::from(&pos)), - last_sent_position: LastSentPosition(pos), - physics: Physics::new(&dimensions, pos), - dimensions, - direction: LookDirection::default(), - - attributes: Attributes::new(EntityKind::Player), - - jumping: Jumping(false), - crouching: Crouching(false), - fluid_on_eyes: FluidOnEyes(FluidKind::Empty), - on_climbable: OnClimbable(false), - active_effects: ActiveEffects::default(), - } - } -} - impl Attributes { pub fn new(_entity_kind: EntityKind) -> Self { // TODO: do the correct defaults for everything, some @@ -534,43 +402,12 @@ impl Attributes { } } -/// A marker component that signifies that this entity is "local" and shouldn't -/// be updated by other clients. +/// The abilities that a player has, such as flying or being able to instantly +/// break blocks. /// -/// If this is for a client then all of our clients will have this. -/// -/// This component is not removed from clients when they disconnect. -#[derive(Clone, Component, Copy, Debug, Default)] -pub struct LocalEntity; - -#[derive(Clone, Component, Copy, Debug, Deref, DerefMut, PartialEq)] -pub struct FluidOnEyes(FluidKind); - -impl FluidOnEyes { - pub fn new(fluid: FluidKind) -> Self { - Self(fluid) - } -} - -#[derive(Clone, Component, Copy, Debug, Deref, DerefMut, PartialEq)] -pub struct OnClimbable(bool); - -/// A component that indicates whether the player is currently sneaking. -/// -/// If the entity isn't a local player, then this is just a shortcut for -/// checking if the [`Pose`] is `Crouching`. -/// -/// If you need to modify this value, use -/// `azalea_client::PhysicsState::trying_to_crouch` or `Client::set_crouching` -/// instead. -#[derive(Clone, Component, Copy, Default, Deref, DerefMut)] -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. -#[derive(Clone, Component, Debug, Default)] +/// This should only be present on local players. +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Debug, Default)] pub struct PlayerAbilities { pub invulnerable: bool, pub flying: bool, @@ -583,3 +420,9 @@ pub struct PlayerAbilities { /// Used for the fov pub walking_speed: f32, } + +/// The type of fluid that is at an entity's eye position, while also accounting +/// for fluid height. +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(Clone, Copy, Debug, Deref, DerefMut, PartialEq)] +pub struct FluidOnEyes(FluidKind); diff --git a/azalea-entity/src/particle.rs b/azalea-entity/src/particle.rs index ca3ac211..397346cf 100644 --- a/azalea-entity/src/particle.rs +++ b/azalea-entity/src/particle.rs @@ -1,16 +1,15 @@ use azalea_block::BlockState; use azalea_buf::AzBuf; -use azalea_core::{color::RgbColor, position::BlockPos}; +use azalea_core::{color::RgbColor, entity_id::MinecraftEntityId, position::BlockPos}; use azalea_inventory::ItemStack; use azalea_registry::builtin::ParticleKind; -use azalea_world::MinecraftEntityId; -use bevy_ecs::component::Component; // the order of this enum must be kept in sync with ParticleKind, otherwise // we get errors parsing particles. /// A [`ParticleKind`] with data potentially attached to it. -#[derive(AzBuf, Clone, Component, Debug, PartialEq)] +#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))] +#[derive(AzBuf, Clone, Debug, PartialEq)] pub enum Particle { AngryVillager, Block(BlockParticle), diff --git a/azalea-entity/src/plugin/components.rs b/azalea-entity/src/plugin/components.rs new file mode 100644 index 00000000..abeab160 --- /dev/null +++ b/azalea-entity/src/plugin/components.rs @@ -0,0 +1,151 @@ +use azalea_block::fluid_state::FluidKind; +use azalea_core::position::{BlockPos, ChunkPos, Vec3}; +use azalea_registry::{builtin::EntityKind, identifier::Identifier}; +use azalea_world::InstanceName; +use bevy_ecs::{bundle::Bundle, component::Component}; +use derive_more::{Deref, DerefMut}; +use uuid::Uuid; + +use crate::{ + ActiveEffects, Attributes, EntityUuid, FluidOnEyes, LookDirection, Physics, Position, + dimensions::EntityDimensions, indexing::EntityChunkPos, +}; + +/// A bundle of components that every entity has. +/// +/// This doesn't contain metadata; that has to be added separately. +#[derive(Bundle)] +pub struct EntityBundle { + pub kind: EntityKindComponent, + pub uuid: EntityUuid, + pub world_name: InstanceName, + pub position: Position, + pub last_sent_position: LastSentPosition, + + pub chunk_pos: EntityChunkPos, + + pub physics: Physics, + pub direction: LookDirection, + pub dimensions: EntityDimensions, + pub attributes: Attributes, + pub jumping: Jumping, + pub crouching: Crouching, + pub fluid_on_eyes: FluidOnEyes, + pub on_climbable: OnClimbable, + pub active_effects: ActiveEffects, +} + +impl EntityBundle { + pub fn new(uuid: Uuid, pos: Vec3, kind: EntityKind, world_name: Identifier) -> Self { + let dimensions = EntityDimensions::from(kind); + + Self { + kind: EntityKindComponent(kind), + uuid: EntityUuid(uuid), + world_name: InstanceName(world_name), + position: Position(pos), + chunk_pos: EntityChunkPos(ChunkPos::from(&pos)), + last_sent_position: LastSentPosition(pos), + physics: Physics::new(&dimensions, pos), + dimensions, + direction: LookDirection::default(), + + attributes: Attributes::new(EntityKind::Player), + + jumping: Jumping(false), + crouching: Crouching(false), + fluid_on_eyes: FluidOnEyes(FluidKind::Empty), + on_climbable: OnClimbable(false), + active_effects: ActiveEffects::default(), + } + } +} + +/// Marker component for entities that are dead. +/// +/// "Dead" means that the entity has 0 health. +#[derive(Clone, Component, Copy, Default)] +pub struct Dead; + +/// A component NewType for [`EntityKind`]. +/// +/// Most of the time, you should be using `azalea_registry::EntityKind` +/// directly instead. +#[derive(Clone, Component, Copy, Debug, Deref, PartialEq)] +pub struct EntityKindComponent(pub EntityKind); + +/// A marker component that signifies that this entity is "local" and shouldn't +/// be updated by other clients. +/// +/// If this is for a client then all of our clients will have this. +/// +/// This component is not removed from clients when they disconnect. +#[derive(Clone, Component, Copy, Debug, Default)] +pub struct LocalEntity; + +impl FluidOnEyes { + pub fn new(fluid: FluidKind) -> Self { + Self(fluid) + } +} + +#[derive(Clone, Component, Copy, Debug, Deref, DerefMut, PartialEq)] +pub struct OnClimbable(bool); + +/// A component that indicates whether the player is currently sneaking. +/// +/// If the entity isn't a local player, then this is just a shortcut for +/// checking if the [`Pose`] is `Crouching`. +/// +/// If you need to modify this value, use +/// `azalea_client::PhysicsState::trying_to_crouch` or `Client::set_crouching` +/// instead. +/// +/// [`Pose`]: crate::data::Pose +#[derive(Clone, Component, Copy, Default, Deref, DerefMut)] +pub struct Crouching(bool); + +/// A component that indicates whether the client has loaded. +/// +/// This is updated by a system in `azalea-client`. +#[derive(Component)] +pub struct HasClientLoaded; + +/// The second most recent position of the entity that was sent over the +/// network. +/// +/// This is currently only updated for our own local player entities. +#[derive(Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq)] +pub struct LastSentPosition(Vec3); +impl From<&LastSentPosition> for Vec3 { + fn from(value: &LastSentPosition) -> Self { + value.0 + } +} +impl From<LastSentPosition> for ChunkPos { + fn from(value: LastSentPosition) -> Self { + ChunkPos::from(&value.0) + } +} +impl From<LastSentPosition> for BlockPos { + fn from(value: LastSentPosition) -> Self { + BlockPos::from(&value.0) + } +} +impl From<&LastSentPosition> for ChunkPos { + fn from(value: &LastSentPosition) -> Self { + ChunkPos::from(value.0) + } +} +impl From<&LastSentPosition> for BlockPos { + fn from(value: &LastSentPosition) -> Self { + BlockPos::from(value.0) + } +} + +/// A component for entities that can jump. +/// +/// If this is true, the entity will try to jump every tick. It's equivalent to +/// the space key being held in vanilla. +#[derive(Clone, Copy, Component, Debug, Default, Deref, DerefMut, Eq, PartialEq)] +pub struct Jumping(pub bool); diff --git a/azalea-entity/src/plugin/indexing.rs b/azalea-entity/src/plugin/indexing.rs index edceccc7..3fba6b3c 100644 --- a/azalea-entity/src/plugin/indexing.rs +++ b/azalea-entity/src/plugin/indexing.rs @@ -5,8 +5,8 @@ use std::{ fmt::{self, Debug}, }; -use azalea_core::position::ChunkPos; -use azalea_world::{Instance, InstanceContainer, InstanceName, MinecraftEntityId}; +use azalea_core::{entity_id::MinecraftEntityId, position::ChunkPos}; +use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_ecs::prelude::*; use derive_more::{Deref, DerefMut}; use nohash_hasher::IntMap; diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs index 855b2899..03dda233 100644 --- a/azalea-entity/src/plugin/mod.rs +++ b/azalea-entity/src/plugin/mod.rs @@ -1,3 +1,4 @@ +mod components; pub mod indexing; mod relative_updates; @@ -5,21 +6,22 @@ use std::collections::HashSet; use azalea_block::{BlockState, BlockTrait, fluid_state::FluidKind, properties}; use azalea_core::{ + entity_id::MinecraftEntityId, position::{BlockPos, ChunkPos}, tick::GameTick, }; use azalea_registry::{builtin::BlockKind, tags}; -use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId}; +use azalea_world::{ChunkStorage, InstanceContainer, InstanceName}; use bevy_app::{App, Plugin, PostUpdate, Update}; use bevy_ecs::prelude::*; +pub use components::*; use derive_more::{Deref, DerefMut}; use indexing::EntityUuidIndex; pub use relative_updates::RelativeEntityUpdate; use tracing::debug; use crate::{ - Crouching, Dead, EntityKindComponent, FluidOnEyes, LocalEntity, LookDirection, OnClimbable, - Physics, Pose, Position, + FluidOnEyes, LookDirection, Physics, Pose, Position, dimensions::{EntityDimensions, calculate_dimensions}, metadata::Health, }; @@ -197,14 +199,9 @@ pub struct LoadedBy(pub HashSet<Entity>); pub fn clamp_look_direction(mut query: Query<&mut LookDirection>) { for mut look_direction in &mut query { - *look_direction = apply_clamp_look_direction(*look_direction); + *look_direction = look_direction.clamped(); } } -pub fn apply_clamp_look_direction(mut look_direction: LookDirection) -> LookDirection { - look_direction.x_rot = look_direction.x_rot.clamp(-90., 90.); - - look_direction -} /// Sets the position of the entity. /// @@ -279,11 +276,47 @@ pub fn update_in_loaded_chunk( } } -/// A component that indicates whether the client has loaded. -/// -/// This is updated by a system in `azalea-client`. -#[derive(Component)] -pub struct HasClientLoaded; +/// Get the position of the block below the entity, but a little lower. +pub fn on_pos_legacy(chunk_storage: &ChunkStorage, position: Position) -> BlockPos { + on_pos(0.2, chunk_storage, position) +} + +// int x = Mth.floor(this.position.x); +// int y = Mth.floor(this.position.y - (double)var1); +// int z = Mth.floor(this.position.z); +// BlockPos var5 = new BlockPos(x, y, z); +// if (this.level.getBlockState(var5).isAir()) { +// BlockPos var6 = var5.below(); +// BlockState var7 = this.level.getBlockState(var6); +// if (var7.is(BlockTags.FENCES) || var7.is(BlockTags.WALLS) || +// var7.getBlock() instanceof FenceGateBlock) { return var6; +// } +// } +// return var5; +pub fn on_pos(offset: f32, chunk_storage: &ChunkStorage, pos: Position) -> BlockPos { + let x = pos.x.floor() as i32; + let y = (pos.y - offset as f64).floor() as i32; + let z = pos.z.floor() as i32; + let pos = BlockPos { x, y, z }; + + // TODO: check if block below is a fence, wall, or fence gate + let block_pos = pos.down(1); + let block_state = chunk_storage.get_block_state(block_pos); + if block_state == Some(BlockState::AIR) { + let block_pos_below = block_pos.down(1); + let block_state_below = chunk_storage.get_block_state(block_pos_below); + if let Some(_block_state_below) = block_state_below { + // if block_state_below.is_fence() + // || block_state_below.is_wall() + // || block_state_below.is_fence_gate() + // { + // return block_pos_below; + // } + } + } + + pos +} #[cfg(test)] mod tests { diff --git a/azalea-entity/src/plugin/relative_updates.rs b/azalea-entity/src/plugin/relative_updates.rs index 3917c946..f80ccddc 100644 --- a/azalea-entity/src/plugin/relative_updates.rs +++ b/azalea-entity/src/plugin/relative_updates.rs @@ -17,7 +17,8 @@ use std::sync::Arc; -use azalea_world::{MinecraftEntityId, PartialInstance}; +use azalea_core::entity_id::MinecraftEntityId; +use azalea_world::PartialInstance; use bevy_ecs::prelude::*; use derive_more::{Deref, DerefMut}; use parking_lot::RwLock; |
