Skip to main content

kojacoord_protocol/versions/v1_19_4/play/
mod.rs

1use bytes::{Buf, BufMut, Bytes, BytesMut};
2
3use crate::codec::{Decode, Encode, PacketId};
4use crate::error::ProtocolError;
5use crate::types::VarInt;
6
7pub use packets::{
8    ClientboundAcknowledgeBlockChange, ClientboundAwardStats, ClientboundBlockAction,
9    ClientboundBlockDestroyStage, ClientboundBlockEntityData, ClientboundBlockUpdate,
10    ClientboundBossBar, ClientboundBundle, ClientboundChangeDifficulty, ClientboundChunkBiomes,
11    ClientboundClearTitles, ClientboundCommandSuggestions, ClientboundCommands,
12    ClientboundContainerClose, ClientboundContainerSetContent, ClientboundContainerSetProperty,
13    ClientboundContainerSetSlot, ClientboundCooldown, ClientboundCustomChatCompletions,
14    ClientboundDamageEvent, ClientboundDeleteChat, ClientboundDisconnect, ClientboundDisguisedChat,
15    ClientboundEntityAnimation, ClientboundEntityEvent, ClientboundExplosion,
16    ClientboundForgetLevelChunk, ClientboundGameEvent, ClientboundHorseScreenOpen,
17    ClientboundHurtAnimation, ClientboundInitializeBorder, ClientboundKeepAlive,
18    ClientboundLevelChunkWithLight, ClientboundLevelEvent, ClientboundLevelParticles,
19    ClientboundLightUpdate, ClientboundLogin, ClientboundMapItemData, ClientboundMerchantOffers,
20    ClientboundMoveEntityPos, ClientboundMoveEntityPosRot, ClientboundMoveEntityRot,
21    ClientboundMoveVehicle, ClientboundOpenBook, ClientboundOpenScreen, ClientboundOpenSignEditor,
22    ClientboundPing, ClientboundPlaceGhostRecipe, ClientboundPlayerAbilities,
23    ClientboundPlayerChat, ClientboundPlayerCombatEnd, ClientboundPlayerCombatEnter,
24    ClientboundPlayerCombatKill, ClientboundPlayerInfoRemove, ClientboundPlayerInfoUpdate,
25    ClientboundPlayerLookAt, ClientboundPlayerPosition, ClientboundPluginMessage,
26    ClientboundRecipeBookSettings, ClientboundRecipes, ClientboundRemoveEntities,
27    ClientboundRemoveEntityEffect, ClientboundResourcePackPush, ClientboundRespawn,
28    ClientboundRotateHead, ClientboundSectionBlocksUpdate, ClientboundSelectAdvancementsTab,
29    ClientboundServerData, ClientboundSetActionBarText, ClientboundSetBorderCenter,
30    ClientboundSetBorderLerpSize, ClientboundSetBorderSize, ClientboundSetBorderWarningDelay,
31    ClientboundSetBorderWarningDistance, ClientboundSetCamera, ClientboundSetCarriedItem,
32    ClientboundSetEntityLink, ClientboundSetEntityMotion, ClientboundSetEquipment,
33    ClientboundSetExperience, ClientboundSetHealth, ClientboundSetScoreboardObjective,
34    ClientboundSetScoreboardScore, ClientboundSetSimulationDistance, ClientboundSetSubtitleText,
35    ClientboundSetTime, ClientboundSetTitleAnimationTimes, ClientboundSetTitleText,
36    ClientboundSound, ClientboundSoundEntity, ClientboundSpawnEntity,
37    ClientboundSpawnExperienceOrb, ClientboundSpawnPlayer, ClientboundStopSound,
38    ClientboundSystemChat, ClientboundTabList, ClientboundTagQuery, ClientboundTakeItemEntity,
39    ClientboundTeleportEntity, ClientboundUpdateAdvancements, ClientboundUpdateAttributes,
40    ClientboundUpdateEffects, ClientboundUpdateRecipes, ClientboundUpdateTags, InteractAction,
41    ServerboundAcceptTeleportation, ServerboundChatCommand, ServerboundChatMessage,
42    ServerboundChatSessionUpdate, ServerboundClickWindow, ServerboundClickWindowButton,
43    ServerboundClientInformation, ServerboundClientStatus, ServerboundCloseWindow,
44    ServerboundCommandSuggestion, ServerboundCreativeInventoryAction, ServerboundDifficultyChange,
45    ServerboundDifficultyLock, ServerboundEditBook, ServerboundEntityAction,
46    ServerboundEntityTagQuery, ServerboundInteract, ServerboundJigsawGenerate,
47    ServerboundKeepAlive, ServerboundMovePlayerPos, ServerboundMovePlayerPosRot,
48    ServerboundMovePlayerRot, ServerboundMovePlayerStatusOnly, ServerboundPaddleBoat,
49    ServerboundPickItem, ServerboundPlaceRecipe, ServerboundPlayerAbilities,
50    ServerboundPlayerAction, ServerboundPluginMessage, ServerboundPong,
51    ServerboundRecipeBookChangeSettings, ServerboundRecipeBookSeenRecipe, ServerboundRenameItem,
52    ServerboundResourcePackStatus, ServerboundSelectTrade, ServerboundSetBeaconEffect,
53    ServerboundSetCarriedItem, ServerboundSetStructureBlock, ServerboundSpectate,
54    ServerboundSteerBoat, ServerboundSteerVehicle, ServerboundSwingArm,
55    ServerboundUpdateCommandBlock, ServerboundUpdateCommandBlockMinecart, ServerboundUpdateSign,
56    ServerboundUseItem, ServerboundUseItemOn, ServerboundVehicleMove,
57};
58
59fn need(src: &Bytes, n: usize) -> Result<(), ProtocolError> {
60    if src.remaining() < n {
61        return Err(ProtocolError::Io(std::io::Error::new(
62            std::io::ErrorKind::UnexpectedEof,
63            "Not enough bytes",
64        )));
65    }
66    Ok(())
67}
68
69mod packets {
70    use super::*;
71
72    #[derive(Debug, Clone, PartialEq)]
73    pub struct ClientboundBundle;
74
75    impl PacketId for ClientboundBundle {
76        fn packet_id(_ver: u32) -> u8 {
77            0x00
78        }
79    }
80    impl Encode for ClientboundBundle {
81        fn encode(&self, _dst: &mut BytesMut) -> Result<(), ProtocolError> {
82            Ok(())
83        }
84    }
85    impl Decode for ClientboundBundle {
86        fn decode(_src: &mut Bytes) -> Result<Self, ProtocolError> {
87            Ok(Self)
88        }
89    }
90
91    #[derive(Debug, Clone, PartialEq)]
92    pub struct ClientboundDisconnect {
93        pub reason: String,
94    }
95    impl PacketId for ClientboundDisconnect {
96        fn packet_id(_ver: u32) -> u8 {
97            0x1A
98        }
99    }
100    impl Encode for ClientboundDisconnect {
101        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
102            self.reason.encode(dst)
103        }
104    }
105    impl Decode for ClientboundDisconnect {
106        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
107            Ok(Self {
108                reason: String::decode(src)?,
109            })
110        }
111    }
112
113    #[derive(Debug, Clone, PartialEq)]
114    pub struct ClientboundKeepAlive {
115        pub id: i64,
116    }
117    impl PacketId for ClientboundKeepAlive {
118        fn packet_id(_ver: u32) -> u8 {
119            0x24
120        }
121    }
122    impl Encode for ClientboundKeepAlive {
123        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
124            self.id.encode(dst)
125        }
126    }
127    impl Decode for ClientboundKeepAlive {
128        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
129            Ok(Self {
130                id: i64::decode(src)?,
131            })
132        }
133    }
134
135    #[derive(Debug, Clone, PartialEq)]
136    pub struct ClientboundLogin {
137        pub entity_id: i32,
138        pub is_hardcore: bool,
139        pub game_mode: u8,
140        pub previous_game_mode: i8,
141        pub dimensions: Vec<String>,
142
143        pub registry_codec: Vec<u8>,
144        pub dimension_type: String,
145        pub dimension_name: String,
146        pub hashed_seed: i64,
147        pub max_players: VarInt,
148        pub chunk_radius: VarInt,
149        pub simulation_distance: VarInt,
150        pub reduced_debug_info: bool,
151        pub enable_respawn_screen: bool,
152        pub is_debug: bool,
153        pub is_flat: bool,
154        pub death_location: Option<(String, i64)>,
155    }
156    impl PacketId for ClientboundLogin {
157        fn packet_id(_ver: u32) -> u8 {
158            0x29
159        }
160    }
161    impl Encode for ClientboundLogin {
162        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
163            self.entity_id.encode(dst)?;
164            self.is_hardcore.encode(dst)?;
165            self.game_mode.encode(dst)?;
166            self.previous_game_mode.encode(dst)?;
167            self.dimensions.encode(dst)?;
168            VarInt(self.registry_codec.len() as i32).encode(dst)?;
169            dst.extend_from_slice(&self.registry_codec);
170            self.dimension_type.encode(dst)?;
171            self.dimension_name.encode(dst)?;
172            self.hashed_seed.encode(dst)?;
173            self.max_players.encode(dst)?;
174            self.chunk_radius.encode(dst)?;
175            self.simulation_distance.encode(dst)?;
176            self.reduced_debug_info.encode(dst)?;
177            self.enable_respawn_screen.encode(dst)?;
178            self.is_debug.encode(dst)?;
179            self.is_flat.encode(dst)?;
180            match &self.death_location {
181                Some((dim, pos)) => {
182                    true.encode(dst)?;
183                    dim.encode(dst)?;
184                    pos.encode(dst)?;
185                },
186                None => false.encode(dst)?,
187            }
188            Ok(())
189        }
190    }
191    impl Decode for ClientboundLogin {
192        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
193            let entity_id = i32::decode(src)?;
194            let is_hardcore = bool::decode(src)?;
195            let game_mode = u8::decode(src)?;
196            let previous_game_mode = i8::decode(src)?;
197            let dimensions = Vec::<String>::decode(src)?;
198            let codec_len = VarInt::decode(src)?.0 as usize;
199            let registry_codec = src.copy_to_bytes(codec_len).to_vec();
200            let dimension_type = String::decode(src)?;
201            let dimension_name = String::decode(src)?;
202            let hashed_seed = i64::decode(src)?;
203            let max_players = VarInt::decode(src)?;
204            let chunk_radius = VarInt::decode(src)?;
205            let simulation_distance = VarInt::decode(src)?;
206            let reduced_debug_info = bool::decode(src)?;
207            let enable_respawn_screen = bool::decode(src)?;
208            let is_debug = bool::decode(src)?;
209            let is_flat = bool::decode(src)?;
210            let has_death = bool::decode(src)?;
211            let death_location = if has_death {
212                Some((String::decode(src)?, i64::decode(src)?))
213            } else {
214                None
215            };
216            Ok(Self {
217                entity_id,
218                is_hardcore,
219                game_mode,
220                previous_game_mode,
221                dimensions,
222                registry_codec,
223                dimension_type,
224                dimension_name,
225                hashed_seed,
226                max_players,
227                chunk_radius,
228                simulation_distance,
229                reduced_debug_info,
230                enable_respawn_screen,
231                is_debug,
232                is_flat,
233                death_location,
234            })
235        }
236    }
237
238    #[derive(Debug, Clone, PartialEq)]
239    pub struct ClientboundPluginMessage {
240        pub channel: String,
241        pub data: Vec<u8>,
242    }
243    impl PacketId for ClientboundPluginMessage {
244        fn packet_id(_ver: u32) -> u8 {
245            0x17
246        }
247    }
248    impl Encode for ClientboundPluginMessage {
249        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
250            self.channel.encode(dst)?;
251            dst.extend_from_slice(&self.data);
252            Ok(())
253        }
254    }
255    impl Decode for ClientboundPluginMessage {
256        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
257            let channel = String::decode(src)?;
258            let data = src.copy_to_bytes(src.remaining()).to_vec();
259            Ok(Self { channel, data })
260        }
261    }
262
263    #[derive(Debug, Clone, PartialEq)]
264    pub struct ClientboundPlayerPosition {
265        pub x: f64,
266        pub y: f64,
267        pub z: f64,
268        pub yaw: f32,
269        pub pitch: f32,
270        pub flags: u8,
271        pub teleport_id: VarInt,
272    }
273    impl PacketId for ClientboundPlayerPosition {
274        fn packet_id(_ver: u32) -> u8 {
275            0x3E
276        }
277    }
278    impl Encode for ClientboundPlayerPosition {
279        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
280            self.x.encode(dst)?;
281            self.y.encode(dst)?;
282            self.z.encode(dst)?;
283            self.yaw.encode(dst)?;
284            self.pitch.encode(dst)?;
285            self.flags.encode(dst)?;
286            self.teleport_id.encode(dst)
287        }
288    }
289    impl Decode for ClientboundPlayerPosition {
290        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
291            Ok(Self {
292                x: f64::decode(src)?,
293                y: f64::decode(src)?,
294                z: f64::decode(src)?,
295                yaw: f32::decode(src)?,
296                pitch: f32::decode(src)?,
297                flags: u8::decode(src)?,
298                teleport_id: VarInt::decode(src)?,
299            })
300        }
301    }
302
303    #[derive(Debug, Clone, PartialEq)]
304    pub struct ClientboundRespawn {
305        pub dimension_type: String,
306        pub dimension_name: String,
307        pub hashed_seed: i64,
308        pub game_mode: u8,
309        pub previous_game_mode: i8,
310        pub is_debug: bool,
311        pub is_flat: bool,
312        pub data_kept: u8,
313        pub death_location: Option<(String, i64)>,
314    }
315    impl PacketId for ClientboundRespawn {
316        fn packet_id(_ver: u32) -> u8 {
317            0x44
318        }
319    }
320    impl Encode for ClientboundRespawn {
321        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
322            self.dimension_type.encode(dst)?;
323            self.dimension_name.encode(dst)?;
324            self.hashed_seed.encode(dst)?;
325            self.game_mode.encode(dst)?;
326            self.previous_game_mode.encode(dst)?;
327            self.is_debug.encode(dst)?;
328            self.is_flat.encode(dst)?;
329            self.data_kept.encode(dst)?;
330            match &self.death_location {
331                Some((dim, pos)) => {
332                    true.encode(dst)?;
333                    dim.encode(dst)?;
334                    pos.encode(dst)?;
335                },
336                None => false.encode(dst)?,
337            }
338            Ok(())
339        }
340    }
341    impl Decode for ClientboundRespawn {
342        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
343            let dimension_type = String::decode(src)?;
344            let dimension_name = String::decode(src)?;
345            let hashed_seed = i64::decode(src)?;
346            let game_mode = u8::decode(src)?;
347            let previous_game_mode = i8::decode(src)?;
348            let is_debug = bool::decode(src)?;
349            let is_flat = bool::decode(src)?;
350            let data_kept = u8::decode(src)?;
351            let has_death = bool::decode(src)?;
352            let death_location = if has_death {
353                Some((String::decode(src)?, i64::decode(src)?))
354            } else {
355                None
356            };
357            Ok(Self {
358                dimension_type,
359                dimension_name,
360                hashed_seed,
361                game_mode,
362                previous_game_mode,
363                is_debug,
364                is_flat,
365                data_kept,
366                death_location,
367            })
368        }
369    }
370
371    #[derive(Debug, Clone, PartialEq)]
372    pub struct ClientboundPlayerAbilities {
373        pub flags: u8,
374        pub flying_speed: f32,
375        pub walking_speed: f32,
376    }
377    impl PacketId for ClientboundPlayerAbilities {
378        fn packet_id(_ver: u32) -> u8 {
379            0x36
380        }
381    }
382    impl Encode for ClientboundPlayerAbilities {
383        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
384            self.flags.encode(dst)?;
385            self.flying_speed.encode(dst)?;
386            self.walking_speed.encode(dst)
387        }
388    }
389    impl Decode for ClientboundPlayerAbilities {
390        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
391            Ok(Self {
392                flags: u8::decode(src)?,
393                flying_speed: f32::decode(src)?,
394                walking_speed: f32::decode(src)?,
395            })
396        }
397    }
398
399    #[derive(Debug, Clone, PartialEq)]
400    pub struct ClientboundSystemChat {
401        pub content: String,
402        pub overlay: bool,
403    }
404    impl PacketId for ClientboundSystemChat {
405        fn packet_id(_ver: u32) -> u8 {
406            0x62
407        }
408    }
409    impl Encode for ClientboundSystemChat {
410        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
411            self.content.encode(dst)?;
412            self.overlay.encode(dst)
413        }
414    }
415    impl Decode for ClientboundSystemChat {
416        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
417            Ok(Self {
418                content: String::decode(src)?,
419                overlay: bool::decode(src)?,
420            })
421        }
422    }
423
424    #[derive(Debug, Clone, PartialEq)]
425    pub struct ClientboundSetTime {
426        pub world_age: i64,
427        pub time_of_day: i64,
428    }
429    impl PacketId for ClientboundSetTime {
430        fn packet_id(_ver: u32) -> u8 {
431            0x59
432        }
433    }
434    impl Encode for ClientboundSetTime {
435        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
436            self.world_age.encode(dst)?;
437            self.time_of_day.encode(dst)
438        }
439    }
440    impl Decode for ClientboundSetTime {
441        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
442            Ok(Self {
443                world_age: i64::decode(src)?,
444                time_of_day: i64::decode(src)?,
445            })
446        }
447    }
448
449    #[derive(Debug, Clone, PartialEq)]
450    pub struct ClientboundEntityEvent {
451        pub entity_id: i32,
452        pub event_id: i8,
453    }
454    impl PacketId for ClientboundEntityEvent {
455        fn packet_id(_ver: u32) -> u8 {
456            0x1C
457        }
458    }
459    impl Encode for ClientboundEntityEvent {
460        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
461            self.entity_id.encode(dst)?;
462            self.event_id.encode(dst)
463        }
464    }
465    impl Decode for ClientboundEntityEvent {
466        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
467            Ok(Self {
468                entity_id: i32::decode(src)?,
469                event_id: i8::decode(src)?,
470            })
471        }
472    }
473
474    #[derive(Debug, Clone, PartialEq)]
475    pub struct ClientboundSetCarriedItem {
476        pub slot: i8,
477    }
478    impl PacketId for ClientboundSetCarriedItem {
479        fn packet_id(_ver: u32) -> u8 {
480            0x4A
481        }
482    }
483    impl Encode for ClientboundSetCarriedItem {
484        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
485            self.slot.encode(dst)
486        }
487    }
488    impl Decode for ClientboundSetCarriedItem {
489        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
490            Ok(Self {
491                slot: i8::decode(src)?,
492            })
493        }
494    }
495
496    macro_rules! passthrough {
497        ($(#[doc = $doc:expr])* $name:ident, $id:expr) => {
498            $(#[doc = $doc])*
499
500            #[derive(Debug, Clone, PartialEq)]
501            pub struct $name { pub raw: Vec<u8> }
502            impl PacketId for $name {
503                fn packet_id(_ver: u32) -> u8 { $id }
504            }
505            impl Encode for $name {
506                fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
507                    dst.extend_from_slice(&self.raw);
508                    Ok(())
509                }
510            }
511            impl Decode for $name {
512                fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
513                    let raw = src.copy_to_bytes(src.remaining()).to_vec();
514                    Ok(Self { raw })
515                }
516            }
517        };
518    }
519
520    passthrough!(ClientboundSpawnEntity, 0x01);
521    passthrough!(ClientboundSpawnExperienceOrb, 0x02);
522    passthrough!(ClientboundSpawnPlayer, 0x03);
523    passthrough!(ClientboundEntityAnimation, 0x04);
524    passthrough!(ClientboundAwardStats, 0x05);
525    passthrough!(ClientboundAcknowledgeBlockChange, 0x06);
526    passthrough!(ClientboundBlockDestroyStage, 0x07);
527    passthrough!(ClientboundBlockEntityData, 0x08);
528    passthrough!(ClientboundBlockAction, 0x09);
529    passthrough!(ClientboundBlockUpdate, 0x0A);
530    passthrough!(ClientboundBossBar, 0x0B);
531    passthrough!(ClientboundChangeDifficulty, 0x0C);
532    passthrough!(ClientboundChunkBiomes, 0x0D);
533    passthrough!(ClientboundClearTitles, 0x0E);
534    passthrough!(ClientboundCommandSuggestions, 0x0F);
535    passthrough!(ClientboundCommands, 0x10);
536    passthrough!(ClientboundContainerClose, 0x11);
537    passthrough!(ClientboundContainerSetProperty, 0x13);
538
539    #[derive(Debug, Clone, PartialEq)]
540    pub struct ClientboundContainerSetContent {
541        pub window_id: u8,
542        pub slots: Vec<crate::types::Slot>,
543        pub carried_item: crate::types::Slot,
544    }
545
546    impl PacketId for ClientboundContainerSetContent {
547        fn packet_id(_ver: u32) -> u8 {
548            0x12
549        }
550    }
551
552    impl Encode for ClientboundContainerSetContent {
553        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
554            dst.put_u8(self.window_id);
555            VarInt(self.slots.len() as i32).encode(dst)?;
556            for slot in &self.slots {
557                slot.encode(dst)?;
558            }
559            self.carried_item.encode(dst)?;
560            Ok(())
561        }
562    }
563
564    impl Decode for ClientboundContainerSetContent {
565        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
566            need(src, 1)?;
567            let window_id = src.get_u8();
568            let count = VarInt::decode(src)?.0 as usize;
569            let mut slots = Vec::with_capacity(count);
570            for _ in 0..count {
571                slots.push(crate::types::Slot::decode(src)?);
572            }
573            let carried_item = crate::types::Slot::decode(src)?;
574            Ok(Self {
575                window_id,
576                slots,
577                carried_item,
578            })
579        }
580    }
581
582    #[derive(Debug, Clone, PartialEq)]
583    pub struct ClientboundContainerSetSlot {
584        pub window_id: i8,
585        pub slot: i16,
586        pub slot_data: crate::types::Slot,
587    }
588
589    impl PacketId for ClientboundContainerSetSlot {
590        fn packet_id(_ver: u32) -> u8 {
591            0x14
592        }
593    }
594
595    impl Encode for ClientboundContainerSetSlot {
596        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
597            dst.put_i8(self.window_id);
598            dst.put_i16(self.slot);
599            self.slot_data.encode(dst)?;
600            Ok(())
601        }
602    }
603
604    impl Decode for ClientboundContainerSetSlot {
605        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
606            need(src, 1 + 2)?;
607            let window_id = src.get_i8();
608            let slot = src.get_i16();
609            let slot_data = crate::types::Slot::decode(src)?;
610            Ok(Self {
611                window_id,
612                slot,
613                slot_data,
614            })
615        }
616    }
617
618    passthrough!(ClientboundCooldown, 0x15);
619    passthrough!(ClientboundCustomChatCompletions, 0x16);
620    passthrough!(ClientboundDamageEvent, 0x18);
621    passthrough!(ClientboundDeleteChat, 0x19);
622    passthrough!(ClientboundDisguisedChat, 0x1B);
623    passthrough!(ClientboundExplosion, 0x1D);
624    passthrough!(ClientboundForgetLevelChunk, 0x1E);
625    passthrough!(ClientboundGameEvent, 0x1F);
626    passthrough!(ClientboundHorseScreenOpen, 0x20);
627    passthrough!(ClientboundHurtAnimation, 0x21);
628    passthrough!(ClientboundInitializeBorder, 0x22);
629    passthrough!(ClientboundLevelChunkWithLight, 0x25);
630    passthrough!(ClientboundLevelEvent, 0x26);
631    passthrough!(ClientboundLevelParticles, 0x27);
632    passthrough!(ClientboundLightUpdate, 0x28);
633    passthrough!(ClientboundMapItemData, 0x2A);
634    passthrough!(ClientboundMerchantOffers, 0x2B);
635    passthrough!(ClientboundMoveEntityPos, 0x2C);
636    passthrough!(ClientboundMoveEntityPosRot, 0x2D);
637    passthrough!(ClientboundMoveEntityRot, 0x2E);
638    passthrough!(ClientboundMoveVehicle, 0x2F);
639    passthrough!(ClientboundOpenBook, 0x30);
640    passthrough!(ClientboundOpenScreen, 0x31);
641    passthrough!(ClientboundOpenSignEditor, 0x32);
642    passthrough!(ClientboundPing, 0x33);
643    passthrough!(ClientboundPlaceGhostRecipe, 0x35);
644    passthrough!(ClientboundPlayerChat, 0x37);
645    passthrough!(ClientboundPlayerCombatEnd, 0x38);
646    passthrough!(ClientboundPlayerCombatEnter, 0x39);
647    passthrough!(ClientboundPlayerCombatKill, 0x3A);
648    passthrough!(ClientboundPlayerInfoRemove, 0x3B);
649    passthrough!(ClientboundPlayerInfoUpdate, 0x3C);
650    passthrough!(ClientboundPlayerLookAt, 0x3D);
651    passthrough!(ClientboundRecipeBookSettings, 0x3F);
652    passthrough!(ClientboundRecipes, 0x40);
653    passthrough!(ClientboundRemoveEntities, 0x41);
654    passthrough!(ClientboundRemoveEntityEffect, 0x42);
655    passthrough!(ClientboundResourcePackPush, 0x43);
656    passthrough!(ClientboundRotateHead, 0x45);
657    passthrough!(ClientboundSectionBlocksUpdate, 0x46);
658    passthrough!(ClientboundSelectAdvancementsTab, 0x47);
659    passthrough!(ClientboundServerData, 0x48);
660    passthrough!(ClientboundSetActionBarText, 0x49);
661    passthrough!(ClientboundSetBorderCenter, 0x4A);
662    passthrough!(ClientboundSetBorderLerpSize, 0x4B);
663    passthrough!(ClientboundSetBorderSize, 0x4C);
664    passthrough!(ClientboundSetBorderWarningDelay, 0x4D);
665    passthrough!(ClientboundSetBorderWarningDistance, 0x4E);
666    passthrough!(ClientboundSetCamera, 0x4F);
667    passthrough!(ClientboundSetEntityLink, 0x50);
668    passthrough!(ClientboundSetEntityMotion, 0x51);
669    passthrough!(ClientboundSetEquipment, 0x52);
670    passthrough!(ClientboundSetExperience, 0x53);
671    passthrough!(ClientboundSetHealth, 0x54);
672    passthrough!(ClientboundSetScoreboardObjective, 0x55);
673    passthrough!(ClientboundSetScoreboardScore, 0x56);
674    passthrough!(ClientboundSetSimulationDistance, 0x57);
675    passthrough!(ClientboundSetSubtitleText, 0x58);
676    passthrough!(ClientboundSetTitleText, 0x5A);
677    passthrough!(ClientboundSetTitleAnimationTimes, 0x5B);
678    passthrough!(ClientboundSoundEntity, 0x5C);
679    passthrough!(ClientboundSound, 0x5D);
680    passthrough!(ClientboundStopSound, 0x5E);
681    passthrough!(ClientboundTabList, 0x63);
682    passthrough!(ClientboundTagQuery, 0x64);
683    passthrough!(ClientboundTakeItemEntity, 0x65);
684    passthrough!(ClientboundTeleportEntity, 0x66);
685    passthrough!(ClientboundUpdateAdvancements, 0x67);
686    passthrough!(ClientboundUpdateAttributes, 0x68);
687    passthrough!(ClientboundUpdateEffects, 0x69);
688    passthrough!(ClientboundUpdateRecipes, 0x6A);
689    passthrough!(ClientboundUpdateTags, 0x6B);
690
691    #[derive(Debug, Clone, PartialEq)]
692    pub struct ServerboundAcceptTeleportation {
693        pub teleport_id: VarInt,
694    }
695    impl PacketId for ServerboundAcceptTeleportation {
696        fn packet_id(_ver: u32) -> u8 {
697            0x00
698        }
699    }
700    impl Encode for ServerboundAcceptTeleportation {
701        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
702            self.teleport_id.encode(dst)
703        }
704    }
705    impl Decode for ServerboundAcceptTeleportation {
706        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
707            Ok(Self {
708                teleport_id: VarInt::decode(src)?,
709            })
710        }
711    }
712
713    #[derive(Debug, Clone, PartialEq)]
714    pub struct ServerboundClientInformation {
715        pub locale: String,
716        pub view_distance: i8,
717        pub chat_mode: VarInt,
718        pub chat_colors: bool,
719        pub displayed_skin_parts: u8,
720        pub main_hand: VarInt,
721        pub enable_text_filtering: bool,
722        pub allow_server_listings: bool,
723    }
724    impl PacketId for ServerboundClientInformation {
725        fn packet_id(_ver: u32) -> u8 {
726            0x07
727        }
728    }
729    impl Encode for ServerboundClientInformation {
730        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
731            self.locale.encode(dst)?;
732            self.view_distance.encode(dst)?;
733            self.chat_mode.encode(dst)?;
734            self.chat_colors.encode(dst)?;
735            self.displayed_skin_parts.encode(dst)?;
736            self.main_hand.encode(dst)?;
737            self.enable_text_filtering.encode(dst)?;
738            self.allow_server_listings.encode(dst)
739        }
740    }
741    impl Decode for ServerboundClientInformation {
742        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
743            Ok(Self {
744                locale: String::decode(src)?,
745                view_distance: i8::decode(src)?,
746                chat_mode: VarInt::decode(src)?,
747                chat_colors: bool::decode(src)?,
748                displayed_skin_parts: u8::decode(src)?,
749                main_hand: VarInt::decode(src)?,
750                enable_text_filtering: bool::decode(src)?,
751                allow_server_listings: bool::decode(src)?,
752            })
753        }
754    }
755
756    #[derive(Debug, Clone, PartialEq)]
757    pub enum InteractAction {
758        Interact {
759            hand: VarInt,
760        },
761        Attack,
762        InteractAt {
763            target_x: f32,
764            target_y: f32,
765            target_z: f32,
766            hand: VarInt,
767        },
768    }
769
770    #[derive(Debug, Clone, PartialEq)]
771    pub struct ServerboundInteract {
772        pub entity_id: VarInt,
773        pub action: InteractAction,
774        pub sneaking: bool,
775    }
776    impl PacketId for ServerboundInteract {
777        fn packet_id(_ver: u32) -> u8 {
778            0x11
779        }
780    }
781    impl Encode for ServerboundInteract {
782        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
783            self.entity_id.encode(dst)?;
784            match &self.action {
785                InteractAction::Interact { hand } => {
786                    VarInt(0).encode(dst)?;
787                    hand.encode(dst)?;
788                },
789                InteractAction::Attack => {
790                    VarInt(1).encode(dst)?;
791                },
792                InteractAction::InteractAt {
793                    target_x,
794                    target_y,
795                    target_z,
796                    hand,
797                } => {
798                    VarInt(2).encode(dst)?;
799                    target_x.encode(dst)?;
800                    target_y.encode(dst)?;
801                    target_z.encode(dst)?;
802                    hand.encode(dst)?;
803                },
804            }
805            self.sneaking.encode(dst)
806        }
807    }
808    impl Decode for ServerboundInteract {
809        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
810            let entity_id = VarInt::decode(src)?;
811            let action = match VarInt::decode(src)?.0 {
812                0 => InteractAction::Interact {
813                    hand: VarInt::decode(src)?,
814                },
815                1 => InteractAction::Attack,
816                2 => InteractAction::InteractAt {
817                    target_x: f32::decode(src)?,
818                    target_y: f32::decode(src)?,
819                    target_z: f32::decode(src)?,
820                    hand: VarInt::decode(src)?,
821                },
822                _ => return Err(ProtocolError::UnexpectedEof),
823            };
824            let sneaking = bool::decode(src)?;
825            Ok(Self {
826                entity_id,
827                action,
828                sneaking,
829            })
830        }
831    }
832
833    #[derive(Debug, Clone, PartialEq)]
834    pub struct ServerboundKeepAlive {
835        pub id: i64,
836    }
837    impl PacketId for ServerboundKeepAlive {
838        fn packet_id(_ver: u32) -> u8 {
839            0x12
840        }
841    }
842    impl Encode for ServerboundKeepAlive {
843        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
844            self.id.encode(dst)
845        }
846    }
847    impl Decode for ServerboundKeepAlive {
848        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
849            Ok(Self {
850                id: i64::decode(src)?,
851            })
852        }
853    }
854
855    #[derive(Debug, Clone, PartialEq)]
856    pub struct ServerboundMovePlayerStatusOnly {
857        pub on_ground: bool,
858    }
859    impl PacketId for ServerboundMovePlayerStatusOnly {
860        fn packet_id(_ver: u32) -> u8 {
861            0x13
862        }
863    }
864    impl Encode for ServerboundMovePlayerStatusOnly {
865        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
866            self.on_ground.encode(dst)
867        }
868    }
869    impl Decode for ServerboundMovePlayerStatusOnly {
870        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
871            Ok(Self {
872                on_ground: bool::decode(src)?,
873            })
874        }
875    }
876
877    #[derive(Debug, Clone, PartialEq)]
878    pub struct ServerboundMovePlayerPos {
879        pub x: f64,
880        pub feet_y: f64,
881        pub z: f64,
882        pub on_ground: bool,
883    }
884    impl PacketId for ServerboundMovePlayerPos {
885        fn packet_id(_ver: u32) -> u8 {
886            0x14
887        }
888    }
889    impl Encode for ServerboundMovePlayerPos {
890        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
891            self.x.encode(dst)?;
892            self.feet_y.encode(dst)?;
893            self.z.encode(dst)?;
894            self.on_ground.encode(dst)
895        }
896    }
897    impl Decode for ServerboundMovePlayerPos {
898        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
899            Ok(Self {
900                x: f64::decode(src)?,
901                feet_y: f64::decode(src)?,
902                z: f64::decode(src)?,
903                on_ground: bool::decode(src)?,
904            })
905        }
906    }
907
908    #[derive(Debug, Clone, PartialEq)]
909    pub struct ServerboundMovePlayerRot {
910        pub yaw: f32,
911        pub pitch: f32,
912        pub on_ground: bool,
913    }
914    impl PacketId for ServerboundMovePlayerRot {
915        fn packet_id(_ver: u32) -> u8 {
916            0x15
917        }
918    }
919    impl Encode for ServerboundMovePlayerRot {
920        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
921            self.yaw.encode(dst)?;
922            self.pitch.encode(dst)?;
923            self.on_ground.encode(dst)
924        }
925    }
926    impl Decode for ServerboundMovePlayerRot {
927        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
928            Ok(Self {
929                yaw: f32::decode(src)?,
930                pitch: f32::decode(src)?,
931                on_ground: bool::decode(src)?,
932            })
933        }
934    }
935
936    #[derive(Debug, Clone, PartialEq)]
937    pub struct ServerboundMovePlayerPosRot {
938        pub x: f64,
939        pub feet_y: f64,
940        pub z: f64,
941        pub yaw: f32,
942        pub pitch: f32,
943        pub on_ground: bool,
944    }
945    impl PacketId for ServerboundMovePlayerPosRot {
946        fn packet_id(_ver: u32) -> u8 {
947            0x16
948        }
949    }
950    impl Encode for ServerboundMovePlayerPosRot {
951        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
952            self.x.encode(dst)?;
953            self.feet_y.encode(dst)?;
954            self.z.encode(dst)?;
955            self.yaw.encode(dst)?;
956            self.pitch.encode(dst)?;
957            self.on_ground.encode(dst)
958        }
959    }
960    impl Decode for ServerboundMovePlayerPosRot {
961        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
962            Ok(Self {
963                x: f64::decode(src)?,
964                feet_y: f64::decode(src)?,
965                z: f64::decode(src)?,
966                yaw: f32::decode(src)?,
967                pitch: f32::decode(src)?,
968                on_ground: bool::decode(src)?,
969            })
970        }
971    }
972
973    #[derive(Debug, Clone, PartialEq)]
974    pub struct ServerboundPluginMessage {
975        pub channel: String,
976        pub data: Vec<u8>,
977    }
978    impl PacketId for ServerboundPluginMessage {
979        fn packet_id(_ver: u32) -> u8 {
980            0x0C
981        }
982    }
983    impl Encode for ServerboundPluginMessage {
984        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
985            self.channel.encode(dst)?;
986            dst.extend_from_slice(&self.data);
987            Ok(())
988        }
989    }
990    impl Decode for ServerboundPluginMessage {
991        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
992            let channel = String::decode(src)?;
993            let data = src.copy_to_bytes(src.remaining()).to_vec();
994            Ok(Self { channel, data })
995        }
996    }
997
998    #[derive(Debug, Clone, PartialEq)]
999    pub struct ServerboundPlayerAbilities {
1000        pub flags: u8,
1001    }
1002    impl PacketId for ServerboundPlayerAbilities {
1003        fn packet_id(_ver: u32) -> u8 {
1004            0x1B
1005        }
1006    }
1007    impl Encode for ServerboundPlayerAbilities {
1008        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1009            self.flags.encode(dst)
1010        }
1011    }
1012    impl Decode for ServerboundPlayerAbilities {
1013        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1014            Ok(Self {
1015                flags: u8::decode(src)?,
1016            })
1017        }
1018    }
1019
1020    #[derive(Debug, Clone, PartialEq)]
1021    pub struct ServerboundPlayerAction {
1022        pub status: VarInt,
1023        pub location: i64,
1024        pub face: i8,
1025        pub sequence: VarInt,
1026    }
1027    impl PacketId for ServerboundPlayerAction {
1028        fn packet_id(_ver: u32) -> u8 {
1029            0x1C
1030        }
1031    }
1032    impl Encode for ServerboundPlayerAction {
1033        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1034            self.status.encode(dst)?;
1035            self.location.encode(dst)?;
1036            self.face.encode(dst)?;
1037            self.sequence.encode(dst)
1038        }
1039    }
1040    impl Decode for ServerboundPlayerAction {
1041        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1042            Ok(Self {
1043                status: VarInt::decode(src)?,
1044                location: i64::decode(src)?,
1045                face: i8::decode(src)?,
1046                sequence: VarInt::decode(src)?,
1047            })
1048        }
1049    }
1050
1051    #[derive(Debug, Clone, PartialEq)]
1052    pub struct ServerboundSetCarriedItem {
1053        pub slot: i16,
1054    }
1055    impl PacketId for ServerboundSetCarriedItem {
1056        fn packet_id(_ver: u32) -> u8 {
1057            0x25
1058        }
1059    }
1060    impl Encode for ServerboundSetCarriedItem {
1061        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1062            self.slot.encode(dst)
1063        }
1064    }
1065    impl Decode for ServerboundSetCarriedItem {
1066        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1067            Ok(Self {
1068                slot: i16::decode(src)?,
1069            })
1070        }
1071    }
1072
1073    #[derive(Debug, Clone, PartialEq)]
1074    pub struct ServerboundSwingArm {
1075        pub hand: VarInt,
1076    }
1077    impl PacketId for ServerboundSwingArm {
1078        fn packet_id(_ver: u32) -> u8 {
1079            0x2C
1080        }
1081    }
1082    impl Encode for ServerboundSwingArm {
1083        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1084            self.hand.encode(dst)
1085        }
1086    }
1087    impl Decode for ServerboundSwingArm {
1088        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1089            Ok(Self {
1090                hand: VarInt::decode(src)?,
1091            })
1092        }
1093    }
1094
1095    #[derive(Debug, Clone, PartialEq)]
1096    pub struct ServerboundUseItemOn {
1097        pub hand: VarInt,
1098        pub location: i64,
1099        pub face: VarInt,
1100        pub cursor_x: f32,
1101        pub cursor_y: f32,
1102        pub cursor_z: f32,
1103        pub inside_block: bool,
1104        pub sequence: VarInt,
1105    }
1106    impl PacketId for ServerboundUseItemOn {
1107        fn packet_id(_ver: u32) -> u8 {
1108            0x2E
1109        }
1110    }
1111    impl Encode for ServerboundUseItemOn {
1112        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1113            self.hand.encode(dst)?;
1114            self.location.encode(dst)?;
1115            self.face.encode(dst)?;
1116            self.cursor_x.encode(dst)?;
1117            self.cursor_y.encode(dst)?;
1118            self.cursor_z.encode(dst)?;
1119            self.inside_block.encode(dst)?;
1120            self.sequence.encode(dst)
1121        }
1122    }
1123    impl Decode for ServerboundUseItemOn {
1124        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1125            Ok(Self {
1126                hand: VarInt::decode(src)?,
1127                location: i64::decode(src)?,
1128                face: VarInt::decode(src)?,
1129                cursor_x: f32::decode(src)?,
1130                cursor_y: f32::decode(src)?,
1131                cursor_z: f32::decode(src)?,
1132                inside_block: bool::decode(src)?,
1133                sequence: VarInt::decode(src)?,
1134            })
1135        }
1136    }
1137
1138    #[derive(Debug, Clone, PartialEq)]
1139    pub struct ServerboundUseItem {
1140        pub hand: VarInt,
1141        pub sequence: VarInt,
1142    }
1143    impl PacketId for ServerboundUseItem {
1144        fn packet_id(_ver: u32) -> u8 {
1145            0x2F
1146        }
1147    }
1148    impl Encode for ServerboundUseItem {
1149        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1150            self.hand.encode(dst)?;
1151            self.sequence.encode(dst)
1152        }
1153    }
1154    impl Decode for ServerboundUseItem {
1155        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1156            Ok(Self {
1157                hand: VarInt::decode(src)?,
1158                sequence: VarInt::decode(src)?,
1159            })
1160        }
1161    }
1162
1163    #[derive(Debug, Clone, PartialEq)]
1164    pub struct ServerboundSteerBoat {
1165        pub left_paddle_turning: bool,
1166        pub right_paddle_turning: bool,
1167    }
1168    impl PacketId for ServerboundSteerBoat {
1169        fn packet_id(_ver: u32) -> u8 {
1170            0x18
1171        }
1172    }
1173    impl Encode for ServerboundSteerBoat {
1174        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1175            self.left_paddle_turning.encode(dst)?;
1176            self.right_paddle_turning.encode(dst)
1177        }
1178    }
1179    impl Decode for ServerboundSteerBoat {
1180        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1181            Ok(Self {
1182                left_paddle_turning: bool::decode(src)?,
1183                right_paddle_turning: bool::decode(src)?,
1184            })
1185        }
1186    }
1187
1188    #[derive(Debug, Clone, PartialEq)]
1189    pub struct ServerboundPaddleBoat {
1190        pub left_paddle_turning: bool,
1191        pub right_paddle_turning: bool,
1192    }
1193    impl PacketId for ServerboundPaddleBoat {
1194        fn packet_id(_ver: u32) -> u8 {
1195            0x18
1196        }
1197    }
1198    impl Encode for ServerboundPaddleBoat {
1199        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1200            self.left_paddle_turning.encode(dst)?;
1201            self.right_paddle_turning.encode(dst)
1202        }
1203    }
1204    impl Decode for ServerboundPaddleBoat {
1205        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1206            Ok(Self {
1207                left_paddle_turning: bool::decode(src)?,
1208                right_paddle_turning: bool::decode(src)?,
1209            })
1210        }
1211    }
1212
1213    passthrough!(ServerboundChatCommand, 0x03);
1214    passthrough!(ServerboundChatMessage, 0x04);
1215    passthrough!(ServerboundChatSessionUpdate, 0x05);
1216    passthrough!(ServerboundClientStatus, 0x06);
1217    passthrough!(ServerboundCommandSuggestion, 0x09);
1218    passthrough!(ServerboundClickWindow, 0x0A);
1219    passthrough!(ServerboundClickWindowButton, 0x09);
1220    passthrough!(ServerboundCloseWindow, 0x0B);
1221    passthrough!(ServerboundCreativeInventoryAction, 0x28);
1222    passthrough!(ServerboundDifficultyChange, 0x02);
1223    passthrough!(ServerboundDifficultyLock, 0x10);
1224    passthrough!(ServerboundEditBook, 0x0D);
1225    passthrough!(ServerboundEntityAction, 0x1D);
1226    passthrough!(ServerboundEntityTagQuery, 0x0E);
1227    passthrough!(ServerboundJigsawGenerate, 0x0F);
1228    passthrough!(ServerboundPickItem, 0x19);
1229    passthrough!(ServerboundPlaceRecipe, 0x1A);
1230    passthrough!(ServerboundPong, 0x20);
1231    passthrough!(ServerboundRecipeBookChangeSettings, 0x21);
1232    passthrough!(ServerboundRecipeBookSeenRecipe, 0x22);
1233    passthrough!(ServerboundRenameItem, 0x23);
1234    passthrough!(ServerboundResourcePackStatus, 0x24);
1235    passthrough!(ServerboundSelectTrade, 0x26);
1236    passthrough!(ServerboundSetBeaconEffect, 0x27);
1237    passthrough!(ServerboundSetStructureBlock, 0x30);
1238    passthrough!(ServerboundSpectate, 0x2D);
1239    passthrough!(ServerboundSteerVehicle, 0x1E);
1240    passthrough!(ServerboundUpdateCommandBlock, 0x2A);
1241    passthrough!(ServerboundUpdateCommandBlockMinecart, 0x2B);
1242    passthrough!(ServerboundUpdateSign, 0x2A);
1243    passthrough!(ServerboundVehicleMove, 0x17);
1244}
1245
1246#[cfg(test)]
1247mod tests {
1248    use super::*;
1249
1250    macro_rules! roundtrip {
1251        ($T:ty, $val:expr) => {{
1252            let v = $val;
1253            let mut buf = BytesMut::new();
1254            v.encode(&mut buf).unwrap();
1255            let mut b = buf.freeze();
1256            assert_eq!(<$T>::decode(&mut b).unwrap(), v);
1257        }};
1258    }
1259
1260    #[test]
1261    fn keepalive_roundtrip() {
1262        roundtrip!(
1263            ClientboundKeepAlive,
1264            ClientboundKeepAlive { id: 987654321_i64 }
1265        );
1266        roundtrip!(
1267            ServerboundKeepAlive,
1268            ServerboundKeepAlive { id: 987654321_i64 }
1269        );
1270    }
1271
1272    #[test]
1273    fn disconnect_roundtrip() {
1274        roundtrip!(
1275            ClientboundDisconnect,
1276            ClientboundDisconnect {
1277                reason: r#"{"text":"bye"}"#.to_string(),
1278            }
1279        );
1280    }
1281
1282    #[test]
1283    fn system_chat_roundtrip() {
1284        roundtrip!(
1285            ClientboundSystemChat,
1286            ClientboundSystemChat {
1287                content: r#"{"text":"Hello"}"#.to_string(),
1288                overlay: false,
1289            }
1290        );
1291    }
1292
1293    #[test]
1294    fn player_position_roundtrip() {
1295        roundtrip!(
1296            ClientboundPlayerPosition,
1297            ClientboundPlayerPosition {
1298                x: 0.0,
1299                y: 64.0,
1300                z: 0.0,
1301                yaw: 0.0,
1302                pitch: 0.0,
1303                flags: 0,
1304                teleport_id: VarInt(3),
1305            }
1306        );
1307    }
1308
1309    #[test]
1310    fn set_time_roundtrip() {
1311        roundtrip!(
1312            ClientboundSetTime,
1313            ClientboundSetTime {
1314                world_age: 1000,
1315                time_of_day: 6000,
1316            }
1317        );
1318    }
1319
1320    #[test]
1321    fn respawn_roundtrip() {
1322        roundtrip!(
1323            ClientboundRespawn,
1324            ClientboundRespawn {
1325                dimension_type: "minecraft:overworld".to_string(),
1326                dimension_name: "minecraft:overworld".to_string(),
1327                hashed_seed: 42,
1328                game_mode: 0,
1329                previous_game_mode: -1,
1330                is_debug: false,
1331                is_flat: false,
1332                data_kept: 0x01,
1333                death_location: None,
1334            }
1335        );
1336    }
1337
1338    #[test]
1339    fn accept_teleportation_roundtrip() {
1340        roundtrip!(
1341            ServerboundAcceptTeleportation,
1342            ServerboundAcceptTeleportation {
1343                teleport_id: VarInt(7),
1344            }
1345        );
1346    }
1347
1348    #[test]
1349    fn client_information_roundtrip() {
1350        roundtrip!(
1351            ServerboundClientInformation,
1352            ServerboundClientInformation {
1353                locale: "en_US".to_string(),
1354                view_distance: 12,
1355                chat_mode: VarInt(0),
1356                chat_colors: true,
1357                displayed_skin_parts: 0x7F,
1358                main_hand: VarInt(1),
1359                enable_text_filtering: false,
1360                allow_server_listings: true,
1361            }
1362        );
1363    }
1364
1365    #[test]
1366    fn move_pos_roundtrip() {
1367        roundtrip!(
1368            ServerboundMovePlayerPos,
1369            ServerboundMovePlayerPos {
1370                x: 5.0,
1371                feet_y: 64.0,
1372                z: -2.0,
1373                on_ground: true,
1374            }
1375        );
1376    }
1377
1378    #[test]
1379    fn move_rot_roundtrip() {
1380        roundtrip!(
1381            ServerboundMovePlayerRot,
1382            ServerboundMovePlayerRot {
1383                yaw: 90.0,
1384                pitch: -10.0,
1385                on_ground: true,
1386            }
1387        );
1388    }
1389
1390    #[test]
1391    fn move_pos_rot_roundtrip() {
1392        roundtrip!(
1393            ServerboundMovePlayerPosRot,
1394            ServerboundMovePlayerPosRot {
1395                x: 1.0,
1396                feet_y: 65.0,
1397                z: 2.0,
1398                yaw: 180.0,
1399                pitch: 45.0,
1400                on_ground: false,
1401            }
1402        );
1403    }
1404
1405    #[test]
1406    fn move_status_only_roundtrip() {
1407        roundtrip!(
1408            ServerboundMovePlayerStatusOnly,
1409            ServerboundMovePlayerStatusOnly { on_ground: true }
1410        );
1411    }
1412
1413    #[test]
1414    fn plugin_message_roundtrip() {
1415        roundtrip!(
1416            ServerboundPluginMessage,
1417            ServerboundPluginMessage {
1418                channel: "minecraft:brand".to_string(),
1419                data: b"fabric".to_vec(),
1420            }
1421        );
1422        roundtrip!(
1423            ClientboundPluginMessage,
1424            ClientboundPluginMessage {
1425                channel: "minecraft:brand".to_string(),
1426                data: b"paper".to_vec(),
1427            }
1428        );
1429    }
1430
1431    #[test]
1432    fn interact_roundtrip() {
1433        roundtrip!(
1434            ServerboundInteract,
1435            ServerboundInteract {
1436                entity_id: VarInt(99),
1437                action: InteractAction::Attack,
1438                sneaking: false,
1439            }
1440        );
1441    }
1442
1443    #[test]
1444    fn use_item_on_roundtrip() {
1445        roundtrip!(
1446            ServerboundUseItemOn,
1447            ServerboundUseItemOn {
1448                hand: VarInt(0),
1449                location: 0,
1450                face: VarInt(1),
1451                cursor_x: 0.5,
1452                cursor_y: 0.5,
1453                cursor_z: 0.5,
1454                inside_block: false,
1455                sequence: VarInt(1),
1456            }
1457        );
1458    }
1459
1460    #[test]
1461    fn player_abilities_roundtrip() {
1462        roundtrip!(
1463            ClientboundPlayerAbilities,
1464            ClientboundPlayerAbilities {
1465                flags: 0x06,
1466                flying_speed: 0.05,
1467                walking_speed: 0.1,
1468            }
1469        );
1470        roundtrip!(
1471            ServerboundPlayerAbilities,
1472            ServerboundPlayerAbilities { flags: 0x02 }
1473        );
1474    }
1475
1476    #[test]
1477    fn swing_arm_roundtrip() {
1478        roundtrip!(ServerboundSwingArm, ServerboundSwingArm { hand: VarInt(0) });
1479    }
1480
1481    #[test]
1482    fn steer_boat_roundtrip() {
1483        roundtrip!(
1484            ServerboundSteerBoat,
1485            ServerboundSteerBoat {
1486                left_paddle_turning: true,
1487                right_paddle_turning: false,
1488            }
1489        );
1490    }
1491
1492    #[test]
1493    fn packet_ids() {
1494        assert_eq!(ClientboundBundle::packet_id(762), 0x00);
1495        assert_eq!(ClientboundSpawnEntity::packet_id(762), 0x01);
1496        assert_eq!(ClientboundEntityAnimation::packet_id(762), 0x04);
1497        assert_eq!(ClientboundDisconnect::packet_id(762), 0x1A);
1498        assert_eq!(ClientboundEntityEvent::packet_id(762), 0x1C);
1499        assert_eq!(ClientboundKeepAlive::packet_id(762), 0x24);
1500        assert_eq!(ClientboundLogin::packet_id(762), 0x29);
1501        assert_eq!(ClientboundPluginMessage::packet_id(762), 0x17);
1502        assert_eq!(ClientboundPlayerAbilities::packet_id(762), 0x36);
1503        assert_eq!(ClientboundPlayerPosition::packet_id(762), 0x3E);
1504        assert_eq!(ClientboundRespawn::packet_id(762), 0x44);
1505        assert_eq!(ClientboundSetCarriedItem::packet_id(762), 0x4A);
1506        assert_eq!(ClientboundSetTime::packet_id(762), 0x59);
1507        assert_eq!(ClientboundSystemChat::packet_id(762), 0x62);
1508
1509        assert_eq!(ServerboundAcceptTeleportation::packet_id(762), 0x00);
1510        assert_eq!(ServerboundChatMessage::packet_id(762), 0x04);
1511        assert_eq!(ServerboundClientInformation::packet_id(762), 0x07);
1512        assert_eq!(ServerboundInteract::packet_id(762), 0x11);
1513        assert_eq!(ServerboundKeepAlive::packet_id(762), 0x12);
1514        assert_eq!(ServerboundMovePlayerStatusOnly::packet_id(762), 0x13);
1515        assert_eq!(ServerboundMovePlayerPos::packet_id(762), 0x14);
1516        assert_eq!(ServerboundMovePlayerRot::packet_id(762), 0x15);
1517        assert_eq!(ServerboundMovePlayerPosRot::packet_id(762), 0x16);
1518        assert_eq!(ServerboundPluginMessage::packet_id(762), 0x0C);
1519        assert_eq!(ServerboundPlayerAbilities::packet_id(762), 0x1B);
1520        assert_eq!(ServerboundPlayerAction::packet_id(762), 0x1C);
1521        assert_eq!(ServerboundSetCarriedItem::packet_id(762), 0x25);
1522        assert_eq!(ServerboundSwingArm::packet_id(762), 0x2C);
1523        assert_eq!(ServerboundUseItemOn::packet_id(762), 0x2E);
1524        assert_eq!(ServerboundUseItem::packet_id(762), 0x2F);
1525        assert_eq!(ServerboundSteerBoat::packet_id(762), 0x18);
1526        assert_eq!(ServerboundPaddleBoat::packet_id(762), 0x18);
1527    }
1528}