use pumpkin_data::{Block, BlockDirection, BlockStateId, entity::EntityType, world::WorldEvent}; use pumpkin_macros::pumpkin_block; use pumpkin_world::world::BlockFlags; use crate::{ block::{ BlockBehaviour, BlockFuture, OnPlaceArgs, PlacedArgs, blocks::skull_block::SkullBlock, }, entity::{Entity, boss::wither::WitherEntity}, }; #[pumpkin_block("wither_skeleton_skull")] pub struct WitherSkeletonSkullBlock; impl BlockBehaviour for WitherSkeletonSkullBlock { fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> { SkullBlock::on_place(&SkullBlock, args) } fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> { Box::pin(async move { let entity = crate::block::entities::skull::SkullBlockEntity::new(*args.position); args.world.add_block_entity(std::sync::Arc::new(entity)); let world = args.world; let pos = args.position; let is_soul_block = |block: &Block| block == &Block::SOUL_SAND || block == &Block::SOUL_SOIL; let is_skull = |block: &Block| block == &Block::WITHER_SKELETON_SKULL; for dir in [BlockDirection::North, BlockDirection::West] { let opposite = dir.opposite(); for offset in 0..3 { let center_skull_pos = match offset { 0 => *pos, 1 => pos.offset(opposite.to_offset()), 2 => pos.offset(dir.to_offset()), _ => { tracing::error!("Invalid offset in wither skull check: {}", offset); *pos } }; let top_middle = center_skull_pos.down(); let base = top_middle.down(); let arm1 = top_middle.offset(dir.to_offset()); let arm2 = top_middle.offset(opposite.to_offset()); let skull1_pos = arm1.up(); let skull2_pos = arm2.up(); if is_soul_block(world.get_block(&top_middle)) && is_soul_block(world.get_block(&base)) && is_soul_block(world.get_block(&arm1)) && is_soul_block(world.get_block(&arm2)) && is_skull(world.get_block(¢er_skull_pos)) && is_skull(world.get_block(&skull1_pos)) && is_skull(world.get_block(&skull2_pos)) { let pattern = [ center_skull_pos, skull1_pos, skull2_pos, top_middle, arm1, arm2, base, ]; for p in pattern { world .set_block_state( &p, Block::AIR.default_state.id, BlockFlags::NOTIFY_ALL, ) .await; world.sync_world_event( WorldEvent::ParticlesDestroyBlock, p, Block::SOUL_SAND.default_state.id.as_u16().into(), ); } let entity = Entity::new( world.clone(), top_middle.to_centered_f64(), &EntityType::WITHER, ); let wither = WitherEntity::new(entity); wither.make_invulnerable(); world.spawn_entity(wither).await; return; } } } }) } }