Dynamic chunk loading
This commit is contained in:
parent
2085307a44
commit
5c0dffbf9d
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1959,6 +1959,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"pumpkin-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2034,6 +2035,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"pumpkin-core",
|
||||||
"rayon",
|
"rayon",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
pub mod gamemode;
|
pub mod gamemode;
|
||||||
|
pub mod math;
|
||||||
pub mod random;
|
pub mod random;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
use pumpkin_protocol::position::WorldPosition;
|
use super::{position::WorldPosition, vector3::Vector3};
|
||||||
use pumpkin_world::vector3::Vector3;
|
|
||||||
|
|
||||||
pub struct BoundingBox {
|
pub struct BoundingBox {
|
||||||
pub min_x: f64,
|
pub min_x: f64,
|
||||||
@ -38,6 +37,6 @@ impl BoundingBox {
|
|||||||
let d = f64::max(f64::max(self.min_x - pos.x, pos.x - self.max_x), 0.0);
|
let d = f64::max(f64::max(self.min_x - pos.x, pos.x - self.max_x), 0.0);
|
||||||
let e = f64::max(f64::max(self.min_y - pos.y, pos.y - self.max_y), 0.0);
|
let e = f64::max(f64::max(self.min_y - pos.y, pos.y - self.max_y), 0.0);
|
||||||
let f = f64::max(f64::max(self.min_z - pos.z, pos.z - self.max_z), 0.0);
|
let f = f64::max(f64::max(self.min_z - pos.z, pos.z - self.max_z), 0.0);
|
||||||
super::math::squared_magnitude(d, e, f)
|
super::squared_magnitude(d, e, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,3 +1,8 @@
|
|||||||
|
pub mod boundingbox;
|
||||||
|
pub mod position;
|
||||||
|
pub mod vector2;
|
||||||
|
pub mod vector3;
|
||||||
|
|
||||||
pub fn wrap_degrees(var: f32) -> f32 {
|
pub fn wrap_degrees(var: f32) -> f32 {
|
||||||
let mut var1 = var % 360.0;
|
let mut var1 = var % 360.0;
|
||||||
if var1 >= 180.0 {
|
if var1 >= 180.0 {
|
||||||
@ -14,3 +19,9 @@ pub fn wrap_degrees(var: f32) -> f32 {
|
|||||||
pub fn squared_magnitude(a: f64, b: f64, c: f64) -> f64 {
|
pub fn squared_magnitude(a: f64, b: f64, c: f64) -> f64 {
|
||||||
a * a + b * b + c * c
|
a * a + b * b + c * c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts a world coordinate to the corresponding chunk-section coordinate.
|
||||||
|
// TODO: This proberbly should place not here
|
||||||
|
pub fn get_section_cord(coord: i32) -> i32 {
|
||||||
|
coord >> 4
|
||||||
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
use pumpkin_world::vector3::Vector3;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::vector3::Vector3;
|
||||||
|
|
||||||
|
/// Aka Block Position
|
||||||
pub struct WorldPosition(pub Vector3<i32>);
|
pub struct WorldPosition(pub Vector3<i32>);
|
||||||
|
|
||||||
impl Serialize for WorldPosition {
|
impl Serialize for WorldPosition {
|
||||||
@ -4,5 +4,7 @@ version.workspace = true
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
pumpkin-core = { path = "../pumpkin-core"}
|
||||||
|
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
num-derive = "0.4"
|
num-derive = "0.4"
|
||||||
@ -1,5 +1,8 @@
|
|||||||
use entity_type::EntityType;
|
use entity_type::EntityType;
|
||||||
use pose::EntityPose;
|
use pose::EntityPose;
|
||||||
|
use pumpkin_core::math::{
|
||||||
|
get_section_cord, position::WorldPosition, vector2::Vector2, vector3::Vector3,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod entity_type;
|
pub mod entity_type;
|
||||||
pub mod pose;
|
pub mod pose;
|
||||||
@ -9,12 +12,10 @@ pub type EntityId = i32;
|
|||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
pub entity_id: EntityId,
|
pub entity_id: EntityId,
|
||||||
pub entity_type: EntityType,
|
pub entity_type: EntityType,
|
||||||
pub x: f64,
|
pub pos: Vector3<f64>,
|
||||||
pub y: f64,
|
pub block_pos: WorldPosition,
|
||||||
pub z: f64,
|
pub chunk_pos: Vector2<i32>,
|
||||||
pub lastx: f64,
|
|
||||||
pub lasty: f64,
|
|
||||||
pub lastz: f64,
|
|
||||||
pub yaw: f32,
|
pub yaw: f32,
|
||||||
pub head_yaw: f32,
|
pub head_yaw: f32,
|
||||||
pub pitch: f32,
|
pub pitch: f32,
|
||||||
@ -28,12 +29,9 @@ impl Entity {
|
|||||||
Self {
|
Self {
|
||||||
entity_id,
|
entity_id,
|
||||||
entity_type,
|
entity_type,
|
||||||
x: 0.0,
|
pos: Vector3::new(0.0, 0.0, 0.0),
|
||||||
y: 0.0,
|
block_pos: WorldPosition(Vector3::new(0, 0, 0)),
|
||||||
z: 0.0,
|
chunk_pos: Vector2::new(0, 0),
|
||||||
lastx: 0.0,
|
|
||||||
lasty: 0.0,
|
|
||||||
lastz: 0.0,
|
|
||||||
yaw: 0.0,
|
yaw: 0.0,
|
||||||
head_yaw: 0.0,
|
head_yaw: 0.0,
|
||||||
pitch: 0.0,
|
pitch: 0.0,
|
||||||
@ -41,4 +39,25 @@ impl Entity {
|
|||||||
pose: EntityPose::Standing,
|
pose: EntityPose::Standing,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_pos(&mut self, x: f64, y: f64, z: f64) {
|
||||||
|
if self.pos.x != x || self.pos.y != y || self.pos.z != z {
|
||||||
|
self.pos = Vector3::new(x, y, z);
|
||||||
|
let i = x.floor() as i32;
|
||||||
|
let j = y.floor() as i32;
|
||||||
|
let k = z.floor() as i32;
|
||||||
|
|
||||||
|
let block_pos = self.block_pos.0;
|
||||||
|
if i != block_pos.x || j != block_pos.y || k != block_pos.z {
|
||||||
|
self.block_pos = WorldPosition(Vector3::new(i, j, k));
|
||||||
|
|
||||||
|
if get_section_cord(i) != self.chunk_pos.x
|
||||||
|
|| get_section_cord(k) != self.chunk_pos.z
|
||||||
|
{
|
||||||
|
self.chunk_pos =
|
||||||
|
Vector2::new(get_section_cord(block_pos.x), get_section_cord(block_pos.z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use bytes::BufMut;
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{self, DeserializeOwned, SeqAccess, Visitor},
|
de::{self, DeserializeOwned, SeqAccess, Visitor},
|
||||||
Deserialize, Deserializer, Serialize, Serializer,
|
Deserialize, Deserializer, Serialize, Serializer,
|
||||||
@ -22,19 +23,16 @@ impl Serialize for VarInt {
|
|||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
let mut val = self.0;
|
let mut value = self.0 as u32;
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
let mut buf = Vec::new();
|
||||||
for _ in 0..5 {
|
|
||||||
let mut b: u8 = val as u8 & 0b01111111;
|
while value > 0x7F {
|
||||||
val >>= 7;
|
buf.put_u8(value as u8 | 0x80);
|
||||||
if val != 0 {
|
value >>= 7;
|
||||||
b |= 0b10000000;
|
|
||||||
}
|
|
||||||
buf.push(b);
|
|
||||||
if val == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf.put_u8(value as u8);
|
||||||
|
|
||||||
serializer.serialize_bytes(&buf)
|
serializer.serialize_bytes(&buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
|
use pumpkin_core::math::position::WorldPosition;
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{position::WorldPosition, VarInt};
|
use crate::VarInt;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[packet(0x06)]
|
#[packet(0x06)]
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
|
use pumpkin_core::math::position::WorldPosition;
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{position::WorldPosition, VarInt};
|
use crate::VarInt;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[packet(0x09)]
|
#[packet(0x09)]
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
|
use pumpkin_core::math::position::WorldPosition;
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{position::WorldPosition, VarInt};
|
use crate::VarInt;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[packet(0x2B)]
|
#[packet(0x2B)]
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
|
use pumpkin_core::math::position::WorldPosition;
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::position::WorldPosition;
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[packet(0x28)]
|
#[packet(0x28)]
|
||||||
pub struct CWorldEvent<'a> {
|
pub struct CWorldEvent<'a> {
|
||||||
|
|||||||
@ -8,7 +8,6 @@ pub mod bytebuf;
|
|||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod packet_decoder;
|
pub mod packet_decoder;
|
||||||
pub mod packet_encoder;
|
pub mod packet_encoder;
|
||||||
pub mod position;
|
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod slot;
|
pub mod slot;
|
||||||
pub mod uuid;
|
pub mod uuid;
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
|
use pumpkin_core::math::position::WorldPosition;
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
|
||||||
use crate::{position::WorldPosition, VarInt};
|
use crate::VarInt;
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
#[packet(0x24)]
|
#[packet(0x24)]
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
|
use pumpkin_core::math::position::WorldPosition;
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{position::WorldPosition, VarInt};
|
use crate::VarInt;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[packet(0x38)]
|
#[packet(0x38)]
|
||||||
|
|||||||
@ -4,7 +4,9 @@ version.workspace = true
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# fastanvil = "0.31"
|
pumpkin-core = { path = "../pumpkin-core"}
|
||||||
|
|
||||||
|
|
||||||
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
|
||||||
fastsnbt = "0.2"
|
fastsnbt = "0.2"
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use crate::vector3::Vector3;
|
|
||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
|
|
||||||
pub mod block_id;
|
pub mod block_id;
|
||||||
mod block_registry;
|
mod block_registry;
|
||||||
|
|
||||||
pub use block_id::BlockId;
|
pub use block_id::BlockId;
|
||||||
|
use pumpkin_core::math::vector3::Vector3;
|
||||||
|
|
||||||
#[derive(FromPrimitive)]
|
#[derive(FromPrimitive)]
|
||||||
pub enum BlockFace {
|
pub enum BlockFace {
|
||||||
|
|||||||
@ -3,13 +3,13 @@ use std::collections::HashMap;
|
|||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
|
||||||
use fastnbt::LongArray;
|
use fastnbt::LongArray;
|
||||||
|
use pumpkin_core::math::vector2::Vector2;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
block::BlockId,
|
block::BlockId,
|
||||||
coordinates::{ChunkRelativeBlockCoordinates, Height},
|
coordinates::{ChunkRelativeBlockCoordinates, Height},
|
||||||
level::{ChunkNotGeneratedError, WorldError},
|
level::{ChunkNotGeneratedError, WorldError},
|
||||||
vector2::Vector2,
|
|
||||||
WORLD_HEIGHT,
|
WORLD_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,9 +2,10 @@ use std::ops::Deref;
|
|||||||
|
|
||||||
use derive_more::derive::{AsMut, AsRef, Display, Into};
|
use derive_more::derive::{AsMut, AsRef, Display, Into};
|
||||||
use num_traits::{PrimInt, Signed, Unsigned};
|
use num_traits::{PrimInt, Signed, Unsigned};
|
||||||
|
use pumpkin_core::math::vector2::Vector2;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{vector2::Vector2, WORLD_LOWEST_Y, WORLD_MAX_Y};
|
use crate::{WORLD_LOWEST_Y, WORLD_MAX_Y};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, AsRef, AsMut, Into, Display,
|
Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, AsRef, AsMut, Into, Display,
|
||||||
|
|||||||
83
pumpkin-world/src/cylindrical_chunk_iterator.rs
Normal file
83
pumpkin-world/src/cylindrical_chunk_iterator.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use pumpkin_core::math::vector2::Vector2;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Cylindrical {
|
||||||
|
pub center: Vector2<i32>,
|
||||||
|
pub view_distance: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cylindrical {
|
||||||
|
pub fn new(center: Vector2<i32>, view_distance: i32) -> Self {
|
||||||
|
Self {
|
||||||
|
center,
|
||||||
|
view_distance,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
pub fn for_each_changed_chunk(
|
||||||
|
old_cylindrical: Cylindrical,
|
||||||
|
new_cylindrical: Cylindrical,
|
||||||
|
mut newly_included: impl FnMut(Vector2<i32>),
|
||||||
|
just_removed: impl FnMut(Vector2<i32>),
|
||||||
|
ignore: bool,
|
||||||
|
) {
|
||||||
|
let min_x = old_cylindrical.get_left().min(new_cylindrical.get_left());
|
||||||
|
let max_x = old_cylindrical.get_right().max(new_cylindrical.get_right());
|
||||||
|
let min_z = old_cylindrical
|
||||||
|
.get_bottom()
|
||||||
|
.min(new_cylindrical.get_bottom());
|
||||||
|
let max_z = old_cylindrical.get_top().max(new_cylindrical.get_top());
|
||||||
|
|
||||||
|
for x in min_x..=max_x {
|
||||||
|
for z in min_z..=max_z {
|
||||||
|
// TODO
|
||||||
|
// let old_is_within = if ignore {
|
||||||
|
// false
|
||||||
|
// } else {
|
||||||
|
// old_cylindrical.is_within_distance(x, z)
|
||||||
|
// };
|
||||||
|
// let new_is_within = if ignore {
|
||||||
|
// true
|
||||||
|
// } else {
|
||||||
|
// new_cylindrical.is_within_distance(x, z)
|
||||||
|
// };
|
||||||
|
|
||||||
|
// if old_is_within != new_is_within {
|
||||||
|
// if new_is_within {
|
||||||
|
newly_included(Vector2::new(x, z));
|
||||||
|
// } else {
|
||||||
|
// dbg!("aa");
|
||||||
|
// just_removed(Vector2::new(x, z));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_left(&self) -> i32 {
|
||||||
|
self.center.x - self.view_distance - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_bottom(&self) -> i32 {
|
||||||
|
self.center.z - self.view_distance - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_right(&self) -> i32 {
|
||||||
|
self.center.x + self.view_distance + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_top(&self) -> i32 {
|
||||||
|
self.center.z + self.view_distance + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn is_within_distance(&self, x: i32, z: i32) -> bool {
|
||||||
|
let max_dist_squared = self.view_distance * self.view_distance;
|
||||||
|
let max_dist = self.view_distance as i64;
|
||||||
|
let dist_x = (x - self.center.x).abs().max(0) - (1);
|
||||||
|
let dist_z = (z - self.center.z).abs().max(0) - (1);
|
||||||
|
let dist_squared = dist_x.pow(2) + (max_dist.min(dist_z as i64) as i32).pow(2);
|
||||||
|
dist_squared < max_dist_squared
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,13 +8,13 @@ use std::{
|
|||||||
|
|
||||||
use flate2::{bufread::ZlibDecoder, read::GzDecoder};
|
use flate2::{bufread::ZlibDecoder, read::GzDecoder};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use pumpkin_core::math::vector2::Vector2;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chunk::ChunkData,
|
chunk::ChunkData,
|
||||||
vector2::Vector2,
|
|
||||||
world_gen::{get_world_gen, Seed, WorldGenerator},
|
world_gen::{get_world_gen, Seed, WorldGenerator},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,11 @@ pub mod biome;
|
|||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod chunk;
|
pub mod chunk;
|
||||||
pub mod coordinates;
|
pub mod coordinates;
|
||||||
|
pub mod cylindrical_chunk_iterator;
|
||||||
pub mod dimension;
|
pub mod dimension;
|
||||||
pub mod global_registry;
|
pub mod global_registry;
|
||||||
pub mod item;
|
pub mod item;
|
||||||
pub mod level;
|
pub mod level;
|
||||||
pub mod radial_chunk_iterator;
|
|
||||||
pub mod vector2;
|
|
||||||
pub mod vector3;
|
|
||||||
mod world_gen;
|
mod world_gen;
|
||||||
|
|
||||||
pub const WORLD_HEIGHT: usize = 384;
|
pub const WORLD_HEIGHT: usize = 384;
|
||||||
|
|||||||
@ -1,59 +0,0 @@
|
|||||||
use crate::vector2::Vector2;
|
|
||||||
|
|
||||||
pub struct RadialIterator {
|
|
||||||
radius: u32,
|
|
||||||
direction: usize,
|
|
||||||
current: Vector2<i32>,
|
|
||||||
step_size: i32,
|
|
||||||
steps_taken: u32,
|
|
||||||
steps_in_direction: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RadialIterator {
|
|
||||||
pub fn new(radius: u32) -> Self {
|
|
||||||
RadialIterator {
|
|
||||||
radius,
|
|
||||||
direction: 0,
|
|
||||||
current: Vector2::new(0, 0),
|
|
||||||
step_size: 1,
|
|
||||||
steps_taken: 0,
|
|
||||||
steps_in_direction: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for RadialIterator {
|
|
||||||
type Item = Vector2<i32>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.steps_taken >= self.radius * self.radius * 4 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = self.current;
|
|
||||||
|
|
||||||
self.steps_in_direction += 1;
|
|
||||||
|
|
||||||
// Move in the current direction
|
|
||||||
match self.direction {
|
|
||||||
0 => self.current.x += 1, // East
|
|
||||||
1 => self.current.z += 1, // North
|
|
||||||
2 => self.current.x -= 1, // West
|
|
||||||
3 => self.current.z -= 1, // South
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.steps_in_direction >= self.step_size {
|
|
||||||
self.direction = (self.direction + 1) % 4;
|
|
||||||
self.steps_in_direction = 0;
|
|
||||||
|
|
||||||
// Increase step size after completing two directions
|
|
||||||
if self.direction == 0 || self.direction == 2 {
|
|
||||||
self.step_size += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.steps_taken += 1;
|
|
||||||
Some(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
|
use pumpkin_core::math::vector2::Vector2;
|
||||||
use static_assertions::assert_obj_safe;
|
use static_assertions::assert_obj_safe;
|
||||||
|
|
||||||
use crate::biome::Biome;
|
use crate::biome::Biome;
|
||||||
use crate::block::BlockId;
|
use crate::block::BlockId;
|
||||||
use crate::chunk::ChunkData;
|
use crate::chunk::ChunkData;
|
||||||
use crate::coordinates::{BlockCoordinates, XZBlockCoordinates};
|
use crate::coordinates::{BlockCoordinates, XZBlockCoordinates};
|
||||||
use crate::vector2::Vector2;
|
|
||||||
use crate::world_gen::Seed;
|
use crate::world_gen::Seed;
|
||||||
|
|
||||||
pub trait GeneratorInit {
|
pub trait GeneratorInit {
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
|
use pumpkin_core::math::vector2::Vector2;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chunk::{ChunkBlocks, ChunkData},
|
chunk::{ChunkBlocks, ChunkData},
|
||||||
coordinates::{ChunkRelativeBlockCoordinates, ChunkRelativeXZBlockCoordinates},
|
coordinates::{ChunkRelativeBlockCoordinates, ChunkRelativeXZBlockCoordinates},
|
||||||
vector2::Vector2,
|
|
||||||
WORLD_LOWEST_Y, WORLD_MAX_Y,
|
WORLD_LOWEST_Y, WORLD_MAX_Y,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,7 @@ mod client_packet;
|
|||||||
mod container;
|
mod container;
|
||||||
pub mod player_packet;
|
pub mod player_packet;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct PlayerConfig {
|
pub struct PlayerConfig {
|
||||||
pub locale: String, // 16
|
pub locale: String, // 16
|
||||||
pub view_distance: i8,
|
pub view_distance: i8,
|
||||||
|
|||||||
@ -4,11 +4,15 @@ use crate::{
|
|||||||
commands::{handle_command, CommandSender},
|
commands::{handle_command, CommandSender},
|
||||||
entity::player::{ChatMode, Hand, Player},
|
entity::player::{ChatMode, Hand, Player},
|
||||||
server::Server,
|
server::Server,
|
||||||
util::math::wrap_degrees,
|
world::player_chunker,
|
||||||
};
|
};
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use pumpkin_config::ADVANCED_CONFIG;
|
use pumpkin_config::ADVANCED_CONFIG;
|
||||||
use pumpkin_core::{text::TextComponent, GameMode};
|
use pumpkin_core::{
|
||||||
|
math::{position::WorldPosition, wrap_degrees},
|
||||||
|
text::TextComponent,
|
||||||
|
GameMode,
|
||||||
|
};
|
||||||
use pumpkin_entity::EntityId;
|
use pumpkin_entity::EntityId;
|
||||||
use pumpkin_inventory::WindowType;
|
use pumpkin_inventory::WindowType;
|
||||||
use pumpkin_protocol::server::play::{SCloseContainer, SSetPlayerGround, SUseItem};
|
use pumpkin_protocol::server::play::{SCloseContainer, SSetPlayerGround, SUseItem};
|
||||||
@ -18,7 +22,6 @@ use pumpkin_protocol::{
|
|||||||
CHeadRot, CHurtAnimation, CPingResponse, CPlayerChatMessage, CUpdateEntityPos,
|
CHeadRot, CHurtAnimation, CPingResponse, CPlayerChatMessage, CUpdateEntityPos,
|
||||||
CUpdateEntityPosRot, CUpdateEntityRot, CWorldEvent, FilterType,
|
CUpdateEntityPosRot, CUpdateEntityRot, CWorldEvent, FilterType,
|
||||||
},
|
},
|
||||||
position::WorldPosition,
|
|
||||||
server::play::{
|
server::play::{
|
||||||
Action, ActionType, SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport,
|
Action, ActionType, SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport,
|
||||||
SInteract, SPlayPingRequest, SPlayerAction, SPlayerCommand, SPlayerPosition,
|
SInteract, SPlayPingRequest, SPlayerAction, SPlayerCommand, SPlayerPosition,
|
||||||
@ -46,9 +49,7 @@ impl Player {
|
|||||||
if let Some((id, position)) = self.awaiting_teleport.as_ref() {
|
if let Some((id, position)) = self.awaiting_teleport.as_ref() {
|
||||||
if id == &confirm_teleport.teleport_id {
|
if id == &confirm_teleport.teleport_id {
|
||||||
// we should set the pos now to that we requested in the teleport packet, Is may fixed issues when the client sended position packets while being teleported
|
// we should set the pos now to that we requested in the teleport packet, Is may fixed issues when the client sended position packets while being teleported
|
||||||
self.entity.x = position.x;
|
self.entity.set_pos(position.x, position.y, position.z);
|
||||||
self.entity.y = position.y;
|
|
||||||
self.entity.z = position.z;
|
|
||||||
|
|
||||||
self.awaiting_teleport = None;
|
self.awaiting_teleport = None;
|
||||||
} else {
|
} else {
|
||||||
@ -75,21 +76,24 @@ impl Player {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let entity = &mut self.entity;
|
let entity = &mut self.entity;
|
||||||
entity.lastx = entity.x;
|
self.lastx = entity.pos.x;
|
||||||
entity.lasty = entity.y;
|
self.lasty = entity.pos.y;
|
||||||
entity.lastz = entity.z;
|
self.lastz = entity.pos.z;
|
||||||
entity.x = Self::clamp_horizontal(position.x);
|
entity.set_pos(
|
||||||
entity.y = Self::clamp_vertical(position.feet_y);
|
Self::clamp_horizontal(position.x),
|
||||||
entity.z = Self::clamp_horizontal(position.z);
|
Self::clamp_vertical(position.feet_y),
|
||||||
|
Self::clamp_horizontal(position.z),
|
||||||
|
);
|
||||||
// TODO: teleport when moving > 8 block
|
// TODO: teleport when moving > 8 block
|
||||||
|
|
||||||
// send new position to all other players
|
// send new position to all other players
|
||||||
let on_ground = self.on_ground;
|
let on_ground = self.on_ground;
|
||||||
let entity_id = entity.entity_id;
|
let entity_id = entity.entity_id;
|
||||||
let (x, lastx) = (entity.x, entity.lastx);
|
let (x, lastx) = (entity.pos.x, self.lastx);
|
||||||
let (y, lasty) = (entity.y, entity.lasty);
|
let (y, lasty) = (entity.pos.y, self.lasty);
|
||||||
let (z, lastz) = (entity.z, entity.lastz);
|
let (z, lastz) = (entity.pos.z, self.lastz);
|
||||||
let world = self.world.lock().await;
|
let world = self.world.clone();
|
||||||
|
let world = world.lock().await;
|
||||||
world.broadcast_packet(
|
world.broadcast_packet(
|
||||||
&[&self.client.token],
|
&[&self.client.token],
|
||||||
&CUpdateEntityPos::new(
|
&CUpdateEntityPos::new(
|
||||||
@ -100,6 +104,7 @@ impl Player {
|
|||||||
on_ground,
|
on_ground,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
player_chunker::update_position(&world, self).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_position_rotation(
|
pub async fn handle_position_rotation(
|
||||||
@ -120,25 +125,28 @@ impl Player {
|
|||||||
}
|
}
|
||||||
let entity = &mut self.entity;
|
let entity = &mut self.entity;
|
||||||
|
|
||||||
entity.lastx = entity.x;
|
self.lastx = entity.pos.x;
|
||||||
entity.lasty = entity.y;
|
self.lasty = entity.pos.y;
|
||||||
entity.lastz = entity.z;
|
self.lastz = entity.pos.z;
|
||||||
entity.x = Self::clamp_horizontal(position_rotation.x);
|
entity.set_pos(
|
||||||
entity.y = Self::clamp_vertical(position_rotation.feet_y);
|
Self::clamp_horizontal(position_rotation.x),
|
||||||
entity.z = Self::clamp_horizontal(position_rotation.z);
|
Self::clamp_vertical(position_rotation.feet_y),
|
||||||
|
Self::clamp_horizontal(position_rotation.z),
|
||||||
|
);
|
||||||
entity.yaw = wrap_degrees(position_rotation.yaw) % 360.0;
|
entity.yaw = wrap_degrees(position_rotation.yaw) % 360.0;
|
||||||
entity.pitch = wrap_degrees(position_rotation.pitch).clamp(-90.0, 90.0) % 360.0;
|
entity.pitch = wrap_degrees(position_rotation.pitch).clamp(-90.0, 90.0) % 360.0;
|
||||||
|
|
||||||
// send new position to all other players
|
// send new position to all other players
|
||||||
let on_ground = self.on_ground;
|
let on_ground = self.on_ground;
|
||||||
let entity_id = entity.entity_id;
|
let entity_id = entity.entity_id;
|
||||||
let (x, lastx) = (entity.x, entity.lastx);
|
let (x, lastx) = (entity.pos.x, self.lastx);
|
||||||
let (y, lasty) = (entity.y, entity.lasty);
|
let (y, lasty) = (entity.pos.y, self.lasty);
|
||||||
let (z, lastz) = (entity.z, entity.lastz);
|
let (z, lastz) = (entity.pos.z, self.lastz);
|
||||||
let yaw = modulus(entity.yaw * 256.0 / 360.0, 256.0);
|
let yaw = modulus(entity.yaw * 256.0 / 360.0, 256.0);
|
||||||
let pitch = modulus(entity.pitch * 256.0 / 360.0, 256.0);
|
let pitch = modulus(entity.pitch * 256.0 / 360.0, 256.0);
|
||||||
// let head_yaw = (entity.head_yaw * 256.0 / 360.0).floor();
|
// let head_yaw = (entity.head_yaw * 256.0 / 360.0).floor();
|
||||||
let world = self.world.lock().await;
|
let world = self.world.clone();
|
||||||
|
let world = world.lock().await;
|
||||||
|
|
||||||
world.broadcast_packet(
|
world.broadcast_packet(
|
||||||
&[&self.client.token],
|
&[&self.client.token],
|
||||||
@ -156,6 +164,8 @@ impl Player {
|
|||||||
&[&self.client.token],
|
&[&self.client.token],
|
||||||
&CHeadRot::new(entity_id.into(), yaw as u8),
|
&CHeadRot::new(entity_id.into(), yaw as u8),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
player_chunker::update_position(&world, self).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_rotation(&mut self, _server: &mut Server, rotation: SPlayerRotation) {
|
pub async fn handle_rotation(&mut self, _server: &mut Server, rotation: SPlayerRotation) {
|
||||||
@ -299,7 +309,7 @@ impl Player {
|
|||||||
Hand::from_i32(client_information.main_hand.into()),
|
Hand::from_i32(client_information.main_hand.into()),
|
||||||
ChatMode::from_i32(client_information.chat_mode.into()),
|
ChatMode::from_i32(client_information.chat_mode.into()),
|
||||||
) {
|
) {
|
||||||
self.client.config = Some(PlayerConfig {
|
self.config = PlayerConfig {
|
||||||
locale: client_information.locale,
|
locale: client_information.locale,
|
||||||
view_distance: client_information.view_distance,
|
view_distance: client_information.view_distance,
|
||||||
chat_mode,
|
chat_mode,
|
||||||
@ -308,7 +318,7 @@ impl Player {
|
|||||||
main_hand,
|
main_hand,
|
||||||
text_filtering: client_information.text_filtering,
|
text_filtering: client_information.text_filtering,
|
||||||
server_listing: client_information.server_listing,
|
server_listing: client_information.server_listing,
|
||||||
});
|
};
|
||||||
} else {
|
} else {
|
||||||
self.kick(TextComponent::text("Invalid hand or chat type"))
|
self.kick(TextComponent::text("Invalid hand or chat type"))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,11 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use pumpkin_core::{text::TextComponent, GameMode};
|
use pumpkin_core::{
|
||||||
|
math::{boundingbox::BoundingBox, position::WorldPosition, vector3::Vector3},
|
||||||
|
text::TextComponent,
|
||||||
|
GameMode,
|
||||||
|
};
|
||||||
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, Entity, EntityId};
|
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, Entity, EntityId};
|
||||||
use pumpkin_inventory::player::PlayerInventory;
|
use pumpkin_inventory::player::PlayerInventory;
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
@ -11,7 +15,6 @@ use pumpkin_protocol::{
|
|||||||
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSetEntityMetadata,
|
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSetEntityMetadata,
|
||||||
CSyncPlayerPosition, CSystemChatMessage, Metadata, PlayerAction,
|
CSyncPlayerPosition, CSystemChatMessage, Metadata, PlayerAction,
|
||||||
},
|
},
|
||||||
position::WorldPosition,
|
|
||||||
server::play::{
|
server::play::{
|
||||||
SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract,
|
SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract,
|
||||||
SPlayPingRequest, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation,
|
SPlayPingRequest, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation,
|
||||||
@ -20,12 +23,10 @@ use pumpkin_protocol::{
|
|||||||
},
|
},
|
||||||
ConnectionState, RawPacket, ServerPacket, VarInt,
|
ConnectionState, RawPacket, ServerPacket, VarInt,
|
||||||
};
|
};
|
||||||
use pumpkin_world::vector3::Vector3;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::{authentication::GameProfile, Client},
|
client::{authentication::GameProfile, Client, PlayerConfig},
|
||||||
server::Server,
|
server::Server,
|
||||||
util::boundingbox::BoundingBox,
|
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ pub struct Player {
|
|||||||
pub gameprofile: GameProfile,
|
pub gameprofile: GameProfile,
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
|
pub config: PlayerConfig,
|
||||||
// TODO: Put this into entity
|
// TODO: Put this into entity
|
||||||
pub world: Arc<tokio::sync::Mutex<World>>,
|
pub world: Arc<tokio::sync::Mutex<World>>,
|
||||||
/// Current gamemode
|
/// Current gamemode
|
||||||
@ -67,6 +69,9 @@ pub struct Player {
|
|||||||
/// send `send_abilties_update` when changed
|
/// send `send_abilties_update` when changed
|
||||||
pub abilities: PlayerAbilities,
|
pub abilities: PlayerAbilities,
|
||||||
|
|
||||||
|
pub lastx: f64,
|
||||||
|
pub lasty: f64,
|
||||||
|
pub lastz: f64,
|
||||||
// Client side value, Should be not trusted
|
// Client side value, Should be not trusted
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
|
|
||||||
@ -82,6 +87,8 @@ pub struct Player {
|
|||||||
pub teleport_id_count: i32,
|
pub teleport_id_count: i32,
|
||||||
// Current awaiting teleport id and location, None if did not teleport
|
// Current awaiting teleport id and location, None if did not teleport
|
||||||
pub awaiting_teleport: Option<(VarInt, Vector3<f64>)>,
|
pub awaiting_teleport: Option<(VarInt, Vector3<f64>)>,
|
||||||
|
|
||||||
|
pub watched_section: Vector3<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
@ -103,8 +110,9 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let config = client.config.clone().unwrap_or_default();
|
||||||
Self {
|
Self {
|
||||||
|
config,
|
||||||
gameprofile,
|
gameprofile,
|
||||||
client,
|
client,
|
||||||
entity: Entity::new(entity_id, EntityType::Player, 1.62),
|
entity: Entity::new(entity_id, EntityType::Player, 1.62),
|
||||||
@ -123,6 +131,10 @@ impl Player {
|
|||||||
teleport_id_count: 0,
|
teleport_id_count: 0,
|
||||||
abilities: PlayerAbilities::default(),
|
abilities: PlayerAbilities::default(),
|
||||||
gamemode,
|
gamemode,
|
||||||
|
watched_section: Vector3::new(0, 0, 0),
|
||||||
|
lastx: 0.0,
|
||||||
|
lasty: 0.0,
|
||||||
|
lastz: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,11 +197,11 @@ impl Player {
|
|||||||
assert!(self.sneaking != sneaking);
|
assert!(self.sneaking != sneaking);
|
||||||
self.sneaking = sneaking;
|
self.sneaking = sneaking;
|
||||||
self.set_flag(Self::SNEAKING_FLAG_INDEX, sneaking).await;
|
self.set_flag(Self::SNEAKING_FLAG_INDEX, sneaking).await;
|
||||||
if sneaking {
|
// if sneaking {
|
||||||
self.set_pose(EntityPose::Crouching).await;
|
// self.set_pose(EntityPose::Crouching).await;
|
||||||
} else {
|
// } else {
|
||||||
self.set_pose(EntityPose::Standing).await;
|
// self.set_pose(EntityPose::Standing).await;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_sprinting(&mut self, sprinting: bool) {
|
pub async fn set_sprinting(&mut self, sprinting: bool) {
|
||||||
@ -242,12 +254,10 @@ impl Player {
|
|||||||
self.teleport_id_count = 0;
|
self.teleport_id_count = 0;
|
||||||
}
|
}
|
||||||
let entity = &mut self.entity;
|
let entity = &mut self.entity;
|
||||||
entity.x = x;
|
entity.set_pos(x, y, z);
|
||||||
entity.y = y;
|
self.lastx = x;
|
||||||
entity.z = z;
|
self.lasty = y;
|
||||||
entity.lastx = x;
|
self.lastz = z;
|
||||||
entity.lasty = y;
|
|
||||||
entity.lastz = z;
|
|
||||||
entity.yaw = yaw;
|
entity.yaw = yaw;
|
||||||
entity.pitch = pitch;
|
entity.pitch = pitch;
|
||||||
self.awaiting_teleport = Some((self.teleport_id_count.into(), Vector3::new(x, y, z)));
|
self.awaiting_teleport = Some((self.teleport_id_count.into(), Vector3::new(x, y, z)));
|
||||||
@ -274,9 +284,9 @@ impl Player {
|
|||||||
let d = self.block_interaction_range() + additional_range;
|
let d = self.block_interaction_range() + additional_range;
|
||||||
let box_pos = BoundingBox::from_block(pos);
|
let box_pos = BoundingBox::from_block(pos);
|
||||||
box_pos.squared_magnitude(Vector3 {
|
box_pos.squared_magnitude(Vector3 {
|
||||||
x: self.entity.x,
|
x: self.entity.pos.x,
|
||||||
y: self.entity.y + self.entity.standing_eye_height as f64,
|
y: self.entity.pos.y + self.entity.standing_eye_height as f64,
|
||||||
z: self.entity.z,
|
z: self.entity.pos.z,
|
||||||
}) < d * d
|
}) < d * d
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,13 +451,13 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromPrimitive)]
|
#[derive(FromPrimitive, Clone)]
|
||||||
pub enum Hand {
|
pub enum Hand {
|
||||||
Main,
|
Main,
|
||||||
Off,
|
Off,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromPrimitive)]
|
#[derive(FromPrimitive, Clone)]
|
||||||
pub enum ChatMode {
|
pub enum ChatMode {
|
||||||
Enabled,
|
Enabled,
|
||||||
CommandsOnly,
|
CommandsOnly,
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
pub mod boundingbox;
|
|
||||||
pub mod math;
|
|
||||||
|
|||||||
@ -4,23 +4,25 @@ use std::{
|
|||||||
sync::{Arc, Mutex, MutexGuard},
|
sync::{Arc, Mutex, MutexGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod player_chunker;
|
||||||
|
|
||||||
use mio::Token;
|
use mio::Token;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use pumpkin_config::BasicConfiguration;
|
use pumpkin_config::BasicConfiguration;
|
||||||
|
use pumpkin_core::math::vector2::Vector2;
|
||||||
use pumpkin_entity::{entity_type::EntityType, EntityId};
|
use pumpkin_entity::{entity_type::EntityType, EntityId};
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
client::play::{
|
client::play::{
|
||||||
CCenterChunk, CChunkData, CGameEvent, CLogin, CPlayerAbilities, CPlayerInfoUpdate,
|
CChunkData, CGameEvent, CLogin, CPlayerAbilities, CPlayerInfoUpdate, CRemoveEntities,
|
||||||
CRemoveEntities, CRemovePlayerInfo, CSetEntityMetadata, CSpawnEntity, Metadata,
|
CRemovePlayerInfo, CSetEntityMetadata, CSpawnEntity, Metadata, PlayerAction,
|
||||||
PlayerAction,
|
|
||||||
},
|
},
|
||||||
uuid::UUID,
|
uuid::UUID,
|
||||||
ClientPacket, VarInt,
|
ClientPacket, VarInt,
|
||||||
};
|
};
|
||||||
use pumpkin_world::{level::Level, radial_chunk_iterator::RadialIterator};
|
use pumpkin_world::level::Level;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::entity::player::Player;
|
use crate::{client::Client, entity::player::Player};
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
pub level: Arc<Mutex<Level>>,
|
pub level: Arc<Mutex<Level>>,
|
||||||
@ -90,7 +92,7 @@ impl World {
|
|||||||
// TODO: this is for debug purpose, remove later
|
// TODO: this is for debug purpose, remove later
|
||||||
player
|
player
|
||||||
.client
|
.client
|
||||||
.send_packet(&CPlayerAbilities::new(0x02, 0.1, 0.1));
|
.send_packet(&CPlayerAbilities::new(0x02, 0.4, 0.1));
|
||||||
|
|
||||||
// teleport
|
// teleport
|
||||||
let x = 10.0;
|
let x = 10.0;
|
||||||
@ -191,12 +193,12 @@ impl World {
|
|||||||
existing_player.entity_id().into(),
|
existing_player.entity_id().into(),
|
||||||
UUID(gameprofile.id),
|
UUID(gameprofile.id),
|
||||||
(EntityType::Player as i32).into(),
|
(EntityType::Player as i32).into(),
|
||||||
entity.x,
|
entity.pos.x,
|
||||||
entity.y,
|
entity.pos.y,
|
||||||
entity.z,
|
entity.pos.z,
|
||||||
entity.yaw,
|
entity.yaw,
|
||||||
entity.pitch,
|
entity.pitch,
|
||||||
entity.pitch,
|
entity.head_yaw,
|
||||||
0.into(),
|
0.into(),
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
@ -214,26 +216,28 @@ impl World {
|
|||||||
self.broadcast_packet(&[&player.client.token], &packet)
|
self.broadcast_packet(&[&player.client.token], &packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.spawn_test_chunk(player, base_config.view_distance as u32)
|
// Spawn in inital chunks
|
||||||
.await;
|
player_chunker::player_join(self, player).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn spawn_test_chunk(&self, player: &mut Player, distance: u32) {
|
async fn spawn_world_chunks(
|
||||||
|
&self,
|
||||||
|
client: &mut Client,
|
||||||
|
chunks: Vec<Vector2<i32>>,
|
||||||
|
distance: i32,
|
||||||
|
) {
|
||||||
let inst = std::time::Instant::now();
|
let inst = std::time::Instant::now();
|
||||||
let (sender, mut chunk_receiver) = mpsc::channel(distance as usize);
|
let (sender, mut chunk_receiver) = mpsc::channel(distance as usize);
|
||||||
|
|
||||||
let chunks: Vec<_> = RadialIterator::new(distance).collect();
|
|
||||||
let level = self.level.clone();
|
let level = self.level.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
level.lock().unwrap().fetch_chunks(&chunks, sender);
|
level.lock().unwrap().fetch_chunks(&chunks, sender);
|
||||||
});
|
});
|
||||||
|
|
||||||
player.client.send_packet(&CCenterChunk {
|
|
||||||
chunk_x: 0.into(),
|
|
||||||
chunk_z: 0.into(),
|
|
||||||
});
|
|
||||||
|
|
||||||
while let Some(chunk_data) = chunk_receiver.recv().await {
|
while let Some(chunk_data) = chunk_receiver.recv().await {
|
||||||
|
if client.closed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// dbg!(chunk_pos);
|
// dbg!(chunk_pos);
|
||||||
let chunk_data = match chunk_data {
|
let chunk_data = match chunk_data {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
@ -252,10 +256,9 @@ impl World {
|
|||||||
len / (1024 * 1024)
|
len / (1024 * 1024)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
player.client.send_packet(&CChunkData(&chunk_data));
|
client.send_packet(&CChunkData(&chunk_data));
|
||||||
}
|
}
|
||||||
let t = inst.elapsed();
|
dbg!("DONE CHUNKS", inst.elapsed());
|
||||||
dbg!("DONE", t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: This definitly should be in world
|
/// TODO: This definitly should be in world
|
||||||
@ -283,12 +286,10 @@ impl World {
|
|||||||
// todo: put this into the entitiy struct
|
// todo: put this into the entitiy struct
|
||||||
let id = player.entity_id();
|
let id = player.entity_id();
|
||||||
let uuid = player.gameprofile.id;
|
let uuid = player.gameprofile.id;
|
||||||
dbg!("1");
|
|
||||||
self.broadcast_packet(
|
self.broadcast_packet(
|
||||||
&[&player.client.token],
|
&[&player.client.token],
|
||||||
&CRemovePlayerInfo::new(1.into(), &[UUID(uuid)]),
|
&CRemovePlayerInfo::new(1.into(), &[UUID(uuid)]),
|
||||||
);
|
);
|
||||||
dbg!("2");
|
|
||||||
self.broadcast_packet(&[&player.client.token], &CRemoveEntities::new(&[id.into()]))
|
self.broadcast_packet(&[&player.client.token], &CRemoveEntities::new(&[id.into()]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
102
pumpkin/src/world/player_chunker.rs
Normal file
102
pumpkin/src/world/player_chunker.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
use super::World;
|
||||||
|
|
||||||
|
fn get_view_distance(player: &Player) -> i8 {
|
||||||
|
player
|
||||||
|
.config
|
||||||
|
.view_distance
|
||||||
|
.clamp(2, BASIC_CONFIG.view_distance as i8)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn player_join(world: &World, player: &mut Player) {
|
||||||
|
let new_watched = chunk_section_from_pos(&player.entity.block_pos);
|
||||||
|
player.watched_section = new_watched;
|
||||||
|
let chunk_pos = player.entity.chunk_pos;
|
||||||
|
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(player.watched_section.x, player.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(&mut player.client, loading_chunks, view_distance)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_position(world: &World, player: &mut Player) {
|
||||||
|
let current_watched = player.watched_section;
|
||||||
|
let new_watched = chunk_section_from_pos(&player.entity.block_pos);
|
||||||
|
if current_watched != new_watched {
|
||||||
|
let chunk_pos = player.entity.chunk_pos;
|
||||||
|
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(player.watched_section.x, player.watched_section.z),
|
||||||
|
view_distance,
|
||||||
|
);
|
||||||
|
let new_cylindrical =
|
||||||
|
Cylindrical::new(Vector2::new(chunk_pos.x, chunk_pos.z), view_distance);
|
||||||
|
player.watched_section = 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() {
|
||||||
|
world
|
||||||
|
.spawn_world_chunks(&mut player.client, loading_chunks, view_distance)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user