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
strip = false
[profile.dev]
debug = "line-tables-only"
debug-assertions = true
overflow-checks = false
split-debuginfo = "packed"
opt-level = 0
[workspace.dependencies]
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 id = self
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
.read_chunk_sync(&chunk_coordinate, |chunk| {
chunk.section.get_block_absolute_y(
relative.x as usize,
relative.y,
relative.z as usize,
)
})
.await;
.flatten();
RawBlockState(id.unwrap_or(Block::VOID_AIR.default_state.id))
}
pub async fn set_block_state(
self: &Arc<Self>,
pub fn set_block_state(
&self,
position: &BlockPos,
block_state_id: BlockStateId,
) -> BlockStateId {
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(
relative.x as usize,
relative.y,
@@ -729,7 +729,7 @@ impl Level {
}
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)>) {
@@ -831,8 +831,8 @@ impl Level {
self.loaded_entity_chunks.try_get(&coordinates).try_unwrap()
}
pub async fn schedule_block_tick(
self: &Arc<Self>,
pub fn schedule_block_tick(
&self,
block: &Block,
block_pos: BlockPos,
delay: u8,
@@ -847,15 +847,18 @@ impl Level {
};
let chunk_pos = block_pos.chunk_position();
self.get_or_fetch_chunk(chunk_pos, |chunk| {
chunk.block_ticks.schedule_tick(&scheduled_tick, tick_order);
})
.await;
self.chunks_with_scheduled_ticks.insert(chunk_pos);
if self
.read_chunk_sync(&chunk_pos, |chunk| {
chunk.block_ticks.schedule_tick(&scheduled_tick, tick_order);
})
.is_some()
{
self.chunks_with_scheduled_ticks.insert(chunk_pos);
}
}
pub async fn schedule_fluid_tick(
self: &Arc<Self>,
pub fn schedule_fluid_tick(
&self,
fluid: &Fluid,
block_pos: BlockPos,
delay: u8,
@@ -870,32 +873,27 @@ impl Level {
};
let chunk_pos = block_pos.chunk_position();
self.get_or_fetch_chunk(chunk_pos, |chunk| {
chunk.fluid_ticks.schedule_tick(&scheduled_tick, tick_order);
})
.await;
self.chunks_with_scheduled_ticks.insert(chunk_pos);
if self
.read_chunk_sync(&chunk_pos, |chunk| {
chunk.fluid_ticks.schedule_tick(&scheduled_tick, tick_order);
})
.is_some()
{
self.chunks_with_scheduled_ticks.insert(chunk_pos);
}
}
pub async fn is_block_tick_scheduled(
self: &Arc<Self>,
block_pos: &BlockPos,
block: &Block,
) -> bool {
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
pub fn is_block_tick_scheduled(&self, block_pos: &BlockPos, block: &Block) -> bool {
self.read_chunk_sync(&block_pos.chunk_position(), |chunk| {
chunk.block_ticks.is_scheduled(*block_pos, block)
})
.await
.unwrap_or(false)
}
pub async fn is_fluid_tick_scheduled(
self: &Arc<Self>,
block_pos: &BlockPos,
fluid: &Fluid,
) -> bool {
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
pub fn is_fluid_tick_scheduled(&self, block_pos: &BlockPos, fluid: &Fluid) -> bool {
self.read_chunk_sync(&block_pos.chunk_position(), |chunk| {
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 {
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 {
return false; // Hit an opaque block before reaching sky
}
@@ -130,8 +130,8 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset());
if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos).await {
let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state();
if let Some(neighbor_light) = self.get_block_light_level(level, &neighbor_pos) {
let neighbor_state = level.get_block_state(&neighbor_pos).to_state();
let opacity = neighbor_state.opacity.max(1);
let new_light = light_level.saturating_sub(opacity);
@@ -139,7 +139,6 @@ impl DynamicLightEngine {
if new_light > neighbor_light
&& self
.set_block_light_level(level, &neighbor_pos, new_light)
.await
.is_ok()
&& new_light > 1
{
@@ -156,7 +155,7 @@ impl DynamicLightEngine {
removed_light_level: u8,
) {
// 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
// This prevents positions that were intentionally set to 0 from propagating light
@@ -165,13 +164,12 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() {
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 {
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 expected_from_removed_source = removed_light_level.saturating_sub(opacity);
@@ -181,14 +179,11 @@ impl DynamicLightEngine {
if neighbor_luminance == 0 {
// No self-emission, darken it completely and continue propagation
self.set_block_light_level(level, &neighbor_pos, 0)
.await
.ok();
self.set_block_light_level(level, &neighbor_pos, 0).ok();
self.queue_block_light_decrease(neighbor_pos, neighbor_light);
} else {
// Has self-emission, set to its own light and re-propagate from it
self.set_block_light_level(level, &neighbor_pos, neighbor_luminance)
.await
.ok();
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) {
match level.lighting_config {
LightingEngineConfig::Full => {
self.set_block_light_level(level, &pos, 15).await.ok();
self.set_block_light_level(level, &pos, 15).ok();
return;
}
LightingEngineConfig::Dark => {
self.set_block_light_level(level, &pos, 0).await.ok();
self.set_block_light_level(level, &pos, 0).ok();
return;
}
LightingEngineConfig::Default => {}
}
let current_light = self.get_block_light_level(level, &pos).await.unwrap_or(0);
let block_state = level.get_block_state(&pos).await.to_state();
let current_light = self.get_block_light_level(level, &pos).unwrap_or(0);
let block_state = level.get_block_state(&pos).to_state();
let expected_light = block_state.luminance;
// Handle light decrease (removing light source or placing opaque block)
if expected_light < current_light {
// Set to expected value immediately, then queue decrease to darken neighbors
self.set_block_light_level(level, &pos, expected_light)
.await
.ok();
self.set_block_light_level(level, &pos, expected_light).ok();
self.queue_block_light_decrease(pos, current_light);
} else if expected_light > current_light {
// Handle light increase (placing light source)
self.set_block_light_level(level, &pos, expected_light)
.await
.ok();
self.set_block_light_level(level, &pos, expected_light).ok();
self.queue_block_light_increase(pos, expected_light);
}
@@ -249,7 +240,7 @@ impl DynamicLightEngine {
) {
for dir in BlockDirection::all() {
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
{
self.queue_block_light_increase(neighbor_pos, neighbor_light);
@@ -301,8 +292,8 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() {
let neighbor_pos = pos.offset(dir.to_offset());
let neighbor_light = self.get_sky_light_level(level, &neighbor_pos).await;
let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state();
let neighbor_light = self.get_sky_light_level(level, &neighbor_pos);
let neighbor_state = level.get_block_state(&neighbor_pos).to_state();
let opacity = neighbor_state.opacity;
// Calculate new light level for neighbor
@@ -317,7 +308,6 @@ impl DynamicLightEngine {
// Only propagate if new light is brighter than current light
if new_light > neighbor_light {
self.set_sky_light_level(level, &neighbor_pos, new_light)
.await
.ok();
if new_light > 0 {
@@ -336,12 +326,12 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() {
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 {
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;
// Calculate what we would have given this neighbor
@@ -353,7 +343,7 @@ impl DynamicLightEngine {
if neighbor_light == expected || neighbor_light < removed_light {
// 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);
} else if neighbor_light > removed_light {
// 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) {
match level.lighting_config {
LightingEngineConfig::Full => {
self.set_sky_light_level(level, &pos, 15).await.ok();
self.set_sky_light_level(level, &pos, 15).ok();
return;
}
LightingEngineConfig::Dark => {
self.set_sky_light_level(level, &pos, 0).await.ok();
self.set_sky_light_level(level, &pos, 0).ok();
return;
}
LightingEngineConfig::Default => {}
}
let current_light = self.get_sky_light_level(level, &pos).await;
let block_state = level.get_block_state(&pos).await.to_state();
let current_light = self.get_sky_light_level(level, &pos);
let block_state = level.get_block_state(&pos).to_state();
let opacity = block_state.opacity;
// Calculate expected sky light
@@ -398,7 +388,7 @@ impl DynamicLightEngine {
for dir in BlockDirection::all() {
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
let potential = if neighbor_light == 15 && dir == BlockDirection::Up {
// Sky light at 15 from above stays 15
@@ -419,15 +409,11 @@ impl DynamicLightEngine {
// Update if needed
if expected_light < current_light {
// Light decreased
self.set_sky_light_level(level, &pos, expected_light)
.await
.ok();
self.set_sky_light_level(level, &pos, expected_light).ok();
self.queue_sky_light_decrease(pos, current_light);
} else if expected_light > current_light {
// Light increased
self.set_sky_light_level(level, &pos, expected_light)
.await
.ok();
self.set_sky_light_level(level, &pos, expected_light).ok();
self.queue_sky_light_increase(pos, expected_light);
}
@@ -489,70 +475,62 @@ impl DynamicLightEngine {
.unwrap_or(0)
}
pub async fn get_block_light_level(
&self,
level: &Arc<Level>,
position: &BlockPos,
) -> Option<u8> {
pub fn get_block_light_level(&self, level: &Arc<Level>, position: &BlockPos) -> Option<u8> {
let (chunk_pos, relative) = position.chunk_and_chunk_relative_position();
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 light_engine = chunk.light_engine.lock().ok()?;
light_engine
.block_light
.get(section_idx)?
.get(
relative.x as usize,
(relative.y - chunk.section.min_y) as usize % 16,
relative.z as usize,
)
.into()
let light_level = light_engine.block_light.get(section_idx)?.get(
relative.x as usize,
(relative.y - chunk.section.min_y) as usize % 16,
relative.z as usize,
);
Some(light_level)
})
.await
.flatten()
}
pub async fn set_block_light_level(
pub fn set_block_light_level(
&self,
level: &Arc<Level>,
position: &BlockPos,
light_level: u8,
) -> Result<(), String> {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
level
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
let section_index =
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
// Bounds check for section index
let mut light_engine = chunk
.light_engine
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if section_index >= light_engine.block_light.len() {
return Err("Invalid section index".to_string());
}
let relative_y = (relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE;
light_engine.block_light[section_index].set(
relative.x as usize,
relative_y,
relative.z as usize,
light_level,
);
// Mark chunk as dirty so lighting changes are saved to disk
if !chunk.is_dirty() {
chunk.mark_dirty(true);
}
Ok(())
})
.await
level.read_chunk_sync(&chunk_coordinate, |chunk| {
let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
// Bounds check for section index
let mut light_engine = chunk
.light_engine
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if section_index >= light_engine.block_light.len() {
return Err("Invalid section index".to_string());
}
let relative_y = (relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE;
light_engine.block_light[section_index].set(
relative.x as usize,
relative_y,
relative.z as usize,
light_level,
);
// Mark chunk as dirty so lighting changes are saved to disk
if !chunk.is_dirty() {
chunk.mark_dirty(true);
}
Ok(())
});
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();
level
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
.read_chunk_sync(&chunk_coordinate, |chunk| {
let section_index =
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
@@ -571,41 +549,39 @@ impl DynamicLightEngine {
relative.z as usize,
)
})
.await
.unwrap_or(0)
}
pub async fn set_sky_light_level(
pub fn set_sky_light_level(
&self,
level: &Arc<Level>,
position: &BlockPos,
light_level: u8,
) -> Result<(), String> {
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
level
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
let section_index =
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
// Bounds check for section index
let mut light_engine = chunk
.light_engine
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if section_index >= light_engine.sky_light.len() {
return Err("Invalid section index".to_string());
}
let relative_y = (relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE;
light_engine.sky_light[section_index].set(
relative.x as usize,
relative_y,
relative.z as usize,
light_level,
);
// Mark chunk as dirty so lighting changes are saved to disk
if !chunk.is_dirty() {
chunk.mark_dirty(true);
}
Ok(())
})
.await
level.read_chunk_sync(&chunk_coordinate, |chunk| {
let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
// Bounds check for section index
let mut light_engine = chunk
.light_engine
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if section_index >= light_engine.sky_light.len() {
return Err("Invalid section index".to_string());
}
let relative_y = (relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE;
light_engine.sky_light[section_index].set(
relative.x as usize,
relative_y,
relative.z as usize,
light_level,
);
// Mark chunk as dirty so lighting changes are saved to disk
if !chunk.is_dirty() {
chunk.mark_dirty(true);
}
Ok(())
});
Ok(())
}
}

View File

@@ -42,8 +42,7 @@ impl BlockBehaviour for BannerBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -75,9 +75,7 @@ impl BlockBehaviour for BarrelBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
let barrel_block_entity = BarrelBlockEntity::new(*args.position);
args.world
.add_block_entity(Arc::new(barrel_block_entity))
.await;
args.world.add_block_entity(Arc::new(barrel_block_entity));
})
}
}

View File

@@ -26,14 +26,12 @@ impl BlockBehaviour for BarrierBlock {
Box::pin(async move {
let props = BarrierLikeProperties::from_state_id(args.state_id, args.block);
if props.waterlogged {
args.world
.schedule_fluid_tick(
&Fluid::WATER,
*args.position,
Fluid::WATER.flow_speed as u8,
TickPriority::Normal,
)
.await;
args.world.schedule_fluid_tick(
&Fluid::WATER,
*args.position,
Fluid::WATER.flow_speed as u8,
TickPriority::Normal,
);
}
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, ()> {
Box::pin(async move {
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);
bed_head_props.facing = BedProperties::from_state_id(args.state_id, args.block).facing;
@@ -132,7 +132,7 @@ impl BlockBehaviour for BedBlock {
.await;
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 {
let blasting_furnace_block_entity = BlastingFurnaceBlockEntity::new(*args.position);
args.world
.add_block_entity(Arc::new(blasting_furnace_block_entity))
.await;
.add_block_entity(Arc::new(blasting_furnace_block_entity));
})
}
@@ -139,7 +138,7 @@ impl BlockBehaviour for BlastFurnaceBlock {
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, ()> {
Box::pin(async move {
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 {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
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);
if props.waterlogged {
props.lit = false;
args.world
.schedule_fluid_tick(
&Fluid::WATER,
*args.position,
Fluid::WATER.flow_speed as u8,
TickPriority::Normal,
)
.await;
args.world.schedule_fluid_tick(
&Fluid::WATER,
*args.position,
Fluid::WATER.flow_speed as u8,
TickPriority::Normal,
);
}
if args.direction == BlockDirection::Down {

View File

@@ -137,8 +137,7 @@ impl BlockBehaviour for CandleCakeBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -149,8 +149,7 @@ impl BlockBehaviour for CandleBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -23,8 +23,7 @@ impl BlockBehaviour for CarpetBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})
@@ -56,8 +55,7 @@ impl BlockBehaviour for MossCarpetBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})
@@ -89,8 +87,7 @@ impl BlockBehaviour for PaleMossCarpetBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -96,7 +96,7 @@ async fn placed_chest_impl<E: BlockEntity + 'static>(
create_entity: impl FnOnce(BlockPos) -> E,
) {
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 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, ()> {
Box::pin(async move {
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
}
async fn update(
fn update(
world: &World,
block: &Block,
command_block: &CommandBlockEntity,
@@ -87,9 +87,7 @@ impl CommandBlock {
let props = CommandBlockLikeProperties::from_state_id(state_id, block);
if !props.conditional {
world
.schedule_block_tick(block, *pos, 1, TickPriority::Normal)
.await;
world.schedule_block_tick(block, *pos, 1, TickPriority::Normal);
return;
}
@@ -109,9 +107,7 @@ impl CommandBlock {
.expect("behind should always be a command block");
if behind_entity.success_count.load(Ordering::Relaxed) > 0 {
world
.schedule_block_tick(block, *pos, 1, TickPriority::Normal)
.await;
world.schedule_block_tick(block, *pos, 1, TickPriority::Normal);
}
}
@@ -226,7 +222,7 @@ impl BlockBehaviour for CommandBlock {
let Some(block_entity) = args.world.get_block_entity(args.position) else {
return BlockActionResult::Pass;
};
args.world.update_block_entity(&block_entity).await;
args.world.update_block_entity(&block_entity);
BlockActionResult::SuccessServer
})
}
@@ -253,8 +249,7 @@ impl BlockBehaviour for CommandBlock {
command_entity,
args.position,
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;
if block == &Block::REPEATING_COMMAND_BLOCK && can_run {
args.world
.schedule_block_tick(block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(block, *args.position, 1, TickPriority::Normal);
}
})
}
@@ -332,7 +326,7 @@ impl BlockBehaviour for CommandBlock {
send_command_feedback,
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)
.await;
if level == 7 {
world
.schedule_block_tick(block, *location, 20, TickPriority::Normal)
.await;
world.schedule_block_tick(block, *location, 20, TickPriority::Normal);
}
}

View File

@@ -47,8 +47,7 @@ impl BlockBehaviour for DirtPathBlock {
Box::pin(async move {
if args.direction == BlockDirection::Up && !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -48,8 +48,7 @@ impl BlockBehaviour for DragonEggBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
args.world
.schedule_block_tick(args.block, *args.position, 5, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 5, TickPriority::Normal);
})
}

View File

@@ -29,8 +29,7 @@ impl BlockBehaviour for EndPortalBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
args.world
.add_block_entity(Arc::new(EndPortalBlockEntity::new(*args.position)))
.await;
.add_block_entity(Arc::new(EndPortalBlockEntity::new(*args.position)));
})
}
}

View File

@@ -103,7 +103,7 @@ impl BlockBehaviour for EnderChestBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
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 {
// TODO: make delay configurable
args.world
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal);
})
}
fn get_state_for_neighbor_update<'a>(
@@ -44,8 +43,7 @@ impl BlockBehaviour for FallingBlock {
Box::pin(async move {
// TODO: make delay configurable
args.world
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal);
args.state_id
})
}

View File

@@ -57,8 +57,7 @@ impl BlockBehaviour for FarmlandBlock {
Box::pin(async move {
if args.direction == BlockDirection::Up && !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -199,14 +199,12 @@ impl BlockBehaviour for FireBlock {
return;
}
args.world
.schedule_block_tick(
args.block,
*args.position,
Self::get_fire_tick_delay() as u8,
TickPriority::Normal,
)
.await;
args.world.schedule_block_tick(
args.block,
*args.position,
Self::get_fire_tick_delay() as u8,
TickPriority::Normal,
);
})
}
@@ -255,14 +253,12 @@ impl BlockBehaviour for FireBlock {
let (world, block, pos) = (args.world, args.block, args.position);
// Schedule next tick first
world
.schedule_block_tick(
block,
*pos,
Self::get_fire_tick_delay() as u8,
TickPriority::Normal,
)
.await;
world.schedule_block_tick(
block,
*pos,
Self::get_fire_tick_delay() as u8,
TickPriority::Normal,
);
// Check if fire can survive
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, ()> {
Box::pin(async move {
let furnace_block_entity = FurnaceBlockEntity::new(*args.position);
args.world
.add_block_entity(Arc::new(furnace_block_entity))
.await;
args.world.add_block_entity(Arc::new(furnace_block_entity));
})
}
@@ -135,7 +133,7 @@ impl BlockBehaviour for FurnaceBlock {
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 {
let props = HopperLikeProperties::from_state_id(args.state_id, args.block);
let hopper_block_entity = HopperBlockEntity::new(*args.position, props.facing);
args.world
.add_block_entity(Arc::new(hopper_block_entity))
.await;
args.world.add_block_entity(Arc::new(hopper_block_entity));
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;
}

View File

@@ -90,7 +90,7 @@ impl BlockBehaviour for JukeboxBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
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(),
) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
})
}

View File

@@ -58,8 +58,7 @@ impl BlockBehaviour for LanternBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -41,7 +41,7 @@ impl BlockBehaviour for LecternBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
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 {
let props = MangroveRootsLikeProperties::from_state_id(args.state_id, args.block);
if props.waterlogged {
args.world
.schedule_fluid_tick(
&Fluid::WATER,
*args.position,
Fluid::WATER.flow_speed as u8,
TickPriority::Normal,
)
.await;
args.world.schedule_fluid_tick(
&Fluid::WATER,
*args.position,
Fluid::WATER.flow_speed as u8,
TickPriority::Normal,
);
}
props.to_state_id(args.block)
})

View File

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

View File

@@ -103,8 +103,7 @@ impl BlockBehaviour for BambooBlock {
Box::pin(async move {
if !<Self as PlantBlockBase>::can_place_at(self, args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
let neighbor_block = args.world.get_block(args.neighbor_position);
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,
};
if tick_delay != -1 {
world
.schedule_block_tick(
&Block::BIG_DRIPLEAF,
*pos,
tick_delay as u8,
pumpkin_world::tick::TickPriority::Normal,
)
.await;
world.schedule_block_tick(
&Block::BIG_DRIPLEAF,
*pos,
tick_delay as u8,
pumpkin_world::tick::TickPriority::Normal,
);
}
}
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 {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id

View File

@@ -29,8 +29,7 @@ impl BlockBehaviour for ChorusFlowerBlock {
Box::pin(async move {
if args.direction != BlockDirection::Up && !can_survive(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -39,8 +39,7 @@ impl BlockBehaviour for ChorusPlantBlock {
if !can_survive(args.world, args.position) {
// Schedule delayed destruction so the whole plant cascades down.
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
return args.state_id;
}

View File

@@ -71,8 +71,7 @@ impl BlockBehaviour for SugarCaneBlock {
Box::pin(async move {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -32,7 +32,6 @@ pub trait 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
where
Self: Send + Sync,
@@ -42,7 +41,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
self.can_place_above(world, under_pos, under_state)
}
// 💡 Converted async fn to fn
fn can_place_above(
&self,
_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 })
}
// 💡 Converted async fn to fn returning BlockFuture
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, ()>
@@ -105,7 +102,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
})
}
// 💡 Converted async fn to fn returning BlockFuture
fn update_powered<'a>(
&'a self,
world: &'a World,
@@ -114,7 +110,6 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
block: &'a Block,
) -> BlockFuture<'a, ()>;
// 💡 Converted async fn to fn returning BlockFuture
fn has_power<'a>(
&'a self,
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 })
}
// 💡 Converted async fn to fn returning BlockFuture
fn get_power<'a>(
&'a self,
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 })
}
// 💡 Converted async fn to fn returning BlockFuture
fn get_max_input_level_sides<'a>(
&'a self,
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>(
&'a self,
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>(
&'a self,
player: &'a Player,
@@ -217,8 +208,7 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
.await
{
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
})
}
@@ -242,29 +232,26 @@ pub trait RedstoneGateBlock<T: Send + Sync + BlockProperties + RedstoneGateBlock
})
}
// 💡 Converted async fn to fn returning BlockFuture
fn is_target_not_aligned<'a>(
&'a self,
world: &'a dyn BlockAccessor,
pos: BlockPos,
state: &'a BlockState,
block: &'a Block,
) -> BlockFuture<'a, bool> {
Box::pin(async move {
let props = T::from_state_id(state.id, block);
let facing = props.get_facing().opposite();
let (target_block, target_state) =
world.get_block_and_state(&pos.offset(facing.to_offset()));
if target_block == &Block::COMPARATOR {
let props = ComparatorLikeProperties::from_state_id(target_state.id, target_block);
props.facing != facing
} else if target_block == &Block::REPEATER {
let props = RepeaterLikeProperties::from_state_id(target_state.id, target_block);
props.facing != facing
} else {
false
}
})
) -> bool {
let props = T::from_state_id(state.id, block);
let facing = props.get_facing().opposite();
let (target_block, target_state) =
world.get_block_and_state(&pos.offset(facing.to_offset()));
if target_block == &Block::COMPARATOR {
let props = ComparatorLikeProperties::from_state_id(target_state.id, target_block);
props.facing != facing
} else if target_block == &Block::REPEATER {
let props = RepeaterLikeProperties::from_state_id(target_state.id, target_block);
props.facing != facing
} else {
false
}
}
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, ()> {
Box::pin(async move {
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, ()> {
Box::pin(async move {
args.world
.add_block_entity(Arc::new(BellBlockEntity::new(*args.position)))
.await;
.add_block_entity(Arc::new(BellBlockEntity::new(*args.position)));
})
}
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 {
30
};
world
.schedule_block_tick(block, *block_pos, delay, TickPriority::Normal)
.await;
world.schedule_block_tick(block, *block_pos, delay, TickPriority::Normal);
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, ()> {
Box::pin(async move {
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(
self,
@@ -78,7 +78,7 @@ impl BlockBehaviour for ComparatorBlock {
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
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,
) -> BlockFuture<'a, ()> {
Box::pin(async move {
if world.is_block_tick_scheduled(&pos, block).await {
if world.is_block_tick_scheduled(&pos, block) {
return;
}
let i = self.calculate_output_signal(world, pos, state, block).await;
@@ -187,20 +187,16 @@ impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock {
|| props.powered
!= RedstoneGateBlock::has_power(self, world, pos, state, block).await
{
world
.schedule_block_tick(
block,
pos,
RedstoneGateBlock::get_update_delay_internal(self, state.id, block),
if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block)
.await
{
TickPriority::High
} else {
TickPriority::Normal
},
)
.await;
world.schedule_block_tick(
block,
pos,
RedstoneGateBlock::get_update_delay_internal(self, state.id, block),
if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block) {
TickPriority::High
} else {
TickPriority::Normal
},
);
}
})
}

View File

@@ -21,14 +21,13 @@ impl BlockBehaviour for DaylightDetectorBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
args.world
.add_block_entity(Arc::new(DaylightDetectorBlockEntity::new(*args.position)))
.await;
.add_block_entity(Arc::new(DaylightDetectorBlockEntity::new(*args.position)));
})
}
fn broken<'a>(&'a self, args: BrokenArgs<'a>) -> BlockFuture<'a, ()> {
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, ()> {
Box::pin(async move {
let dropper_block_entity = DropperBlockEntity::new(*args.position);
args.world
.add_block_entity(Arc::new(dropper_block_entity))
.await;
args.world.add_block_entity(Arc::new(dropper_block_entity));
})
}
@@ -127,8 +125,7 @@ impl BlockBehaviour for DropperBlock {
);
if powered && !props.triggered {
args.world
.schedule_block_tick(args.block, *args.position, 4, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 4, TickPriority::Normal);
props.triggered = true;
args.world
.set_block_state(

View File

@@ -50,8 +50,7 @@ impl BlockBehaviour for ObserverBlock {
)
.await;
args.world
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 2, TickPriority::Normal);
}
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);
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
@@ -112,7 +111,6 @@ impl BlockBehaviour for ObserverBlock {
&& args
.world
.is_block_tick_scheduled(args.position, &Block::OBSERVER)
.await
{
Self::update_neighbors(args.world, args.block, args.position, &props).await;
}
@@ -137,9 +135,7 @@ impl ObserverBlock {
.await;
}
async fn schedule_tick(world: &World, block_pos: &BlockPos) {
world
.schedule_block_tick(&Block::OBSERVER, *block_pos, 2, TickPriority::Normal)
.await;
fn schedule_tick(world: &World, block_pos: &BlockPos) {
world.schedule_block_tick(&Block::OBSERVER, *block_pos, 2, TickPriority::Normal);
}
}

View File

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

View File

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

View File

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

View File

@@ -89,18 +89,16 @@ impl BlockBehaviour for RepeaterBlock {
)
.await;
if !should_be_powered {
args.world
.schedule_block_tick(
args.world.schedule_block_tick(
args.block,
*args.position,
RedstoneGateBlock::get_update_delay_internal(
self,
props.to_state_id(args.block),
args.block,
*args.position,
RedstoneGateBlock::get_update_delay_internal(
self,
props.to_state_id(args.block),
args.block,
),
TickPriority::VeryHigh,
)
.await;
),
TickPriority::VeryHigh,
);
}
RedstoneGateBlock::update_target(
self,
@@ -240,16 +238,12 @@ impl RedstoneGateBlock<RepeaterProperties> for RepeaterBlock {
let props = RepeaterProperties::from_state_id(state.id, block);
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.
let has_power = RedstoneGateBlock::has_power(self, world, pos, state, block).await;
if powered != has_power && !world.is_block_tick_scheduled(&pos, block).await {
// 💡 FIX 4: is_target_not_aligned returns a Future and must be awaited.
if powered != has_power && !world.is_block_tick_scheduled(&pos, block) {
let priority =
if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block)
.await
{
if RedstoneGateBlock::is_target_not_aligned(self, world, pos, state, block) {
TickPriority::ExtremelyHigh
} else if powered {
TickPriority::VeryHigh
@@ -257,15 +251,12 @@ impl RedstoneGateBlock<RepeaterProperties> for RepeaterBlock {
TickPriority::High
};
world
.schedule_block_tick(
block,
pos,
// 💡 FIX 5: get_update_delay_internal is not async and is called normally.
RedstoneGateBlock::get_update_delay_internal(self, state.id, block),
priority,
)
.await;
world.schedule_block_tick(
block,
pos,
RedstoneGateBlock::get_update_delay_internal(self, state.id, block),
priority,
);
}
})
}

View File

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

View File

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

View File

@@ -79,9 +79,7 @@ impl BlockBehaviour for ShulkerBoxBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
let barrel_block_entity = ShulkerBoxBlockEntity::new(*args.position);
args.world
.add_block_entity(Arc::new(barrel_block_entity))
.await;
args.world.add_block_entity(Arc::new(barrel_block_entity));
})
}

View File

@@ -307,8 +307,7 @@ impl BlockBehaviour for SignBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
args.world
.add_block_entity(Arc::new(SignBlockEntity::empty(*args.position)))
.await;
.add_block_entity(Arc::new(SignBlockEntity::empty(*args.position)));
})
}
@@ -368,7 +367,7 @@ impl BlockBehaviour for SignBlock {
fn on_state_replaced<'a>(&'a self, args: OnStateReplacedArgs<'a>) -> BlockFuture<'a, ()> {
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.
#[expect(clippy::option_if_let_else)]
fn use_with_item<'a>(
&'a self,
args: UseWithItemArgs<'a>,
@@ -507,27 +507,39 @@ impl BlockBehaviour for SignBlock {
return BlockActionResult::PassToDefaultBlockAction;
};
let result = if let Some(honeycomb_item) =
pumpkin_item.as_any().downcast_ref::<HoneyCombItem>()
{
honeycomb_item
.apply_to_sign(&args, &block_entity, sign_entity)
.await
} else if let Some(g_ink_sac_item) =
pumpkin_item.as_any().downcast_ref::<GlowingInkSacItem>()
{
g_ink_sac_item
.apply_to_sign(&args, &block_entity, text)
.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)
.await
} else {
BlockActionResult::PassToDefaultBlockAction
};
let result = pumpkin_item
.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>()
{
ink_sac_item.apply_to_sign(&args, &block_entity, text)
} 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)
} else {
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 !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, ()> {
Box::pin(async move {
let smoker_block_entity = SmokerBlockEntity::new(*args.position);
args.world
.add_block_entity(Arc::new(smoker_block_entity))
.await;
args.world.add_block_entity(Arc::new(smoker_block_entity));
})
}
@@ -134,7 +132,7 @@ impl BlockBehaviour for SmokerBlock {
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 {
if !can_place_at(args.world, args.position) {
args.world
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal)
.await;
.schedule_block_tick(args.block, *args.position, 1, TickPriority::Normal);
}
args.state_id
})

View File

@@ -12,9 +12,7 @@ impl BlockBehaviour for SpawnerBlock {
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
Box::pin(async move {
let hopper_block_entity = MobSpawnerBlockEntity::new(*args.position, None);
args.world
.add_block_entity(Arc::new(hopper_block_entity))
.await;
args.world.add_block_entity(Arc::new(hopper_block_entity));
})
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -157,7 +157,11 @@ impl BlockPosArgumentConsumer {
) -> Result<BlockPos, CommandError> {
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(
"argument.pos.unloaded",
"argument.pos.unloaded",

View File

@@ -109,7 +109,11 @@ impl BlockPosArgumentType {
world: &World,
) -> Result<BlockPos, CommandSyntaxError> {
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())
} else if !world.is_in_build_limit(pos) {
Err(OUT_OF_WORLD_ERROR_TYPE.create_without_context())

View File

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

View File

@@ -359,7 +359,10 @@ impl EntityBase for ArmorStandEntity {
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;
}

View File

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

View File

@@ -51,7 +51,7 @@ impl BatEntity {
if rand::random_bool(1.0) {
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;
}
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 {
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) {
return false;
}
@@ -192,7 +192,7 @@ impl MobEntity {
let dimension = &world.dimension;
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 {
return false;
}
@@ -307,7 +307,7 @@ impl MobEntity {
.level
.light_engine
.get_sky_light_level(&world.level, &eye_block_pos.to_block_pos())
.await as f32
as f32
/ 15.0;
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.
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
if matches!(
*damage_type,
@@ -2308,9 +2308,7 @@ impl Entity {
}
// 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

View File

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

View File

@@ -32,7 +32,7 @@ impl ItemBehaviour for DyeItem {
}
impl DyeItem {
pub async fn apply_to_sign(
pub fn apply_to_sign(
&self,
args: &UseWithItemArgs<'_>,
block_entity: &Arc<dyn BlockEntity>,
@@ -43,7 +43,7 @@ impl DyeItem {
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(
pumpkin_data::sound::Sound::ItemDyeUse,
pumpkin_data::sound::SoundCategory::Blocks,

View File

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

View File

@@ -86,7 +86,7 @@ impl ItemBehaviour for HoneyCombItem {
}
impl HoneyCombItem {
pub async fn apply_to_sign(
pub fn apply_to_sign(
&self,
args: &UseWithItemArgs<'_>,
block_entity: &Arc<dyn BlockEntity>,
@@ -94,7 +94,7 @@ impl HoneyCombItem {
) -> BlockActionResult {
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
.sync_world_event(WorldEvent::ParticlesAndSoundWaxOn, *args.position, 0);

View File

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

View File

@@ -42,7 +42,7 @@ impl ItemBehaviour for SpawnEggItem {
.downcast_ref::<MobSpawnerBlockEntity>()
{
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);
return;
}

View File

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

View File

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