refactor things out into functions

This commit is contained in:
Edvin Bryntesson
2024-10-21 15:10:09 +02:00
parent d7b162e68e
commit 4338bcff16
4 changed files with 63 additions and 40 deletions

View File

@@ -1,13 +1,33 @@
use super::vector3::Vector3;
use std::fmt;
use crate::math::vector2::Vector2;
use num_traits::Euclid;
use serde::{Deserialize, Serialize};
use super::vector3::Vector3;
#[derive(Clone, Copy)]
/// Aka Block Position
pub struct WorldPosition(pub Vector3<i32>);
impl WorldPosition {
pub fn chunk_and_chunk_relative_position(&self) -> (Vector2<i32>, Vector3<i32>) {
let (z_chunk, z_rem) = self.0.z.div_rem_euclid(&16);
let (x_chunk, x_rem) = self.0.x.div_rem_euclid(&16);
let chunk_coordinate = Vector2 {
x: x_chunk,
z: z_chunk,
};
// Since we divide by 16 remnant can never exceed u8
let relative = Vector3 {
x: x_rem,
z: z_rem,
y: self.0.y,
};
(chunk_coordinate, relative)
}
}
impl Serialize for WorldPosition {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where

View File

@@ -1,12 +1,12 @@
use std::ops::Deref;
use crate::{WORLD_LOWEST_Y, WORLD_MAX_Y};
use derive_more::derive::{AsMut, AsRef, Display, Into};
use num_traits::{PrimInt, Signed, Unsigned};
use pumpkin_core::math::vector2::Vector2;
use pumpkin_core::math::vector3::Vector3;
use serde::{Deserialize, Serialize};
use crate::{WORLD_LOWEST_Y, WORLD_MAX_Y};
#[derive(
Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, AsRef, AsMut, Into, Display,
)]
@@ -130,3 +130,13 @@ impl ChunkRelativeXZBlockCoordinates {
}
}
}
impl From<Vector3<i32>> for ChunkRelativeBlockCoordinates {
fn from(value: Vector3<i32>) -> Self {
Self {
x: (value.x as u8).into(),
z: (value.z as u8).into(),
y: value.y.into(),
}
}
}

View File

@@ -6,7 +6,7 @@ use crate::{
client::Client,
entity::{player::Player, Entity},
};
use num_traits::{Euclid, ToPrimitive};
use num_traits::ToPrimitive;
use pumpkin_config::BasicConfiguration;
use pumpkin_core::math::position::WorldPosition;
use pumpkin_core::math::vector2::Vector2;
@@ -20,11 +20,12 @@ use pumpkin_protocol::{
ClientPacket, VarInt,
};
use pumpkin_world::block::BlockId;
use pumpkin_world::chunk::ChunkData;
use pumpkin_world::coordinates::ChunkRelativeBlockCoordinates;
use pumpkin_world::level::Level;
use scoreboard::Scoreboard;
use tokio::sync::mpsc;
use tokio::sync::Mutex;
use tokio::sync::{mpsc, RwLock};
pub mod scoreboard;
@@ -285,7 +286,7 @@ impl World {
level.mark_chunk_as_newly_watched(chunks).await;
}
fn spawn_world_chunks(&self, client: Arc<Client>, chunks: Vec<Vector2<i32>>, distance: i32) {
async fn spawn_world_chunks(&self, client: Arc<Client>, chunks: Vec<Vector2<i32>>) {
if client.closed.load(std::sync::atomic::Ordering::Relaxed) {
log::info!(
"The connection with {} has closed before world chunks were spawned",
@@ -294,21 +295,10 @@ impl World {
return;
}
let inst = std::time::Instant::now();
let (sender, mut chunk_receiver) = mpsc::channel(distance as usize);
let client_id = client.id;
{
let level = self.level.clone();
tokio::spawn(async move {
log::debug!("Spawned chunk fetcher for {}", client_id);
let level = level.lock().await;
level.fetch_chunks(&chunks, sender);
});
}
let chunks = self.get_chunks(chunks).await;
tokio::spawn(async move {
log::debug!("Spawned chunk sender for {}", client_id);
while let Some(chunk_data) = chunk_receiver.recv().await {
for chunk_data in chunks {
let chunk_data = chunk_data.read().await;
let packet = CChunkData(&chunk_data);
#[cfg(debug_assertions)]
@@ -381,32 +371,32 @@ impl World {
.await;
}
pub async fn set_block(&self, position: WorldPosition, block_id: BlockId) {
let (z_chunk, z_rem) = position.0.z.div_rem_euclid(&16);
let (x_chunk, x_rem) = position.0.x.div_rem_euclid(&16);
let chunk_coordinate = Vector2 {
x: x_chunk,
z: z_chunk,
};
let (chunk_coordinate, relative_coordinates) = position.chunk_and_chunk_relative_position();
// Since we divide by 16 remnant can never exceed u8
let relative = ChunkRelativeBlockCoordinates {
x: (x_rem as u8).into(),
z: (z_rem as u8).into(),
y: position.0.y.into(),
};
let relative = ChunkRelativeBlockCoordinates::from(relative_coordinates);
let chunk = self.get_chunks(vec![chunk_coordinate]).await[0].clone();
chunk.write().await.blocks.set_block(relative, block_id);
self.broadcast_packet_all(&CBlockUpdate::new(
&position,
i32::from(block_id.data).into(),
))
.await;
}
pub async fn get_chunks(&self, chunks: Vec<Vector2<i32>>) -> Vec<Arc<RwLock<ChunkData>>> {
let (sender, mut receive) = mpsc::channel(1024);
{
let level = self.level.clone();
tokio::spawn(
async move { level.lock().await.fetch_chunks(&[chunk_coordinate], sender) },
);
tokio::spawn(async move { level.lock().await.fetch_chunks(&chunks, sender) });
}
if let Some(data) = receive.recv().await {
data.write().await.blocks.set_block(relative, block_id);
self.broadcast_packet_all(&CBlockUpdate::new(&position, (block_id.data as i32).into()))
.await;
let mut received = vec![];
while let Some(chunk) = receive.recv().await {
received.push(chunk);
}
received
}
pub async fn break_block(&self, position: WorldPosition) {

View File

@@ -74,7 +74,9 @@ pub async fn player_join(world: &World, player: Arc<Player>) {
if !loading_chunks.is_empty() {
world.mark_chunks_as_watched(&loading_chunks).await;
world.spawn_world_chunks(player.client.clone(), loading_chunks, view_distance);
world
.spawn_world_chunks(player.client.clone(), loading_chunks)
.await;
}
if !unloading_chunks.is_empty() {
@@ -134,7 +136,8 @@ pub async fn update_position(player: &Player) {
entity.world.mark_chunks_as_watched(&loading_chunks).await;
entity
.world
.spawn_world_chunks(player.client.clone(), loading_chunks, view_distance);
.spawn_world_chunks(player.client.clone(), loading_chunks)
.await;
}
if !unloading_chunks.is_empty() {