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