chore(mappings): add 1.7 & 1.8

This commit is contained in:
Alexander Medvedev
2026-07-25 16:48:20 +02:00
parent 40d7ed052f
commit faf8c50d80
38 changed files with 593 additions and 132 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -59,7 +59,7 @@ pub(crate) fn build() -> TokenStream {
use pumpkin_util::version::JavaMinecraftVersion;
pub const CURRENT_MC_VERSION: JavaMinecraftVersion = #LATEST_VERSION;
pub const LOWEST_SUPPORTED_MC_VERSION: JavaMinecraftVersion = JavaMinecraftVersion::V_1_20_5;
pub const LOWEST_SUPPORTED_MC_VERSION: JavaMinecraftVersion = JavaMinecraftVersion::V_1_7_2;
#packet_id_struct

View File

@@ -7,10 +7,30 @@ use crate::version::JavaMinecraftVersion;
/// Generates the `TokenStream` for per-version block-state remap tables and the
/// `remap_block_state_for_version` function.
pub fn build() -> TokenStream {
let node_1_7_2 = MappingNode {
version: JavaMinecraftVersion::V_1_7_2,
value: "../assets/viabackwards/data/mappings-1.7.6to1.7.2.nbt",
child: None,
};
let node_1_7_6 = MappingNode {
version: JavaMinecraftVersion::V_1_7_6,
value: "../assets/viarewind/data/mappings-1.8to1.7.10.nbt",
child: Some(&node_1_7_2),
};
let node_1_8 = MappingNode {
version: JavaMinecraftVersion::V_1_8,
value: "../assets/viarewind/data/mappings-1.9.4to1.8.nbt",
child: Some(&node_1_7_6),
};
let node_1_9 = MappingNode {
version: JavaMinecraftVersion::V_1_9,
value: "../assets/viabackwards/data/mappings-1.10to1.9.4.nbt",
child: Some(&node_1_8),
};
let node_1_10 = MappingNode {
version: JavaMinecraftVersion::V_1_10,
value: "../assets/viabackwards/data/mappings-1.11to1.10.nbt",
child: None,
child: Some(&node_1_9),
};
let node_1_11 = MappingNode {
version: JavaMinecraftVersion::V_1_11,

View File

@@ -7,10 +7,30 @@ use crate::version::JavaMinecraftVersion;
/// Generates the `TokenStream` for per-version entity ID remap tables and the
/// `remap_entity_id_for_version` function.
pub fn build() -> TokenStream {
let node_1_7_2 = MappingNode {
version: JavaMinecraftVersion::V_1_7_2,
value: "../assets/viabackwards/data/mappings-1.7.6to1.7.2.nbt",
child: None,
};
let node_1_7_6 = MappingNode {
version: JavaMinecraftVersion::V_1_7_6,
value: "../assets/viarewind/data/mappings-1.8to1.7.10.nbt",
child: Some(&node_1_7_2),
};
let node_1_8 = MappingNode {
version: JavaMinecraftVersion::V_1_8,
value: "../assets/viarewind/data/mappings-1.9.4to1.8.nbt",
child: Some(&node_1_7_6),
};
let node_1_9 = MappingNode {
version: JavaMinecraftVersion::V_1_9,
value: "../assets/viabackwards/data/mappings-1.10to1.9.4.nbt",
child: Some(&node_1_8),
};
let node_1_10 = MappingNode {
version: JavaMinecraftVersion::V_1_10,
value: "../assets/viabackwards/data/mappings-1.11to1.10.nbt",
child: None,
child: Some(&node_1_9),
};
let node_1_11 = MappingNode {
version: JavaMinecraftVersion::V_1_11,

View File

@@ -9,10 +9,30 @@ use crate::version::JavaMinecraftVersion;
pub fn build() -> TokenStream {
// ViaBackwards mappings go new → old (26.1 → 1.21.11 → ... → 1.20.5)
// This is the correct direction for a new server sending to old clients.
let node_1_7_2 = MappingNode {
version: JavaMinecraftVersion::V_1_7_2,
value: "../assets/viabackwards/data/mappings-1.7.6to1.7.2.nbt",
child: None,
};
let node_1_7_6 = MappingNode {
version: JavaMinecraftVersion::V_1_7_6,
value: "../assets/viarewind/data/mappings-1.8to1.7.10.nbt",
child: Some(&node_1_7_2),
};
let node_1_8 = MappingNode {
version: JavaMinecraftVersion::V_1_8,
value: "../assets/viarewind/data/mappings-1.9.4to1.8.nbt",
child: Some(&node_1_7_6),
};
let node_1_9 = MappingNode {
version: JavaMinecraftVersion::V_1_9,
value: "../assets/viabackwards/data/mappings-1.10to1.9.4.nbt",
child: Some(&node_1_8),
};
let node_1_10 = MappingNode {
version: JavaMinecraftVersion::V_1_10,
value: "../assets/viabackwards/data/mappings-1.11to1.10.nbt",
child: None,
child: Some(&node_1_9),
};
let node_1_11 = MappingNode {
version: JavaMinecraftVersion::V_1_11,

View File

@@ -7,10 +7,30 @@ use crate::version::JavaMinecraftVersion;
/// Generates the `TokenStream` for per-version particle ID remap tables and the
/// `remap_particle_id_for_version` function.
pub fn build() -> TokenStream {
let node_1_7_2 = MappingNode {
version: JavaMinecraftVersion::V_1_7_2,
value: "../assets/viabackwards/data/mappings-1.7.6to1.7.2.nbt",
child: None,
};
let node_1_7_6 = MappingNode {
version: JavaMinecraftVersion::V_1_7_6,
value: "../assets/viarewind/data/mappings-1.8to1.7.10.nbt",
child: Some(&node_1_7_2),
};
let node_1_8 = MappingNode {
version: JavaMinecraftVersion::V_1_8,
value: "../assets/viarewind/data/mappings-1.9.4to1.8.nbt",
child: Some(&node_1_7_6),
};
let node_1_9 = MappingNode {
version: JavaMinecraftVersion::V_1_9,
value: "../assets/viabackwards/data/mappings-1.10to1.9.4.nbt",
child: Some(&node_1_8),
};
let node_1_10 = MappingNode {
version: JavaMinecraftVersion::V_1_10,
value: "../assets/viabackwards/data/mappings-1.11to1.10.nbt",
child: None,
child: Some(&node_1_9),
};
let node_1_11 = MappingNode {
version: JavaMinecraftVersion::V_1_11,

View File

@@ -7,10 +7,30 @@ use crate::version::JavaMinecraftVersion;
/// Generates the `TokenStream` for per-version sound ID remap tables and the
/// `remap_sound_id_for_version` function.
pub fn build() -> TokenStream {
let node_1_7_2 = MappingNode {
version: JavaMinecraftVersion::V_1_7_2,
value: "../assets/viabackwards/data/mappings-1.7.6to1.7.2.nbt",
child: None,
};
let node_1_7_6 = MappingNode {
version: JavaMinecraftVersion::V_1_7_6,
value: "../assets/viarewind/data/mappings-1.8to1.7.10.nbt",
child: Some(&node_1_7_2),
};
let node_1_8 = MappingNode {
version: JavaMinecraftVersion::V_1_8,
value: "../assets/viarewind/data/mappings-1.9.4to1.8.nbt",
child: Some(&node_1_7_6),
};
let node_1_9 = MappingNode {
version: JavaMinecraftVersion::V_1_9,
value: "../assets/viabackwards/data/mappings-1.10to1.9.4.nbt",
child: Some(&node_1_8),
};
let node_1_10 = MappingNode {
version: JavaMinecraftVersion::V_1_10,
value: "../assets/viabackwards/data/mappings-1.11to1.10.nbt",
child: None,
child: Some(&node_1_9),
};
let node_1_11 = MappingNode {
version: JavaMinecraftVersion::V_1_11,

View File

@@ -0,0 +1,28 @@
use pumpkin_data::packet::clientbound::CONFIG_UPDATE_ENABLED_FEATURES;
use pumpkin_macros::java_packet;
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
use crate::{ClientPacket, ser::NetworkWriteExt};
#[java_packet(CONFIG_UPDATE_ENABLED_FEATURES)]
pub struct CFeatureFlags<'a> {
pub features: &'a [ResourceLocation],
}
impl<'a> CFeatureFlags<'a> {
#[must_use]
pub const fn new(features: &'a [ResourceLocation]) -> Self {
Self { features }
}
}
impl ClientPacket for CFeatureFlags<'_> {
fn write_packet_data(
&self,
mut write: impl std::io::Write,
_version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
write.write_list(self.features, |write, feature| write.write_string(feature))?;
Ok(())
}
}

View File

@@ -16,3 +16,12 @@ impl ClientPacket for CFinishConfig {
Ok(())
}
}
impl<'a> crate::ServerPacket<'a> for CFinishConfig {
fn read(
_bytebuf: &mut &'a [u8],
_version: &JavaMinecraftVersion,
) -> Result<Self, crate::ser::ReadingError> {
Ok(Self)
}
}

View File

@@ -2,6 +2,7 @@ mod add_resource_pack;
mod clear_dialog;
mod config_disconnect;
mod cookie_request;
mod feature_flags;
mod finish_config;
mod known_packs;
mod plugin_message;
@@ -16,6 +17,7 @@ pub use add_resource_pack::*;
pub use clear_dialog::*;
pub use config_disconnect::*;
pub use cookie_request::*;
pub use feature_flags::*;
pub use finish_config::*;
pub use known_packs::*;
pub use plugin_message::*;

View File

@@ -46,14 +46,16 @@ impl ClientPacket for CEncryptionRequest<'_> {
fn write_packet_data(
&self,
mut write: impl std::io::Write,
_version: &JavaMinecraftVersion,
version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
write.write_string(self.server_id)?;
write.write_var_int(&crate::VarInt(self.public_key.len() as i32))?;
write.write_all(self.public_key)?;
write.write_var_int(&crate::VarInt(self.verify_token.len() as i32))?;
write.write_all(self.verify_token)?;
write.write_bool(self.should_authenticate)?;
if version >= &JavaMinecraftVersion::V_1_19 {
write.write_bool(self.should_authenticate)?;
}
Ok(())
}
}

View File

@@ -32,3 +32,15 @@ impl ClientPacket for CLoginDisconnect {
Ok(())
}
}
impl<'a> crate::ServerPacket<'a> for CLoginDisconnect {
fn read(
bytebuf: &mut &'a [u8],
_version: &JavaMinecraftVersion,
) -> Result<Self, crate::ser::ReadingError> {
use crate::ser::NetworkReadExt;
Ok(Self {
json_reason: bytebuf.get_str()?.into_string(),
})
}
}

View File

@@ -57,12 +57,19 @@ impl ClientPacket for CLoginSuccess<'_> {
mut write: impl std::io::Write,
version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
write.write_uuid(self.uuid)?;
if version < &JavaMinecraftVersion::V_1_16 {
write.write_string(&self.uuid.to_string())?;
} else {
write.write_uuid(self.uuid)?;
}
write.write_string(self.username)?;
write.write_list(self.properties, |write, property| property.write(write))?;
if version < &JavaMinecraftVersion::V_1_21_2 {
if version >= &JavaMinecraftVersion::V_1_19 {
write.write_list(self.properties, |write, property| property.write(write))?;
}
if version >= &JavaMinecraftVersion::V_1_20_2 && version < &JavaMinecraftVersion::V_1_21_2 {
write.write_bool(self.strict_error_handling)?;
} else if version >= &JavaMinecraftVersion::V_26_2 {
}
if version >= &JavaMinecraftVersion::V_26_2 {
write.write_uuid(&self.session_id)?;
}
Ok(())

View File

@@ -81,18 +81,36 @@ impl ClientPacket for CLogin<'_> {
) -> Result<(), WritingError> {
write.write_i32_be(self.entity_id)?;
write.write_bool(self.is_hardcore)?;
write.write_list(self.dimension_names, |write, dim| write.write_string(dim))?;
write.write_var_int(&self.max_players)?;
write.write_var_int(&self.view_distance)?;
write.write_var_int(&self.simulated_distance)?;
write.write_bool(self.reduced_debug_info)?;
write.write_bool(self.enabled_respawn_screen)?;
write.write_bool(self.limited_crafting)?;
if version >= &JavaMinecraftVersion::V_1_16 {
write.write_list(self.dimension_names, |write, dim| write.write_string(dim))?;
}
if version >= &JavaMinecraftVersion::V_1_16 {
write.write_var_int(&self.max_players)?;
} else {
write.write_u8(self.max_players.0 as u8)?;
}
if version >= &JavaMinecraftVersion::V_1_14 {
write.write_var_int(&self.view_distance)?;
}
if version >= &JavaMinecraftVersion::V_1_18 {
write.write_var_int(&self.simulated_distance)?;
}
if version >= &JavaMinecraftVersion::V_1_8 {
write.write_bool(self.reduced_debug_info)?;
}
if version >= &JavaMinecraftVersion::V_1_15 {
write.write_bool(self.enabled_respawn_screen)?;
}
if version >= &JavaMinecraftVersion::V_1_19_3 {
write.write_bool(self.limited_crafting)?;
}
self.spawn_data.write_packet_data(&mut write, version)?;
if version >= &JavaMinecraftVersion::V_26_2 {
write.write_bool(self.online_mode)?;
}
write.write_bool(self.enforce_secure_chat)?;
if version >= &JavaMinecraftVersion::V_1_19_1 {
write.write_bool(self.enforce_secure_chat)?;
}
Ok(())
}
}

View File

@@ -69,7 +69,6 @@ impl ClientPacket for CPlayerPosition {
write.write_f64_be(self.delta.z)?;
write.write_f32_be(self.yaw)?;
write.write_f32_be(self.pitch)?;
// not sure about that
write.write_i32_be(PositionFlag::get_bitfield(self.relatives.as_slice()))?;
} else {
write.write_f64_be(self.position.x)?;
@@ -77,8 +76,14 @@ impl ClientPacket for CPlayerPosition {
write.write_f64_be(self.position.z)?;
write.write_f32_be(self.yaw)?;
write.write_f32_be(self.pitch)?;
write.write_u8(PositionFlag::get_bitfield(self.relatives.as_slice()) as u8)?;
write.write_var_int(&self.teleport_id)?;
if version >= &JavaMinecraftVersion::V_1_19_4 {
write.write_i32_be(PositionFlag::get_bitfield(self.relatives.as_slice()))?;
} else {
write.write_u8(PositionFlag::get_bitfield(self.relatives.as_slice()) as u8)?;
}
if version >= &JavaMinecraftVersion::V_1_9 {
write.write_var_int(&self.teleport_id)?;
}
}
Ok(())
}

View File

@@ -61,8 +61,12 @@ impl PlayerSpawnData {
) -> Result<(), WritingError> {
if version >= &JavaMinecraftVersion::V_1_21_2 {
write.write_var_int(&VarInt(self.dimension.id as i32))?;
} else if version >= &JavaMinecraftVersion::V_1_16 {
write.write_string(self.dimension.minecraft_name)?;
} else if version >= &JavaMinecraftVersion::V_1_9 {
write.write_i32_be(self.dimension.id as i32)?;
} else {
write.write_string("")?;
write.write_i8(self.dimension.id as i8)?;
}
write.write_string(self.dimension.minecraft_name)?;
write.write_i64_be(self.hashed_seed)?;
@@ -70,12 +74,16 @@ impl PlayerSpawnData {
write.write_i8(self.previous_gamemode)?;
write.write_bool(self.debug)?;
write.write_bool(self.is_flat)?;
write.write_option(&self.death_dimension_name, |write, (dim, pos)| {
write.write_string(dim)?;
write.write_block_pos(pos)?;
Ok(())
})?;
write.write_var_int(&self.portal_cooldown)?;
if version >= &JavaMinecraftVersion::V_1_19 {
write.write_option(&self.death_dimension_name, |write, (dim, pos)| {
write.write_string(dim)?;
write.write_block_pos(pos)?;
Ok(())
})?;
}
if version >= &JavaMinecraftVersion::V_1_20 {
write.write_var_int(&self.portal_cooldown)?;
}
if version >= &JavaMinecraftVersion::V_1_21_2 {
write.write_var_int(&self.sealevel)?;
}

View File

@@ -35,3 +35,15 @@ impl ClientPacket for CPingResponse {
Ok(())
}
}
impl<'a> crate::ServerPacket<'a> for CPingResponse {
fn read(
bytebuf: &mut &'a [u8],
_version: &JavaMinecraftVersion,
) -> Result<Self, crate::ser::ReadingError> {
use crate::ser::NetworkReadExt;
Ok(Self {
payload: bytebuf.get_i64_be()?,
})
}
}

View File

@@ -34,3 +34,15 @@ impl ClientPacket for CStatusResponse {
Ok(())
}
}
impl<'a> crate::ServerPacket<'a> for CStatusResponse {
fn read(
bytebuf: &mut &'a [u8],
_version: &JavaMinecraftVersion,
) -> Result<Self, crate::ser::ReadingError> {
use crate::ser::NetworkReadExt;
Ok(Self {
json_response: bytebuf.get_str()?.into_string(),
})
}
}

View File

@@ -17,3 +17,13 @@ impl<'a> ServerPacket<'a> for SAcknowledgeFinishConfig {
Ok(Self)
}
}
impl crate::ClientPacket for SAcknowledgeFinishConfig {
fn write_packet_data(
&self,
_write: impl std::io::Write,
_version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
Ok(())
}
}

View File

@@ -31,16 +31,37 @@ pub struct SClientInformationConfig<'a> {
}
impl<'a> ServerPacket<'a> for SClientInformationConfig<'a> {
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let locale = bytebuf.get_str_borrowed()?;
let view_distance = bytebuf.get_i8()?;
let chat_mode = bytebuf.get_var_int()?;
let chat_colors = bytebuf.get_bool()?;
let skin_parts = bytebuf.get_u8()?;
let main_hand = if version >= &JavaMinecraftVersion::V_1_9 {
bytebuf.get_var_int()?
} else {
VarInt(1)
};
let text_filtering = if version >= &JavaMinecraftVersion::V_1_17 {
bytebuf.get_bool()?
} else {
false
};
let server_listing = if version >= &JavaMinecraftVersion::V_1_18 {
bytebuf.get_bool()?
} else {
true
};
Ok(Self {
locale: bytebuf.get_str_borrowed()?,
view_distance: bytebuf.get_i8()?,
chat_mode: bytebuf.get_var_int()?,
chat_colors: bytebuf.get_bool()?,
skin_parts: bytebuf.get_u8()?,
main_hand: bytebuf.get_var_int()?,
text_filtering: bytebuf.get_bool()?,
server_listing: bytebuf.get_bool()?,
locale,
view_distance,
chat_mode,
chat_colors,
skin_parts,
main_hand,
text_filtering,
server_listing,
})
}
}

View File

@@ -1,24 +1,33 @@
use pumpkin_data::packet::serverbound::CONFIG_SELECT_KNOWN_PACKS;
use pumpkin_macros::java_packet;
use crate::VarInt;
use crate::KnownPack;
use crate::{
ServerPacket,
ser::{NetworkReadExt, ReadingError},
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
};
use pumpkin_data::packet::serverbound::CONFIG_SELECT_KNOWN_PACKS;
use pumpkin_macros::java_packet;
use pumpkin_util::version::JavaMinecraftVersion;
#[java_packet(CONFIG_SELECT_KNOWN_PACKS)]
pub struct SKnownPacks {
pub known_pack_count: VarInt,
// known_packs: &'a [KnownPack]
pub struct SKnownPacks<'a> {
pub known_packs: Vec<KnownPack<'a>>,
}
impl<'a> ServerPacket<'a> for SKnownPacks {
impl<'a> ServerPacket<'a> for SKnownPacks<'a> {
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
Ok(Self {
known_pack_count: bytebuf.get_var_int()?,
})
let count = bytebuf.get_var_int()?.0;
if !(0..=64).contains(&count) {
return Err(ReadingError::Message(
"Known packs count out of bounds".into(),
));
}
let mut known_packs = Vec::with_capacity(count as usize);
for _ in 0..count {
known_packs.push(KnownPack {
namespace: bytebuf.get_str_borrowed()?,
id: bytebuf.get_str_borrowed()?,
version: bytebuf.get_str_borrowed()?,
});
}
Ok(Self { known_packs })
}
}

