aboutsummaryrefslogtreecommitdiff
path: root/azalea-entity/src
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2026-01-12 02:09:41 -0600
committerGitHub <noreply@github.com>2026-01-12 02:09:41 -0600
commit1accbac964168af5fa0d87cb170389f0a9d01363 (patch)
tree1509b26c19beaa23a492289f6bf00d3958be44d5 /azalea-entity/src
parent58339b9d229592dee40e15b8648fe4075cc391f4 (diff)
downloadazalea-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.rs6
-rw-r--r--azalea-entity/src/data.rs4
-rw-r--r--azalea-entity/src/dimensions.rs6
-rw-r--r--azalea-entity/src/effects.rs6
-rw-r--r--azalea-entity/src/inventory.rs7
-rw-r--r--azalea-entity/src/lib.rs229
-rw-r--r--azalea-entity/src/particle.rs7
-rw-r--r--azalea-entity/src/plugin/components.rs151
-rw-r--r--azalea-entity/src/plugin/indexing.rs4
-rw-r--r--azalea-entity/src/plugin/mod.rs61
-rw-r--r--azalea-entity/src/plugin/relative_updates.rs3
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;