108 lines
3.4 KiB
Rust
108 lines
3.4 KiB
Rust
use std::sync::Arc;
|
|
|
|
use pumpkin_config::BASIC_CONFIG;
|
|
use pumpkin_core::math::{
|
|
get_section_cord, position::WorldPosition, vector2::Vector2, vector3::Vector3,
|
|
};
|
|
use pumpkin_protocol::client::play::{CCenterChunk, CUnloadChunk};
|
|
use pumpkin_world::cylindrical_chunk_iterator::Cylindrical;
|
|
|
|
use crate::entity::{player::Player, Entity};
|
|
|
|
use super::World;
|
|
|
|
fn get_view_distance(player: &Player) -> i8 {
|
|
player
|
|
.config
|
|
.lock()
|
|
.view_distance
|
|
.clamp(2, BASIC_CONFIG.view_distance as i8)
|
|
}
|
|
|
|
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 watched_section = new_watched;
|
|
let chunk_pos = player.living_entity.entity.chunk_pos.load();
|
|
player.client.send_packet(&CCenterChunk {
|
|
chunk_x: chunk_pos.x.into(),
|
|
chunk_z: chunk_pos.z.into(),
|
|
});
|
|
let view_distance = get_view_distance(&player) as i32;
|
|
dbg!(view_distance);
|
|
let old_cylindrical = Cylindrical::new(
|
|
Vector2::new(watched_section.x, watched_section.z),
|
|
view_distance,
|
|
);
|
|
let new_cylindrical = Cylindrical::new(Vector2::new(chunk_pos.x, chunk_pos.z), view_distance);
|
|
let mut loading_chunks = Vec::new();
|
|
Cylindrical::for_each_changed_chunk(
|
|
old_cylindrical,
|
|
new_cylindrical,
|
|
|chunk_pos| {
|
|
loading_chunks.push(chunk_pos);
|
|
},
|
|
|chunk_pos| {
|
|
player
|
|
.client
|
|
.send_packet(&CUnloadChunk::new(chunk_pos.x, chunk_pos.z));
|
|
},
|
|
true,
|
|
);
|
|
if !loading_chunks.is_empty() {
|
|
world
|
|
.spawn_world_chunks(&player.client, loading_chunks, view_distance)
|
|
.await;
|
|
}
|
|
}
|
|
|
|
pub async fn update_position(entity: &Entity, player: &Player) {
|
|
let current_watched = player.watched_section.load();
|
|
let new_watched = chunk_section_from_pos(&entity.block_pos.load());
|
|
if current_watched != new_watched {
|
|
let chunk_pos = entity.chunk_pos.load();
|
|
player.client.send_packet(&CCenterChunk {
|
|
chunk_x: chunk_pos.x.into(),
|
|
chunk_z: chunk_pos.z.into(),
|
|
});
|
|
|
|
let view_distance = get_view_distance(player) as i32;
|
|
let old_cylindrical = Cylindrical::new(
|
|
Vector2::new(current_watched.x, current_watched.z),
|
|
view_distance,
|
|
);
|
|
let new_cylindrical =
|
|
Cylindrical::new(Vector2::new(chunk_pos.x, chunk_pos.z), view_distance);
|
|
player.watched_section.store(new_watched);
|
|
let mut loading_chunks = Vec::new();
|
|
Cylindrical::for_each_changed_chunk(
|
|
old_cylindrical,
|
|
new_cylindrical,
|
|
|chunk_pos| {
|
|
loading_chunks.push(chunk_pos);
|
|
},
|
|
|chunk_pos| {
|
|
player
|
|
.client
|
|
.send_packet(&CUnloadChunk::new(chunk_pos.x, chunk_pos.z));
|
|
},
|
|
false,
|
|
);
|
|
if !loading_chunks.is_empty() {
|
|
entity
|
|
.world
|
|
.spawn_world_chunks(&player.client, loading_chunks, view_distance)
|
|
.await;
|
|
}
|
|
}
|
|
}
|
|
|
|
const fn chunk_section_from_pos(block_pos: &WorldPosition) -> Vector3<i32> {
|
|
let block_pos = block_pos.0;
|
|
Vector3::new(
|
|
get_section_cord(block_pos.x),
|
|
get_section_cord(block_pos.y),
|
|
get_section_cord(block_pos.z),
|
|
)
|
|
}
|