View File

@@ -25,6 +25,21 @@ impl<'a> ServerPacket<'a> for SEncryptionResponse {
}
}
impl crate::ClientPacket for SEncryptionResponse {
fn write_packet_data(
&self,
mut write: impl std::io::Write,
_version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
use crate::ser::NetworkWriteExt;
write.write_var_int(&crate::VarInt(self.shared_secret.len() as i32))?;
write.write_all(&self.shared_secret)?;
write.write_var_int(&crate::VarInt(self.verify_token.len() as i32))?;
write.write_all(&self.verify_token)?;
Ok(())
}
}
fn read_encryption_buffer(read: &mut impl NetworkReadExt) -> Result<Box<[u8]>, ReadingError> {
let length = read.get_var_int()?.0 as usize;
if length > 256 {

View File

@@ -14,10 +14,31 @@ pub struct SLoginStart {
}
impl<'a> ServerPacket<'a> for SLoginStart {
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
Ok(Self {
name: read.get_str_bounded(16)?,
uuid: read.get_uuid()?,
})
fn read(read: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let name = read.get_str_bounded(16)?;
let uuid = if version >= &JavaMinecraftVersion::V_1_20_2 {
read.get_uuid()?
} else {
uuid::Uuid::new_v3(
&uuid::Uuid::nil(),
format!("OfflinePlayer:{name}").as_bytes(),
)
};
Ok(Self { name, uuid })
}
}
impl crate::ClientPacket for SLoginStart {
fn write_packet_data(
&self,
mut write: impl std::io::Write,
version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
use crate::ser::NetworkWriteExt;
write.write_string_bounded(&self.name, 16)?;
if version >= &JavaMinecraftVersion::V_1_20_2 {
write.write_uuid(&self.uuid)?;
}
Ok(())
}
}

View File

@@ -21,15 +21,27 @@ pub struct SChatMessage<'a> {
}
impl<'a> ServerPacket<'a> for SChatMessage<'a> {
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
fn read(read: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let message = read.get_str_bounded_borrowed(256)?;
let timestamp = read.get_i64_be()?;
let salt = read.get_i64_be()?;
let signature = read.get_option(|v| v.read_slice_borrowed(256))?;
let message_count = read.get_var_int()?;
let acknowledged = read.read_slice_borrowed(3)?;
let checksum = if version >= &JavaMinecraftVersion::V_1_21_5 {
read.get_u8()?
} else {
0
};
Ok(Self {
message: read.get_str_bounded_borrowed(256)?,
timestamp: read.get_i64_be()?,
salt: read.get_i64_be()?,
signature: read.get_option(|v| v.read_slice_borrowed(256))?,
message_count: read.get_var_int()?,
acknowledged: read.read_slice_borrowed(3)?,
checksum: read.get_u8()?,
message,
timestamp,
salt,
signature,
message_count,
acknowledged,
checksum,
})
}
}
@@ -38,7 +50,7 @@ impl ClientPacket for SChatMessage<'_> {
fn write_packet_data(
&self,
mut write: impl std::io::Write,
_version: &JavaMinecraftVersion,
version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
write.write_string(self.message)?;
write.write_i64_be(self.timestamp)?;
@@ -46,7 +58,9 @@ impl ClientPacket for SChatMessage<'_> {
write.write_option(&self.signature, |p, v| p.write_slice(v))?;
write.write_var_int(&self.message_count)?;
write.write_slice(self.acknowledged)?;
write.write_u8(self.checksum)?;
if version >= &JavaMinecraftVersion::V_1_21_5 {
write.write_u8(self.checksum)?;
}
Ok(())
}

