Some Chunkloading fixes (#342)

* fixed cylindrical

* Fixed chunk loading when changing view distance
This commit is contained in:
Alvsch
2024-11-27 18:37:14 +01:00
committed by GitHub
parent 836ddd39eb
commit df25c1fceb
5 changed files with 48 additions and 23 deletions

View File

@@ -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

View File

@@ -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,
@@ -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>

View File

@@ -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,
@@ -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

View File

@@ -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,
@@ -55,7 +56,6 @@ use crate::{
server::Server,
world::World,
};
use crate::{error::PumpkinError, world::player_chunker::get_view_distance};
use super::living::LivingEntity;
@@ -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
@@ -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,
@@ -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()),
@@ -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
@@ -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) => {

View File

@@ -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);
@@ -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
@@ -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(
@@ -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);