From 253866cba3d24e3ac6fc6cd022e6f9f540e882b0 Mon Sep 17 00:00:00 2001 From: Alvsch <94403567+Alvsch@users.noreply.github.com> Date: Mon, 25 Nov 2024 18:12:36 +0100 Subject: [PATCH 1/2] fixed cylindrical --- pumpkin-world/src/cylindrical_chunk_iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pumpkin-world/src/cylindrical_chunk_iterator.rs b/pumpkin-world/src/cylindrical_chunk_iterator.rs index d1146557f..9316b842e 100644 --- a/pumpkin-world/src/cylindrical_chunk_iterator.rs +++ b/pumpkin-world/src/cylindrical_chunk_iterator.rs @@ -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 From 3d3ba9b8c2f7325d53babfb2585af77091a94565 Mon Sep 17 00:00:00 2001 From: Alvsch <94403567+Alvsch@users.noreply.github.com> Date: Mon, 25 Nov 2024 18:13:10 +0100 Subject: [PATCH 2/2] Fixed chunk loading when changing view distance --- Cargo.toml | 6 +++ pumpkin-core/src/math/vector2.rs | 11 ++++++ .../src/cylindrical_chunk_iterator.rs | 2 +- pumpkin/src/entity/player.rs | 13 +++---- pumpkin/src/world/player_chunker.rs | 37 ++++++++++++------- 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4f449a64e..d8cf627c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/pumpkin-core/src/math/vector2.rs b/pumpkin-core/src/math/vector2.rs index 3c3728ba5..be74a5eca 100644 --- a/pumpkin-core/src/math/vector2.rs +++ b/pumpkin-core/src/math/vector2.rs @@ -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 { pub x: T, @@ -90,6 +92,15 @@ impl From<(T, T)> for Vector2 { } } +impl From> for Vector2 { + fn from(value: Vector3) -> Self { + Self { + x: value.x, + z: value.z, + } + } +} + pub trait Math: Mul + Neg diff --git a/pumpkin-world/src/cylindrical_chunk_iterator.rs b/pumpkin-world/src/cylindrical_chunk_iterator.rs index 9316b842e..f7ee02e9b 100644 --- a/pumpkin-world/src/cylindrical_chunk_iterator.rs +++ b/pumpkin-world/src/cylindrical_chunk_iterator.rs @@ -1,6 +1,6 @@ use pumpkin_core::math::vector2::Vector2; -#[derive(Debug, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Cylindrical { pub center: Vector2, pub view_distance: u8, diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index c6a4f9121..86ec41cd5 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -45,6 +45,7 @@ use tokio::sync::{Mutex, Notify}; use tokio::task::JoinHandle; use super::Entity; +use crate::error::PumpkinError; use crate::{ client::{ authentication::GameProfile, @@ -54,7 +55,6 @@ use crate::{ server::Server, world::World, }; -use crate::{error::PumpkinError, world::player_chunker::get_view_distance}; use super::living::LivingEntity; @@ -134,7 +134,7 @@ pub struct Player { /// The pending teleport information, including the teleport ID and target location. pub awaiting_teleport: Mutex)>>, /// The coordinates of the chunk section the player is currently watching. - pub watched_section: AtomicCell>, + pub watched_section: AtomicCell, /// 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 @@ -180,6 +180,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, @@ -208,7 +209,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()), @@ -232,9 +233,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 @@ -685,7 +684,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) => { diff --git a/pumpkin/src/world/player_chunker.rs b/pumpkin/src/world/player_chunker.rs index 6639c48ba..d190061fe 100644 --- a/pumpkin/src/world/player_chunker.rs +++ b/pumpkin/src/world/player_chunker.rs @@ -23,7 +23,11 @@ pub async fn get_view_distance(player: &Player) -> u8 { pub async fn player_join(world: &World, player: Arc) { 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); @@ -62,15 +66,20 @@ pub async fn update_position(player: &Arc) { } 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 @@ -80,13 +89,6 @@ pub async fn update_position(player: &Arc) { }) .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( @@ -101,6 +103,13 @@ pub async fn update_position(player: &Arc) { ); 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);