chore: less awaits more fun part 2

This commit is contained in:
Alexander Medvedev 2026-05-14 20:34:55 +02:00
parent d5026cb55e
commit cf9c7e85dc
78 changed files with 494 additions and 623 deletions

View File

@ -89,12 +89,6 @@ inherits = "release"
debug = true debug = true
strip = false strip = false
[profile.dev]
debug = "line-tables-only"
debug-assertions = true
overflow-checks = false
split-debuginfo = "packed"
opt-level = 0
[workspace.dependencies] [workspace.dependencies]
tokio = { version = "1.52", default-features = false } tokio = { version = "1.52", default-features = false }

View File

@ -697,27 +697,27 @@ impl Level {
} }
} }
pub async fn get_block_state(self: &Arc<Self>, position: &BlockPos) -> RawBlockState { pub fn get_block_state(&self, position: &BlockPos) -> RawBlockState {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
let id = self let id = self
.get_or_fetch_chunk(chunk_coordinate, |chunk| { .read_chunk_sync(&chunk_coordinate, |chunk| {
chunk.section.get_block_absolute_y( chunk.section.get_block_absolute_y(
relative.x as usize, relative.x as usize,
relative.y, relative.y,
relative.z as usize, relative.z as usize,
) )
}) })
.await; .flatten();
RawBlockState(id.unwrap_or(Block::VOID_AIR.default_state.id)) RawBlockState(id.unwrap_or(Block::VOID_AIR.default_state.id))
} }
pub async fn set_block_state( pub fn set_block_state(
self: &Arc<Self>, &self,
position: &BlockPos, position: &BlockPos,
block_state_id: BlockStateId, block_state_id: BlockStateId,
) -> BlockStateId { ) -> BlockStateId {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
self.get_or_fetch_chunk(chunk_coordinate, |chunk| { self.read_chunk_sync(&chunk_coordinate, |chunk| {
let replaced_block_state_id = chunk.set_block_absolute_y( let replaced_block_state_id = chunk.set_block_absolute_y(
relative.x as usize, relative.x as usize,
relative.y, relative.y,
@ -729,7 +729,7 @@ impl Level {
} }
replaced_block_state_id replaced_block_state_id
}) })
.await .unwrap_or(Block::VOID_AIR.default_state.id)
} }
pub async fn write_chunks(&self, chunks_to_write: Vec<(Vector2<i32>, SyncChunk)>) { pub async fn write_chunks(&self, chunks_to_write: Vec<(Vector2<i32>, SyncChunk)>) {
@ -831,8 +831,8 @@ impl Level {
self.loaded_entity_chunks.try_get(&coordinates).try_unwrap() self.loaded_entity_chunks.try_get(&coordinates).try_unwrap()
} }
pub async fn schedule_block_tick( pub fn schedule_block_tick(
self: &Arc<Self>, &self,
block: &Block, block: &Block,
block_pos: BlockPos, block_pos: BlockPos,
delay: u8, delay: u8,
@ -847,15 +847,18 @@ impl Level {
}; };
let chunk_pos = block_pos.chunk_position(); let chunk_pos = block_pos.chunk_position();
self.get_or_fetch_chunk(chunk_pos, |chunk| { if self
.read_chunk_sync(&chunk_pos, |chunk| {
chunk.block_ticks.schedule_tick(&scheduled_tick, tick_order); chunk.block_ticks.schedule_tick(&scheduled_tick, tick_order);
}) })
.await; .is_some()
{
self.chunks_with_scheduled_ticks.insert(chunk_pos); self.chunks_with_scheduled_ticks.insert(chunk_pos);
} }
}
pub async fn schedule_fluid_tick( pub fn schedule_fluid_tick(
self: &Arc<Self>, &self,
fluid: &Fluid, fluid: &Fluid,
block_pos: BlockPos, block_pos: BlockPos,
delay: u8, delay: u8,
@ -870,32 +873,27 @@ impl Level {
}; };
let chunk_pos = block_pos.chunk_position(); let chunk_pos = block_pos.chunk_position();
self.get_or_fetch_chunk(chunk_pos, |chunk| { if self
.read_chunk_sync(&chunk_pos, |chunk| {
chunk.fluid_ticks.schedule_tick(&scheduled_tick, tick_order); chunk.fluid_ticks.schedule_tick(&scheduled_tick, tick_order);
}) })
.await; .is_some()
{
self.chunks_with_scheduled_ticks.insert(chunk_pos); self.chunks_with_scheduled_ticks.insert(chunk_pos);
} }
}
pub async fn is_block_tick_scheduled( pub fn is_block_tick_scheduled(&self, block_pos: &BlockPos, block: &Block) -> bool {
self: &Arc<Self>, self.read_chunk_sync(&block_pos.chunk_position(), |chunk| {
block_pos: &BlockPos,
block: &Block,
) -> bool {
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
chunk.block_ticks.is_scheduled(*block_pos, block) chunk.block_ticks.is_scheduled(*block_pos, block)
}) })
.await .unwrap_or(false)
} }
pub async fn is_fluid_tick_scheduled( pub fn is_fluid_tick_scheduled(&self, block_pos: &BlockPos, fluid: &Fluid) -> bool {
self: &Arc<Self>, self.read_chunk_sync(&block_pos.chunk_position(), |chunk| {
block_pos: &BlockPos,
fluid: &Fluid,
) -> bool {
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
chunk.fluid_ticks.is_scheduled(*block_pos, fluid) chunk.fluid_ticks.is_scheduled(*block_pos, fluid)
}) })
.await .unwrap_or(false)
} }
} }

View File

