mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
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
This commit is contained in:
committed by
GitHub
parent
1b78299193
commit
5645eb4f6f
140
pumpkin/src/block/blocks/bed.rs
Normal file
140
pumpkin/src/block/blocks/bed.rs
Normal file
@@ -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<World>,
|
||||
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<Player>,
|
||||
block_pos: BlockPos,
|
||||
_server: &Server,
|
||||
world: Arc<World>,
|
||||
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<World>,
|
||||
) {
|
||||
// Sleep
|
||||
}
|
||||
}
|
||||
@@ -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<World>, _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()
|
||||
}
|
||||
|
||||
@@ -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<Player>,
|
||||
block_pos: BlockPos,
|
||||
server: &Server,
|
||||
world: Arc<World>,
|
||||
|
||||
@@ -46,7 +46,7 @@ impl PumpkinBlock for CraftingTableBlock {
|
||||
async fn broken(
|
||||
&self,
|
||||
block: &Block,
|
||||
player: &Player,
|
||||
player: &Arc<Player>,
|
||||
location: BlockPos,
|
||||
server: &Server,
|
||||
_world: Arc<World>,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<Player>,
|
||||
block_pos: BlockPos,
|
||||
_server: &Server,
|
||||
world: Arc<World>,
|
||||
state: BlockState,
|
||||
_state: BlockState,
|
||||
) {
|
||||
FireBlockBase::broken(
|
||||
&FireBlockBase,
|
||||
block,
|
||||
player,
|
||||
position,
|
||||
server,
|
||||
world,
|
||||
state,
|
||||
)
|
||||
.await;
|
||||
FireBlockBase::broken(world, block_pos).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<World>,
|
||||
_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<World>,
|
||||
_state: BlockState,
|
||||
) {
|
||||
async fn broken(world: Arc<World>, block_pos: BlockPos) {
|
||||
world
|
||||
.sync_world_event(WorldEvent::FireExtinguished, position, 0)
|
||||
.sync_world_event(WorldEvent::FireExtinguished, block_pos, 0)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<World>,
|
||||
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<Player>,
|
||||
block_pos: BlockPos,
|
||||
_server: &Server,
|
||||
world: Arc<World>,
|
||||
state: BlockState,
|
||||
_state: BlockState,
|
||||
) {
|
||||
FireBlockBase::broken(
|
||||
&FireBlockBase,
|
||||
block,
|
||||
player,
|
||||
position,
|
||||
server,
|
||||
world,
|
||||
state,
|
||||
)
|
||||
.await;
|
||||
FireBlockBase::broken(world, block_pos).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ impl PumpkinBlock for FurnaceBlock {
|
||||
async fn broken(
|
||||
&self,
|
||||
block: &Block,
|
||||
player: &Player,
|
||||
player: &Arc<Player>,
|
||||
location: BlockPos,
|
||||
server: &Server,
|
||||
_world: Arc<World>,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -112,7 +112,7 @@ impl PumpkinBlock for JukeboxBlock {
|
||||
async fn broken(
|
||||
&self,
|
||||
_block: &Block,
|
||||
_player: &Player,
|
||||
_player: &Arc<Player>,
|
||||
position: BlockPos,
|
||||
_server: &Server,
|
||||
world: Arc<World>,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Player>,
|
||||
location: BlockPos,
|
||||
_server: &Server,
|
||||
world: Arc<World>,
|
||||
@@ -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<World>, block_pos: &BlockPos) -> bool {
|
||||
if is_cross(wire) || is_dot(wire) {
|
||||
let mut new_wire = if is_cross(wire) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<World>, _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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<BlockRegistry> {
|
||||
let mut manager = BlockRegistry::default();
|
||||
|
||||
// Blocks
|
||||
manager.register(BedBlock);
|
||||
manager.register(CactusBlock);
|
||||
manager.register(ChestBlock);
|
||||
manager.register(CraftingTableBlock);
|
||||
|
||||
@@ -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<World>, _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<Player>,
|
||||
_location: BlockPos,
|
||||
_server: &Server,
|
||||
_world: Arc<World>,
|
||||
|
||||
@@ -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<World>,
|
||||
@@ -214,7 +220,7 @@ impl BlockRegistry {
|
||||
&self,
|
||||
world: Arc<World>,
|
||||
block: &Block,
|
||||
player: &Player,
|
||||
player: &Arc<Player>,
|
||||
location: BlockPos,
|
||||
server: &Server,
|
||||
state: BlockState,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user