chore: less awaits more fun
This commit is contained in:
parent
c8633b78d7
commit
92abb1e44e
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -886,9 +886,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crossfire"
|
||||
version = "3.1.10"
|
||||
version = "3.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebed7d0a3a92ebc771f880516a5eecef5942a0fc67855dc4f30e719b04c77ac5"
|
||||
checksum = "72bdfcf389b100bb85fcf39ad434f67b617813cf0608095c905b79f6b2194aea"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"futures-core",
|
||||
|
||||
@ -120,7 +120,7 @@ console-subscriber = { version = "0.5.0", default-features = false }
|
||||
crc-fast = "1.10.0"
|
||||
criterion = { version = "0.8", default-features = false }
|
||||
crossbeam-utils = "0.8.21"
|
||||
crossfire = { version = "3.1.10", features = ["compat"] }
|
||||
crossfire = { version = "3.1.12", features = ["compat"] }
|
||||
crypto-bigint = "0.7.3"
|
||||
dashmap = "6.1"
|
||||
ecdsa = "0.16.9"
|
||||
|
||||
@ -15,8 +15,6 @@ use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::HeightMap;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use tracing::debug;
|
||||
|
||||
pub struct Cache {
|
||||
@ -45,35 +43,21 @@ impl HeightLimitView for Cache {
|
||||
}
|
||||
|
||||
impl BlockAccessor for Cache {
|
||||
fn get_block<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = &'static Block> + Send + 'a>> {
|
||||
Box::pin(async move { GenerationCache::get_block_state(self, &position.0).to_block() })
|
||||
fn get_block(&self, position: &BlockPos) -> &'static Block {
|
||||
GenerationCache::get_block_state(self, &position.0).to_block()
|
||||
}
|
||||
|
||||
fn get_block_state<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = &'static BlockState> + Send + 'a>> {
|
||||
Box::pin(async move { GenerationCache::get_block_state(self, &position.0).to_state() })
|
||||
fn get_block_state(&self, position: &BlockPos) -> &'static BlockState {
|
||||
GenerationCache::get_block_state(self, &position.0).to_state()
|
||||
}
|
||||
|
||||
fn get_block_state_id<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = BlockStateId> + Send + 'a>> {
|
||||
Box::pin(async move { GenerationCache::get_block_state(self, &position.0).0 })
|
||||
fn get_block_state_id(&self, position: &BlockPos) -> BlockStateId {
|
||||
GenerationCache::get_block_state(self, &position.0).0
|
||||
}
|
||||
|
||||
fn get_block_and_state<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = (&'static Block, &'static BlockState)> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let id = GenerationCache::get_block_state(self, &position.0);
|
||||
(id.to_block(), id.to_state())
|
||||
})
|
||||
fn get_block_and_state(&self, position: &BlockPos) -> (&'static Block, &'static BlockState) {
|
||||
let state = GenerationCache::get_block_state(self, &position.0);
|
||||
(state.to_block(), state.to_state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::block_properties::is_air;
|
||||
@ -1362,34 +1361,20 @@ impl ProtoChunk {
|
||||
}
|
||||
|
||||
impl BlockAccessor for ProtoChunk {
|
||||
fn get_block<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = &'static Block> + Send + 'a>> {
|
||||
Box::pin(async move { self.get_block_state(&position.0).to_block() })
|
||||
fn get_block(&self, position: &BlockPos) -> &'static Block {
|
||||
self.get_block_state(&position.0).to_block()
|
||||
}
|
||||
|
||||
fn get_block_state<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = &'static BlockState> + Send + 'a>> {
|
||||
Box::pin(async move { self.get_block_state(&position.0).to_state() })
|
||||
fn get_block_state(&self, position: &BlockPos) -> &'static BlockState {
|
||||
self.get_block_state(&position.0).to_state()
|
||||
}
|
||||
|
||||
fn get_block_state_id<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = BlockStateId> + Send + 'a>> {
|
||||
Box::pin(async move { self.get_block_state(&position.0).0 })
|
||||
fn get_block_state_id(&self, position: &BlockPos) -> BlockStateId {
|
||||
self.get_block_state(&position.0).0
|
||||
}
|
||||
|
||||
fn get_block_and_state<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = (&'static Block, &'static BlockState)> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
fn get_block_and_state(&self, position: &BlockPos) -> (&'static Block, &'static BlockState) {
|
||||
let id = self.get_block_state(&position.0);
|
||||
BlockState::from_id_with_block(id.0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -711,20 +711,6 @@ impl Level {
|
||||
RawBlockState(id.unwrap_or(Block::VOID_AIR.default_state.id))
|
||||
}
|
||||
|
||||
pub async fn get_rough_biome(self: &Arc<Self>, position: &BlockPos) -> &'static Biome {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let id = self
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
chunk.section.get_rough_biome_absolute_y(
|
||||
relative.x as usize,
|
||||
relative.y,
|
||||
relative.z as usize,
|
||||
)
|
||||
})
|
||||
.await;
|
||||
Biome::from_id(id.unwrap_or(0)).unwrap_or(&Biome::THE_VOID)
|
||||
}
|
||||
|
||||
pub async fn set_block_state(
|
||||
self: &Arc<Self>,
|
||||
position: &BlockPos,
|
||||
@ -798,6 +784,18 @@ impl Level {
|
||||
self.loaded_chunks.get(coordinates).map(|x| f(x.value()))
|
||||
}
|
||||
|
||||
pub fn get_rough_biome(&self, position: &BlockPos) -> &'static Biome {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let id = self.read_chunk_sync(&chunk_coordinate, |chunk| {
|
||||
chunk.section.get_rough_biome_absolute_y(
|
||||
relative.x as usize,
|
||||
relative.y,
|
||||
relative.z as usize,
|
||||
)
|
||||
});
|
||||
Biome::from_id(id.flatten().unwrap_or(0)).unwrap_or(&Biome::THE_VOID)
|
||||
}
|
||||
|
||||
pub fn read_entity_chunk_sync<R, F: Fn(&SyncEntityChunk) -> R>(
|
||||
&self,
|
||||
coordinates: &Vector2<i32>,
|
||||
@ -808,6 +806,12 @@ impl Level {
|
||||
.map(|x| f(x.value()))
|
||||
}
|
||||
|
||||
pub fn get_entity_chunk_sync(&self, pos: &Vector2<i32>) -> Option<SyncEntityChunk> {
|
||||
self.loaded_entity_chunks
|
||||
.get(pos)
|
||||
.map(|x| x.value().clone())
|
||||
}
|
||||
|
||||
pub async fn get_or_fetch_entity_chunk<R, F: Fn(&SyncEntityChunk) -> R>(
|
||||
self: &Arc<Self>,
|
||||
pos: Vector2<i32>,
|
||||
|
||||
@ -445,6 +445,50 @@ impl DynamicLightEngine {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_block_light_level_sync(&self, level: &Level, position: &BlockPos) -> Option<u8> {
|
||||
let (chunk_pos, relative) = position.chunk_and_chunk_relative_position();
|
||||
|
||||
level.read_chunk_sync(&chunk_pos, |chunk| {
|
||||
let section_idx = (relative.y - chunk.section.min_y) as usize / 16;
|
||||
let light_engine = chunk.light_engine.lock().ok()?;
|
||||
|
||||
light_engine
|
||||
.block_light
|
||||
.get(section_idx)?
|
||||
.get(
|
||||
relative.x as usize,
|
||||
(relative.y - chunk.section.min_y) as usize % 16,
|
||||
relative.z as usize,
|
||||
)
|
||||
.into()
|
||||
})?
|
||||
}
|
||||
|
||||
pub fn get_sky_light_level_sync(&self, level: &Level, position: &BlockPos) -> u8 {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
level
|
||||
.read_chunk_sync(&chunk_coordinate, |chunk| {
|
||||
let section_index =
|
||||
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
|
||||
|
||||
let light_engine = chunk
|
||||
.light_engine
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Bounds check for section index (lock the light engine)
|
||||
if section_index >= light_engine.sky_light.len() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
light_engine.sky_light[section_index].get(
|
||||
relative.x as usize,
|
||||
(relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE,
|
||||
relative.z as usize,
|
||||
)
|
||||
})
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
pub async fn get_block_light_level(
|
||||
&self,
|
||||
level: &Arc<Level>,
|
||||
|
||||
@ -74,23 +74,11 @@ pub trait WorldPortalExt: Send + Sync {
|
||||
}
|
||||
|
||||
pub trait BlockAccessor: Send + Sync {
|
||||
fn get_block<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = &'static Block> + Send + 'a>>;
|
||||
fn get_block(&self, position: &BlockPos) -> &'static Block;
|
||||
|
||||
fn get_block_state<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = &'static BlockState> + Send + 'a>>;
|
||||
fn get_block_state(&self, position: &BlockPos) -> &'static BlockState;
|
||||
|
||||
fn get_block_state_id<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = BlockStateId> + Send + 'a>>;
|
||||
fn get_block_state_id(&self, position: &BlockPos) -> BlockStateId;
|
||||
|
||||
fn get_block_and_state<'a>(
|
||||
&'a self,
|
||||
position: &'a BlockPos,
|
||||
) -> Pin<Box<dyn Future<Output = (&'static Block, &'static BlockState)> + Send + 'a>>;
|
||||
fn get_block_and_state(&self, position: &BlockPos) -> (&'static Block, &'static BlockState);
|
||||
}
|
||||
|
||||
@ -53,12 +53,10 @@ pub trait WallMountedBlock: Send + Sync {
|
||||
world: &'a dyn BlockAccessor,
|
||||
pos: &'a BlockPos,
|
||||
direction: BlockDirection,
|
||||
) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
) -> bool {
|
||||
let block_pos = pos.offset(direction.to_offset());
|
||||
let block_state = world.get_block_state(&block_pos).await;
|
||||
let block_state = world.get_block_state(&block_pos);
|
||||
block_state.is_side_solid(direction.opposite())
|
||||
})
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -67,9 +65,7 @@ pub trait WallMountedBlock: Send + Sync {
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if self.get_direction(args.state_id, args.block).opposite() == args.direction
|
||||
&& !self
|
||||
.can_place_at(args.world, args.position, args.direction)
|
||||
.await
|
||||
&& !self.can_place_at(args.world, args.position, args.direction)
|
||||
{
|
||||
Block::AIR.default_state.id
|
||||
} else {
|
||||
|
||||
@ -21,13 +21,13 @@ impl BlockBehaviour for BannerBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: crate::block::CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: crate::block::CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -40,7 +40,7 @@ impl BlockBehaviour for BannerBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -50,7 +50,7 @@ impl BlockBehaviour for BannerBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&position.down()).await;
|
||||
fn can_place_at(world: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&position.down());
|
||||
state.is_solid()
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ impl BlockBehaviour for BarrelBlock {
|
||||
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.get_inventory()
|
||||
{
|
||||
args.player
|
||||
|
||||
@ -51,7 +51,7 @@ pub struct BeaconBlock;
|
||||
impl BlockBehaviour for BeaconBlock {
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let block_entity = args.world.get_block_entity(args.position).await;
|
||||
let block_entity = args.world.get_block_entity(args.position);
|
||||
|
||||
// Extract the inventory from the entity
|
||||
let Some(inventory) = block_entity.and_then(BlockEntity::get_inventory) else {
|
||||
|
||||
@ -70,23 +70,19 @@ const NO_SLEEP_IDS: &[u16] = &[
|
||||
pub struct BedBlock;
|
||||
|
||||
impl BlockBehaviour for BedBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
if let Some(player) = args.player {
|
||||
let facing = player.living_entity.entity.get_horizontal_facing();
|
||||
return args
|
||||
.block_accessor
|
||||
.get_block_state(args.position)
|
||||
.await
|
||||
.replaceable()
|
||||
&& args
|
||||
.block_accessor
|
||||
.get_block_state(&args.position.offset(facing.to_offset()))
|
||||
.await
|
||||
.replaceable();
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fn on_landed_upon<'a>(&'a self, args: OnLandedUponArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
@ -150,7 +146,7 @@ impl BlockBehaviour for BedBlock {
|
||||
args.position.offset(bed_props.facing.to_offset())
|
||||
};
|
||||
|
||||
let neighbor_block_id = args.world.get_block_state_id(&other_half_pos).await;
|
||||
let neighbor_block_id = args.world.get_block_state_id(&other_half_pos);
|
||||
if neighbor_block_id != args.block.id {
|
||||
args.world.update_neighbors(&other_half_pos, None).await;
|
||||
return;
|
||||
@ -180,7 +176,7 @@ impl BlockBehaviour for BedBlock {
|
||||
// If the block is being replaced with air (i.e., broken), the `broken` callback
|
||||
// will handle breaking the other half with the correct drop flags. Only handle it here
|
||||
// if the block is being replaced with something else (e.g., piston movement).
|
||||
let new_state_id = args.world.get_block_state_id(args.position).await;
|
||||
let new_state_id = args.world.get_block_state_id(args.position);
|
||||
let new_block = Block::from_state_id(new_state_id);
|
||||
if new_block == &Block::AIR {
|
||||
return;
|
||||
@ -194,7 +190,7 @@ impl BlockBehaviour for BedBlock {
|
||||
args.position.offset(bed_props.facing.to_offset())
|
||||
};
|
||||
|
||||
let (other_block, other_state) = args.world.get_block_and_state(&other_half_pos).await;
|
||||
let (other_block, other_state) = args.world.get_block_and_state(&other_half_pos);
|
||||
if other_block == args.block {
|
||||
let other_props = BedProperties::from_state_id(other_state.id, other_block);
|
||||
if other_props.part != bed_props.part {
|
||||
@ -213,7 +209,7 @@ impl BlockBehaviour for BedBlock {
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let bed_props = BedProperties::from_state_id(state_id, args.block);
|
||||
|
||||
let (bed_head_pos, bed_foot_pos) = if bed_props.part == BedPart::Head {
|
||||
@ -246,16 +242,8 @@ impl BlockBehaviour for BedBlock {
|
||||
}
|
||||
|
||||
// Make sure the bed is not obstructed
|
||||
if args
|
||||
.world
|
||||
.get_block_state(&bed_head_pos.up())
|
||||
.await
|
||||
.is_solid()
|
||||
|| args
|
||||
.world
|
||||
.get_block_state(&bed_foot_pos.up())
|
||||
.await
|
||||
.is_solid()
|
||||
if args.world.get_block_state(&bed_head_pos.up()).is_solid()
|
||||
|| args.world.get_block_state(&bed_foot_pos.up()).is_solid()
|
||||
{
|
||||
args.player
|
||||
.send_system_message_raw(
|
||||
@ -370,7 +358,7 @@ impl BlockBehaviour for BedBlock {
|
||||
}
|
||||
}
|
||||
|
||||
args.player.sleep(bed_head_pos).await;
|
||||
args.player.sleep(bed_head_pos);
|
||||
Self::set_occupied(true, args.world, args.block, args.position, state_id).await;
|
||||
|
||||
BlockActionResult::SuccessServer
|
||||
|
||||
@ -86,7 +86,7 @@ pub struct BlastFurnaceBlock;
|
||||
impl BlockBehaviour for BlastFurnaceBlock {
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.clone().get_inventory()
|
||||
&& let Some(property_delegate) = block_entity.clone().to_property_delegate()
|
||||
&& let Some(experience_container) = block_entity.to_experience_container()
|
||||
@ -130,7 +130,7 @@ impl BlockBehaviour for BlastFurnaceBlock {
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
// Extract and drop accumulated XP as orbs before removing the block entity
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(experience_container) = block_entity.to_experience_container()
|
||||
{
|
||||
let xp = experience_container.extract_experience();
|
||||
|
||||
@ -52,7 +52,7 @@ pub struct BrewingStandBlock;
|
||||
impl BlockBehaviour for BrewingStandBlock {
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.clone().get_inventory()
|
||||
&& let Some(pd) = block_entity.clone().to_property_delegate()
|
||||
{
|
||||
|
||||
@ -84,15 +84,15 @@ impl CakeBlock {
|
||||
impl BlockBehaviour for CakeBlock {
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
Block::CAKE.default_state.id
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn use_with_item<'a>(
|
||||
@ -100,7 +100,7 @@ impl BlockBehaviour for CakeBlock {
|
||||
args: UseWithItemArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let properties = CakeLikeProperties::from_state_id(state_id, args.block);
|
||||
let item_lock = args.item_stack.lock().await;
|
||||
let item = item_lock.item;
|
||||
@ -159,7 +159,7 @@ impl BlockBehaviour for CakeBlock {
|
||||
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
Self::consume_if_hungry(args.world, args.player, args.block, args.position, state_id)
|
||||
.await
|
||||
})
|
||||
@ -167,7 +167,7 @@ impl BlockBehaviour for CakeBlock {
|
||||
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -180,7 +180,7 @@ impl BlockBehaviour for CakeBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -190,7 +190,7 @@ impl BlockBehaviour for CakeBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&position.down()).await;
|
||||
fn can_place_at(world: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&position.down());
|
||||
state.is_solid()
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ impl BlockBehaviour for CampfireBlock {
|
||||
CampfireLikeProperties::from_state_id(args.block.default_state.id, args.block);
|
||||
props.waterlogged = is_replacing_water;
|
||||
props.signal_fire =
|
||||
is_signal_fire_base_block(args.world.get_block(&args.position.down()).await);
|
||||
is_signal_fire_base_block(args.world.get_block(&args.position.down()));
|
||||
props.lit = !is_replacing_water;
|
||||
props.facing = args.player.get_entity().get_horizontal_facing();
|
||||
props.to_state_id(args.block)
|
||||
@ -93,7 +93,7 @@ impl BlockBehaviour for CampfireBlock {
|
||||
|
||||
if args.direction == BlockDirection::Down {
|
||||
props.signal_fire =
|
||||
is_signal_fire_base_block(args.world.get_block(args.neighbor_position).await);
|
||||
is_signal_fire_base_block(args.world.get_block(args.neighbor_position));
|
||||
}
|
||||
|
||||
props.to_state_id(args.block)
|
||||
|
||||
@ -92,7 +92,7 @@ impl CandleCakeBlock {
|
||||
)
|
||||
.await;
|
||||
|
||||
let (block, state) = world.get_block_and_state_id(location).await;
|
||||
let (block, state) = world.get_block_and_state_id(location);
|
||||
|
||||
CakeBlock::consume_if_hungry(world, player, block, location, state).await
|
||||
}
|
||||
@ -122,7 +122,7 @@ impl BlockBehaviour for CandleCakeBlock {
|
||||
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -135,7 +135,7 @@ impl BlockBehaviour for CandleCakeBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -145,7 +145,7 @@ impl BlockBehaviour for CandleCakeBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&position.down()).await;
|
||||
fn can_place_at(world: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&position.down());
|
||||
state.is_solid()
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ impl BlockBehaviour for CandleBlock {
|
||||
args: UseWithItemArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
let state = args.world.get_block_state(args.position);
|
||||
let mut properties = CandleLikeProperties::from_state_id(state.id, args.block);
|
||||
|
||||
let item_lock = args.item_stack.lock().await;
|
||||
@ -102,7 +102,7 @@ impl BlockBehaviour for CandleBlock {
|
||||
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let mut properties = CandleLikeProperties::from_state_id(state_id, args.block);
|
||||
|
||||
if properties.lit {
|
||||
@ -121,22 +121,20 @@ impl BlockBehaviour for CandleBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn can_update_at<'a>(&'a self, args: CanUpdateAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
let b = args.world.get_block(args.position).await;
|
||||
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
|
||||
&& CandleLikeProperties::from_state_id(args.state_id, args.block).candles != 4
|
||||
&& args.block.id == b.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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -149,7 +147,7 @@ impl BlockBehaviour for CandleBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -159,7 +157,7 @@ impl BlockBehaviour for CandleBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(block_accessor: &dyn BlockAccessor, position: &BlockPos) -> bool {
|
||||
let (support_block, state) = block_accessor.get_block_and_state(&position.down()).await;
|
||||
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.is_waterlogged(state.id) && state.is_center_solid(BlockDirection::Up)
|
||||
}
|
||||
|
||||
@ -12,8 +12,8 @@ use pumpkin_world::world::{BlockAccessor, BlockFlags};
|
||||
pub struct CarpetBlock;
|
||||
|
||||
impl BlockBehaviour for CarpetBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -21,7 +21,7 @@ impl BlockBehaviour for CarpetBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -32,7 +32,7 @@ impl BlockBehaviour for CarpetBlock {
|
||||
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -45,8 +45,8 @@ impl BlockBehaviour for CarpetBlock {
|
||||
pub struct MossCarpetBlock;
|
||||
|
||||
impl BlockBehaviour for MossCarpetBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -54,7 +54,7 @@ impl BlockBehaviour for MossCarpetBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -65,7 +65,7 @@ impl BlockBehaviour for MossCarpetBlock {
|
||||
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -78,8 +78,8 @@ impl BlockBehaviour for MossCarpetBlock {
|
||||
pub struct PaleMossCarpetBlock;
|
||||
|
||||
impl BlockBehaviour for PaleMossCarpetBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -87,7 +87,7 @@ impl BlockBehaviour for PaleMossCarpetBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -98,7 +98,7 @@ impl BlockBehaviour for PaleMossCarpetBlock {
|
||||
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -107,6 +107,6 @@ impl BlockBehaviour for PaleMossCarpetBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
!is_air(block_accessor.get_block_state_id(&block_pos.down()).await)
|
||||
fn can_place_at(block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
!is_air(block_accessor.get_block_state_id(&block_pos.down()))
|
||||
}
|
||||
|
||||
@ -40,8 +40,8 @@ impl BlockBehaviour for CarvedPumpkinBlock {
|
||||
// Mojang uses some BlockPattern magic, way too complex tbh
|
||||
Box::pin(async {
|
||||
let down_pos = args.position.down();
|
||||
let upper = args.world.get_block(&down_pos).await;
|
||||
let lower = args.world.get_block(&down_pos.down()).await;
|
||||
let upper = args.world.get_block(&down_pos);
|
||||
let lower = args.world.get_block(&down_pos.down());
|
||||
if upper == &Block::SNOW_BLOCK && lower == &Block::SNOW_BLOCK {
|
||||
for i in 0..3 {
|
||||
let pos = args.position.down_height(i);
|
||||
@ -52,20 +52,18 @@ impl BlockBehaviour for CarvedPumpkinBlock {
|
||||
BlockFlags::NOTIFY_LISTENERS,
|
||||
)
|
||||
.await;
|
||||
args.world
|
||||
.sync_world_event(
|
||||
args.world.sync_world_event(
|
||||
WorldEvent::ParticlesDestroyBlock,
|
||||
pos,
|
||||
Block::SNOW_BLOCK.default_state.id.into(),
|
||||
)
|
||||
.await;
|
||||
);
|
||||
}
|
||||
let entity = Entity::new(
|
||||
args.world.clone(),
|
||||
down_pos.down().to_centered_f64(),
|
||||
&EntityType::SNOW_GOLEM,
|
||||
);
|
||||
let golem = SnowGolemEntity::new(entity).await;
|
||||
let golem = SnowGolemEntity::new(entity);
|
||||
args.world.spawn_entity(golem).await;
|
||||
return;
|
||||
}
|
||||
@ -76,8 +74,8 @@ impl BlockBehaviour for CarvedPumpkinBlock {
|
||||
let arm1 = down_pos.offset(dir.to_offset());
|
||||
let arm2 = down_pos.offset(opposite.to_offset());
|
||||
|
||||
if args.world.get_block(&arm1).await == &Block::IRON_BLOCK
|
||||
&& args.world.get_block(&arm2).await == &Block::IRON_BLOCK
|
||||
if args.world.get_block(&arm1) == &Block::IRON_BLOCK
|
||||
&& args.world.get_block(&arm2) == &Block::IRON_BLOCK
|
||||
{
|
||||
let pattern = [*args.position, down_pos, down_pos.down(), arm1, arm2];
|
||||
|
||||
@ -89,13 +87,11 @@ impl BlockBehaviour for CarvedPumpkinBlock {
|
||||
BlockFlags::NOTIFY_LISTENERS,
|
||||
)
|
||||
.await;
|
||||
args.world
|
||||
.sync_world_event(
|
||||
args.world.sync_world_event(
|
||||
WorldEvent::ParticlesDestroyBlock,
|
||||
p,
|
||||
Block::IRON_BLOCK.default_state.id.into(),
|
||||
)
|
||||
.await;
|
||||
);
|
||||
}
|
||||
|
||||
let entity = Entity::new(
|
||||
@ -103,7 +99,7 @@ impl BlockBehaviour for CarvedPumpkinBlock {
|
||||
down_pos.down().to_centered_f64(),
|
||||
&EntityType::IRON_GOLEM,
|
||||
);
|
||||
let golem = IronGolemEntity::new(entity).await;
|
||||
let golem = IronGolemEntity::new(entity);
|
||||
args.world.spawn_entity(golem).await;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ use std::sync::Arc;
|
||||
|
||||
use crate::block::entities::BlockEntity;
|
||||
use crate::block::entities::chest::ChestBlockEntity;
|
||||
use futures::future::join;
|
||||
use pumpkin_data::block_properties::{
|
||||
BlockProperties, ChestLikeProperties, ChestType, HorizontalFacing,
|
||||
};
|
||||
@ -75,7 +74,7 @@ impl ScreenHandlerFactory for ChestScreenFactory {
|
||||
// Shared chest behavior implementations
|
||||
const LID_ANIMATION_EVENT_TYPE: u8 = 1;
|
||||
|
||||
async fn on_place_chest_impl(args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
fn on_place_chest_impl(args: &OnPlaceArgs<'_>) -> BlockStateId {
|
||||
let mut chest_props = ChestLikeProperties::default(args.block);
|
||||
chest_props.waterlogged = args.replacing.water_source();
|
||||
|
||||
@ -85,8 +84,7 @@ async fn on_place_chest_impl(args: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
args.block,
|
||||
args.position,
|
||||
args.direction,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
chest_props.facing = facing;
|
||||
chest_props.r#type = r#type;
|
||||
|
||||
@ -114,9 +112,7 @@ async fn placed_chest_impl<E: BlockEntity + 'static>(
|
||||
chest_props.facing,
|
||||
connected_towards,
|
||||
ChestType::Single,
|
||||
)
|
||||
.await
|
||||
{
|
||||
) {
|
||||
neighbor_props.r#type = chest_props.r#type.opposite();
|
||||
|
||||
args.world
|
||||
@ -130,11 +126,8 @@ async fn placed_chest_impl<E: BlockEntity + 'static>(
|
||||
}
|
||||
|
||||
async fn normal_use_chest_impl(args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
let (state, first_chest) = join(
|
||||
args.world.get_block_state_id(args.position),
|
||||
args.world.get_block_entity(args.position),
|
||||
)
|
||||
.await;
|
||||
let state = args.world.get_block_state_id(args.position);
|
||||
let first_chest = args.world.get_block_entity(args.position);
|
||||
|
||||
let Some(first_inventory) = first_chest.and_then(BlockEntity::get_inventory) else {
|
||||
return BlockActionResult::Fail;
|
||||
@ -147,13 +140,13 @@ async fn normal_use_chest_impl(args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
ChestType::Right => Some(chest_props.facing.rotate_counter_clockwise()),
|
||||
};
|
||||
|
||||
if is_chest_blocked(args.world, args.position).await {
|
||||
if is_chest_blocked(args.world, args.position) {
|
||||
return BlockActionResult::Success;
|
||||
}
|
||||
|
||||
if let Some(direction) = connected_towards {
|
||||
let neighbor_pos = args.position.offset(direction.to_offset());
|
||||
if is_chest_blocked(args.world, &neighbor_pos).await {
|
||||
if is_chest_blocked(args.world, &neighbor_pos) {
|
||||
return BlockActionResult::Success;
|
||||
}
|
||||
}
|
||||
@ -162,7 +155,6 @@ async fn normal_use_chest_impl(args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
&& let Some(second_inventory) = args
|
||||
.world
|
||||
.get_block_entity(&args.position.offset(direction.to_offset()))
|
||||
.await
|
||||
.and_then(BlockEntity::get_inventory)
|
||||
{
|
||||
// Vanilla: chestType == ChestType.RIGHT ? DoubleBlockProperties.Type.FIRST : DoubleBlockProperties.Type.SECOND;
|
||||
@ -197,9 +189,7 @@ async fn broken_chest_impl(args: BrokenArgs<'_>) {
|
||||
chest_props.facing,
|
||||
connected_towards,
|
||||
chest_props.r#type.opposite(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
) {
|
||||
neighbor_props.r#type = ChestType::Single;
|
||||
|
||||
args.world
|
||||
@ -217,7 +207,7 @@ pub struct ChestBlock;
|
||||
|
||||
impl BlockBehaviour for ChestBlock {
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(on_place_chest_impl(args))
|
||||
Box::pin(async move { on_place_chest_impl(&args) })
|
||||
}
|
||||
|
||||
fn on_synced_block_event<'a>(
|
||||
@ -246,7 +236,7 @@ pub struct CopperChestBlock;
|
||||
|
||||
impl BlockBehaviour for CopperChestBlock {
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(on_place_chest_impl(args))
|
||||
Box::pin(async move { on_place_chest_impl(&args) })
|
||||
}
|
||||
|
||||
fn on_synced_block_event<'a>(
|
||||
@ -270,7 +260,7 @@ impl BlockBehaviour for CopperChestBlock {
|
||||
|
||||
fn random_tick<'a>(&'a self, args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let current_state_id = args.world.get_block_state_id(args.position).await;
|
||||
let current_state_id = args.world.get_block_state_id(args.position);
|
||||
let chest_props = ChestLikeProperties::from_state_id(current_state_id, args.block);
|
||||
|
||||
// Only oxidize LEFT or SINGLE chests (not RIGHT) to prevent double oxidation
|
||||
@ -279,7 +269,7 @@ impl BlockBehaviour for CopperChestBlock {
|
||||
}
|
||||
|
||||
// Only oxidize if no players are viewing the chest
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(chest_entity) = block_entity.as_any().downcast_ref::<ChestBlockEntity>()
|
||||
&& chest_entity.get_viewer_count() > 0
|
||||
{
|
||||
@ -355,7 +345,7 @@ async fn try_oxidize_copper_chest(
|
||||
|
||||
// Scan neighbors in 4-block Manhattan distance to calculate oxidation chance
|
||||
let (same_level_count, higher_level_count) =
|
||||
count_neighbor_oxidation_levels(world, position, current_level).await;
|
||||
count_neighbor_oxidation_levels(world, position, current_level);
|
||||
|
||||
// If we found any neighbors at a LOWER level, oxidation is blocked
|
||||
// (This is handled in count_neighbor_oxidation_levels by returning early)
|
||||
@ -380,7 +370,7 @@ async fn try_oxidize_copper_chest(
|
||||
|
||||
/// Count copper blocks at same and higher oxidation levels within 4-block Manhattan distance.
|
||||
/// Returns (same, higher) counts, or (0, 0) if a lower-level neighbor was found (blocking oxidation).
|
||||
async fn count_neighbor_oxidation_levels(
|
||||
fn count_neighbor_oxidation_levels(
|
||||
world: &Arc<World>,
|
||||
center: &BlockPos,
|
||||
current_level: u8,
|
||||
@ -405,7 +395,7 @@ async fn count_neighbor_oxidation_levels(
|
||||
center.0.z + dz,
|
||||
));
|
||||
|
||||
let neighbor_block = world.get_block(&neighbor_pos).await;
|
||||
let neighbor_block = world.get_block(&neighbor_pos);
|
||||
|
||||
if let Some(neighbor_level) = get_oxidation_level(neighbor_block) {
|
||||
match neighbor_level.cmp(¤t_level) {
|
||||
@ -434,7 +424,7 @@ pub struct TrappedChestBlock;
|
||||
|
||||
impl BlockBehaviour for TrappedChestBlock {
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(on_place_chest_impl(args))
|
||||
Box::pin(async move { on_place_chest_impl(&args) })
|
||||
}
|
||||
|
||||
fn on_synced_block_event<'a>(
|
||||
@ -473,7 +463,7 @@ impl BlockBehaviour for TrappedChestBlock {
|
||||
|
||||
// Get viewer count from this chest
|
||||
let viewer_count = if let Some(block_entity) =
|
||||
args.world.get_block_entity(args.position).await
|
||||
args.world.get_block_entity(args.position)
|
||||
&& let Some(trapped_chest) = block_entity
|
||||
.as_any()
|
||||
.downcast_ref::<TrappedChestBlockEntity>()
|
||||
@ -503,7 +493,7 @@ impl BlockBehaviour for TrappedChestBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn compute_chest_props(
|
||||
fn compute_chest_props(
|
||||
world: &World,
|
||||
player: &Player,
|
||||
block: &Block,
|
||||
@ -518,9 +508,8 @@ async fn compute_chest_props(
|
||||
return (ChestType::Single, chest_facing);
|
||||
};
|
||||
|
||||
let (clicked_block, clicked_block_state) = world
|
||||
.get_block_and_state_id(&block_pos.offset(face.to_offset()))
|
||||
.await;
|
||||
let (clicked_block, clicked_block_state) =
|
||||
world.get_block_and_state_id(&block_pos.offset(face.to_offset()));
|
||||
|
||||
if clicked_block == block {
|
||||
let clicked_props =
|
||||
@ -548,7 +537,6 @@ async fn compute_chest_props(
|
||||
chest_facing.rotate_clockwise(),
|
||||
ChestType::Single,
|
||||
)
|
||||
.await
|
||||
.is_some()
|
||||
{
|
||||
(ChestType::Left, chest_facing)
|
||||
@ -560,7 +548,6 @@ async fn compute_chest_props(
|
||||
chest_facing.rotate_counter_clockwise(),
|
||||
ChestType::Single,
|
||||
)
|
||||
.await
|
||||
.is_some()
|
||||
{
|
||||
(ChestType::Right, chest_facing)
|
||||
@ -569,7 +556,7 @@ async fn compute_chest_props(
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_chest_properties_if_can_connect(
|
||||
fn get_chest_properties_if_can_connect(
|
||||
world: &World,
|
||||
block: &Block,
|
||||
block_pos: &BlockPos,
|
||||
@ -577,9 +564,8 @@ async fn get_chest_properties_if_can_connect(
|
||||
direction: HorizontalFacing,
|
||||
wanted_type: ChestType,
|
||||
) -> Option<ChestLikeProperties> {
|
||||
let (neighbor_block, neighbor_block_state) = world
|
||||
.get_block_and_state_id(&block_pos.offset(direction.to_offset()))
|
||||
.await;
|
||||
let (neighbor_block, neighbor_block_state) =
|
||||
world.get_block_and_state_id(&block_pos.offset(direction.to_offset()));
|
||||
|
||||
if neighbor_block != block {
|
||||
return None;
|
||||
@ -593,13 +579,13 @@ async fn get_chest_properties_if_can_connect(
|
||||
None
|
||||
}
|
||||
|
||||
async fn is_chest_blocked(world: &World, block_pos: &BlockPos) -> bool {
|
||||
fn is_chest_blocked(world: &World, block_pos: &BlockPos) -> bool {
|
||||
// TODO: Block opening when a cat is sitting on top.
|
||||
has_block_on_top(world, block_pos).await
|
||||
has_block_on_top(world, block_pos)
|
||||
}
|
||||
async fn has_block_on_top(world: &World, block_pos: &BlockPos) -> bool {
|
||||
fn has_block_on_top(world: &World, block_pos: &BlockPos) -> bool {
|
||||
let above_pos = block_pos.up();
|
||||
let above_state = world.get_block_state(&above_pos).await;
|
||||
let above_state = world.get_block_state(&above_pos);
|
||||
above_state.is_solid_block()
|
||||
}
|
||||
|
||||
|
||||
@ -41,12 +41,12 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
|
||||
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
let state = args.world.get_block_state(args.position);
|
||||
let properties = ChiseledBookshelfLikeProperties::from_state_id(state.id, args.block);
|
||||
|
||||
if let Some(slot) = Self::get_slot_for_hit(args.hit, properties.facing) {
|
||||
if Self::is_slot_used(properties, slot) {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(block_entity) = block_entity
|
||||
.as_any()
|
||||
.downcast_ref::<ChiseledBookshelfBlockEntity>()
|
||||
@ -75,7 +75,7 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
|
||||
args: UseWithItemArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
let state = args.world.get_block_state(args.position);
|
||||
let properties = ChiseledBookshelfLikeProperties::from_state_id(state.id, args.block);
|
||||
|
||||
if !args
|
||||
@ -90,7 +90,7 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
|
||||
if let Some(slot) = Self::get_slot_for_hit(args.hit, properties.facing) {
|
||||
if Self::is_slot_used(properties, slot) {
|
||||
return BlockActionResult::PassToDefaultBlockAction;
|
||||
} else if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
} else if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(block_entity) = block_entity
|
||||
.as_any()
|
||||
.downcast_ref::<ChiseledBookshelfBlockEntity>()
|
||||
@ -125,7 +125,7 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
|
||||
args: GetComparatorOutputArgs<'a>,
|
||||
) -> BlockFuture<'a, Option<u8>> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(block_entity) = block_entity
|
||||
.as_any()
|
||||
.downcast_ref::<ChiseledBookshelfBlockEntity>()
|
||||
@ -164,9 +164,7 @@ impl ChiseledBookshelfBlock {
|
||||
.await;
|
||||
entity.update_state(properties, world.clone(), slot).await;
|
||||
|
||||
world
|
||||
.play_sound(sound, SoundCategory::Blocks, &position.to_centered_f64())
|
||||
.await;
|
||||
world.play_sound(sound, SoundCategory::Blocks, &position.to_centered_f64());
|
||||
}
|
||||
|
||||
async fn try_remove_book(
|
||||
@ -195,9 +193,7 @@ impl ChiseledBookshelfBlock {
|
||||
}
|
||||
entity.update_state(properties, world.clone(), slot).await;
|
||||
|
||||
world
|
||||
.play_sound(sound, SoundCategory::Blocks, &position.to_centered_f64())
|
||||
.await;
|
||||
world.play_sound(sound, SoundCategory::Blocks, &position.to_centered_f64());
|
||||
}
|
||||
|
||||
fn get_slot_for_hit(hit: &BlockHitResult<'_>, facing: HorizontalFacing) -> Option<i8> {
|
||||
|
||||
@ -23,13 +23,13 @@ use tracing::warn;
|
||||
pub struct CommandBlock;
|
||||
|
||||
impl CommandBlock {
|
||||
async fn get_relative_facing(
|
||||
fn get_relative_facing(
|
||||
world: &World,
|
||||
pos: &BlockPos,
|
||||
dir: Facing,
|
||||
) -> Option<(BlockPos, CommandBlockLikeProperties)> {
|
||||
let target_pos = pos.offset(dir.to_block_direction().to_offset());
|
||||
let block = world.get_block(&target_pos).await;
|
||||
let block = world.get_block(&target_pos);
|
||||
|
||||
let allowed_blocks = [
|
||||
Block::COMMAND_BLOCK.name,
|
||||
@ -40,24 +40,24 @@ impl CommandBlock {
|
||||
return None;
|
||||
}
|
||||
|
||||
let state_id = world.get_block_state_id(&target_pos).await;
|
||||
let state_id = world.get_block_state_id(&target_pos);
|
||||
let props = CommandBlockLikeProperties::from_state_id(state_id, block);
|
||||
|
||||
Some((target_pos, props))
|
||||
}
|
||||
|
||||
async fn conditions_met(world: &Arc<World>, pos: &BlockPos, facing: Facing) -> bool {
|
||||
let (block, state_id) = world.get_block_and_state_id(pos).await;
|
||||
fn conditions_met(world: &Arc<World>, pos: &BlockPos, facing: Facing) -> bool {
|
||||
let (block, state_id) = world.get_block_and_state_id(pos);
|
||||
let props = CommandBlockLikeProperties::from_state_id(state_id, block);
|
||||
|
||||
if !props.conditional {
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(before) = Self::get_relative_facing(world, pos, facing.opposite()).await else {
|
||||
let Some(before) = Self::get_relative_facing(world, pos, facing.opposite()) else {
|
||||
return false;
|
||||
};
|
||||
let Some(before_entity) = world.get_block_entity(&before.0).await else {
|
||||
let Some(before_entity) = world.get_block_entity(&before.0) else {
|
||||
warn!("Command block has no matching entity");
|
||||
return false;
|
||||
};
|
||||
@ -83,7 +83,7 @@ impl CommandBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
let state_id = world.get_block_state_id(pos).await;
|
||||
let state_id = world.get_block_state_id(pos);
|
||||
let props = CommandBlockLikeProperties::from_state_id(state_id, block);
|
||||
|
||||
if !props.conditional {
|
||||
@ -93,11 +93,10 @@ impl CommandBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(behind) = Self::get_relative_facing(world, pos, props.facing.opposite()).await
|
||||
else {
|
||||
let Some(behind) = Self::get_relative_facing(world, pos, props.facing.opposite()) else {
|
||||
return;
|
||||
};
|
||||
let Some(behind_entity) = world.get_block_entity(&behind.0).await else {
|
||||
let Some(behind_entity) = world.get_block_entity(&behind.0) else {
|
||||
warn!(
|
||||
"Command Block exists at {} with no matching block entity!",
|
||||
behind.0
|
||||
@ -159,12 +158,12 @@ impl CommandBlock {
|
||||
if !command_blocks_work {
|
||||
return;
|
||||
}
|
||||
let block = world.get_block(&pos).await;
|
||||
let block = world.get_block(&pos);
|
||||
|
||||
if block.id != Block::CHAIN_COMMAND_BLOCK.id {
|
||||
break;
|
||||
}
|
||||
let Some(block_entity) = world.get_block_entity(&pos).await else {
|
||||
let Some(block_entity) = world.get_block_entity(&pos) else {
|
||||
warn!("Missing command block entity");
|
||||
break;
|
||||
};
|
||||
@ -172,14 +171,14 @@ impl CommandBlock {
|
||||
let command_entity: &CommandBlockEntity = block_entity.as_any().downcast_ref().unwrap();
|
||||
let powered = command_entity.powered.load(Ordering::Relaxed);
|
||||
let auto = command_entity.auto.load(Ordering::Relaxed);
|
||||
let state_id = world.get_block_state_id(&pos).await;
|
||||
let state_id = world.get_block_state_id(&pos);
|
||||
let props = CommandBlockLikeProperties::from_state_id(state_id, block);
|
||||
|
||||
if powered || auto {
|
||||
let conditions_met = Self::conditions_met(&world, &pos, direction).await;
|
||||
let conditions_met = Self::conditions_met(&world, &pos, direction);
|
||||
if conditions_met {
|
||||
let command = command_entity.command.lock().await;
|
||||
let entity = world.get_block_entity(&pos).await.unwrap();
|
||||
let entity = world.get_block_entity(&pos).unwrap();
|
||||
Self::execute(server, world.clone(), entity, &command).await;
|
||||
} else if props.conditional {
|
||||
command_entity.success_count.store(0, Ordering::Release);
|
||||
@ -224,7 +223,7 @@ impl BlockBehaviour for CommandBlock {
|
||||
if args.player.permission_lvl.load() < PermissionLvl::Two {
|
||||
return BlockActionResult::Pass;
|
||||
}
|
||||
let Some(block_entity) = args.world.get_block_entity(args.position).await else {
|
||||
let Some(block_entity) = args.world.get_block_entity(args.position) else {
|
||||
return BlockActionResult::Pass;
|
||||
};
|
||||
args.world.update_block_entity(&block_entity).await;
|
||||
@ -239,7 +238,7 @@ impl BlockBehaviour for CommandBlock {
|
||||
if !command_blocks_work {
|
||||
return;
|
||||
}
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position) {
|
||||
if block_entity.resource_location() != CommandBlockEntity::ID {
|
||||
return;
|
||||
}
|
||||
@ -267,7 +266,7 @@ impl BlockBehaviour for CommandBlock {
|
||||
if !command_blocks_work {
|
||||
return;
|
||||
}
|
||||
let Some(block_entity) = args.world.get_block_entity(args.position).await else {
|
||||
let Some(block_entity) = args.world.get_block_entity(args.position) else {
|
||||
return;
|
||||
};
|
||||
if block_entity.resource_location() != CommandBlockEntity::ID {
|
||||
@ -279,7 +278,7 @@ impl BlockBehaviour for CommandBlock {
|
||||
return;
|
||||
};
|
||||
let props = CommandBlockLikeProperties::from_state_id(
|
||||
args.world.get_block_state_id(args.position).await,
|
||||
args.world.get_block_state_id(args.position),
|
||||
args.block,
|
||||
);
|
||||
|
||||
@ -300,7 +299,7 @@ impl BlockBehaviour for CommandBlock {
|
||||
)
|
||||
.await;
|
||||
|
||||
let block = args.world.get_block(args.position).await;
|
||||
let block = args.world.get_block(args.position);
|
||||
let is_auto = command_entity.auto.load(Ordering::Relaxed);
|
||||
let can_run = command_entity.powered.load(Ordering::Relaxed) || is_auto;
|
||||
if block == &Block::REPEATING_COMMAND_BLOCK && can_run {
|
||||
@ -311,8 +310,7 @@ impl BlockBehaviour for CommandBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
if let Some(player) = args.player
|
||||
&& player.gamemode.load() == GameMode::Creative
|
||||
{
|
||||
@ -320,7 +318,6 @@ impl BlockBehaviour for CommandBlock {
|
||||
}
|
||||
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
@ -344,7 +341,7 @@ impl BlockBehaviour for CommandBlock {
|
||||
args: crate::block::GetComparatorOutputArgs<'a>,
|
||||
) -> BlockFuture<'a, Option<u8>> {
|
||||
Box::pin(async {
|
||||
let entity = args.world.get_block_entity(args.position).await;
|
||||
let entity = args.world.get_block_entity(args.position);
|
||||
|
||||
entity.map_or_else(
|
||||
|| {
|
||||
|
||||
@ -29,7 +29,7 @@ pub struct ComposterBlock;
|
||||
impl BlockBehaviour for ComposterBlock {
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let props = ComposterLikeProperties::from_state_id(state_id, args.block);
|
||||
if props.level == 8 {
|
||||
self.clear_composter(args.world, args.position, state_id, args.block)
|
||||
@ -45,7 +45,7 @@ impl BlockBehaviour for ComposterBlock {
|
||||
args: UseWithItemArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let props = ComposterLikeProperties::from_state_id(state_id, args.block);
|
||||
let level = props.level;
|
||||
|
||||
@ -80,8 +80,7 @@ impl BlockBehaviour for ComposterBlock {
|
||||
)
|
||||
.await;
|
||||
args.world
|
||||
.sync_world_event(WorldEvent::ComposterFill, *args.position, 1)
|
||||
.await;
|
||||
.sync_world_event(WorldEvent::ComposterFill, *args.position, 1);
|
||||
}
|
||||
|
||||
// Consume the item
|
||||
@ -91,7 +90,7 @@ impl BlockBehaviour for ComposterBlock {
|
||||
|
||||
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let props = ComposterLikeProperties::from_state_id(state_id, args.block);
|
||||
let level = props.level;
|
||||
if level == 7 {
|
||||
@ -161,8 +160,7 @@ impl ComposterBlock {
|
||||
let item_entity = ItemEntity::new(
|
||||
Entity::new(world.clone(), item_position, &EntityType::ITEM),
|
||||
ItemStack::new(1, &Item::BONE_MEAL),
|
||||
)
|
||||
.await;
|
||||
);
|
||||
|
||||
world.spawn_entity(Arc::new(item_entity)).await;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ impl BlockBehaviour for DirtPathBlock {
|
||||
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
return Block::DIRT.default_state.id;
|
||||
}
|
||||
|
||||
@ -45,9 +45,7 @@ impl BlockBehaviour for DirtPathBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if args.direction == BlockDirection::Up
|
||||
&& !can_place_at(args.world, args.position).await
|
||||
{
|
||||
if args.direction == BlockDirection::Up && !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -56,12 +54,12 @@ impl BlockBehaviour for DirtPathBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&block_pos.up()).await;
|
||||
fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&block_pos.up());
|
||||
!state.is_solid() // TODO: add fence gate block
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ use pumpkin_util::GameMode;
|
||||
type DoorProperties = pumpkin_data::block_properties::OakDoorLikeProperties;
|
||||
|
||||
async fn toggle_door(player: &Player, world: &Arc<World>, block_pos: &BlockPos) {
|
||||
let (block, block_state) = world.get_block_and_state_id(block_pos).await;
|
||||
let (block, block_state) = world.get_block_and_state_id(block_pos);
|
||||
let mut door_props = DoorProperties::from_state_id(block_state, block);
|
||||
door_props.open = !door_props.open;
|
||||
|
||||
@ -47,18 +47,16 @@ async fn toggle_door(player: &Player, world: &Arc<World>, block_pos: &BlockPos)
|
||||
};
|
||||
let other_pos = block_pos.offset(other_half.to_offset());
|
||||
|
||||
let (other_block, other_state_id) = world.get_block_and_state_id(&other_pos).await;
|
||||
let (other_block, other_state_id) = world.get_block_and_state_id(&other_pos);
|
||||
let mut other_door_props = DoorProperties::from_state_id(other_state_id, other_block);
|
||||
other_door_props.open = door_props.open;
|
||||
|
||||
world
|
||||
.play_block_sound_expect(
|
||||
world.play_block_sound_expect(
|
||||
player,
|
||||
get_sound(block, door_props.open),
|
||||
SoundCategory::Blocks,
|
||||
*block_pos,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
|
||||
world
|
||||
.set_block_state(
|
||||
@ -114,24 +112,22 @@ async fn get_hinge(
|
||||
let top_pos = pos.up();
|
||||
let left_dir = facing.rotate_counter_clockwise();
|
||||
let left_pos = pos.offset(left_dir.to_block_direction().to_offset());
|
||||
let (left_block, left_state) = world.get_block_and_state(&left_pos).await;
|
||||
let (left_block, left_state) = world.get_block_and_state(&left_pos);
|
||||
let top_facing = top_pos.offset(facing.to_block_direction().to_offset());
|
||||
let top_state = world.get_block_state(&top_facing).await;
|
||||
let top_state = world.get_block_state(&top_facing);
|
||||
let right_dir = facing.rotate_clockwise();
|
||||
let right_pos = pos.offset(right_dir.to_block_direction().to_offset());
|
||||
let (right_block, right_state) = world.get_block_and_state(&right_pos).await;
|
||||
let (right_block, right_state) = world.get_block_and_state(&right_pos);
|
||||
let top_right = top_pos.offset(facing.to_block_direction().to_offset());
|
||||
let top_right_state = world.get_block_state(&top_right).await;
|
||||
let top_right_state = world.get_block_state(&top_right);
|
||||
|
||||
let has_left_door = world
|
||||
.get_block(&left_pos)
|
||||
.await
|
||||
.has_tag(&tag::Block::MINECRAFT_DOORS)
|
||||
&& DoorProperties::from_state_id(left_state.id, left_block).half == DoubleBlockHalf::Lower;
|
||||
|
||||
let has_right_door = world
|
||||
.get_block(&right_pos)
|
||||
.await
|
||||
.has_tag(&tag::Block::MINECRAFT_DOORS)
|
||||
&& DoorProperties::from_state_id(right_state.id, right_block).half
|
||||
== DoubleBlockHalf::Lower;
|
||||
@ -184,8 +180,8 @@ impl BlockBehaviour for DoorBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
@ -223,7 +219,7 @@ impl BlockBehaviour for DoorBlock {
|
||||
DoubleBlockHalf::Lower => args.position.up(),
|
||||
};
|
||||
|
||||
let neighbor_block_id = args.world.get_block_state_id(&other_half_pos).await;
|
||||
let neighbor_block_id = args.world.get_block_state_id(&other_half_pos);
|
||||
if neighbor_block_id != args.block.id {
|
||||
args.world.update_neighbors(&other_half_pos, None).await;
|
||||
return; // Neighbor is already gone or is a different block
|
||||
@ -244,7 +240,7 @@ impl BlockBehaviour for DoorBlock {
|
||||
|
||||
fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let block_state = args.world.get_block_state(args.position).await;
|
||||
let block_state = args.world.get_block_state(args.position);
|
||||
let mut door_props = DoorProperties::from_state_id(block_state.id, args.block);
|
||||
|
||||
let other_half = match door_props.half {
|
||||
@ -252,7 +248,7 @@ impl BlockBehaviour for DoorBlock {
|
||||
DoubleBlockHalf::Lower => BlockDirection::Up,
|
||||
};
|
||||
let other_pos = args.position.offset(other_half.to_offset());
|
||||
let (other_block, other_state_id) = args.world.get_block_and_state_id(&other_pos).await;
|
||||
let (other_block, other_state_id) = args.world.get_block_and_state_id(&other_pos);
|
||||
|
||||
if other_block.id != args.block.id {
|
||||
return;
|
||||
@ -271,13 +267,11 @@ impl BlockBehaviour for DoorBlock {
|
||||
door_props.open = door_props.powered;
|
||||
other_door_props.open = other_door_props.powered;
|
||||
|
||||
args.world
|
||||
.play_block_sound(
|
||||
args.world.play_block_sound(
|
||||
get_sound(args.block, powered),
|
||||
SoundCategory::Blocks,
|
||||
*args.position,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
}
|
||||
|
||||
args.world
|
||||
@ -309,7 +303,7 @@ impl BlockBehaviour for DoorBlock {
|
||||
{
|
||||
if lv == DoubleBlockHalf::Lower
|
||||
&& args.direction == BlockDirection::Down
|
||||
&& !can_place_at(args.world, args.position).await
|
||||
&& !can_place_at(args.world, args.position)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -333,7 +327,7 @@ impl BlockBehaviour for DoorBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
let new_state_id = args.world.get_block_state_id(args.position).await;
|
||||
let new_state_id = args.world.get_block_state_id(args.position);
|
||||
let new_block = Block::from_state_id(new_state_id);
|
||||
if new_block == &Block::AIR {
|
||||
return;
|
||||
@ -356,10 +350,9 @@ impl BlockBehaviour for DoorBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
world.get_block_state(&block_pos.up()).await.replaceable()
|
||||
fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
world.get_block_state(&block_pos.up()).replaceable()
|
||||
&& world
|
||||
.get_block_state(&block_pos.down())
|
||||
.await
|
||||
.is_side_solid(BlockDirection::Up)
|
||||
}
|
||||
|
||||
@ -19,11 +19,11 @@ impl DragonEggBlock {
|
||||
let z = pos.0.z + rng().random_range(-16..16);
|
||||
let test_pos = BlockPos::new(x, y, z);
|
||||
|
||||
let state = world.get_block_state(&test_pos).await;
|
||||
let below_state = world.get_block_state(&test_pos.down()).await;
|
||||
let state = world.get_block_state(&test_pos);
|
||||
let below_state = world.get_block_state(&test_pos.down());
|
||||
|
||||
if state.is_air() && !below_state.is_air() {
|
||||
let current_state = world.get_block_state(pos).await;
|
||||
let current_state = world.get_block_state(pos);
|
||||
world
|
||||
.set_block_state(
|
||||
&test_pos,
|
||||
|
||||
@ -28,16 +28,13 @@ impl BlockMetadata for DripstoneBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for DripstoneBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at_pos(
|
||||
args.block_accessor,
|
||||
args.position,
|
||||
args.direction,
|
||||
args.player,
|
||||
)
|
||||
.await
|
||||
})
|
||||
}
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
@ -48,9 +45,7 @@ impl BlockBehaviour for DripstoneBlock {
|
||||
args.position,
|
||||
Some(args.direction),
|
||||
Some(args.player),
|
||||
)
|
||||
.await
|
||||
else {
|
||||
) else {
|
||||
//this shouldn't happen
|
||||
return Block::AIR.id;
|
||||
};
|
||||
@ -65,8 +60,7 @@ impl BlockBehaviour for DripstoneBlock {
|
||||
args.world,
|
||||
args.position,
|
||||
args.state_id,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
match vertical_dir {
|
||||
VerticalDirection::Up => {
|
||||
update_stalagmite(args.world, len, args.position).await;
|
||||
@ -90,8 +84,7 @@ impl BlockBehaviour for DripstoneBlock {
|
||||
args.world,
|
||||
&new_tip_pos,
|
||||
args.state.id,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
match vertical_dir {
|
||||
VerticalDirection::Up => {
|
||||
update_stalagmite(args.world, len, &new_tip_pos).await;
|
||||
@ -107,7 +100,7 @@ impl BlockBehaviour for DripstoneBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at_pos(args.world, args.position, None, None).await {
|
||||
if !can_place_at_pos(args.world, args.position, None, None) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
let mut dripstone_props =
|
||||
@ -117,14 +110,14 @@ impl BlockBehaviour for DripstoneBlock {
|
||||
}
|
||||
match dripstone_props.vertical_direction {
|
||||
VerticalDirection::Up => {
|
||||
let block_above = args.world.get_block(&args.position.up()).await;
|
||||
let block_above = args.world.get_block(&args.position.up());
|
||||
if block_above != &Block::POINTED_DRIPSTONE {
|
||||
dripstone_props.thickness = DripstoneThickness::Tip;
|
||||
return dripstone_props.to_state_id(args.block);
|
||||
}
|
||||
}
|
||||
VerticalDirection::Down => {
|
||||
let block_below = args.world.get_block(&args.position.down()).await;
|
||||
let block_below = args.world.get_block(&args.position.down());
|
||||
if block_below != &Block::POINTED_DRIPSTONE {
|
||||
dripstone_props.thickness = DripstoneThickness::Tip;
|
||||
return dripstone_props.to_state_id(args.block);
|
||||
@ -136,7 +129,7 @@ impl BlockBehaviour for DripstoneBlock {
|
||||
}
|
||||
}
|
||||
async fn update_stalagmite(world: &Arc<World>, stalagmite_len: u8, tip_pos: &BlockPos) {
|
||||
let block_above = world.get_block(&tip_pos.up()).await;
|
||||
let block_above = world.get_block(&tip_pos.up());
|
||||
if block_above == &Block::POINTED_DRIPSTONE {
|
||||
modify_dripstone_thickness_to(world, tip_pos, DripstoneThickness::TipMerge).await;
|
||||
modify_dripstone_thickness_to(world, &tip_pos.up(), DripstoneThickness::TipMerge).await;
|
||||
@ -203,7 +196,7 @@ async fn update_stalagmite(world: &Arc<World>, stalagmite_len: u8, tip_pos: &Blo
|
||||
}
|
||||
|
||||
async fn update_stalactite(world: &Arc<World>, stalagmite_len: u8, tip_pos: &BlockPos) {
|
||||
let block_below = world.get_block(&tip_pos.down()).await;
|
||||
let block_below = world.get_block(&tip_pos.down());
|
||||
if block_below == &Block::POINTED_DRIPSTONE {
|
||||
modify_dripstone_thickness_to(world, tip_pos, DripstoneThickness::TipMerge).await;
|
||||
modify_dripstone_thickness_to(world, &tip_pos.down(), DripstoneThickness::TipMerge).await;
|
||||
@ -256,7 +249,7 @@ async fn update_stalactite(world: &Arc<World>, stalagmite_len: u8, tip_pos: &Blo
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
async fn get_stalagmite_or_stalactice_len_and_dir_from_tip_pos(
|
||||
fn get_stalagmite_or_stalactice_len_and_dir_from_tip_pos(
|
||||
world: &Arc<World>,
|
||||
position: &BlockPos,
|
||||
block_state_id: BlockStateId,
|
||||
@ -268,7 +261,7 @@ async fn get_stalagmite_or_stalactice_len_and_dir_from_tip_pos(
|
||||
let mut next_dripstone_pos = offset_pos_by_vertical_dir(position, props.vertical_direction);
|
||||
//We dont care if it's longer than 5 blocks because of how thickness system works.
|
||||
while dripstone_len < 5 {
|
||||
if world.get_block(&next_dripstone_pos).await != &Block::POINTED_DRIPSTONE {
|
||||
if world.get_block(&next_dripstone_pos) != &Block::POINTED_DRIPSTONE {
|
||||
break;
|
||||
}
|
||||
next_dripstone_pos =
|
||||
@ -277,7 +270,7 @@ async fn get_stalagmite_or_stalactice_len_and_dir_from_tip_pos(
|
||||
}
|
||||
(dripstone_len, props.vertical_direction)
|
||||
}
|
||||
async fn can_place_at_pos(
|
||||
fn can_place_at_pos(
|
||||
block_accessor: &dyn BlockAccessor,
|
||||
position: &BlockPos,
|
||||
placing_direction: Option<BlockDirection>,
|
||||
@ -289,22 +282,21 @@ async fn can_place_at_pos(
|
||||
position,
|
||||
placing_direction,
|
||||
player_option,
|
||||
)
|
||||
.await
|
||||
else {
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
let support_pos = match support_block_vertical_direction {
|
||||
VerticalDirection::Up => position.up(),
|
||||
VerticalDirection::Down => position.down(),
|
||||
};
|
||||
let support_block = block_accessor.get_block(&support_pos).await;
|
||||
let support_block = block_accessor.get_block(&support_pos);
|
||||
if can_support_dripstone(support_block) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
async fn get_support_block_vertical_direction(
|
||||
|
||||
fn get_support_block_vertical_direction(
|
||||
block_accessor: &dyn BlockAccessor,
|
||||
position: &BlockPos,
|
||||
placing_direction_wrapper: Option<BlockDirection>,
|
||||
@ -312,7 +304,7 @@ async fn get_support_block_vertical_direction(
|
||||
) -> Option<VerticalDirection> {
|
||||
let Some(placing_direction) = placing_direction_wrapper else {
|
||||
//then this is basically called by a neighbor update check
|
||||
let (block, state) = block_accessor.get_block_and_state(position).await;
|
||||
let (block, state) = block_accessor.get_block_and_state(position);
|
||||
if block != &Block::POINTED_DRIPSTONE {
|
||||
return None;
|
||||
}
|
||||
@ -322,8 +314,8 @@ async fn get_support_block_vertical_direction(
|
||||
match block_direction_to_vertical_direction(placing_direction) {
|
||||
Some(ver_dir) => match ver_dir {
|
||||
VerticalDirection::Up => {
|
||||
let block_above = block_accessor.get_block(&position.up()).await;
|
||||
let block_below = block_accessor.get_block(&position.down()).await;
|
||||
let block_above = block_accessor.get_block(&position.up());
|
||||
let block_below = block_accessor.get_block(&position.down());
|
||||
if can_support_dripstone(block_above) {
|
||||
return Some(VerticalDirection::Up);
|
||||
} else if can_support_dripstone(block_below) {
|
||||
@ -332,8 +324,8 @@ async fn get_support_block_vertical_direction(
|
||||
None
|
||||
}
|
||||
VerticalDirection::Down => {
|
||||
let block_above = block_accessor.get_block(&position.up()).await;
|
||||
let block_below = block_accessor.get_block(&position.down()).await;
|
||||
let block_above = block_accessor.get_block(&position.up());
|
||||
let block_below = block_accessor.get_block(&position.down());
|
||||
if can_support_dripstone(block_below) {
|
||||
return Some(VerticalDirection::Down);
|
||||
} else if can_support_dripstone(block_above) {
|
||||
@ -342,12 +334,11 @@ async fn get_support_block_vertical_direction(
|
||||
None
|
||||
}
|
||||
},
|
||||
None => match player_option {
|
||||
Some(player) => {
|
||||
None => player_option.map_or(Some(VerticalDirection::Up), |player| {
|
||||
let (_, pitch) = player.rotation();
|
||||
let (can_place_above, can_place_below) = {
|
||||
let block_above = block_accessor.get_block(&position.up()).await;
|
||||
let block_below = block_accessor.get_block(&position.down()).await;
|
||||
let block_above = block_accessor.get_block(&position.up());
|
||||
let block_below = block_accessor.get_block(&position.down());
|
||||
(
|
||||
can_support_dripstone(block_above),
|
||||
can_support_dripstone(block_below),
|
||||
@ -365,9 +356,7 @@ async fn get_support_block_vertical_direction(
|
||||
(true, false) => Some(VerticalDirection::Up),
|
||||
(false, true) => Some(VerticalDirection::Down),
|
||||
}
|
||||
}
|
||||
None => Some(VerticalDirection::Up),
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
fn can_support_dripstone(support_block: &Block) -> bool {
|
||||
@ -384,7 +373,7 @@ async fn modify_dripstone_thickness_to(
|
||||
pos: &BlockPos,
|
||||
new_thickness: DripstoneThickness,
|
||||
) {
|
||||
let (block, support_block_state_id) = world.get_block_and_state_id(pos).await;
|
||||
let (block, support_block_state_id) = world.get_block_and_state_id(pos);
|
||||
|
||||
if block != &Block::POINTED_DRIPSTONE {
|
||||
//this shouldn't happen
|
||||
|
||||
@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, BlockFuture, NormalUseArgs};
|
||||
use pumpkin_data::translation;
|
||||
use pumpkin_data::{Block, translation};
|
||||
use pumpkin_inventory::enchanting::enchanting_screen_handler::EnchantingTableScreenHandler;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
use pumpkin_inventory::screen_handler::{
|
||||
@ -25,37 +25,28 @@ impl BlockBehaviour for EnchantingTableBlock {
|
||||
for off_z in -1..=1 {
|
||||
for off_x in -1..=1 {
|
||||
if (off_z != 0 || off_x != 0)
|
||||
&& args.world.get_block_state(&args.position.add(off_x, 0, off_z)).await.id == 0 // Air
|
||||
&& args.world.get_block_state(&args.position.add(off_x, 1, off_z)).await.id == 0
|
||||
&& args.world.get_block_state(&args.position.add(off_x, 0, off_z)).id == 0 // Air
|
||||
&& args.world.get_block_state(&args.position.add(off_x, 1, off_z)).id == 0
|
||||
// Air
|
||||
{
|
||||
for off_y in 0..=1 {
|
||||
if self
|
||||
.is_bookshelf(
|
||||
if Self::is_bookshelf(
|
||||
args.world,
|
||||
&args.position.add(off_x * 2, off_y, off_z * 2),
|
||||
)
|
||||
.await
|
||||
{
|
||||
) {
|
||||
bookshelf_count += 1;
|
||||
}
|
||||
if off_x != 0 && off_z != 0 {
|
||||
if self
|
||||
.is_bookshelf(
|
||||
if Self::is_bookshelf(
|
||||
args.world,
|
||||
&args.position.add(off_x * 2, off_y, off_z),
|
||||
)
|
||||
.await
|
||||
{
|
||||
) {
|
||||
bookshelf_count += 1;
|
||||
}
|
||||
if self
|
||||
.is_bookshelf(
|
||||
if Self::is_bookshelf(
|
||||
args.world,
|
||||
&args.position.add(off_x, off_y, off_z * 2),
|
||||
)
|
||||
.await
|
||||
{
|
||||
) {
|
||||
bookshelf_count += 1;
|
||||
}
|
||||
}
|
||||
@ -80,10 +71,10 @@ impl BlockBehaviour for EnchantingTableBlock {
|
||||
}
|
||||
|
||||
impl EnchantingTableBlock {
|
||||
async fn is_bookshelf(&self, world: &Arc<crate::world::World>, pos: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(pos).await;
|
||||
fn is_bookshelf(world: &Arc<crate::world::World>, pos: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(pos);
|
||||
let block = pumpkin_data::Block::from_state_id(state.id);
|
||||
block.name == "bookshelf"
|
||||
block == &Block::BOOKSHELF
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,8 +16,7 @@ impl BlockBehaviour for EndRodBlock {
|
||||
|
||||
let blockstate = args
|
||||
.world
|
||||
.get_block_state_id(&args.position.offset(args.direction.to_offset()))
|
||||
.await;
|
||||
.get_block_state_id(&args.position.offset(args.direction.to_offset()));
|
||||
|
||||
if Block::from_state_id(blockstate).eq(args.block)
|
||||
&& EndRodLikeProperties::from_state_id(blockstate, args.block).facing
|
||||
|
||||
@ -74,11 +74,11 @@ impl BlockBehaviour for EnderChestBlock {
|
||||
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
if is_chest_blocked(args.world, args.position).await {
|
||||
if is_chest_blocked(args.world, args.position) {
|
||||
return BlockActionResult::Success;
|
||||
}
|
||||
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(block_entity) = block_entity
|
||||
.as_any()
|
||||
.downcast_ref::<EnderChestBlockEntity>()
|
||||
@ -108,13 +108,13 @@ impl BlockBehaviour for EnderChestBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn is_chest_blocked(world: &World, block_pos: &BlockPos) -> bool {
|
||||
fn is_chest_blocked(world: &World, block_pos: &BlockPos) -> bool {
|
||||
// TODO: Block opening when a cat is sitting on top.
|
||||
has_block_on_top(world, block_pos).await
|
||||
has_block_on_top(world, block_pos)
|
||||
}
|
||||
async fn has_block_on_top(world: &World, block_pos: &BlockPos) -> bool {
|
||||
fn has_block_on_top(world: &World, block_pos: &BlockPos) -> bool {
|
||||
let above_pos = block_pos.up();
|
||||
let above_state = world.get_block_state(&above_pos).await;
|
||||
let above_state = world.get_block_state(&above_pos);
|
||||
above_state.is_solid_block()
|
||||
}
|
||||
impl EnderChestBlock {
|
||||
|
||||
@ -52,11 +52,11 @@ impl BlockBehaviour for FallingBlock {
|
||||
|
||||
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let (block, state) = args.world.get_block_and_state(&args.position.down()).await;
|
||||
let (block, state) = args.world.get_block_and_state(&args.position.down());
|
||||
if !Self::can_fall_through(state, block) || args.position.0.y < args.world.min_y {
|
||||
return;
|
||||
}
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
let state = args.world.get_block_state(args.position);
|
||||
FallingEntity::replace_spawn(args.world, *args.position, state.id).await;
|
||||
})
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ impl BlockBehaviour for FarmlandBlock {
|
||||
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
return Block::DIRT.default_state.id;
|
||||
}
|
||||
args.block.default_state.id
|
||||
@ -55,9 +55,7 @@ impl BlockBehaviour for FarmlandBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if args.direction == BlockDirection::Up
|
||||
&& !can_place_at(args.world, args.position).await
|
||||
{
|
||||
if args.direction == BlockDirection::Up && !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -66,14 +64,14 @@ impl BlockBehaviour for FarmlandBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn random_tick<'a>(&'a self, args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
// TODO: add rain check. Remember to check which one is most optimized.
|
||||
if is_water_nearby(args.world, args.position).await {
|
||||
if is_water_nearby(args.world, args.position) {
|
||||
let mut props = FarmlandProperties::default(args.block);
|
||||
props.moisture = 7;
|
||||
args.world
|
||||
@ -84,13 +82,12 @@ impl BlockBehaviour for FarmlandBlock {
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let mut props = FarmlandProperties::from_state_id(state_id, args.block);
|
||||
if props.moisture == 0 {
|
||||
if !args
|
||||
.world
|
||||
.get_block(&args.position.up())
|
||||
.await
|
||||
.has_tag(&tag::Block::MINECRAFT_MAINTAINS_FARMLAND)
|
||||
{
|
||||
//TODO push entities up
|
||||
@ -117,12 +114,12 @@ impl BlockBehaviour for FarmlandBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&block_pos.up()).await;
|
||||
fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let state = world.get_block_state(&block_pos.up());
|
||||
!state.is_solid() // TODO: add fence gate block
|
||||
}
|
||||
|
||||
async fn is_water_nearby(world: &Arc<World>, block_pos: &BlockPos) -> bool {
|
||||
fn is_water_nearby(world: &Arc<World>, block_pos: &BlockPos) -> bool {
|
||||
for dx in -4..=4 {
|
||||
for dy in 0..=1 {
|
||||
for dz in -4..=4 {
|
||||
@ -132,7 +129,7 @@ async fn is_water_nearby(world: &Arc<World>, block_pos: &BlockPos) -> bool {
|
||||
z: dz,
|
||||
});
|
||||
//TODO this should use tag water. It does not seem to work rn.
|
||||
if world.get_block(&check_pos).await == &Block::WATER {
|
||||
if world.get_block(&check_pos) == &Block::WATER {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ pub async fn toggle_fence_gate(
|
||||
block_pos: &BlockPos,
|
||||
player: &Player,
|
||||
) -> BlockStateId {
|
||||
let (block, state) = world.get_block_and_state_id(block_pos).await;
|
||||
let (block, state) = world.get_block_and_state_id(block_pos);
|
||||
|
||||
let mut fence_gate_props = FenceGateProperties::from_state_id(state, block);
|
||||
if fence_gate_props.open {
|
||||
@ -60,14 +60,12 @@ pub async fn toggle_fence_gate(
|
||||
fence_gate_props.open = true;
|
||||
}
|
||||
|
||||
world
|
||||
.play_block_sound_expect(
|
||||
world.play_block_sound_expect(
|
||||
player,
|
||||
get_sound(block, fence_gate_props.open),
|
||||
SoundCategory::Blocks,
|
||||
*block_pos,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
|
||||
world
|
||||
.set_block_state(
|
||||
@ -101,7 +99,7 @@ impl BlockBehaviour for FenceGateBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
let fence_props = is_in_wall(&args).await;
|
||||
let fence_props = is_in_wall(&args);
|
||||
fence_props.to_state_id(args.block)
|
||||
})
|
||||
}
|
||||
@ -116,7 +114,7 @@ impl BlockBehaviour for FenceGateBlock {
|
||||
|
||||
fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let block_state = args.world.get_block_state(args.position).await;
|
||||
let block_state = args.world.get_block_state(args.position);
|
||||
let mut fence_gate_props =
|
||||
FenceGateProperties::from_state_id(block_state.id, args.block);
|
||||
let powered = block_receives_redstone_power(args.world, args.position).await;
|
||||
@ -130,13 +128,11 @@ impl BlockBehaviour for FenceGateBlock {
|
||||
if powered != fence_gate_props.open {
|
||||
fence_gate_props.open = powered;
|
||||
|
||||
args.world
|
||||
.play_block_sound(
|
||||
args.world.play_block_sound(
|
||||
get_sound(args.block, powered),
|
||||
SoundCategory::Blocks,
|
||||
*args.position,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
}
|
||||
|
||||
args.world
|
||||
@ -150,7 +146,7 @@ impl BlockBehaviour for FenceGateBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn is_in_wall(args: &GetStateForNeighborUpdateArgs<'_>) -> FenceGateProperties {
|
||||
fn is_in_wall(args: &GetStateForNeighborUpdateArgs<'_>) -> FenceGateProperties {
|
||||
let mut fence_props = FenceGateProperties::from_state_id(args.state_id, args.block);
|
||||
|
||||
let side_offset_left = args
|
||||
@ -165,8 +161,8 @@ async fn is_in_wall(args: &GetStateForNeighborUpdateArgs<'_>) -> FenceGateProper
|
||||
args.neighbor_position == &side_offset_left || args.neighbor_position == &side_offset_right;
|
||||
|
||||
if neighbor_on_side {
|
||||
let neighbor_right = args.world.get_block(&side_offset_right).await;
|
||||
let neighbor_left = args.world.get_block(&side_offset_left).await;
|
||||
let neighbor_right = args.world.get_block(&side_offset_right);
|
||||
let neighbor_left = args.world.get_block(&side_offset_left);
|
||||
|
||||
fence_props.in_wall = neighbor_left.has_tag(&tag::Block::MINECRAFT_WALLS)
|
||||
|| neighbor_right.has_tag(&tag::Block::MINECRAFT_WALLS);
|
||||
|
||||
@ -28,7 +28,7 @@ impl BlockBehaviour for FenceBlock {
|
||||
let mut fence_props = FenceProperties::default(args.block);
|
||||
fence_props.waterlogged = args.replacing.water_source();
|
||||
|
||||
compute_fence_state(fence_props, args.world, args.block, args.position).await
|
||||
compute_fence_state(fence_props, args.world, args.block, args.position)
|
||||
})
|
||||
}
|
||||
|
||||
@ -38,12 +38,12 @@ impl BlockBehaviour for FenceBlock {
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
let fence_props = FenceProperties::from_state_id(args.state_id, args.block);
|
||||
compute_fence_state(fence_props, args.world, args.block, args.position).await
|
||||
compute_fence_state(fence_props, args.world, args.block, args.position)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn compute_fence_state(
|
||||
pub fn compute_fence_state(
|
||||
mut fence_props: FenceProperties,
|
||||
world: &World,
|
||||
block: &Block,
|
||||
@ -51,7 +51,7 @@ pub async fn compute_fence_state(
|
||||
) -> u16 {
|
||||
for direction in BlockDirection::horizontal() {
|
||||
let other_block_pos = block_pos.offset(direction.to_offset());
|
||||
let (other_block, other_block_state) = world.get_block_and_state(&other_block_pos).await;
|
||||
let (other_block, other_block_state) = world.get_block_and_state(&other_block_pos);
|
||||
|
||||
let connected = connects_to(block, other_block, other_block_state, direction);
|
||||
match direction {
|
||||
|
||||
@ -54,14 +54,10 @@ impl FireBlock {
|
||||
.is_some_and(|f| f.burn_chance > 0)
|
||||
}
|
||||
|
||||
async fn are_blocks_around_flammable(
|
||||
&self,
|
||||
block_accessor: &dyn BlockAccessor,
|
||||
pos: &BlockPos,
|
||||
) -> bool {
|
||||
fn are_blocks_around_flammable(block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
for direction in BlockDirection::all() {
|
||||
let neighbor_pos = pos.offset(direction.to_offset());
|
||||
let block_state = block_accessor.get_block_state(&neighbor_pos).await;
|
||||
let block_state = block_accessor.get_block_state(&neighbor_pos);
|
||||
if Self::is_flammable(block_state) {
|
||||
return true;
|
||||
}
|
||||
@ -69,21 +65,21 @@ impl FireBlock {
|
||||
false
|
||||
}
|
||||
|
||||
pub async fn get_state_for_position(
|
||||
pub fn get_state_for_position(
|
||||
&self,
|
||||
world: &World,
|
||||
block: &Block,
|
||||
pos: &BlockPos,
|
||||
) -> BlockStateId {
|
||||
let down_pos = pos.down();
|
||||
let down_state = world.get_block_state(&down_pos).await;
|
||||
let down_state = world.get_block_state(&down_pos);
|
||||
if Self::is_flammable(down_state) || down_state.is_side_solid(BlockDirection::Up) {
|
||||
return block.default_state.id;
|
||||
}
|
||||
let mut fire_props = FireProperties::from_state_id(block.default_state.id, block);
|
||||
for direction in BlockDirection::all() {
|
||||
let neighbor_pos = pos.offset(direction.to_offset());
|
||||
let neighbor_state = world.get_block_state(&neighbor_pos).await;
|
||||
let neighbor_state = world.get_block_state(&neighbor_pos);
|
||||
if Self::is_flammable(neighbor_state) {
|
||||
match direction {
|
||||
BlockDirection::North => fire_props.north = true,
|
||||
@ -99,16 +95,16 @@ impl FireBlock {
|
||||
}
|
||||
|
||||
// Used for spreading fire
|
||||
pub async fn get_burn_chance(&self, world: &Arc<World>, pos: &BlockPos) -> i32 {
|
||||
let block_state = world.get_block_state(pos).await;
|
||||
pub fn get_burn_chance(&self, world: &Arc<World>, pos: &BlockPos) -> i32 {
|
||||
let block_state = world.get_block_state(pos);
|
||||
if !block_state.is_air() {
|
||||
return 0;
|
||||
}
|
||||
let mut total_burn_chance = 0;
|
||||
|
||||
for dir in BlockDirection::all() {
|
||||
let neighbor_block = world.get_block(&pos.offset(dir.to_offset())).await;
|
||||
if world.get_fluid(&pos.offset(dir.to_offset())).await.name != Fluid::EMPTY.name {
|
||||
let neighbor_block = world.get_block(&pos.offset(dir.to_offset()));
|
||||
if world.get_fluid(&pos.offset(dir.to_offset())).name != Fluid::EMPTY.name {
|
||||
continue; // Skip if there is a fluid
|
||||
}
|
||||
if let Some(flammable) = &neighbor_block.flammable {
|
||||
@ -130,7 +126,7 @@ impl FireBlock {
|
||||
block.flammable.as_ref().map_or(0, |f| f.burn_chance.into())
|
||||
}
|
||||
|
||||
async fn is_increased_burnout_biome(world: &World, pos: &BlockPos) -> bool {
|
||||
fn is_increased_burnout_biome(world: &World, pos: &BlockPos) -> bool {
|
||||
// Fire burnout increases in the Nether
|
||||
if world.dimension == Dimension::THE_NETHER {
|
||||
return true;
|
||||
@ -138,7 +134,7 @@ impl FireBlock {
|
||||
|
||||
// Fire burnout increases in specific biomes
|
||||
// TODO: Use proper tag or bool for this when available
|
||||
let biome_id = world.level.get_rough_biome(pos).await.id;
|
||||
let biome_id = world.level.get_rough_biome(pos).id;
|
||||
matches!(
|
||||
biome_id,
|
||||
id if id == Biome::BAMBOO_JUNGLE.id
|
||||
@ -153,7 +149,7 @@ impl FireBlock {
|
||||
}
|
||||
|
||||
async fn try_spreading_fire(&self, world: &Arc<World>, pos: &BlockPos, chance: i32, age: u8) {
|
||||
let block = world.get_block(pos).await;
|
||||
let block = world.get_block(pos);
|
||||
let odds = Self::get_burn_odds(block);
|
||||
if rand::rng().random_range(0..chance) < odds {
|
||||
let old_block = block;
|
||||
@ -161,9 +157,7 @@ impl FireBlock {
|
||||
&& !Self::is_near_rain(world.as_ref(), pos)
|
||||
{
|
||||
let new_age = (age + (rand::rng().random_range(0..5) / 4)).min(15) as u8;
|
||||
let state_id = self
|
||||
.get_state_for_position(world.as_ref(), &Block::FIRE, pos)
|
||||
.await;
|
||||
let state_id = self.get_state_for_position(world.as_ref(), &Block::FIRE, pos);
|
||||
let mut fire_props = FireProperties::from_state_id(state_id, &Block::FIRE);
|
||||
fire_props.age = new_age;
|
||||
let new_state_id = fire_props.to_state_id(&Block::FIRE);
|
||||
@ -199,7 +193,7 @@ impl BlockBehaviour for FireBlock {
|
||||
// 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 == &Dimension::OVERWORLD || dimension == &Dimension::THE_NETHER)
|
||||
&& let Some(portal) =
|
||||
NetherPortal::get_new_portal(args.world, args.position, HorizontalAxis::X).await
|
||||
NetherPortal::get_new_portal(args.world, args.position, HorizontalAxis::X)
|
||||
{
|
||||
portal.create(args.world).await;
|
||||
return;
|
||||
@ -225,8 +219,7 @@ impl BlockBehaviour for FireBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if self
|
||||
.can_place_at(CanPlaceAtArgs {
|
||||
if self.can_place_at(CanPlaceAtArgs {
|
||||
server: None,
|
||||
world: Some(args.world),
|
||||
block_accessor: args.world,
|
||||
@ -236,13 +229,10 @@ impl BlockBehaviour for FireBlock {
|
||||
direction: None,
|
||||
player: None,
|
||||
use_item_on: None,
|
||||
})
|
||||
.await
|
||||
{
|
||||
}) {
|
||||
let old_fire_props = FireProperties::from_state_id(args.state_id, &Block::FIRE);
|
||||
let fire_state_id = self
|
||||
.get_state_for_position(args.world, &Block::FIRE, args.position)
|
||||
.await;
|
||||
let fire_state_id =
|
||||
self.get_state_for_position(args.world, &Block::FIRE, args.position);
|
||||
let mut fire_props = FireProperties::from_state_id(fire_state_id, &Block::FIRE);
|
||||
fire_props.age = old_fire_props.age;
|
||||
return fire_props.to_state_id(&Block::FIRE);
|
||||
@ -251,18 +241,12 @@ impl BlockBehaviour for FireBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
let state = args
|
||||
.block_accessor
|
||||
.get_block_state(&args.position.down())
|
||||
.await;
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
let state = args.block_accessor.get_block_state(&args.position.down());
|
||||
if state.is_side_solid(BlockDirection::Up) {
|
||||
return true;
|
||||
}
|
||||
self.are_blocks_around_flammable(args.block_accessor, args.position)
|
||||
.await
|
||||
})
|
||||
Self::are_blocks_around_flammable(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
@ -281,8 +265,7 @@ impl BlockBehaviour for FireBlock {
|
||||
.await;
|
||||
|
||||
// Check if fire can survive
|
||||
if !Self
|
||||
.can_place_at(CanPlaceAtArgs {
|
||||
if !self.can_place_at(CanPlaceAtArgs {
|
||||
server: None,
|
||||
world: Some(world),
|
||||
block_accessor: world.as_ref(),
|
||||
@ -292,9 +275,7 @@ impl BlockBehaviour for FireBlock {
|
||||
direction: None,
|
||||
player: None,
|
||||
use_item_on: None,
|
||||
})
|
||||
.await
|
||||
{
|
||||
}) {
|
||||
world
|
||||
.set_block_state(
|
||||
pos,
|
||||
@ -305,8 +286,8 @@ impl BlockBehaviour for FireBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
let block_state = world.get_block_state(pos).await;
|
||||
let block_below = world.get_block(&pos.down()).await;
|
||||
let block_state = world.get_block_state(pos);
|
||||
let block_below = world.get_block(&pos.down());
|
||||
|
||||
// Check for infiniburn blocks (depending on dimension)
|
||||
let infiniburn = match world.dimension.id {
|
||||
@ -353,8 +334,8 @@ impl BlockBehaviour for FireBlock {
|
||||
|
||||
if !infiniburn {
|
||||
// Check if fire should extinguish due to lack of fuel
|
||||
if !self.are_blocks_around_flammable(world.as_ref(), pos).await {
|
||||
let block_below_state = world.get_block_state(&pos.down()).await;
|
||||
if !Self::are_blocks_around_flammable(world.as_ref(), pos) {
|
||||
let block_below_state = world.get_block_state(&pos.down());
|
||||
if !block_below_state.is_side_solid(BlockDirection::Up) || new_age > 3 {
|
||||
world
|
||||
.set_block_state(
|
||||
@ -370,7 +351,7 @@ impl BlockBehaviour for FireBlock {
|
||||
// At max age, fire has a chance to extinguish if not on flammable block
|
||||
if new_age == 15
|
||||
&& rand::rng().random_range(0..4) == 0
|
||||
&& !Self::is_flammable(world.get_block_state(&pos.down()).await)
|
||||
&& !Self::is_flammable(world.get_block_state(&pos.down()))
|
||||
{
|
||||
world
|
||||
.set_block_state(
|
||||
@ -384,7 +365,7 @@ impl BlockBehaviour for FireBlock {
|
||||
}
|
||||
|
||||
// Burn adjacent blocks
|
||||
let extra = if Self::is_increased_burnout_biome(world, pos).await {
|
||||
let extra = if Self::is_increased_burnout_biome(world, pos) {
|
||||
-50 // Increases chance of block being destroyed
|
||||
} else {
|
||||
0
|
||||
@ -448,7 +429,7 @@ impl BlockBehaviour for FireBlock {
|
||||
for yy in -1..=4 {
|
||||
if xx != 0 || yy != 0 || zz != 0 {
|
||||
let offset_pos = pos.offset(Vector3::new(xx, yy, zz));
|
||||
let ignite_odds = self.get_burn_chance(world, &offset_pos).await;
|
||||
let ignite_odds = self.get_burn_chance(world, &offset_pos);
|
||||
|
||||
if ignite_odds > 0 {
|
||||
// Skip if spreding is disabled or if there are no players nearby
|
||||
@ -473,7 +454,7 @@ impl BlockBehaviour for FireBlock {
|
||||
(ignite_odds + 40 + difficulty * 7) / (new_age as i32 + 30);
|
||||
|
||||
// Reduce spread odds in certain biomes
|
||||
if Self::is_increased_burnout_biome(world, &offset_pos).await {
|
||||
if Self::is_increased_burnout_biome(world, &offset_pos) {
|
||||
odds /= 2; // Fire spreads 50% slower
|
||||
}
|
||||
|
||||
@ -484,9 +465,11 @@ impl BlockBehaviour for FireBlock {
|
||||
let spread_age = (new_age + rand::rng().random_range(0..5) / 4)
|
||||
.min(15)
|
||||
as u8;
|
||||
let fire_state_id = self
|
||||
.get_state_for_position(world.as_ref(), block, &offset_pos)
|
||||
.await;
|
||||
let fire_state_id = self.get_state_for_position(
|
||||
world.as_ref(),
|
||||
block,
|
||||
&offset_pos,
|
||||
);
|
||||
let mut new_fire_props =
|
||||
FireProperties::from_state_id(fire_state_id, &Block::FIRE);
|
||||
new_fire_props.age = spread_age;
|
||||
@ -509,7 +492,7 @@ impl BlockBehaviour for FireBlock {
|
||||
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
FireBlockBase::broken(args.world, *args.position).await;
|
||||
FireBlockBase::broken(args.world, *args.position);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,8 +26,8 @@ pub mod soul_fire;
|
||||
pub struct FireBlockBase;
|
||||
|
||||
impl FireBlockBase {
|
||||
pub async fn get_fire_type(world: &World, pos: &BlockPos) -> Block {
|
||||
let block = world.get_block(&pos.down()).await;
|
||||
pub fn get_fire_type(world: &World, pos: &BlockPos) -> Block {
|
||||
let block = world.get_block(&pos.down());
|
||||
if SoulFireBlock::is_soul_base(block) {
|
||||
return Block::SOUL_FIRE;
|
||||
}
|
||||
@ -43,19 +43,18 @@ impl FireBlockBase {
|
||||
&& block != &Block::LAVA
|
||||
}
|
||||
|
||||
pub async fn is_soul_fire(world: &Arc<World>, block_pos: &BlockPos) -> bool {
|
||||
let block = world.get_block(&block_pos.down()).await;
|
||||
pub fn is_soul_fire(world: &Arc<World>, block_pos: &BlockPos) -> bool {
|
||||
let block = world.get_block(&block_pos.down());
|
||||
block.has_tag(&tag::Block::MINECRAFT_SOUL_FIRE_BASE_BLOCKS)
|
||||
}
|
||||
|
||||
pub async fn can_place_at(world: &Arc<World>, block_pos: &BlockPos) -> bool {
|
||||
let block_state = world.get_block_state(block_pos).await;
|
||||
pub fn can_place_at(world: &Arc<World>, block_pos: &BlockPos) -> bool {
|
||||
let block_state = world.get_block_state(block_pos);
|
||||
if !block_state.is_air() {
|
||||
return false;
|
||||
}
|
||||
if Self::is_soul_fire(world, block_pos).await {
|
||||
SoulFireBlock
|
||||
.can_place_at(CanPlaceAtArgs {
|
||||
if Self::is_soul_fire(world, block_pos) {
|
||||
SoulFireBlock.can_place_at(CanPlaceAtArgs {
|
||||
server: None,
|
||||
world: Some(world),
|
||||
block_accessor: world.as_ref(),
|
||||
@ -66,10 +65,8 @@ impl FireBlockBase {
|
||||
player: None,
|
||||
use_item_on: None,
|
||||
})
|
||||
.await
|
||||
} else {
|
||||
FireBlock
|
||||
.can_place_at(CanPlaceAtArgs {
|
||||
FireBlock.can_place_at(CanPlaceAtArgs {
|
||||
server: None,
|
||||
world: Some(world),
|
||||
block_accessor: world.as_ref(),
|
||||
@ -79,13 +76,11 @@ impl FireBlockBase {
|
||||
direction: None,
|
||||
player: None,
|
||||
use_item_on: None,
|
||||
})
|
||||
.await
|
||||
|| Self::should_light_portal_at(world, block_pos, BlockDirection::Up).await
|
||||
}) || Self::should_light_portal_at(world, block_pos, BlockDirection::Up)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn should_light_portal_at(
|
||||
pub fn should_light_portal_at(
|
||||
world: &Arc<World>,
|
||||
block_pos: &BlockPos,
|
||||
direction: BlockDirection,
|
||||
@ -97,7 +92,7 @@ impl FireBlockBase {
|
||||
let mut found = false;
|
||||
|
||||
for dir in BlockDirection::all() {
|
||||
if world.get_block(&block_pos.offset(dir.to_offset())).await == &Block::OBSIDIAN {
|
||||
if world.get_block(&block_pos.offset(dir.to_offset())) == &Block::OBSIDIAN {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@ -114,9 +109,7 @@ impl FireBlockBase {
|
||||
Xoroshiro::from_seed(rand::rng().random()),
|
||||
))
|
||||
};
|
||||
return NetherPortal::get_new_portal(world, block_pos, dir.to_horizontal_axis().unwrap())
|
||||
.await
|
||||
.is_some();
|
||||
NetherPortal::get_new_portal(world, block_pos, dir.to_horizontal_axis().unwrap()).is_some()
|
||||
}
|
||||
|
||||
/// Shared fire collision behavior used by `fire` and `soul_fire`.
|
||||
@ -162,9 +155,7 @@ impl FireBlockBase {
|
||||
})
|
||||
}
|
||||
|
||||
async fn broken(world: &World, block_pos: BlockPos) {
|
||||
world
|
||||
.sync_world_event(WorldEvent::SoundExtinguishFire, block_pos, 0)
|
||||
.await;
|
||||
fn broken(world: &World, block_pos: BlockPos) {
|
||||
world.sync_world_event(WorldEvent::SoundExtinguishFire, block_pos, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ impl BlockBehaviour for SoulFireBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !Self::is_soul_base(args.world.get_block(&args.position.down()).await) {
|
||||
if !Self::is_soul_base(args.world.get_block(&args.position.down())) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
|
||||
@ -38,15 +38,13 @@ impl BlockBehaviour for SoulFireBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
Self::is_soul_base(args.block_accessor.get_block(&args.position.down()).await)
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
Self::is_soul_base(args.block_accessor.get_block(&args.position.down()))
|
||||
}
|
||||
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
FireBlockBase::broken(args.world, *args.position).await;
|
||||
FireBlockBase::broken(args.world, *args.position);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ pub struct FurnaceBlock;
|
||||
impl BlockBehaviour for FurnaceBlock {
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.clone().get_inventory()
|
||||
&& let Some(property_delegate) = block_entity.clone().to_property_delegate()
|
||||
&& let Some(experience_container) = block_entity.to_experience_container()
|
||||
@ -126,7 +126,7 @@ impl BlockBehaviour for FurnaceBlock {
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
// Extract and drop accumulated XP as orbs before removing the block entity
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(experience_container) = block_entity.to_experience_container()
|
||||
{
|
||||
let xp = experience_container.extract_experience();
|
||||
|
||||
@ -26,7 +26,7 @@ impl BlockBehaviour for GlassPaneBlock {
|
||||
let mut pane_props = GlassPaneProperties::default(args.block);
|
||||
pane_props.waterlogged = args.replacing.water_source();
|
||||
|
||||
compute_pane_state(pane_props, args.world, args.block, args.position).await
|
||||
compute_pane_state(pane_props, args.world, args.block, args.position)
|
||||
})
|
||||
}
|
||||
|
||||
@ -36,12 +36,12 @@ impl BlockBehaviour for GlassPaneBlock {
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
let pane_props = GlassPaneProperties::from_state_id(args.state_id, args.block);
|
||||
compute_pane_state(pane_props, args.world, args.block, args.position).await
|
||||
compute_pane_state(pane_props, args.world, args.block, args.position)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn compute_pane_state(
|
||||
pub fn compute_pane_state(
|
||||
mut pane_props: GlassPaneProperties,
|
||||
world: &World,
|
||||
block: &Block,
|
||||
@ -49,7 +49,7 @@ pub async fn compute_pane_state(
|
||||
) -> u16 {
|
||||
for direction in BlockDirection::horizontal() {
|
||||
let other_block_pos = block_pos.offset(direction.to_offset());
|
||||
let (other_block, other_block_state) = world.get_block_and_state(&other_block_pos).await;
|
||||
let (other_block, other_block_state) = world.get_block_and_state(&other_block_pos);
|
||||
|
||||
let connected = other_block == block
|
||||
|| other_block_state.is_side_solid(direction.opposite())
|
||||
|
||||
@ -27,16 +27,13 @@ impl BlockBehaviour for GrindstoneBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
// Use the provided direction, or fallback to the current state's direction if missing
|
||||
let direction = args
|
||||
.direction
|
||||
.unwrap_or_else(|| self.get_direction(args.state.id, args.block));
|
||||
|
||||
WallMountedBlock::can_place_at(self, args.block_accessor, args.position, direction)
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -53,8 +50,8 @@ impl WallMountedBlock for GrindstoneBlock {
|
||||
_world: &'a dyn BlockAccessor,
|
||||
_pos: &'a BlockPos,
|
||||
_direction: BlockDirection,
|
||||
) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { true })
|
||||
) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn get_direction(&self, state_id: BlockStateId, block: &Block) -> BlockDirection {
|
||||
|
||||
@ -59,7 +59,7 @@ type HopperLikeProperties = pumpkin_data::block_properties::HopperLikeProperties
|
||||
impl BlockBehaviour for HopperBlock {
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(inventory) = block_entity.get_inventory()
|
||||
{
|
||||
args.player
|
||||
@ -104,7 +104,7 @@ impl BlockBehaviour for HopperBlock {
|
||||
check_powered_state(
|
||||
args.world,
|
||||
args.position,
|
||||
args.world.get_block_state_id(args.position).await,
|
||||
args.world.get_block_state_id(args.position),
|
||||
args.block,
|
||||
)
|
||||
.await;
|
||||
|
||||
@ -23,7 +23,7 @@ impl BlockBehaviour for IronBarsBlock {
|
||||
let mut bars_props = IronBarsProperties::default(args.block);
|
||||
bars_props.waterlogged = args.replacing.water_source();
|
||||
|
||||
compute_bars_state(bars_props, args.world, args.block, args.position).await
|
||||
compute_bars_state(bars_props, args.world, args.block, args.position)
|
||||
})
|
||||
}
|
||||
|
||||
@ -33,12 +33,12 @@ impl BlockBehaviour for IronBarsBlock {
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
let bars_props = IronBarsProperties::from_state_id(args.state_id, args.block);
|
||||
compute_bars_state(bars_props, args.world, args.block, args.position).await
|
||||
compute_bars_state(bars_props, args.world, args.block, args.position)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn compute_bars_state(
|
||||
pub fn compute_bars_state(
|
||||
mut bars_props: IronBarsProperties,
|
||||
world: &World,
|
||||
block: &Block,
|
||||
@ -46,7 +46,7 @@ pub async fn compute_bars_state(
|
||||
) -> u16 {
|
||||
for direction in BlockDirection::horizontal() {
|
||||
let other_block_pos = block_pos.offset(direction.to_offset());
|
||||
let (other_block, other_block_state) = world.get_block_and_state(&other_block_pos).await;
|
||||
let (other_block, other_block_state) = world.get_block_and_state(&other_block_pos);
|
||||
|
||||
let connected = other_block == block
|
||||
|| other_block_state.is_side_solid(direction.opposite())
|
||||
|
||||
@ -52,7 +52,7 @@ impl JukeboxBlock {
|
||||
/// Drops the record from the jukebox - matches vanilla's `JukeboxBlockEntity.dropRecord()`
|
||||
/// Spawns item at (pos + 0.5, pos + 1.01, pos + 0.5) with horizontal random offset
|
||||
async fn drop_record(position: &BlockPos, world: &Arc<World>) {
|
||||
if let Some(block_entity) = world.get_block_entity(position).await
|
||||
if let Some(block_entity) = world.get_block_entity(position)
|
||||
&& let Some(jukebox_entity) = block_entity.as_any().downcast_ref::<JukeboxBlockEntity>()
|
||||
{
|
||||
let record = jukebox_entity.clear_record().await;
|
||||
@ -67,7 +67,7 @@ impl JukeboxBlock {
|
||||
|
||||
let entity = Entity::new(world.clone(), spawn_pos, &EntityType::ITEM);
|
||||
// Vanilla: setToDefaultPickupDelay() = 10 ticks
|
||||
let item_entity = Arc::new(ItemEntity::new(entity, record).await);
|
||||
let item_entity = Arc::new(ItemEntity::new(entity, record));
|
||||
world.spawn_entity(item_entity).await;
|
||||
}
|
||||
}
|
||||
@ -76,16 +76,12 @@ impl JukeboxBlock {
|
||||
/// Stops the music and updates block state
|
||||
async fn stop_playing(block: &Block, position: &BlockPos, world: &Arc<World>) {
|
||||
Self::set_record_state(false, block, position, world).await;
|
||||
world
|
||||
.sync_world_event(WorldEvent::SoundStopJukeboxSong, *position, 0)
|
||||
.await;
|
||||
world.sync_world_event(WorldEvent::SoundStopJukeboxSong, *position, 0);
|
||||
}
|
||||
|
||||
/// Starts playing music
|
||||
async fn start_playing(position: &BlockPos, world: &Arc<World>, song_id: u32) {
|
||||
world
|
||||
.sync_world_event(WorldEvent::SoundPlayJukeboxSong, *position, song_id as i32)
|
||||
.await;
|
||||
fn start_playing(position: &BlockPos, world: &Arc<World>, song_id: u32) {
|
||||
world.sync_world_event(WorldEvent::SoundPlayJukeboxSong, *position, song_id as i32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +98,7 @@ impl BlockBehaviour for JukeboxBlock {
|
||||
/// Vanilla: `JukeboxBlock.onUse()` - drops record if present
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state(args.position).await.id;
|
||||
let state_id = args.world.get_block_state(args.position).id;
|
||||
|
||||
// Vanilla: if (state.get(HAS_RECORD) && world.getBlockEntity(pos) instanceof JukeboxBlockEntity lv)
|
||||
if Self::has_record_state(args.block, state_id) {
|
||||
@ -125,7 +121,7 @@ impl BlockBehaviour for JukeboxBlock {
|
||||
) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let world = args.world;
|
||||
let state_id = world.get_block_state(args.position).await.id;
|
||||
let state_id = world.get_block_state(args.position).id;
|
||||
|
||||
// Vanilla: if (state.get(HAS_RECORD)) return PASS_TO_DEFAULT_BLOCK_ACTION
|
||||
if Self::has_record_state(args.block, state_id) {
|
||||
@ -157,7 +153,7 @@ impl BlockBehaviour for JukeboxBlock {
|
||||
let record = item_stack.split_unless_creative(args.player.gamemode.load(), 1);
|
||||
|
||||
// Vanilla: lv4.setStack(lv3)
|
||||
if let Some(block_entity) = world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = world.get_block_entity(args.position)
|
||||
&& let Some(jukebox_entity) =
|
||||
block_entity.as_any().downcast_ref::<JukeboxBlockEntity>()
|
||||
{
|
||||
@ -170,7 +166,7 @@ impl BlockBehaviour for JukeboxBlock {
|
||||
Self::set_record_state(true, args.block, args.position, world).await;
|
||||
|
||||
// Start playing the music (client-side audio)
|
||||
Self::start_playing(args.position, world, jukebox_song.get_id()).await;
|
||||
Self::start_playing(args.position, world, jukebox_song.get_id());
|
||||
|
||||
// TODO: world.emitGameEvent(GameEvent.BLOCK_CHANGE, pos, ...)
|
||||
// TODO: player.incrementStat(Stats.PLAY_RECORD)
|
||||
@ -186,8 +182,7 @@ impl BlockBehaviour for JukeboxBlock {
|
||||
Self::drop_record(args.position, args.world).await;
|
||||
// Stop the music
|
||||
args.world
|
||||
.sync_world_event(WorldEvent::SoundStopJukeboxSong, *args.position, 0)
|
||||
.await;
|
||||
.sync_world_event(WorldEvent::SoundStopJukeboxSong, *args.position, 0);
|
||||
})
|
||||
}
|
||||
|
||||
@ -214,7 +209,7 @@ impl BlockBehaviour for JukeboxBlock {
|
||||
) -> BlockFuture<'a, u8> {
|
||||
Box::pin(async move {
|
||||
// Vanilla: return world.getBlockEntity(pos) instanceof JukeboxBlockEntity lv && lv.getManager().isPlaying() ? 15 : 0
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(jukebox_entity) =
|
||||
block_entity.as_any().downcast_ref::<JukeboxBlockEntity>()
|
||||
&& jukebox_entity.is_playing()
|
||||
@ -233,7 +228,7 @@ impl BlockBehaviour for JukeboxBlock {
|
||||
) -> BlockFuture<'a, Option<u8>> {
|
||||
Box::pin(async move {
|
||||
// Vanilla: return world.getBlockEntity(pos) instanceof JukeboxBlockEntity lv ? lv.getComparatorOutput() : 0
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(jukebox_entity) =
|
||||
block_entity.as_any().downcast_ref::<JukeboxBlockEntity>()
|
||||
{
|
||||
|
||||
@ -20,7 +20,7 @@ impl BlockBehaviour for LadderBlock {
|
||||
Box::pin(async move {
|
||||
let clicked_pos = args.use_item_on.position;
|
||||
let (clicked_block, clicked_block_state_id) =
|
||||
args.world.get_block_and_state_id(&clicked_pos).await;
|
||||
args.world.get_block_and_state_id(&clicked_pos);
|
||||
if clicked_block == &Block::LADDER {
|
||||
//you can't click on a ladder and place a ladder
|
||||
let props =
|
||||
@ -38,7 +38,7 @@ impl BlockBehaviour for LadderBlock {
|
||||
if dir == Facing::Up || dir == Facing::Down {
|
||||
continue;
|
||||
}
|
||||
if !can_place_ladder_at(args.world, args.position, dir.to_block_direction()).await {
|
||||
if !can_place_ladder_at(args.world, args.position, dir.to_block_direction()) {
|
||||
continue;
|
||||
}
|
||||
props.facing = dir
|
||||
@ -51,19 +51,17 @@ impl BlockBehaviour for LadderBlock {
|
||||
Block::AIR.default_state.id
|
||||
})
|
||||
}
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
for dir in BlockDirection::horizontal() {
|
||||
let Some(world) = args.world else {
|
||||
//this won't happen
|
||||
return false;
|
||||
};
|
||||
if can_place_ladder_at(world, args.position, dir).await {
|
||||
if can_place_ladder_at(world, args.position, dir) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -77,7 +75,6 @@ impl BlockBehaviour for LadderBlock {
|
||||
args.position,
|
||||
props.facing.to_block_direction().opposite(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -87,7 +84,7 @@ impl BlockBehaviour for LadderBlock {
|
||||
|
||||
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
if Block::from_state_id(state_id) != &Block::LADDER {
|
||||
return;
|
||||
}
|
||||
@ -96,9 +93,7 @@ impl BlockBehaviour for LadderBlock {
|
||||
args.world,
|
||||
args.position,
|
||||
props.facing.to_block_direction().opposite(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -116,9 +111,8 @@ pub const fn horizontal_facing_from_offset(offset: Vector3<i32>) -> Option<Block
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
async fn can_place_ladder_at(world: &World, block_pos: &BlockPos, facing: BlockDirection) -> bool {
|
||||
fn can_place_ladder_at(world: &World, block_pos: &BlockPos, facing: BlockDirection) -> bool {
|
||||
world
|
||||
.get_block_state(&block_pos.offset(facing.to_offset()))
|
||||
.await
|
||||
.is_side_solid(facing.opposite())
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ impl BlockBehaviour for LanternBlock {
|
||||
pumpkin_data::block_properties::LanternLikeProperties::default(args.block);
|
||||
props.r#waterlogged = args.replacing.water_source();
|
||||
|
||||
let block_up_state = args.world.get_block_state(&args.position.up()).await;
|
||||
let block_up_state = args.world.get_block_state(&args.position.up());
|
||||
if block_up_state.is_center_solid(BlockDirection::Down) {
|
||||
props.r#hanging = true;
|
||||
}
|
||||
@ -47,8 +47,8 @@ impl BlockBehaviour for LanternBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.world.unwrap(), args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.world.unwrap(), args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -56,7 +56,7 @@ impl BlockBehaviour for LanternBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -67,7 +67,7 @@ impl BlockBehaviour for LanternBlock {
|
||||
|
||||
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -76,25 +76,24 @@ impl BlockBehaviour for LanternBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &World, position: &BlockPos) -> bool {
|
||||
fn can_place_at(world: &World, position: &BlockPos) -> bool {
|
||||
//idk why this don't update with .is_center_solid so this is a 'temporary patch'
|
||||
if world
|
||||
.get_block(&position.down())
|
||||
.await
|
||||
.has_tag(&tag::Block::C_FENCE_GATES)
|
||||
{
|
||||
let fence_gate_props =
|
||||
pumpkin_data::block_properties::OakFenceGateLikeProperties::from_state_id(
|
||||
world.get_block_state_id(&position.down()).await,
|
||||
world.get_block(&position.down()).await,
|
||||
world.get_block_state_id(&position.down()),
|
||||
world.get_block(&position.down()),
|
||||
);
|
||||
|
||||
if fence_gate_props.open {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let (block_down, block_down_state) = world.get_block_and_state(&position.down()).await;
|
||||
let block_up_state = world.get_block_state(&position.up()).await;
|
||||
let (block_down, block_down_state) = world.get_block_and_state(&position.down());
|
||||
let block_up_state = world.get_block_state(&position.up());
|
||||
block_down_state.is_center_solid(BlockDirection::Up)
|
||||
|| block_up_state.is_center_solid(BlockDirection::Down)
|
||||
|| block_down.has_tag(&tag::Block::MINECRAFT_UNSTABLE_BOTTOM_CENTER)
|
||||
|
||||
@ -60,7 +60,7 @@ impl BlockBehaviour for LecternBlock {
|
||||
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(lectern_entity) =
|
||||
block_entity.as_any().downcast_ref::<LecternBlockEntity>()
|
||||
{
|
||||
@ -70,7 +70,7 @@ impl BlockBehaviour for LecternBlock {
|
||||
// Need to find a proper way to give items to player. For now skip.
|
||||
|
||||
let mut props = LecternLikeProperties::from_state_id(
|
||||
args.world.get_block_state(args.position).await.id,
|
||||
args.world.get_block_state(args.position).id,
|
||||
args.block,
|
||||
);
|
||||
Self::update_lectern_state(
|
||||
@ -97,7 +97,7 @@ impl BlockBehaviour for LecternBlock {
|
||||
|
||||
// Check if it's a book
|
||||
if item_stack.item.registry_key.contains("book")
|
||||
&& let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
&& let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(lectern_entity) =
|
||||
block_entity.as_any().downcast_ref::<LecternBlockEntity>()
|
||||
&& lectern_entity.book.lock().await.is_empty()
|
||||
@ -106,7 +106,7 @@ impl BlockBehaviour for LecternBlock {
|
||||
lectern_entity.set_stack(0, book).await;
|
||||
|
||||
let mut props = LecternLikeProperties::from_state_id(
|
||||
args.world.get_block_state(args.position).await.id,
|
||||
args.world.get_block_state(args.position).id,
|
||||
args.block,
|
||||
);
|
||||
Self::update_lectern_state(true, args.block, args.position, args.world, &mut props)
|
||||
@ -119,7 +119,7 @@ impl BlockBehaviour for LecternBlock {
|
||||
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position).await
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position)
|
||||
&& let Some(lectern_entity) =
|
||||
block_entity.as_any().downcast_ref::<LecternBlockEntity>()
|
||||
{
|
||||
@ -135,7 +135,7 @@ impl BlockBehaviour for LecternBlock {
|
||||
),
|
||||
&EntityType::ITEM,
|
||||
);
|
||||
let item_entity = ItemEntity::new(entity, book).await;
|
||||
let item_entity = ItemEntity::new(entity, book);
|
||||
args.world.spawn_entity(Arc::new(item_entity)).await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,6 @@ impl BlockBehaviour for NetherPortalBlock {
|
||||
if is_horizontal_and_different
|
||||
|| args.neighbor_state_id == args.state_id
|
||||
|| NetherPortal::get_on_axis(args.world, args.position, state_axis)
|
||||
.await
|
||||
.is_some_and(|e| e.was_already_valid())
|
||||
{
|
||||
return args.state_id;
|
||||
|
||||
@ -26,7 +26,7 @@ pub struct NoteBlock;
|
||||
|
||||
impl NoteBlock {
|
||||
pub async fn play_note(props: &NoteBlockLikeProperties, world: &World, pos: &BlockPos) {
|
||||
if !is_base_block(props.instrument) || world.get_block_state(&pos.up()).await.is_air() {
|
||||
if !is_base_block(props.instrument) || world.get_block_state(&pos.up()).is_air() {
|
||||
world.add_synced_block_event(*pos, 0, 0).await;
|
||||
}
|
||||
}
|
||||
@ -34,20 +34,20 @@ impl NoteBlock {
|
||||
((f32::from(note) - 12.0) / 12.0).exp2()
|
||||
}
|
||||
|
||||
async fn get_state_with_instrument(
|
||||
fn get_state_with_instrument(
|
||||
world: &World,
|
||||
pos: &BlockPos,
|
||||
state: BlockStateId,
|
||||
block: &Block,
|
||||
) -> BlockStateId {
|
||||
let upper_instrument = world.get_block_state(&pos.up()).await.instrument;
|
||||
let upper_instrument = world.get_block_state(&pos.up()).instrument;
|
||||
|
||||
let mut note_props = NoteBlockLikeProperties::from_state_id(state, block);
|
||||
if !is_base_block(upper_instrument) {
|
||||
note_props.instrument = upper_instrument;
|
||||
return note_props.to_state_id(block);
|
||||
}
|
||||
let below_instrument = world.get_block_state(&pos.down()).await.instrument;
|
||||
let below_instrument = world.get_block_state(&pos.down()).instrument;
|
||||
let below_instrument = if is_base_block(below_instrument) {
|
||||
below_instrument
|
||||
} else {
|
||||
@ -61,7 +61,7 @@ impl NoteBlock {
|
||||
impl BlockBehaviour for NoteBlock {
|
||||
fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let block_state = args.world.get_block_state(args.position).await;
|
||||
let block_state = args.world.get_block_state(args.position);
|
||||
let mut note_props = NoteBlockLikeProperties::from_state_id(block_state.id, args.block);
|
||||
let powered = block_receives_redstone_power(args.world, args.position).await;
|
||||
// check if powered state changed
|
||||
@ -83,7 +83,7 @@ impl BlockBehaviour for NoteBlock {
|
||||
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let block_state = args.world.get_block_state(args.position).await;
|
||||
let block_state = args.world.get_block_state(args.position);
|
||||
let mut note_props = NoteBlockLikeProperties::from_state_id(block_state.id, args.block);
|
||||
note_props.note = (note_props.note + 1) % 25;
|
||||
args.world
|
||||
@ -114,7 +114,7 @@ impl BlockBehaviour for NoteBlock {
|
||||
args: OnSyncedBlockEventArgs<'a>,
|
||||
) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
let block_state = args.world.get_block_state(args.position).await;
|
||||
let block_state = args.world.get_block_state(args.position);
|
||||
let note_props = NoteBlockLikeProperties::from_state_id(block_state.id, args.block);
|
||||
let instrument = note_props.instrument;
|
||||
let pitch = if is_base_block(instrument) {
|
||||
@ -124,15 +124,13 @@ impl BlockBehaviour for NoteBlock {
|
||||
1.0 // default pitch
|
||||
};
|
||||
// check hasCustomSound
|
||||
args.world
|
||||
.play_sound_raw(
|
||||
args.world.play_sound_raw(
|
||||
convert_instrument_to_sound(instrument) as u16,
|
||||
SoundCategory::Records,
|
||||
&args.position.to_f64(),
|
||||
3.0,
|
||||
pitch,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
true
|
||||
})
|
||||
}
|
||||
@ -145,7 +143,6 @@ impl BlockBehaviour for NoteBlock {
|
||||
Block::NOTE_BLOCK.default_state.id,
|
||||
args.block,
|
||||
)
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
@ -160,8 +157,7 @@ impl BlockBehaviour for NoteBlock {
|
||||
args.position,
|
||||
args.state_id,
|
||||
args.block,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
}
|
||||
args.state_id
|
||||
})
|
||||
|
||||
@ -49,7 +49,7 @@ impl<'a> PistonHandler<'a> {
|
||||
pub async fn calculate_push(&mut self) -> bool {
|
||||
self.moved_blocks.clear();
|
||||
self.broken_blocks.clear();
|
||||
let (block, block_state) = self.world.get_block_and_state(&self.pos_to).await;
|
||||
let (block, block_state) = self.world.get_block_and_state(&self.pos_to);
|
||||
|
||||
if !PistonBlock::is_movable(
|
||||
block,
|
||||
@ -69,7 +69,7 @@ impl<'a> PistonHandler<'a> {
|
||||
}
|
||||
for i in 0..self.moved_blocks.len() {
|
||||
let block_pos = self.moved_blocks[i];
|
||||
let block = self.world.get_block(&block_pos).await;
|
||||
let block = self.world.get_block(&block_pos);
|
||||
if Self::is_block_sticky(block)
|
||||
&& !self.try_move_adjacent_block(block, &block_pos).await
|
||||
{
|
||||
@ -94,7 +94,7 @@ impl<'a> PistonHandler<'a> {
|
||||
}
|
||||
|
||||
async fn try_move(&mut self, pos: BlockPos, dir: BlockDirection) -> bool {
|
||||
let (block, block_state) = self.world.get_block_and_state(&pos).await;
|
||||
let (block, block_state) = self.world.get_block_and_state(&pos);
|
||||
if block_state.is_air() {
|
||||
return true;
|
||||
}
|
||||
@ -114,7 +114,7 @@ impl<'a> PistonHandler<'a> {
|
||||
while Self::is_block_sticky(block) {
|
||||
let block_pos = pos.offset_dir(self.motion_direction.opposite().to_offset(), i as i32);
|
||||
let block2 = block;
|
||||
let (block, block_state) = self.world.get_block_and_state(&block_pos).await;
|
||||
let (block, block_state) = self.world.get_block_and_state(&block_pos);
|
||||
if block_state.is_air()
|
||||
|| !Self::is_adjacent_block_stuck(block2, block)
|
||||
|| !PistonBlock::is_movable(
|
||||
@ -146,7 +146,7 @@ impl<'a> PistonHandler<'a> {
|
||||
self.set_moved_blocks(j, l);
|
||||
for m in 0..=(l + j) {
|
||||
let block_pos3 = self.moved_blocks[m];
|
||||
let block = self.world.get_block(&block_pos3).await;
|
||||
let block = self.world.get_block(&block_pos3);
|
||||
if Self::is_block_sticky(block)
|
||||
&& !Box::pin(self.try_move_adjacent_block(block, &block_pos3)).await
|
||||
{
|
||||
@ -155,7 +155,7 @@ impl<'a> PistonHandler<'a> {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
let (block, block_state) = self.world.get_block_and_state(&block_pos2).await;
|
||||
let (block, block_state) = self.world.get_block_and_state(&block_pos2);
|
||||
if block_state.is_air() {
|
||||
return true;
|
||||
}
|
||||
@ -201,7 +201,7 @@ impl<'a> PistonHandler<'a> {
|
||||
continue;
|
||||
}
|
||||
let block_pos = pos.offset(direction.to_offset());
|
||||
let block_state2 = self.world.get_block(&block_pos).await;
|
||||
let block_state2 = self.world.get_block(&block_pos);
|
||||
if Self::is_adjacent_block_stuck(block_state2, block)
|
||||
&& !self.try_move(block_pos, direction).await
|
||||
{
|
||||
|
||||
@ -91,8 +91,7 @@ impl BlockBehaviour for PistonBlock {
|
||||
let pos = args
|
||||
.position
|
||||
.offset(props.facing.to_block_direction().to_offset());
|
||||
let (block_to_check, block_to_check_state_id) =
|
||||
args.world.get_block_and_state_id(&pos).await;
|
||||
let (block_to_check, block_to_check_state_id) = args.world.get_block_and_state_id(&pos);
|
||||
if &Block::PISTON_HEAD == block_to_check {
|
||||
let head_props =
|
||||
PistonHeadProperties::from_state_id(block_to_check_state_id, block_to_check);
|
||||
@ -144,7 +143,7 @@ impl BlockBehaviour for PistonBlock {
|
||||
args.data,
|
||||
);
|
||||
|
||||
let state = world.get_block_state(pos).await;
|
||||
let state = world.get_block_state(pos);
|
||||
let mut props = PistonProps::from_state_id(state.id, block);
|
||||
let dir = props.facing.to_block_direction();
|
||||
|
||||
@ -180,22 +179,20 @@ impl BlockBehaviour for PistonBlock {
|
||||
.await;
|
||||
// Play piston extend sound
|
||||
let pitch = rand::rng().random_range(0.6f32..0.85);
|
||||
world
|
||||
.play_sound_fine(
|
||||
world.play_sound_fine(
|
||||
Sound::BlockPistonExtend,
|
||||
SoundCategory::Blocks,
|
||||
&pos.to_centered_f64(),
|
||||
0.5,
|
||||
pitch,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// Reduce Piston
|
||||
|
||||
let extended_pos = pos.offset(dir.to_offset());
|
||||
|
||||
if let Some(block_entity) = world.get_block_entity(&extended_pos).await
|
||||
if let Some(block_entity) = world.get_block_entity(&extended_pos)
|
||||
&& let Some(piston) = block_entity.as_any().downcast_ref::<PistonBlockEntity>()
|
||||
{
|
||||
piston.finish(world.clone()).await;
|
||||
@ -237,9 +234,9 @@ impl BlockBehaviour for PistonBlock {
|
||||
world.update_neighbors(pos, None).await;
|
||||
if sticky {
|
||||
let pull_pos = pos.offset_dir(dir.to_offset(), 2);
|
||||
let (block, state) = world.get_block_and_state(&pull_pos).await;
|
||||
let (block, state) = world.get_block_and_state(&pull_pos);
|
||||
let piston_piece = if block == &Block::MOVING_PISTON
|
||||
&& let Some(entity) = world.get_block_entity(&pull_pos).await
|
||||
&& let Some(entity) = world.get_block_entity(&pull_pos)
|
||||
&& let Some(piston) = entity.as_any().downcast_ref::<PistonBlockEntity>()
|
||||
&& piston.facing == dir
|
||||
&& piston.extending
|
||||
@ -281,15 +278,13 @@ impl BlockBehaviour for PistonBlock {
|
||||
}
|
||||
// Play piston contract sound
|
||||
let pitch = rand::rng().random_range(0.6f32..0.75);
|
||||
world
|
||||
.play_sound_fine(
|
||||
world.play_sound_fine(
|
||||
Sound::BlockPistonContract,
|
||||
SoundCategory::Blocks,
|
||||
&pos.to_centered_f64(),
|
||||
0.5,
|
||||
pitch,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
true
|
||||
})
|
||||
}
|
||||
@ -298,7 +293,7 @@ impl BlockBehaviour for PistonBlock {
|
||||
async fn should_extend(world: &World, block_pos: &BlockPos, piston_dir: BlockDirection) -> bool {
|
||||
for dir in BlockDirection::all() {
|
||||
let neighbor_pos = block_pos.offset(dir.to_offset());
|
||||
let (block, state) = world.get_block_and_state(&neighbor_pos).await;
|
||||
let (block, state) = world.get_block_and_state(&neighbor_pos);
|
||||
// Pistons can't be powered from the same direction as they are facing
|
||||
if dir == piston_dir
|
||||
|| !is_emitting_redstone_power(block, state, world, &neighbor_pos, dir).await
|
||||
@ -308,13 +303,13 @@ async fn should_extend(world: &World, block_pos: &BlockPos, piston_dir: BlockDir
|
||||
return true;
|
||||
}
|
||||
let neighbor_pos = block_pos.offset(BlockDirection::Down.to_offset());
|
||||
let (block, state) = world.get_block_and_state(&neighbor_pos).await;
|
||||
let (block, state) = world.get_block_and_state(&neighbor_pos);
|
||||
if is_emitting_redstone_power(block, state, world, block_pos, BlockDirection::Down).await {
|
||||
return true;
|
||||
}
|
||||
for dir in BlockDirection::all() {
|
||||
let neighbor_pos = block_pos.up().offset(dir.to_offset());
|
||||
let (block, state) = world.get_block_and_state(&neighbor_pos).await;
|
||||
let (block, state) = world.get_block_and_state(&neighbor_pos);
|
||||
if dir == BlockDirection::Down
|
||||
|| !is_emitting_redstone_power(block, state, world, &neighbor_pos, dir).await
|
||||
{
|
||||
@ -326,7 +321,7 @@ async fn should_extend(world: &World, block_pos: &BlockPos, piston_dir: BlockDir
|
||||
}
|
||||
|
||||
pub async fn try_move(world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
|
||||
let state = world.get_block_state(block_pos).await;
|
||||
let state = world.get_block_state(block_pos);
|
||||
let props = PistonProps::from_state_id(state.id, block);
|
||||
let dir = props.facing.to_block_direction();
|
||||
let should_extent = should_extend(world, block_pos, dir).await;
|
||||
@ -342,13 +337,13 @@ pub async fn try_move(world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
|
||||
}
|
||||
} else if !should_extent && props.extended {
|
||||
let new_pos = block_pos.offset_dir(dir.to_offset(), 2);
|
||||
let (new_block, new_state) = world.get_block_and_state_id(&new_pos).await;
|
||||
let (new_block, new_state) = world.get_block_and_state_id(&new_pos);
|
||||
let mut r#type = 1;
|
||||
|
||||
if new_block == &Block::MOVING_PISTON {
|
||||
let new_props = MovingPistonLikeProperties::from_state_id(new_state, new_block);
|
||||
if new_props.facing == props.facing
|
||||
&& let Some(entity) = world.get_block_entity(&new_pos).await
|
||||
&& let Some(entity) = world.get_block_entity(&new_pos)
|
||||
{
|
||||
let piston = entity.as_any().downcast_ref::<PistonBlockEntity>().unwrap();
|
||||
if piston.extending && piston.current_progress.load() < 0.5
|
||||
@ -374,7 +369,7 @@ async fn move_piston(
|
||||
sticky: bool,
|
||||
) -> bool {
|
||||
let extended_pos = block_pos.offset(dir.to_offset());
|
||||
if !extend && world.get_block(&extended_pos).await == &Block::PISTON_HEAD {
|
||||
if !extend && world.get_block(&extended_pos) == &Block::PISTON_HEAD {
|
||||
world
|
||||
.set_block_state(
|
||||
&extended_pos,
|
||||
@ -394,7 +389,7 @@ async fn move_piston(
|
||||
let mut moved_block_states: Vec<&BlockState> = Vec::new();
|
||||
|
||||
for &block_pos in &moved_blocks {
|
||||
let block_state = world.get_block_state(&block_pos).await;
|
||||
let block_state = world.get_block_state(&block_pos);
|
||||
moved_block_states.push(block_state);
|
||||
moved_blocks_map.insert(block_pos, block_state);
|
||||
}
|
||||
@ -405,7 +400,7 @@ async fn move_piston(
|
||||
let move_direction = if extend { dir } else { dir.opposite() };
|
||||
|
||||
for &broken_block_pos in broken_blocks.iter().rev() {
|
||||
let block_state = world.get_block_state(&broken_block_pos).await;
|
||||
let block_state = world.get_block_state(&broken_block_pos);
|
||||
world
|
||||
.break_block(
|
||||
&broken_block_pos,
|
||||
@ -417,7 +412,7 @@ async fn move_piston(
|
||||
}
|
||||
|
||||
for (index, &moved_block_pos) in moved_blocks.iter().rev().enumerate() {
|
||||
let block_state = world.get_block_state(&moved_block_pos).await;
|
||||
let block_state = world.get_block_state(&moved_block_pos);
|
||||
let target_pos = moved_block_pos.offset(move_direction.to_offset());
|
||||
moved_blocks_map.remove(&target_pos);
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ impl BlockBehaviour for PistonExtensionBlock {
|
||||
let pos = args
|
||||
.position
|
||||
.offset(props.facing.opposite().to_block_direction().to_offset());
|
||||
let (new_block, new_state) = args.world.get_block_and_state_id(&pos).await;
|
||||
let (new_block, new_state) = args.world.get_block_and_state_id(&pos);
|
||||
if &Block::PISTON == new_block || &Block::STICKY_PISTON == new_block {
|
||||
let props = PistonProps::from_state_id(new_state, new_block);
|
||||
if props.extended {
|
||||
|
||||
@ -21,7 +21,7 @@ impl BlockBehaviour for PistonHeadBlock {
|
||||
let pos = args
|
||||
.position
|
||||
.offset(props.facing.opposite().to_block_direction().to_offset());
|
||||
let (new_block, new_state) = args.world.get_block_and_state_id(&pos).await;
|
||||
let (new_block, new_state) = args.world.get_block_and_state_id(&pos);
|
||||
if &Block::PISTON == new_block || &Block::STICKY_PISTON == new_block {
|
||||
let props = PistonProps::from_state_id(new_state, new_block);
|
||||
if props.extended {
|
||||
@ -35,7 +35,7 @@ impl BlockBehaviour for PistonHeadBlock {
|
||||
}
|
||||
fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let head_state_id = args.world.get_block_state_id(args.position).await;
|
||||
let head_state_id = args.world.get_block_state_id(args.position);
|
||||
let head_props =
|
||||
PistonHeadProperties::from_state_id(head_state_id, &Block::PISTON_HEAD);
|
||||
if head_props.facing != Facing::Up {
|
||||
@ -48,12 +48,12 @@ impl BlockBehaviour for PistonHeadBlock {
|
||||
.to_block_direction()
|
||||
.to_offset(),
|
||||
);
|
||||
let piston_block = args.world.get_block(&piston_pos).await;
|
||||
let piston_block = args.world.get_block(&piston_pos);
|
||||
if &Block::PISTON == piston_block || &Block::STICKY_PISTON == piston_block {
|
||||
let up_pos = args
|
||||
.position
|
||||
.offset(head_props.facing.to_block_direction().to_offset());
|
||||
let upper_block = args.world.get_block(&up_pos).await;
|
||||
let upper_block = args.world.get_block(&up_pos);
|
||||
if upper_block != &Block::REDSTONE_BLOCK {
|
||||
//Then somebody probably broke the redstone block, try to check if piston should still be extended.
|
||||
try_move(args.world, piston_block, &piston_pos).await;
|
||||
|
||||
@ -27,10 +27,8 @@ pub struct BambooBlock;
|
||||
impl BlockBehaviour for BambooBlock {
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
let (block_below, state_id_below) = args
|
||||
.world
|
||||
.get_block_and_state_id(&args.position.down())
|
||||
.await;
|
||||
let (block_below, state_id_below) =
|
||||
args.world.get_block_and_state_id(&args.position.down());
|
||||
|
||||
if block_below.has_tag(&MINECRAFT_SUPPORTS_BAMBOO) {
|
||||
let mut props = BambooLikeProperties::from_state_id(
|
||||
@ -47,7 +45,7 @@ impl BlockBehaviour for BambooBlock {
|
||||
}
|
||||
} else {
|
||||
let (block_above, state_id_above) =
|
||||
args.world.get_block_and_state_id(&args.position.up()).await;
|
||||
args.world.get_block_and_state_id(&args.position.up());
|
||||
if block_above == &Block::BAMBOO {
|
||||
let props_above =
|
||||
BambooLikeProperties::from_state_id(state_id_above, block_above);
|
||||
@ -76,21 +74,17 @@ impl BlockBehaviour for BambooBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world.as_ref(), args.position)
|
||||
.await
|
||||
{
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
} else if args.world.get_block(&args.position.down()).await == &Block::BAMBOO_SAPLING {
|
||||
} else if args.world.get_block(&args.position.down()) == &Block::BAMBOO_SAPLING {
|
||||
args.world
|
||||
.set_block_state(
|
||||
&args.position.down(),
|
||||
@ -107,12 +101,12 @@ impl BlockBehaviour for BambooBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world, args.position).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
}
|
||||
let neighbor_block = args.world.get_block(args.neighbor_position).await;
|
||||
let neighbor_block = args.world.get_block(args.neighbor_position);
|
||||
if args.direction == BlockDirection::Up && neighbor_block == &Block::BAMBOO {
|
||||
let neighbor_props =
|
||||
BambooLikeProperties::from_state_id(args.neighbor_state_id, neighbor_block);
|
||||
@ -143,8 +137,8 @@ async fn update_leaves_and_grow(world: Arc<World>, position: &BlockPos) {
|
||||
let below_pos = position.down();
|
||||
let two_below_pos = position.down_height(2);
|
||||
|
||||
let (block, state_id) = world.get_block_and_state_id(position).await;
|
||||
let state_above = world.get_block_state(&above_pos).await;
|
||||
let (block, state_id) = world.get_block_and_state_id(position);
|
||||
let state_above = world.get_block_state(&above_pos);
|
||||
|
||||
if !state_above.is_air() {
|
||||
return;
|
||||
@ -155,12 +149,12 @@ async fn update_leaves_and_grow(world: Arc<World>, position: &BlockPos) {
|
||||
return;
|
||||
}
|
||||
|
||||
let bamboo_count = count_bamboo_below(world.clone(), position).await;
|
||||
let bamboo_count = count_bamboo_below(&world, position);
|
||||
if bamboo_count >= 16 {
|
||||
return;
|
||||
}
|
||||
let (block_below, state_id_below) = world.get_block_and_state_id(&below_pos).await;
|
||||
let (block_two_below, state_id_two_below) = world.get_block_and_state_id(&two_below_pos).await;
|
||||
let (block_below, state_id_below) = world.get_block_and_state_id(&below_pos);
|
||||
let (block_two_below, state_id_two_below) = world.get_block_and_state_id(&two_below_pos);
|
||||
|
||||
let mut props_below = BambooLikeProperties::from_state_id(state_id_below, block_below);
|
||||
|
||||
@ -209,13 +203,13 @@ async fn update_leaves_and_grow(world: Arc<World>, position: &BlockPos) {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn count_bamboo_below(world: Arc<World>, pos: &BlockPos) -> usize {
|
||||
fn count_bamboo_below(world: &World, pos: &BlockPos) -> usize {
|
||||
let mut bamboo_count = 0;
|
||||
let mut found_bamboo_below = true;
|
||||
let mut current_position = pos.down();
|
||||
while found_bamboo_below && bamboo_count < 16 {
|
||||
found_bamboo_below = false;
|
||||
if world.get_block(¤t_position).await == &Block::BAMBOO {
|
||||
if world.get_block(¤t_position) == &Block::BAMBOO {
|
||||
current_position = current_position.down();
|
||||
bamboo_count += 1;
|
||||
found_bamboo_below = true;
|
||||
@ -224,13 +218,13 @@ async fn count_bamboo_below(world: Arc<World>, pos: &BlockPos) -> usize {
|
||||
bamboo_count
|
||||
}
|
||||
|
||||
async fn count_bamboo_above(world: Arc<World>, pos: &BlockPos) -> usize {
|
||||
fn count_bamboo_above(world: &World, pos: &BlockPos) -> usize {
|
||||
let mut bamboo_count = 0;
|
||||
let mut found_bamboo_below = true;
|
||||
let mut current_position = pos.up();
|
||||
while found_bamboo_below && bamboo_count < 16 {
|
||||
found_bamboo_below = false;
|
||||
if world.get_block(¤t_position).await == &Block::BAMBOO {
|
||||
if world.get_block(¤t_position) == &Block::BAMBOO {
|
||||
current_position = current_position.up();
|
||||
bamboo_count += 1;
|
||||
found_bamboo_below = true;
|
||||
@ -240,16 +234,15 @@ async fn count_bamboo_above(world: Arc<World>, pos: &BlockPos) -> usize {
|
||||
}
|
||||
|
||||
async fn bone_meal(world: Arc<World>, position: &BlockPos) {
|
||||
let mut bamboo_above = count_bamboo_above(Arc::clone(&world), position).await;
|
||||
let bamboo_below = count_bamboo_below(Arc::clone(&world), position).await;
|
||||
let bamboo_below = count_bamboo_below(&world, position);
|
||||
|
||||
let growth_amount = rand::rng().random_range(1..=3);
|
||||
|
||||
for _ in 0..growth_amount {
|
||||
for (bamboo_above, _) in (count_bamboo_above(&world, position)..).zip(0..growth_amount) {
|
||||
let current_total_height = bamboo_above + bamboo_below + 1;
|
||||
|
||||
let next_pos = position.up_height(bamboo_above as i32);
|
||||
let next_state = world.get_block_state(&next_pos).await;
|
||||
let next_state = world.get_block_state(&next_pos);
|
||||
|
||||
if !next_state.is_air() || current_total_height >= 16 {
|
||||
return;
|
||||
@ -261,22 +254,20 @@ async fn bone_meal(world: Arc<World>, position: &BlockPos) {
|
||||
}
|
||||
|
||||
update_leaves_and_grow(Arc::clone(&world), position).await;
|
||||
|
||||
bamboo_above += 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl PlantBlockBase for BambooBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
let block = block_accessor.get_block(pos);
|
||||
block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_BAMBOO)
|
||||
}
|
||||
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down()).await
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down())
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,11 +22,8 @@ use crate::block::{
|
||||
pub struct BambooSaplingBlock;
|
||||
|
||||
impl BlockBehaviour for BambooSaplingBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, &args.position.down())
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
fn use_with_item<'a>(
|
||||
@ -57,7 +54,7 @@ impl BlockBehaviour for BambooSaplingBlock {
|
||||
fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if args.block == &Block::BAMBOO_SAPLING
|
||||
&& args.world.get_block(&args.position.up()).await == &Block::BAMBOO
|
||||
&& args.world.get_block(&args.position.up()) == &Block::BAMBOO
|
||||
{
|
||||
args.world
|
||||
.set_block_state(
|
||||
@ -75,11 +72,11 @@ impl BlockBehaviour for BambooSaplingBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world, args.position).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world, args.position) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
if args.direction == BlockDirection::Up
|
||||
&& args.world.get_block(args.neighbor_position).await == &Block::BAMBOO
|
||||
&& args.world.get_block(args.neighbor_position) == &Block::BAMBOO
|
||||
{
|
||||
return Block::BAMBOO.default_state.id;
|
||||
}
|
||||
@ -89,7 +86,7 @@ impl BlockBehaviour for BambooSaplingBlock {
|
||||
|
||||
fn random_tick<'a>(&'a self, args: crate::block::RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let state_above = args.world.get_block_state(&args.position.up()).await;
|
||||
let state_above = args.world.get_block_state(&args.position.up());
|
||||
if !state_above.is_air() || rand::rng().random_range(0..3) > 0 {
|
||||
return;
|
||||
}
|
||||
@ -108,12 +105,12 @@ impl BlockBehaviour for BambooSaplingBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for BambooSaplingBlock {
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down()).await
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down())
|
||||
}
|
||||
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos);
|
||||
block.has_tag(&pumpkin_data::tag::Block::MINECRAFT_SUPPORTS_BAMBOO)
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ impl BlockBehaviour for BigDripleafBlock {
|
||||
}
|
||||
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
let state = args.world.get_block_state(args.position);
|
||||
if block_receives_redstone_power(args.world, args.position).await {
|
||||
reset_tilt(state.id, args.world, args.position).await;
|
||||
} else {
|
||||
@ -82,17 +82,13 @@ impl BlockBehaviour for BigDripleafBlock {
|
||||
})
|
||||
}
|
||||
//TODO: onProjectileHit
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
let (support_block, support_block_state_id) = args
|
||||
.world
|
||||
.get_block_and_state_id(&args.position.down())
|
||||
.await;
|
||||
let (support_block, support_block_state_id) =
|
||||
args.world.get_block_and_state_id(&args.position.down());
|
||||
let facing = if support_block == &Block::BIG_DRIPLEAF {
|
||||
get_dripleaf_facing_dir(support_block_state_id)
|
||||
} else {
|
||||
@ -128,7 +124,7 @@ impl BlockBehaviour for BigDripleafBlock {
|
||||
fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if block_receives_redstone_power(args.world, args.position).await {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
reset_tilt(state_id, args.world, args.position).await;
|
||||
}
|
||||
})
|
||||
@ -138,8 +134,7 @@ impl BlockBehaviour for BigDripleafBlock {
|
||||
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let support_pos = args.position.down();
|
||||
let (support_block, support_state_id) =
|
||||
args.world.get_block_and_state_id(&support_pos).await;
|
||||
let (support_block, support_state_id) = args.world.get_block_and_state_id(&support_pos);
|
||||
if support_block == &Block::BIG_DRIPLEAF {
|
||||
let old_dripleaf_props = BigDripleafLikeProperties::from_state_id(
|
||||
support_state_id,
|
||||
@ -175,7 +170,7 @@ async fn set_tilt_and_schedule_tick(
|
||||
) {
|
||||
set_tilt(state_id, world, pos, tilt).await;
|
||||
if let Some(tilt_sound) = sound_wrapper {
|
||||
play_tilt_sound(world, pos, tilt_sound).await;
|
||||
play_tilt_sound(world, pos, tilt_sound);
|
||||
}
|
||||
let tick_delay = match tilt {
|
||||
Tilt::None => -1,
|
||||
@ -193,19 +188,17 @@ async fn set_tilt_and_schedule_tick(
|
||||
.await;
|
||||
}
|
||||
}
|
||||
async fn play_tilt_sound(world: &Arc<World>, pos: &BlockPos, tilt_sound: Sound) {
|
||||
fn play_tilt_sound(world: &Arc<World>, pos: &BlockPos, tilt_sound: Sound) {
|
||||
let pitch = rand::rng().random_range(0.8f32..1.2f32);
|
||||
let v = pos.as_vector3();
|
||||
let position = Vector3::new(v.x as f64, v.y as f64, v.z as f64);
|
||||
world
|
||||
.play_sound_fine(tilt_sound, SoundCategory::Blocks, &position, 1f32, pitch)
|
||||
.await;
|
||||
world.play_sound_fine(tilt_sound, SoundCategory::Blocks, &position, 1f32, pitch);
|
||||
}
|
||||
async fn reset_tilt(state_id: BlockStateId, world: &Arc<World>, pos: &BlockPos) {
|
||||
set_tilt(state_id, world, pos, Tilt::None).await;
|
||||
let props = BigDripleafLikeProperties::from_state_id(state_id, &Block::BIG_DRIPLEAF);
|
||||
if props.tilt != Tilt::None {
|
||||
play_tilt_sound(world, pos, Sound::BlockBigDripleafTiltUp).await;
|
||||
play_tilt_sound(world, pos, Sound::BlockBigDripleafTiltUp);
|
||||
}
|
||||
}
|
||||
async fn set_tilt(state_id: BlockStateId, world: &Arc<World>, pos: &BlockPos, new_tilt: Tilt) {
|
||||
@ -234,8 +227,8 @@ fn is_dripleaf_waterlogged(state_id: BlockStateId) -> bool {
|
||||
dripleaf_props.waterlogged
|
||||
}
|
||||
impl PlantBlockBase for BigDripleafBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let support_block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let support_block = block_accessor.get_block(pos);
|
||||
can_plant_dripleaf_on_top(support_block)
|
||||
}
|
||||
async fn get_state_for_neighbor_update(
|
||||
@ -244,7 +237,7 @@ impl PlantBlockBase for BigDripleafBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
if is_dripleaf_waterlogged(block_state) {
|
||||
return Block::WATER.default_state.id;
|
||||
}
|
||||
|
||||
@ -21,10 +21,8 @@ pub struct BigDripleafStemBlock;
|
||||
pub type BigDripleafStemLikeProperties = LadderLikeProperties;
|
||||
|
||||
impl BlockBehaviour for BigDripleafStemBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -46,8 +44,8 @@ impl BlockBehaviour for BigDripleafStemBlock {
|
||||
}
|
||||
}
|
||||
impl PlantBlockBase for BigDripleafStemBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let support_block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let support_block = block_accessor.get_block(pos);
|
||||
can_plant_dripleaf_on_top(support_block)
|
||||
}
|
||||
|
||||
@ -57,8 +55,8 @@ impl PlantBlockBase for BigDripleafStemBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
let block = block_accessor.get_block(block_pos).await;
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
let block = block_accessor.get_block(block_pos);
|
||||
|
||||
let dripleaf_stem_props =
|
||||
BigDripleafStemLikeProperties::from_state_id(block_state, block);
|
||||
@ -72,7 +70,7 @@ impl PlantBlockBase for BigDripleafStemBlock {
|
||||
}
|
||||
pub async fn handle_big_dripleaf_breaking(world: &Arc<World>, position: &BlockPos) {
|
||||
let support_pos = position.down();
|
||||
let (support_block, support_state_id) = world.get_block_and_state_id(&support_pos).await;
|
||||
let (support_block, support_state_id) = world.get_block_and_state_id(&support_pos);
|
||||
if support_block == &Block::BIG_DRIPLEAF_STEM {
|
||||
let dripleaf_stem_props =
|
||||
BigDripleafStemLikeProperties::from_state_id(support_state_id, support_block);
|
||||
|
||||
@ -15,10 +15,8 @@ impl BlockMetadata for BushBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for BushBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -20,7 +20,7 @@ pub struct CactusBlock;
|
||||
impl BlockBehaviour for CactusBlock {
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -31,19 +31,19 @@ impl BlockBehaviour for CactusBlock {
|
||||
fn random_tick<'a>(&'a self, args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let block_up = args.position.up();
|
||||
if args.world.get_block_state(&block_up).await.is_air() {
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
if args.world.get_block_state(&block_up).is_air() {
|
||||
let state = args.world.get_block_state(args.position);
|
||||
let mut props = CactusLikeProperties::from_state_id(state.id, args.block);
|
||||
let age = props.age;
|
||||
let mut i = 1;
|
||||
while args.world.get_block(&args.position.down_height(i)).await == &Block::CACTUS {
|
||||
while args.world.get_block(&args.position.down_height(i)) == &Block::CACTUS {
|
||||
i += 1;
|
||||
if 1 == 3 && age == 15 {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if age == 8 && can_place_at(args.world.as_ref(), &block_up).await {
|
||||
if age == 8 && can_place_at(args.world.as_ref(), &block_up) {
|
||||
let d = if i >= 3 { 0.25 } else { 0.1 };
|
||||
if rand::rng().random_range(0.0..1.0) <= d {
|
||||
args.world
|
||||
@ -102,7 +102,7 @@ impl BlockBehaviour for CactusBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -112,21 +112,19 @@ impl BlockBehaviour for CactusBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
fn can_place_at(world: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
for direction in BlockDirection::horizontal() {
|
||||
let (block, state) = world
|
||||
.get_block_and_state(&block_pos.offset(direction.to_offset()))
|
||||
.await;
|
||||
let (block, state) = world.get_block_and_state(&block_pos.offset(direction.to_offset()));
|
||||
if state.is_solid() || block == &Block::LAVA {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let block = world.get_block(&block_pos.down()).await;
|
||||
let block = world.get_block(&block_pos.down());
|
||||
(block == &Block::CACTUS || block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_CACTUS))
|
||||
&& !world.get_block_state(&block_pos.up()).await.is_liquid()
|
||||
&& !world.get_block_state(&block_pos.up()).is_liquid()
|
||||
}
|
||||
|
||||
@ -11,10 +11,8 @@ use pumpkin_world::world::BlockAccessor;
|
||||
pub struct CactusFlowerBlock;
|
||||
|
||||
impl BlockBehaviour for CactusFlowerBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -33,14 +31,13 @@ impl BlockBehaviour for CactusFlowerBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for CactusFlowerBlock {
|
||||
async fn can_place_at(
|
||||
fn can_place_at(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
let support_pos = pos.down();
|
||||
let (support_block, support_block_state) =
|
||||
block_accessor.get_block_and_state(&support_pos).await;
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(&support_pos);
|
||||
if supports_cactus_flower(support_block, support_block_state) {
|
||||
return true;
|
||||
}
|
||||
@ -52,7 +49,7 @@ impl PlantBlockBase for CactusFlowerBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
block_state
|
||||
|
||||
@ -18,8 +18,8 @@ use crate::block::{
|
||||
pub struct ChorusFlowerBlock;
|
||||
|
||||
impl BlockBehaviour for ChorusFlowerBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_survive(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_survive(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -27,8 +27,7 @@ impl BlockBehaviour for ChorusFlowerBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if args.direction != BlockDirection::Up && !can_survive(args.world, args.position).await
|
||||
{
|
||||
if args.direction != BlockDirection::Up && !can_survive(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -39,7 +38,7 @@ impl BlockBehaviour for ChorusFlowerBlock {
|
||||
|
||||
fn on_scheduled_tick<'a>(&'a self, args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if !can_survive(args.world.as_ref(), args.position).await {
|
||||
if !can_survive(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -48,8 +47,8 @@ impl BlockBehaviour for ChorusFlowerBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_survive(block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block_below = block_accessor.get_block(&pos.down()).await;
|
||||
fn can_survive(block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block_below = block_accessor.get_block(&pos.down());
|
||||
|
||||
if block_below == &Block::CHORUS_PLANT
|
||||
|| block_below.has_tag(&tag::Block::MINECRAFT_SUPPORTS_CHORUS_FLOWER)
|
||||
@ -65,7 +64,7 @@ async fn can_survive(block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool
|
||||
// Exactly one horizontal neighbor must be a chorus plant stem.
|
||||
let mut plant_count = 0u32;
|
||||
for dir in BlockDirection::horizontal() {
|
||||
let neighbor = block_accessor.get_block(&pos.offset(dir.to_offset())).await;
|
||||
let neighbor = block_accessor.get_block(&pos.offset(dir.to_offset()));
|
||||
if neighbor == &Block::CHORUS_PLANT {
|
||||
plant_count += 1;
|
||||
if plant_count > 1 {
|
||||
|
||||
@ -23,12 +23,12 @@ impl BlockBehaviour for ChorusPlantBlock {
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
// Compute all 6 face connections immediately so the placed block visually connects to its neighbors.
|
||||
get_state_with_connections(args.world, args.block, args.position).await
|
||||
get_state_with_connections(args.world, args.block, args.position)
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_survive(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_survive(args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -36,7 +36,7 @@ impl BlockBehaviour for ChorusPlantBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_survive(args.world, args.position).await {
|
||||
if !can_survive(args.world, args.position) {
|
||||
// Schedule delayed destruction so the whole plant cascades down.
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
@ -45,7 +45,7 @@ impl BlockBehaviour for ChorusPlantBlock {
|
||||
}
|
||||
|
||||
// Update the single face connection for the direction that changed.
|
||||
let neighbor_block = args.world.get_block(args.neighbor_position).await;
|
||||
let neighbor_block = args.world.get_block(args.neighbor_position);
|
||||
let connect = neighbor_block == &Block::CHORUS_PLANT
|
||||
|| neighbor_block == &Block::CHORUS_FLOWER
|
||||
|| (args.direction == BlockDirection::Down
|
||||
@ -69,7 +69,7 @@ impl BlockBehaviour for ChorusPlantBlock {
|
||||
Box::pin(async move {
|
||||
// Destroy if unsupported; breaking propagates neighbor-update callbacks
|
||||
// to connected chorus blocks, which schedule their own ticks.
|
||||
if !can_survive(args.world.as_ref(), args.position).await {
|
||||
if !can_survive(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -78,7 +78,7 @@ impl BlockBehaviour for ChorusPlantBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_state_with_connections(
|
||||
fn get_state_with_connections(
|
||||
block_accessor: &dyn BlockAccessor,
|
||||
block: &Block,
|
||||
pos: &BlockPos,
|
||||
@ -89,20 +89,12 @@ async fn get_state_with_connections(
|
||||
|
||||
let connects = |b: &Block| b.id == plant_id || b.id == flower_id;
|
||||
|
||||
let block_down = block_accessor.get_block(&pos.down()).await;
|
||||
let block_up = block_accessor.get_block(&pos.up()).await;
|
||||
let block_north = block_accessor
|
||||
.get_block(&pos.offset(BlockDirection::North.to_offset()))
|
||||
.await;
|
||||
let block_east = block_accessor
|
||||
.get_block(&pos.offset(BlockDirection::East.to_offset()))
|
||||
.await;
|
||||
let block_south = block_accessor
|
||||
.get_block(&pos.offset(BlockDirection::South.to_offset()))
|
||||
.await;
|
||||
let block_west = block_accessor
|
||||
.get_block(&pos.offset(BlockDirection::West.to_offset()))
|
||||
.await;
|
||||
let block_down = block_accessor.get_block(&pos.down());
|
||||
let block_up = block_accessor.get_block(&pos.up());
|
||||
let block_north = block_accessor.get_block(&pos.offset(BlockDirection::North.to_offset()));
|
||||
let block_east = block_accessor.get_block(&pos.offset(BlockDirection::East.to_offset()));
|
||||
let block_south = block_accessor.get_block(&pos.offset(BlockDirection::South.to_offset()));
|
||||
let block_west = block_accessor.get_block(&pos.offset(BlockDirection::West.to_offset()));
|
||||
|
||||
let props = BrownMushroomBlockLikeProperties {
|
||||
down: connects(block_down) || block_down.has_tag(supports),
|
||||
@ -115,12 +107,12 @@ async fn get_state_with_connections(
|
||||
props.to_state_id(block)
|
||||
}
|
||||
|
||||
async fn can_survive(block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
fn can_survive(block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let below_pos = pos.down();
|
||||
let above_pos = pos.up();
|
||||
|
||||
let (block_below, state_below) = block_accessor.get_block_and_state(&below_pos).await;
|
||||
let state_above = block_accessor.get_block_state(&above_pos).await;
|
||||
let (block_below, state_below) = block_accessor.get_block_and_state(&below_pos);
|
||||
let state_above = block_accessor.get_block_state(&above_pos);
|
||||
|
||||
// A horizontal branch is invalid when both the block immediately above and
|
||||
// below this one are non-air (enclosed inside something).
|
||||
@ -128,12 +120,12 @@ async fn can_survive(block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool
|
||||
|
||||
for dir in BlockDirection::horizontal() {
|
||||
let neighbor_pos = pos.offset(dir.to_offset());
|
||||
let neighbor_block = block_accessor.get_block(&neighbor_pos).await;
|
||||
let neighbor_block = block_accessor.get_block(&neighbor_pos);
|
||||
if neighbor_block == &Block::CHORUS_PLANT {
|
||||
if block_above_or_below {
|
||||
return false;
|
||||
}
|
||||
let neighbor_below = block_accessor.get_block(&neighbor_pos.down()).await;
|
||||
let neighbor_below = block_accessor.get_block(&neighbor_pos.down());
|
||||
if neighbor_below == &Block::CHORUS_PLANT
|
||||
|| neighbor_below.has_tag(&tag::Block::MINECRAFT_SUPPORTS_CHORUS_PLANT)
|
||||
{
|
||||
|
||||
@ -16,15 +16,8 @@ type BeetrootProperties = NetherWartLikeProperties;
|
||||
pub struct BeetrootBlock;
|
||||
|
||||
impl BlockBehaviour for BeetrootBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as CropBlockBase>::can_plant_on_top(
|
||||
self,
|
||||
args.block_accessor,
|
||||
&args.position.down(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as CropBlockBase>::can_plant_on_top(self, args.block_accessor, &args.position.down())
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -11,15 +11,8 @@ use crate::block::{
|
||||
pub struct CarrotBlock;
|
||||
|
||||
impl BlockBehaviour for CarrotBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as CropBlockBase>::can_plant_on_top(
|
||||
self,
|
||||
args.block_accessor,
|
||||
&args.position.down(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as CropBlockBase>::can_plant_on_top(self, args.block_accessor, &args.position.down())
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -45,10 +45,8 @@ impl AttachedStemBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for AttachedStemBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -76,8 +74,8 @@ impl BlockBehaviour for AttachedStemBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for AttachedStemBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos);
|
||||
if block == &Block::ATTACHED_PUMPKIN_STEM {
|
||||
block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_PUMPKIN_STEM)
|
||||
} else {
|
||||
|
||||
@ -58,10 +58,8 @@ impl StemBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for StemBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -84,7 +82,7 @@ impl BlockBehaviour for StemBlock {
|
||||
// TODO add light level check
|
||||
let f: f32 = get_available_moisture(args.world, args.position, args.block).await;
|
||||
if rand::rng().random_range(0..=(25.0 / f).floor() as i32) == 0 {
|
||||
let (block, state) = args.world.get_block_and_state_id(args.position).await;
|
||||
let (block, state) = args.world.get_block_and_state_id(args.position);
|
||||
let props = StemProperties::from_state_id(state, block);
|
||||
let age = i32::from(props.age);
|
||||
if age < 7 {
|
||||
@ -100,8 +98,8 @@ impl BlockBehaviour for StemBlock {
|
||||
Xoroshiro::from_seed(rand::rng().random()),
|
||||
));
|
||||
let plant_block_pos = args.position.offset(dir.to_offset());
|
||||
let plant_block_state = args.world.get_block_state(&plant_block_pos).await;
|
||||
let under_block: &Block = args.world.get_block(&plant_block_pos.down()).await;
|
||||
let plant_block_state = args.world.get_block_state(&plant_block_pos);
|
||||
let under_block: &Block = args.world.get_block(&plant_block_pos.down());
|
||||
if plant_block_state.is_air()
|
||||
&& (under_block == &Block::FARMLAND
|
||||
|| under_block.has_tag(&tag::Block::MINECRAFT_DIRT))
|
||||
@ -130,8 +128,8 @@ impl BlockBehaviour for StemBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for StemBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos);
|
||||
if block == &Block::PUMPKIN_STEM {
|
||||
block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_PUMPKIN_STEM)
|
||||
} else {
|
||||
|
||||
@ -30,8 +30,8 @@ pub mod torch_flower;
|
||||
pub mod wheat;
|
||||
|
||||
trait CropBlockBase: PlantBlockBase {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos);
|
||||
block == &Block::FARMLAND
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ trait CropBlockBase: PlantBlockBase {
|
||||
}
|
||||
|
||||
async fn random_tick(&self, world: &Arc<World>, pos: &BlockPos) {
|
||||
let (block, state) = world.get_block_and_state_id(pos).await;
|
||||
let (block, state) = world.get_block_and_state_id(pos);
|
||||
let age = self.get_age(state, block);
|
||||
if age < self.max_age() {
|
||||
let f = get_available_moisture(world, pos, block).await;
|
||||
@ -90,9 +90,8 @@ pub async fn get_available_moisture(world: &Arc<World>, pos: &BlockPos, block: &
|
||||
for dz in -1..=1 {
|
||||
let mut local_moisture = 0.0;
|
||||
|
||||
let (block, block_state) = world
|
||||
.get_block_and_state_id(&down_pos.offset(Vector3 { x: dx, y: 0, z: dz }))
|
||||
.await;
|
||||
let (block, block_state) =
|
||||
world.get_block_and_state_id(&down_pos.offset(Vector3 { x: dx, y: 0, z: dz }));
|
||||
if block == &Block::FARMLAND {
|
||||
local_moisture = 1.0;
|
||||
let props = FarmlandProperties::from_state_id(block_state, block);
|
||||
@ -113,13 +112,13 @@ pub async fn get_available_moisture(world: &Arc<World>, pos: &BlockPos, block: &
|
||||
let south = pos.offset(South.to_offset());
|
||||
let west = pos.offset(West.to_offset());
|
||||
let east = pos.offset(East.to_offset());
|
||||
let horizontal = world.get_block(&west).await == block || world.get_block(&east).await == block;
|
||||
let vertical = world.get_block(&north).await == block || world.get_block(&south).await == block;
|
||||
let horizontal = world.get_block(&west) == block || world.get_block(&east) == block;
|
||||
let vertical = world.get_block(&north) == block || world.get_block(&south) == block;
|
||||
if (horizontal && vertical)
|
||||
|| world.get_block(&west.offset(North.to_offset())).await == block
|
||||
|| world.get_block(&east.offset(North.to_offset())).await == block
|
||||
|| world.get_block(&east.offset(South.to_offset())).await == block
|
||||
|| world.get_block(&west.offset(South.to_offset())).await == block
|
||||
|| world.get_block(&west.offset(North.to_offset())) == block
|
||||
|| world.get_block(&east.offset(North.to_offset())) == block
|
||||
|| world.get_block(&east.offset(South.to_offset())) == block
|
||||
|| world.get_block(&west.offset(South.to_offset())) == block
|
||||
{
|
||||
moisture /= 2.0;
|
||||
}
|
||||
|
||||
@ -25,10 +25,8 @@ use crate::{
|
||||
pub struct NetherWartBlock;
|
||||
|
||||
impl BlockBehaviour for NetherWartBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -54,19 +52,19 @@ impl BlockBehaviour for NetherWartBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for NetherWartBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos);
|
||||
block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_NETHER_WART)
|
||||
}
|
||||
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down()).await
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down())
|
||||
}
|
||||
}
|
||||
|
||||
impl CropBlockBase for NetherWartBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, pos).await
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, pos)
|
||||
}
|
||||
|
||||
fn max_age(&self) -> i32 {
|
||||
@ -85,7 +83,7 @@ impl CropBlockBase for NetherWartBlock {
|
||||
}
|
||||
|
||||
async fn random_tick(&self, world: &Arc<World>, pos: &BlockPos) {
|
||||
let (block, state) = world.get_block_and_state_id(pos).await;
|
||||
let (block, state) = world.get_block_and_state_id(pos);
|
||||
let age = self.get_age(state, block);
|
||||
if age < self.max_age() && rand::rng().random_range(0..=10) == 0 {
|
||||
world
|
||||
|
||||
@ -11,15 +11,8 @@ use crate::block::{
|
||||
pub struct PotatoBlock;
|
||||
|
||||
impl BlockBehaviour for PotatoBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as CropBlockBase>::can_plant_on_top(
|
||||
self,
|
||||
args.block_accessor,
|
||||
&args.position.down(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as CropBlockBase>::can_plant_on_top(self, args.block_accessor, &args.position.down())
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -32,7 +32,7 @@ pub struct SweetBerryBushBlock;
|
||||
impl BlockBehaviour for SweetBerryBushBlock {
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let mut props = NetherWartLikeProperties::from_state_id(state_id, args.block);
|
||||
match props.age {
|
||||
2 | 3 => {
|
||||
@ -66,7 +66,7 @@ impl BlockBehaviour for SweetBerryBushBlock {
|
||||
args: UseWithItemArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let props = NetherWartLikeProperties::from_state_id(state_id, &Block::SWEET_BERRY_BUSH);
|
||||
if props.age != 3 && args.item_stack.lock().await.get_item() == &Item::BONE_MEAL {
|
||||
BlockActionResult::Pass
|
||||
@ -76,10 +76,8 @@ impl BlockBehaviour for SweetBerryBushBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -119,7 +117,7 @@ impl BlockBehaviour for SweetBerryBushBlock {
|
||||
entity.last_pos.load() - entity.pos.load()
|
||||
};
|
||||
|
||||
let state_id = args.world.get_block_state_id(args.position).await;
|
||||
let state_id = args.world.get_block_state_id(args.position);
|
||||
let props = NetherWartLikeProperties::from_state_id(state_id, args.block);
|
||||
if props.age == 0 {
|
||||
return;
|
||||
@ -153,20 +151,20 @@ impl PlantBlockBase for SweetBerryBushBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
block_state
|
||||
}
|
||||
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down()).await
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down())
|
||||
}
|
||||
}
|
||||
|
||||
impl CropBlockBase for SweetBerryBushBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, pos).await
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, pos)
|
||||
}
|
||||
|
||||
fn max_age(&self) -> i32 {
|
||||
@ -185,10 +183,10 @@ impl CropBlockBase for SweetBerryBushBlock {
|
||||
}
|
||||
|
||||
async fn random_tick(&self, world: &Arc<World>, pos: &BlockPos) {
|
||||
let (block, state) = world.get_block_and_state_id(pos).await;
|
||||
let (block, state) = world.get_block_and_state_id(pos);
|
||||
let age = self.get_age(state, block);
|
||||
if age < self.max_age() {
|
||||
let state_above = world.get_block_state(&pos.up()).await;
|
||||
let state_above = world.get_block_state(&pos.up());
|
||||
|
||||
if state_above.is_full_cube() || state_above.is_solid() {
|
||||
return;
|
||||
|
||||
@ -16,15 +16,8 @@ type TorchFlowerProperties = TorchflowerCropLikeProperties;
|
||||
pub struct TorchFlowerBlock;
|
||||
|
||||
impl BlockBehaviour for TorchFlowerBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as CropBlockBase>::can_plant_on_top(
|
||||
self,
|
||||
args.block_accessor,
|
||||
&args.position.down(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as CropBlockBase>::can_plant_on_top(self, args.block_accessor, &args.position.down())
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -11,15 +11,8 @@ use crate::block::{
|
||||
pub struct WheatBlock;
|
||||
|
||||
impl BlockBehaviour for WheatBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as CropBlockBase>::can_plant_on_top(
|
||||
self,
|
||||
args.block_accessor,
|
||||
&args.position.down(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as CropBlockBase>::can_plant_on_top(self, args.block_accessor, &args.position.down())
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -22,10 +22,8 @@ impl BlockMetadata for DryVegetationBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for DryVegetationBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -45,12 +43,8 @@ impl BlockBehaviour for DryVegetationBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for DryVegetationBlock {
|
||||
async fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn BlockAccessor,
|
||||
block_pos: &BlockPos,
|
||||
) -> bool {
|
||||
let block_below = block_accessor.get_block(block_pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let block_below = block_accessor.get_block(block_pos);
|
||||
block_below.has_tag(&tag::Block::MINECRAFT_SUPPORTS_DRY_VEGETATION)
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,10 +19,8 @@ impl BlockMetadata for FlowerBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for FlowerBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -22,19 +22,17 @@ impl BlockMetadata for FlowerbedBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for FlowerbedBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
let block_below = args.block_accessor.get_block(&args.position.down()).await;
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
let block_below = args.block_accessor.get_block(&args.position.down());
|
||||
block_below.has_tag(&tag::Block::MINECRAFT_DIRT) || block_below == &Block::FARMLAND
|
||||
})
|
||||
}
|
||||
|
||||
fn can_update_at<'a>(&'a self, args: CanUpdateAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { Segmented::can_update_at(self, args).await })
|
||||
fn can_update_at(&self, args: CanUpdateAtArgs<'_>) -> bool {
|
||||
Segmented::can_update_at(self, args)
|
||||
}
|
||||
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move { Segmented::on_place(self, args).await })
|
||||
Segmented::on_place(self, args)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -14,10 +14,8 @@ impl BlockMetadata for FungusBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for FungusBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -35,19 +33,19 @@ impl BlockBehaviour for FungusBlock {
|
||||
}
|
||||
}
|
||||
impl PlantBlockBase for FungusBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
let block = block_accessor.get_block(pos);
|
||||
|
||||
if block == &Block::WARPED_FUNGUS {
|
||||
return block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_WARPED_FUNGUS);
|
||||
}
|
||||
block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_CRIMSON_FUNGUS)
|
||||
}
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down()).await
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
<Self as PlantBlockBase>::can_plant_on_top(self, block_accessor, &block_pos.down())
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,10 +18,8 @@ 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 {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -40,7 +38,7 @@ impl BlockBehaviour for KelpBlock {
|
||||
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let support_pos = args.position.down();
|
||||
let support_block = args.world.get_block(&support_pos).await;
|
||||
let support_block = args.world.get_block(&support_pos);
|
||||
if support_block == &Block::KELP {
|
||||
args.world
|
||||
.set_block_state(
|
||||
@ -55,7 +53,7 @@ impl BlockBehaviour for KelpBlock {
|
||||
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;
|
||||
let support_block = args.world.get_block(&support_pos);
|
||||
if support_block == &Block::KELP_PLANT {
|
||||
args.world
|
||||
.set_block_state(
|
||||
@ -77,7 +75,7 @@ impl BlockBehaviour for KelpBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for KelpBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
@ -85,9 +83,8 @@ impl PlantBlockBase for KelpBlock {
|
||||
// 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;
|
||||
block_accessor.get_block_and_state(&pos.up());
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(support_pos);
|
||||
if replacing_block == &Block::WATER {
|
||||
let water_props =
|
||||
WaterLikeProperties::from_state_id(replacing_block_state.id, replacing_block);
|
||||
@ -122,7 +119,7 @@ impl PlantBlockBase for KelpBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
return Block::WATER.default_state.id;
|
||||
}
|
||||
block_state
|
||||
|
||||
@ -19,18 +19,13 @@ impl BlockMetadata for LeafLitterBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for LeafLitterBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
let block_below = args
|
||||
.block_accessor
|
||||
.get_block_state(&args.position.down())
|
||||
.await;
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
let block_below = args.block_accessor.get_block_state(&args.position.down());
|
||||
block_below.is_side_solid(BlockDirection::Up)
|
||||
})
|
||||
}
|
||||
|
||||
fn can_update_at<'a>(&'a self, args: CanUpdateAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { Segmented::can_update_at(self, args).await })
|
||||
fn can_update_at(&self, args: CanUpdateAtArgs<'_>) -> bool {
|
||||
Segmented::can_update_at(self, args)
|
||||
}
|
||||
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
@ -43,7 +38,7 @@ impl BlockBehaviour for LeafLitterBlock {
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if args.direction == BlockDirection::Down {
|
||||
let block_below_state = args.world.get_block_state(&args.position.down()).await;
|
||||
let block_below_state = args.world.get_block_state(&args.position.down());
|
||||
if !block_below_state.is_side_solid(BlockDirection::Up) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
|
||||
@ -31,10 +31,8 @@ impl BlockBehaviour for LilyPadBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -54,10 +52,10 @@ impl BlockBehaviour for LilyPadBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for LilyPadBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
// TODO: get and use fluids not blocks
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
let above_fluid = block_accessor.get_block(&pos.up()).await;
|
||||
let block = block_accessor.get_block(pos);
|
||||
let above_fluid = block_accessor.get_block(&pos.up());
|
||||
(block.has_tag(&tag::Fluid::MINECRAFT_SUPPORTS_LILY_PAD)
|
||||
|| block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_LILY_PAD))
|
||||
&& above_fluid.is_air()
|
||||
|
||||
@ -37,8 +37,8 @@ pub mod weeping_vines;
|
||||
pub mod wither_rose;
|
||||
|
||||
trait PlantBlockBase {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos);
|
||||
block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_VEGETATION)
|
||||
}
|
||||
|
||||
@ -48,14 +48,13 @@ trait PlantBlockBase {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !self.can_place_at(block_accessor, block_pos).await {
|
||||
if !self.can_place_at(block_accessor, block_pos) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
block_state
|
||||
}
|
||||
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
self.can_plant_on_top(block_accessor, &block_pos.down())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,10 +17,8 @@ impl BlockMetadata for MushroomPlantBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for MushroomPlantBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -40,8 +38,8 @@ impl BlockBehaviour for MushroomPlantBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for MushroomPlantBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block = block_accessor.get_block(pos);
|
||||
block.has_tag(&tag::Block::MINECRAFT_OVERRIDES_MUSHROOM_LIGHT_REQUIREMENT)
|
||||
// TODO: Check light level and isOpaqueFullCube
|
||||
}
|
||||
|
||||
@ -7,10 +7,8 @@ use pumpkin_world::BlockStateId;
|
||||
pub struct NetherSproutsBlock;
|
||||
|
||||
impl BlockBehaviour for NetherSproutsBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -28,12 +26,12 @@ impl BlockBehaviour for NetherSproutsBlock {
|
||||
}
|
||||
}
|
||||
impl PlantBlockBase for NetherSproutsBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
let block = block_accessor.get_block(pos).await;
|
||||
let block = block_accessor.get_block(pos);
|
||||
block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_NETHER_SPROUTS)
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,10 +18,8 @@ impl BlockMetadata for RootsBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for RootsBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -41,8 +39,8 @@ impl BlockBehaviour for RootsBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for RootsBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block_below = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let block_below = block_accessor.get_block(pos);
|
||||
if block_below == &Block::WARPED_ROOTS {
|
||||
block_below.has_tag(&tag::Block::MINECRAFT_SUPPORTS_WARPED_ROOTS)
|
||||
} else {
|
||||
@ -50,8 +48,7 @@ impl PlantBlockBase for RootsBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
self.can_plant_on_top(block_accessor, &block_pos.down())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ pub struct SaplingBlock;
|
||||
|
||||
impl SaplingBlock {
|
||||
async fn generate(&self, world: &Arc<World>, pos: &BlockPos) {
|
||||
let (block, state) = world.get_block_and_state_id(pos).await;
|
||||
let (block, state) = world.get_block_and_state_id(pos);
|
||||
let mut props = SaplingProperties::from_state_id(state, block);
|
||||
if props.stage == 0 {
|
||||
props.stage = 1;
|
||||
@ -32,10 +32,8 @@ impl SaplingBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for SaplingBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -32,10 +32,9 @@ impl BlockBehaviour for SeaPickleBlock {
|
||||
|| !args
|
||||
.world
|
||||
.get_block(&args.position.down())
|
||||
.await
|
||||
.has_tag(&tag::Block::MINECRAFT_CORAL_BLOCKS)
|
||||
|| !SeaPickleProperties::from_state_id(
|
||||
args.world.get_block_state_id(args.position).await,
|
||||
args.world.get_block_state_id(args.position),
|
||||
args.block,
|
||||
)
|
||||
.waterlogged
|
||||
@ -62,11 +61,10 @@ impl BlockBehaviour for SeaPickleBlock {
|
||||
);
|
||||
if &lv == args.position
|
||||
|| rand::rng().random_range(0..6) != 0
|
||||
|| !args.world.get_block(&lv).await.eq(&Block::WATER)
|
||||
|| !args.world.get_block(&lv).eq(&Block::WATER)
|
||||
|| !args
|
||||
.world
|
||||
.get_block(&lv.down())
|
||||
.await
|
||||
.has_tag(&tag::Block::MINECRAFT_CORAL_BLOCKS)
|
||||
{
|
||||
continue;
|
||||
@ -124,21 +122,14 @@ impl BlockBehaviour for SeaPickleBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
let support_block = args
|
||||
.block_accessor
|
||||
.get_block_state(&args.position.down())
|
||||
.await;
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
let support_block = args.block_accessor.get_block_state(&args.position.down());
|
||||
support_block.is_center_solid(BlockDirection::Up)
|
||||
})
|
||||
}
|
||||
|
||||
fn can_update_at<'a>(&'a self, args: CanUpdateAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_update_at(&self, args: CanUpdateAtArgs<'_>) -> bool {
|
||||
args.player.get_entity().pose.load() != EntityPose::Crouching
|
||||
&& SeaPickleProperties::from_state_id(args.state_id, args.block).pickles < 4
|
||||
})
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -13,10 +13,8 @@ use crate::block::{
|
||||
#[pumpkin_block("minecraft:seagrass")]
|
||||
pub struct SeaGrassBlock;
|
||||
impl BlockBehaviour for SeaGrassBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -36,13 +34,13 @@ impl BlockBehaviour for SeaGrassBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for SeaGrassBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(pos).await;
|
||||
let replacing_block = block_accessor.get_block(&pos.up()).await;
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(pos);
|
||||
let replacing_block = block_accessor.get_block(&pos.up());
|
||||
if replacing_block != &Block::WATER && replacing_block != &Block::SEAGRASS {
|
||||
return false;
|
||||
}
|
||||
@ -57,7 +55,7 @@ impl PlantBlockBase for SeaGrassBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
return Block::WATER.default_state.id;
|
||||
}
|
||||
block_state
|
||||
|
||||
@ -73,11 +73,9 @@ pub trait Segmented: BlockBehaviour {
|
||||
}
|
||||
}
|
||||
|
||||
fn can_update_at<'a>(&'a self, ctx: CanUpdateAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_update_at(&self, ctx: CanUpdateAtArgs<'_>) -> bool {
|
||||
let current_props = Self::Properties::from_state_id(ctx.state_id, ctx.block);
|
||||
self.can_add_segment(¤t_props)
|
||||
})
|
||||
}
|
||||
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
|
||||
@ -15,10 +15,8 @@ impl BlockMetadata for ShortPlantBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for ShortPlantBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
|
||||
@ -17,10 +17,8 @@ use pumpkin_world::world::{BlockAccessor, BlockFlags};
|
||||
pub struct SmallDripleafBlock;
|
||||
|
||||
impl BlockBehaviour for SmallDripleafBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
@ -65,7 +63,7 @@ impl BlockBehaviour for SmallDripleafBlock {
|
||||
let mut upper_small_dripleaf_props =
|
||||
SmallDripleafLikeProperties::default(&Block::SMALL_DRIPLEAF);
|
||||
|
||||
let upper_block = args.world.get_block(&args.position.up()).await;
|
||||
let upper_block = args.world.get_block(&args.position.up());
|
||||
upper_small_dripleaf_props.facing = lower_small_dripleaf_props.facing;
|
||||
upper_small_dripleaf_props.waterlogged = upper_block == &Block::WATER;
|
||||
upper_small_dripleaf_props.half = DoubleBlockHalf::Upper;
|
||||
@ -86,13 +84,13 @@ fn is_small_dripleaf_waterlogged(state_id: BlockStateId) -> bool {
|
||||
dripleaf_props.waterlogged
|
||||
}
|
||||
impl PlantBlockBase for SmallDripleafBlock {
|
||||
async fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let support_block = block_accessor.get_block(pos).await;
|
||||
fn can_plant_on_top(&self, block_accessor: &dyn BlockAccessor, pos: &BlockPos) -> bool {
|
||||
let support_block = block_accessor.get_block(pos);
|
||||
|
||||
if support_block == &Block::SMALL_DRIPLEAF {
|
||||
return true;
|
||||
}
|
||||
let upper_block = block_accessor.get_block(&pos.up_height(2)).await;
|
||||
let upper_block = block_accessor.get_block(&pos.up_height(2));
|
||||
if upper_block != &Block::AIR
|
||||
&& upper_block != &Block::WATER
|
||||
&& upper_block != &Block::SMALL_DRIPLEAF
|
||||
@ -100,7 +98,7 @@ impl PlantBlockBase for SmallDripleafBlock {
|
||||
return false;
|
||||
}
|
||||
let (replacing_block, replacing_block_state) =
|
||||
block_accessor.get_block_and_state(&pos.up()).await;
|
||||
block_accessor.get_block_and_state(&pos.up());
|
||||
if replacing_block == &Block::SMALL_DRIPLEAF && replacing_block_state.is_waterlogged() {
|
||||
//in case of neighbor update check
|
||||
supports_small_dripleaf(support_block, true)
|
||||
@ -115,14 +113,14 @@ impl PlantBlockBase for SmallDripleafBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
if is_small_dripleaf_waterlogged(block_state) {
|
||||
return Block::WATER.default_state.id;
|
||||
}
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
let upper_block = block_accessor.get_block(&block_pos.up()).await;
|
||||
let below_blow = block_accessor.get_block(&block_pos.down()).await;
|
||||
let upper_block = block_accessor.get_block(&block_pos.up());
|
||||
let below_blow = block_accessor.get_block(&block_pos.down());
|
||||
if upper_block != &Block::SMALL_DRIPLEAF && below_blow != &Block::SMALL_DRIPLEAF {
|
||||
if is_small_dripleaf_waterlogged(block_state) {
|
||||
return Block::WATER.default_state.id;
|
||||
|
||||
@ -11,10 +11,8 @@ use pumpkin_world::world::BlockAccessor;
|
||||
pub struct SporeBlossomBlock;
|
||||
|
||||
impl BlockBehaviour for SporeBlossomBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -32,15 +30,15 @@ impl BlockBehaviour for SporeBlossomBlock {
|
||||
}
|
||||
}
|
||||
impl PlantBlockBase for SporeBlossomBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
_block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
_pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
async fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let ceiling_block = block_accessor.get_block(&block_pos.up()).await;
|
||||
fn can_place_at(&self, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let ceiling_block = block_accessor.get_block(&block_pos.up());
|
||||
supports_spore_blossom(ceiling_block)
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ pub struct SugarCaneBlock;
|
||||
impl BlockBehaviour for SugarCaneBlock {
|
||||
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).await {
|
||||
if !can_place_at(args.world.as_ref(), args.position) {
|
||||
args.world
|
||||
.break_block(args.position, None, BlockFlags::empty())
|
||||
.await;
|
||||
@ -32,16 +32,11 @@ impl BlockBehaviour for SugarCaneBlock {
|
||||
|
||||
fn random_tick<'a>(&'a self, args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if args
|
||||
.world
|
||||
.get_block_state(&args.position.up())
|
||||
.await
|
||||
.is_air()
|
||||
&& !(args.world.get_block(&args.position.down()).await == &Block::SUGAR_CANE
|
||||
&& args.world.get_block(&args.position.down().down()).await
|
||||
== &Block::SUGAR_CANE)
|
||||
if args.world.get_block_state(&args.position.up()).is_air()
|
||||
&& !(args.world.get_block(&args.position.down()) == &Block::SUGAR_CANE
|
||||
&& args.world.get_block(&args.position.down().down()) == &Block::SUGAR_CANE)
|
||||
{
|
||||
let state_id = args.world.get_block_state(args.position).await.id;
|
||||
let state_id = args.world.get_block_state(args.position).id;
|
||||
let age = CactusLikeProperties::from_state_id(state_id, args.block).age;
|
||||
if age == 15 {
|
||||
args.world
|
||||
@ -74,7 +69,7 @@ impl BlockBehaviour for SugarCaneBlock {
|
||||
args: GetStateForNeighborUpdateArgs<'a>,
|
||||
) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if !can_place_at(args.world, args.position).await {
|
||||
if !can_place_at(args.world, args.position) {
|
||||
args.world
|
||||
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
|
||||
.await;
|
||||
@ -83,13 +78,13 @@ impl BlockBehaviour for SugarCaneBlock {
|
||||
})
|
||||
}
|
||||
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move { can_place_at(args.block_accessor, args.position).await })
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
can_place_at(args.block_accessor, args.position)
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let block_below = block_accessor.get_block(&block_pos.down()).await;
|
||||
fn can_place_at(block_accessor: &dyn BlockAccessor, block_pos: &BlockPos) -> bool {
|
||||
let block_below = block_accessor.get_block(&block_pos.down());
|
||||
|
||||
if block_below == &Block::SUGAR_CANE {
|
||||
return true;
|
||||
@ -97,9 +92,7 @@ async fn can_place_at(block_accessor: &dyn BlockAccessor, block_pos: &BlockPos)
|
||||
|
||||
if block_below.has_tag(&tag::Block::MINECRAFT_SUPPORTS_SUGAR_CANE) {
|
||||
for direction in HorizontalFacing::all() {
|
||||
let block = block_accessor
|
||||
.get_block(&block_pos.down().offset(direction.to_offset()))
|
||||
.await;
|
||||
let block = block_accessor.get_block(&block_pos.down().offset(direction.to_offset()));
|
||||
// TODO: use fluid
|
||||
if block.has_tag(&tag::Fluid::MINECRAFT_SUPPORTS_SUGAR_CANE_ADJACENTLY)
|
||||
&& block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_SUGAR_CANE_ADJACENTLY)
|
||||
|
||||
@ -32,32 +32,23 @@ impl BlockMetadata for TallPlantBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for TallPlantBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
let up_pos = args.position.up();
|
||||
|
||||
let upper_state = args.block_accessor.get_block_state(&up_pos).await;
|
||||
let upper_state = args.block_accessor.get_block_state(&up_pos);
|
||||
let Some(world) = args.world else {
|
||||
return <Self as PlantBlockBase>::can_place_at(
|
||||
self,
|
||||
args.block_accessor,
|
||||
args.position,
|
||||
)
|
||||
.await
|
||||
&& upper_state.is_air();
|
||||
) && upper_state.is_air();
|
||||
};
|
||||
|
||||
if up_pos.0.y > world.get_top_y() {
|
||||
return false;
|
||||
}
|
||||
return <Self as PlantBlockBase>::can_place_at(
|
||||
self,
|
||||
args.block_accessor,
|
||||
args.position,
|
||||
)
|
||||
.await
|
||||
&& upper_state.is_air();
|
||||
})
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
&& upper_state.is_air()
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -71,14 +62,11 @@ impl BlockBehaviour for TallPlantBlock {
|
||||
DoubleBlockHalf::Upper => (args.position.down_height(2), args.position.down()),
|
||||
DoubleBlockHalf::Lower => (args.position.down(), args.position.up()),
|
||||
};
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world, &support_block_pos.up())
|
||||
.await
|
||||
{
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, args.world, &support_block_pos.up()) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
|
||||
let (other_block, other_state_id) =
|
||||
args.world.get_block_and_state_id(&other_block_pos).await;
|
||||
let (other_block, other_state_id) = args.world.get_block_and_state_id(&other_block_pos);
|
||||
if Self::ids().contains(&other_block.id) {
|
||||
let other_props =
|
||||
TallSeagrassLikeProperties::from_state_id(other_state_id, other_block);
|
||||
@ -117,8 +105,7 @@ impl BlockBehaviour for TallPlantBlock {
|
||||
DoubleBlockHalf::Upper => args.position.down(),
|
||||
DoubleBlockHalf::Lower => args.position.up(),
|
||||
};
|
||||
let (other_block, other_state_id) =
|
||||
args.world.get_block_and_state_id(&other_block_pos).await;
|
||||
let (other_block, other_state_id) = args.world.get_block_and_state_id(&other_block_pos);
|
||||
if Self::ids().contains(&other_block.id) {
|
||||
let other_props =
|
||||
TallSeagrassLikeProperties::from_state_id(other_state_id, other_block);
|
||||
|
||||
@ -10,10 +10,8 @@ use crate::block::{
|
||||
#[pumpkin_block("minecraft:tall_seagrass")]
|
||||
pub struct TallSeaGrassBlock;
|
||||
impl BlockBehaviour for TallSeaGrassBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
@ -33,20 +31,20 @@ impl BlockBehaviour for TallSeaGrassBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for TallSeaGrassBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(pos).await;
|
||||
let replacing_block = block_accessor.get_block(&pos.up()).await;
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(pos);
|
||||
let replacing_block = block_accessor.get_block(&pos.up());
|
||||
if replacing_block != &Block::WATER && replacing_block != &Block::TALL_SEAGRASS {
|
||||
return false;
|
||||
}
|
||||
|
||||
if replacing_block == &Block::TALL_SEAGRASS {
|
||||
//only for blockupdate
|
||||
let block_above = block_accessor.get_block(&pos.up_height(2)).await;
|
||||
let block_above = block_accessor.get_block(&pos.up_height(2));
|
||||
let is_support_seagrass_block = support_block == &Block::TALL_SEAGRASS;
|
||||
let is_above_seagrass_block = block_above == &Block::TALL_SEAGRASS;
|
||||
match (is_support_seagrass_block, is_above_seagrass_block) {
|
||||
@ -68,7 +66,7 @@ impl PlantBlockBase for TallSeaGrassBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
return Block::WATER.default_state.id;
|
||||
}
|
||||
block_state
|
||||
|
||||
@ -16,10 +16,8 @@ impl BlockMetadata for TwistingVinesBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for TwistingVinesBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -38,7 +36,7 @@ impl BlockBehaviour for TwistingVinesBlock {
|
||||
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let support_pos = args.position.down();
|
||||
let support_block = args.world.get_block(&support_pos).await;
|
||||
let support_block = args.world.get_block(&support_pos);
|
||||
if support_block == &Block::TWISTING_VINES {
|
||||
args.world
|
||||
.set_block_state(
|
||||
@ -53,7 +51,7 @@ impl BlockBehaviour for TwistingVinesBlock {
|
||||
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;
|
||||
let support_block = args.world.get_block(&support_pos);
|
||||
if support_block == &Block::TWISTING_VINES_PLANT {
|
||||
args.world
|
||||
.set_block_state(
|
||||
@ -68,15 +66,14 @@ impl BlockBehaviour for TwistingVinesBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for TwistingVinesBlock {
|
||||
async fn can_plant_on_top(
|
||||
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 (support_block, support_block_state) =
|
||||
block_accessor.get_block_and_state(support_pos).await;
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(support_pos);
|
||||
|
||||
if support_block == &Block::TWISTING_VINES || support_block == &Block::TWISTING_VINES_PLANT
|
||||
{
|
||||
@ -95,7 +92,7 @@ impl PlantBlockBase for TwistingVinesBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
block_state
|
||||
|
||||
@ -16,10 +16,8 @@ impl BlockMetadata for WeepingVinesBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for WeepingVinesBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -38,7 +36,7 @@ impl BlockBehaviour for WeepingVinesBlock {
|
||||
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let support_pos = args.position.up();
|
||||
let support_block = args.world.get_block(&support_pos).await;
|
||||
let support_block = args.world.get_block(&support_pos);
|
||||
if support_block == &Block::WEEPING_VINES {
|
||||
args.world
|
||||
.set_block_state(
|
||||
@ -53,7 +51,7 @@ impl BlockBehaviour for WeepingVinesBlock {
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let support_pos = args.position.up();
|
||||
let support_block = args.world.get_block(&support_pos).await;
|
||||
let support_block = args.world.get_block(&support_pos);
|
||||
if support_block == &Block::WEEPING_VINES_PLANT {
|
||||
args.world
|
||||
.set_block_state(
|
||||
@ -68,15 +66,14 @@ impl BlockBehaviour for WeepingVinesBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for WeepingVinesBlock {
|
||||
async fn can_place_at(
|
||||
fn can_place_at(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
// Determine support block
|
||||
let support_pos = pos.up();
|
||||
let (support_block, support_block_state) =
|
||||
block_accessor.get_block_and_state(&support_pos).await;
|
||||
let (support_block, support_block_state) = block_accessor.get_block_and_state(&support_pos);
|
||||
|
||||
if support_block == &Block::WEEPING_VINES || support_block == &Block::WEEPING_VINES_PLANT {
|
||||
return true;
|
||||
@ -94,7 +91,7 @@ impl PlantBlockBase for WeepingVinesBlock {
|
||||
block_pos: &BlockPos,
|
||||
block_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos).await {
|
||||
if !<Self as PlantBlockBase>::can_place_at(self, block_accessor, block_pos) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
block_state
|
||||
|
||||
@ -42,10 +42,8 @@ impl BlockBehaviour for WitherRoseBlock {
|
||||
}
|
||||
})
|
||||
}
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position).await
|
||||
})
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
<Self as PlantBlockBase>::can_place_at(self, args.block_accessor, args.position)
|
||||
}
|
||||
fn get_state_for_neighbor_update<'a>(
|
||||
&'a self,
|
||||
@ -64,12 +62,12 @@ impl BlockBehaviour for WitherRoseBlock {
|
||||
}
|
||||
|
||||
impl PlantBlockBase for WitherRoseBlock {
|
||||
async fn can_plant_on_top(
|
||||
fn can_plant_on_top(
|
||||
&self,
|
||||
block_accessor: &dyn pumpkin_world::world::BlockAccessor,
|
||||
pos: &pumpkin_util::math::position::BlockPos,
|
||||
) -> bool {
|
||||
let support_block = block_accessor.get_block(pos).await;
|
||||
let support_block = block_accessor.get_block(pos);
|
||||
support_block.has_tag(&tag::Block::MINECRAFT_SUPPORTS_WITHER_ROSE)
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ impl BlockBehaviour for PowderSnowBlock {
|
||||
Sound::EntityGenericBigFall
|
||||
};
|
||||
|
||||
living.entity.play_sound(sound).await;
|
||||
living.entity.play_sound(sound);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -42,8 +42,10 @@ impl crate::block::BlockBehaviour for PumpkinBlock {
|
||||
args.position.to_f64(),
|
||||
&EntityType::ITEM,
|
||||
);
|
||||
let item_entity =
|
||||
Arc::new(ItemEntity::new(entity, ItemStack::new(4, &Item::PUMPKIN_SEEDS)).await);
|
||||
let item_entity = Arc::new(ItemEntity::new(
|
||||
entity,
|
||||
ItemStack::new(4, &Item::PUMPKIN_SEEDS),
|
||||
));
|
||||
args.world.spawn_entity(item_entity).await;
|
||||
// TODO: Deduct 1 durability from held shears (skip in Creative mode).
|
||||
BlockActionResult::Consume
|
||||
|
||||
@ -32,30 +32,24 @@ pub trait RedstoneGateBlockProperties {
|
||||
}
|
||||
|
||||
pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlockProperties> {
|
||||
// 💡 Converted async fn to fn returning BlockFuture
|
||||
fn can_place_at<'a>(
|
||||
&'a self,
|
||||
world: &'a dyn BlockAccessor,
|
||||
pos: BlockPos,
|
||||
) -> BlockFuture<'a, bool>
|
||||
// 💡 Converted async fn to fn
|
||||
fn can_place_at(&self, world: &dyn BlockAccessor, pos: BlockPos) -> bool
|
||||
where
|
||||
Self: Send + Sync,
|
||||
{
|
||||
Box::pin(async move {
|
||||
let under_pos = pos.down();
|
||||
let under_state = world.get_block_state(&under_pos).await;
|
||||
self.can_place_above(world, under_pos, under_state).await
|
||||
})
|
||||
let under_state = world.get_block_state(&under_pos);
|
||||
self.can_place_above(world, under_pos, under_state)
|
||||
}
|
||||
|
||||
// 💡 Converted async fn to fn returning BlockFuture
|
||||
fn can_place_above<'a>(
|
||||
&'a self,
|
||||
_world: &'a dyn BlockAccessor,
|
||||
// 💡 Converted async fn to fn
|
||||
fn can_place_above(
|
||||
&self,
|
||||
_world: &dyn BlockAccessor,
|
||||
_pos: BlockPos,
|
||||
state: &'a BlockState,
|
||||
) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async { state.is_side_solid(BlockDirection::Up) })
|
||||
state: &BlockState,
|
||||
) -> bool {
|
||||
state.is_side_solid(BlockDirection::Up)
|
||||
}
|
||||
|
||||
fn get_weak_redstone_power<'a>(&'a self, args: GetRedstonePowerArgs<'a>) -> BlockFuture<'a, u8>
|
||||
@ -90,8 +84,8 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
|
||||
Self: Send + Sync,
|
||||
{
|
||||
Box::pin(async move {
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
if RedstoneGateBlock::can_place_at(self, args.world.as_ref(), *args.position).await {
|
||||
let state = args.world.get_block_state(args.position);
|
||||
if RedstoneGateBlock::can_place_at(self, args.world.as_ref(), *args.position) {
|
||||
self.update_powered(args.world, *args.position, state, args.block)
|
||||
.await;
|
||||
return;
|
||||
@ -259,9 +253,8 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
|
||||
Box::pin(async move {
|
||||
let props = T::from_state_id(state.id, block);
|
||||
let facing = props.get_facing().opposite();
|
||||
let (target_block, target_state) = world
|
||||
.get_block_and_state(&pos.offset(facing.to_offset()))
|
||||
.await;
|
||||
let (target_block, target_state) =
|
||||
world.get_block_and_state(&pos.offset(facing.to_offset()));
|
||||
if target_block == &Block::COMPARATOR {
|
||||
let props = ComparatorLikeProperties::from_state_id(target_state.id, target_block);
|
||||
props.facing != facing
|
||||
@ -286,7 +279,7 @@ pub async fn get_power<T: BlockProperties + RedstoneGateBlockProperties + Send>(
|
||||
let props = T::from_state_id(state_id, block);
|
||||
let facing = props.get_facing();
|
||||
let source_pos = pos.offset(facing.to_offset());
|
||||
let (source_block, source_state) = world.get_block_and_state(&source_pos).await;
|
||||
let (source_block, source_state) = world.get_block_and_state(&source_pos);
|
||||
let source_level = get_redstone_power(
|
||||
source_block,
|
||||
source_state,
|
||||
@ -314,7 +307,7 @@ async fn get_power_on_side(
|
||||
only_gate: bool,
|
||||
) -> u8 {
|
||||
let side_pos = pos.offset(side.to_block_direction().to_offset());
|
||||
let (side_block, side_state) = world.get_block_and_state(&side_pos).await;
|
||||
let (side_block, side_state) = world.get_block_and_state(&side_pos);
|
||||
if !only_gate || is_diode(side_block) {
|
||||
world
|
||||
.block_registry
|
||||
|
||||
@ -21,31 +21,25 @@ use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
async fn ring_bell(
|
||||
position: BlockPos,
|
||||
world: &Arc<World>,
|
||||
hit_direction: Option<HorizontalFacing>,
|
||||
) {
|
||||
let (block, state_id) = world.get_block_and_state_id(&position).await;
|
||||
fn ring_bell(position: BlockPos, world: &Arc<World>, hit_direction: Option<HorizontalFacing>) {
|
||||
let (block, state_id) = world.get_block_and_state_id(&position);
|
||||
|
||||
let props = BellLikeProperties::from_state_id(state_id, block);
|
||||
let direction = hit_direction.map_or(props.facing, |direction3| direction3);
|
||||
|
||||
if let Some(block_entity) = world.get_block_entity(&position).await
|
||||
if let Some(block_entity) = world.get_block_entity(&position)
|
||||
&& let Some(be) = block_entity.as_any().downcast_ref::<BellBlockEntity>()
|
||||
{
|
||||
be.activate(direction);
|
||||
}
|
||||
|
||||
world
|
||||
.play_sound_fine(
|
||||
world.play_sound_fine(
|
||||
Sound::BlockBellUse,
|
||||
SoundCategory::Blocks,
|
||||
&position.to_centered_f64(),
|
||||
1.0,
|
||||
2.0,
|
||||
)
|
||||
.await;
|
||||
);
|
||||
|
||||
//TODO Emit game event: BLOCK_CHANGE -> Send block update Packet
|
||||
}
|
||||
@ -73,10 +67,9 @@ fn is_point_on_bell(
|
||||
}
|
||||
}
|
||||
|
||||
async fn is_single_wall(position: BlockPos, facing: HorizontalFacing, world: &World) -> bool {
|
||||
fn is_single_wall(position: BlockPos, facing: HorizontalFacing, world: &World) -> bool {
|
||||
!world
|
||||
.get_block(&position.offset(facing.to_offset()))
|
||||
.await
|
||||
.is_solid()
|
||||
}
|
||||
|
||||
@ -97,28 +90,26 @@ impl WallMountedBlock for BellBlock {
|
||||
}
|
||||
|
||||
impl BlockBehaviour for BellBlock {
|
||||
fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
|
||||
if let Some(direction) = args.direction
|
||||
&& let Some(world) = args.world
|
||||
{
|
||||
if direction == BlockDirection::Up {
|
||||
let block: &Block = world.get_block(args.position).await;
|
||||
let block: &Block = world.get_block(args.position);
|
||||
|
||||
if block.has_tag(&tag::Block::MINECRAFT_UNSTABLE_BOTTOM_CENTER) {
|
||||
false
|
||||
} else {
|
||||
let block_pos = args.position.offset(direction.to_offset());
|
||||
let block_state = world.get_block_state(&block_pos).await;
|
||||
let block_state = world.get_block_state(&block_pos);
|
||||
block_state.is_center_solid(direction)
|
||||
}
|
||||
} else {
|
||||
WallMountedBlock::can_place_at(self, world, args.position, direction).await
|
||||
WallMountedBlock::can_place_at(self, world, args.position, direction)
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
@ -136,7 +127,7 @@ impl BlockBehaviour for BellBlock {
|
||||
}
|
||||
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {
|
||||
Box::pin(async move {
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
let state = args.world.get_block_state(args.position);
|
||||
|
||||
let props = BellLikeProperties::from_state_id(state.id, args.block);
|
||||
|
||||
@ -147,8 +138,7 @@ impl BlockBehaviour for BellBlock {
|
||||
*args.position,
|
||||
args.world,
|
||||
args.hit.face.to_horizontal_facing(),
|
||||
)
|
||||
.await;
|
||||
);
|
||||
|
||||
BlockActionResult::Success
|
||||
})
|
||||
@ -170,7 +160,7 @@ impl BlockBehaviour for BellBlock {
|
||||
|
||||
props.attachment = match block_face {
|
||||
AttachFace::Wall => {
|
||||
if is_single_wall(*args.position, props.facing.opposite(), args.world).await {
|
||||
if is_single_wall(*args.position, props.facing.opposite(), args.world) {
|
||||
BellAttachment::SingleWall
|
||||
} else {
|
||||
BellAttachment::DoubleWall
|
||||
@ -189,7 +179,7 @@ impl BlockBehaviour for BellBlock {
|
||||
let world: &World = args.world;
|
||||
|
||||
let is_receiving_power = block_receives_redstone_power(world, args.position).await;
|
||||
let state = args.world.get_block_state(args.position).await;
|
||||
let state = args.world.get_block_state(args.position);
|
||||
|
||||
let mut props = BellLikeProperties::from_state_id(state.id, args.block);
|
||||
|
||||
@ -205,7 +195,7 @@ impl BlockBehaviour for BellBlock {
|
||||
.await;
|
||||
|
||||
if is_receiving_power {
|
||||
ring_bell(*args.position, args.world, None).await;
|
||||
ring_bell(*args.position, args.world, None);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user