From 3556e3d1c24d5387420fe97c6e76eeedaf57e517 Mon Sep 17 00:00:00 2001 From: zani Date: Tue, 11 Feb 2025 11:53:43 -0700 Subject: [PATCH] feat: packet registry --- assets/packets.json | 732 ++++++++++++++++++++ src/net/io.rs | 4 +- src/net/player.rs | 42 +- src/protocol/decoder.rs | 4 +- src/protocol/mod.rs | 144 +++- src/protocol/packets/login/config.rs | 21 +- src/protocol/packets/login/handshake.rs | 13 +- src/protocol/packets/login/login.rs | 25 +- src/protocol/packets/login/registry/mod.rs | 6 +- src/protocol/packets/login/registry/tags.rs | 6 +- src/protocol/packets/login/status.rs | 45 +- src/protocol/packets/play/container.rs | 9 +- src/protocol/packets/play/game_event.rs | 6 +- src/protocol/packets/play/interactions.rs | 11 +- src/protocol/packets/play/keepalive.rs | 10 +- src/protocol/packets/play/login.rs | 9 +- src/protocol/packets/play/position.rs | 10 +- src/protocol/packets/play/status.rs | 9 +- src/protocol/packets/play/teleport.rs | 10 +- src/protocol/packets/play/tick.rs | 10 +- src/protocol/packets/play/world.rs | 21 +- 21 files changed, 1036 insertions(+), 111 deletions(-) create mode 100644 assets/packets.json diff --git a/assets/packets.json b/assets/packets.json new file mode 100644 index 0000000..0c39708 --- /dev/null +++ b/assets/packets.json @@ -0,0 +1,732 @@ +{ + "configuration": { + "clientbound": { + "minecraft:cookie_request": { + "protocol_id": 0 + }, + "minecraft:custom_payload": { + "protocol_id": 1 + }, + "minecraft:custom_report_details": { + "protocol_id": 15 + }, + "minecraft:disconnect": { + "protocol_id": 2 + }, + "minecraft:finish_configuration": { + "protocol_id": 3 + }, + "minecraft:keep_alive": { + "protocol_id": 4 + }, + "minecraft:ping": { + "protocol_id": 5 + }, + "minecraft:registry_data": { + "protocol_id": 7 + }, + "minecraft:reset_chat": { + "protocol_id": 6 + }, + "minecraft:resource_pack_pop": { + "protocol_id": 8 + }, + "minecraft:resource_pack_push": { + "protocol_id": 9 + }, + "minecraft:select_known_packs": { + "protocol_id": 14 + }, + "minecraft:server_links": { + "protocol_id": 16 + }, + "minecraft:store_cookie": { + "protocol_id": 10 + }, + "minecraft:transfer": { + "protocol_id": 11 + }, + "minecraft:update_enabled_features": { + "protocol_id": 12 + }, + "minecraft:update_tags": { + "protocol_id": 13 + } + }, + "serverbound": { + "minecraft:client_information": { + "protocol_id": 0 + }, + "minecraft:cookie_response": { + "protocol_id": 1 + }, + "minecraft:custom_payload": { + "protocol_id": 2 + }, + "minecraft:finish_configuration": { + "protocol_id": 3 + }, + "minecraft:keep_alive": { + "protocol_id": 4 + }, + "minecraft:pong": { + "protocol_id": 5 + }, + "minecraft:resource_pack": { + "protocol_id": 6 + }, + "minecraft:select_known_packs": { + "protocol_id": 7 + } + } + }, + "handshake": { + "serverbound": { + "minecraft:intention": { + "protocol_id": 0 + } + } + }, + "login": { + "clientbound": { + "minecraft:cookie_request": { + "protocol_id": 5 + }, + "minecraft:custom_query": { + "protocol_id": 4 + }, + "minecraft:hello": { + "protocol_id": 1 + }, + "minecraft:login_compression": { + "protocol_id": 3 + }, + "minecraft:login_disconnect": { + "protocol_id": 0 + }, + "minecraft:login_finished": { + "protocol_id": 2 + } + }, + "serverbound": { + "minecraft:cookie_response": { + "protocol_id": 4 + }, + "minecraft:custom_query_answer": { + "protocol_id": 2 + }, + "minecraft:hello": { + "protocol_id": 0 + }, + "minecraft:key": { + "protocol_id": 1 + }, + "minecraft:login_acknowledged": { + "protocol_id": 3 + } + } + }, + "play": { + "clientbound": { + "minecraft:add_entity": { + "protocol_id": 1 + }, + "minecraft:add_experience_orb": { + "protocol_id": 2 + }, + "minecraft:animate": { + "protocol_id": 3 + }, + "minecraft:award_stats": { + "protocol_id": 4 + }, + "minecraft:block_changed_ack": { + "protocol_id": 5 + }, + "minecraft:block_destruction": { + "protocol_id": 6 + }, + "minecraft:block_entity_data": { + "protocol_id": 7 + }, + "minecraft:block_event": { + "protocol_id": 8 + }, + "minecraft:block_update": { + "protocol_id": 9 + }, + "minecraft:boss_event": { + "protocol_id": 10 + }, + "minecraft:bundle_delimiter": { + "protocol_id": 0 + }, + "minecraft:change_difficulty": { + "protocol_id": 11 + }, + "minecraft:chunk_batch_finished": { + "protocol_id": 12 + }, + "minecraft:chunk_batch_start": { + "protocol_id": 13 + }, + "minecraft:chunks_biomes": { + "protocol_id": 14 + }, + "minecraft:clear_titles": { + "protocol_id": 15 + }, + "minecraft:command_suggestions": { + "protocol_id": 16 + }, + "minecraft:commands": { + "protocol_id": 17 + }, + "minecraft:container_close": { + "protocol_id": 18 + }, + "minecraft:container_set_content": { + "protocol_id": 19 + }, + "minecraft:container_set_data": { + "protocol_id": 20 + }, + "minecraft:container_set_slot": { + "protocol_id": 21 + }, + "minecraft:cookie_request": { + "protocol_id": 22 + }, + "minecraft:cooldown": { + "protocol_id": 23 + }, + "minecraft:custom_chat_completions": { + "protocol_id": 24 + }, + "minecraft:custom_payload": { + "protocol_id": 25 + }, + "minecraft:custom_report_details": { + "protocol_id": 129 + }, + "minecraft:damage_event": { + "protocol_id": 26 + }, + "minecraft:debug_sample": { + "protocol_id": 27 + }, + "minecraft:delete_chat": { + "protocol_id": 28 + }, + "minecraft:disconnect": { + "protocol_id": 29 + }, + "minecraft:disguised_chat": { + "protocol_id": 30 + }, + "minecraft:entity_event": { + "protocol_id": 31 + }, + "minecraft:entity_position_sync": { + "protocol_id": 32 + }, + "minecraft:explode": { + "protocol_id": 33 + }, + "minecraft:forget_level_chunk": { + "protocol_id": 34 + }, + "minecraft:game_event": { + "protocol_id": 35 + }, + "minecraft:horse_screen_open": { + "protocol_id": 36 + }, + "minecraft:hurt_animation": { + "protocol_id": 37 + }, + "minecraft:initialize_border": { + "protocol_id": 38 + }, + "minecraft:keep_alive": { + "protocol_id": 39 + }, + "minecraft:level_chunk_with_light": { + "protocol_id": 40 + }, + "minecraft:level_event": { + "protocol_id": 41 + }, + "minecraft:level_particles": { + "protocol_id": 42 + }, + "minecraft:light_update": { + "protocol_id": 43 + }, + "minecraft:login": { + "protocol_id": 44 + }, + "minecraft:map_item_data": { + "protocol_id": 45 + }, + "minecraft:merchant_offers": { + "protocol_id": 46 + }, + "minecraft:move_entity_pos": { + "protocol_id": 47 + }, + "minecraft:move_entity_pos_rot": { + "protocol_id": 48 + }, + "minecraft:move_entity_rot": { + "protocol_id": 50 + }, + "minecraft:move_minecart_along_track": { + "protocol_id": 49 + }, + "minecraft:move_vehicle": { + "protocol_id": 51 + }, + "minecraft:open_book": { + "protocol_id": 52 + }, + "minecraft:open_screen": { + "protocol_id": 53 + }, + "minecraft:open_sign_editor": { + "protocol_id": 54 + }, + "minecraft:ping": { + "protocol_id": 55 + }, + "minecraft:place_ghost_recipe": { + "protocol_id": 57 + }, + "minecraft:player_abilities": { + "protocol_id": 58 + }, + "minecraft:player_chat": { + "protocol_id": 59 + }, + "minecraft:player_combat_end": { + "protocol_id": 60 + }, + "minecraft:player_combat_enter": { + "protocol_id": 61 + }, + "minecraft:player_combat_kill": { + "protocol_id": 62 + }, + "minecraft:player_info_remove": { + "protocol_id": 63 + }, + "minecraft:player_info_update": { + "protocol_id": 64 + }, + "minecraft:player_look_at": { + "protocol_id": 65 + }, + "minecraft:player_position": { + "protocol_id": 66 + }, + "minecraft:player_rotation": { + "protocol_id": 67 + }, + "minecraft:pong_response": { + "protocol_id": 56 + }, + "minecraft:projectile_power": { + "protocol_id": 128 + }, + "minecraft:recipe_book_add": { + "protocol_id": 68 + }, + "minecraft:recipe_book_remove": { + "protocol_id": 69 + }, + "minecraft:recipe_book_settings": { + "protocol_id": 70 + }, + "minecraft:remove_entities": { + "protocol_id": 71 + }, + "minecraft:remove_mob_effect": { + "protocol_id": 72 + }, + "minecraft:reset_score": { + "protocol_id": 73 + }, + "minecraft:resource_pack_pop": { + "protocol_id": 74 + }, + "minecraft:resource_pack_push": { + "protocol_id": 75 + }, + "minecraft:respawn": { + "protocol_id": 76 + }, + "minecraft:rotate_head": { + "protocol_id": 77 + }, + "minecraft:section_blocks_update": { + "protocol_id": 78 + }, + "minecraft:select_advancements_tab": { + "protocol_id": 79 + }, + "minecraft:server_data": { + "protocol_id": 80 + }, + "minecraft:server_links": { + "protocol_id": 130 + }, + "minecraft:set_action_bar_text": { + "protocol_id": 81 + }, + "minecraft:set_border_center": { + "protocol_id": 82 + }, + "minecraft:set_border_lerp_size": { + "protocol_id": 83 + }, + "minecraft:set_border_size": { + "protocol_id": 84 + }, + "minecraft:set_border_warning_delay": { + "protocol_id": 85 + }, + "minecraft:set_border_warning_distance": { + "protocol_id": 86 + }, + "minecraft:set_camera": { + "protocol_id": 87 + }, + "minecraft:set_chunk_cache_center": { + "protocol_id": 88 + }, + "minecraft:set_chunk_cache_radius": { + "protocol_id": 89 + }, + "minecraft:set_cursor_item": { + "protocol_id": 90 + }, + "minecraft:set_default_spawn_position": { + "protocol_id": 91 + }, + "minecraft:set_display_objective": { + "protocol_id": 92 + }, + "minecraft:set_entity_data": { + "protocol_id": 93 + }, + "minecraft:set_entity_link": { + "protocol_id": 94 + }, + "minecraft:set_entity_motion": { + "protocol_id": 95 + }, + "minecraft:set_equipment": { + "protocol_id": 96 + }, + "minecraft:set_experience": { + "protocol_id": 97 + }, + "minecraft:set_health": { + "protocol_id": 98 + }, + "minecraft:set_held_slot": { + "protocol_id": 99 + }, + "minecraft:set_objective": { + "protocol_id": 100 + }, + "minecraft:set_passengers": { + "protocol_id": 101 + }, + "minecraft:set_player_inventory": { + "protocol_id": 102 + }, + "minecraft:set_player_team": { + "protocol_id": 103 + }, + "minecraft:set_score": { + "protocol_id": 104 + }, + "minecraft:set_simulation_distance": { + "protocol_id": 105 + }, + "minecraft:set_subtitle_text": { + "protocol_id": 106 + }, + "minecraft:set_time": { + "protocol_id": 107 + }, + "minecraft:set_title_text": { + "protocol_id": 108 + }, + "minecraft:set_titles_animation": { + "protocol_id": 109 + }, + "minecraft:sound": { + "protocol_id": 111 + }, + "minecraft:sound_entity": { + "protocol_id": 110 + }, + "minecraft:start_configuration": { + "protocol_id": 112 + }, + "minecraft:stop_sound": { + "protocol_id": 113 + }, + "minecraft:store_cookie": { + "protocol_id": 114 + }, + "minecraft:system_chat": { + "protocol_id": 115 + }, + "minecraft:tab_list": { + "protocol_id": 116 + }, + "minecraft:tag_query": { + "protocol_id": 117 + }, + "minecraft:take_item_entity": { + "protocol_id": 118 + }, + "minecraft:teleport_entity": { + "protocol_id": 119 + }, + "minecraft:ticking_state": { + "protocol_id": 120 + }, + "minecraft:ticking_step": { + "protocol_id": 121 + }, + "minecraft:transfer": { + "protocol_id": 122 + }, + "minecraft:update_advancements": { + "protocol_id": 123 + }, + "minecraft:update_attributes": { + "protocol_id": 124 + }, + "minecraft:update_mob_effect": { + "protocol_id": 125 + }, + "minecraft:update_recipes": { + "protocol_id": 126 + }, + "minecraft:update_tags": { + "protocol_id": 127 + } + }, + "serverbound": { + "minecraft:accept_teleportation": { + "protocol_id": 0 + }, + "minecraft:block_entity_tag_query": { + "protocol_id": 1 + }, + "minecraft:bundle_item_selected": { + "protocol_id": 2 + }, + "minecraft:change_difficulty": { + "protocol_id": 3 + }, + "minecraft:chat": { + "protocol_id": 7 + }, + "minecraft:chat_ack": { + "protocol_id": 4 + }, + "minecraft:chat_command": { + "protocol_id": 5 + }, + "minecraft:chat_command_signed": { + "protocol_id": 6 + }, + "minecraft:chat_session_update": { + "protocol_id": 8 + }, + "minecraft:chunk_batch_received": { + "protocol_id": 9 + }, + "minecraft:client_command": { + "protocol_id": 10 + }, + "minecraft:client_information": { + "protocol_id": 12 + }, + "minecraft:client_tick_end": { + "protocol_id": 11 + }, + "minecraft:command_suggestion": { + "protocol_id": 13 + }, + "minecraft:configuration_acknowledged": { + "protocol_id": 14 + }, + "minecraft:container_button_click": { + "protocol_id": 15 + }, + "minecraft:container_click": { + "protocol_id": 16 + }, + "minecraft:container_close": { + "protocol_id": 17 + }, + "minecraft:container_slot_state_changed": { + "protocol_id": 18 + }, + "minecraft:cookie_response": { + "protocol_id": 19 + }, + "minecraft:custom_payload": { + "protocol_id": 20 + }, + "minecraft:debug_sample_subscription": { + "protocol_id": 21 + }, + "minecraft:edit_book": { + "protocol_id": 22 + }, + "minecraft:entity_tag_query": { + "protocol_id": 23 + }, + "minecraft:interact": { + "protocol_id": 24 + }, + "minecraft:jigsaw_generate": { + "protocol_id": 25 + }, + "minecraft:keep_alive": { + "protocol_id": 26 + }, + "minecraft:lock_difficulty": { + "protocol_id": 27 + }, + "minecraft:move_player_pos": { + "protocol_id": 28 + }, + "minecraft:move_player_pos_rot": { + "protocol_id": 29 + }, + "minecraft:move_player_rot": { + "protocol_id": 30 + }, + "minecraft:move_player_status_only": { + "protocol_id": 31 + }, + "minecraft:move_vehicle": { + "protocol_id": 32 + }, + "minecraft:paddle_boat": { + "protocol_id": 33 + }, + "minecraft:pick_item_from_block": { + "protocol_id": 34 + }, + "minecraft:pick_item_from_entity": { + "protocol_id": 35 + }, + "minecraft:ping_request": { + "protocol_id": 36 + }, + "minecraft:place_recipe": { + "protocol_id": 37 + }, + "minecraft:player_abilities": { + "protocol_id": 38 + }, + "minecraft:player_action": { + "protocol_id": 39 + }, + "minecraft:player_command": { + "protocol_id": 40 + }, + "minecraft:player_input": { + "protocol_id": 41 + }, + "minecraft:player_loaded": { + "protocol_id": 42 + }, + "minecraft:pong": { + "protocol_id": 43 + }, + "minecraft:recipe_book_change_settings": { + "protocol_id": 44 + }, + "minecraft:recipe_book_seen_recipe": { + "protocol_id": 45 + }, + "minecraft:rename_item": { + "protocol_id": 46 + }, + "minecraft:resource_pack": { + "protocol_id": 47 + }, + "minecraft:seen_advancements": { + "protocol_id": 48 + }, + "minecraft:select_trade": { + "protocol_id": 49 + }, + "minecraft:set_beacon": { + "protocol_id": 50 + }, + "minecraft:set_carried_item": { + "protocol_id": 51 + }, + "minecraft:set_command_block": { + "protocol_id": 52 + }, + "minecraft:set_command_minecart": { + "protocol_id": 53 + }, + "minecraft:set_creative_mode_slot": { + "protocol_id": 54 + }, + "minecraft:set_jigsaw_block": { + "protocol_id": 55 + }, + "minecraft:set_structure_block": { + "protocol_id": 56 + }, + "minecraft:sign_update": { + "protocol_id": 57 + }, + "minecraft:swing": { + "protocol_id": 58 + }, + "minecraft:teleport_to_entity": { + "protocol_id": 59 + }, + "minecraft:use_item": { + "protocol_id": 61 + }, + "minecraft:use_item_on": { + "protocol_id": 60 + } + } + }, + "status": { + "clientbound": { + "minecraft:pong_response": { + "protocol_id": 1 + }, + "minecraft:status_response": { + "protocol_id": 0 + } + }, + "serverbound": { + "minecraft:ping_request": { + "protocol_id": 1 + }, + "minecraft:status_request": { + "protocol_id": 0 + } + } + } +} \ No newline at end of file diff --git a/src/net/io.rs b/src/net/io.rs index 80ed102..6ec95f4 100644 --- a/src/net/io.rs +++ b/src/net/io.rs @@ -86,11 +86,11 @@ impl NetIo { let mut decoder = self.decoder.lock().await; loop { if let Some(frame) = decoder.try_read_next().context("failed try_read_next")? { - if frame.id != P::ID { + if frame.id != P::get_id() { debug!( "Got packet ID {} while awaiting {}, discarding", frame.id, - P::ID + P::get_id() ); continue; } diff --git a/src/net/player.rs b/src/net/player.rs index fec9fd9..43be169 100644 --- a/src/net/player.rs +++ b/src/net/player.rs @@ -48,7 +48,7 @@ use crate::{ SetPlayerPositionS, SetTickingStateC, StepTicksC, SynchronisePositionC, UseItemOnS, }, }, - Frame, Packet, PacketState, + Frame, Packet, ProtocolState, }, server::window::{Window, WindowType}, CrawlState, @@ -56,7 +56,7 @@ use crate::{ #[cfg(feature = "encryption")] use crate::protocol::{datatypes::Bytes, packets::login::PluginRequestC}; - +use crate::protocol::{PacketDirection, PACKETS}; use super::{entity::Entity, io::NetIo}; #[derive(Debug)] @@ -67,7 +67,7 @@ pub struct Player { frame_queue: Mutex>, crawlstate: CrawlState, - packet_state: RwLock, + protocol_state: RwLock, uuid: RwLock>, tp_state: RwLock, @@ -104,7 +104,7 @@ impl SharedPlayer { _permit: permit, crawlstate, - packet_state: RwLock::new(PacketState::Handshaking), + protocol_state: RwLock::new(ProtocolState::Handshaking), uuid: RwLock::new(None), tp_state: RwLock::new(TeleportState::Clear), @@ -136,8 +136,8 @@ impl SharedPlayer { Err(e) => warn!("Timed out waiting for {} to connect: {e}", self.0.id), Ok(Err(why)) => warn!("Error handshaking: {why}"), Ok(Ok(())) => { - let s = self.0.packet_state.read().await; - if let PacketState::Status = *s { + let s = self.0.protocol_state.read().await; + if let ProtocolState::Status = *s { return; } drop(s); @@ -170,15 +170,15 @@ impl SharedPlayer { let next_state = p.next_state; - let mut s = self.0.packet_state.write().await; + let mut s = self.0.protocol_state.write().await; match next_state { - PacketState::Status => { - *s = PacketState::Status; + ProtocolState::Status => { + *s = ProtocolState::Status; drop(s); self.handle_status().await?; } - PacketState::Login => { - *s = PacketState::Login; + ProtocolState::Login => { + *s = ProtocolState::Login; drop(s); self.login().await?; } @@ -212,9 +212,11 @@ impl SharedPlayer { }; self.0.io.tx(&res).await?; - let ping: Ping = self.0.io.rx::().await?.decode()?; + let ping: PingS = self.0.io.rx::().await?.decode()?; - self.0.io.tx(&ping).await?; + self.0.io.tx(&PingC { + payload: ping.payload + }).await?; Ok(()) } @@ -287,8 +289,8 @@ impl SharedPlayer { } async fn begin_play(&self) -> Result<()> { - let mut packet_state = self.0.packet_state.write().await; - *packet_state = PacketState::Play; + let mut packet_state = self.0.protocol_state.write().await; + *packet_state = ProtocolState::Play; let state = self.0.crawlstate.clone(); @@ -526,7 +528,15 @@ impl SharedPlayer { } async fn handle_frame(&self, frame: Frame) -> Result<()> { - match frame.id { + let packet_state = self.0.protocol_state.read().await.to_owned().into(); + let resource = PACKETS + .get_resource_id(packet_state, PacketDirection::Serverbound, frame.id) + .unwrap_or_else(|| { + panic!("{} cannot map to any resource in state {:?}", frame.id, packet_state) + }) + .as_str(); + + match resource { SetPlayerPositionS::ID => { let packet: SetPlayerPositionS = frame.decode()?; diff --git a/src/protocol/decoder.rs b/src/protocol/decoder.rs index 7e3e6d8..227e060 100644 --- a/src/protocol/decoder.rs +++ b/src/protocol/decoder.rs @@ -49,9 +49,9 @@ impl Frame { P: ServerboundPacket<'a>, { ensure!( - P::ID == self.id, + P::get_id() == self.id, "Mismatched packet IDs: expected {} got {}", - P::ID, + P::get_id(), self.id ); diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 6a6848c..6e130db 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -78,13 +78,85 @@ mod decoder; mod encoder; use std::{fmt::Debug, io::Write}; - +use std::collections::HashMap; +use std::sync::LazyLock; use bit_vec::BitVec; use color_eyre::eyre::{Context, Result}; +use serde::{Deserialize, Serialize}; use datatypes::{Bounded, VarInt}; +use thiserror::Error; + pub use decoder::*; pub use encoder::*; -use thiserror::Error; + +pub static PACKETS: LazyLock = LazyLock::new(|| { + Packets::new( + serde_json::from_str(include_str!("../../assets/packets.json")) + .expect("packets.json should be parseable") + ) +}); + +#[derive(Clone, Debug, Deserialize)] +pub struct PacketType { + pub protocol_id: i32, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct ForwardPackets(pub HashMap>>); + +#[derive(Clone, Debug)] +pub struct Packets { + forward: ForwardPackets, + reverse: HashMap>> +} + +impl Packets { + pub fn new(forward: ForwardPackets) -> Self { + Self { + reverse: Self::build_reverse(&forward), + forward + } + } + + pub fn get_protocol_id(&self, state: PacketState, direction: PacketDirection, name: &str) -> Option { + Some( + self.forward + .0.get(&state) + ?.get(&direction) + ?.get(name.into()) + ?.protocol_id + ) + } + + pub fn get_resource_id(&self, state: PacketState, direction: PacketDirection, protocol_id: i32) -> Option<&String> { + Some( + self.reverse + .get(&state) + ?.get(&direction) + ?.get(&protocol_id)? + ) + } + + fn build_reverse(forward: &ForwardPackets) -> HashMap>> { + let mut reverse = HashMap::new(); + + for state in forward.0.keys() { + let direction_mapping = reverse + .entry(*state) + .or_insert_with(|| { HashMap::new() }) + .entry(PacketDirection::Serverbound) + .or_insert_with(|| { HashMap::new() }); + + for (key, value) in forward.0.get(&state).unwrap().get(&PacketDirection::Serverbound).unwrap() { + direction_mapping + .entry(value.protocol_id) + .or_insert_with(move || { key.clone() }); + } + } + + reverse + } +} const MAX_PACKET_SIZE: i32 = 2097152; @@ -102,8 +174,25 @@ pub trait DecodeSized<'a>: Sized { fn decode(times: usize, r: &mut &'a [u8]) -> Result; } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum PacketDirection { + Clientbound, + Serverbound, +} + +#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Deserialize)] +#[serde(rename_all = "lowercase")] pub enum PacketState { + Handshake, + Login, + Configuration, + Play, + Status +} + +#[derive(Clone, Copy, Debug)] +pub enum ProtocolState { Handshaking, Play, Status, @@ -112,29 +201,58 @@ pub enum PacketState { } #[derive(Error, Debug)] -pub enum PacketStateDecodeError { +pub enum ProtocolStateDecodeError { #[error("Unable to decode {0} into a PacketState")] InvalidState(i32), } -impl TryFrom for PacketState { - type Error = PacketStateDecodeError; +impl Into for ProtocolState { + fn into(self) -> PacketState { + match self { + ProtocolState::Handshaking => PacketState::Handshake, + ProtocolState::Play => PacketState::Play, + ProtocolState::Status => PacketState::Status, + ProtocolState::Login => PacketState::Login, + ProtocolState::Transfer => PacketState::Login + } + } +} + +impl TryFrom for ProtocolState { + type Error = ProtocolStateDecodeError; fn try_from(value: i32) -> Result { match value { - 1 => Ok(PacketState::Status), - 2 => Ok(PacketState::Login), - 3 => Ok(PacketState::Transfer), - i => Err(PacketStateDecodeError::InvalidState(i)), + 1 => Ok(ProtocolState::Status), + 2 => Ok(ProtocolState::Login), + 3 => Ok(ProtocolState::Transfer), + i => Err(ProtocolStateDecodeError::InvalidState(i)), } } } pub trait Packet { - const ID: i32; + const ID: &'static str; + const STATE: PacketState; + const DIRECTION: PacketDirection; + + fn get_id() -> i32 { + PACKETS + .get_protocol_id(Self::STATE, Self::DIRECTION, Self::ID) + .unwrap_or_else(|| { + panic!( + "expected packet {:?}/{} ({:?}) to exist", + Self::STATE, + Self::ID, + Self::DIRECTION + ) + }) + } } -pub trait ServerboundPacket<'a>: Packet + Decode<'a> + Debug {} +pub trait ServerboundPacket<'a>: Packet + Decode<'a> + Debug { + const DIRECTION: PacketDirection = PacketDirection::Serverbound; +} impl<'a, P> ServerboundPacket<'a> for P where P: Packet + Decode<'a> + Debug {} pub trait ClientboundPacket: Packet + Encode + Debug { @@ -142,7 +260,7 @@ pub trait ClientboundPacket: Packet + Encode + Debug { where Self: Encode, { - VarInt(Self::ID) + VarInt(Self::get_id()) .encode(&mut w) .context("Failed to encode packet id")?; diff --git a/src/protocol/packets/login/config.rs b/src/protocol/packets/login/config.rs index 0a603fb..a4a64c7 100644 --- a/src/protocol/packets/login/config.rs +++ b/src/protocol/packets/login/config.rs @@ -19,10 +19,7 @@ use color_eyre::eyre::{ensure, Result}; -use crate::protocol::{ - datatypes::{Bounded, VarInt}, - Decode, DecodeSized, Encode, Packet, -}; +use crate::protocol::{datatypes::{Bounded, VarInt}, Decode, DecodeSized, Encode, Packet, PacketDirection, PacketState, ProtocolState}; #[derive(Debug)] pub struct KnownPacksC<'a> { @@ -38,7 +35,9 @@ pub struct KnownPack<'a> { } impl Packet for KnownPacksC<'_> { - const ID: i32 = 0x0E; + const ID: &'static str = "minecraft:select_known_packs"; + const STATE: PacketState = PacketState::Configuration; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for KnownPacksC<'_> { @@ -87,7 +86,9 @@ pub struct KnownPacksS<'a> { } impl Packet for KnownPacksS<'_> { - const ID: i32 = 0x07; + const ID: &'static str = "minecraft:select_known_packs"; + const STATE: PacketState = PacketState::Configuration; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl<'a> Decode<'a> for KnownPacksS<'a> { @@ -116,7 +117,9 @@ impl<'a> Decode<'a> for KnownPack<'a> { pub struct FinishConfigurationC; impl Packet for FinishConfigurationC { - const ID: i32 = 0x03; + const ID: &'static str = "minecraft:finish_configuration"; + const STATE: PacketState = PacketState::Configuration; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for FinishConfigurationC { @@ -129,7 +132,9 @@ impl Encode for FinishConfigurationC { pub struct FinishConfigurationAckS; impl Packet for FinishConfigurationAckS { - const ID: i32 = 0x03; + const ID: &'static str = "minecraft:finish_configuration"; + const STATE: PacketState = PacketState::Configuration; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl<'a> Decode<'a> for FinishConfigurationAckS { diff --git a/src/protocol/packets/login/handshake.rs b/src/protocol/packets/login/handshake.rs index 8d13e15..d2b5997 100644 --- a/src/protocol/packets/login/handshake.rs +++ b/src/protocol/packets/login/handshake.rs @@ -20,21 +20,20 @@ use byteorder::{BigEndian, ReadBytesExt}; use color_eyre::eyre::Result; -use crate::protocol::{ - datatypes::{Bounded, VarInt}, - Decode, Packet, PacketState, -}; +use crate::protocol::{datatypes::{Bounded, VarInt}, Decode, Packet, PacketDirection, PacketState, ProtocolState}; #[derive(Debug)] pub struct HandshakeS<'a> { pub protocol_version: VarInt, _server_address: Bounded<&'a str, 255>, _server_port: u16, - pub next_state: PacketState, + pub next_state: ProtocolState, } impl Packet for HandshakeS<'_> { - const ID: i32 = 0x00; + const ID: &'static str = "minecraft:intention"; + const STATE: PacketState = PacketState::Handshake; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl<'a> Decode<'a> for HandshakeS<'a> { @@ -43,7 +42,7 @@ impl<'a> Decode<'a> for HandshakeS<'a> { protocol_version: VarInt::decode(buf)?, _server_address: Bounded::<&'a str, 255>::decode(buf)?, _server_port: buf.read_u16::()?, - next_state: PacketState::try_from(VarInt::decode(buf)?.0)?, + next_state: ProtocolState::try_from(VarInt::decode(buf)?.0)?, }) } } diff --git a/src/protocol/packets/login/login.rs b/src/protocol/packets/login/login.rs index 5638abe..1e3c079 100644 --- a/src/protocol/packets/login/login.rs +++ b/src/protocol/packets/login/login.rs @@ -20,10 +20,7 @@ use color_eyre::eyre::Result; use uuid::Uuid; -use crate::protocol::{ - datatypes::{Bounded, Bytes, Rest, VarInt}, - Decode, Encode, Packet, Property, -}; +use crate::protocol::{datatypes::{Bounded, Bytes, Rest, VarInt}, Decode, Encode, Packet, PacketDirection, PacketState, Property}; #[derive(Debug)] pub struct LoginStartS<'a> { @@ -32,7 +29,9 @@ pub struct LoginStartS<'a> { } impl Packet for LoginStartS<'_> { - const ID: i32 = 0x00; + const ID: &'static str = "minecraft:hello"; + const STATE: PacketState = PacketState::Login; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl<'a> Decode<'a> for LoginStartS<'a> { @@ -52,7 +51,9 @@ pub struct LoginSuccessC<'a> { } impl Packet for LoginSuccessC<'_> { - const ID: i32 = 0x02; + const ID: &'static str = "minecraft:login_finished"; + const STATE: PacketState = PacketState::Login; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl<'a> Encode for LoginSuccessC<'a> { @@ -76,7 +77,9 @@ pub struct PluginRequestC<'a> { } impl Packet for PluginRequestC<'_> { - const ID: i32 = 0x04; + const ID: &'static str = "minecraft:custom_query"; + const STATE: PacketState = PacketState::Login; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl<'a> Encode for PluginRequestC<'a> { @@ -96,7 +99,9 @@ pub struct PluginResponseS<'a> { } impl Packet for PluginResponseS<'_> { - const ID: i32 = 0x02; + const ID: &'static str = "minecraft:custom_query_answer"; + const STATE: PacketState = PacketState::Login; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl<'a> Decode<'a> for PluginResponseS<'a> { @@ -112,7 +117,9 @@ impl<'a> Decode<'a> for PluginResponseS<'a> { pub struct LoginAckS; impl Packet for LoginAckS { - const ID: i32 = 0x03; + const ID: &'static str = "minecraft:login_acknowledged"; + const STATE: PacketState = PacketState::Login; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl Decode<'_> for LoginAckS { diff --git a/src/protocol/packets/login/registry/mod.rs b/src/protocol/packets/login/registry/mod.rs index b226178..34d9cb4 100644 --- a/src/protocol/packets/login/registry/mod.rs +++ b/src/protocol/packets/login/registry/mod.rs @@ -22,7 +22,7 @@ use std::{collections::HashMap, sync::LazyLock}; use fastnbt::SerOpts; use serde::{de, Deserialize, Serialize}; -use crate::protocol::{datatypes::VarInt, Encode, Packet}; +use crate::protocol::{datatypes::VarInt, Encode, Packet, PacketDirection, PacketState}; mod banner; mod biome; @@ -75,7 +75,9 @@ impl Packet for Registry where T: RegistryItem, { - const ID: i32 = 0x07; + const ID: &'static str = "minecraft:registry_data"; + const STATE: PacketState = PacketState::Configuration; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/src/protocol/packets/login/registry/tags.rs b/src/protocol/packets/login/registry/tags.rs index ef3352f..bb9633e 100644 --- a/src/protocol/packets/login/registry/tags.rs +++ b/src/protocol/packets/login/registry/tags.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use crate::protocol::{Encode, Packet}; +use crate::protocol::{Encode, Packet, PacketDirection, PacketState}; use crate::protocol::datatypes::{Bounded, VarInt}; #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] @@ -9,7 +9,9 @@ pub struct AllTags(pub HashMap); pub struct Tags(pub HashMap>); impl Packet for AllTags { - const ID: i32 = 0x0D; + const ID: &'static str = "minecraft:update_tags"; + const STATE: PacketState = PacketState::Configuration; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for AllTags { diff --git a/src/protocol/packets/login/status.rs b/src/protocol/packets/login/status.rs index 61da817..2918f6f 100644 --- a/src/protocol/packets/login/status.rs +++ b/src/protocol/packets/login/status.rs @@ -22,13 +22,15 @@ use std::io::Write; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use color_eyre::eyre::Result; -use crate::protocol::{Decode, Encode, Packet}; +use crate::protocol::{Decode, Encode, Packet, PacketDirection, PacketState}; #[derive(Debug)] pub struct StatusRequestS; impl Packet for StatusRequestS { - const ID: i32 = 0x00; + const ID: &'static str = "minecraft:status_request"; + const STATE: PacketState = PacketState::Status; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl<'a> Decode<'a> for StatusRequestS { @@ -43,7 +45,9 @@ pub struct StatusResponseC<'a> { } impl<'a> Packet for StatusResponseC<'a> { - const ID: i32 = 0x00; + const ID: &'static str = "minecraft:status_response"; + const STATE: PacketState = PacketState::Status; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl<'a> Encode for StatusResponseC<'a> { @@ -53,24 +57,37 @@ impl<'a> Encode for StatusResponseC<'a> { } #[derive(Debug)] -pub struct Ping { - payload: i64, +pub struct PingC { + pub payload: i64, } -impl Packet for Ping { - const ID: i32 = 0x01; +#[derive(Debug)] +pub struct PingS { + pub payload: i64, } -impl<'a> Decode<'a> for Ping { - fn decode(buf: &mut &'a [u8]) -> Result { - Ok(Self { - payload: buf.read_i64::()?, - }) - } +impl Packet for PingC { + const ID: &'static str = "minecraft:ping"; + const STATE: PacketState = PacketState::Status; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; +} + +impl Packet for PingS { + const ID: &'static str = "minecraft:pong"; + const STATE: PacketState = PacketState::Status; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } -impl Encode for Ping { +impl Encode for PingC { fn encode(&self, mut w: impl Write) -> Result<()> { Ok(w.write_i64::(self.payload)?) } } + +impl<'a> Decode<'a> for PingS { + fn decode(buf: &mut &'a [u8]) -> Result { + Ok(Self { + payload: buf.read_i64::()?, + }) + } +} diff --git a/src/protocol/packets/play/container.rs b/src/protocol/packets/play/container.rs index 674ee75..f6ca665 100644 --- a/src/protocol/packets/play/container.rs +++ b/src/protocol/packets/play/container.rs @@ -24,6 +24,7 @@ use crate::{ }, server::window::{Window, WindowType}, }; +use crate::protocol::{PacketDirection, PacketState}; #[derive(Debug)] pub struct OpenScreenC { @@ -33,7 +34,9 @@ pub struct OpenScreenC { } impl Packet for OpenScreenC { - const ID: i32 = 0x35; + const ID: &'static str = "minecraft:open_screen"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for OpenScreenC { @@ -66,7 +69,9 @@ pub struct SetContainerContentC { } impl Packet for SetContainerContentC { - const ID: i32 = 0x13; + const ID: &'static str = "minecraft:container_set_content"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for SetContainerContentC { diff --git a/src/protocol/packets/play/game_event.rs b/src/protocol/packets/play/game_event.rs index cfa066a..6baf7c0 100644 --- a/src/protocol/packets/play/game_event.rs +++ b/src/protocol/packets/play/game_event.rs @@ -17,7 +17,7 @@ * . */ -use crate::protocol::{Encode, Packet}; +use crate::protocol::{Encode, Packet, PacketDirection, PacketState}; use super::Gamemode; @@ -28,7 +28,9 @@ pub struct GameEventC { } impl Packet for GameEventC { - const ID: i32 = 0x23; + const ID: &'static str = "minecraft:game_event"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for GameEventC { diff --git a/src/protocol/packets/play/interactions.rs b/src/protocol/packets/play/interactions.rs index 0a7248c..db786c7 100644 --- a/src/protocol/packets/play/interactions.rs +++ b/src/protocol/packets/play/interactions.rs @@ -19,10 +19,7 @@ use byteorder::{BigEndian, ReadBytesExt}; -use crate::protocol::{ - datatypes::{Position, VarInt}, - Decode, Packet, -}; +use crate::protocol::{datatypes::{Position, VarInt}, Decode, Packet, PacketDirection, PacketState}; #[derive(Debug)] pub struct UseItemOnS { @@ -33,6 +30,7 @@ pub struct UseItemOnS { pub cursor_y: f32, pub cursor_z: f32, pub inside_block: bool, + pub world_border_hit: bool, pub sequence: VarInt, } @@ -93,7 +91,9 @@ impl TryFrom for Face { } impl Packet for UseItemOnS { - const ID: i32 = 0x3C; + const ID: &'static str = "minecraft:use_item_on"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl Decode<'_> for UseItemOnS { @@ -109,6 +109,7 @@ impl Decode<'_> for UseItemOnS { cursor_y: r.read_f32::()?, cursor_z: r.read_f32::()?, inside_block: r.read_u8()? == 1, + world_border_hit: r.read_u8()? == 1, sequence: VarInt::decode(r)?, }) } diff --git a/src/protocol/packets/play/keepalive.rs b/src/protocol/packets/play/keepalive.rs index 9d2515f..884aa98 100644 --- a/src/protocol/packets/play/keepalive.rs +++ b/src/protocol/packets/play/keepalive.rs @@ -17,13 +17,15 @@ * . */ -use crate::protocol::{Decode, Encode, Packet}; +use crate::protocol::{Decode, Encode, Packet, PacketDirection, PacketState}; #[derive(Debug)] pub struct KeepAliveC(pub i64); impl Packet for KeepAliveC { - const ID: i32 = 0x27; + const ID: &'static str = "minecraft:keep_alive"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for KeepAliveC { @@ -37,7 +39,9 @@ impl Encode for KeepAliveC { pub struct KeepAliveS(i64); impl Packet for KeepAliveS { - const ID: i32 = 0x1A; + const ID: &'static str = "minecraft:keep_alive"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl<'a> Decode<'a> for KeepAliveS { diff --git a/src/protocol/packets/play/login.rs b/src/protocol/packets/play/login.rs index 9fe414b..df6d5ae 100644 --- a/src/protocol/packets/play/login.rs +++ b/src/protocol/packets/play/login.rs @@ -17,10 +17,7 @@ * . */ -use crate::protocol::{ - datatypes::{Bounded, Position, VarInt}, - Encode, Packet, -}; +use crate::protocol::{datatypes::{Bounded, Position, VarInt}, Encode, Packet, PacketDirection, PacketState}; #[derive(Debug)] pub struct LoginPlayC<'a> { @@ -93,7 +90,9 @@ pub struct DeathLocation<'a> { } impl Packet for LoginPlayC<'_> { - const ID: i32 = 0x2C; + const ID: &'static str = "minecraft:login"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl<'a> Encode for LoginPlayC<'a> { diff --git a/src/protocol/packets/play/position.rs b/src/protocol/packets/play/position.rs index d546a26..2a4590c 100644 --- a/src/protocol/packets/play/position.rs +++ b/src/protocol/packets/play/position.rs @@ -19,7 +19,7 @@ use byteorder::{BigEndian, ReadBytesExt}; -use crate::protocol::{Decode, Packet}; +use crate::protocol::{Decode, Packet, PacketDirection, PacketState}; #[derive(Debug)] pub struct SetPlayerPositionS { @@ -30,7 +30,9 @@ pub struct SetPlayerPositionS { } impl Packet for SetPlayerPositionS { - const ID: i32 = 0x1C; + const ID: &'static str = "minecraft:move_player_pos"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl Decode<'_> for SetPlayerPositionS { @@ -58,7 +60,9 @@ pub struct SetPlayerPositionAndRotationS { } impl Packet for SetPlayerPositionAndRotationS { - const ID: i32 = 0x1D; + const ID: &'static str = "minecraft:move_player_pos_rot"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl Decode<'_> for SetPlayerPositionAndRotationS { diff --git a/src/protocol/packets/play/status.rs b/src/protocol/packets/play/status.rs index fc52d60..0d82f83 100644 --- a/src/protocol/packets/play/status.rs +++ b/src/protocol/packets/play/status.rs @@ -19,10 +19,7 @@ use uuid::Uuid; -use crate::protocol::{ - datatypes::{Bounded, VarInt}, - Encode, Packet, Property, -}; +use crate::protocol::{datatypes::{Bounded, VarInt}, Encode, Packet, PacketDirection, PacketState, Property}; use super::Gamemode; @@ -55,7 +52,9 @@ enum PlayerAction<'a> { } impl Packet for PlayerInfoUpdateC<'_> { - const ID: i32 = 0x40; + const ID: &'static str = "minecraft:player_info_update"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } // "I'm a Never-Nester" diff --git a/src/protocol/packets/play/teleport.rs b/src/protocol/packets/play/teleport.rs index 70017fb..a347ccb 100644 --- a/src/protocol/packets/play/teleport.rs +++ b/src/protocol/packets/play/teleport.rs @@ -19,7 +19,7 @@ use std::sync::atomic::{AtomicI32, Ordering}; -use crate::protocol::{datatypes::VarInt, Decode, Encode, Packet}; +use crate::protocol::{datatypes::VarInt, Decode, Encode, Packet, PacketDirection, PacketState}; static TP_ID: AtomicI32 = AtomicI32::new(0); @@ -123,7 +123,9 @@ impl SynchronisePositionC { } impl Packet for SynchronisePositionC { - const ID: i32 = 0x42; + const ID: &'static str = "minecraft:player_position"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for SynchronisePositionC { @@ -149,7 +151,9 @@ pub struct ConfirmTeleportS { } impl Packet for ConfirmTeleportS { - const ID: i32 = 0x00; + const ID: &'static str = "minecraft:accept_teleportation"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Serverbound; } impl Decode<'_> for ConfirmTeleportS { diff --git a/src/protocol/packets/play/tick.rs b/src/protocol/packets/play/tick.rs index 2174c3a..4bd2dce 100644 --- a/src/protocol/packets/play/tick.rs +++ b/src/protocol/packets/play/tick.rs @@ -17,7 +17,7 @@ * . */ -use crate::protocol::{datatypes::VarInt, Encode, Packet}; +use crate::protocol::{datatypes::VarInt, Encode, Packet, PacketDirection, PacketState}; #[derive(Debug)] pub struct SetTickingStateC { @@ -26,7 +26,9 @@ pub struct SetTickingStateC { } impl Packet for SetTickingStateC { - const ID: i32 = 0x78; + const ID: &'static str = "minecraft:ticking_state"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for SetTickingStateC { @@ -41,7 +43,9 @@ impl Encode for SetTickingStateC { pub struct StepTicksC(pub i32); impl Packet for StepTicksC { - const ID: i32 = 0x79; + const ID: &'static str = "minecraft:ticking_step"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for StepTicksC { diff --git a/src/protocol/packets/play/world.rs b/src/protocol/packets/play/world.rs index 31dbe8b..be643ae 100644 --- a/src/protocol/packets/play/world.rs +++ b/src/protocol/packets/play/world.rs @@ -34,6 +34,7 @@ use crate::{ }, CrawlState, }; +use crate::protocol::{PacketDirection, PacketState}; #[derive(Debug)] pub struct SetCenterChunkC { @@ -42,7 +43,9 @@ pub struct SetCenterChunkC { } impl Packet for SetCenterChunkC { - const ID: i32 = 0x58; + const ID: &'static str = "minecraft:set_chunk_cache_center"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for SetCenterChunkC { @@ -212,7 +215,9 @@ impl Encode for PalettedContainer { } impl Packet for ChunkDataUpdateLightC<'_> { - const ID: i32 = 0x28; + const ID: &'static str = "minecraft:level_chunk_with_light"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for ChunkDataUpdateLightC<'_> { @@ -454,7 +459,9 @@ pub struct InitializeWorldBorderC { } impl Packet for InitializeWorldBorderC { - const ID: i32 = 0x25; + const ID: &'static str = "minecraft:initialize_border"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for InitializeWorldBorderC { @@ -478,7 +485,9 @@ pub struct SetBorderCenterC { } impl Packet for SetBorderCenterC { - const ID: i32 = 0x52; + const ID: &'static str = "minecraft:set_border_center"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for SetBorderCenterC { @@ -493,7 +502,9 @@ impl Encode for SetBorderCenterC { pub struct SetBorderSizeC(pub f64); impl Packet for SetBorderSizeC { - const ID: i32 = 0x54; + const ID: &'static str = "minecraft:set_border_size"; + const STATE: PacketState = PacketState::Play; + const DIRECTION: PacketDirection = PacketDirection::Clientbound; } impl Encode for SetBorderSizeC { -- 2.51.2