View File

@@ -25,10 +25,14 @@ pub struct SClickSlot {
impl<'a> ServerPacket<'a> for SClickSlot {
fn read(
mut bytebuf: &mut &'a [u8],
_version: &JavaMinecraftVersion,
version: &JavaMinecraftVersion,
) -> Result<Self, ReadingError> {
let sync_id = bytebuf.get_var_int()?;
let revision = bytebuf.get_var_int()?;
let revision = if version >= &JavaMinecraftVersion::V_1_17_1 {
bytebuf.get_var_int()?
} else {
VarInt(i32::from(bytebuf.get_i16_be()?))
};
let slot = bytebuf.get_i16_be()?;
let button = bytebuf.get_i8()?;
let mode = SlotActionType::read(&mut bytebuf)?;

View File

@@ -21,16 +21,37 @@ pub struct SClientInformationPlay<'a> {
}
impl<'a> ServerPacket<'a> for SClientInformationPlay<'a> {
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let locale = bytebuf.get_str_borrowed()?;
let view_distance = bytebuf.get_i8()?;
let chat_mode = bytebuf.get_var_int()?;
let chat_colors = bytebuf.get_bool()?;
let skin_parts = bytebuf.get_u8()?;
let main_hand = if version >= &JavaMinecraftVersion::V_1_9 {
bytebuf.get_var_int()?
} else {
VarInt(1)
};
let text_filtering = if version >= &JavaMinecraftVersion::V_1_17 {
bytebuf.get_bool()?
} else {
false
};
let server_listing = if version >= &JavaMinecraftVersion::V_1_18 {
bytebuf.get_bool()?
} else {
true
};
Ok(Self {
locale: bytebuf.get_str_borrowed()?,
view_distance: bytebuf.get_i8()?,
chat_mode: bytebuf.get_var_int()?,
chat_colors: bytebuf.get_bool()?,
skin_parts: bytebuf.get_u8()?,
main_hand: bytebuf.get_var_int()?,
text_filtering: bytebuf.get_bool()?,
server_listing: bytebuf.get_bool()?,
locale,
view_distance,
chat_mode,
chat_colors,
skin_parts,
main_hand,
text_filtering,
server_listing,
})
}
}

