Skip to content

Commit

Permalink
stablize cylindrical chunks (#385)
Browse files Browse the repository at this point in the history
  • Loading branch information
kralverde authored Dec 8, 2024
1 parent c7e02ec commit 4763fa3
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 61 deletions.
44 changes: 13 additions & 31 deletions pumpkin-world/src/cylindrical_chunk_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,17 @@ impl Cylindrical {
mut newly_included: impl FnMut(Vector2<i32>),
mut just_removed: impl FnMut(Vector2<i32>),
) {
let min_x = old_cylindrical.left().min(new_cylindrical.left());
let max_x = old_cylindrical.right().max(new_cylindrical.right());
let min_z = old_cylindrical.bottom().min(new_cylindrical.bottom());
let max_z = old_cylindrical.top().max(new_cylindrical.top());

//log::debug!("{:?} {:?}", old_cylindrical, new_cylindrical);
for x in min_x..=max_x {
for z in min_z..=max_z {
let old_is_within = old_cylindrical.is_within_distance(x, z);
let new_is_within = new_cylindrical.is_within_distance(x, z);

//log::debug!("{}, {}: {} {}", x, z, old_is_within, new_is_within);

if old_is_within != new_is_within {
if new_is_within {
newly_included(Vector2::new(x, z));
} else {
just_removed(Vector2::new(x, z));
}
}
for new_cylindrical_chunk in new_cylindrical.all_chunks_within() {
if !old_cylindrical.is_within_distance(new_cylindrical_chunk.x, new_cylindrical_chunk.z)
{
newly_included(new_cylindrical_chunk);
}
}

for old_cylindrical_chunk in old_cylindrical.all_chunks_within() {
if !new_cylindrical.is_within_distance(old_cylindrical_chunk.x, old_cylindrical_chunk.z)
{
just_removed(old_cylindrical_chunk);
}
}
}
Expand Down Expand Up @@ -82,19 +73,10 @@ impl Cylindrical {
}
}

let mut result = all_chunks
all_chunks
.into_iter()
.filter(|chunk| self.is_within_distance(chunk.x, chunk.z))
.collect_vec();

// Sort such that the first chunks are closest to the center
result.sort_unstable_by_key(|pos| {
let rel_x = pos.x - self.center.x;
let rel_z = pos.z - self.center.z;
rel_x * rel_x + rel_z * rel_z
});

result
.collect_vec()
}
}

Expand Down
2 changes: 1 addition & 1 deletion pumpkin-world/src/level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl Level {
// - Player disconnecting before all packets have been sent
// - Player moving so fast that the chunk leaves the render distance before it
// is loaded into memory
false
true
}
}
}
Expand Down
20 changes: 17 additions & 3 deletions pumpkin/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,12 @@ impl World {
}

