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}