diff --git a/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt b/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt
index dfedee0c3..a9ff4007d 100644
--- a/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt
+++ b/extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt
@@ -28,7 +28,7 @@ class Extractor : ModInitializer {
Particles(),
SyncedRegistries(),
Packet(),
- Screen(),
+ Screens(),
Items(),
Blocks(),
)
diff --git a/extractor/src/main/kotlin/de/snowii/extractor/extractors/Recipes.kt b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Recipes.kt
index bc58511ae..de6243cce 100644
--- a/extractor/src/main/kotlin/de/snowii/extractor/extractors/Recipes.kt
+++ b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Recipes.kt
@@ -46,7 +46,6 @@ class Recipes : Extractor.Extractor {
}
}
recipeJson.add("ingredients", ingredientArray)
-// recipeJson.addProperty("placementSlots", gson.toJson(recipe.ingredientPlacement.placementSlots))
recipesJson.add(recipeJson)
}
diff --git a/extractor/src/main/kotlin/de/snowii/extractor/extractors/Screen.kt b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Screens.kt
similarity index 95%
rename from extractor/src/main/kotlin/de/snowii/extractor/extractors/Screen.kt
rename to extractor/src/main/kotlin/de/snowii/extractor/extractors/Screens.kt
index 54ad23418..42b8a165f 100644
--- a/extractor/src/main/kotlin/de/snowii/extractor/extractors/Screen.kt
+++ b/extractor/src/main/kotlin/de/snowii/extractor/extractors/Screens.kt
@@ -7,7 +7,7 @@ import de.snowii.extractor.Extractor
import net.minecraft.registry.Registries
import net.minecraft.server.MinecraftServer
-class Screen : Extractor.Extractor {
+class Screens : Extractor.Extractor {
override fun fileName(): String {
return "screens.json"
}
diff --git a/pumpkin-macros/src/lib.rs b/pumpkin-macros/src/lib.rs
index 989641c9c..cd7c79580 100644
--- a/pumpkin-macros/src/lib.rs
+++ b/pumpkin-macros/src/lib.rs
@@ -17,7 +17,28 @@ pub fn client_packet(input: TokenStream, item: TokenStream) -> TokenStream {
let gen = quote! {
#item
- impl #impl_generics crate::bytebuf::packet_id::ClientPacketID for #name #ty_generics {
+ impl #impl_generics crate::bytebuf::packet_id::Packet for #name #ty_generics {
+ const PACKET_ID: i32 = #input as i32;
+ }
+ };
+
+ gen.into()
+}
+
+#[proc_macro_attribute]
+pub fn server_packet(input: TokenStream, item: TokenStream) -> TokenStream {
+ let ast: syn::DeriveInput = syn::parse(item.clone()).unwrap();
+
+ let name = &ast.ident;
+
+ let (impl_generics, ty_generics, _) = ast.generics.split_for_impl();
+
+ let input: proc_macro2::TokenStream = packet::packet_serverbound(input);
+ let item: proc_macro2::TokenStream = item.into();
+
+ let gen = quote! {
+ #item
+ impl #impl_generics crate::bytebuf::packet_id::Packet for #name #ty_generics {
const PACKET_ID: i32 = #input as i32;
}
};
diff --git a/pumpkin-macros/src/packet.rs b/pumpkin-macros/src/packet.rs
index 2b0b838e3..0d0a7c1a7 100644
--- a/pumpkin-macros/src/packet.rs
+++ b/pumpkin-macros/src/packet.rs
@@ -30,7 +30,6 @@ pub(crate) fn packet_clientbound(item: TokenStream) -> proc_macro2::TokenStream
quote! { #id }
}
-#[expect(dead_code)]
pub(crate) fn packet_serverbound(item: TokenStream) -> proc_macro2::TokenStream {
let input_string = item.to_string();
let packet_name = input_string.trim_matches('"');
diff --git a/pumpkin-protocol/src/bytebuf/packet_id.rs b/pumpkin-protocol/src/bytebuf/packet_id.rs
index c8d17c695..f2505b832 100644
--- a/pumpkin-protocol/src/bytebuf/packet_id.rs
+++ b/pumpkin-protocol/src/bytebuf/packet_id.rs
@@ -130,13 +130,13 @@ impl<'de> Deserialize<'de> for VarLong {
}
}
-pub trait ClientPacketID {
+pub trait Packet {
const PACKET_ID: VarIntType;
}
impl
ClientPacket for P
where
- P: ClientPacketID + Serialize,
+ P: Packet + Serialize,
{
fn write(&self, bytebuf: &mut ByteBuffer) {
let mut serializer = serializer::Serializer::new(ByteBuffer::empty());
@@ -151,7 +151,7 @@ where
impl
ServerPacket for P
where
- P: DeserializeOwned,
+ P: Packet + DeserializeOwned,
{
fn read(bytebuf: &mut ByteBuffer) -> Result
{
let deserializer = deserializer::Deserializer::new(bytebuf);
diff --git a/pumpkin-protocol/src/lib.rs b/pumpkin-protocol/src/lib.rs
index 5def3df30..b550ff43e 100644
--- a/pumpkin-protocol/src/lib.rs
+++ b/pumpkin-protocol/src/lib.rs
@@ -1,4 +1,4 @@
-use bytebuf::{packet_id::ClientPacketID, ByteBuffer, DeserializerError};
+use bytebuf::{packet_id::Packet, ByteBuffer, DeserializerError};
use pumpkin_core::text::{style::Style, TextComponent};
use serde::{Deserialize, Serialize};
@@ -72,11 +72,11 @@ pub struct RawPacket {
pub bytebuf: ByteBuffer,
}
-pub trait ClientPacket: ClientPacketID {
+pub trait ClientPacket: Packet {
fn write(&self, bytebuf: &mut ByteBuffer);
}
-pub trait ServerPacket: Sized {
+pub trait ServerPacket: Packet + Sized {
fn read(bytebuf: &mut ByteBuffer) -> Result;
}
diff --git a/pumpkin-protocol/src/server/config/mod.rs b/pumpkin-protocol/src/server/config/mod.rs
index b59b0e705..164c8e60a 100644
--- a/pumpkin-protocol/src/server/config/mod.rs
+++ b/pumpkin-protocol/src/server/config/mod.rs
@@ -3,22 +3,7 @@ mod s_client_information;
mod s_known_packs;
mod s_plugin_message;
-use num_derive::FromPrimitive;
pub use s_acknowledge_finish_config::*;
pub use s_client_information::*;
pub use s_known_packs::*;
pub use s_plugin_message::*;
-
-/// DO NOT CHANGE ORDER
-/// This Enum has the exact order like vanilla, Vanilla parses their Packet IDs from the enum order. Its also way easier to port.
-#[derive(FromPrimitive)]
-pub enum ServerboundConfigPackets {
- ClientInformation,
- CookieResponse,
- PluginMessage,
- AcknowledgedFinish,
- KeepAlive,
- Pong,
- ResourcePackResponse,
- KnownPacks,
-}
diff --git a/pumpkin-protocol/src/server/config/s_acknowledge_finish_config.rs b/pumpkin-protocol/src/server/config/s_acknowledge_finish_config.rs
index 20b81d462..7796b8510 100644
--- a/pumpkin-protocol/src/server/config/s_acknowledge_finish_config.rs
+++ b/pumpkin-protocol/src/server/config/s_acknowledge_finish_config.rs
@@ -1,2 +1,5 @@
+use pumpkin_macros::server_packet;
+
#[derive(serde::Deserialize)]
+#[server_packet("configuration:finish_configuration")]
pub struct SAcknowledgeFinishConfig {}
diff --git a/pumpkin-protocol/src/server/config/s_client_information.rs b/pumpkin-protocol/src/server/config/s_client_information.rs
index 4ec1a6984..ba6823f7e 100644
--- a/pumpkin-protocol/src/server/config/s_client_information.rs
+++ b/pumpkin-protocol/src/server/config/s_client_information.rs
@@ -1,6 +1,9 @@
+use pumpkin_macros::server_packet;
+
use crate::VarInt;
#[derive(serde::Deserialize)]
+#[server_packet("configuration:client_information")]
pub struct SClientInformationConfig {
pub locale: String, // 16
pub view_distance: i8,
diff --git a/pumpkin-protocol/src/server/config/s_known_packs.rs b/pumpkin-protocol/src/server/config/s_known_packs.rs
index f468609cd..138cf2ae2 100644
--- a/pumpkin-protocol/src/server/config/s_known_packs.rs
+++ b/pumpkin-protocol/src/server/config/s_known_packs.rs
@@ -1,6 +1,9 @@
+use pumpkin_macros::server_packet;
+
use crate::VarInt;
#[derive(serde::Deserialize)]
+#[server_packet("configuration:select_known_packs")]
pub struct SKnownPacks {
pub known_pack_count: VarInt,
// known_packs: &'a [KnownPack]
diff --git a/pumpkin-protocol/src/server/config/s_plugin_message.rs b/pumpkin-protocol/src/server/config/s_plugin_message.rs
index d2341a9de..7007f35d8 100644
--- a/pumpkin-protocol/src/server/config/s_plugin_message.rs
+++ b/pumpkin-protocol/src/server/config/s_plugin_message.rs
@@ -1,8 +1,11 @@
+use pumpkin_macros::server_packet;
+
use crate::{
bytebuf::{ByteBuffer, DeserializerError},
Identifier, ServerPacket,
};
+#[server_packet("configuration:custom_payload")]
pub struct SPluginMessage {
pub channel: Identifier,
pub data: Vec,
diff --git a/pumpkin-protocol/src/server/handshake/mod.rs b/pumpkin-protocol/src/server/handshake/mod.rs
index cbed59db7..a1d743528 100644
--- a/pumpkin-protocol/src/server/handshake/mod.rs
+++ b/pumpkin-protocol/src/server/handshake/mod.rs
@@ -1,8 +1,11 @@
+use pumpkin_macros::server_packet;
+
use crate::{
bytebuf::{ByteBuffer, DeserializerError},
ConnectionState, ServerPacket, VarInt,
};
+#[server_packet("handshake:intention")]
pub struct SHandShake {
pub protocol_version: VarInt,
pub server_address: String, // 255
diff --git a/pumpkin-protocol/src/server/login/mod.rs b/pumpkin-protocol/src/server/login/mod.rs
index aa0aca2ec..872f74bbc 100644
--- a/pumpkin-protocol/src/server/login/mod.rs
+++ b/pumpkin-protocol/src/server/login/mod.rs
@@ -3,19 +3,7 @@ mod s_login_response;
mod s_login_start;
mod s_plugin_response;
-use num_derive::FromPrimitive;
pub use s_encryption_response::*;
pub use s_login_response::*;
pub use s_login_start::*;
pub use s_plugin_response::*;
-
-/// DO NOT CHANGE ORDER
-/// This Enum has the exact order like vanilla, Vanilla parses their Packet IDs from the enum order. Its also way easier to port.
-#[derive(FromPrimitive)]
-pub enum ServerboundLoginPackets {
- LoginStart,
- EncryptionResponse,
- PluginResponse,
- LoginAcknowledged,
- CookieResponse,
-}
diff --git a/pumpkin-protocol/src/server/login/s_encryption_response.rs b/pumpkin-protocol/src/server/login/s_encryption_response.rs
index 6c3a5d3ef..06c224624 100644
--- a/pumpkin-protocol/src/server/login/s_encryption_response.rs
+++ b/pumpkin-protocol/src/server/login/s_encryption_response.rs
@@ -1,8 +1,11 @@
+use pumpkin_macros::server_packet;
+
use crate::{
bytebuf::{ByteBuffer, DeserializerError},
ServerPacket, VarInt,
};
+#[server_packet("login:key")]
pub struct SEncryptionResponse {
pub shared_secret_length: VarInt,
pub shared_secret: Vec,
diff --git a/pumpkin-protocol/src/server/login/s_login_response.rs b/pumpkin-protocol/src/server/login/s_login_response.rs
index 1a1d432d8..aaf250bf6 100644
--- a/pumpkin-protocol/src/server/login/s_login_response.rs
+++ b/pumpkin-protocol/src/server/login/s_login_response.rs
@@ -1,3 +1,6 @@
+use pumpkin_macros::server_packet;
+
// Acknowledgement to the Login Success packet sent to the server.
#[derive(serde::Deserialize)]
+#[server_packet("login:login_acknowledged")]
pub struct SLoginAcknowledged {}
diff --git a/pumpkin-protocol/src/server/login/s_login_start.rs b/pumpkin-protocol/src/server/login/s_login_start.rs
index 41aaa96b9..7a4a724da 100644
--- a/pumpkin-protocol/src/server/login/s_login_start.rs
+++ b/pumpkin-protocol/src/server/login/s_login_start.rs
@@ -1,8 +1,11 @@
+use pumpkin_macros::server_packet;
+
use crate::{
bytebuf::{ByteBuffer, DeserializerError},
ServerPacket,
};
+#[server_packet("login:hello")]
pub struct SLoginStart {
pub name: String, // 16
pub uuid: uuid::Uuid,
diff --git a/pumpkin-protocol/src/server/login/s_plugin_response.rs b/pumpkin-protocol/src/server/login/s_plugin_response.rs
index 9f3ec74ec..24656471e 100644
--- a/pumpkin-protocol/src/server/login/s_plugin_response.rs
+++ b/pumpkin-protocol/src/server/login/s_plugin_response.rs
@@ -3,7 +3,9 @@ use crate::{
ServerPacket, VarInt,
};
use bytes::BytesMut;
+use pumpkin_macros::server_packet;
+#[server_packet("login:custom_query_answer")]
pub struct SLoginPluginResponse {
pub message_id: VarInt,
pub data: Option,
diff --git a/pumpkin-protocol/src/server/play/mod.rs b/pumpkin-protocol/src/server/play/mod.rs
index 0c1f9b9d1..6d97dd3d6 100644
--- a/pumpkin-protocol/src/server/play/mod.rs
+++ b/pumpkin-protocol/src/server/play/mod.rs
@@ -20,7 +20,6 @@ mod s_swing_arm;
mod s_use_item;
mod s_use_item_on;
-use num_derive::FromPrimitive;
pub use s_chat_command::*;
pub use s_chat_message::*;
pub use s_click_container::*;
@@ -42,72 +41,3 @@ pub use s_set_held_item::*;
pub use s_swing_arm::*;
pub use s_use_item::*;
pub use s_use_item_on::*;
-
-/// DO NOT CHANGE ORDER
-/// This Enum has the exact order like vanilla, Vanilla parses their Packet IDs from the enum order. Its also way easier to port.
-#[derive(FromPrimitive)]
-pub enum ServerboundPlayPackets {
- TeleportConfirm,
- QueryBlockNbt,
- SelectBundleItem,
- SetDifficulty,
- ChatAck,
- ChatCommandUnsigned,
- ChatCommand,
- ChatMessage,
- ChatSessionUpdate,
- ChunkBatchAck,
- ClientStatus,
- ClientTickEnd,
- ClientSettings,
- TabComplete,
- ConfigurationAck,
- ClickWindowButton,
- ClickWindow,
- CloseWindow,
- SlotStateChange,
- CookieResponse,
- PluginMessage,
- DebugSampleSubscription,
- EditBook,
- QueryEntityNbt,
- InteractEntity,
- GenerateStructure,
- KeepAlive,
- LockDifficulty,
- PlayerPosition,
- PlayerPositionAndRotation,
- PlayerRotation,
- PlayerFlying,
-
- VehicleMove,
- SteerBoat,
- PickItem,
- DebugPing,
- CraftRecipeRequest,
- PlayerAbilities,
- PlayerDigging,
- EntityAction,
- PlayerInput,
- Pong,
- SetRecipeBookState,
- SetDisplayedRecipe,
- NameItem,
- ResourcePackStatus,
- AdvancementTab,
- SelectTrade,
- SetBeaconEffect,
- HeldItemChange,
-
- UpdateCommandBlock,
- UpdateCommandBlockMinecart,
- CreativeInventoryAction,
- UpdateJigsawBlock,
- UpdateStructureBlock,
- UpdateSign,
-
- Animation,
- Spectate,
- PlayerBlockPlacement,
- UseItem,
-}
diff --git a/pumpkin-protocol/src/server/play/s_chat_command.rs b/pumpkin-protocol/src/server/play/s_chat_command.rs
index e12bcdd89..c5c572cfb 100644
--- a/pumpkin-protocol/src/server/play/s_chat_command.rs
+++ b/pumpkin-protocol/src/server/play/s_chat_command.rs
@@ -1,4 +1,7 @@
+use pumpkin_macros::server_packet;
+
#[derive(serde::Deserialize)]
+#[server_packet("play:chat_command")]
pub struct SChatCommand {
pub command: String,
}
diff --git a/pumpkin-protocol/src/server/play/s_chat_message.rs b/pumpkin-protocol/src/server/play/s_chat_message.rs
index 58d3179b4..a8e61d746 100644
--- a/pumpkin-protocol/src/server/play/s_chat_message.rs
+++ b/pumpkin-protocol/src/server/play/s_chat_message.rs
@@ -1,4 +1,5 @@
use bytes::Bytes;
+use pumpkin_macros::server_packet;
use crate::{
bytebuf::{ByteBuffer, DeserializerError},
@@ -6,6 +7,7 @@ use crate::{
};
// derive(Deserialize)]
+#[server_packet("play:chat")]
pub struct SChatMessage {
pub message: String,
pub timestamp: i64,
diff --git a/pumpkin-protocol/src/server/play/s_click_container.rs b/pumpkin-protocol/src/server/play/s_click_container.rs
index f82aca1d3..8de3f8a79 100644
--- a/pumpkin-protocol/src/server/play/s_click_container.rs
+++ b/pumpkin-protocol/src/server/play/s_click_container.rs
@@ -1,9 +1,11 @@
use crate::slot::Slot;
use crate::VarInt;
+use pumpkin_macros::server_packet;
use serde::de::SeqAccess;
use serde::{de, Deserialize};
#[derive(Debug)]
+#[server_packet("play:container_click")]
pub struct SClickContainer {
pub window_id: VarInt,
pub state_id: VarInt,
diff --git a/pumpkin-protocol/src/server/play/s_client_information.rs b/pumpkin-protocol/src/server/play/s_client_information.rs
index b93760c2b..b16be1380 100644
--- a/pumpkin-protocol/src/server/play/s_client_information.rs
+++ b/pumpkin-protocol/src/server/play/s_client_information.rs
@@ -1,6 +1,9 @@
+use pumpkin_macros::server_packet;
+
use crate::VarInt;
#[derive(serde::Deserialize)]
+#[server_packet("play:client_information")]
pub struct SClientInformationPlay {
pub locale: String, // 16
pub view_distance: i8,
diff --git a/pumpkin-protocol/src/server/play/s_close_container.rs b/pumpkin-protocol/src/server/play/s_close_container.rs
index 1c6140195..d6f97dadc 100644
--- a/pumpkin-protocol/src/server/play/s_close_container.rs
+++ b/pumpkin-protocol/src/server/play/s_close_container.rs
@@ -1,8 +1,10 @@
+use pumpkin_macros::server_packet;
use serde::Deserialize;
use crate::VarInt;
#[derive(Deserialize)]
+#[server_packet("play:container_close")]
pub struct SCloseContainer {
pub window_id: VarInt,
}
diff --git a/pumpkin-protocol/src/server/play/s_confirm_teleport.rs b/pumpkin-protocol/src/server/play/s_confirm_teleport.rs
index 2ee49d02a..b6f724e26 100644
--- a/pumpkin-protocol/src/server/play/s_confirm_teleport.rs
+++ b/pumpkin-protocol/src/server/play/s_confirm_teleport.rs
@@ -1,6 +1,9 @@
+use pumpkin_macros::server_packet;
+
use crate::VarInt;
#[derive(serde::Deserialize)]
+#[server_packet("play:accept_teleportation")]
pub struct SConfirmTeleport {
pub teleport_id: VarInt,
}
diff --git a/pumpkin-protocol/src/server/play/s_interact.rs b/pumpkin-protocol/src/server/play/s_interact.rs
index 4350812a3..9a1a5d7b5 100644
--- a/pumpkin-protocol/src/server/play/s_interact.rs
+++ b/pumpkin-protocol/src/server/play/s_interact.rs
@@ -1,8 +1,10 @@
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
+use pumpkin_macros::server_packet;
use crate::{bytebuf::DeserializerError, ServerPacket, VarInt};
+#[server_packet("play:interact")]
pub struct SInteract {
pub entity_id: VarInt,
pub typ: VarInt,
diff --git a/pumpkin-protocol/src/server/play/s_keep_alive.rs b/pumpkin-protocol/src/server/play/s_keep_alive.rs
index d49b7ecb5..714aaa134 100644
--- a/pumpkin-protocol/src/server/play/s_keep_alive.rs
+++ b/pumpkin-protocol/src/server/play/s_keep_alive.rs
@@ -1,6 +1,8 @@
+use pumpkin_macros::server_packet;
use serde::Deserialize;
#[derive(Deserialize)]
+#[server_packet("play:keep_alive")]
pub struct SKeepAlive {
pub keep_alive_id: i64,
}
diff --git a/pumpkin-protocol/src/server/play/s_ping_request.rs b/pumpkin-protocol/src/server/play/s_ping_request.rs
index 2b52299ea..77655ed3e 100644
--- a/pumpkin-protocol/src/server/play/s_ping_request.rs
+++ b/pumpkin-protocol/src/server/play/s_ping_request.rs
@@ -1,6 +1,8 @@
+use pumpkin_macros::server_packet;
use serde::Deserialize;
#[derive(Deserialize)]
+#[server_packet("play:ping_request")]
pub struct SPlayPingRequest {
pub payload: i64,
}
diff --git a/pumpkin-protocol/src/server/play/s_player_abilities.rs b/pumpkin-protocol/src/server/play/s_player_abilities.rs
index 0de8efadd..0bd5c06ed 100644
--- a/pumpkin-protocol/src/server/play/s_player_abilities.rs
+++ b/pumpkin-protocol/src/server/play/s_player_abilities.rs
@@ -1,8 +1,10 @@
+use pumpkin_macros::server_packet;
use serde::Deserialize;
//The vanilla client sends this packet when the player starts/stops flying. Bitmask 0x02 is set when the player is flying.
#[derive(Deserialize)]
+#[server_packet("play:player_abilities")]
pub struct SPlayerAbilities {
pub flags: i8,
}
diff --git a/pumpkin-protocol/src/server/play/s_player_action.rs b/pumpkin-protocol/src/server/play/s_player_action.rs
index f53ca006d..b8d774dc2 100644
--- a/pumpkin-protocol/src/server/play/s_player_action.rs
+++ b/pumpkin-protocol/src/server/play/s_player_action.rs
@@ -1,9 +1,11 @@
use num_derive::FromPrimitive;
use pumpkin_core::math::position::WorldPosition;
+use pumpkin_macros::server_packet;
use crate::VarInt;
#[derive(serde::Deserialize)]
+#[server_packet("play:player_action")]
pub struct SPlayerAction {
pub status: VarInt,
pub location: WorldPosition,
diff --git a/pumpkin-protocol/src/server/play/s_player_command.rs b/pumpkin-protocol/src/server/play/s_player_command.rs
index e37011200..aeafcf153 100644
--- a/pumpkin-protocol/src/server/play/s_player_command.rs
+++ b/pumpkin-protocol/src/server/play/s_player_command.rs
@@ -1,7 +1,9 @@
use num_derive::FromPrimitive;
+use pumpkin_macros::server_packet;
use crate::{bytebuf::DeserializerError, ServerPacket, VarInt};
+#[server_packet("play:player_command")]
pub struct SPlayerCommand {
pub entity_id: VarInt,
pub action: VarInt,
diff --git a/pumpkin-protocol/src/server/play/s_player_ground.rs b/pumpkin-protocol/src/server/play/s_player_ground.rs
index 0c167d829..dca0d17ee 100644
--- a/pumpkin-protocol/src/server/play/s_player_ground.rs
+++ b/pumpkin-protocol/src/server/play/s_player_ground.rs
@@ -1,6 +1,8 @@
+use pumpkin_macros::server_packet;
use serde::Deserialize;
#[derive(Deserialize)]
+#[server_packet("play:move_player_status_only")]
pub struct SSetPlayerGround {
pub on_ground: bool,
}
diff --git a/pumpkin-protocol/src/server/play/s_player_position.rs b/pumpkin-protocol/src/server/play/s_player_position.rs
index ae17d46e1..729b406be 100644
--- a/pumpkin-protocol/src/server/play/s_player_position.rs
+++ b/pumpkin-protocol/src/server/play/s_player_position.rs
@@ -1,4 +1,7 @@
+use pumpkin_macros::server_packet;
+
#[derive(serde::Deserialize)]
+#[server_packet("play:move_player_pos")]
pub struct SPlayerPosition {
pub x: f64,
pub feet_y: f64,
diff --git a/pumpkin-protocol/src/server/play/s_player_position_rotation.rs b/pumpkin-protocol/src/server/play/s_player_position_rotation.rs
index e83c57bc9..a97a68ed5 100644
--- a/pumpkin-protocol/src/server/play/s_player_position_rotation.rs
+++ b/pumpkin-protocol/src/server/play/s_player_position_rotation.rs
@@ -1,4 +1,7 @@
+use pumpkin_macros::server_packet;
+
#[derive(serde::Deserialize)]
+#[server_packet("play:move_player_pos_rot")]
pub struct SPlayerPositionRotation {
pub x: f64,
pub feet_y: f64,
diff --git a/pumpkin-protocol/src/server/play/s_player_rotation.rs b/pumpkin-protocol/src/server/play/s_player_rotation.rs
index 8a8ec4aab..ac2acafa8 100644
--- a/pumpkin-protocol/src/server/play/s_player_rotation.rs
+++ b/pumpkin-protocol/src/server/play/s_player_rotation.rs
@@ -1,4 +1,7 @@
+use pumpkin_macros::server_packet;
+
#[derive(serde::Deserialize)]
+#[server_packet("play:move_player_rot")]
pub struct SPlayerRotation {
pub yaw: f32,
pub pitch: f32,
diff --git a/pumpkin-protocol/src/server/play/s_set_creative_slot.rs b/pumpkin-protocol/src/server/play/s_set_creative_slot.rs
index f35318bb3..0dff80b44 100644
--- a/pumpkin-protocol/src/server/play/s_set_creative_slot.rs
+++ b/pumpkin-protocol/src/server/play/s_set_creative_slot.rs
@@ -1,6 +1,9 @@
+use pumpkin_macros::server_packet;
+
use crate::slot::Slot;
#[derive(serde::Deserialize, Debug)]
+#[server_packet("play:set_creative_mode_slot")]
pub struct SSetCreativeSlot {
pub slot: i16,
pub clicked_item: Slot,
diff --git a/pumpkin-protocol/src/server/play/s_set_held_item.rs b/pumpkin-protocol/src/server/play/s_set_held_item.rs
index 2bf752878..05117dd29 100644
--- a/pumpkin-protocol/src/server/play/s_set_held_item.rs
+++ b/pumpkin-protocol/src/server/play/s_set_held_item.rs
@@ -1,6 +1,8 @@
+use pumpkin_macros::server_packet;
use serde::Deserialize;
#[derive(Deserialize)]
+#[server_packet("play:pick_item")]
pub struct SSetHeldItem {
pub slot: i16,
}
diff --git a/pumpkin-protocol/src/server/play/s_swing_arm.rs b/pumpkin-protocol/src/server/play/s_swing_arm.rs
index 65d69bd34..0f7d0f16e 100644
--- a/pumpkin-protocol/src/server/play/s_swing_arm.rs
+++ b/pumpkin-protocol/src/server/play/s_swing_arm.rs
@@ -1,6 +1,9 @@
+use pumpkin_macros::server_packet;
+
use crate::VarInt;
#[derive(serde::Deserialize)]
+#[server_packet("play:swing")]
pub struct SSwingArm {
pub hand: VarInt,
}
diff --git a/pumpkin-protocol/src/server/play/s_use_item.rs b/pumpkin-protocol/src/server/play/s_use_item.rs
index 933e66b78..7035fd0a9 100644
--- a/pumpkin-protocol/src/server/play/s_use_item.rs
+++ b/pumpkin-protocol/src/server/play/s_use_item.rs
@@ -1,8 +1,10 @@
+use pumpkin_macros::server_packet;
use serde::Deserialize;
use crate::VarInt;
#[derive(Deserialize)]
+#[server_packet("play:use_item")]
pub struct SUseItem {
// 0 for main hand, 1 for off hand
pub hand: VarInt,
diff --git a/pumpkin-protocol/src/server/play/s_use_item_on.rs b/pumpkin-protocol/src/server/play/s_use_item_on.rs
index a4338ad33..3e16d282c 100644
--- a/pumpkin-protocol/src/server/play/s_use_item_on.rs
+++ b/pumpkin-protocol/src/server/play/s_use_item_on.rs
@@ -1,9 +1,11 @@
use pumpkin_core::math::position::WorldPosition;
+use pumpkin_macros::server_packet;
use serde::Deserialize;
use crate::VarInt;
#[derive(Deserialize)]
+#[server_packet("play:use_item_on")]
pub struct SUseItemOn {
pub hand: VarInt,
pub location: WorldPosition,
diff --git a/pumpkin-protocol/src/server/status/mod.rs b/pumpkin-protocol/src/server/status/mod.rs
index 008bc5e5d..fb6b04ab5 100644
--- a/pumpkin-protocol/src/server/status/mod.rs
+++ b/pumpkin-protocol/src/server/status/mod.rs
@@ -1,14 +1,5 @@
mod s_ping_request;
mod s_status_request;
-use num_derive::FromPrimitive;
pub use s_ping_request::*;
pub use s_status_request::*;
-
-/// DO NOT CHANGE ORDER
-/// This Enum has the exact order like vanilla, Vanilla parses their Packet IDs from the enum order. Its also way easier to port.
-#[derive(FromPrimitive)]
-pub enum ServerboundStatusPackets {
- StatusRequest,
- PingRequest,
-}
diff --git a/pumpkin-protocol/src/server/status/s_ping_request.rs b/pumpkin-protocol/src/server/status/s_ping_request.rs
index 33054d22f..b8fd75c16 100644
--- a/pumpkin-protocol/src/server/status/s_ping_request.rs
+++ b/pumpkin-protocol/src/server/status/s_ping_request.rs
@@ -1,4 +1,7 @@
+use pumpkin_macros::server_packet;
+
#[derive(serde::Deserialize)]
+#[server_packet("status:ping_request")]
pub struct SStatusPingRequest {
pub payload: i64,
}
diff --git a/pumpkin-protocol/src/server/status/s_status_request.rs b/pumpkin-protocol/src/server/status/s_status_request.rs
index ecd3ba85d..9d96fcc66 100644
--- a/pumpkin-protocol/src/server/status/s_status_request.rs
+++ b/pumpkin-protocol/src/server/status/s_status_request.rs
@@ -1,4 +1,7 @@
+use pumpkin_macros::server_packet;
+
#[derive(serde::Deserialize)]
+#[server_packet("status:status_request")]
pub struct SStatusRequest {
// empty
}
diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs
index 8e4065c5b..12f018f77 100644
--- a/pumpkin/src/client/mod.rs
+++ b/pumpkin/src/client/mod.rs
@@ -14,25 +14,18 @@ use crate::{
use authentication::GameProfile;
use crossbeam::atomic::AtomicCell;
-use num_traits::FromPrimitive;
use pumpkin_config::compression::CompressionInfo;
use pumpkin_core::text::TextComponent;
use pumpkin_protocol::{
- bytebuf::DeserializerError,
+ bytebuf::{packet_id::Packet, DeserializerError},
client::{config::CConfigDisconnect, login::CLoginDisconnect, play::CPlayDisconnect},
packet_decoder::PacketDecoder,
packet_encoder::{PacketEncodeError, PacketEncoder},
server::{
- config::{
- SAcknowledgeFinishConfig, SClientInformationConfig, SKnownPacks, SPluginMessage,
- ServerboundConfigPackets,
- },
+ config::{SAcknowledgeFinishConfig, SClientInformationConfig, SKnownPacks, SPluginMessage},
handshake::SHandShake,
- login::{
- SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart,
- ServerboundLoginPackets,
- },
- status::{SStatusPingRequest, SStatusRequest, ServerboundStatusPackets},
+ login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
+ status::{SStatusPingRequest, SStatusRequest},
},
ClientPacket, ConnectionState, RawPacket, ServerPacket,
};
@@ -397,24 +390,24 @@ impl Client {
) -> Result<(), DeserializerError> {
log::debug!("Handling status group");
let bytebuf = &mut packet.bytebuf;
- if let Some(packet) = ServerboundStatusPackets::from_i32(packet.id.0) {
- match packet {
- ServerboundStatusPackets::StatusRequest => {
- self.handle_status_request(server, SStatusRequest::read(bytebuf)?)
- .await;
- }
- ServerboundStatusPackets::PingRequest => {
- self.handle_ping_request(SStatusPingRequest::read(bytebuf)?)
- .await;
- }
- };
- } else {
- log::error!(
- "Failed to handle client packet id {:#04x} in Status State",
- packet.id.0
- );
- return Err(DeserializerError::UnknownPacket);
+ match packet.id.0 {
+ SStatusRequest::PACKET_ID => {
+ self.handle_status_request(server, SStatusRequest::read(bytebuf)?)
+ .await;
+ }
+ SStatusPingRequest::PACKET_ID => {
+ self.handle_ping_request(SStatusPingRequest::read(bytebuf)?)
+ .await;
+ }
+ _ => {
+ log::error!(
+ "Failed to handle client packet id {:#04x} in Status State",
+ packet.id.0
+ );
+ return Err(DeserializerError::UnknownPacket);
+ }
};
+
Ok(())
}
@@ -425,32 +418,30 @@ impl Client {
) -> Result<(), DeserializerError> {
log::debug!("Handling login group for id");
let bytebuf = &mut packet.bytebuf;
- if let Some(packet) = ServerboundLoginPackets::from_i32(packet.id.0) {
- match packet {
- ServerboundLoginPackets::LoginStart => {
- self.handle_login_start(server, SLoginStart::read(bytebuf)?)
- .await;
- }
- ServerboundLoginPackets::EncryptionResponse => {
- self.handle_encryption_response(server, SEncryptionResponse::read(bytebuf)?)
- .await;
- }
- ServerboundLoginPackets::PluginResponse => {
- self.handle_plugin_response(SLoginPluginResponse::read(bytebuf)?)
- .await;
- }
- ServerboundLoginPackets::LoginAcknowledged => {
- self.handle_login_acknowledged(server, SLoginAcknowledged::read(bytebuf)?)
- .await;
- }
- ServerboundLoginPackets::CookieResponse => {}
- };
- } else {
- log::error!(
- "Failed to handle client packet id {:#04x} in Login State",
- packet.id.0
- );
- return Ok(());
+ match packet.id.0 {
+ SLoginStart::PACKET_ID => {
+ self.handle_login_start(server, SLoginStart::read(bytebuf)?)
+ .await;
+ }
+ SEncryptionResponse::PACKET_ID => {
+ self.handle_encryption_response(server, SEncryptionResponse::read(bytebuf)?)
+ .await;
+ }
+ SLoginPluginResponse::PACKET_ID => {
+ self.handle_plugin_response(SLoginPluginResponse::read(bytebuf)?)
+ .await;
+ }
+ SLoginAcknowledged::PACKET_ID => {
+ self.handle_login_acknowledged(server, SLoginAcknowledged::read(bytebuf)?)
+ .await;
+ }
+ _ => {
+ log::error!(
+ "Failed to handle client packet id {:#04x} in Login State",
+ packet.id.0
+ );
+ return Ok(());
+ }
};
Ok(())
}
@@ -462,35 +453,29 @@ impl Client {
) -> Result<(), DeserializerError> {
log::debug!("Handling config group");
let bytebuf = &mut packet.bytebuf;
- if let Some(packet) = ServerboundConfigPackets::from_i32(packet.id.0) {
- #[expect(clippy::match_same_arms)]
- match packet {
- ServerboundConfigPackets::ClientInformation => {
- self.handle_client_information_config(SClientInformationConfig::read(bytebuf)?)
- .await;
- }
- ServerboundConfigPackets::CookieResponse => {}
- ServerboundConfigPackets::PluginMessage => {
- self.handle_plugin_message(SPluginMessage::read(bytebuf)?)
- .await;
- }
- ServerboundConfigPackets::AcknowledgedFinish => {
- self.handle_config_acknowledged(&SAcknowledgeFinishConfig::read(bytebuf)?);
- }
- ServerboundConfigPackets::KeepAlive => {}
- ServerboundConfigPackets::Pong => {}
- ServerboundConfigPackets::ResourcePackResponse => {}
- ServerboundConfigPackets::KnownPacks => {
- self.handle_known_packs(server, SKnownPacks::read(bytebuf)?)
- .await;
- }
- };
- } else {
- log::error!(
- "Failed to handle client packet id {:#04x} in Config State",
- packet.id.0
- );
- return Err(DeserializerError::UnknownPacket);
+ match packet.id.0 {
+ SClientInformationConfig::PACKET_ID => {
+ self.handle_client_information_config(SClientInformationConfig::read(bytebuf)?)
+ .await;
+ }
+ SPluginMessage::PACKET_ID => {
+ self.handle_plugin_message(SPluginMessage::read(bytebuf)?)
+ .await;
+ }
+ SAcknowledgeFinishConfig::PACKET_ID => {
+ self.handle_config_acknowledged(&SAcknowledgeFinishConfig::read(bytebuf)?);
+ }
+ SKnownPacks::PACKET_ID => {
+ self.handle_known_packs(server, SKnownPacks::read(bytebuf)?)
+ .await;
+ }
+ _ => {
+ log::error!(
+ "Failed to handle client packet id {:#04x} in Config State",
+ packet.id.0
+ );
+ return Err(DeserializerError::UnknownPacket);
+ }
};
Ok(())
}
diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs
index 097b64bf9..a3d91428f 100644
--- a/pumpkin/src/entity/player.rs
+++ b/pumpkin/src/entity/player.rs
@@ -10,7 +10,7 @@ use std::{
use crossbeam::atomic::AtomicCell;
use itertools::Itertools;
use num_derive::FromPrimitive;
-use num_traits::{FromPrimitive, ToPrimitive};
+use num_traits::ToPrimitive;
use pumpkin_config::ADVANCED_CONFIG;
use pumpkin_core::{
math::{boundingbox::BoundingBox, position::WorldPosition, vector2::Vector2, vector3::Vector3},
@@ -21,7 +21,7 @@ use pumpkin_entity::{entity_type::EntityType, EntityId};
use pumpkin_inventory::player::PlayerInventory;
use pumpkin_macros::sound;
use pumpkin_protocol::{
- bytebuf::DeserializerError,
+ bytebuf::packet_id::Packet,
client::play::{
CGameEvent, CHurtAnimation, CKeepAlive, CPlayDisconnect, CPlayerAbilities,
CPlayerInfoUpdate, CSetHealth, CSyncPlayerPosition, CSystemChatMessage, GameEvent,
@@ -31,7 +31,7 @@ use pumpkin_protocol::{
SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract,
SPlayerAbilities, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation,
SPlayerRotation, SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem,
- SUseItemOn, ServerboundPlayPackets,
+ SUseItemOn,
},
RawPacket, ServerPacket, SoundCategory, VarInt,
};
@@ -653,124 +653,80 @@ impl Player {
}
}
- #[expect(clippy::too_many_lines)]
pub async fn handle_play_packet(
self: &Arc,
server: &Arc,
packet: &mut RawPacket,
) -> Result<(), Box> {
let bytebuf = &mut packet.bytebuf;
- if let Some(packet) = ServerboundPlayPackets::from_i32(packet.id.0) {
- #[expect(clippy::match_same_arms)]
- match packet {
- ServerboundPlayPackets::TeleportConfirm => {
- self.handle_confirm_teleport(SConfirmTeleport::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::QueryBlockNbt => {}
- ServerboundPlayPackets::SelectBundleItem => {}
- ServerboundPlayPackets::SetDifficulty => {}
- ServerboundPlayPackets::ChatAck => {}
- ServerboundPlayPackets::ChatCommandUnsigned => {
- self.handle_chat_command(server, SChatCommand::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::ChatCommand => {}
- ServerboundPlayPackets::ChatMessage => {
- self.handle_chat_message(SChatMessage::read(bytebuf)?).await;
- }
- ServerboundPlayPackets::ChatSessionUpdate => {}
- ServerboundPlayPackets::ChunkBatchAck => {}
- ServerboundPlayPackets::ClientStatus => {}
- ServerboundPlayPackets::ClientTickEnd => {}
- ServerboundPlayPackets::ClientSettings => {
- self.handle_client_information(SClientInformationPlay::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::TabComplete => {}
- ServerboundPlayPackets::ConfigurationAck => {}
- ServerboundPlayPackets::ClickWindowButton => {}
- ServerboundPlayPackets::ClickWindow => {}
- ServerboundPlayPackets::CloseWindow => {}
- ServerboundPlayPackets::SlotStateChange => {}
- ServerboundPlayPackets::CookieResponse => {}
- ServerboundPlayPackets::PluginMessage => {}
- ServerboundPlayPackets::DebugSampleSubscription => {}
- ServerboundPlayPackets::EditBook => {}
- ServerboundPlayPackets::QueryEntityNbt => {}
- ServerboundPlayPackets::InteractEntity => {
- self.handle_interact(server, SInteract::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::GenerateStructure => {}
- ServerboundPlayPackets::KeepAlive => {
- self.handle_keep_alive(SKeepAlive::read(bytebuf)?).await;
- }
- ServerboundPlayPackets::LockDifficulty => {}
- ServerboundPlayPackets::PlayerPosition => {
- self.handle_position(SPlayerPosition::read(bytebuf)?).await;
- }
- ServerboundPlayPackets::PlayerPositionAndRotation => {
- self.handle_position_rotation(SPlayerPositionRotation::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::PlayerRotation => {
- self.handle_rotation(SPlayerRotation::read(bytebuf)?).await;
- }
- ServerboundPlayPackets::PlayerFlying => {
- self.handle_player_ground(&SSetPlayerGround::read(bytebuf)?);
- }
- ServerboundPlayPackets::VehicleMove => {}
- ServerboundPlayPackets::SteerBoat => {}
- ServerboundPlayPackets::PickItem => {}
- ServerboundPlayPackets::DebugPing => {}
- ServerboundPlayPackets::CraftRecipeRequest => {}
- ServerboundPlayPackets::PlayerAbilities => {
- self.handle_player_abilities(SPlayerAbilities::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::PlayerDigging => {
- self.handle_player_action(SPlayerAction::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::EntityAction => {
- self.handle_player_command(SPlayerCommand::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::PlayerInput => {}
- ServerboundPlayPackets::Pong => {}
- ServerboundPlayPackets::SetRecipeBookState => {}
- ServerboundPlayPackets::SetDisplayedRecipe => {}
- ServerboundPlayPackets::NameItem => {}
- ServerboundPlayPackets::ResourcePackStatus => {}
- ServerboundPlayPackets::AdvancementTab => {}
- ServerboundPlayPackets::SelectTrade => {}
- ServerboundPlayPackets::SetBeaconEffect => {}
- ServerboundPlayPackets::HeldItemChange => {
- self.handle_set_held_item(SSetHeldItem::read(bytebuf)?)
- .await;
- }
- ServerboundPlayPackets::UpdateCommandBlock => {}
- ServerboundPlayPackets::UpdateCommandBlockMinecart => {}
- ServerboundPlayPackets::CreativeInventoryAction => {
- self.handle_set_creative_slot(SSetCreativeSlot::read(bytebuf)?)
- .await?;
- }
- ServerboundPlayPackets::UpdateJigsawBlock => {}
- ServerboundPlayPackets::UpdateStructureBlock => {}
- ServerboundPlayPackets::UpdateSign => {}
- ServerboundPlayPackets::Animation => {
- self.handle_swing_arm(SSwingArm::read(bytebuf)?).await;
- }
- ServerboundPlayPackets::Spectate => {}
- ServerboundPlayPackets::PlayerBlockPlacement => {
- self.handle_use_item_on(SUseItemOn::read(bytebuf)?).await;
- }
- ServerboundPlayPackets::UseItem => self.handle_use_item(&SUseItem::read(bytebuf)?),
- };
- } else {
- log::error!("Failed to handle player packet id {:#04x}", packet.id.0);
- return Err(Box::new(DeserializerError::UnknownPacket));
+ match packet.id.0 {
+ SConfirmTeleport::PACKET_ID => {
+ self.handle_confirm_teleport(SConfirmTeleport::read(bytebuf)?)
+ .await;
+ }
+ SChatCommand::PACKET_ID => {
+ self.handle_chat_command(server, SChatCommand::read(bytebuf)?)
+ .await;
+ }
+ SChatMessage::PACKET_ID => {
+ self.handle_chat_message(SChatMessage::read(bytebuf)?).await;
+ }
+ SClientInformationPlay::PACKET_ID => {
+ self.handle_client_information(SClientInformationPlay::read(bytebuf)?)
+ .await;
+ }
+ SInteract::PACKET_ID => {
+ self.handle_interact(server, SInteract::read(bytebuf)?)
+ .await;
+ }
+ SKeepAlive::PACKET_ID => {
+ self.handle_keep_alive(SKeepAlive::read(bytebuf)?).await;
+ }
+ SPlayerPosition::PACKET_ID => {
+ self.handle_position(SPlayerPosition::read(bytebuf)?).await;
+ }
+ SPlayerPositionRotation::PACKET_ID => {
+ self.handle_position_rotation(SPlayerPositionRotation::read(bytebuf)?)
+ .await;
+ }
+ SPlayerRotation::PACKET_ID => {
+ self.handle_rotation(SPlayerRotation::read(bytebuf)?).await;
+ }
+ SSetPlayerGround::PACKET_ID => {
+ self.handle_player_ground(&SSetPlayerGround::read(bytebuf)?);
+ }
+ SPlayerAbilities::PACKET_ID => {
+ self.handle_player_abilities(SPlayerAbilities::read(bytebuf)?)
+ .await;
+ }
+ SPlayerAction::PACKET_ID => {
+ self.handle_player_action(SPlayerAction::read(bytebuf)?)
+ .await;
+ }
+ SPlayerCommand::PACKET_ID => {
+ self.handle_player_command(SPlayerCommand::read(bytebuf)?)
+ .await;
+ }
+ SSetHeldItem::PACKET_ID => {
+ self.handle_set_held_item(SSetHeldItem::read(bytebuf)?)
+ .await;
+ }
+ SSetCreativeSlot::PACKET_ID => {
+ self.handle_set_creative_slot(SSetCreativeSlot::read(bytebuf)?)
+ .await?;
+ }
+ SSwingArm::PACKET_ID => {
+ self.handle_swing_arm(SSwingArm::read(bytebuf)?).await;
+ }
+ SUseItemOn::PACKET_ID => {
+ self.handle_use_item_on(SUseItemOn::read(bytebuf)?).await;
+ }
+ SUseItem::PACKET_ID => self.handle_use_item(&SUseItem::read(bytebuf)?),
+ _ => {
+ log::warn!("Failed to handle player packet id {:#04x}", packet.id.0);
+ // TODO: We give an error if all play packets are implemented
+ // return Err(Box::new(DeserializerError::UnknownPacket));
+ }
};
Ok(())
}