Pumpkin/pumpkin/src/block/blocks/ladder.rs
2026-01-13 23:36:49 +01:00

94 lines
3.1 KiB
Rust

use crate::block::{
BlockBehaviour, BlockFuture, CanPlaceAtArgs, GetStateForNeighborUpdateArgs, OnPlaceArgs,
OnScheduledTickArgs,
};
use crate::world::World;
use pumpkin_data::block_properties::HorizontalFacing;
use pumpkin_data::block_properties::{BlockProperties, LadderLikeProperties};
use pumpkin_data::{BlockDirection, HorizontalFacingExt};
use pumpkin_macros::pumpkin_block;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::BlockStateId;
use pumpkin_world::tick::TickPriority;
use pumpkin_world::world::BlockFlags;
#[pumpkin_block("minecraft:ladder")]
pub struct LadderBlock;
impl BlockBehaviour for LadderBlock {
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
Box::pin(async move {
let mut props = LadderLikeProperties::default(args.block);
props.facing = args.direction.opposite().to_cardinal_direction();
props.to_state_id(args.block)
})
}
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
Box::pin(async move {
let props = LadderLikeProperties::from_state_id(args.state.id, args.block);
args.block_accessor
.get_block_state(&args.use_item_on.unwrap().position)
.await
.is_side_solid(props.facing.opposite().to_block_direction())
})
}
fn get_state_for_neighbor_update<'a>(
&'a self,
args: GetStateForNeighborUpdateArgs<'a>,
) -> BlockFuture<'a, BlockStateId> {
Box::pin(async move {
if !can_place_at(args.world, args.position).await {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
}
args.state_id
})
}
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
if !can_place_at(args.world, args.position).await {
args.world
.break_block(args.position, None, BlockFlags::empty())
.await;
}
})
}
}
async fn can_place_at(world: &World, position: &BlockPos) -> bool {
let props = LadderLikeProperties::from_state_id(
world.get_block_state_id(position).await,
world.get_block(position).await,
);
let pos;
let direction;
match props.r#facing {
HorizontalFacing::North => {
pos = position.add(0, 0, 1);
direction = BlockDirection::North;
}
HorizontalFacing::South => {
pos = position.add(0, 0, -1);
direction = BlockDirection::South;
}
HorizontalFacing::West => {
pos = position.add(1, 0, 0);
direction = BlockDirection::West;
}
HorizontalFacing::East => {
pos = position.add(-1, 0, 0);
direction = BlockDirection::East;
}
}
world
.get_block_state(&pos)
.await
.is_side_solid(direction.opposite())
&& direction.is_horizontal()
}