125 lines
4.5 KiB
Rust
125 lines
4.5 KiB
Rust
use async_trait::async_trait;
|
|
use pumpkin_data::block_properties::HorizontalFacing;
|
|
use pumpkin_data::block_properties::RailShape;
|
|
use pumpkin_macros::pumpkin_block;
|
|
use pumpkin_world::BlockStateId;
|
|
use pumpkin_world::world::BlockFlags;
|
|
|
|
use crate::block::BlockBehaviour;
|
|
use crate::block::CanPlaceAtArgs;
|
|
use crate::block::OnNeighborUpdateArgs;
|
|
use crate::block::OnPlaceArgs;
|
|
use crate::block::PlacedArgs;
|
|
|
|
use super::StraightRailShapeExt;
|
|
use super::common::{can_place_rail_at, rail_placement_is_valid, update_flanking_rails_shape};
|
|
use super::{HorizontalFacingRailExt, Rail, RailElevation, RailProperties};
|
|
|
|
#[pumpkin_block("minecraft:rail")]
|
|
pub struct RailBlock;
|
|
|
|
#[async_trait]
|
|
impl BlockBehaviour for RailBlock {
|
|
async fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
|
|
let world = args.world;
|
|
let block_pos = args.position;
|
|
let mut rail_props = RailProperties::default(args.block);
|
|
rail_props.set_waterlogged(args.replacing.water_source());
|
|
|
|
let shape = if let Some(east_rail) =
|
|
Rail::find_if_unlocked(world, block_pos, HorizontalFacing::East).await
|
|
{
|
|
if Rail::find_if_unlocked(world, block_pos, HorizontalFacing::South)
|
|
.await
|
|
.is_some()
|
|
{
|
|
RailShape::SouthEast
|
|
} else if Rail::find_if_unlocked(world, block_pos, HorizontalFacing::North)
|
|
.await
|
|
.is_some()
|
|
{
|
|
RailShape::NorthEast
|
|
} else {
|
|
match Rail::find_if_unlocked(world, block_pos, HorizontalFacing::West).await {
|
|
Some(west_rail) if west_rail.elevation == RailElevation::Up => {
|
|
RailShape::AscendingWest
|
|
}
|
|
_ => {
|
|
if east_rail.elevation == RailElevation::Up {
|
|
RailShape::AscendingEast
|
|
} else {
|
|
RailShape::EastWest
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if let Some(south_rail) =
|
|
Rail::find_if_unlocked(world, block_pos, HorizontalFacing::South).await
|
|
{
|
|
if Rail::find_if_unlocked(world, block_pos, HorizontalFacing::West)
|
|
.await
|
|
.is_some()
|
|
{
|
|
RailShape::SouthWest
|
|
} else if south_rail.elevation == RailElevation::Up {
|
|
RailShape::AscendingSouth
|
|
} else {
|
|
match Rail::find_if_unlocked(world, block_pos, HorizontalFacing::North).await {
|
|
Some(north_rail) if north_rail.elevation == RailElevation::Up => {
|
|
RailShape::AscendingNorth
|
|
}
|
|
_ => RailShape::NorthSouth,
|
|
}
|
|
}
|
|
} else if let Some(west_rail) =
|
|
Rail::find_if_unlocked(world, block_pos, HorizontalFacing::West).await
|
|
{
|
|
if Rail::find_if_unlocked(world, block_pos, HorizontalFacing::North)
|
|
.await
|
|
.is_some()
|
|
{
|
|
RailShape::NorthWest
|
|
} else if west_rail.elevation == RailElevation::Up {
|
|
RailShape::AscendingWest
|
|
} else {
|
|
RailShape::EastWest
|
|
}
|
|
} else if let Some(north_rail) =
|
|
Rail::find_if_unlocked(world, block_pos, HorizontalFacing::North).await
|
|
{
|
|
if north_rail.elevation == RailElevation::Up {
|
|
RailShape::AscendingNorth
|
|
} else {
|
|
RailShape::NorthSouth
|
|
}
|
|
} else {
|
|
args.player
|
|
.living_entity
|
|
.entity
|
|
.get_horizontal_facing()
|
|
.to_rail_shape_flat()
|
|
.as_shape()
|
|
};
|
|
|
|
rail_props.set_shape(shape);
|
|
rail_props.to_state_id(args.block)
|
|
}
|
|
|
|
async fn placed(&self, args: PlacedArgs<'_>) {
|
|
update_flanking_rails_shape(args.world, args.block, args.state_id, args.position).await;
|
|
}
|
|
|
|
async fn on_neighbor_update(&self, args: OnNeighborUpdateArgs<'_>) {
|
|
if !rail_placement_is_valid(args.world, args.block, args.position).await {
|
|
args.world
|
|
.break_block(args.position, None, BlockFlags::NOTIFY_ALL)
|
|
.await;
|
|
return;
|
|
}
|
|
}
|
|
|
|
async fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
|
can_place_rail_at(args.block_accessor, args.position).await
|
|
}
|
|
}
|