mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
103 lines
3.5 KiB
Rust
103 lines
3.5 KiB
Rust
use std::pin::Pin;
|
|
use std::sync::Arc;
|
|
|
|
use crate::entity::Entity;
|
|
use crate::entity::decoration::armor_stand::ArmorStandEntity;
|
|
use crate::entity::player::Player;
|
|
use crate::item::{ItemBehaviour, ItemMetadata};
|
|
use crate::server::Server;
|
|
use pumpkin_data::entity::EntityType;
|
|
use pumpkin_data::item::Item;
|
|
use pumpkin_data::item_stack::ItemStack;
|
|
use pumpkin_data::sound::{Sound, SoundCategory};
|
|
use pumpkin_data::{Block, BlockDirection};
|
|
use pumpkin_util::math::boundingbox::BoundingBox;
|
|
use pumpkin_util::math::position::BlockPos;
|
|
use pumpkin_util::math::vector3::Vector3;
|
|
use pumpkin_util::math::wrap_degrees;
|
|
|
|
pub struct ArmorStandItem;
|
|
|
|
impl ArmorStandItem {
|
|
fn calculate_placement_position(location: &BlockPos, face: BlockDirection) -> BlockPos {
|
|
match face {
|
|
BlockDirection::Up => location.offset(Vector3::new(0, 1, 0)),
|
|
BlockDirection::Down => location.offset(Vector3::new(0, -1, 0)),
|
|
BlockDirection::North => location.offset(Vector3::new(0, 0, -1)),
|
|
BlockDirection::South => location.offset(Vector3::new(0, 0, 1)),
|
|
BlockDirection::West => location.offset(Vector3::new(-1, 0, 0)),
|
|
BlockDirection::East => location.offset(Vector3::new(1, 0, 0)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ItemMetadata for ArmorStandItem {
|
|
fn ids() -> Box<[u16]> {
|
|
[Item::ARMOR_STAND.id].into()
|
|
}
|
|
}
|
|
|
|
impl ItemBehaviour for ArmorStandItem {
|
|
fn use_on_block<'a>(
|
|
&'a self,
|
|
_item: &'a mut ItemStack,
|
|
player: &'a Player,
|
|
location: BlockPos,
|
|
face: BlockDirection,
|
|
_cursor_pos: Vector3<f32>,
|
|
_block: &'a Block,
|
|
_server: &'a Server,
|
|
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
|
Box::pin(async move {
|
|
let world = player.world();
|
|
let position = Self::calculate_placement_position(&location, face).to_f64();
|
|
|
|
let bottom_center = Vector3::new(position.x, position.y, position.z);
|
|
|
|
let armor_stand_dimensions = EntityType::ARMOR_STAND.dimension;
|
|
let width = f64::from(armor_stand_dimensions[0]);
|
|
let height = f64::from(armor_stand_dimensions[1]);
|
|
|
|
let bounding_box = BoundingBox::new(
|
|
Vector3::new(
|
|
bottom_center.x - width / 2.0,
|
|
bottom_center.y,
|
|
bottom_center.z - width / 2.0,
|
|
),
|
|
Vector3::new(
|
|
bottom_center.x + width / 2.0,
|
|
bottom_center.y + height,
|
|
bottom_center.z + width / 2.0,
|
|
),
|
|
);
|
|
|
|
if world.is_space_empty(bounding_box).await
|
|
&& world.get_entities_at_box(&bounding_box).is_empty()
|
|
{
|
|
let (player_yaw, _) = player.rotation();
|
|
let rotation = ((wrap_degrees(player_yaw - 180.0) + 22.5) / 45.0).floor() * 45.0;
|
|
|
|
let entity = Entity::new(world.clone(), position, &EntityType::ARMOR_STAND);
|
|
|
|
entity.set_rotation(rotation, 0.0);
|
|
|
|
world
|
|
.play_sound(
|
|
Sound::EntityArmorStandPlace,
|
|
SoundCategory::Blocks,
|
|
&entity.pos.load(),
|
|
)
|
|
.await;
|
|
|
|
let armor_stand = ArmorStandEntity::new(entity);
|
|
|
|
world.spawn_entity(Arc::new(armor_stand)).await;
|
|
}
|
|
})
|
|
}
|
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
}
|