use std::sync::Arc; use crate::entity::Entity; use crate::entity::decoration::end_crystal::EndCrystalEntity; 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::{Block, BlockDirection}; use pumpkin_util::math::boundingbox::BoundingBox; use pumpkin_util::math::position::BlockPos; use pumpkin_util::math::vector3::Vector3; pub struct EndCrystalItem; impl ItemMetadata for EndCrystalItem { fn ids() -> Box<[u16]> { [Item::END_CRYSTAL.id].into() } } impl ItemBehaviour for EndCrystalItem { fn use_on_block( &self, item: &mut ItemStack, player: &Player, location: BlockPos, _face: BlockDirection, _cursor_pos: Vector3, _block: &Block, _server: &Server, ) { let world = player.world(); let block = world.get_block(&location); if block != &Block::OBSIDIAN && block != &Block::BEDROCK { return; } let location = location.up(); let location_vec = location.0.to_f64(); if !world.get_block_state(&location).is_air() || !world .get_entities_at_box(&BoundingBox::new( Vector3::new(location_vec.x, location_vec.y, location_vec.z), Vector3::new(location_vec.x + 1.0, location_vec.y + 2.0, location_vec.z), )) .is_empty() { return; } let entity = Entity::new(world.clone(), location.to_f64(), &EntityType::END_CRYSTAL); let end_crystal = Arc::new(EndCrystalEntity::new(entity)); world.spawn_entity(end_crystal.clone()); end_crystal.set_show_bottom(false); item.decrement_unless_creative(player.gamemode.load(), 1); if let Some(ref fight_mutex) = world.dragon_fight && let Ok(mut fight) = fight_mutex.lock() { fight.try_respawn(&world); } } fn as_any(&self) -> &dyn std::any::Any { self } }