View File

@@ -15,6 +15,7 @@ pub struct SPlayerCommand {
pub jump_boost: VarInt,
}
#[derive(PartialEq, Eq, Debug)]
pub enum Action {
// <=1.21.5
StartSneaking,

View File

@@ -23,9 +23,36 @@ impl SPlayerInput {
}
impl<'a> ServerPacket<'a> for SPlayerInput {
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
Ok(Self {
input: bytebuf.get_i8()?,
})
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
if version >= &JavaMinecraftVersion::V_1_21_2 {
Ok(Self {
input: bytebuf.get_i8()?,
})
} else {
let sideways = bytebuf.get_f32_be()?;
let forward = bytebuf.get_f32_be()?;
let jumping = bytebuf.get_bool()?;
let sneaking = bytebuf.get_bool()?;
let mut input: i8 = 0;
if forward > 0.0 {
input |= Self::FORWARD;
} else if forward < 0.0 {
input |= Self::BACKWARD;
}
if sideways > 0.0 {
input |= Self::LEFT;
} else if sideways < 0.0 {
input |= Self::RIGHT;
}
if jumping {
input |= Self::JUMP;
}
if sneaking {
input |= Self::SNEAK;
}
Ok(Self { input })
}
}
}

View File

@@ -18,15 +18,20 @@ pub struct SUseItem {
}
impl<'a> ServerPacket<'a> for SUseItem {
fn read(
bytebuf: &mut &'a [u8],
_protocol_version: &JavaMinecraftVersion,
) -> Result<Self, ReadingError> {
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let hand = bytebuf.get_var_int()?;
let sequence = bytebuf.get_var_int()?;
let (yaw, pitch) = if version >= &JavaMinecraftVersion::V_1_21_2 {
(bytebuf.get_f32_be()?, bytebuf.get_f32_be()?)
} else {
(0.0, 0.0)
};
Ok(Self {
hand: bytebuf.get_var_int()?,
sequence: bytebuf.get_var_int()?,
yaw: bytebuf.get_f32_be()?,
pitch: bytebuf.get_f32_be()?,
hand,
sequence,
yaw,
pitch,
})
}
}

