use pumpkin_data::{ Block, BlockDirection, BlockState, block_properties::BlockProperties, tag::{self}, }; use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos}; use pumpkin_world::{BlockStateId, world::BlockFlags}; use crate::{ block::{ BlockBehaviour, BlockFuture, BlockMetadata, CanPlaceAtArgs, EmitsRedstonePowerArgs, GetRedstonePowerArgs, OnEntityCollisionArgs, OnNeighborUpdateArgs, OnScheduledTickArgs, OnStateReplacedArgs, }, world::World, }; use super::PressurePlate; /// This is for Normal Pressure plates, so not Gold or Iron pub struct PressurePlateBlock; type PressurePlateProps = pumpkin_data::block_properties::StonePressurePlateLikeProperties; impl BlockMetadata for PressurePlateBlock { fn ids() -> Box<[u16]> { let mut combined = Vec::new(); combined.extend_from_slice(tag::Block::MINECRAFT_WOODEN_PRESSURE_PLATES.1); combined.extend_from_slice(tag::Block::MINECRAFT_STONE_PRESSURE_PLATES.1); combined.into_boxed_slice() } } impl BlockBehaviour for PressurePlateBlock { fn on_entity_collision<'a>(&'a self, args: OnEntityCollisionArgs<'a>) -> BlockFuture<'a, ()> { Box::pin(async move { self.on_entity_collision_pp(args).await; }) } fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> { Box::pin(async move { self.on_scheduled_tick_pp(args).await; }) } fn on_state_replaced<'a>(&'a self, args: OnStateReplacedArgs<'a>) -> BlockFuture<'a, ()> { Box::pin(async move { self.on_state_replaced_pp(args).await; }) } fn get_weak_redstone_power<'a>( &'a self, args: GetRedstonePowerArgs<'a>, ) -> BlockFuture<'a, u8> { Box::pin(async move { self.get_redstone_output(args.block, args.state.id) }) } fn get_strong_redstone_power<'a>( &'a self, args: GetRedstonePowerArgs<'a>, ) -> BlockFuture<'a, u8> { Box::pin(async move { if args.direction == BlockDirection::Up { return self.get_redstone_output(args.block, args.state.id); } 0 }) } fn emits_redstone_power<'a>( &'a self, _args: EmitsRedstonePowerArgs<'a>, ) -> BlockFuture<'a, bool> { Box::pin(async move { true }) } fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> { Box::pin(async move { if !Self::can_pressure_plate_place_at(args.world, args.position).await { args.world .break_block(args.position, None, BlockFlags::NOTIFY_ALL) .await; } }) } fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { Box::pin(async move { Self::can_pressure_plate_place_at(args.world.unwrap(), args.position).await }) } } impl PressurePlate for PressurePlateBlock { fn get_redstone_output(&self, block: &Block, state: BlockStateId) -> u8 { let props = PressurePlateProps::from_state_id(state, block); if props.powered { 15 } else { 0 } } async fn calculate_redstone_output(&self, world: &World, _block: &Block, pos: &BlockPos) -> u8 { // TODO: this is bad use real box let aabb = BoundingBox::from_block(pos); if !world.get_entities_at_box(&aabb).await.is_empty() || !world.get_players_at_box(&aabb).await.is_empty() { return 15; } 0 } fn set_redstone_output( &self, block: &Block, state: &BlockState, output: u8, ) -> pumpkin_world::BlockStateId { let mut props = PressurePlateProps::from_state_id(state.id, block); props.powered = output > 0; props.to_state_id(block) } }