diff --git a/pumpkin/src/block/blocks/mod.rs b/pumpkin/src/block/blocks/mod.rs index 86d59b010..6936c21d9 100644 --- a/pumpkin/src/block/blocks/mod.rs +++ b/pumpkin/src/block/blocks/mod.rs @@ -15,6 +15,7 @@ pub(crate) mod jukebox; pub(crate) mod lever; pub(crate) mod logs; pub(crate) mod tnt; +pub(crate) mod torch; /// The standard destroy with container removes the player forcibly from the container, /// drops items to the floor, and back to the player's inventory if the item stack is in movement. diff --git a/pumpkin/src/block/blocks/torch.rs b/pumpkin/src/block/blocks/torch.rs new file mode 100644 index 000000000..88068ef66 --- /dev/null +++ b/pumpkin/src/block/blocks/torch.rs @@ -0,0 +1,177 @@ +use async_trait::async_trait; +use log::error; +use pumpkin_data::block::{ + Block, BlockProperties, EnumVariants, FurnaceLikeProperties, HorizontalFacing, + WallTorchLikeProperties, +}; +use pumpkin_macros::pumpkin_block; +use pumpkin_protocol::server::play::SUseItemOn; +use pumpkin_util::math::position::BlockPos; +use pumpkin_world::block::BlockDirection; + +use crate::{block::pumpkin_block::PumpkinBlock, server::Server, world::World}; + +#[pumpkin_block("minecraft:torch")] +pub struct TorchBlock; +#[pumpkin_block("minecraft:redstone_torch")] +pub struct RedstoneTorchBlock; +#[pumpkin_block("minecraft:soul_torch")] +pub struct SoulTorchBlock; +#[async_trait] +impl PumpkinBlock for TorchBlock { + async fn on_place( + &self, + _server: &Server, + world: &World, + block: &Block, + face: &BlockDirection, + block_pos: &BlockPos, + _use_item_on: &SUseItemOn, + player_direction: &HorizontalFacing, + _other: bool, + ) -> u16 { + if face == &BlockDirection::Down { + block.default_state_id + } else { + let props = get_wall_block_props( + world, + block, + block_pos, + face, + player_direction, + WallTorchLikeProperties::default(&Block::WALL_TORCH).to_props(), + ) + .await; + WallTorchLikeProperties::from_props(props, &Block::WALL_TORCH) + .to_state_id(&Block::WALL_TORCH) + } + } +} + +#[async_trait] +impl PumpkinBlock for RedstoneTorchBlock { + async fn on_place( + &self, + _server: &Server, + world: &World, + block: &Block, + face: &BlockDirection, + block_pos: &BlockPos, + _use_item_on: &SUseItemOn, + player_direction: &HorizontalFacing, + _other: bool, + ) -> u16 { + if face == &BlockDirection::Down { + block.default_state_id + } else { + let props = get_wall_block_props( + world, + block, + block_pos, + face, + player_direction, + FurnaceLikeProperties::default(&Block::REDSTONE_WALL_TORCH).to_props(), + ) + .await; + FurnaceLikeProperties::from_props(props, &Block::REDSTONE_WALL_TORCH) + .to_state_id(&Block::REDSTONE_WALL_TORCH) + } + } +} + +#[async_trait] +impl PumpkinBlock for SoulTorchBlock { + async fn on_place( + &self, + _server: &Server, + world: &World, + block: &Block, + face: &BlockDirection, + block_pos: &BlockPos, + _use_item_on: &SUseItemOn, + player_direction: &HorizontalFacing, + _other: bool, + ) -> u16 { + if face == &BlockDirection::Down { + block.default_state_id + } else { + let props = get_wall_block_props( + world, + block, + block_pos, + face, + player_direction, + WallTorchLikeProperties::default(&Block::SOUL_WALL_TORCH).to_props(), + ) + .await; + WallTorchLikeProperties::from_props(props, &Block::SOUL_WALL_TORCH) + .to_state_id(&Block::SOUL_WALL_TORCH) + } + } +} +async fn get_wall_block_props( + world: &World, + block: &Block, + block_pos: &BlockPos, + face: &BlockDirection, + player_direction: &HorizontalFacing, + mut block_properties: Vec<(String, String)>, +) -> Vec<(String, String)> { + let contains_facing = block_properties.iter().any(|(key, _)| key == "facing"); + + if !contains_facing { + error!("Cannot find facing property in block {}", block.name); + return Block::AIR + .properties(Block::AIR.default_state_id) + .unwrap() + .to_props(); + } + + let facing_index = block_properties + .iter() + .position(|(key, _)| key == "facing") + .unwrap(); + + match face { + BlockDirection::North + | BlockDirection::South + | BlockDirection::West + | BlockDirection::East => { + block_properties[facing_index].1 = face + .to_cardinal_direction() + .opposite() + .to_value() + .to_string(); + return block_properties; + } + BlockDirection::Up => { + let mut possible_directions = vec![]; + for bd in BlockDirection::horizontal() { + let block_offset = bd.to_offset(); + let base_block_pos = block_pos.offset(block_offset); + let base_block = world.get_block(&base_block_pos).await.unwrap(); + if base_block.id != 0 { + possible_directions.push(bd.to_cardinal_direction()); + } + } + + return if possible_directions.contains(player_direction) { + block_properties[facing_index].1 = + player_direction.opposite().to_value().to_string(); + block_properties + } else if possible_directions.is_empty() { + block_properties[facing_index].1 = + possible_directions[0].opposite().to_value().to_string(); + block_properties + } else { + Block::AIR + .properties(Block::AIR.default_state_id) + .unwrap() + .to_props() + }; + } + BlockDirection::Down => {} + } + + block_properties +} diff --git a/pumpkin/src/block/mod.rs b/pumpkin/src/block/mod.rs index c99eaa06d..58d0f807c 100644 --- a/pumpkin/src/block/mod.rs +++ b/pumpkin/src/block/mod.rs @@ -14,6 +14,7 @@ use pumpkin_util::math::vector3::Vector3; use pumpkin_world::item::ItemStack; use rand::Rng; +use crate::block::blocks::torch::{RedstoneTorchBlock, SoulTorchBlock, TorchBlock}; use crate::block::registry::BlockRegistry; use crate::entity::item::ItemEntity; use crate::world::World; @@ -35,6 +36,9 @@ pub fn default_registry() -> Arc { manager.register(ChestBlock); manager.register(TNTBlock); manager.register(LeverBlock); + manager.register(TorchBlock); + manager.register(RedstoneTorchBlock); + manager.register(SoulTorchBlock); register_door_blocks(&mut manager); register_fence_blocks(&mut manager);