View File

@@ -21,19 +21,31 @@ pub struct SUseItemOn {
}
impl<'a> ServerPacket<'a> for SUseItemOn {
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let hand = bytebuf.get_var_int()?;
let position = BlockPos::from_i64(bytebuf.get_i64_be()?);
let face = bytebuf.get_var_int()?;
let cursor_pos = Vector3::new(
bytebuf.get_f32_be()?,
bytebuf.get_f32_be()?,
bytebuf.get_f32_be()?,
);
let inside_block = bytebuf.get_bool()?;
let is_against_world_border = if version >= &JavaMinecraftVersion::V_1_21_5 {
bytebuf.get_bool()?
} else {
false
};
let sequence = bytebuf.get_var_int()?;
Ok(Self {
hand: bytebuf.get_var_int()?,
position: BlockPos::from_i64(bytebuf.get_i64_be()?),
face: bytebuf.get_var_int()?,
cursor_pos: Vector3::new(
bytebuf.get_f32_be()?,
bytebuf.get_f32_be()?,
bytebuf.get_f32_be()?,
),
inside_block: bytebuf.get_bool()?,
is_against_world_border: bytebuf.get_bool()?,
sequence: bytebuf.get_var_int()?,
hand,
position,
face,
cursor_pos,
inside_block,
is_against_world_border,
sequence,
})
}
}

