diff options
Diffstat (limited to 'azalea-entity/src')
| -rwxr-xr-x | azalea-entity/src/data.rs | 2 | ||||
| -rw-r--r-- | azalea-entity/src/lib.rs | 19 | ||||
| -rw-r--r-- | azalea-entity/src/plugin/mod.rs | 71 |
3 files changed, 89 insertions, 3 deletions
diff --git a/azalea-entity/src/data.rs b/azalea-entity/src/data.rs index 83779b21..b0a05e74 100755 --- a/azalea-entity/src/data.rs +++ b/azalea-entity/src/data.rs @@ -134,7 +134,7 @@ pub struct Rotations { pub z: f32, } -#[derive(Clone, Debug, Copy, McBuf, Default, Component)] +#[derive(Clone, Debug, Copy, McBuf, Default, Component, Eq, PartialEq)] pub enum Pose { #[default] Standing = 0, diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index bf3dfc82..eb5b5b25 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -116,8 +116,13 @@ pub fn on_pos(offset: f32, chunk_storage: &ChunkStorage, pos: &Position) -> Bloc /// The Minecraft UUID of the entity. For players, this is their actual player /// UUID, and for other entities it's just random. -#[derive(Component, Deref, DerefMut, Clone, Copy)] +#[derive(Component, Deref, DerefMut, Clone, Copy, Default)] pub struct EntityUuid(Uuid); +impl EntityUuid { + pub fn new(uuid: Uuid) -> Self { + Self(uuid) + } +} impl Debug for EntityUuid { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { (self.0).fmt(f) @@ -228,6 +233,10 @@ pub struct Physics { pub bounding_box: AABB, pub has_impulse: bool, + + pub horizontal_collision: bool, + // pub minor_horizontal_collision: bool, + pub vertical_collision: bool, } impl Physics { @@ -246,6 +255,9 @@ impl Physics { dimensions, has_impulse: false, + + horizontal_collision: false, + vertical_collision: false, } } } @@ -311,6 +323,7 @@ pub struct EntityBundle { pub attributes: Attributes, pub jumping: Jumping, pub fluid_on_eyes: FluidOnEyes, + pub on_climbable: OnClimbable, } impl EntityBundle { @@ -346,6 +359,7 @@ impl EntityBundle { jumping: Jumping(false), fluid_on_eyes: FluidOnEyes(azalea_registry::Fluid::Empty), + on_climbable: OnClimbable(false), } } } @@ -373,6 +387,9 @@ impl FluidOnEyes { } } +#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)] +pub struct OnClimbable(bool); + // #[cfg(test)] // mod tests { // use super::*; diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs index 9950e6ba..4b6d9979 100644 --- a/azalea-entity/src/plugin/mod.rs +++ b/azalea-entity/src/plugin/mod.rs @@ -3,6 +3,7 @@ mod relative_updates; use std::collections::HashSet; +use azalea_block::BlockState; use azalea_core::position::{BlockPos, ChunkPos, Vec3}; use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId}; use bevy_app::{App, Plugin, PreUpdate, Update}; @@ -11,7 +12,8 @@ use derive_more::{Deref, DerefMut}; use tracing::debug; use crate::{ - metadata::Health, Dead, EyeHeight, FluidOnEyes, LocalEntity, LookDirection, Physics, Position, + metadata::Health, Dead, EyeHeight, FluidOnEyes, LocalEntity, LookDirection, OnClimbable, + Physics, Position, }; use indexing::EntityUuidIndex; @@ -48,6 +50,7 @@ impl Plugin for EntityPlugin { add_dead, clamp_look_direction, update_fluid_on_eyes, + update_on_climbable, ), ), ) @@ -106,6 +109,72 @@ pub fn update_fluid_on_eyes( } } +pub fn update_on_climbable( + mut query: Query<(&mut OnClimbable, &Position, &InstanceName)>, + instance_container: Res<InstanceContainer>, +) { + for (mut on_climbable, position, instance_name) in query.iter_mut() { + // TODO: there's currently no gamemode component that can be accessed from here, + // maybe LocalGameMode should be replaced with two components, maybe called + // EntityGameMode and PreviousGameMode? + + // if game_mode == GameMode::Spectator { + // continue; + // } + + let Some(instance) = instance_container.get(instance_name) else { + continue; + }; + + let instance = instance.read(); + + let block_pos = BlockPos::from(position); + let block_state_at_feet = instance.get_block_state(&block_pos).unwrap_or_default(); + let block_at_feet = Box::<dyn azalea_block::Block>::from(block_state_at_feet); + let registry_block_at_feet = block_at_feet.as_registry_block(); + + **on_climbable = azalea_registry::tags::blocks::CLIMBABLE.contains(®istry_block_at_feet) + || (azalea_registry::tags::blocks::TRAPDOORS.contains(®istry_block_at_feet) + && is_trapdoor_useable_as_ladder(block_state_at_feet, block_pos, &instance)); + } +} + +fn is_trapdoor_useable_as_ladder( + block_state: BlockState, + block_pos: BlockPos, + instance: &azalea_world::Instance, +) -> bool { + // trapdoor must be open + if !block_state + .property::<azalea_block::properties::Open>() + .unwrap_or_default() + { + return false; + } + + // block below must be a ladder + let block_below = instance + .get_block_state(&block_pos.down(1)) + .unwrap_or_default(); + let registry_block_below = + Box::<dyn azalea_block::Block>::from(block_below).as_registry_block(); + if registry_block_below != azalea_registry::Block::Ladder { + return false; + } + // and the ladder must be facing the same direction as the trapdoor + let ladder_facing = block_below + .property::<azalea_block::properties::Facing>() + .expect("ladder block must have facing property"); + let trapdoor_facing = block_state + .property::<azalea_block::properties::Facing>() + .expect("trapdoor block must have facing property"); + if ladder_facing != trapdoor_facing { + return false; + } + + true +} + /// A component that lists all the local player entities that have this entity /// loaded. If this is empty, the entity will be removed from the ECS. #[derive(Component, Clone, Deref, DerefMut)] |
