Skip to content

Commit

Permalink
Some Chunkloading fixes (#342)
Browse files Browse the repository at this point in the history
* fixed cylindrical

* Fixed chunk loading when changing view distance
  • Loading branch information
Alvsch authored Nov 27, 2024
1 parent 836ddd3 commit df25c1f
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 23 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ members = [
version = "0.1.0"
edition = "2021"

[profile.dev.package."*"]
opt-level = 3

[profile.dev]
opt-level = 1

[profile.release]
lto = true
codegen-units = 1
Expand Down
11 changes: 11 additions & 0 deletions pumpkin-core/src/math/vector2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::ops::{Add, Div, Mul, Neg, Sub};

use num_traits::Float;

use super::vector3::Vector3;

#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
pub struct Vector2<T> {
pub x: T,
Expand Down Expand Up @@ -90,6 +92,15 @@ impl<T> From<(T, T)> for Vector2<T> {
}
}

impl<T> From<Vector3<T>> for Vector2<T> {
fn from(value: Vector3<T>) -> Self {
Self {
x: value.x,
z: value.z,
}
}
}

pub trait Math:
Mul<Output = Self>
+ Neg<Output = Self>
Expand Down
4 changes: 2 additions & 2 deletions pumpkin-world/src/cylindrical_chunk_iterator.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use pumpkin_core::math::vector2::Vector2;

#[derive(Debug, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Cylindrical {
pub center: Vector2<i32>,
pub view_distance: u8,
Expand Down Expand Up @@ -68,7 +68,7 @@ impl Cylindrical {
let min_leg = rel_x.min(rel_z) as i64;

let hyp_sqr = max_leg * max_leg + min_leg * min_leg;
hyp_sqr < (self.view_distance * self.view_distance) as i64
hyp_sqr < (self.view_distance as i64 * self.view_distance as i64)
}

/// Returns an iterator of all chunks within this cylinder
Expand Down
13 changes: 6 additions & 7 deletions pumpkin/src/entity/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use tokio::sync::{Mutex, Notify};
use tokio::task::JoinHandle;

use super::Entity;
use crate::error::PumpkinError;
use crate::{
client::{
authentication::GameProfile,
Expand All @@ -55,7 +56,6 @@ use crate::{
server::Server,
world::World,
};
use crate::{error::PumpkinError, world::player_chunker::get_view_distance};

use super::living::LivingEntity;

Expand Down Expand Up @@ -135,7 +135,7 @@ pub struct Player {
/// The pending teleport information, including the teleport ID and target location.
pub awaiting_teleport: Mutex<Option<(VarInt, Vector3<f64>)>>,
/// The coordinates of the chunk section the player is currently watching.
pub watched_section: AtomicCell<Vector3<i32>>,
pub watched_section: AtomicCell<Cylindrical>,
/// Did we send a keep alive Packet and wait for the response?
pub wait_for_keep_alive: AtomicBool,
/// Whats the keep alive packet payload we send, The client should responde with the same id
Expand Down Expand Up @@ -181,6 +181,7 @@ impl Player {
|profile| profile,
);
let config = client.config.lock().await.clone().unwrap_or_default();
let view_distance = config.view_distance;
let bounding_box_size = BoundingBoxSize {
width: 0.6,
height: 1.8,
Expand Down Expand Up @@ -209,7 +210,7 @@ impl Player {
teleport_id_count: AtomicI32::new(0),
abilities: Mutex::new(Abilities::default()),
gamemode: AtomicCell::new(gamemode),
watched_section: AtomicCell::new(Vector3::new(0, 0, 0)),
watched_section: AtomicCell::new(Cylindrical::new(Vector2::new(0, 0), view_distance)),
wait_for_keep_alive: AtomicBool::new(false),
keep_alive_id: AtomicI64::new(0),
last_keep_alive_time: AtomicCell::new(std::time::Instant::now()),
Expand All @@ -233,9 +234,7 @@ impl Player {

world.remove_player(self).await;

let watched = self.watched_section.load();
let view_distance = get_view_distance(self).await;
let cylindrical = Cylindrical::new(Vector2::new(watched.x, watched.z), view_distance);
let cylindrical = self.watched_section.load();

// NOTE: This all must be synchronous to make sense! The chunks are handled asynhrously.
// Non-async code is atomic to async code
Expand Down Expand Up @@ -682,7 +681,7 @@ impl Player {
},
packet_result = self.handle_play_packet(server, &mut packet) => {
#[cfg(debug_assertions)]
log::debug!("Handled play packet in {:?}", inst.elapsed());
log::trace!("Handled play packet in {:?}", inst.elapsed());
match packet_result {
Ok(()) => {}
Err(e) => {
Expand Down
37 changes: 23 additions & 14 deletions pumpkin/src/world/player_chunker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ pub async fn get_view_distance(player: &Player) -> u8 {

pub async fn player_join(world: &World, player: Arc<Player>) {
let new_watched = chunk_section_from_pos(&player.living_entity.entity.block_pos.load());
player.watched_section.store(new_watched);

let mut cylindrical = player.watched_section.load();
cylindrical.center = new_watched.into();
player.watched_section.store(cylindrical);

let chunk_pos = player.living_entity.entity.chunk_pos.load();

assert_eq!(new_watched.x, chunk_pos.x);
Expand Down Expand Up @@ -62,15 +66,20 @@ pub async fn update_position(player: &Arc<Player>) {
}

let entity = &player.living_entity.entity;
let current_watched = player.watched_section.load();
let new_watched = chunk_section_from_pos(&entity.block_pos.load());
player.watched_section.store(new_watched);

if current_watched != new_watched {
let view_distance = get_view_distance(player).await;
let chunk_center = chunk_section_from_pos(&entity.block_pos.load()).into();

let old_cylindrical = player.watched_section.load();
let new_cylindrical = Cylindrical::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_watched.x, chunk_pos.x);
assert_eq!(new_watched.z, chunk_pos.z);
assert_eq!(new_cylindrical.center.x, chunk_pos.x);
assert_eq!(new_cylindrical.center.z, chunk_pos.z);

player
.client
Expand All @@ -80,13 +89,6 @@ pub async fn update_position(player: &Arc<Player>) {
})
.await;

let view_distance = get_view_distance(player).await;
let old_cylindrical = Cylindrical::new(
Vector2::new(current_watched.x, current_watched.z),
view_distance,
);
let new_cylindrical = Cylindrical::new(chunk_pos, view_distance);

let mut loading_chunks = Vec::new();
let mut unloading_chunks = Vec::new();
Cylindrical::for_each_changed_chunk(
Expand All @@ -101,6 +103,13 @@ pub async fn update_position(player: &Arc<Player>) {
);
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);
Expand Down

0 comments on commit df25c1f

Please sign in to comment.