View File

@@ -1,6 +1,6 @@
use crate::{
ServerPacket,
ser::{NetworkReadExt, ReadingError},
ser::{NetworkReadExt, NetworkWriteExt, ReadingError},
};
use pumpkin_data::packet::serverbound::STATUS_PING_REQUEST;
use pumpkin_macros::java_packet;
@@ -25,3 +25,14 @@ impl<'a> ServerPacket<'a> for SStatusPingRequest {
})
}
}
impl crate::ClientPacket for SStatusPingRequest {
fn write_packet_data(
&self,
mut write: impl std::io::Write,
_version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
write.write_i64_be(self.payload)?;
Ok(())
}
}

View File

@@ -18,3 +18,13 @@ impl<'a> ServerPacket<'a> for SStatusRequest {
Ok(Self)
}
}
impl crate::ClientPacket for SStatusRequest {
fn write_packet_data(
&self,
_write: impl std::io::Write,
_version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
Ok(())
}
}

View File

@@ -2126,15 +2126,14 @@ impl Player {
progress.clamp(0.0, 1.0)
}
pub async fn fire_packet_sent<P: 'static + Send + Sync + std::any::Any + Clone>(
pub async fn fire_packet_sent<P: Send + Sync + std::any::Any>(
self: &Arc<Self>,
packet: &P,
packet: P,
packet_id: i32,
payload: Bytes,
) -> bool {
if let Some(server) = self.world().server.upgrade() {
let event =
PacketSentEvent::new(self.clone(), packet_id, payload, Arc::new(packet.clone()));
let event = PacketSentEvent::new(self.clone(), packet_id, payload, Arc::new(packet));
let event = server.plugin_manager.fire(event).await;
return event.cancelled;
}

View File

@@ -1,7 +1,4 @@
use std::{
num::NonZeroU8,
sync::{Arc, atomic::Ordering},
};
use std::{num::NonZeroU8, sync::atomic::Ordering};
use crate::{
entity::player::ChatMode,
@@ -16,7 +13,7 @@ use pumpkin_data::{registry::Registry, translation};
use pumpkin_protocol::{
ConnectionState,
java::{
client::config::{CFinishConfig, CRegistryData, CUpdateTags},
client::config::{CFeatureFlags, CFinishConfig, CRegistryData, CUpdateTags},
server::config::{
ResourcePackResponseResult, SClientInformationConfig, SConfigCookieResponse,
SConfigResourcePack, SKeepAlive, SKnownPacks, SPluginMessage,
@@ -156,24 +153,44 @@ impl JavaClient {
pub async fn handle_known_packs(
&self,
_config_acknowledged: SKnownPacks,
server: &Arc<Server>,
_config_acknowledged: SKnownPacks<'_>,
server: &Server,
) -> Option<PacketHandlerResult> {
debug!("Handling known packs");
// let mut tags_to_send = Vec::new();
let version = self.version.load();
let registry = Registry::get_synced(version);
for registry in registry {
self.send_packet_now(&CRegistryData::new(
&registry.registry_id,
&registry.registry_entries,
))
.await;
// if let Some(tag) = RegistryKey::from_string(&registry.registry_id.path)
// && pumpkin_data::tag::get_registry_key_tags(self.version.load(), tag).is_some()
// {
// tags_to_send.push(tag);
// }
if version >= JavaMinecraftVersion::V_1_20_2 {
self.send_packet_now(&CFeatureFlags::new(&["minecraft:vanilla".to_string()]))
.await;
let registry = Registry::get_synced(version);
let mut sent_dimension_type = false;
for reg in &registry {
if reg.registry_id == "minecraft:dimension_type" {
sent_dimension_type = true;
}
self.send_packet_now(&CRegistryData::new(&reg.registry_id, &reg.registry_entries))
.await;
}
if !sent_dimension_type {
let dims = [
&pumpkin_data::dimension::Dimension::OVERWORLD,
&pumpkin_data::dimension::Dimension::OVERWORLD_CAVES,
&pumpkin_data::dimension::Dimension::THE_END,
&pumpkin_data::dimension::Dimension::THE_NETHER,
];
let dim_entries: Vec<pumpkin_data::registry::RegistryEntryData> = dims
.iter()
.map(|dim| pumpkin_data::registry::RegistryEntryData {
entry_id: dim.minecraft_name.to_string(),
data: Some(build_dimension_nbt(dim).into_boxed_slice()),
})
.collect();
self.send_packet_now(&CRegistryData::new(
&"minecraft:dimension_type".to_string(),
&dim_entries,
))
.await;
}
}
//self.send_packet_now(&CUpdateTags::new(&tags_to_send)).await;
let mut tags = vec![
@@ -244,7 +261,7 @@ impl JavaClient {
}
}
pub async fn handle_config_acknowledged(&self, server: &Arc<Server>) -> PacketHandlerResult {
pub async fn handle_config_acknowledged(&self, server: &Server) -> PacketHandlerResult {
debug!("Handling config acknowledgement");
self.connection_state.store(ConnectionState::Play);
@@ -261,3 +278,38 @@ impl JavaClient {
PacketHandlerResult::ReadyToPlay(profile, config.clone().unwrap_or_default())
}
}
fn build_dimension_nbt(dim: &pumpkin_data::dimension::Dimension) -> Vec<u8> {
let mut compound = pumpkin_nbt::compound::NbtCompound::new();
compound.put_float("ambient_light", dim.ambient_light);
compound.put_int("height", dim.height);
compound.put_int("logical_height", dim.logical_height);
compound.put_int("min_y", dim.min_y);
compound.put_string("infiniburn", dim.infiniburn.to_string());
compound.put_int(
"monster_spawn_block_light_limit",
dim.monster_spawn_block_light_limit as i32,
);
compound.put_double("coordinate_scale", dim.coordinate_scale);
compound.put_byte("has_skylight", i8::from(dim.has_skylight));
compound.put_byte("has_ceiling", i8::from(dim.has_ceiling));
compound.put_byte("ultrawarm", i8::from(dim.id == 3));
compound.put_byte("natural", i8::from(dim.id == 0 || dim.id == 1));
compound.put_byte("piglin_safe", i8::from(dim.id == 3));
compound.put_byte("respawn_anchor_works", i8::from(dim.id == 3));
compound.put_byte("bed_works", i8::from(dim.id == 0 || dim.id == 1));
compound.put_byte("has_raids", i8::from(dim.id == 0 || dim.id == 1));
compound.put_string("effects", dim.minecraft_name.to_string());
let mut monster_spawn = pumpkin_nbt::compound::NbtCompound::new();
monster_spawn.put_string("type", "minecraft:uniform".to_string());
let mut value = pumpkin_nbt::compound::NbtCompound::new();
value.put_int("min_inclusive", 0);
value.put_int("max_inclusive", 7);
monster_spawn.put_compound("value", value);
compound.put_compound("monster_spawn_light_level", monster_spawn);
let mut bytes = Vec::new();
let _ = pumpkin_nbt::serializer::to_bytes(&compound, &mut bytes);
bytes
}

View File

@@ -6,6 +6,7 @@ use pumpkin_protocol::{
config::{CConfigAddResourcePack, CConfigServerLinks, CKnownPacks},
login::{CLoginSuccess, CSetCompression},
},
java::server::config::SKnownPacks,
java::server::login::{
SEncryptionResponse, SLoginCookieResponse, SLoginPluginResponse, SLoginStart,
},
@@ -201,6 +202,9 @@ impl JavaClient {
}
async fn enable_compression(&self, server: &Server) {
if self.version.load() < JavaMinecraftVersion::V_1_8 {
return;
}
let compression = server
.advanced_config
.networking
@@ -226,6 +230,9 @@ impl JavaClient {
uuid::Uuid::new_v4(),
);
self.send_packet_now(&packet).await;
if self.version.load() < JavaMinecraftVersion::V_1_20_2 {
self.connection_state.store(ConnectionState::Play);
}
}
async fn authenticate(
@@ -405,19 +412,27 @@ impl JavaClient {
);
self.send_packet_now(&resource_pack).await;
} else {
// This will be invoked by our resource pack handler in the case of the above branch.
} else if self.version.load() >= JavaMinecraftVersion::V_1_20_5 {
self.send_known_packs().await;
} else {
self.handle_known_packs(
SKnownPacks {
known_packs: Vec::new(),
},
server,
)
.await;
}
debug!("login acknowledged");
}
/// Send the known data packs to the client.
pub async fn send_known_packs(&self) {
let version_str = self.version.load().to_string();
self.send_packet_now(&CKnownPacks::new(&[KnownPack {
namespace: "minecraft",
id: "core",
version: "26.2",
version: &version_str,
}]))
.await;
}

View File

@@ -780,7 +780,6 @@ impl JavaClient {
debug!("Handling login group for id");
let mut payload = &packet.payload[..];
let version = self.version.load();
match packet.id {
id if id == SLoginStart::to_id(version) => {
self.handle_login_start(server, SLoginStart::read(&mut payload, &version)?)

View File

@@ -771,7 +771,7 @@ pub fn deserialize_java_serverbound_packet(
use pumpkin_protocol::ServerPacket;
let p = <pumpkin_protocol::java::server::config::SKnownPacks as pumpkin_protocol::ServerPacket>::read(&mut payload, &version).ok()?;
Some(ServerboundPacket::ConfigSKnownPacks(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::ConfigSKnownPacks {
known_pack_count: p.known_pack_count.0.try_into().unwrap(),
known_pack_count: p.known_packs.len().try_into().unwrap(),
}))
}
id if id == pumpkin_protocol::java::server::config::SConfigResourcePack::to_id(version) => {