mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
Fully fonctionnal stairs (#776)
* Started working on stairs * Implemented locking shape to straight when sides are also stairs * Implemented locking shape to straight when sides are also stairs
This commit is contained in:
committed by
GitHub
parent
488e4de586
commit
785f47f0d4
@@ -18,6 +18,7 @@ pub(crate) mod jukebox;
|
||||
pub(crate) mod logs;
|
||||
pub(crate) mod redstone;
|
||||
pub(crate) mod signs;
|
||||
pub(crate) mod stairs;
|
||||
pub(crate) mod sugar_cane;
|
||||
pub(crate) mod tnt;
|
||||
pub(crate) mod torches;
|
||||
|
||||
165
pumpkin/src/block/blocks/stairs.rs
Normal file
165
pumpkin/src/block/blocks/stairs.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::block_properties::BlockHalf;
|
||||
use pumpkin_data::block_properties::BlockProperties;
|
||||
use pumpkin_data::block_properties::HorizontalFacing;
|
||||
use pumpkin_data::block_properties::StairShape;
|
||||
use pumpkin_data::tag::RegistryKey;
|
||||
use pumpkin_data::tag::Tagable;
|
||||
use pumpkin_data::tag::get_tag_values;
|
||||
use pumpkin_protocol::server::play::SUseItemOn;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::block::BlockDirection;
|
||||
use pumpkin_world::block::HorizontalFacingExt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::block::pumpkin_block::{BlockMetadata, PumpkinBlock};
|
||||
use crate::world::BlockFlags;
|
||||
use crate::world::World;
|
||||
use crate::{entity::player::Player, server::Server};
|
||||
|
||||
type StairsProperties = pumpkin_data::block_properties::OakStairsLikeProperties;
|
||||
|
||||
pub struct StairBlock;
|
||||
|
||||
impl BlockMetadata for StairBlock {
|
||||
fn namespace(&self) -> &'static str {
|
||||
"minecraft"
|
||||
}
|
||||
|
||||
fn ids(&self) -> &'static [&'static str] {
|
||||
get_tag_values(RegistryKey::Block, "minecraft:stairs").unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl PumpkinBlock for StairBlock {
|
||||
async fn on_place(
|
||||
&self,
|
||||
_server: &Server,
|
||||
world: &World,
|
||||
block: &Block,
|
||||
face: &BlockDirection,
|
||||
block_pos: &BlockPos,
|
||||
use_item_on: &SUseItemOn,
|
||||
player: &Player,
|
||||
_other: bool,
|
||||
) -> BlockStateId {
|
||||
let mut stair_props = StairsProperties::default(block);
|
||||
|
||||
stair_props.facing = player.living_entity.entity.get_horizontal_facing();
|
||||
stair_props.half = match face {
|
||||
BlockDirection::Up => BlockHalf::Top,
|
||||
BlockDirection::Down => BlockHalf::Bottom,
|
||||
_ => match use_item_on.cursor_pos.y {
|
||||
0.0...0.5 => BlockHalf::Bottom,
|
||||
0.5...1.0 => BlockHalf::Top,
|
||||
|
||||
// This cannot happen normally
|
||||
#[allow(clippy::match_same_arms)]
|
||||
_ => BlockHalf::Bottom,
|
||||
},
|
||||
};
|
||||
|
||||
stair_props.shape =
|
||||
compute_stair_shape(world, block_pos, stair_props.facing, stair_props.half).await;
|
||||
|
||||
stair_props.to_state_id(block)
|
||||
}
|
||||
|
||||
async fn on_neighbor_update(
|
||||
&self,
|
||||
world: &Arc<World>,
|
||||
block: &Block,
|
||||
block_pos: &BlockPos,
|
||||
_source_block: &Block,
|
||||
_notify: bool,
|
||||
) {
|
||||
let state_id = world.get_block_state_id(block_pos).await.unwrap();
|
||||
let mut stair_props = StairsProperties::from_state_id(state_id, block);
|
||||
|
||||
let new_shape =
|
||||
compute_stair_shape(world, block_pos, stair_props.facing, stair_props.half).await;
|
||||
|
||||
if stair_props.shape != new_shape {
|
||||
stair_props.shape = new_shape;
|
||||
world
|
||||
.set_block_state(
|
||||
block_pos,
|
||||
stair_props.to_state_id(block),
|
||||
BlockFlags::NOTIFY_ALL,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn compute_stair_shape(
|
||||
world: &World,
|
||||
block_pos: &BlockPos,
|
||||
facing: HorizontalFacing,
|
||||
half: BlockHalf,
|
||||
) -> StairShape {
|
||||
let right_locked = get_stair_properties_if_exists(
|
||||
world,
|
||||
&block_pos.offset(facing.rotate_clockwise().to_offset()),
|
||||
)
|
||||
.await
|
||||
.is_some_and(|other_stair_props| {
|
||||
other_stair_props.half == half && other_stair_props.facing == facing
|
||||
});
|
||||
|
||||
let left_locked = get_stair_properties_if_exists(
|
||||
world,
|
||||
&block_pos.offset(facing.rotate_counter_clockwise().to_offset()),
|
||||
)
|
||||
.await
|
||||
.is_some_and(|other_stair_props| {
|
||||
other_stair_props.half == half && other_stair_props.facing == facing
|
||||
});
|
||||
|
||||
if left_locked && right_locked {
|
||||
return StairShape::Straight;
|
||||
}
|
||||
|
||||
if let Some(other_stair_props) =
|
||||
get_stair_properties_if_exists(world, &block_pos.offset(facing.to_offset())).await
|
||||
{
|
||||
if other_stair_props.half == half {
|
||||
if !left_locked && other_stair_props.facing == facing.rotate_clockwise() {
|
||||
return StairShape::OuterRight;
|
||||
} else if !right_locked && other_stair_props.facing == facing.rotate_counter_clockwise()
|
||||
{
|
||||
return StairShape::OuterLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(other_stair_props) =
|
||||
get_stair_properties_if_exists(world, &block_pos.offset(facing.opposite().to_offset()))
|
||||
.await
|
||||
{
|
||||
if other_stair_props.half == half {
|
||||
if !right_locked && other_stair_props.facing == facing.rotate_clockwise() {
|
||||
return StairShape::InnerRight;
|
||||
} else if !left_locked && other_stair_props.facing == facing.rotate_counter_clockwise()
|
||||
{
|
||||
return StairShape::InnerLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StairShape::Straight
|
||||
}
|
||||
|
||||
async fn get_stair_properties_if_exists(
|
||||
world: &World,
|
||||
block_pos: &BlockPos,
|
||||
) -> Option<StairsProperties> {
|
||||
let (block, block_state) = world.get_block_and_block_state(block_pos).await.unwrap();
|
||||
block
|
||||
.is_tagged_with("#minecraft:stairs")
|
||||
.unwrap()
|
||||
.then(|| StairsProperties::from_state_id(block_state.id, &block))
|
||||
}
|
||||
@@ -19,6 +19,7 @@ use blocks::redstone::redstone_wire::RedstoneWireBlock;
|
||||
use blocks::redstone::repeater::RepeaterBlock;
|
||||
use blocks::redstone::target_block::TargetBlock;
|
||||
use blocks::signs::SignBlock;
|
||||
use blocks::stairs::StairBlock;
|
||||
use blocks::sugar_cane::SugarCaneBlock;
|
||||
use blocks::torches::TorchBlock;
|
||||
use blocks::{
|
||||
@@ -68,6 +69,7 @@ pub fn default_registry() -> Arc<BlockRegistry> {
|
||||
manager.register(JukeboxBlock);
|
||||
manager.register(LogBlock);
|
||||
manager.register(SignBlock);
|
||||
manager.register(StairBlock);
|
||||
manager.register(SugarCaneBlock);
|
||||
manager.register(TNTBlock);
|
||||
manager.register(TorchBlock);
|
||||
|
||||
Reference in New Issue
Block a user