100 lines
4.0 KiB
Rust
100 lines
4.0 KiB
Rust
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;
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|