@ -40,7 +40,7 @@ impl DynamicLightEngine {
while current_pos.0.y < max_y { while current_pos.0.y < max_y {
current_pos.0.y += 1; current_pos.0.y += 1;
let state = level.get_block_state(&current_pos).await.to_state(); let state = level.get_block_state(&current_pos).to_state();
if state.opacity > 0 { if state.opacity > 0 {
return false; // Hit an opaque block before reaching sky return false; // Hit an opaque block before reaching sky
} }
@ -130,8 +130,8 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() { for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset()); let neighbor_pos = pos.offset(dir.to_offset());
if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos).await { if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos) {
let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); let neighbor_state = level.get_block_state(&neighbor_pos).to_state();
let opacity = neighbor_state.opacity.max(1); let opacity = neighbor_state.opacity.max(1);
let new_light = light_level.saturating_sub(opacity); let new_light = light_level.saturating_sub(opacity);
@ -139,7 +139,6 @@ impl DynamicLightEngine {
if new_light > neighbor_light if new_light > neighbor_light
&& self && self
.set_block_light_level(level, &neighbor_pos, new_light) .set_block_light_level(level, &neighbor_pos, new_light)
.await
.is_ok() .is_ok()
&& new_light > 1 && new_light > 1
{ {
@ -156,7 +155,7 @@ impl DynamicLightEngine {
removed_light_level: u8, removed_light_level: u8,
) { ) {
// Check what the current light level actually is at this position // Check what the current light level actually is at this position
let current_level = self.get_block_light_level(level, pos).await.unwrap_or(0); let current_level = self.get_block_light_level(level, pos).unwrap_or(0);
// Only propagate decrease if this position hasn't already been reset to 0 // Only propagate decrease if this position hasn't already been reset to 0
// This prevents positions that were intentionally set to 0 from propagating light // This prevents positions that were intentionally set to 0 from propagating light
@ -165,13 +164,12 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() { for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset()); let neighbor_pos = pos.offset(dir.to_offset());
if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos).await if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos) {
{
if neighbor_light == 0 { if neighbor_light == 0 {
continue; // Skip if already 0 continue; // Skip if already 0
} }
let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); let neighbor_state = level.get_block_state(&neighbor_pos).to_state();
let opacity = neighbor_state.opacity.max(1); let opacity = neighbor_state.opacity.max(1);
let expected_from_removed_source = removed_light_level.saturating_sub(opacity); let expected_from_removed_source = removed_light_level.saturating_sub(opacity);
@ -181,14 +179,11 @@ impl DynamicLightEngine {
if neighbor_luminance == 0 { if neighbor_luminance == 0 {
// No self-emission, darken it completely and continue propagation // No self-emission, darken it completely and continue propagation
self.set_block_light_level(level, &neighbor_pos, 0) self.set_block_light_level(level, &neighbor_pos, 0).ok();
.await
.ok();
self.queue_block_light_decrease(neighbor_pos, neighbor_light); self.queue_block_light_decrease(neighbor_pos, neighbor_light);
} else { } else {
// Has self-emission, set to its own light and re-propagate from it // Has self-emission, set to its own light and re-propagate from it
self.set_block_light_level(level, &neighbor_pos, neighbor_luminance) self.set_block_light_level(level, &neighbor_pos, neighbor_luminance)
.await
.ok(); .ok();
self.queue_block_light_increase(neighbor_pos, neighbor_luminance); self.queue_block_light_increase(neighbor_pos, neighbor_luminance);
} }
@ -204,32 +199,28 @@ impl DynamicLightEngine {
pub async fn check_block_light_updates(&self, level: &Arc<Level>, pos: BlockPos) { pub async fn check_block_light_updates(&self, level: &Arc<Level>, pos: BlockPos) {
match level.lighting_config { match level.lighting_config {
LightingEngineConfig::Full => { LightingEngineConfig::Full => {
self.set_block_light_level(level, &pos, 15).await.ok(); self.set_block_light_level(level, &pos, 15).ok();
return; return;
} }
LightingEngineConfig::Dark => { LightingEngineConfig::Dark => {
self.set_block_light_level(level, &pos, 0).await.ok(); self.set_block_light_level(level, &pos, 0).ok();
return; return;
} }
LightingEngineConfig::Default => {} LightingEngineConfig::Default => {}
} }
let current_light = self.get_block_light_level(level, &pos).await.unwrap_or(0); let current_light = self.get_block_light_level(level, &pos).unwrap_or(0);
let block_state = level.get_block_state(&pos).await.to_state(); let block_state = level.get_block_state(&pos).to_state();
let expected_light = block_state.luminance; let expected_light = block_state.luminance;
// Handle light decrease (removing light source or placing opaque block) // Handle light decrease (removing light source or placing opaque block)
if expected_light < current_light { if expected_light < current_light {
// Set to expected value immediately, then queue decrease to darken neighbors // Set to expected value immediately, then queue decrease to darken neighbors
self.set_block_light_level(level, &pos, expected_light) self.set_block_light_level(level, &pos, expected_light).ok();
.await
.ok();
self.queue_block_light_decrease(pos, current_light); self.queue_block_light_decrease(pos, current_light);
} else if expected_light > current_light { } else if expected_light > current_light {
// Handle light increase (placing light source) // Handle light increase (placing light source)
self.set_block_light_level(level, &pos, expected_light) self.set_block_light_level(level, &pos, expected_light).ok();
.await
.ok();
self.queue_block_light_increase(pos, expected_light); self.queue_block_light_increase(pos, expected_light);
} }
@ -249,7 +240,7 @@ impl DynamicLightEngine {
) { ) {
for dir in BlockDirection::all() { for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset()); let neighbor_pos = pos.offset(dir.to_offset());
if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos).await if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos)
&& neighbor_light > current_light + 1 && neighbor_light > current_light + 1
{ {
self.queue_block_light_increase(neighbor_pos, neighbor_light); self.queue_block_light_increase(neighbor_pos, neighbor_light);
@ -301,8 +292,8 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() { for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset()); let neighbor_pos = pos.offset(dir.to_offset());
let neighbor_light = self.get_sky_light_level(level, &neighbor_pos).await; let neighbor_light = self.get_sky_light_level(level, &neighbor_pos);
let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); let neighbor_state = level.get_block_state(&neighbor_pos).to_state();
let opacity = neighbor_state.opacity; let opacity = neighbor_state.opacity;
// Calculate new light level for neighbor // Calculate new light level for neighbor
@ -317,7 +308,6 @@ impl DynamicLightEngine {
// Only propagate if new light is brighter than current light // Only propagate if new light is brighter than current light
if new_light > neighbor_light { if new_light > neighbor_light {
self.set_sky_light_level(level, &neighbor_pos, new_light) self.set_sky_light_level(level, &neighbor_pos, new_light)
.await
.ok(); .ok();
if new_light > 0 { if new_light > 0 {
@ -336,12 +326,12 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() { for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset()); let neighbor_pos = pos.offset(dir.to_offset());
let neighbor_light = self.get_sky_light_level(level, &neighbor_pos).await; let neighbor_light = self.get_sky_light_level(level, &neighbor_pos);
if neighbor_light == 0 { if neighbor_light == 0 {
continue; // Already dark continue; // Already dark
} }
let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); let neighbor_state = level.get_block_state(&neighbor_pos).to_state();
let opacity = neighbor_state.opacity; let opacity = neighbor_state.opacity;
// Calculate what we would have given this neighbor // Calculate what we would have given this neighbor
@ -353,7 +343,7 @@ impl DynamicLightEngine {
if neighbor_light == expected || neighbor_light < removed_light { if neighbor_light == expected || neighbor_light < removed_light {
// This neighbor was lit by us, darken it // This neighbor was lit by us, darken it
self.set_sky_light_level(level, &neighbor_pos, 0).await.ok(); self.set_sky_light_level(level, &neighbor_pos, 0).ok();
self.queue_sky_light_decrease(neighbor_pos, neighbor_light); self.queue_sky_light_decrease(neighbor_pos, neighbor_light);
} else if neighbor_light > removed_light { } else if neighbor_light > removed_light {
// Neighbor has brighter light from another source // Neighbor has brighter light from another source
@ -366,18 +356,18 @@ impl DynamicLightEngine {
pub async fn check_sky_light_updates(&self, level: &Arc<Level>, pos: BlockPos) { pub async fn check_sky_light_updates(&self, level: &Arc<Level>, pos: BlockPos) {
match level.lighting_config { match level.lighting_config {
LightingEngineConfig::Full => { LightingEngineConfig::Full => {
self.set_sky_light_level(level, &pos, 15).await.ok(); self.set_sky_light_level(level, &pos, 15).ok();
return; return;
} }
LightingEngineConfig::Dark => { LightingEngineConfig::Dark => {
self.set_sky_light_level(level, &pos, 0).await.ok(); self.set_sky_light_level(level, &pos, 0).ok();
return; return;
} }
LightingEngineConfig::Default => {} LightingEngineConfig::Default => {}
} }
let current_light = self.get_sky_light_level(level, &pos).await; let current_light = self.get_sky_light_level(level, &pos);
let block_state = level.get_block_state(&pos).await.to_state(); let block_state = level.get_block_state(&pos).to_state();
let opacity = block_state.opacity; let opacity = block_state.opacity;
// Calculate expected sky light // Calculate expected sky light
@ -398,7 +388,7 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() { for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset()); let neighbor_pos = pos.offset(dir.to_offset());
let neighbor_light = self.get_sky_light_level(level, &neighbor_pos).await; let neighbor_light = self.get_sky_light_level(level, &neighbor_pos);
// Calculate potential light from this neighbor // Calculate potential light from this neighbor
let potential = if neighbor_light == 15 && dir == BlockDirection::Up { let potential = if neighbor_light == 15 && dir == BlockDirection::Up {
// Sky light at 15 from above stays 15 // Sky light at 15 from above stays 15
@ -419,15 +409,11 @@ impl DynamicLightEngine {
// Update if needed // Update if needed
if expected_light < current_light { if expected_light < current_light {
// Light decreased // Light decreased
self.set_sky_light_level(level, &pos, expected_light) self.set_sky_light_level(level, &pos, expected_light).ok();
.await
.ok();
self.queue_sky_light_decrease(pos, current_light); self.queue_sky_light_decrease(pos, current_light);
} else if expected_light > current_light { } else if expected_light > current_light {
// Light increased // Light increased
self.set_sky_light_level(level, &pos, expected_light) self.set_sky_light_level(level, &pos, expected_light).ok();
.await
.ok();
self.queue_sky_light_increase(pos, expected_light); self.queue_sky_light_increase(pos, expected_light);
} }
@ -489,42 +475,34 @@ impl DynamicLightEngine {
.unwrap_or(0) .unwrap_or(0)
} }
pub async fn get_block_light_level( pub fn get_block_light_level(&self, level: &Arc<Level>, position: &BlockPos) -> Option<u8> {
&self,
level: &Arc<Level>,
position: &BlockPos,
) -> Option<u8> {
let (chunk_pos, relative) = position.chunk_and_chunk_relative_position(); let (chunk_pos, relative) = position.chunk_and_chunk_relative_position();
level level
.get_or_fetch_chunk(chunk_pos, |chunk| { .read_chunk_sync(&chunk_pos, |chunk| {
let section_idx = (relative.y - chunk.section.min_y) as usize / 16; let section_idx = (relative.y - chunk.section.min_y) as usize / 16;
let light_engine = chunk.light_engine.lock().ok()?; let light_engine = chunk.light_engine.lock().ok()?;
light_engine let light_level = light_engine.block_light.get(section_idx)?.get(
.block_light
.get(section_idx)?
.get(
relative.x as usize, relative.x as usize,
(relative.y - chunk.section.min_y) as usize % 16, (relative.y - chunk.section.min_y) as usize % 16,
relative.z as usize, relative.z as usize,
) );
.into()
Some(light_level)
}) })
.await .flatten()
} }
pub async fn set_block_light_level( pub fn set_block_light_level(
&self, &self,
level: &Arc<Level>, level: &Arc<Level>,
position: &BlockPos, position: &BlockPos,
light_level: u8, light_level: u8,
) -> Result<(), String> { ) -> Result<(), String> {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
level level.read_chunk_sync(&chunk_coordinate, |chunk| {
.get_or_fetch_chunk(chunk_coordinate, |chunk| { let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
let section_index =
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
// Bounds check for section index // Bounds check for section index
let mut light_engine = chunk let mut light_engine = chunk
.light_engine .light_engine
@ -545,14 +523,14 @@ impl DynamicLightEngine {
chunk.mark_dirty(true); chunk.mark_dirty(true);
} }
Ok(()) Ok(())
}) });
.await Ok(())
} }
pub async fn get_sky_light_level(&self, level: &Arc<Level>, position: &BlockPos) -> u8 { pub fn get_sky_light_level(&self, level: &Arc<Level>, position: &BlockPos) -> u8 {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
level level
.get_or_fetch_chunk(chunk_coordinate, |chunk| { .read_chunk_sync(&chunk_coordinate, |chunk| {
let section_index = let section_index =
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE; (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
@ -571,20 +549,18 @@ impl DynamicLightEngine {
relative.z as usize, relative.z as usize,
) )
}) })
.await .unwrap_or(0)
} }
pub async fn set_sky_light_level( pub fn set_sky_light_level(
&self, &self,
level: &Arc<Level>, level: &Arc<Level>,
position: &BlockPos, position: &BlockPos,
light_level: u8, light_level: u8,
) -> Result<(), String> { ) -> Result<(), String> {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
level level.read_chunk_sync(&chunk_coordinate, |chunk| {
.get_or_fetch_chunk(chunk_coordinate, |chunk| { let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
let section_index =
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
// Bounds check for section index // Bounds check for section index
let mut light_engine = chunk let mut light_engine = chunk
.light_engine .light_engine
@ -605,7 +581,7 @@ impl DynamicLightEngine {
chunk.mark_dirty(true); chunk.mark_dirty(true);
} }
Ok(()) Ok(())
}) });
.await Ok(())
} }
} }

View File

@ -42,8 +42,7 @@ impl BlockBehaviour for BannerBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -75,9 +75,7 @@ impl BlockBehaviour for BarrelBlock {
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 barrel_block_entity = BarrelBlockEntity::new(*args.position); let barrel_block_entity = BarrelBlockEntity::new(*args.position);
args.world args.world.add_block_entity(Arc::new(barrel_block_entity));
.add_block_entity(Arc::new(barrel_block_entity))
.await;
}) })
} }
} }

View File

@ -26,14 +26,12 @@ impl BlockBehaviour for BarrierBlock {
Box::pin(async move { Box::pin(async move {
let props = BarrierLikeProperties::from_state_id(args.state_id, args.block); let props = BarrierLikeProperties::from_state_id(args.state_id, args.block);
if props.waterlogged { if props.waterlogged {
args.world args.world.schedule_fluid_tick(
.schedule_fluid_tick(
&Fluid::WATER, &Fluid::WATER,
*args.position, *args.position,
Fluid::WATER.flow_speed as u8, Fluid::WATER.flow_speed as u8,
TickPriority::Normal, TickPriority::Normal,
) );
.await;
} }
props.to_state_id(args.block) props.to_state_id(args.block)
}) })

View File

@ -116,7 +116,7 @@ impl BlockBehaviour for BedBlock {
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 bed_entity = BedBlockEntity::new(*args.position); let bed_entity = BedBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(bed_entity)).await; args.world.add_block_entity(Arc::new(bed_entity));
let mut bed_head_props = BedProperties::default(args.block); let mut bed_head_props = BedProperties::default(args.block);
bed_head_props.facing = BedProperties::from_state_id(args.state_id, args.block).facing; bed_head_props.facing = BedProperties::from_state_id(args.state_id, args.block).facing;
@ -132,7 +132,7 @@ impl BlockBehaviour for BedBlock {
.await; .await;
let bed_head_entity = BedBlockEntity::new(bed_head_pos); let bed_head_entity = BedBlockEntity::new(bed_head_pos);
args.world.add_block_entity(Arc::new(bed_head_entity)).await; args.world.add_block_entity(Arc::new(bed_head_entity));
}) })
} }

View File

@ -122,8 +122,7 @@ impl BlockBehaviour for BlastFurnaceBlock {
Box::pin(async move { Box::pin(async move {
let blasting_furnace_block_entity = BlastingFurnaceBlockEntity::new(*args.position); let blasting_furnace_block_entity = BlastingFurnaceBlockEntity::new(*args.position);
args.world args.world
.add_block_entity(Arc::new(blasting_furnace_block_entity)) .add_block_entity(Arc::new(blasting_furnace_block_entity));
.await;
}) })
} }
@ -139,7 +138,7 @@ impl BlockBehaviour for BlastFurnaceBlock {
ExperienceOrbEntity::spawn(args.world, pos, xp as u32).await; ExperienceOrbEntity::spawn(args.world, pos, xp as u32).await;
} }
} }
args.world.remove_block_entity(args.position).await; args.world.remove_block_entity(args.position);
}) })
} }
} }

