Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Commit

Permalink
Refactor sky light calculations and add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DimitriTimoz committed Nov 18, 2023
1 parent ead4294 commit 2bebed7
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 32 deletions.
35 changes: 3 additions & 32 deletions minecraft-server/src/world/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ impl Light {
self.sky_light.get_packet_data()
}

pub fn get_skylight_level(&self, position: LightPositionInChunkColumn) -> u8 {
self.sky_light.get_level(position).unwrap_or_default()
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -551,36 +554,4 @@ mod tests {
assert_eq!(sky_light.light_arrays[4].get(BlockPositionInChunk { bx: 9, by: 0, bz: 10 }).unwrap(), 0);
}

#[test]
fn test_sky_light_flat_chunk() {
let mut flat_chunk = ChunkColumn::flat();

// Check that the sky light is equal to the light level above the grass and on the top of the world.
for x in 0..16 {
for z in 0..16 {
assert_eq!(flat_chunk.light.sky_light.light_arrays[0].get(BlockPositionInChunk { bx: x, by: 0, bz: z }).unwrap(), 0);
assert_eq!(flat_chunk.light.sky_light.light_arrays[4].get(BlockPositionInChunk { bx: x, by: 0, bz: z }).unwrap(), 15);
assert_eq!(flat_chunk.light.sky_light.light_arrays[25].get(BlockPositionInChunk { bx: x, by: 15, bz: z }).unwrap(), 15);
}
}

// Break the grass block and check that the sky light is correct.
assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 15, bz: 0 }).unwrap(), 0);
flat_chunk.set_block_for_test(BlockPositionInChunkColumn { bx: 0, y: -49, bz: 0 }, Block::Air.into());
assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 15, bz: 0 }).unwrap(), 15);

assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 14, bz: 0 }).unwrap(), 0);
flat_chunk.set_block_for_test(BlockPositionInChunkColumn { bx: 0, y: -50, bz: 0 }, Block::Air.into());
assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 14, bz: 0 }).unwrap(), 15);

flat_chunk.set_block_for_test(BlockPositionInChunkColumn { bx: 0, y: -50, bz: 1 }, Block::Air.into());
assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 14, bz: 1 }).unwrap(), 14);
assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 0, bz: 10 }).unwrap(), 0);

flat_chunk.set_block_for_test(BlockPositionInChunkColumn { bx: 0, y: -50, bz: 2 }, Block::Air.into());
assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 14, bz: 2 }).unwrap(), 13);

flat_chunk.set_block_for_test(BlockPositionInChunkColumn { bx: 0, y: -51, bz: 2 }, Block::Air.into());
assert_eq!(flat_chunk.light.sky_light.light_arrays[1].get(BlockPositionInChunk { bx: 0, by: 13, bz: 2 }).unwrap(), 12);
}
}
45 changes: 45 additions & 0 deletions minecraft-server/src/world/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,10 @@ impl ChunkColumn {
_ => {}
}
}

fn get_skylight(&self, position: BlockPositionInChunkColumn) -> u8 {
self.light.get_skylight_level(position.into())
}
}

impl WorldMap {
Expand Down Expand Up @@ -503,6 +507,17 @@ impl WorldMap {
}
}

pub async fn get_skylight(&self, position: BlockPosition) -> u8 {
let chunk_position = position.chunk();
let position_in_chunk_column = position.in_chunk_column();
let chunk_column_position = chunk_position.chunk_column();
let shard = chunk_column_position.shard(self.shard_count);

let shard = self.shards[shard].read().await;
let chunk_column = shard.get(&chunk_column_position).unwrap();
chunk_column.light.get_skylight_level(position_in_chunk_column.into())
}

async fn update_light_from_edge(&self, s: &WorldMap, chunk_column_position: ChunkColumnPosition, to_propagate: BinaryHeap<(LightPositionInChunkColumn, u8)>) {
let shard = chunk_column_position.shard(self.shard_count);

Expand Down Expand Up @@ -726,6 +741,36 @@ mod tests {

}

#[tokio::test]
async fn test_sky_light_flat_chunk() {
let world = WorldMap::new(10);
world.load(ChunkColumnPosition { cx: 0, cz: 0 }).await;


// Check that the sky light is equal to the light level above the grass and on the top of the world.
for x in 0..16 {
for z in 0..16 {
assert_eq!(world.get_skylight(BlockPosition { x, y: -60, z}).await, 0);
assert_eq!(world.get_skylight(BlockPosition { x, y: -49, z}).await, 0);
assert_eq!(world.get_skylight(BlockPosition { x, y: 120, z}).await, 15);
}
}

// Break the grass block and check that the sky light is correct.
assert_ne!(world.get_skylight(BlockPosition { x: 0, y: -49, z: 0}).await, 15);
world.set_block(BlockPosition { x: 0, y: -49, z: 0 }, BlockWithState::Air).await;
assert_eq!(world.get_skylight(BlockPosition { x: 0, y: -49, z: 0}).await, 15);

assert_ne!(world.get_skylight(BlockPosition { x: 0, y: -50, z: 0}).await, 15);
world.set_block(BlockPosition { x: 0, y: -50, z: 0 }, BlockWithState::Air).await;
assert_eq!(world.get_skylight(BlockPosition { x: 0, y: -50, z: 0}).await, 15);

assert_ne!(world.get_skylight(BlockPosition { x: 0, y: -50, z: 1}).await, 14);
world.set_block(BlockPosition { x: 0, y: -50, z: 1 }, BlockWithState::Air).await;
assert_eq!(world.get_skylight(BlockPosition { x: 0, y: -50, z: 1}).await, 14);
}


#[test]
fn benchmark_get_block() {

Expand Down

0 comments on commit 2bebed7

Please sign in to comment.