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