View File

@ -68,7 +68,7 @@ impl BlockBehaviour for BrewingStandBlock {
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 be = BrewingStandBlockEntity::new(*args.position); let be = BrewingStandBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(be)).await; args.world.add_block_entity(Arc::new(be));
}) })
} }
} }

View File

@ -182,8 +182,7 @@ impl BlockBehaviour for CakeBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -81,14 +81,12 @@ impl BlockBehaviour for CampfireBlock {
let mut props = CampfireLikeProperties::from_state_id(args.state_id, args.block); let mut props = CampfireLikeProperties::from_state_id(args.state_id, args.block);
if props.waterlogged { if props.waterlogged {
props.lit = false; props.lit = false;
args.world args.world.schedule_fluid_tick(
.schedule_fluid_tick(
&Fluid::WATER, &Fluid::WATER,
*args.position, *args.position,
Fluid::WATER.flow_speed as u8, Fluid::WATER.flow_speed as u8,
TickPriority::Normal, TickPriority::Normal,
) );
.await;
} }
if args.direction == BlockDirection::Down { if args.direction == BlockDirection::Down {

View File

@ -137,8 +137,7 @@ impl BlockBehaviour for CandleCakeBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -149,8 +149,7 @@ impl BlockBehaviour for CandleBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -23,8 +23,7 @@ impl BlockBehaviour for CarpetBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })
@ -56,8 +55,7 @@ impl BlockBehaviour for MossCarpetBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })
@ -89,8 +87,7 @@ impl BlockBehaviour for PaleMossCarpetBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -96,7 +96,7 @@ async fn placed_chest_impl<E: BlockEntity + 'static>(
create_entity: impl FnOnce(BlockPos) -> E, create_entity: impl FnOnce(BlockPos) -> E,
) { ) {
let chest = create_entity(*args.position); let chest = create_entity(*args.position);
args.world.add_block_entity(Arc::new(chest)).await; args.world.add_block_entity(Arc::new(chest));
let chest_props = ChestLikeProperties::from_state_id(args.state_id, args.block); let chest_props = ChestLikeProperties::from_state_id(args.state_id, args.block);
let connected_towards = match chest_props.r#type { let connected_towards = match chest_props.r#type {

View File

@ -116,7 +116,7 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
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 block_entity = ChiseledBookshelfBlockEntity::new(*args.position); let block_entity = ChiseledBookshelfBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(block_entity)).await; args.world.add_block_entity(Arc::new(block_entity));
}) })
} }

View File

@ -66,7 +66,7 @@ impl CommandBlock {
command_entity.success_count.load(Ordering::Relaxed) > 0 command_entity.success_count.load(Ordering::Relaxed) > 0
} }
async fn update( fn update(
world: &World, world: &World,
block: &Block, block: &Block,
command_block: &CommandBlockEntity, command_block: &CommandBlockEntity,
@ -87,9 +87,7 @@ impl CommandBlock {
let props = CommandBlockLikeProperties::from_state_id(state_id, block); let props = CommandBlockLikeProperties::from_state_id(state_id, block);
if !props.conditional { if !props.conditional {
world world.schedule_block_tick(block, *pos, 1, TickPriority::Normal);
.schedule_block_tick(block, *pos, 1, TickPriority::Normal)
.await;
return; return;
} }
@ -109,9 +107,7 @@ impl CommandBlock {
.expect("behind should always be a command block"); .expect("behind should always be a command block");
if behind_entity.success_count.load(Ordering::Relaxed) > 0 { if behind_entity.success_count.load(Ordering::Relaxed) > 0 {
world world.schedule_block_tick(block, *pos, 1, TickPriority::Normal);
.schedule_block_tick(block, *pos, 1, TickPriority::Normal)
.await;
} }
} }
@ -226,7 +222,7 @@ impl BlockBehaviour for CommandBlock {
let Some(block_entity) = args.world.get_block_entity(args.position) 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);
BlockActionResult::SuccessServer BlockActionResult::SuccessServer
}) })
} }
@ -253,8 +249,7 @@ impl BlockBehaviour for CommandBlock {
command_entity, command_entity,
args.position, args.position,
block_receives_redstone_power(args.world, args.position).await, block_receives_redstone_power(args.world, args.position).await,
) );
.await;
} }
}) })
} }
@ -304,8 +299,7 @@ impl BlockBehaviour for CommandBlock {
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 {
args.world args.world
.schedule_block_tick(block, *args.position, 1, TickPriority::Normal) .schedule_block_tick(block, *args.position, 1, TickPriority::Normal);
.await;
} }
}) })
} }
@ -332,7 +326,7 @@ impl BlockBehaviour for CommandBlock {
send_command_feedback, send_command_feedback,
args.block.id == Block::CHAIN_COMMAND_BLOCK.id, args.block.id == Block::CHAIN_COMMAND_BLOCK.id,
); );
args.world.add_block_entity(Arc::new(entity)).await; args.world.add_block_entity(Arc::new(entity));
}) })
} }

View File

@ -132,9 +132,7 @@ impl ComposterBlock {
.set_block_state(location, props.to_state_id(block), BlockFlags::NOTIFY_ALL) .set_block_state(location, props.to_state_id(block), BlockFlags::NOTIFY_ALL)
.await; .await;
if level == 7 { if level == 7 {
world world.schedule_block_tick(block, *location, 20, TickPriority::Normal);
.schedule_block_tick(block, *location, 20, TickPriority::Normal)
.await;
} }
} }

View File

@ -47,8 +47,7 @@ impl BlockBehaviour for DirtPathBlock {
Box::pin(async move { Box::pin(async move {
if args.direction == BlockDirection::Up && !can_place_at(args.world, args.position) { if args.direction == BlockDirection::Up && !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;
} }
args.state_id args.state_id
}) })

View File

@ -48,8 +48,7 @@ impl BlockBehaviour for DragonEggBlock {
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 {
args.world args.world
.schedule_block_tick(args.block, *args.position, 5, TickPriority::Normal) .schedule_block_tick(args.block, *args.position, 5, TickPriority::Normal);
.await;
}) })
} }

View File

@ -29,8 +29,7 @@ impl BlockBehaviour for EndPortalBlock {
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 {
args.world args.world
.add_block_entity(Arc::new(EndPortalBlockEntity::new(*args.position))) .add_block_entity(Arc::new(EndPortalBlockEntity::new(*args.position)));
.await;
}) })
} }
} }

View File

@ -103,7 +103,7 @@ impl BlockBehaviour for EnderChestBlock {
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 block_entity = EnderChestBlockEntity::new(*args.position); let block_entity = EnderChestBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(block_entity)).await; args.world.add_block_entity(Arc::new(block_entity));
}) })
} }
} }

View File

@ -33,8 +33,7 @@ impl BlockBehaviour for FallingBlock {
Box::pin(async move { Box::pin(async move {
// TODO: make delay configurable // TODO: make delay configurable
args.world args.world
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal) .schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal);
.await;
}) })
} }
fn get_state_for_neighbor_update<'a>( fn get_state_for_neighbor_update<'a>(
@ -44,8 +43,7 @@ impl BlockBehaviour for FallingBlock {
Box::pin(async move { Box::pin(async move {
// TODO: make delay configurable // TODO: make delay configurable
args.world args.world
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal) .schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal);
.await;
args.state_id args.state_id
}) })
} }

View File

@ -57,8 +57,7 @@ impl BlockBehaviour for FarmlandBlock {
Box::pin(async move { Box::pin(async move {
if args.direction == BlockDirection::Up && !can_place_at(args.world, args.position) { if args.direction == BlockDirection::Up && !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;
} }
args.state_id args.state_id
}) })

View File

@ -199,14 +199,12 @@ impl BlockBehaviour for FireBlock {
return; return;
} }
args.world args.world.schedule_block_tick(
.schedule_block_tick(
args.block, args.block,
*args.position, *args.position,
Self::get_fire_tick_delay() as u8, Self::get_fire_tick_delay() as u8,
TickPriority::Normal, TickPriority::Normal,
) );
.await;
}) })
} }
@ -255,14 +253,12 @@ impl BlockBehaviour for FireBlock {
let (world, block, pos) = (args.world, args.block, args.position); let (world, block, pos) = (args.world, args.block, args.position);
// Schedule next tick first // Schedule next tick first
world world.schedule_block_tick(
.schedule_block_tick(
block, block,
*pos, *pos,
Self::get_fire_tick_delay() as u8, Self::get_fire_tick_delay() as u8,
TickPriority::Normal, TickPriority::Normal,
) );
.await;
// Check if fire can survive // Check if fire can survive
if !self.can_place_at(CanPlaceAtArgs { if !self.can_place_at(CanPlaceAtArgs {

View File

@ -117,9 +117,7 @@ impl BlockBehaviour for FurnaceBlock {
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 furnace_block_entity = FurnaceBlockEntity::new(*args.position); let furnace_block_entity = FurnaceBlockEntity::new(*args.position);
args.world args.world.add_block_entity(Arc::new(furnace_block_entity));
.add_block_entity(Arc::new(furnace_block_entity))
.await;
}) })
} }
@ -135,7 +133,7 @@ impl BlockBehaviour for FurnaceBlock {
ExperienceOrbEntity::spawn(args.world, pos, xp as u32).await; ExperienceOrbEntity::spawn(args.world, pos, xp as u32).await;
} }
} }
args.world.remove_block_entity(args.position).await; args.world.remove_block_entity(args.position);
}) })
} }
} }

View File

@ -90,9 +90,7 @@ impl BlockBehaviour for HopperBlock {
Box::pin(async move { Box::pin(async move {
let props = HopperLikeProperties::from_state_id(args.state_id, args.block); let props = HopperLikeProperties::from_state_id(args.state_id, args.block);
let hopper_block_entity = HopperBlockEntity::new(*args.position, props.facing); let hopper_block_entity = HopperBlockEntity::new(*args.position, props.facing);
args.world args.world.add_block_entity(Arc::new(hopper_block_entity));
.add_block_entity(Arc::new(hopper_block_entity))
.await;
if Block::from_state_id(args.old_state_id) != Block::from_state_id(args.state_id) { if Block::from_state_id(args.old_state_id) != Block::from_state_id(args.state_id) {
check_powered_state(args.world, args.position, args.state_id, args.block).await; check_powered_state(args.world, args.position, args.state_id, args.block).await;
} }

View File

@ -90,7 +90,7 @@ impl BlockBehaviour for JukeboxBlock {
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 block_entity = JukeboxBlockEntity::new(*args.position); let block_entity = JukeboxBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(block_entity)).await; args.world.add_block_entity(Arc::new(block_entity));
}) })
} }

View File

