chore: add uuid to world
This commit is contained in:
parent
67fc80439d
commit
452d8c413b
@ -1,10 +1,16 @@
|
|||||||
|
use std::fmt::Formatter;
|
||||||
|
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
VarInt,
|
VarInt,
|
||||||
ser::{NetworkWriteExt, WritingError},
|
ser::{NetworkWriteExt, ReadingError, WritingError},
|
||||||
|
};
|
||||||
|
use serde::{
|
||||||
|
Deserializer, Serialize,
|
||||||
|
de::{self, Visitor},
|
||||||
|
ser::Serializer,
|
||||||
};
|
};
|
||||||
use serde::{Serialize, ser::Serializer};
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Velocity(pub Vector3<f64>);
|
pub struct Velocity(pub Vector3<f64>);
|
||||||
@ -58,6 +64,52 @@ impl Velocity {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read<R: std::io::Read>(reader: &mut R) -> Result<Self, ReadingError> {
|
||||||
|
let mut low_16 = [0u8; 2];
|
||||||
|
reader
|
||||||
|
.read_exact(&mut low_16)
|
||||||
|
.map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||||
|
|
||||||
|
if low_16[0] == 0 && low_16[1] == 0 {
|
||||||
|
return Ok(Self(Vector3::new(0.0, 0.0, 0.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mid_32 = [0u8; 4];
|
||||||
|
reader
|
||||||
|
.read_exact(&mut mid_32)
|
||||||
|
.map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||||
|
|
||||||
|
let low = u16::from_le_bytes(low_16) as i64;
|
||||||
|
let mid = i32::from_be_bytes(mid_32) as i64;
|
||||||
|
let packed_data = low | (mid << 16);
|
||||||
|
|
||||||
|
let header = packed_data & 0x07;
|
||||||
|
let is_extended = (header & 4) != 0;
|
||||||
|
|
||||||
|
let scale_factor = if is_extended {
|
||||||
|
let scale_tail = VarInt::decode(reader)?;
|
||||||
|
((scale_tail.0 as i64) << 2) | (header & 3)
|
||||||
|
} else {
|
||||||
|
header & 3
|
||||||
|
};
|
||||||
|
|
||||||
|
if scale_factor == 0 && !is_extended {
|
||||||
|
return Ok(Self(Vector3::new(0.0, 0.0, 0.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let q_x = (packed_data >> 3) & 0x7FFF;
|
||||||
|
let q_y = (packed_data >> 18) & 0x7FFF;
|
||||||
|
let q_z = (packed_data >> 33) & 0x7FFF;
|
||||||
|
|
||||||
|
let scale = scale_factor as f64;
|
||||||
|
|
||||||
|
Ok(Self(Vector3::new(
|
||||||
|
from_long(q_x, scale),
|
||||||
|
from_long(q_y, scale),
|
||||||
|
from_long(q_z, scale),
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_VELOCITY_CLAMP: f64 = 1.717_986_918_3E10;
|
const MAX_VELOCITY_CLAMP: f64 = 1.717_986_918_3E10;
|
||||||
@ -79,6 +131,12 @@ fn to_long(value: f64) -> i64 {
|
|||||||
((value.mul_add(0.5, 0.5) * MAX_15_BIT_VALUE).round() as i64).clamp(0, 32766)
|
((value.mul_add(0.5, 0.5) * MAX_15_BIT_VALUE).round() as i64).clamp(0, 32766)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_long(quantized: i64, scale: f64) -> f64 {
|
||||||
|
// Reverse: ((v * 0.5 + 0.5) * 32766) -> v
|
||||||
|
let normalized = (quantized as f64 / MAX_15_BIT_VALUE) - 0.5;
|
||||||
|
(normalized / 0.5) * scale
|
||||||
|
}
|
||||||
|
|
||||||
impl Serialize for Velocity {
|
impl Serialize for Velocity {
|
||||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
@ -86,3 +144,30 @@ impl Serialize for Velocity {
|
|||||||
serializer.serialize_bytes(&buf)
|
serializer.serialize_bytes(&buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> de::Deserialize<'de> for Velocity {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct VelocityVisitor;
|
||||||
|
|
||||||
|
impl Visitor<'_> for VelocityVisitor {
|
||||||
|
type Value = Velocity;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("a byte array representing bit-packed velocity")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
let mut cursor = std::io::Cursor::new(v);
|
||||||
|
Velocity::read(&mut cursor).map_err(de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_bytes(VelocityVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use pumpkin_data::packet::clientbound::PLAY_SET_ENTITY_MOTION;
|
use pumpkin_data::packet::clientbound::PLAY_SET_ENTITY_MOTION;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use serde::Serialize;
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{VarInt, codec::velocity::Velocity};
|
use crate::{VarInt, codec::velocity::Velocity};
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ use crate::{VarInt, codec::velocity::Velocity};
|
|||||||
///
|
///
|
||||||
/// This packet informs the client of a sudden change in an entity's movement,
|
/// This packet informs the client of a sudden change in an entity's movement,
|
||||||
/// such as knockback from an attack, explosions, or being launched by a piston.
|
/// such as knockback from an attack, explosions, or being launched by a piston.
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[java_packet(PLAY_SET_ENTITY_MOTION)]
|
#[java_packet(PLAY_SET_ENTITY_MOTION)]
|
||||||
pub struct CEntityVelocity {
|
pub struct CEntityVelocity {
|
||||||
/// The Entity ID of the entity whose velocity is being set
|
/// The Entity ID of the entity whose velocity is being set
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use pumpkin_data::packet::clientbound::PLAY_LOGIN;
|
|||||||
use pumpkin_util::{math::position::BlockPos, resource_location::ResourceLocation};
|
use pumpkin_util::{math::position::BlockPos, resource_location::ResourceLocation};
|
||||||
|
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use serde::Serialize;
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -12,14 +12,14 @@ use crate::VarInt;
|
|||||||
/// This is one of the largest and most important packets in the protocol. It
|
/// This is one of the largest and most important packets in the protocol. It
|
||||||
/// initializes the player's world view, dimension settings, and local game
|
/// initializes the player's world view, dimension settings, and local game
|
||||||
/// rules. Once received, the client begins rendering the world.
|
/// rules. Once received, the client begins rendering the world.
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[java_packet(PLAY_LOGIN)]
|
#[java_packet(PLAY_LOGIN)]
|
||||||
pub struct CLogin<'a> {
|
pub struct CLogin {
|
||||||
/// The unique ID assigned to the player for the current session.
|
/// The unique ID assigned to the player for the current session.
|
||||||
pub entity_id: i32,
|
pub entity_id: i32,
|
||||||
pub is_hardcore: bool,
|
pub is_hardcore: bool,
|
||||||
/// A list of all dimensions present on the server (e.g., overworld, nether, end).
|
/// A list of all dimensions present on the server (e.g., overworld, nether, end).
|
||||||
pub dimension_names: &'a [ResourceLocation],
|
pub dimension_names: Vec<ResourceLocation>,
|
||||||
pub max_players: VarInt,
|
pub max_players: VarInt,
|
||||||
/// The number of chunks the client will render in each direction.
|
/// The number of chunks the client will render in each direction.
|
||||||
pub view_distance: VarInt,
|
pub view_distance: VarInt,
|
||||||
@ -52,14 +52,14 @@ pub struct CLogin<'a> {
|
|||||||
pub enforce_secure_chat: bool,
|
pub enforce_secure_chat: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CLogin<'a> {
|
impl CLogin {
|
||||||
#[expect(clippy::too_many_arguments)]
|
#[expect(clippy::too_many_arguments)]
|
||||||
#[expect(clippy::fn_params_excessive_bools)]
|
#[expect(clippy::fn_params_excessive_bools)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
entity_id: i32,
|
entity_id: i32,
|
||||||
is_hardcore: bool,
|
is_hardcore: bool,
|
||||||
dimension_names: &'a [ResourceLocation],
|
dimension_names: Vec<ResourceLocation>,
|
||||||
max_players: VarInt,
|
max_players: VarInt,
|
||||||
view_distance: VarInt,
|
view_distance: VarInt,
|
||||||
simulated_distance: VarInt,
|
simulated_distance: VarInt,
|
||||||
|
|||||||
@ -165,6 +165,8 @@ impl PumpkinError for GetBlockError {
|
|||||||
/// - Stores and tracks active `Player` entities within the world.
|
/// - Stores and tracks active `Player` entities within the world.
|
||||||
/// - Provides a central hub for interacting with the world's entities and environment.
|
/// - Provides a central hub for interacting with the world's entities and environment.
|
||||||
pub struct World {
|
pub struct World {
|
||||||
|
/// Represents the World's Unique Identifier
|
||||||
|
pub uuid: Uuid,
|
||||||
/// The underlying level, responsible for chunk management and terrain generation.
|
/// The underlying level, responsible for chunk management and terrain generation.
|
||||||
pub level: Arc<Level>,
|
pub level: Arc<Level>,
|
||||||
pub level_info: Arc<ArcSwap<LevelData>>,
|
pub level_info: Arc<ArcSwap<LevelData>>,
|
||||||
@ -197,6 +199,14 @@ pub struct World {
|
|||||||
pub portal_poi: Mutex<portal::PortalPoiStorage>,
|
pub portal_poi: Mutex<portal::PortalPoiStorage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for World {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.uuid == other.uuid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for World {}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn load(
|
pub fn load(
|
||||||
@ -213,6 +223,7 @@ impl World {
|
|||||||
let portal_poi = portal::PortalPoiStorage::new(&level.level_folder.root_folder);
|
let portal_poi = portal::PortalPoiStorage::new(&level.level_folder.root_folder);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
uuid: Uuid::new_v4(),
|
||||||
level,
|
level,
|
||||||
level_info,
|
level_info,
|
||||||
players: ArcSwap::new(Arc::new(Vec::new())),
|
players: ArcSwap::new(Arc::new(Vec::new())),
|
||||||
@ -1445,7 +1456,7 @@ impl World {
|
|||||||
.send_packet_now(&CLogin::new(
|
.send_packet_now(&CLogin::new(
|
||||||
entity_id,
|
entity_id,
|
||||||
base_config.hardcore,
|
base_config.hardcore,
|
||||||
&dimensions,
|
dimensions,
|
||||||
base_config.max_players.try_into().unwrap(),
|
base_config.max_players.try_into().unwrap(),
|
||||||
base_config.view_distance.get().into(), // TODO: view distance
|
base_config.view_distance.get().into(), // TODO: view distance
|
||||||
base_config.simulation_distance.get().into(), // TODO: sim view dinstance
|
base_config.simulation_distance.get().into(), // TODO: sim view dinstance
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user