/// IMPORTANT: Chunks have to be non-empty
fn spawn_world_chunks(&self, player: Arc<Player>, chunks: Vec<Vector2<i32>>) {
fn spawn_world_chunks(
&self,
player: Arc<Player>,
chunks: Vec<Vector2<i32>>,
center_chunk: Vector2<i32>,
) {
if player
.client
.closed
Expand All @@ -544,6 +549,14 @@ impl World {
#[cfg(debug_assertions)]
let inst = std::time::Instant::now();

// Sort such that the first chunks are closest to the center
let mut chunks = chunks;
chunks.sort_unstable_by_key(|pos| {
let rel_x = pos.x - center_chunk.x;
let rel_z = pos.z - center_chunk.z;
rel_x * rel_x + rel_z * rel_z
});

player.world().mark_chunks_as_watched(&chunks);
let mut receiver = self.receive_chunks(chunks);
let level = self.level.clone();
Expand All @@ -567,11 +580,12 @@ impl World {
}

if !level.is_chunk_watched(&chunk_data.position) {
log::debug!(
log::trace!(
"Received chunk {:?}, but it is no longer watched... cleaning",
&chunk_data.position
);
level.clean_chunk(&chunk_data.position);
continue;
}

if !player
Expand Down Expand Up @@ -741,7 +755,7 @@ impl World {
.expect("Channel closed for unknown reason");

if !self.level.is_chunk_watched(&chunk_pos) {
log::debug!(
log::trace!(
"Received chunk {:?}, but it is not watched... cleaning",
chunk_pos
);
Expand Down
48 changes: 22 additions & 26 deletions pumpkin/src/world/player_chunker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;

use pumpkin_config::BASIC_CONFIG;
use pumpkin_core::{
math::{get_section_cord, position::WorldPosition, vector2::Vector2, vector3::Vector3},
math::{get_section_cord, position::WorldPosition, vector3::Vector3},
GameMode,
};
use pumpkin_protocol::client::play::{CCenterChunk, CUnloadChunk};
Expand Down Expand Up @@ -49,11 +49,11 @@ pub async fn player_join(world: &World, player: Arc<Player>) {
view_distance
);

let new_cylindrical = Cylindrical::new(Vector2::new(chunk_pos.x, chunk_pos.z), view_distance);
let new_cylindrical = Cylindrical::new(chunk_pos, view_distance);
let loading_chunks = new_cylindrical.all_chunks_within();

if !loading_chunks.is_empty() {
world.spawn_world_chunks(player, loading_chunks);
world.spawn_world_chunks(player, loading_chunks, chunk_pos);
}
}

Expand All @@ -68,24 +68,19 @@ pub async fn update_position(player: &Arc<Player>) {
let entity = &player.living_entity.entity;

let view_distance = get_view_distance(player).await;
let chunk_center = chunk_section_from_pos(&entity.block_pos.load()).into();
let new_chunk_center = entity.chunk_pos.load();

let old_cylindrical = player.watched_section.load();
let new_cylindrical = Cylindrical::new(chunk_center, view_distance);
let new_cylindrical = Cylindrical::new(new_chunk_center, view_distance);

if old_cylindrical != new_cylindrical {
player.watched_section.store(new_cylindrical);

//log::debug!("changing chunks");
let chunk_pos = entity.chunk_pos.load();
assert_eq!(new_cylindrical.center.x, chunk_pos.x);
assert_eq!(new_cylindrical.center.z, chunk_pos.z);

player
.client
.send_packet(&CCenterChunk {
chunk_x: chunk_pos.x.into(),
chunk_z: chunk_pos.z.into(),
chunk_x: new_chunk_center.x.into(),
chunk_z: new_chunk_center.z.into(),
})
.await;

Expand All @@ -101,20 +96,6 @@ pub async fn update_position(player: &Arc<Player>) {
unloading_chunks.push(chunk_pos);
},
);
if !loading_chunks.is_empty() {
//let inst = std::time::Instant::now();

// loading_chunks.sort_by(|a, b| {
// let distance_a_squared = a.sub(a).length_squared();
// let distance_b_squared = b.sub(a).length_squared();
// distance_a_squared.cmp(&distance_b_squared)
// });

entity
.world
.spawn_world_chunks(player.clone(), loading_chunks);
//log::debug!("Loading chunks took {:?}", inst.elapsed());
}

if !unloading_chunks.is_empty() {
//let inst = std::time::Instant::now();
Expand All @@ -139,6 +120,21 @@ pub async fn update_position(player: &Arc<Player>) {
});
//log::debug!("Unloading chunks took {:?} (3)", inst.elapsed());
}

if !loading_chunks.is_empty() {
//let inst = std::time::Instant::now();

// loading_chunks.sort_by(|a, b| {
// let distance_a_squared = a.sub(a).length_squared();
// let distance_b_squared = b.sub(a).length_squared();
// distance_a_squared.cmp(&distance_b_squared)
// });

entity
.world
.spawn_world_chunks(player.clone(), loading_chunks, new_chunk_center);
//log::debug!("Loading chunks took {:?}", inst.elapsed());
}
}
}

Expand Down

0 comments on commit 4763fa3

Please sign in to comment.