@ -95,8 +95,7 @@ impl BlockBehaviour for LadderBlock {
props.facing.to_block_direction().opposite(), props.facing.to_block_direction().opposite(),
) { ) {
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;
} }
}) })
} }

View File

@ -58,8 +58,7 @@ impl BlockBehaviour for LanternBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -41,7 +41,7 @@ impl BlockBehaviour for LecternBlock {
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 block_entity = LecternBlockEntity::new(*args.position); let block_entity = LecternBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(block_entity)).await; args.world.add_block_entity(Arc::new(block_entity));
}) })
} }

View File

@ -24,14 +24,12 @@ impl BlockBehaviour for MangroveRootsBlock {
Box::pin(async move { Box::pin(async move {
let props = MangroveRootsLikeProperties::from_state_id(args.state_id, args.block); let props = MangroveRootsLikeProperties::from_state_id(args.state_id, args.block);
if props.waterlogged { if props.waterlogged {
args.world args.world.schedule_fluid_tick(
.schedule_fluid_tick(
&Fluid::WATER, &Fluid::WATER,
*args.position, *args.position,
Fluid::WATER.flow_speed as u8, Fluid::WATER.flow_speed as u8,
TickPriority::Normal, TickPriority::Normal,
) );
.await;
} }
props.to_state_id(args.block) props.to_state_id(args.block)
}) })

View File

@ -219,8 +219,7 @@ impl BlockBehaviour for PistonBlock {
.unwrap() .unwrap()
.to_facing(); .to_facing();
world world.add_block_entity(Arc::new(PistonBlockEntity {
.add_block_entity(Arc::new(PistonBlockEntity {
position: *pos, position: *pos,
facing: dir, facing: dir,
pushed_block_state: BlockState::from_id(props.to_state_id(block)), pushed_block_state: BlockState::from_id(props.to_state_id(block)),
@ -228,8 +227,7 @@ impl BlockBehaviour for PistonBlock {
last_progress: 0.0.into(), last_progress: 0.0.into(),
extending: false, extending: false,
source: true, source: true,
})) }));
.await;
world.update_neighbors(pos, None).await; world.update_neighbors(pos, None).await;
if sticky { if sticky {
@ -425,8 +423,7 @@ async fn move_piston(
.await; .await;
if let Some(moved_state) = moved_block_states.get(moved_blocks.len() - 1 - index) { if let Some(moved_state) = moved_block_states.get(moved_blocks.len() - 1 - index) {
world world.add_block_entity(Arc::new(PistonBlockEntity {
.add_block_entity(Arc::new(PistonBlockEntity {
position: target_pos, position: target_pos,
facing: dir.to_facing().to_block_direction(), facing: dir.to_facing().to_block_direction(),
pushed_block_state: moved_state, pushed_block_state: moved_state,
@ -434,8 +431,7 @@ async fn move_piston(
last_progress: 0.0.into(), last_progress: 0.0.into(),
extending: extend, extending: extend,
source: false, source: false,
})) }));
.await;
} }
affected_block_states.push(block_state); affected_block_states.push(block_state);
} }
@ -460,8 +456,7 @@ async fn move_piston(
let mut props = PistonHeadLikeProperties::default(&Block::PISTON_HEAD); let mut props = PistonHeadLikeProperties::default(&Block::PISTON_HEAD);
props.facing = dir.to_facing(); props.facing = dir.to_facing();
props.r#type = pistion_type; props.r#type = pistion_type;
world world.add_block_entity(Arc::new(PistonBlockEntity {
.add_block_entity(Arc::new(PistonBlockEntity {
position: extended_pos, position: extended_pos,
facing: dir.to_facing().to_block_direction(), facing: dir.to_facing().to_block_direction(),
pushed_block_state: BlockState::from_id(props.to_state_id(&Block::PISTON_HEAD)), pushed_block_state: BlockState::from_id(props.to_state_id(&Block::PISTON_HEAD)),
@ -469,8 +464,7 @@ async fn move_piston(
last_progress: 0.0.into(), last_progress: 0.0.into(),
extending: true, extending: true,
source: true, source: true,
})) }));
.await;
} }
let air_state = Block::AIR.default_state.id; let air_state = Block::AIR.default_state.id;

View File

@ -103,8 +103,7 @@ impl BlockBehaviour for BambooBlock {
Box::pin(async move { Box::pin(async move {
if !<Self as PlantBlockBase>::can_place_at(self, args.world, args.position) { 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;
} }
let neighbor_block = args.world.get_block(args.neighbor_position); 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 {

View File

@ -178,14 +178,12 @@ async fn set_tilt_and_schedule_tick(
Tilt::Full => 100, Tilt::Full => 100,
}; };
if tick_delay != -1 { if tick_delay != -1 {
world world.schedule_block_tick(
.schedule_block_tick(
&Block::BIG_DRIPLEAF, &Block::BIG_DRIPLEAF,
*pos, *pos,
tick_delay as u8, tick_delay as u8,
pumpkin_world::tick::TickPriority::Normal, pumpkin_world::tick::TickPriority::Normal,
) );
.await;
} }
} }
fn play_tilt_sound(world: &Arc<World>, pos: &BlockPos, tilt_sound: Sound) { fn play_tilt_sound(world: &Arc<World>, pos: &BlockPos, tilt_sound: Sound) {

View File

@ -104,8 +104,7 @@ impl BlockBehaviour for CactusBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id

View File

@ -29,8 +29,7 @@ impl BlockBehaviour for ChorusFlowerBlock {
Box::pin(async move { Box::pin(async move {
if args.direction != BlockDirection::Up && !can_survive(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -39,8 +39,7 @@ impl BlockBehaviour for ChorusPlantBlock {
if !can_survive(args.world, args.position) { 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);
.await;
return args.state_id; return args.state_id;
} }

View File

@ -71,8 +71,7 @@ impl BlockBehaviour for SugarCaneBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -32,7 +32,6 @@ pub trait RedstoneGateBlockProperties {
} }
pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlockProperties> { pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlockProperties> {
// 💡 Converted async fn to fn
fn can_place_at(&self, world: &dyn BlockAccessor, pos: BlockPos) -> bool fn can_place_at(&self, world: &dyn BlockAccessor, pos: BlockPos) -> bool
where where
Self: Send + Sync, Self: Send + Sync,
@ -42,7 +41,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
self.can_place_above(world, under_pos, under_state) self.can_place_above(world, under_pos, under_state)
} }
// 💡 Converted async fn to fn
fn can_place_above( fn can_place_above(
&self, &self,
_world: &dyn BlockAccessor, _world: &dyn BlockAccessor,
@ -76,7 +74,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
Box::pin(async move { self.get_weak_redstone_power(args).await }) Box::pin(async move { self.get_weak_redstone_power(args).await })
} }
// 💡 Converted async fn to fn returning BlockFuture
fn get_output_level<'a>(&'a self, world: &'a World, pos: BlockPos) -> BlockFuture<'a, u8>; fn get_output_level<'a>(&'a self, world: &'a World, pos: BlockPos) -> BlockFuture<'a, u8>;
fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> fn on_neighbor_update<'a>(&'a self, args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()>
@ -105,7 +102,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
}) })
} }
// 💡 Converted async fn to fn returning BlockFuture
fn update_powered<'a>( fn update_powered<'a>(
&'a self, &'a self,
world: &'a World, world: &'a World,
@ -114,7 +110,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
block: &'a Block, block: &'a Block,
) -> BlockFuture<'a, ()>; ) -> BlockFuture<'a, ()>;
// 💡 Converted async fn to fn returning BlockFuture
fn has_power<'a>( fn has_power<'a>(
&'a self, &'a self,
world: &'a World, world: &'a World,
@ -128,7 +123,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
Box::pin(async move { self.get_power(world, pos, state, block).await > 0 }) Box::pin(async move { self.get_power(world, pos, state, block).await > 0 })
} }
// 💡 Converted async fn to fn returning BlockFuture
fn get_power<'a>( fn get_power<'a>(
&'a self, &'a self,
world: &'a World, world: &'a World,
@ -142,7 +136,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
Box::pin(async move { get_power::<T>(world, pos, state.id, block).await }) Box::pin(async move { get_power::<T>(world, pos, state.id, block).await })
} }
// 💡 Converted async fn to fn returning BlockFuture
fn get_max_input_level_sides<'a>( fn get_max_input_level_sides<'a>(
&'a self, &'a self,
world: &'a World, world: &'a World,
@ -164,7 +157,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
}) })
} }
// 💡 Converted async fn to fn returning BlockFuture
fn update_target<'a>( fn update_target<'a>(
&'a self, &'a self,
world: &'a Arc<World>, world: &'a Arc<World>,
@ -183,7 +175,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
}) })
} }
// 💡 Converted async fn to fn returning BlockFuture
fn on_place<'a>( fn on_place<'a>(
&'a self, &'a self,
player: &'a Player, player: &'a Player,
@ -217,8 +208,7 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
.await .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;
} }
}) })
} }
@ -242,15 +232,13 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
}) })
} }
// 💡 Converted async fn to fn returning BlockFuture
fn is_target_not_aligned<'a>( fn is_target_not_aligned<'a>(
&'a self, &'a self,
world: &'a dyn BlockAccessor, world: &'a dyn BlockAccessor,
pos: BlockPos, pos: BlockPos,
state: &'a BlockState, state: &'a BlockState,
block: &'a Block, block: &'a Block,
) -> BlockFuture<'a, bool> { ) -> bool {
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) = let (target_block, target_state) =
@ -264,7 +252,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
} else { } else {
false false
} }
})
} }
fn get_update_delay_internal(&self, state_id: BlockStateId, block: &Block) -> u8; fn get_update_delay_internal(&self, state_id: BlockStateId, block: &Block) -> u8;

View File

@ -114,15 +114,14 @@ impl BlockBehaviour for BellBlock {
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 world: &World = args.world; let world: &World = args.world;
world.remove_block_entity(args.position).await; world.remove_block_entity(args.position);
}) })
} }
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 {
args.world args.world
.add_block_entity(Arc::new(BellBlockEntity::new(*args.position))) .add_block_entity(Arc::new(BellBlockEntity::new(*args.position)));
.await;
}) })
} }
fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> { fn normal_use<'a>(&'a self, args: NormalUseArgs<'a>) -> BlockFuture<'a, BlockActionResult> {

View File

@ -45,9 +45,7 @@ async fn click_button(world: &Arc<World>, block_pos: &BlockPos) {
} else { } else {
30 30
}; };
world world.schedule_block_tick(block, *block_pos, delay, TickPriority::Normal);
.schedule_block_tick(block, *block_pos, delay, TickPriority::Normal)
.await;
ButtonBlock::update_neighbors(world, block_pos, &button_props).await; ButtonBlock::update_neighbors(world, block_pos, &button_props).await;
} }
} }

View File

