From 5645eb4f6fee24809e03a88d35ec424775301e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20St=C3=A9phenne?= Date: Tue, 6 May 2025 12:21:47 -0400 Subject: [PATCH] Correct bed placement (#797) * Added bed * Changed can_place_at params to match on_place * Bed placement restrictions * Removed replacing from can_place_at, as it is handled by can_update_at * Made fire work with the on_place changes --- pumpkin/src/block/blocks/bed.rs | 140 ++++++++++++++++++ pumpkin/src/block/blocks/cactus.rs | 67 ++++++--- pumpkin/src/block/blocks/chest.rs | 10 +- pumpkin/src/block/blocks/crafting_table.rs | 2 +- pumpkin/src/block/blocks/dirt_path.rs | 34 +++-- pumpkin/src/block/blocks/doors.rs | 34 +++-- pumpkin/src/block/blocks/farmland.rs | 33 +++-- pumpkin/src/block/blocks/fence_gates.rs | 8 +- pumpkin/src/block/blocks/fences.rs | 8 +- pumpkin/src/block/blocks/fire/fire.rs | 91 +++++++----- pumpkin/src/block/blocks/fire/mod.rs | 76 ++-------- pumpkin/src/block/blocks/fire/soul_fire.rs | 73 ++++----- pumpkin/src/block/blocks/furnace.rs | 2 +- pumpkin/src/block/blocks/glass_panes.rs | 8 +- pumpkin/src/block/blocks/iron_bars.rs | 8 +- pumpkin/src/block/blocks/jukebox.rs | 2 +- pumpkin/src/block/blocks/logs.rs | 8 +- pumpkin/src/block/blocks/mod.rs | 1 + pumpkin/src/block/blocks/redstone/buttons.rs | 8 +- pumpkin/src/block/blocks/redstone/lever.rs | 8 +- pumpkin/src/block/blocks/redstone/observer.rs | 8 +- pumpkin/src/block/blocks/redstone/piston.rs | 8 +- .../blocks/redstone/rails/activator_rail.rs | 21 ++- .../blocks/redstone/rails/detector_rail.rs | 21 ++- .../blocks/redstone/rails/powered_rail.rs | 21 ++- .../src/block/blocks/redstone/rails/rail.rs | 21 ++- .../block/blocks/redstone/redstone_lamp.rs | 8 +- .../block/blocks/redstone/redstone_torch.rs | 8 +- .../block/blocks/redstone/redstone_wire.rs | 28 ++-- pumpkin/src/block/blocks/redstone/repeater.rs | 8 +- pumpkin/src/block/blocks/signs.rs | 8 +- pumpkin/src/block/blocks/slabs.rs | 8 +- pumpkin/src/block/blocks/stairs.rs | 8 +- pumpkin/src/block/blocks/sugar_cane.rs | 68 +++++---- pumpkin/src/block/blocks/torches.rs | 8 +- pumpkin/src/block/blocks/walls.rs | 8 +- pumpkin/src/block/mod.rs | 2 + pumpkin/src/block/pumpkin_block.rs | 15 +- pumpkin/src/block/registry.rs | 88 ++++++----- pumpkin/src/item/items/flint_and_steel.rs | 32 ++-- pumpkin/src/net/packet/play.rs | 18 ++- 41 files changed, 622 insertions(+), 414 deletions(-) create mode 100644 pumpkin/src/block/blocks/bed.rs diff --git a/pumpkin/src/block/blocks/bed.rs b/pumpkin/src/block/blocks/bed.rs new file mode 100644 index 000000000..d9cdfd031 --- /dev/null +++ b/pumpkin/src/block/blocks/bed.rs @@ -0,0 +1,140 @@ +use async_trait::async_trait; +use pumpkin_data::Block; +use pumpkin_data::BlockState; +use pumpkin_data::block_properties::BedPart; +use pumpkin_data::block_properties::BlockProperties; +use pumpkin_data::tag::RegistryKey; +use pumpkin_data::tag::get_tag_values; +use pumpkin_util::GameMode; +use pumpkin_util::math::position::BlockPos; +use pumpkin_world::BlockStateId; +use pumpkin_world::block::BlockDirection; +use std::sync::Arc; + +use crate::block::BlockIsReplacing; +use crate::block::pumpkin_block::{BlockMetadata, PumpkinBlock}; +use crate::entity::player::Player; +use crate::world::BlockFlags; +use pumpkin_protocol::server::play::SUseItemOn; + +use crate::server::Server; +use crate::world::World; + +type BedProperties = pumpkin_data::block_properties::WhiteBedLikeProperties; + +pub struct BedBlock; +impl BlockMetadata for BedBlock { + fn namespace(&self) -> &'static str { + "minecraft" + } + + fn ids(&self) -> &'static [&'static str] { + get_tag_values(RegistryKey::Block, "minecraft:beds").unwrap() + } +} + +#[async_trait] +impl PumpkinBlock for BedBlock { + async fn can_place_at( + &self, + _server: &Server, + world: &World, + player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + let facing = player.living_entity.entity.get_horizontal_facing(); + + world + .get_block_state(block_pos) + .await + .is_ok_and(|state| state.replaceable()) + && world + .get_block_state(&block_pos.offset(facing.to_offset())) + .await + .is_ok_and(|state| state.replaceable()) + } + + async fn on_place( + &self, + _server: &Server, + _world: &World, + player: &Player, + block: &Block, + _block_pos: &BlockPos, + _face: BlockDirection, + _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, + ) -> BlockStateId { + let mut bed_props = BedProperties::default(block); + + bed_props.facing = player.living_entity.entity.get_horizontal_facing(); + bed_props.part = BedPart::Foot; + + bed_props.to_state_id(block) + } + + async fn placed( + &self, + world: &Arc, + block: &Block, + state_id: BlockStateId, + block_pos: &BlockPos, + _old_state_id: BlockStateId, + _notify: bool, + ) { + let mut head_props = BedProperties::default(block); + head_props.facing = BedProperties::from_state_id(state_id, block).facing; + head_props.part = BedPart::Head; + + world + .set_block_state( + &block_pos.offset(head_props.facing.to_offset()), + head_props.to_state_id(block), + BlockFlags::NOTIFY_ALL | BlockFlags::SKIP_BLOCK_ADDED_CALLBACK, + ) + .await; + } + + async fn broken( + &self, + block: &Block, + player: &Arc, + block_pos: BlockPos, + _server: &Server, + world: Arc, + state: BlockState, + ) { + let bed_props = BedProperties::from_state_id(state.id, block); + let other_half_pos = if bed_props.part == BedPart::Head { + block_pos.offset(bed_props.facing.opposite().to_offset()) + } else { + block_pos.offset(bed_props.facing.to_offset()) + }; + + world + .break_block( + &other_half_pos, + Some(player.clone()), + if player.gamemode.load() == GameMode::Creative { + BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS + } else { + BlockFlags::NOTIFY_NEIGHBORS + }, + ) + .await; + } + + async fn normal_use( + &self, + _block: &Block, + _player: &Player, + _location: BlockPos, + _server: &Server, + _world: &Arc, + ) { + // Sleep + } +} diff --git a/pumpkin/src/block/blocks/cactus.rs b/pumpkin/src/block/blocks/cactus.rs index b5c3bbe2f..7598955a6 100644 --- a/pumpkin/src/block/blocks/cactus.rs +++ b/pumpkin/src/block/blocks/cactus.rs @@ -1,20 +1,23 @@ use std::sync::Arc; use async_trait::async_trait; -use pumpkin_data::tag::Tagable; -use pumpkin_data::{ - Block, - block_properties::{BlockProperties, CactusLikeProperties, EnumVariants, Integer0To15}, +use pumpkin_data::Block; +use pumpkin_data::block_properties::{ + BlockProperties, CactusLikeProperties, EnumVariants, Integer0To15, }; +use pumpkin_data::tag::Tagable; use pumpkin_macros::pumpkin_block; +use pumpkin_protocol::server::play::SUseItemOn; +use pumpkin_util::math::position::BlockPos; use pumpkin_world::BlockStateId; use pumpkin_world::block::BlockDirection; use pumpkin_world::chunk::TickPriority; use crate::block::pumpkin_block::PumpkinBlock; +use crate::entity::player::Player; +use crate::server::Server; use crate::world::BlockFlags; use crate::world::World; -use pumpkin_util::math::position::BlockPos; #[pumpkin_block("minecraft:cactus")] pub struct CactusBlock; @@ -22,7 +25,7 @@ pub struct CactusBlock; #[async_trait] impl PumpkinBlock for CactusBlock { async fn on_scheduled_tick(&self, world: &Arc, _block: &Block, pos: &BlockPos) { - if !self.can_place_at(world, pos, BlockDirection::Down).await { + if !can_place_at(world, pos).await { world.break_block(pos, None, BlockFlags::empty()).await; } } @@ -66,29 +69,47 @@ impl PumpkinBlock for CactusBlock { _neighbor_pos: &BlockPos, _neighbor_state: BlockStateId, ) -> BlockStateId { - if !self.can_place_at(world, pos, BlockDirection::Down).await { + if !can_place_at(world, pos).await { world .schedule_block_tick(block, *pos, 1, TickPriority::Normal) .await; } + state } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - // TODO: use tags - // Disallow to place any blocks nearby a cactus - for direction in BlockDirection::horizontal() { - let (block, state) = world - .get_block_and_block_state(&pos.offset(direction.to_offset())) - .await - .unwrap(); - if state.is_solid() || block == Block::LAVA { - return false; - } - } - let block = world.get_block(&pos.down()).await.unwrap(); - // TODO: use tags - (block == Block::CACTUS || block.is_tagged_with("minecraft:sand").unwrap()) - && !world.get_block_state(&pos.up()).await.unwrap().is_liquid() + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_at(world, block_pos).await } } + +async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool { + // TODO: use tags + // Disallow to place any blocks nearby a cactus + for direction in BlockDirection::horizontal() { + let (block, state) = world + .get_block_and_block_state(&block_pos.offset(direction.to_offset())) + .await + .unwrap(); + if state.is_solid() || block == Block::LAVA { + return false; + } + } + let block = world.get_block(&block_pos.down()).await.unwrap(); + // TODO: use tags + (block == Block::CACTUS || block.is_tagged_with("minecraft:sand").unwrap()) + && !world + .get_block_state(&block_pos.up()) + .await + .unwrap() + .is_liquid() +} diff --git a/pumpkin/src/block/blocks/chest.rs b/pumpkin/src/block/blocks/chest.rs index 60c1f60fe..ae8b5c8b6 100644 --- a/pumpkin/src/block/blocks/chest.rs +++ b/pumpkin/src/block/blocks/chest.rs @@ -44,12 +44,12 @@ impl PumpkinBlock for ChestBlock { &self, _server: &Server, world: &World, - block: &Block, - face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut chest_props = ChestLikeProperties::default(block); @@ -131,7 +131,7 @@ impl PumpkinBlock for ChestBlock { async fn broken( &self, block: &Block, - player: &Player, + player: &Arc, block_pos: BlockPos, server: &Server, world: Arc, diff --git a/pumpkin/src/block/blocks/crafting_table.rs b/pumpkin/src/block/blocks/crafting_table.rs index 93b1d889e..78fa5a87c 100644 --- a/pumpkin/src/block/blocks/crafting_table.rs +++ b/pumpkin/src/block/blocks/crafting_table.rs @@ -46,7 +46,7 @@ impl PumpkinBlock for CraftingTableBlock { async fn broken( &self, block: &Block, - player: &Player, + player: &Arc, location: BlockPos, server: &Server, _world: Arc, diff --git a/pumpkin/src/block/blocks/dirt_path.rs b/pumpkin/src/block/blocks/dirt_path.rs index cdfa2767d..8c8f9f3b3 100644 --- a/pumpkin/src/block/blocks/dirt_path.rs +++ b/pumpkin/src/block/blocks/dirt_path.rs @@ -31,16 +31,17 @@ impl PumpkinBlock for DirtPathBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { - if !self.can_place_at(world, pos, BlockDirection::Down).await { + if !can_place_at(world, block_pos).await { return Block::DIRT.default_state_id; } + block.default_state_id } @@ -54,9 +55,7 @@ impl PumpkinBlock for DirtPathBlock { _neighbor_pos: &BlockPos, _neighbor_state: BlockStateId, ) -> BlockStateId { - if direction == BlockDirection::Up - && !self.can_place_at(world, pos, BlockDirection::Down).await - { + if direction == BlockDirection::Up && !can_place_at(world, pos).await { world .schedule_block_tick(block, *pos, 1, TickPriority::Normal) .await; @@ -64,8 +63,21 @@ impl PumpkinBlock for DirtPathBlock { state } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - let state = world.get_block_state(&pos.up()).await.unwrap(); - !state.is_solid() // TODO: add fence gata block + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_at(world, block_pos).await } } + +async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool { + let state = world.get_block_state(&block_pos.up()).await.unwrap(); + !state.is_solid() // TODO: add fence gate block +} diff --git a/pumpkin/src/block/blocks/doors.rs b/pumpkin/src/block/blocks/doors.rs index 3086e2851..364437780 100644 --- a/pumpkin/src/block/blocks/doors.rs +++ b/pumpkin/src/block/blocks/doors.rs @@ -167,12 +167,12 @@ impl PumpkinBlock for DoorBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + use_item_on: &SUseItemOn, ) -> BlockStateId { let powered = block_receives_redstone_power(world, block_pos).await || block_receives_redstone_power(world, &block_pos.up()).await; @@ -192,18 +192,15 @@ impl PumpkinBlock for DoorBlock { async fn can_place_at( &self, + _server: &Server, world: &World, + _player: &Player, + _block: &Block, block_pos: &BlockPos, _face: BlockDirection, + _use_item_on: &SUseItemOn, ) -> bool { - world - .get_block_state(&block_pos.offset(BlockDirection::Up.to_offset())) - .await - .is_ok_and(|state| state.replaceable()) - && world - .get_block_state(&block_pos.offset(BlockDirection::Down.to_offset())) - .await - .is_ok_and(|state| state.is_solid() && state.is_full_cube()) + can_place_at(world, block_pos).await } async fn placed( @@ -328,7 +325,7 @@ impl PumpkinBlock for DoorBlock { { if lv == DoubleBlockHalf::Lower && direction == BlockDirection::Down - && !self.can_place_at(world, block_pos, direction).await + && !can_place_at(world, block_pos).await { return 0; } @@ -344,3 +341,14 @@ impl PumpkinBlock for DoorBlock { state } } + +async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool { + world + .get_block_state(&block_pos.up()) + .await + .is_ok_and(|state| state.replaceable()) + && world + .get_block_state(&block_pos.down()) + .await + .is_ok_and(|state| state.is_solid() && state.is_full_cube()) +} diff --git a/pumpkin/src/block/blocks/farmland.rs b/pumpkin/src/block/blocks/farmland.rs index 326dc8dea..f589a1d66 100644 --- a/pumpkin/src/block/blocks/farmland.rs +++ b/pumpkin/src/block/blocks/farmland.rs @@ -31,14 +31,14 @@ impl PumpkinBlock for FarmLandBlock { &self, _server: &Server, world: &World, - block: &Block, - face: BlockDirection, - pos: &BlockPos, - _use_item_on: &SUseItemOn, _player_direction: &Player, + block: &Block, + pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { - if !self.can_place_at(world, pos, face).await { + if !can_place_at(world, pos).await { return Block::DIRT.default_state_id; } block.default_state_id @@ -54,9 +54,7 @@ impl PumpkinBlock for FarmLandBlock { _neighbor_pos: &BlockPos, _neighbor_state: BlockStateId, ) -> BlockStateId { - if direction == BlockDirection::Up - && !self.can_place_at(world, pos, BlockDirection::Down).await - { + if direction == BlockDirection::Up && !can_place_at(world, pos).await { world .schedule_block_tick(block, *pos, 1, TickPriority::Normal) .await; @@ -64,8 +62,21 @@ impl PumpkinBlock for FarmLandBlock { state } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - let state = world.get_block_state(&pos.up()).await.unwrap(); - !state.is_solid() // TODO: add fence gata block + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_at(world, block_pos).await } } + +async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool { + let state = world.get_block_state(&block_pos.up()).await.unwrap(); + !state.is_solid() // TODO: add fence gate block +} diff --git a/pumpkin/src/block/blocks/fence_gates.rs b/pumpkin/src/block/blocks/fence_gates.rs index be6b85cd8..857225a64 100644 --- a/pumpkin/src/block/blocks/fence_gates.rs +++ b/pumpkin/src/block/blocks/fence_gates.rs @@ -54,12 +54,12 @@ impl PumpkinBlock for FenceGateBlock { &self, _server: &Server, _world: &World, - block: &Block, - _face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + _block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut fence_gate_props = FenceGateProperties::default(block); fence_gate_props.facing = player.living_entity.entity.get_horizontal_facing(); diff --git a/pumpkin/src/block/blocks/fences.rs b/pumpkin/src/block/blocks/fences.rs index b9847a29e..7fd75c536 100644 --- a/pumpkin/src/block/blocks/fences.rs +++ b/pumpkin/src/block/blocks/fences.rs @@ -36,12 +36,12 @@ impl PumpkinBlock for FenceBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> u16 { let mut fence_props = FenceProperties::default(block); fence_props.waterlogged = replacing.water_source(); diff --git a/pumpkin/src/block/blocks/fire/fire.rs b/pumpkin/src/block/blocks/fire/fire.rs index aca0a176e..eb213797b 100644 --- a/pumpkin/src/block/blocks/fire/fire.rs +++ b/pumpkin/src/block/blocks/fire/fire.rs @@ -1,18 +1,22 @@ +use pumpkin_data::block_properties::HorizontalAxis; +use pumpkin_registry::DimensionType; +use rand::Rng; use std::sync::Arc; +use async_trait::async_trait; +use pumpkin_data::{Block, BlockState}; +use pumpkin_macros::pumpkin_block; +use pumpkin_protocol::server::play::SUseItemOn; +use pumpkin_util::math::position::BlockPos; +use pumpkin_world::BlockStateId; +use pumpkin_world::block::BlockDirection; use pumpkin_world::chunk::TickPriority; -use rand::Rng; use crate::block::pumpkin_block::PumpkinBlock; use crate::entity::player::Player; use crate::server::Server; use crate::world::World; -use async_trait::async_trait; -use pumpkin_data::{Block, BlockState}; -use pumpkin_macros::pumpkin_block; -use pumpkin_util::math::position::BlockPos; -use pumpkin_world::BlockStateId; -use pumpkin_world::block::BlockDirection; +use crate::world::portal::NetherPortal; use super::FireBlockBase; @@ -34,18 +38,23 @@ impl PumpkinBlock for FireBlock { state_id: BlockStateId, pos: &BlockPos, old_state_id: BlockStateId, - notify: bool, + _notify: bool, ) { - FireBlockBase::placed( - &FireBlockBase, - world, - block, - state_id, - pos, - old_state_id, - notify, - ) - .await; + if old_state_id == state_id { + // Already a fire + return; + } + + let dimension = world.dimension_type; + // First lets check if we are in OverWorld or Nether, its not possible to place an Nether portal in other dimensions in Vanilla + if dimension == DimensionType::Overworld || dimension == DimensionType::TheNether { + if let Some(portal) = NetherPortal::get_new_portal(world, pos, HorizontalAxis::X).await + { + portal.create(world).await; + return; + } + } + world .schedule_block_tick( block, @@ -60,37 +69,41 @@ impl PumpkinBlock for FireBlock { &self, world: &World, _block: &Block, - state: BlockStateId, + state_id: BlockStateId, block_pos: &BlockPos, - direction: BlockDirection, + _direction: BlockDirection, _neighbor_pos: &BlockPos, _neighbor_state: BlockStateId, ) -> BlockStateId { - // TODO: add can_place_at - if self.can_place_at(world, block_pos, direction).await { - return state; + if !FireBlockBase::can_place_on(&world.get_block(&block_pos.down()).await.unwrap()) { + return Block::AIR.default_state_id; } - Block::AIR.default_state_id + + state_id + } + + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + FireBlockBase::can_place_at(world, block_pos).await } async fn broken( &self, - block: &Block, - player: &Player, - position: BlockPos, - server: &Server, + _block: &Block, + _player: &Arc, + block_pos: BlockPos, + _server: &Server, world: Arc, - state: BlockState, + _state: BlockState, ) { - FireBlockBase::broken( - &FireBlockBase, - block, - player, - position, - server, - world, - state, - ) - .await; + FireBlockBase::broken(world, block_pos).await; } } diff --git a/pumpkin/src/block/blocks/fire/mod.rs b/pumpkin/src/block/blocks/fire/mod.rs index 2a3bdec91..9584197f7 100644 --- a/pumpkin/src/block/blocks/fire/mod.rs +++ b/pumpkin/src/block/blocks/fire/mod.rs @@ -1,20 +1,12 @@ use std::sync::Arc; -use crate::block::pumpkin_block::PumpkinBlock; -use crate::entity::player::Player; -use crate::server::Server; -use crate::world::World; -use crate::world::portal::NetherPortal; -use async_trait::async_trait; -use pumpkin_data::block_properties::HorizontalAxis; +use pumpkin_data::Block; use pumpkin_data::world::WorldEvent; -use pumpkin_data::{Block, BlockState}; -use pumpkin_registry::DimensionType; use pumpkin_util::math::position::BlockPos; -use pumpkin_world::BlockStateId; -use pumpkin_world::block::BlockDirection; use soul_fire::SoulFireBlock; +use crate::world::World; + #[expect(clippy::module_inception)] pub mod fire; pub mod soul_fire; @@ -22,7 +14,7 @@ pub mod soul_fire; pub struct FireBlockBase; impl FireBlockBase { - pub async fn get_state(world: &World, pos: &BlockPos) -> Block { + pub async fn get_fire_type(world: &World, pos: &BlockPos) -> Block { let (block, _block_state) = world.get_block_and_block_state(&pos.down()).await.unwrap(); if SoulFireBlock::is_soul_base(&block) { return Block::SOUL_FIRE; @@ -30,62 +22,24 @@ impl FireBlockBase { // TODO Block::FIRE } -} -#[async_trait] -impl PumpkinBlock for FireBlockBase { - async fn placed( - &self, - world: &Arc, - _block: &Block, - state_id: BlockStateId, - pos: &BlockPos, - old_state_id: BlockStateId, - _notify: bool, - ) { - if old_state_id == state_id { - return; - } - let dimension = world.dimension_type; - // First lets check if we are in OverWorld or Nether, its not possible to place an Nether portal in other dimensions in Vanilla - if dimension == DimensionType::Overworld || dimension == DimensionType::TheNether { - if let Some(portal) = NetherPortal::get_new_portal(world, pos, HorizontalAxis::X).await - { - portal.create(world).await; - } - } + pub fn can_place_on(_block: &Block) -> bool { + // TODO: make sure the block can be lit + // block + // .is_tagged_with("minecraft:soul_fire_base_blocks") + // .unwrap() + true } - async fn can_place_at( - &self, - world: &World, - block_pos: &BlockPos, - face: BlockDirection, - ) -> bool { + pub async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool { let block_state = world.get_block_state(block_pos).await.unwrap(); - - if !block_state.is_air() { - return false; - } - let block = Self::get_state(world, block_pos).await; - - if let Some(block) = world.block_registry.get_pumpkin_block(&block) { - return block.can_place_at(world, block_pos, face).await; - } - return false; + block_state.is_air() + && Self::can_place_on(&world.get_block(&block_pos.down()).await.unwrap()) } - async fn broken( - &self, - _block: &Block, - _player: &Player, - position: BlockPos, - _server: &Server, - world: Arc, - _state: BlockState, - ) { + async fn broken(world: Arc, block_pos: BlockPos) { world - .sync_world_event(WorldEvent::FireExtinguished, position, 0) + .sync_world_event(WorldEvent::FireExtinguished, block_pos, 0) .await; } } diff --git a/pumpkin/src/block/blocks/fire/soul_fire.rs b/pumpkin/src/block/blocks/fire/soul_fire.rs index 2d4683d25..888c81e2f 100644 --- a/pumpkin/src/block/blocks/fire/soul_fire.rs +++ b/pumpkin/src/block/blocks/fire/soul_fire.rs @@ -1,17 +1,18 @@ use std::sync::Arc; +use async_trait::async_trait; use pumpkin_data::tag::Tagable; +use pumpkin_data::{Block, BlockState}; +use pumpkin_macros::pumpkin_block; +use pumpkin_protocol::server::play::SUseItemOn; +use pumpkin_util::math::position::BlockPos; +use pumpkin_world::BlockStateId; +use pumpkin_world::block::BlockDirection; use crate::block::pumpkin_block::PumpkinBlock; use crate::entity::player::Player; use crate::server::Server; use crate::world::World; -use async_trait::async_trait; -use pumpkin_data::{Block, BlockState}; -use pumpkin_macros::pumpkin_block; -use pumpkin_util::math::position::BlockPos; -use pumpkin_world::BlockStateId; -use pumpkin_world::block::BlockDirection; use super::FireBlockBase; @@ -28,70 +29,46 @@ impl SoulFireBlock { #[async_trait] impl PumpkinBlock for SoulFireBlock { - async fn placed( - &self, - world: &Arc, - block: &Block, - state_id: BlockStateId, - pos: &BlockPos, - old_state_id: BlockStateId, - notify: bool, - ) { - FireBlockBase::placed( - &FireBlockBase, - world, - block, - state_id, - pos, - old_state_id, - notify, - ) - .await; - } - async fn get_state_for_neighbor_update( &self, world: &World, _block: &Block, - state: BlockStateId, + state_id: BlockStateId, block_pos: &BlockPos, - direction: BlockDirection, + _direction: BlockDirection, _neighbor_pos: &BlockPos, _neighbor_state: BlockStateId, ) -> BlockStateId { - if self.can_place_at(world, block_pos, direction).await { - return state; + if !Self::is_soul_base(&world.get_block(&block_pos.down()).await.unwrap()) { + return Block::AIR.default_state_id; } - Block::AIR.default_state_id + + state_id } async fn can_place_at( &self, + _server: &Server, world: &World, + _player: &Player, + _block: &Block, block_pos: &BlockPos, _face: BlockDirection, + _use_item_on: &SUseItemOn, ) -> bool { - Self::is_soul_base(&world.get_block(&block_pos.down()).await.unwrap()) + FireBlockBase::can_place_at(world, block_pos).await + && Self::is_soul_base(&world.get_block(&block_pos.down()).await.unwrap()) } async fn broken( &self, - block: &Block, - player: &Player, - position: BlockPos, - server: &Server, + _block: &Block, + _player: &Arc, + block_pos: BlockPos, + _server: &Server, world: Arc, - state: BlockState, + _state: BlockState, ) { - FireBlockBase::broken( - &FireBlockBase, - block, - player, - position, - server, - world, - state, - ) - .await; + FireBlockBase::broken(world, block_pos).await; } } diff --git a/pumpkin/src/block/blocks/furnace.rs b/pumpkin/src/block/blocks/furnace.rs index 54cf18190..cbaf23ea4 100644 --- a/pumpkin/src/block/blocks/furnace.rs +++ b/pumpkin/src/block/blocks/furnace.rs @@ -46,7 +46,7 @@ impl PumpkinBlock for FurnaceBlock { async fn broken( &self, block: &Block, - player: &Player, + player: &Arc, location: BlockPos, server: &Server, _world: Arc, diff --git a/pumpkin/src/block/blocks/glass_panes.rs b/pumpkin/src/block/blocks/glass_panes.rs index b30f3f126..3b07b413c 100644 --- a/pumpkin/src/block/blocks/glass_panes.rs +++ b/pumpkin/src/block/blocks/glass_panes.rs @@ -34,12 +34,12 @@ impl PumpkinBlock for GlassPaneBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> u16 { let mut pane_props = GlassPaneProperties::default(block); pane_props.waterlogged = replacing.water_source(); diff --git a/pumpkin/src/block/blocks/iron_bars.rs b/pumpkin/src/block/blocks/iron_bars.rs index d9880006c..bfa06d5eb 100644 --- a/pumpkin/src/block/blocks/iron_bars.rs +++ b/pumpkin/src/block/blocks/iron_bars.rs @@ -25,12 +25,12 @@ impl PumpkinBlock for IronBarsBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> u16 { let mut bars_props = IronBarsProperties::default(block); bars_props.waterlogged = replacing.water_source(); diff --git a/pumpkin/src/block/blocks/jukebox.rs b/pumpkin/src/block/blocks/jukebox.rs index 03ba76fe8..edad608b9 100644 --- a/pumpkin/src/block/blocks/jukebox.rs +++ b/pumpkin/src/block/blocks/jukebox.rs @@ -112,7 +112,7 @@ impl PumpkinBlock for JukeboxBlock { async fn broken( &self, _block: &Block, - _player: &Player, + _player: &Arc, position: BlockPos, _server: &Server, world: Arc, diff --git a/pumpkin/src/block/blocks/logs.rs b/pumpkin/src/block/blocks/logs.rs index 7f538024c..83493a2c8 100644 --- a/pumpkin/src/block/blocks/logs.rs +++ b/pumpkin/src/block/blocks/logs.rs @@ -32,12 +32,12 @@ impl PumpkinBlock for LogBlock { &self, _server: &Server, _world: &World, - block: &Block, - face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + _block_pos: &BlockPos, + face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut log_props = LogProperties::default(block); log_props.axis = face.to_axis(); diff --git a/pumpkin/src/block/blocks/mod.rs b/pumpkin/src/block/blocks/mod.rs index c33a18563..d3d2ef191 100644 --- a/pumpkin/src/block/blocks/mod.rs +++ b/pumpkin/src/block/blocks/mod.rs @@ -5,6 +5,7 @@ use pumpkin_util::math::position::BlockPos; use crate::{entity::player::Player, server::Server}; +pub mod bed; pub mod cactus; pub mod chest; pub mod crafting_table; diff --git a/pumpkin/src/block/blocks/redstone/buttons.rs b/pumpkin/src/block/blocks/redstone/buttons.rs index 9f8e44f98..a05cffdb1 100644 --- a/pumpkin/src/block/blocks/redstone/buttons.rs +++ b/pumpkin/src/block/blocks/redstone/buttons.rs @@ -64,12 +64,12 @@ impl PumpkinBlock for ButtonBlock { &self, _server: &Server, _world: &World, - block: &Block, - face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + _block_pos: &BlockPos, + face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut props = ButtonLikeProperties::default(block); diff --git a/pumpkin/src/block/blocks/redstone/lever.rs b/pumpkin/src/block/blocks/redstone/lever.rs index 89c6b2754..eb7d6d385 100644 --- a/pumpkin/src/block/blocks/redstone/lever.rs +++ b/pumpkin/src/block/blocks/redstone/lever.rs @@ -45,12 +45,12 @@ impl PumpkinBlock for LeverBlock { &self, _server: &Server, _world: &World, - block: &Block, - face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + _block_pos: &BlockPos, + face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut lever_props = LeverLikeProperties::from_state_id(block.default_state_id, block); diff --git a/pumpkin/src/block/blocks/redstone/observer.rs b/pumpkin/src/block/blocks/redstone/observer.rs index 22de9caa6..cb7e805f4 100644 --- a/pumpkin/src/block/blocks/redstone/observer.rs +++ b/pumpkin/src/block/blocks/redstone/observer.rs @@ -30,12 +30,12 @@ impl PumpkinBlock for ObserverBlock { &self, _server: &Server, _world: &World, - block: &Block, - _face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + _block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut props = ObserverLikeProperties::default(block); props.facing = player.living_entity.entity.get_facing(); diff --git a/pumpkin/src/block/blocks/redstone/piston.rs b/pumpkin/src/block/blocks/redstone/piston.rs index 545c1fc12..e5d7392f7 100644 --- a/pumpkin/src/block/blocks/redstone/piston.rs +++ b/pumpkin/src/block/blocks/redstone/piston.rs @@ -35,12 +35,12 @@ impl PumpkinBlock for PistonBlock { &self, _server: &Server, _world: &World, - block: &Block, - _face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + _block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut props = PistonProps::default(block); props.extended = false; diff --git a/pumpkin/src/block/blocks/redstone/rails/activator_rail.rs b/pumpkin/src/block/blocks/redstone/rails/activator_rail.rs index c29402160..595d4023c 100644 --- a/pumpkin/src/block/blocks/redstone/rails/activator_rail.rs +++ b/pumpkin/src/block/blocks/redstone/rails/activator_rail.rs @@ -29,12 +29,12 @@ impl PumpkinBlock for ActivatorRailBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut rail_props = RailProperties::default(block); let player_facing = player.living_entity.entity.get_horizontal_facing(); @@ -74,7 +74,16 @@ impl PumpkinBlock for ActivatorRailBlock { } } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - can_place_rail_at(world, pos).await + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_rail_at(world, block_pos).await } } diff --git a/pumpkin/src/block/blocks/redstone/rails/detector_rail.rs b/pumpkin/src/block/blocks/redstone/rails/detector_rail.rs index 2c9d41903..4e4d1d9ba 100644 --- a/pumpkin/src/block/blocks/redstone/rails/detector_rail.rs +++ b/pumpkin/src/block/blocks/redstone/rails/detector_rail.rs @@ -29,12 +29,12 @@ impl PumpkinBlock for DetectorRailBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut rail_props = RailProperties::default(block); let player_facing = player.living_entity.entity.get_horizontal_facing(); @@ -74,7 +74,16 @@ impl PumpkinBlock for DetectorRailBlock { } } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - can_place_rail_at(world, pos).await + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_rail_at(world, block_pos).await } } diff --git a/pumpkin/src/block/blocks/redstone/rails/powered_rail.rs b/pumpkin/src/block/blocks/redstone/rails/powered_rail.rs index b6d98629d..b6000a89d 100644 --- a/pumpkin/src/block/blocks/redstone/rails/powered_rail.rs +++ b/pumpkin/src/block/blocks/redstone/rails/powered_rail.rs @@ -29,12 +29,12 @@ impl PumpkinBlock for PoweredRailBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut rail_props = RailProperties::default(block); let player_facing = player.living_entity.entity.get_horizontal_facing(); @@ -74,7 +74,16 @@ impl PumpkinBlock for PoweredRailBlock { } } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - can_place_rail_at(world, pos).await + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_rail_at(world, block_pos).await } } diff --git a/pumpkin/src/block/blocks/redstone/rails/rail.rs b/pumpkin/src/block/blocks/redstone/rails/rail.rs index dbf20ccb2..08ae0fdbe 100644 --- a/pumpkin/src/block/blocks/redstone/rails/rail.rs +++ b/pumpkin/src/block/blocks/redstone/rails/rail.rs @@ -29,12 +29,12 @@ impl PumpkinBlock for RailBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut rail_props = RailProperties::default(block); rail_props.set_waterlogged(replacing.water_source()); @@ -146,7 +146,16 @@ impl PumpkinBlock for RailBlock { } } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - can_place_rail_at(world, pos).await + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_rail_at(world, block_pos).await } } diff --git a/pumpkin/src/block/blocks/redstone/redstone_lamp.rs b/pumpkin/src/block/blocks/redstone/redstone_lamp.rs index 11b159d27..c029c74f8 100644 --- a/pumpkin/src/block/blocks/redstone/redstone_lamp.rs +++ b/pumpkin/src/block/blocks/redstone/redstone_lamp.rs @@ -27,12 +27,12 @@ impl PumpkinBlock for RedstoneLamp { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut props = RedstoneLampProperties::default(block); props.lit = block_receives_redstone_power(world, block_pos).await; diff --git a/pumpkin/src/block/blocks/redstone/redstone_torch.rs b/pumpkin/src/block/blocks/redstone/redstone_torch.rs index d08fd7d5a..3eebd530e 100644 --- a/pumpkin/src/block/blocks/redstone/redstone_torch.rs +++ b/pumpkin/src/block/blocks/redstone/redstone_torch.rs @@ -41,12 +41,12 @@ impl PumpkinBlock for RedstoneTorchBlock { &self, _server: &Server, world: &World, - _block: &Block, - face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + _block: &Block, + block_pos: &BlockPos, + face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { if face.is_horizontal() { let mut torch_props = RWallTorchProps::default(&Block::REDSTONE_WALL_TORCH); diff --git a/pumpkin/src/block/blocks/redstone/redstone_wire.rs b/pumpkin/src/block/blocks/redstone/redstone_wire.rs index b192670ee..b983ce5f0 100644 --- a/pumpkin/src/block/blocks/redstone/redstone_wire.rs +++ b/pumpkin/src/block/blocks/redstone/redstone_wire.rs @@ -30,29 +30,29 @@ pub struct RedstoneWireBlock; #[async_trait] impl PumpkinBlock for RedstoneWireBlock { - // Start of placement - async fn can_place_at( &self, + _server: &Server, world: &World, + _player: &Player, + _block: &Block, block_pos: &BlockPos, _face: BlockDirection, + _use_item_on: &SUseItemOn, ) -> bool { - let floor = world.get_block_state(&block_pos.down()).await.unwrap(); - // TODO: Only check face instead of block - return floor.is_full_cube(); + can_place_at(world, block_pos).await } async fn on_place( &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut wire = RedstoneWireProperties::default(block); wire.power = Integer0To15::from_index(calculate_power(world, block_pos).await.into()); @@ -201,7 +201,7 @@ impl PumpkinBlock for RedstoneWireBlock { _source_block: &Block, _notify: bool, ) { - if self.can_place_at(world, pos, BlockDirection::Down).await { + if can_place_at(world, pos).await { let state = world.get_block_state(pos).await.unwrap(); let mut wire = RedstoneWireProperties::from_state_id(state.id, block); let new_power = calculate_power(world, pos).await; @@ -268,7 +268,7 @@ impl PumpkinBlock for RedstoneWireBlock { async fn broken( &self, _block: &Block, - _player: &Player, + _player: &Arc, location: BlockPos, _server: &Server, world: Arc, @@ -278,6 +278,12 @@ impl PumpkinBlock for RedstoneWireBlock { } } +async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool { + let floor = world.get_block_state(&block_pos.down()).await.unwrap(); + // TODO: Only check face instead of block + floor.is_full_cube() +} + async fn on_use(wire: RedstoneWireProperties, world: &Arc, block_pos: &BlockPos) -> bool { if is_cross(wire) || is_dot(wire) { let mut new_wire = if is_cross(wire) { diff --git a/pumpkin/src/block/blocks/redstone/repeater.rs b/pumpkin/src/block/blocks/redstone/repeater.rs index 42ea3b715..a2d27a25d 100644 --- a/pumpkin/src/block/blocks/redstone/repeater.rs +++ b/pumpkin/src/block/blocks/redstone/repeater.rs @@ -32,12 +32,12 @@ impl PumpkinBlock for RepeaterBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { let mut props = RepeaterProperties::default(block); let dir = player diff --git a/pumpkin/src/block/blocks/signs.rs b/pumpkin/src/block/blocks/signs.rs index 0b63d5c6a..05e7bec22 100644 --- a/pumpkin/src/block/blocks/signs.rs +++ b/pumpkin/src/block/blocks/signs.rs @@ -36,12 +36,12 @@ impl PumpkinBlock for SignBlock { &self, _server: &Server, _world: &World, - block: &Block, - _face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + _block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> u16 { let mut sign_props = SignProperties::default(block); sign_props.waterlogged = replacing.water_source(); diff --git a/pumpkin/src/block/blocks/slabs.rs b/pumpkin/src/block/blocks/slabs.rs index 83be7fd47..cbcad7b10 100644 --- a/pumpkin/src/block/blocks/slabs.rs +++ b/pumpkin/src/block/blocks/slabs.rs @@ -34,12 +34,12 @@ impl PumpkinBlock for SlabBlock { &self, _server: &Server, _world: &World, - block: &Block, - face: BlockDirection, - _block_pos: &BlockPos, - use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + _block_pos: &BlockPos, + face: BlockDirection, replacing: BlockIsReplacing, + use_item_on: &SUseItemOn, ) -> BlockStateId { if let BlockIsReplacing::Itself(state_id) = replacing { let mut slab_props = SlabProperties::from_state_id(state_id, block); diff --git a/pumpkin/src/block/blocks/stairs.rs b/pumpkin/src/block/blocks/stairs.rs index a47d0d266..31e2ed6dd 100644 --- a/pumpkin/src/block/blocks/stairs.rs +++ b/pumpkin/src/block/blocks/stairs.rs @@ -39,12 +39,12 @@ impl PumpkinBlock for StairBlock { &self, _server: &Server, world: &World, - block: &Block, - face: BlockDirection, - block_pos: &BlockPos, - use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + face: BlockDirection, replacing: BlockIsReplacing, + use_item_on: &SUseItemOn, ) -> BlockStateId { let mut stair_props = StairsProperties::default(block); stair_props.waterlogged = replacing.water_source(); diff --git a/pumpkin/src/block/blocks/sugar_cane.rs b/pumpkin/src/block/blocks/sugar_cane.rs index 101d8f439..28de7aa4a 100644 --- a/pumpkin/src/block/blocks/sugar_cane.rs +++ b/pumpkin/src/block/blocks/sugar_cane.rs @@ -1,20 +1,24 @@ use std::sync::Arc; use async_trait::async_trait; +use pumpkin_data::block_properties::HorizontalFacing; use pumpkin_data::tag::Tagable; use pumpkin_data::{ Block, block_properties::{BlockProperties, CactusLikeProperties, EnumVariants, Integer0To15}, }; use pumpkin_macros::pumpkin_block; +use pumpkin_protocol::server::play::SUseItemOn; +use pumpkin_util::math::position::BlockPos; use pumpkin_world::BlockStateId; use pumpkin_world::block::BlockDirection; use pumpkin_world::chunk::TickPriority; use crate::block::pumpkin_block::PumpkinBlock; +use crate::entity::player::Player; +use crate::server::Server; use crate::world::BlockFlags; use crate::world::World; -use pumpkin_util::math::position::BlockPos; #[pumpkin_block("minecraft:sugar_cane")] pub struct SugarCaneBlock; @@ -22,7 +26,7 @@ pub struct SugarCaneBlock; #[async_trait] impl PumpkinBlock for SugarCaneBlock { async fn on_scheduled_tick(&self, world: &Arc, _block: &Block, pos: &BlockPos) { - if !self.can_place_at(world, pos, BlockDirection::Down).await { + if !can_place_at(world, pos).await { world.break_block(pos, None, BlockFlags::empty()).await; } } @@ -66,7 +70,7 @@ impl PumpkinBlock for SugarCaneBlock { _neighbor_pos: &BlockPos, _neighbor_state: BlockStateId, ) -> BlockStateId { - if !self.can_place_at(world, pos, BlockDirection::Down).await { + if !can_place_at(world, pos).await { world .schedule_block_tick(block, *pos, 1, TickPriority::Normal) .await; @@ -74,27 +78,41 @@ impl PumpkinBlock for SugarCaneBlock { state } - async fn can_place_at(&self, world: &World, pos: &BlockPos, _face: BlockDirection) -> bool { - let block = world.get_block(&pos.down()).await.unwrap(); - - if block == Block::SUGAR_CANE { - return true; - } - - if block.is_tagged_with("minecraft:dirt").unwrap() - || block.is_tagged_with("minecraft:sand").unwrap() - { - for direction in BlockDirection::horizontal() { - let block = world - .get_block(&pos.down().offset(direction.to_offset())) - .await - .unwrap(); - if block == Block::WATER || block == Block::FROSTED_ICE { - return true; - } - } - } - - false + async fn can_place_at( + &self, + _server: &Server, + world: &World, + _player: &Player, + _block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, + _use_item_on: &SUseItemOn, + ) -> bool { + can_place_at(world, block_pos).await } } + +async fn can_place_at(world: &World, block_pos: &BlockPos) -> bool { + let block_below = world.get_block(&block_pos.down()).await.unwrap(); + + if block_below == Block::SUGAR_CANE { + return true; + } + + if block_below.is_tagged_with("minecraft:dirt").unwrap() + || block_below.is_tagged_with("minecraft:sand").unwrap() + { + for direction in HorizontalFacing::all() { + let block = world + .get_block(&block_pos.down().offset(direction.to_offset())) + .await + .unwrap(); + + if block == Block::WATER || block == Block::FROSTED_ICE { + return true; + } + } + } + + false +} diff --git a/pumpkin/src/block/blocks/torches.rs b/pumpkin/src/block/blocks/torches.rs index 97564388e..12b248881 100644 --- a/pumpkin/src/block/blocks/torches.rs +++ b/pumpkin/src/block/blocks/torches.rs @@ -33,12 +33,12 @@ impl PumpkinBlock for TorchBlock { &self, _server: &Server, _world: &World, - block: &Block, - face: BlockDirection, - _block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + _block_pos: &BlockPos, + face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { if face.is_horizontal() { let wall_block = match block.name { diff --git a/pumpkin/src/block/blocks/walls.rs b/pumpkin/src/block/blocks/walls.rs index 9fbc5c013..0ff044755 100644 --- a/pumpkin/src/block/blocks/walls.rs +++ b/pumpkin/src/block/blocks/walls.rs @@ -41,12 +41,12 @@ impl PumpkinBlock for WallBlock { &self, _server: &Server, world: &World, - block: &Block, - _face: BlockDirection, - block_pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + block_pos: &BlockPos, + _face: BlockDirection, replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> u16 { let mut wall_props = WallProperties::default(block); wall_props.waterlogged = replacing.water_source(); diff --git a/pumpkin/src/block/mod.rs b/pumpkin/src/block/mod.rs index 98fce3865..d4ac147b1 100644 --- a/pumpkin/src/block/mod.rs +++ b/pumpkin/src/block/mod.rs @@ -1,3 +1,4 @@ +use blocks::bed::BedBlock; use blocks::cactus::CactusBlock; use blocks::dirt_path::DirtPathBlock; use blocks::doors::DoorBlock; @@ -64,6 +65,7 @@ pub fn default_registry() -> Arc { let mut manager = BlockRegistry::default(); // Blocks + manager.register(BedBlock); manager.register(CactusBlock); manager.register(ChestBlock); manager.register(CraftingTableBlock); diff --git a/pumpkin/src/block/pumpkin_block.rs b/pumpkin/src/block/pumpkin_block.rs index 948ec62b8..d514a2d8b 100644 --- a/pumpkin/src/block/pumpkin_block.rs +++ b/pumpkin/src/block/pumpkin_block.rs @@ -61,23 +61,28 @@ pub trait PumpkinBlock: Send + Sync { &self, _server: &Server, _world: &World, - block: &Block, - _face: BlockDirection, - _pos: &BlockPos, - _use_item_on: &SUseItemOn, _player: &Player, + block: &Block, + _block_pos: &BlockPos, + _face: BlockDirection, _replacing: BlockIsReplacing, + _use_item_on: &SUseItemOn, ) -> BlockStateId { block.default_state_id } async fn random_tick(&self, _block: &Block, _world: &Arc, _pos: &BlockPos) {} + #[allow(clippy::too_many_arguments)] async fn can_place_at( &self, + _server: &Server, _world: &World, + _player: &Player, + _block: &Block, _block_pos: &BlockPos, _face: BlockDirection, + _use_item_on: &SUseItemOn, ) -> bool { true } @@ -120,7 +125,7 @@ pub trait PumpkinBlock: Send + Sync { async fn broken( &self, _block: &Block, - _player: &Player, + _player: &Arc, _location: BlockPos, _server: &Server, _world: Arc, diff --git a/pumpkin/src/block/registry.rs b/pumpkin/src/block/registry.rs index 477805492..5f42a1964 100644 --- a/pumpkin/src/block/registry.rs +++ b/pumpkin/src/block/registry.rs @@ -97,17 +97,55 @@ impl BlockRegistry { BlockActionResult::Continue } + #[allow(clippy::too_many_arguments)] + pub async fn can_place_at( + &self, + server: &Server, + world: &World, + player: &Player, + block: &Block, + block_pos: &BlockPos, + face: BlockDirection, + use_item_on: &SUseItemOn, + ) -> bool { + let pumpkin_block = self.get_pumpkin_block(block); + if let Some(pumpkin_block) = pumpkin_block { + return pumpkin_block + .can_place_at(server, world, player, block, block_pos, face, use_item_on) + .await; + } + true + } + + pub async fn can_update_at( + &self, + world: &World, + block: &Block, + state_id: BlockStateId, + block_pos: &BlockPos, + face: BlockDirection, + use_item_on: &SUseItemOn, + ) -> bool { + let pumpkin_block = self.get_pumpkin_block(block); + if let Some(pumpkin_block) = pumpkin_block { + return pumpkin_block + .can_update_at(world, block, state_id, block_pos, face, use_item_on) + .await; + } + false + } + #[allow(clippy::too_many_arguments)] pub async fn on_place( &self, server: &Server, world: &World, - block: &Block, - face: BlockDirection, - block_pos: &BlockPos, - use_item_on: &SUseItemOn, player: &Player, + block: &Block, + block_pos: &BlockPos, + face: BlockDirection, replacing: BlockIsReplacing, + use_item_on: &SUseItemOn, ) -> BlockStateId { let pumpkin_block = self.get_pumpkin_block(block); if let Some(pumpkin_block) = pumpkin_block { @@ -115,12 +153,12 @@ impl BlockRegistry { .on_place( server, world, - block, - face, - block_pos, - use_item_on, player, + block, + block_pos, + face, replacing, + use_item_on, ) .await; } @@ -144,38 +182,6 @@ impl BlockRegistry { } } - pub async fn can_place_at( - &self, - world: &World, - block: &Block, - block_pos: &BlockPos, - face: BlockDirection, - ) -> bool { - let pumpkin_block = self.get_pumpkin_block(block); - if let Some(pumpkin_block) = pumpkin_block { - return pumpkin_block.can_place_at(world, block_pos, face).await; - } - true - } - - pub async fn can_update_at( - &self, - world: &World, - block: &Block, - state_id: BlockStateId, - block_pos: &BlockPos, - face: BlockDirection, - use_item_on: &SUseItemOn, - ) -> bool { - let pumpkin_block = self.get_pumpkin_block(block); - if let Some(pumpkin_block) = pumpkin_block { - return pumpkin_block - .can_update_at(world, block, state_id, block_pos, face, use_item_on) - .await; - } - false - } - pub async fn on_placed( &self, world: &Arc, @@ -214,7 +220,7 @@ impl BlockRegistry { &self, world: Arc, block: &Block, - player: &Player, + player: &Arc, location: BlockPos, server: &Server, state: BlockState, diff --git a/pumpkin/src/item/items/flint_and_steel.rs b/pumpkin/src/item/items/flint_and_steel.rs index a608c0054..c411be85c 100644 --- a/pumpkin/src/item/items/flint_and_steel.rs +++ b/pumpkin/src/item/items/flint_and_steel.rs @@ -1,14 +1,14 @@ -use crate::block::blocks::fire::FireBlockBase; -use crate::block::pumpkin_block::PumpkinBlock; -use crate::entity::player::Player; -use crate::item::pumpkin_item::{ItemMetadata, PumpkinItem}; -use crate::server::Server; -use crate::world::BlockFlags; use async_trait::async_trait; use pumpkin_data::Block; use pumpkin_data::item::Item; use pumpkin_util::math::position::BlockPos; -use pumpkin_world::block::{BlockDirection, HorizontalFacingExt}; +use pumpkin_world::block::BlockDirection; + +use crate::block::blocks::fire::FireBlockBase; +use crate::entity::player::Player; +use crate::item::pumpkin_item::{ItemMetadata, PumpkinItem}; +use crate::server::Server; +use crate::world::BlockFlags; pub struct FlintAndSteelItem; @@ -32,21 +32,11 @@ impl PumpkinItem for FlintAndSteelItem { // TODO: check CampfireBlock, CandleBlock and CandleCakeBlock let world = player.world().await; let pos = location.offset(face.to_offset()); - if FireBlockBase::can_place_at( - &FireBlockBase, - &world, - &pos, - player - .living_entity - .entity - .get_horizontal_facing() - .to_block_direction(), - ) - .await - { - let state = FireBlockBase::get_state(&world, &pos).await; + if FireBlockBase::can_place_at(&world, &pos).await { + let fire_block = FireBlockBase::get_fire_type(&world, &pos).await; + world - .set_block_state(&pos, state.default_state_id, BlockFlags::NOTIFY_ALL) + .set_block_state(&pos, fire_block.default_state_id, BlockFlags::NOTIFY_ALL) .await; // TODO } diff --git a/pumpkin/src/net/packet/play.rs b/pumpkin/src/net/packet/play.rs index cb7b5fef9..e6adcce24 100644 --- a/pumpkin/src/net/packet/play.rs +++ b/pumpkin/src/net/packet/play.rs @@ -1766,7 +1766,15 @@ impl Player { if !server .block_registry - .can_place_at(world, &block, &final_block_pos, face) + .can_place_at( + server, + world, + self, + &block, + &final_block_pos, + final_face, + &use_item_on, + ) .await { return Ok(false); @@ -1777,12 +1785,12 @@ impl Player { .on_place( server, world, - &block, - final_face, - &final_block_pos, - &use_item_on, self, + &block, + &final_block_pos, + final_face, replacing, + &use_item_on, ) .await;