mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-31 08:22:33 +00:00
fix: add Kelp block placement/break rules (#1805)
* fix: wrong piston break check * feat: kelp placement rules and break/place behaviour * chore: make clippy happy * fix: breaking kelp now places water instead of air * chore: make clippy happy * fix: vanilla parity
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
use crate::block::blocks::plant::PlantBlockBase;
|
||||
use crate::block::{BlockBehaviour, BlockFuture, BlockMetadata, CanPlaceAtArgs};
|
||||
use crate::block::{
|
||||
BlockBehaviour, BlockFuture, BlockMetadata, BrokenArgs, CanPlaceAtArgs,
|
||||
GetStateForNeighborUpdateArgs, PlacedArgs,
|
||||
};
|
||||
use pumpkin_data::Block;
|
||||
|
||||
use pumpkin_data::block_properties::{BlockProperties, WaterLikeProperties};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::world::{BlockAccessor, BlockFlags};
|
||||
pub struct KelpBlock;
|
||||
|
||||
impl BlockMetadata for KelpBlock {
|
||||
@@ -13,22 +19,111 @@ impl BlockMetadata for KelpBlock {
|
||||
impl BlockBehaviour for KelpBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
// Determine support block
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::get_state_for_neighbor_update(
|
||||
self,
|
||||
args.world,
|
||||
args.position,
|
||||
args.state_id,
|
||||
)
|
||||
.await
|
||||
})
|
||||
}
|
||||
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let support_pos = args.position.down();
|
||||
let support_block = args.block_accessor.get_block(&support_pos).await;
|
||||
|
||||
// If placing the base kelp block, allow placement on water or on other kelp segments.
|
||||
if args.block.id == Block::KELP.id {
|
||||
support_block == &Block::WATER
|
||||
|| support_block == &Block::KELP
|
||||
|| support_block == &Block::KELP_PLANT
|
||||
} else {
|
||||
support_block == &Block::KELP || support_block == &Block::KELP_PLANT
|
||||
let support_block = args.world.get_block(&support_pos).await;
|
||||
if support_block == &Block::KELP {
|
||||
args.world
|
||||
.set_block_state(
|
||||
&support_pos,
|
||||
Block::KELP_PLANT.default_state.id,
|
||||
BlockFlags::empty(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
})
|
||||
}
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let support_pos = args.position.down();
|
||||
let support_block = args.world.get_block(&support_pos).await;
|
||||
if support_block == &Block::KELP_PLANT {
|
||||
args.world
|
||||
.set_block_state(
|
||||
&support_pos,
|
||||
Block::KELP.default_state.id,
|
||||
BlockFlags::empty(),
|
||||
)
|
||||
.await;
|
||||
args.world
|
||||
.set_block_state(
|
||||
args.position,
|
||||
Block::WATER.default_state.id,
|
||||
BlockFlags::empty(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: proper kelp placement (fix `can_place_at`) and break behavior (including supporting blocks)
|
||||
}
|
||||
|
||||
impl PlantBlockBase for KelpBlock {}
|
||||
impl PlantBlockBase for KelpBlock {
|
||||
async fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
// Determine support block
|
||||
let support_pos = pos;
|
||||
let (replacing_block, replacing_block_state) =
|
||||
block_accessor.get_block_and_state(&pos.up()).await;
|
||||
let (support_block, support_block_state) =
|
||||
block_accessor.get_block_and_state(support_pos).await;
|
||||
if replacing_block == &Block::WATER {
|
||||
let water_props =
|
||||
WaterLikeProperties::from_state_id(replacing_block_state.id, replacing_block);
|
||||
|
||||
//Only allow placing kelp on either full water or downward flowing water
|
||||
if water_props.level as u8 != 0 && water_props.level as u8 != 8 {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
//Replacing block can also be a kelp_plant or kelp in case this is an neighbour update check
|
||||
if replacing_block != &Block::KELP_PLANT && replacing_block != &Block::KELP {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If placing the base kelp block, allow placement on water or on other kelp segments.
|
||||
if support_block == &Block::KELP || support_block == &Block::KELP_PLANT {
|
||||
return true;
|
||||
}
|
||||
if support_block == &Block::MAGMA_BLOCK {
|
||||
return false;
|
||||
}
|
||||
if support_block_state.is_side_solid(pumpkin_data::BlockDirection::Up)
|
||||
&& support_block.is_solid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
async fn get_state_for_neighbor_update(
|
||||
&self,
|
||||
block_accessor: &dyn BlockAccessor,
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
return Block::WATER.default_state.id;
|
||||
}
|
||||
block_state
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ pub fn can_be_replaced(block_state: &BlockState, block: &Block, fluid: &Fluid) -
|
||||
|| id == Block::CAMPFIRE.id
|
||||
|| id == Block::DRAGON_EGG.id
|
||||
|| id == Block::KELP.id
|
||||
|| id == Block::KELP_PLANT.id
|
||||
|| id == Block::LADDER.id
|
||||
|| id == Block::POINTED_DRIPSTONE.id
|
||||
|| id == Block::SCAFFOLDING.id
|
||||
|
||||
Reference in New Issue
Block a user