@ -57,7 +57,7 @@ impl BlockBehaviour for ComparatorBlock {
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 comparator = ComparatorBlockEntity::new(*args.position); let comparator = ComparatorBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(comparator)).await; args.world.add_block_entity(Arc::new(comparator));
RedstoneGateBlock::update_target( RedstoneGateBlock::update_target(
self, self,
@ -78,7 +78,7 @@ impl BlockBehaviour for ComparatorBlock {
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 {
args.world.remove_block_entity(args.position).await; args.world.remove_block_entity(args.position);
}) })
} }
@ -174,7 +174,7 @@ impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock {
block: &'a Block, block: &'a Block,
) -> BlockFuture<'a, ()> { ) -> BlockFuture<'a, ()> {
Box::pin(async move { Box::pin(async move {
if world.is_block_tick_scheduled(&pos, block).await { if world.is_block_tick_scheduled(&pos, block) {
return; return;
} }
let i = self.calculate_output_signal(world, pos, state, block).await; let i = self.calculate_output_signal(world, pos, state, block).await;
@ -187,20 +187,16 @@ impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock {
|| props.powered || props.powered
!= RedstoneGateBlock::has_power(self, world, pos, state, block).await != RedstoneGateBlock::has_power(self, world, pos, state, block).await
{ {
world world.schedule_block_tick(
.schedule_block_tick(
block, block,
pos, pos,
RedstoneGateBlock::get_update_delay_internal(self, state.id, block), RedstoneGateBlock::get_update_delay_internal(self, state.id, block),
if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block) if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block) {
.await
{
TickPriority::High TickPriority::High
} else { } else {
TickPriority::Normal TickPriority::Normal
}, },
) );
.await;
} }
}) })
} }

View File

@ -21,14 +21,13 @@ impl BlockBehaviour for DaylightDetectorBlock {
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 {
args.world args.world
.add_block_entity(Arc::new(DaylightDetectorBlockEntity::new(*args.position))) .add_block_entity(Arc::new(DaylightDetectorBlockEntity::new(*args.position)));
.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 {
args.world.remove_block_entity(args.position).await; args.world.remove_block_entity(args.position);
}) })
} }

View File

@ -111,9 +111,7 @@ impl BlockBehaviour for DropperBlock {
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 dropper_block_entity = DropperBlockEntity::new(*args.position); let dropper_block_entity = DropperBlockEntity::new(*args.position);
args.world args.world.add_block_entity(Arc::new(dropper_block_entity));
.add_block_entity(Arc::new(dropper_block_entity))
.await;
}) })
} }
@ -127,8 +125,7 @@ impl BlockBehaviour for DropperBlock {
); );
if powered && !props.triggered { if powered && !props.triggered {
args.world args.world
.schedule_block_tick(args.block, *args.position, 4, TickPriority::Normal) .schedule_block_tick(args.block, *args.position, 4, TickPriority::Normal);
.await;
props.triggered = true; props.triggered = true;
args.world args.world
.set_block_state( .set_block_state(

View File

@ -50,8 +50,7 @@ impl BlockBehaviour for ObserverBlock {
) )
.await; .await;
args.world args.world
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal) .schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal);
.await;
} }
Self::update_neighbors(args.world, args.block, args.position, &props).await; Self::update_neighbors(args.world, args.block, args.position, &props).await;
@ -66,7 +65,7 @@ impl BlockBehaviour for ObserverBlock {
let props = ObserverLikeProperties::from_state_id(args.state_id, args.block); let props = ObserverLikeProperties::from_state_id(args.state_id, args.block);
if props.facing.to_block_direction() == args.direction && !props.powered { if props.facing.to_block_direction() == args.direction && !props.powered {
Self::schedule_tick(args.world, args.position).await; Self::schedule_tick(args.world, args.position);
} }
args.state_id args.state_id
@ -112,7 +111,6 @@ impl BlockBehaviour for ObserverBlock {
&& args && args
.world .world
.is_block_tick_scheduled(args.position, &Block::OBSERVER) .is_block_tick_scheduled(args.position, &Block::OBSERVER)
.await
{ {
Self::update_neighbors(args.world, args.block, args.position, &props).await; Self::update_neighbors(args.world, args.block, args.position, &props).await;
} }
@ -137,9 +135,7 @@ impl ObserverBlock {
.await; .await;
} }
async fn schedule_tick(world: &World, block_pos: &BlockPos) { fn schedule_tick(world: &World, block_pos: &BlockPos) {
world world.schedule_block_tick(&Block::OBSERVER, *block_pos, 2, TickPriority::Normal);
.schedule_block_tick(&Block::OBSERVER, *block_pos, 2, TickPriority::Normal)
.await;
} }
} }

View File

@ -74,9 +74,7 @@ pub(crate) trait PressurePlate {
world.update_neighbors(&pos.down(), None).await; world.update_neighbors(&pos.down(), None).await;
} }
if has_output { if has_output {
world world.schedule_block_tick(block, *pos, self.tick_rate(), TickPriority::Normal);
.schedule_block_tick(block, *pos, self.tick_rate(), TickPriority::Normal)
.await;
} }
} }

View File

@ -30,9 +30,12 @@ impl BlockBehaviour for RedstoneLamp {
if is_lit != is_receiving_power { if is_lit != is_receiving_power {
if is_lit { if is_lit {
args.world args.world.schedule_block_tick(
.schedule_block_tick(args.block, *args.position, 4, TickPriority::Normal) args.block,
.await; *args.position,
4,
TickPriority::Normal,
);
} else { } else {
props.lit = !props.lit; props.lit = !props.lit;
args.world args.world

View File

@ -143,7 +143,6 @@ impl BlockBehaviour for RedstoneTorchBlock {
if args if args
.world .world
.is_block_tick_scheduled(args.position, args.block) .is_block_tick_scheduled(args.position, args.block)
.await
{ {
return; return;
} }
@ -158,17 +157,23 @@ impl BlockBehaviour for RedstoneTorchBlock {
) )
.await .await
{ {
args.world args.world.schedule_block_tick(
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal) args.block,
.await; *args.position,
2,
TickPriority::Normal,
);
} }
} else if args.block == &Block::REDSTONE_TORCH { } else if args.block == &Block::REDSTONE_TORCH {
let props = RTorchProps::from_state_id(state.id, args.block); let props = RTorchProps::from_state_id(state.id, args.block);
if props.lit != should_be_lit(args.world, args.position, BlockDirection::Down).await if props.lit != should_be_lit(args.world, args.position, BlockDirection::Down).await
{ {
args.world args.world.schedule_block_tick(
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal) args.block,
.await; *args.position,
2,
TickPriority::Normal,
);
} }
} }
}) })

View File

@ -89,8 +89,7 @@ impl BlockBehaviour for RepeaterBlock {
) )
.await; .await;
if !should_be_powered { if !should_be_powered {
args.world args.world.schedule_block_tick(
.schedule_block_tick(
args.block, args.block,
*args.position, *args.position,
RedstoneGateBlock::get_update_delay_internal( RedstoneGateBlock::get_update_delay_internal(
@ -99,8 +98,7 @@ impl BlockBehaviour for RepeaterBlock {
args.block, args.block,
), ),
TickPriority::VeryHigh, TickPriority::VeryHigh,
) );
.await;
} }
RedstoneGateBlock::update_target( RedstoneGateBlock::update_target(
self, self,
@ -240,16 +238,12 @@ impl RedstoneGateBlock<RepeaterProperties> for RepeaterBlock {
let props = RepeaterProperties::from_state_id(state.id, block); let props = RepeaterProperties::from_state_id(state.id, block);
let powered = props.powered; let powered = props.powered;
// 💡 FIX 3: Trait method calls now return futures and must be awaited.
// Note: The signature for has_power must be called without self, as it's a trait method. // Note: The signature for has_power must be called without self, as it's a trait method.
let has_power = RedstoneGateBlock::has_power(self, world, pos, state, block).await; let has_power = RedstoneGateBlock::has_power(self, world, pos, state, block).await;
if powered != has_power && !world.is_block_tick_scheduled(&pos, block).await { if powered != has_power && !world.is_block_tick_scheduled(&pos, block) {
// 💡 FIX 4: is_target_not_aligned returns a Future and must be awaited.
let priority = let priority =
if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block) if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block) {
.await
{
TickPriority::ExtremelyHigh TickPriority::ExtremelyHigh
} else if powered { } else if powered {
TickPriority::VeryHigh TickPriority::VeryHigh
@ -257,15 +251,12 @@ impl RedstoneGateBlock<RepeaterProperties> for RepeaterBlock {
TickPriority::High TickPriority::High
}; };
world world.schedule_block_tick(
.schedule_block_tick(
block, block,
pos, pos,
// 💡 FIX 5: get_update_delay_internal is not async and is called normally.
RedstoneGateBlock::get_update_delay_internal(self, state.id, block), RedstoneGateBlock::get_update_delay_internal(self, state.id, block),
priority, priority,
) );
.await;
} }
}) })
} }

View File

@ -43,8 +43,7 @@ impl BlockBehaviour for TripwireBlock {
Self::update(args.world, args.position, state_id).await; Self::update(args.world, args.position, state_id).await;
args.world args.world
.schedule_block_tick(args.block, *args.position, 10, TickPriority::Normal) .schedule_block_tick(args.block, *args.position, 10, TickPriority::Normal);
.await;
}) })
} }
@ -151,9 +150,12 @@ impl BlockBehaviour for TripwireBlock {
.await; .await;
Self::update(args.world, args.position, state_id).await; Self::update(args.world, args.position, state_id).await;
} else { } else {
args.world args.world.schedule_block_tick(
.schedule_block_tick(args.block, *args.position, 10, TickPriority::Normal) args.block,
.await; *args.position,
10,
TickPriority::Normal,
);
} }
}) })
} }

View File

@ -217,14 +217,12 @@ impl TripwireHookBlock {
wire_attached |= (!current_wire_props.disarmed) && current_wire_props.powered; wire_attached |= (!current_wire_props.disarmed) && current_wire_props.powered;
wires_props[k as usize] = Some(current_wire_props); wires_props[k as usize] = Some(current_wire_props);
if k == raw_wire_index { if k == raw_wire_index {
world world.schedule_block_tick(
.schedule_block_tick(
&Block::TRIPWIRE_HOOK, &Block::TRIPWIRE_HOOK,
start_hook_pos, start_hook_pos,
10, 10,
TickPriority::Normal, TickPriority::Normal,
) );
.await;
can_attach &= !current_wire_props.disarmed; can_attach &= !current_wire_props.disarmed;
} }
} else { } else {

View File

@ -79,9 +79,7 @@ impl BlockBehaviour for ShulkerBoxBlock {
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 barrel_block_entity = ShulkerBoxBlockEntity::new(*args.position); let barrel_block_entity = ShulkerBoxBlockEntity::new(*args.position);
args.world args.world.add_block_entity(Arc::new(barrel_block_entity));
.add_block_entity(Arc::new(barrel_block_entity))
.await;
}) })
} }

View File

