feat(block): implement turtle egg block
This commit is contained in:
parent
22daa1e5d0
commit
788e369786
@ -115,4 +115,5 @@ pub mod creaking_heart;
|
|||||||
pub mod decorated_pot;
|
pub mod decorated_pot;
|
||||||
pub mod sniffer_egg;
|
pub mod sniffer_egg;
|
||||||
pub mod trial_spawner;
|
pub mod trial_spawner;
|
||||||
|
pub mod turtle_egg;
|
||||||
pub mod vault;
|
pub mod vault;
|
||||||
|
|||||||
@ -76,8 +76,12 @@ impl BlockBehaviour for SnifferEggBlock {
|
|||||||
|
|
||||||
let on_moss = Self::is_on_moss(args.world.as_ref(), args.position);
|
let on_moss = Self::is_on_moss(args.world.as_ref(), args.position);
|
||||||
let delay = Self::get_hatch_delay(on_moss);
|
let delay = Self::get_hatch_delay(on_moss);
|
||||||
args.world
|
args.world.schedule_block_tick(
|
||||||
.schedule_block_tick(args.block, *args.position, delay, TickPriority::Normal);
|
args.block,
|
||||||
|
*args.position,
|
||||||
|
delay,
|
||||||
|
TickPriority::Normal,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
args.world
|
args.world
|
||||||
.break_block(args.position, None, BlockFlags::SKIP_DROPS)
|
.break_block(args.position, None, BlockFlags::SKIP_DROPS)
|
||||||
|
|||||||
151
crates/pumpkin/src/block/blocks/turtle_egg.rs
Normal file
151
crates/pumpkin/src/block/blocks/turtle_egg.rs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
use pumpkin_data::block_properties::{BlockProperties, TurtleEggLikeProperties};
|
||||||
|
use pumpkin_data::entity::EntityPose;
|
||||||
|
use pumpkin_data::sound::{Sound, SoundCategory};
|
||||||
|
use pumpkin_data::tag::Taggable;
|
||||||
|
use pumpkin_data::{BlockDirection, BlockStateId, tag};
|
||||||
|
use pumpkin_macros::pumpkin_block;
|
||||||
|
use pumpkin_util::math::position::BlockPos;
|
||||||
|
use pumpkin_world::tick::TickPriority;
|
||||||
|
use pumpkin_world::world::{BlockAccessor, BlockFlags};
|
||||||
|
|
||||||
|
use crate::block::{
|
||||||
|
BlockBehaviour, BlockFuture, BlockIsReplacing, BrokenArgs, CanPlaceAtArgs, CanUpdateAtArgs,
|
||||||
|
GetStateForNeighborUpdateArgs, OnLandedUponArgs, OnPlaceArgs, OnScheduledTickArgs,
|
||||||
|
RandomTickArgs,
|
||||||
|
};
|
||||||
|
use crate::entity::EntityBase;
|
||||||
|
|
||||||
|
type TurtleEggProperties = TurtleEggLikeProperties;
|
||||||
|
|
||||||
|
#[pumpkin_block("minecraft:turtle_egg")]
|
||||||
|
pub struct TurtleEggBlock;
|
||||||
|
|
||||||
|
impl BlockBehaviour for TurtleEggBlock {
|
||||||
|
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||||
|
Box::pin(async move {
|
||||||
|
if args.player.get_entity().pose.load() != EntityPose::Crouching
|
||||||
|
&& let BlockIsReplacing::Itself(state_id) = args.replacing
|
||||||
|
{
|
||||||
|
let mut properties = TurtleEggProperties::from_state_id(state_id, args.block);
|
||||||
|
if properties.eggs < 4 {
|
||||||
|
properties.eggs += 1;
|
||||||
|
}
|
||||||
|
return properties.to_state_id(args.block);
|
||||||
|
}
|
||||||
|
|
||||||
|
let properties = TurtleEggProperties::default(args.block);
|
||||||
|
properties.to_state_id(args.block)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||||
|
can_place_at(args.block_accessor, args.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_update_at(&self, args: CanUpdateAtArgs<'_>) -> bool {
|
||||||
|
let b = BlockAccessor::get_block(args.world, args.position);
|
||||||
|
args.player.get_entity().pose.load() != EntityPose::Crouching
|
||||||
|
&& TurtleEggProperties::from_state_id(args.state_id, args.block).eggs < 4
|
||||||
|
&& args.block.id == b.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_state_for_neighbor_update<'a>(
|
||||||
|
&'a self,
|
||||||
|
args: GetStateForNeighborUpdateArgs<'a>,
|
||||||
|
) -> BlockFuture<'a, BlockStateId> {
|
||||||
|
Box::pin(async move {
|
||||||
|
if !can_place_at(args.world, args.position) {
|
||||||
|
args.world
|
||||||
|
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
|
||||||
|
}
|
||||||
|
args.state_id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||||
|
Box::pin(async move {
|
||||||
|
if !can_place_at(args.world.as_ref(), args.position) {
|
||||||
|
args.world
|
||||||
|
.break_block(args.position, None, BlockFlags::empty())
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_tick<'a>(&'a self, args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||||
|
Box::pin(async move {
|
||||||
|
// Turtle eggs can only hatch when placed on sand
|
||||||
|
if !args
|
||||||
|
.world
|
||||||
|
.get_block(&args.position.down())
|
||||||
|
.has_tag(&tag::Block::MINECRAFT_SAND)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let state_id = args.world.get_block_state_id(args.position);
|
||||||
|
let mut props = TurtleEggProperties::from_state_id(state_id, args.block);
|
||||||
|
|
||||||
|
if props.hatch < 2 {
|
||||||
|
props.hatch += 1;
|
||||||
|
args.world
|
||||||
|
.set_block_state(
|
||||||
|
args.position,
|
||||||
|
props.to_state_id(args.block),
|
||||||
|
BlockFlags::NOTIFY_ALL,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
args.world.play_sound(
|
||||||
|
Sound::EntityTurtleEggCrack,
|
||||||
|
SoundCategory::Blocks,
|
||||||
|
&args.position.to_f64(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
args.world
|
||||||
|
.break_block(args.position, None, BlockFlags::SKIP_DROPS)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
args.world.play_sound(
|
||||||
|
Sound::EntityTurtleEggHatch,
|
||||||
|
SoundCategory::Blocks,
|
||||||
|
&args.position.to_f64(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_landed_upon<'a>(&'a self, args: OnLandedUponArgs<'a>) -> BlockFuture<'a, ()> {
|
||||||
|
Box::pin(async move {
|
||||||
|
if let Some(living) = args.entity.get_living_entity() {
|
||||||
|
living
|
||||||
|
.handle_fall_damage(args.entity, args.fall_distance, 1.0)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entity falling onto turtle egg breaks an egg
|
||||||
|
if args.fall_distance > 0.5 {
|
||||||
|
args.world.play_sound(
|
||||||
|
Sound::EntityTurtleEggBreak,
|
||||||
|
SoundCategory::Blocks,
|
||||||
|
&args.entity.get_entity().pos.load(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||||
|
Box::pin(async move {
|
||||||
|
args.world.play_sound(
|
||||||
|
Sound::EntityTurtleEggBreak,
|
||||||
|
SoundCategory::Blocks,
|
||||||
|
&args.position.to_f64(),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_place_at(block_accessor: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||||
|
let (support_block, state) = block_accessor.get_block_and_state(&position.down());
|
||||||
|
support_block.has_tag(&tag::Block::MINECRAFT_SAND) || state.is_center_solid(BlockDirection::Up)
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ use crate::block::blocks::beacon::BeaconBlock;
|
|||||||
use crate::block::blocks::bed::BedBlock;
|
use crate::block::blocks::bed::BedBlock;
|
||||||
use crate::block::blocks::beehive::BeehiveBlock;
|
use crate::block::blocks::beehive::BeehiveBlock;
|
||||||
use crate::block::blocks::brewing_stand::BrewingStandBlock;
|
use crate::block::blocks::brewing_stand::BrewingStandBlock;
|
||||||
|
use crate::block::blocks::brushable_block::BrushableBlock;
|
||||||
use crate::block::blocks::bubble_column::BubbleColumnBlock;
|
use crate::block::blocks::bubble_column::BubbleColumnBlock;
|
||||||
use crate::block::blocks::cake::CakeBlock;
|
use crate::block::blocks::cake::CakeBlock;
|
||||||
use crate::block::blocks::campfire::CampfireBlock;
|
use crate::block::blocks::campfire::CampfireBlock;
|
||||||
@ -127,10 +128,8 @@ use crate::block::blocks::sculk::sculk_vein::SculkVeinBlock;
|
|||||||
use crate::block::blocks::shelf::ShelfBlock;
|
use crate::block::blocks::shelf::ShelfBlock;
|
||||||
use crate::block::blocks::signs::SignBlock;
|
use crate::block::blocks::signs::SignBlock;
|
||||||
use crate::block::blocks::slabs::SlabBlock;
|
use crate::block::blocks::slabs::SlabBlock;
|
||||||
use crate::block::blocks::slime::SlimeBlock;
|
|
||||||
use crate::block::blocks::snow::LayeredSnowBlock;
|
|
||||||
use crate::block::blocks::brushable_block::BrushableBlock;
|
|
||||||
use crate::block::blocks::sniffer_egg::SnifferEggBlock;
|
use crate::block::blocks::sniffer_egg::SnifferEggBlock;
|
||||||
|
use crate::block::blocks::snow::LayeredSnowBlock;
|
||||||
use crate::block::blocks::spawner::SpawnerBlock;
|
use crate::block::blocks::spawner::SpawnerBlock;
|
||||||
use crate::block::blocks::sponge::{SpongeBlock, WetSpongeBlock};
|
use crate::block::blocks::sponge::{SpongeBlock, WetSpongeBlock};
|
||||||
use crate::block::blocks::stairs::StairBlock;
|
use crate::block::blocks::stairs::StairBlock;
|
||||||
@ -138,6 +137,7 @@ use crate::block::blocks::tnt::TNTBlock;
|
|||||||
use crate::block::blocks::torches::TorchBlock;
|
use crate::block::blocks::torches::TorchBlock;
|
||||||
use crate::block::blocks::trapdoor::TrapDoorBlock;
|
use crate::block::blocks::trapdoor::TrapDoorBlock;
|
||||||
use crate::block::blocks::trial_spawner::TrialSpawnerBlock;
|
use crate::block::blocks::trial_spawner::TrialSpawnerBlock;
|
||||||
|
use crate::block::blocks::turtle_egg::TurtleEggBlock;
|
||||||
use crate::block::blocks::vault::VaultBlock;
|
use crate::block::blocks::vault::VaultBlock;
|
||||||
use crate::block::blocks::vine::VineBlock;
|
use crate::block::blocks::vine::VineBlock;
|
||||||
use crate::block::blocks::walls::WallBlock;
|
use crate::block::blocks::walls::WallBlock;
|
||||||
@ -259,6 +259,7 @@ pub fn default_registry() -> Arc<BlockRegistry> {
|
|||||||
manager.register(DecoratedPotBlock);
|
manager.register(DecoratedPotBlock);
|
||||||
manager.register(CreakingHeartBlock);
|
manager.register(CreakingHeartBlock);
|
||||||
manager.register(SnifferEggBlock);
|
manager.register(SnifferEggBlock);
|
||||||
|
manager.register(TurtleEggBlock);
|
||||||
manager.register(BrushableBlock);
|
manager.register(BrushableBlock);
|
||||||
manager.register(BushBlock);
|
manager.register(BushBlock);
|
||||||
manager.register(FlowerBlock);
|
manager.register(FlowerBlock);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user