mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
Some Chunkloading fixes (#342)
* fixed cylindrical * Fixed chunk loading when changing view distance
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user