@ -307,8 +307,7 @@ impl BlockBehaviour for SignBlock {
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 {
args.world args.world
.add_block_entity(Arc::new(SignBlockEntity::empty(*args.position))) .add_block_entity(Arc::new(SignBlockEntity::empty(*args.position)));
.await;
}) })
} }
@ -368,7 +367,7 @@ impl BlockBehaviour for SignBlock {
fn on_state_replaced<'a>(&'a self, args: OnStateReplacedArgs<'a>) -> BlockFuture<'a, ()> { fn on_state_replaced<'a>(&'a self, args: OnStateReplacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move { Box::pin(async move {
args.world.remove_block_entity(args.position).await; args.world.remove_block_entity(args.position);
}) })
} }
@ -467,6 +466,7 @@ impl BlockBehaviour for SignBlock {
} }
/// Handles use with an item on the sign block. /// Handles use with an item on the sign block.
#[expect(clippy::option_if_let_else)]
fn use_with_item<'a>( fn use_with_item<'a>(
&'a self, &'a self,
args: UseWithItemArgs<'a>, args: UseWithItemArgs<'a>,
@ -507,27 +507,39 @@ impl BlockBehaviour for SignBlock {
return BlockActionResult::PassToDefaultBlockAction; return BlockActionResult::PassToDefaultBlockAction;
}; };
let result = if let Some(honeycomb_item) = let result = pumpkin_item
pumpkin_item.as_any().downcast_ref::<HoneyCombItem>() .as_any()
.downcast_ref::<HoneyCombItem>()
.map_or_else(
|| {
pumpkin_item
.as_any()
.downcast_ref::<GlowingInkSacItem>()
.map_or_else(
|| {
if let Some(ink_sac_item) =
pumpkin_item.as_any().downcast_ref::<InkSacItem>()
{ {
honeycomb_item ink_sac_item.apply_to_sign(&args, &block_entity, text)
.apply_to_sign(&args, &block_entity, sign_entity) } else if let Some(dye) =
.await pumpkin_item.as_any().downcast_ref::<DyeItem>()
} else if let Some(g_ink_sac_item) =
pumpkin_item.as_any().downcast_ref::<GlowingInkSacItem>()
{ {
g_ink_sac_item let color_name =
.apply_to_sign(&args, &block_entity, text) item.item.registry_key.strip_suffix("_dye").unwrap();
.await
} else if let Some(ink_sac_item) = pumpkin_item.as_any().downcast_ref::<InkSacItem>() {
ink_sac_item.apply_to_sign(&args, &block_entity, text).await
} else if let Some(dye) = pumpkin_item.as_any().downcast_ref::<DyeItem>() {
let color_name = item.item.registry_key.strip_suffix("_dye").unwrap();
dye.apply_to_sign(&args, &block_entity, text, color_name) dye.apply_to_sign(&args, &block_entity, text, color_name)
.await
} else { } else {
BlockActionResult::PassToDefaultBlockAction BlockActionResult::PassToDefaultBlockAction
}; }
},
|g_ink_sac_item| {
g_ink_sac_item.apply_to_sign(&args, &block_entity, text)
},
)
},
|honeycomb_item| {
honeycomb_item.apply_to_sign(&args, &block_entity, sign_entity)
},
);
if result == BlockActionResult::Success { if result == BlockActionResult::Success {
if !args.player.has_infinite_materials() { if !args.player.has_infinite_materials() {

View File

@ -116,9 +116,7 @@ impl BlockBehaviour for SmokerBlock {
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 smoker_block_entity = SmokerBlockEntity::new(*args.position); let smoker_block_entity = SmokerBlockEntity::new(*args.position);
args.world args.world.add_block_entity(Arc::new(smoker_block_entity));
.add_block_entity(Arc::new(smoker_block_entity))
.await;
}) })
} }
@ -134,7 +132,7 @@ impl BlockBehaviour for SmokerBlock {
ExperienceOrbEntity::spawn(args.world, pos, xp as u32).await; ExperienceOrbEntity::spawn(args.world, pos, xp as u32).await;
} }
} }
args.world.remove_block_entity(args.position).await; args.world.remove_block_entity(args.position);
}) })
} }
} }

View File

@ -93,8 +93,7 @@ impl BlockBehaviour for LayeredSnowBlock {
Box::pin(async move { Box::pin(async move {
if !can_place_at(args.world, args.position) { 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;
} }
args.state_id args.state_id
}) })

View File

@ -12,9 +12,7 @@ impl BlockBehaviour for SpawnerBlock {
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 hopper_block_entity = MobSpawnerBlockEntity::new(*args.position, None); let hopper_block_entity = MobSpawnerBlockEntity::new(*args.position, None);
args.world args.world.add_block_entity(Arc::new(hopper_block_entity));
.add_block_entity(Arc::new(hopper_block_entity))
.await;
}) })
} }
} }

View File

@ -97,10 +97,7 @@ impl DaylightDetectorBlockEntity {
0 // full daylight 0 // full daylight
}; };
let sky_light_level = level let sky_light_level = level.light_engine.get_sky_light_level(&level, block_pos);
.light_engine
.get_sky_light_level(&level, block_pos)
.await;
let mut power = sky_light_level - ambient_darkness; let mut power = sky_light_level - ambient_darkness;

View File

@ -25,7 +25,7 @@ impl PistonBlockEntity {
pub async fn finish(&self, world: Arc<World>) { pub async fn finish(&self, world: Arc<World>) {
if self.last_progress.load() < 1.0 { if self.last_progress.load() < 1.0 {
let pos = self.position; let pos = self.position;
world.remove_block_entity(&pos).await; world.remove_block_entity(&pos);
if world.get_block(&pos) == &Block::MOVING_PISTON { if world.get_block(&pos) == &Block::MOVING_PISTON {
let state = if self.source { let state = if self.source {
Block::AIR.default_state.id Block::AIR.default_state.id
@ -67,7 +67,7 @@ impl BlockEntity for PistonBlockEntity {
self.last_progress.store(current_progress); self.last_progress.store(current_progress);
if current_progress >= 1.0 { if current_progress >= 1.0 {
let pos = self.position; let pos = self.position;
world.remove_block_entity(&pos).await; world.remove_block_entity(&pos);
if world.get_block(&pos) == &Block::MOVING_PISTON { if world.get_block(&pos) == &Block::MOVING_PISTON {
if self.pushed_block_state.is_air() { if self.pushed_block_state.is_air() {
world world

View File

@ -109,14 +109,12 @@ pub trait FlowingFluid: Send + Sync {
// Schedule next tick for this position // Schedule next tick for this position
let tick_delay = self.get_flow_speed(world); let tick_delay = self.get_flow_speed(world);
world world.schedule_fluid_tick(
.schedule_fluid_tick(
fluid, fluid,
*block_pos, *block_pos,
tick_delay, tick_delay,
TickPriority::Normal, TickPriority::Normal,
) );
.await;
} }
// Use the new state for spreading // Use the new state for spreading
@ -400,9 +398,7 @@ pub trait FlowingFluid: Send + Sync {
if !is_source { if !is_source {
let tick_delay = self.get_flow_speed(world); let tick_delay = self.get_flow_speed(world);
world world.schedule_fluid_tick(fluid, *pos, tick_delay, TickPriority::Normal);
.schedule_fluid_tick(fluid, *pos, tick_delay, TickPriority::Normal)
.await;
} }
} }
} }

View File

@ -158,9 +158,7 @@ impl FluidBehaviour for FlowingLava {
&& Self::receive_neighbor_fluids(world, fluid, block_pos).await && Self::receive_neighbor_fluids(world, fluid, block_pos).await
{ {
let flow_speed = self.get_flow_speed(world); let flow_speed = self.get_flow_speed(world);
world world.schedule_fluid_tick(fluid, *block_pos, flow_speed, TickPriority::Normal);
.schedule_fluid_tick(fluid, *block_pos, flow_speed, TickPriority::Normal)
.await;
} }
}) })
} }
@ -187,9 +185,7 @@ impl FluidBehaviour for FlowingLava {
Box::pin(async move { Box::pin(async move {
if Self::receive_neighbor_fluids(world, fluid, block_pos).await { if Self::receive_neighbor_fluids(world, fluid, block_pos).await {
let flow_speed = self.get_flow_speed(world); let flow_speed = self.get_flow_speed(world);
world world.schedule_fluid_tick(fluid, *block_pos, flow_speed, TickPriority::Normal);
.schedule_fluid_tick(fluid, *block_pos, flow_speed, TickPriority::Normal)
.await;
} }
}) })
} }

View File

@ -31,9 +31,12 @@ impl FluidBehaviour for FlowingWater {
) -> BlockFuture<'a, ()> { ) -> BlockFuture<'a, ()> {
Box::pin(async move { Box::pin(async move {
if old_state_id != state_id { if old_state_id != state_id {
world world.schedule_fluid_tick(
.schedule_fluid_tick(fluid, *block_pos, WATER_FLOW_SPEED, TickPriority::Normal) fluid,
.await; *block_pos,
WATER_FLOW_SPEED,
TickPriority::Normal,
);
} }
}) })
} }
@ -59,10 +62,13 @@ impl FluidBehaviour for FlowingWater {
) -> BlockFuture<'a, ()> { ) -> BlockFuture<'a, ()> {
Box::pin(async move { Box::pin(async move {
// Avoid rescheduling a fluid tick if one is already queued. // Avoid rescheduling a fluid tick if one is already queued.
if !world.is_fluid_tick_scheduled(block_pos, fluid).await { if !world.is_fluid_tick_scheduled(block_pos, fluid) {
world world.schedule_fluid_tick(
.schedule_fluid_tick(fluid, *block_pos, WATER_FLOW_SPEED, TickPriority::Normal) fluid,
.await; *block_pos,
WATER_FLOW_SPEED,
TickPriority::Normal,
);
} }
}) })
} }

View File

@ -157,7 +157,11 @@ impl BlockPosArgumentConsumer {
) -> Result<BlockPos, CommandError> { ) -> Result<BlockPos, CommandError> {
let pos = Self::find_arg(args, name)?; let pos = Self::find_arg(args, name)?;
if world.level.try_get_chunk(&pos.chunk_position()).is_none() { if world
.level
.read_chunk_sync(&pos.chunk_position(), |_| ())
.is_none()
{
return Err(CommandError::CommandFailed(TextComponent::translate_cross( return Err(CommandError::CommandFailed(TextComponent::translate_cross(
"argument.pos.unloaded", "argument.pos.unloaded",
"argument.pos.unloaded", "argument.pos.unloaded",

View File

@ -109,7 +109,11 @@ impl BlockPosArgumentType {
world: &World, world: &World,
) -> Result<BlockPos, CommandSyntaxError> { ) -> Result<BlockPos, CommandSyntaxError> {
let pos = Self::get_block_pos(context, name)?; let pos = Self::get_block_pos(context, name)?;
if world.level.try_get_chunk(&pos.chunk_position()).is_none() { if world
.level
.read_chunk_sync(&pos.chunk_position(), |_| ())
.is_none()
{
Err(NOT_LOADED_ERROR_TYPE.create_without_context()) Err(NOT_LOADED_ERROR_TYPE.create_without_context())
} else if !world.is_in_build_limit(pos) { } else if !world.is_in_build_limit(pos) {
Err(OUT_OF_WORLD_ERROR_TYPE.create_without_context()) Err(OUT_OF_WORLD_ERROR_TYPE.create_without_context())

View File

@ -186,12 +186,13 @@ impl CommandSender {
Self::CommandBlock(command_block, world) => { Self::CommandBlock(command_block, world) => {
let pos = command_block.get_position(); let pos = command_block.get_position();
let (chunk_coordinate, relative) = pos.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = pos.chunk_and_chunk_relative_position();
let chunk = world.level.try_get_chunk(&chunk_coordinate)?; let state_id = world.level.read_chunk_sync(&chunk_coordinate, |chunk| {
let state_id = chunk.section.get_block_absolute_y( chunk.section.get_block_absolute_y(
relative.x as usize, relative.x as usize,
relative.y, relative.y,
relative.z as usize, relative.z as usize,
)?; )
})??;
let block = Block::from_state_id(state_id); let block = Block::from_state_id(state_id);
if !CommandBlockLikeProperties::handles_block_id(block.id) { if !CommandBlockLikeProperties::handles_block_id(block.id) {
return None; return None;

View File

@ -359,7 +359,10 @@ impl EntityBase for ArmorStandEntity {
return false; return false;
} }
if entity.is_invulnerable_to(&damage_type) || self.is_invisible() || self.is_marker() { if entity.is_invulnerable_to(&damage_type).await
|| self.is_invisible()
|| self.is_marker()
{
return false; return false;
} }

View File

@ -1850,7 +1850,7 @@ impl EntityBase for LivingEntity {
let mut amount = amount; let mut amount = amount;
// Check invulnerability before applying damage // Check invulnerability before applying damage
if self.entity.is_invulnerable_to(&damage_type) { if self.entity.is_invulnerable_to(&damage_type).await {
return false; return false;
} }

View File

@ -51,7 +51,7 @@ impl BatEntity {
if rand::random_bool(1.0) { if rand::random_bool(1.0) {
return false; return false;
} }
if world.get_max_local_raw_brightness_sync(pos) > rand::random_range(0..4) { if world.get_max_local_raw_brightness(pos) > rand::random_range(0..4) {
return false; return false;
} }
if world if world

View File

@ -184,7 +184,7 @@ impl MobEntity {
} }
pub fn is_dark_enough_to_spawn(world: &World, pos: &BlockPos, is_thundering: bool) -> bool { pub fn is_dark_enough_to_spawn(world: &World, pos: &BlockPos, is_thundering: bool) -> bool {
let sky_light = world.get_sky_light_level_sync(pos); let sky_light = world.get_sky_light_level(pos);
if sky_light > rand::random_range(0..32) { if sky_light > rand::random_range(0..32) {
return false; return false;
} }
@ -192,7 +192,7 @@ impl MobEntity {
let dimension = &world.dimension; let dimension = &world.dimension;
let block_light_limit = dimension.monster_spawn_block_light_limit; let block_light_limit = dimension.monster_spawn_block_light_limit;
let block_light = world.get_block_light_level_sync(pos).unwrap(); let block_light = world.get_block_light_level(pos).unwrap();
if block_light_limit < 15 && block_light > block_light_limit { if block_light_limit < 15 && block_light > block_light_limit {
return false; return false;
} }
@ -307,7 +307,7 @@ impl MobEntity {
.level .level
.light_engine .light_engine
.get_sky_light_level(&world.level, &eye_block_pos.to_block_pos()) .get_sky_light_level(&world.level, &eye_block_pos.to_block_pos())
.await as f32 as f32
/ 15.0; / 15.0;
if brightness <= 0.5 { if brightness <= 0.5 {

View File

@ -2293,7 +2293,7 @@ impl Entity {
} }
/// Checks if the entity is invulnerable to the given damage type, considering both general invulnerability and specific immunities. /// Checks if the entity is invulnerable to the given damage type, considering both general invulnerability and specific immunities.
pub fn is_invulnerable_to(&self, damage_type: &DamageType) -> bool { pub async fn is_invulnerable_to(&self, damage_type: &DamageType) -> bool {
// Nothing is immune to void or kill // Nothing is immune to void or kill
if matches!( if matches!(
*damage_type, *damage_type,
@ -2308,9 +2308,7 @@ impl Entity {
} }
// Specific type immunities // Specific type immunities
futures::executor::block_on(async {
self.damage_immunities.lock().await.contains(damage_type) self.damage_immunities.lock().await.contains(damage_type)
})
} }
/// Sets if the entity is invulnerable to a specific damage type /// Sets if the entity is invulnerable to a specific damage type

View File

@ -142,9 +142,7 @@ async fn try_pickup_bucket_item(
world world
.set_block_state(&block_pos, state_id, BlockFlags::NOTIFY_NEIGHBORS) .set_block_state(&block_pos, state_id, BlockFlags::NOTIFY_NEIGHBORS)
.await; .await;
world world.schedule_fluid_tick(&Fluid::WATER, block_pos, 5, TickPriority::Normal);
.schedule_fluid_tick(&Fluid::WATER, block_pos, 5, TickPriority::Normal)
.await;
return Some(&Item::WATER_BUCKET); return Some(&Item::WATER_BUCKET);
} }
@ -173,9 +171,7 @@ async fn try_pickup_bucket_item(
world world
.set_block_state(&target_pos, state_id, BlockFlags::NOTIFY_NEIGHBORS) .set_block_state(&target_pos, state_id, BlockFlags::NOTIFY_NEIGHBORS)
.await; .await;
world world.schedule_fluid_tick(&Fluid::WATER, target_pos, 5, TickPriority::Normal);
.schedule_fluid_tick(&Fluid::WATER, target_pos, 5, TickPriority::Normal)
.await;
return Some(&Item::WATER_BUCKET); return Some(&Item::WATER_BUCKET);
} }
@ -239,9 +235,7 @@ async fn try_place_filled_bucket(
world world
.set_block_state(&pos, state_id, BlockFlags::NOTIFY_NEIGHBORS) .set_block_state(&pos, state_id, BlockFlags::NOTIFY_NEIGHBORS)
.await; .await;
world world.schedule_fluid_tick(&Fluid::WATER, pos, 5, TickPriority::Normal);
.schedule_fluid_tick(&Fluid::WATER, pos, 5, TickPriority::Normal)
.await;
return true; return true;
} }
@ -256,9 +250,7 @@ async fn try_place_filled_bucket(
world world
.set_block_state(&target_pos, state_id, BlockFlags::NOTIFY_NEIGHBORS) .set_block_state(&target_pos, state_id, BlockFlags::NOTIFY_NEIGHBORS)
.await; .await;
world world.schedule_fluid_tick(&Fluid::WATER, target_pos, 5, TickPriority::Normal);
.schedule_fluid_tick(&Fluid::WATER, target_pos, 5, TickPriority::Normal)
.await;
return true; return true;
} }

View File

@ -32,7 +32,7 @@ impl ItemBehaviour for DyeItem {
} }
impl DyeItem { impl DyeItem {
pub async fn apply_to_sign( pub fn apply_to_sign(
&self, &self,
args: &UseWithItemArgs<'_>, args: &UseWithItemArgs<'_>,
block_entity: &Arc<dyn BlockEntity>, block_entity: &Arc<dyn BlockEntity>,
@ -43,7 +43,7 @@ impl DyeItem {
text.set_color(dye_color); text.set_color(dye_color);
args.world.update_block_entity(block_entity).await; args.world.update_block_entity(block_entity);
args.world.play_block_sound( args.world.play_block_sound(
pumpkin_data::sound::Sound::ItemDyeUse, pumpkin_data::sound::Sound::ItemDyeUse,
pumpkin_data::sound::SoundCategory::Blocks, pumpkin_data::sound::SoundCategory::Blocks,

View File

@ -23,7 +23,7 @@ impl ItemBehaviour for GlowingInkSacItem {
} }
impl GlowingInkSacItem { impl GlowingInkSacItem {
pub async fn apply_to_sign( pub fn apply_to_sign(
&self, &self,
args: &UseWithItemArgs<'_>, args: &UseWithItemArgs<'_>,
block_entity: &Arc<dyn BlockEntity>, block_entity: &Arc<dyn BlockEntity>,
@ -35,7 +35,7 @@ impl GlowingInkSacItem {
return BlockActionResult::PassToDefaultBlockAction; return BlockActionResult::PassToDefaultBlockAction;
} }
args.world.update_block_entity(block_entity).await; args.world.update_block_entity(block_entity);
args.world.play_block_sound( args.world.play_block_sound(
pumpkin_data::sound::Sound::ItemGlowInkSacUse, pumpkin_data::sound::Sound::ItemGlowInkSacUse,
pumpkin_data::sound::SoundCategory::Blocks, pumpkin_data::sound::SoundCategory::Blocks,

View File

@ -86,7 +86,7 @@ impl ItemBehaviour for HoneyCombItem {
} }
impl HoneyCombItem { impl HoneyCombItem {
pub async fn apply_to_sign( pub fn apply_to_sign(
&self, &self,
args: &UseWithItemArgs<'_>, args: &UseWithItemArgs<'_>,
block_entity: &Arc<dyn BlockEntity>, block_entity: &Arc<dyn BlockEntity>,
@ -94,7 +94,7 @@ impl HoneyCombItem {
) -> BlockActionResult { ) -> BlockActionResult {
sign_entity.is_waxed.store(true, Ordering::Relaxed); sign_entity.is_waxed.store(true, Ordering::Relaxed);
args.world.update_block_entity(block_entity).await; args.world.update_block_entity(block_entity);
args.world args.world
.sync_world_event(WorldEvent::ParticlesAndSoundWaxOn, *args.position, 0); .sync_world_event(WorldEvent::ParticlesAndSoundWaxOn, *args.position, 0);

View File

@ -23,7 +23,7 @@ impl ItemBehaviour for InkSacItem {
} }
impl InkSacItem { impl InkSacItem {
pub async fn apply_to_sign( pub fn apply_to_sign(
&self, &self,
args: &UseWithItemArgs<'_>, args: &UseWithItemArgs<'_>,
block_entity: &Arc<dyn BlockEntity>, block_entity: &Arc<dyn BlockEntity>,
@ -35,7 +35,7 @@ impl InkSacItem {
return BlockActionResult::PassToDefaultBlockAction; return BlockActionResult::PassToDefaultBlockAction;
} }
args.world.update_block_entity(block_entity).await; args.world.update_block_entity(block_entity);
args.world.play_block_sound( args.world.play_block_sound(
pumpkin_data::sound::Sound::ItemInkSacUse, pumpkin_data::sound::Sound::ItemInkSacUse,
pumpkin_data::sound::SoundCategory::Blocks, pumpkin_data::sound::SoundCategory::Blocks,

View File

@ -42,7 +42,7 @@ impl ItemBehaviour for SpawnEggItem {
.downcast_ref::<MobSpawnerBlockEntity>() .downcast_ref::<MobSpawnerBlockEntity>()
{ {
spawner.set_entity_type(entity_type); spawner.set_entity_type(entity_type);
world.update_block_entity(&block_entity).await; world.update_block_entity(&block_entity);
item.decrement_unless_creative(player.gamemode.load(), 1); item.decrement_unless_creative(player.gamemode.load(), 1);
return; return;
} }

View File

@ -769,10 +769,7 @@ impl JavaClient {
track_output: (command.flags & 0x1 != 0).into(), track_output: (command.flags & 0x1 != 0).into(),
success_count: AtomicU32::new(0), success_count: AtomicU32::new(0),
}; };
player player.world().add_block_entity(Arc::new(command_block));
.world()
.add_block_entity(Arc::new(command_block))
.await;
player player
.send_system_message(&TextComponent::text(format!( .send_system_message(&TextComponent::text(format!(
@ -783,15 +780,12 @@ impl JavaClient {
// The 0x4 flag means always active // The 0x4 flag means always active
if command.flags & 0x4 != 0 && block_type != Block::CHAIN_COMMAND_BLOCK { if command.flags & 0x4 != 0 && block_type != Block::CHAIN_COMMAND_BLOCK {
player player.world().schedule_block_tick(
.world()
.schedule_block_tick(
&block_type, &block_type,
pos, pos,
1, 1,
pumpkin_world::tick::TickPriority::Normal, pumpkin_world::tick::TickPriority::Normal,
) );
.await;
} }
} }
} }
@ -2228,7 +2222,7 @@ impl JavaClient {
sign_data.line_4, sign_data.line_4,
]; ];
*sign_entity.currently_editing_player.lock().await = None; *sign_entity.currently_editing_player.lock().await = None;
world.update_block_entity(&block_entity).await; world.update_block_entity(&block_entity);
} }
pub async fn handle_use_item( pub async fn handle_use_item(

View File

@ -1075,7 +1075,7 @@ impl World {
let mut spawning_chunks = Vec::new(); let mut spawning_chunks = Vec::new();
for pos in active_chunks.iter() { for pos in active_chunks.iter() {
if let Some(chunk) = self.level.try_get_chunk(pos) { if let Some(chunk) = self.level.read_chunk_sync(pos, std::clone::Clone::clone) {
spawning_chunks.push((*pos, chunk)); spawning_chunks.push((*pos, chunk));
} }
} }
@ -1536,15 +1536,36 @@ impl World {
/// Gets the y position of the first non air block from the top down /// Gets the y position of the first non air block from the top down
pub fn get_top_block(&self, position: Vector2<i32>) -> i32 { pub fn get_top_block(&self, position: Vector2<i32>) -> i32 {
for y in (self.dimension.min_y..self.dimension.height).rev() { let chunk_pos = Vector2::new(position.x >> 4, position.y >> 4);
let pos = BlockPos::new(position.x, y, position.y); let relative_x = (position.x & 15) as usize;
let block = self.get_block_state(&pos); let relative_z = (position.y & 15) as usize;
if block.is_air() {
continue; self.level
.read_chunk_sync(&chunk_pos, |chunk| {
let height = chunk.heightmap.lock().unwrap().get(
ChunkHeightmapType::WorldSurface,
position.x,
position.y,
self.dimension.min_y,
);
if height >= self.dimension.min_y {
return height;
} }
for y in (self.dimension.min_y..self.dimension.min_y + self.dimension.height).rev()
{
if let Some(block_id) = chunk
.section
.get_block_absolute_y(relative_x, y, relative_z)
&& !is_air(block_id)
{
return y; return y;
} }
}
self.dimension.min_y self.dimension.min_y
})
.unwrap_or(self.dimension.min_y)
} }
pub fn get_heightmap_height(&self, height_map: ChunkHeightmapType, x: i32, z: i32) -> i32 { pub fn get_heightmap_height(&self, height_map: ChunkHeightmapType, x: i32, z: i32) -> i32 {
@ -3245,7 +3266,7 @@ impl World {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
let replaced_block_state_id = self let replaced_block_state_id = self
.level .level
.get_or_fetch_chunk(chunk_coordinate, |chunk| { .read_chunk_sync(&chunk_coordinate, |chunk| {
let replaced_block_state_id = chunk.set_block_absolute_y( let replaced_block_state_id = chunk.set_block_absolute_y(
relative.x as usize, relative.x as usize,
relative.y, relative.y,
@ -3258,7 +3279,7 @@ impl World {
} }
replaced_block_state_id replaced_block_state_id
}) })
.await; .unwrap_or(Block::AIR.default_state.id);
if replaced_block_state_id == block_state_id { if replaced_block_state_id == block_state_id {
return block_state_id; return block_state_id;
@ -3282,7 +3303,7 @@ impl World {
&& let Some(entity) = self.get_block_entity(position) && let Some(entity) = self.get_block_entity(position)
{ {
entity.on_block_replaced(self.clone(), *position).await; entity.on_block_replaced(self.clone(), *position).await;
self.remove_block_entity(position).await; self.remove_block_entity(position);
} }
// WorldChunk.java line 317 // WorldChunk.java line 317
@ -3377,49 +3398,25 @@ impl World {
replaced_block_state_id replaced_block_state_id
} }
pub fn is_thundering_sync(&self) -> bool { pub fn get_max_local_raw_brightness(&self, pos: &BlockPos) -> u8 {
self.weather.blocking_lock().thundering let sky_light = self.get_sky_light_level(pos);
} let block_light = self.get_block_light_level(pos).unwrap_or(0);
pub fn get_block_light_level_sync(&self, position: &BlockPos) -> Option<u8> {
self.level
.light_engine
.get_block_light_level_sync(&self.level, position)
}
pub fn get_sky_light_level_sync(&self, position: &BlockPos) -> u8 {
self.level
.light_engine
.get_sky_light_level_sync(&self.level, position)
}
pub fn get_max_local_raw_brightness_sync(&self, pos: &BlockPos) -> u8 {
let sky_light = self.get_sky_light_level_sync(pos);
let block_light = self.get_block_light_level_sync(pos).unwrap_or(0);
sky_light.max(block_light) // TODO: getSkyDarken sky_light.max(block_light) // TODO: getSkyDarken
} }
pub async fn get_max_local_raw_brightness(&self, pos: &BlockPos) -> u8 { pub fn get_block_light_level(&self, position: &BlockPos) -> Option<u8> {
let sky_light = self.get_sky_light_level(pos).await;
let block_light = self.get_block_light_level(pos).await.unwrap();
sky_light.max(block_light) // TODO: getSkyDarken
}
pub async fn get_block_light_level(&self, position: &BlockPos) -> Option<u8> {
self.level self.level
.light_engine .light_engine
.get_block_light_level(&self.level, position) .get_block_light_level(&self.level, position)
.await
} }
pub async fn get_sky_light_level(&self, position: &BlockPos) -> u8 { pub fn get_sky_light_level(&self, position: &BlockPos) -> u8 {
self.level self.level
.light_engine .light_engine
.get_sky_light_level(&self.level, position) .get_sky_light_level(&self.level, position)
.await
} }
pub async fn schedule_block_tick( pub fn schedule_block_tick(
&self, &self,
block: &Block, block: &Block,
block_pos: BlockPos, block_pos: BlockPos,
@ -3427,11 +3424,10 @@ impl World {
priority: TickPriority, priority: TickPriority,
) { ) {
self.level self.level
.schedule_block_tick(block, block_pos, delay, priority) .schedule_block_tick(block, block_pos, delay, priority);
.await;
} }
pub async fn schedule_fluid_tick( pub fn schedule_fluid_tick(
&self, &self,
fluid: &Fluid, fluid: &Fluid,
block_pos: BlockPos, block_pos: BlockPos,
@ -3439,16 +3435,15 @@ impl World {
priority: TickPriority, priority: TickPriority,
) { ) {
self.level self.level
.schedule_fluid_tick(fluid, block_pos, delay, priority) .schedule_fluid_tick(fluid, block_pos, delay, priority);
.await;
} }
pub async fn is_block_tick_scheduled(&self, block_pos: &BlockPos, block: &Block) -> bool { pub fn is_block_tick_scheduled(&self, block_pos: &BlockPos, block: &Block) -> bool {
self.level.is_block_tick_scheduled(block_pos, block).await self.level.is_block_tick_scheduled(block_pos, block)
} }
pub async fn is_fluid_tick_scheduled(&self, block_pos: &BlockPos, fluid: &Fluid) -> bool { pub fn is_fluid_tick_scheduled(&self, block_pos: &BlockPos, fluid: &Fluid) -> bool {
self.level.is_fluid_tick_scheduled(block_pos, fluid).await self.level.is_fluid_tick_scheduled(block_pos, fluid)
} }
// Return new state // Return new state
@ -3664,10 +3659,11 @@ impl World {
} }
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
let chunk = self.level.try_get_chunk(&chunk_coordinate)?; self.level.read_chunk_sync(&chunk_coordinate, |chunk| {
chunk chunk
.section .section
.get_block_absolute_y(relative.x as usize, relative.y, relative.z as usize) .get_block_absolute_y(relative.x as usize, relative.y, relative.z as usize)
})?
} }
#[must_use] #[must_use]
@ -3929,7 +3925,7 @@ impl World {
.map(|e| e.value().clone()) .map(|e| e.value().clone())
} }
pub async fn add_block_entity(&self, block_entity: Arc<dyn BlockEntity>) { pub fn add_block_entity(&self, block_entity: Arc<dyn BlockEntity>) {
let block_pos = block_entity.get_position(); let block_pos = block_entity.get_position();
let chunk_pos = block_pos.chunk_position(); let chunk_pos = block_pos.chunk_position();
let block_entity_nbt = block_entity.chunk_data_nbt(); let block_entity_nbt = block_entity.chunk_data_nbt();
@ -3947,25 +3943,22 @@ impl World {
); );
} }
self.block_entities.insert(block_pos, block_entity.clone()); self.block_entities.insert(block_pos, block_entity);
self.level self.level.read_chunk_sync(&chunk_pos, |chunk| {
.get_or_fetch_chunk(chunk_pos, |chunk| {
chunk.mark_dirty(true); chunk.mark_dirty(true);
}) });
.await;
} }
pub async fn remove_block_entity(&self, block_pos: &BlockPos) { pub fn remove_block_entity(&self, block_pos: &BlockPos) {
if self.block_entities.remove(block_pos).is_some() { if self.block_entities.remove(block_pos).is_some() {
self.level self.level
.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| { .read_chunk_sync(&block_pos.chunk_position(), |chunk| {
chunk.mark_dirty(true); chunk.mark_dirty(true);
}) });
.await;
} }
} }
pub async fn update_block_entity(&self, block_entity: &Arc<dyn BlockEntity>) { pub fn update_block_entity(&self, block_entity: &Arc<dyn BlockEntity>) {
let block_pos = block_entity.get_position(); let block_pos = block_entity.get_position();
let chunk_pos = block_pos.chunk_position(); let chunk_pos = block_pos.chunk_position();
let block_entity_nbt = block_entity.chunk_data_nbt(); let block_entity_nbt = block_entity.chunk_data_nbt();
@ -3982,11 +3975,9 @@ impl World {
), ),
); );
} }
self.level self.level.read_chunk_sync(&chunk_pos, |chunk| {
.get_or_fetch_chunk(chunk_pos, |chunk| {
chunk.mark_dirty(true); chunk.mark_dirty(true);
}) });
.await;
} }
fn intersects_aabb_with_direction( fn intersects_aabb_with_direction(