1use bytes::{Buf, BufMut, Bytes, BytesMut};
2
3use crate::codec::{Decode, Encode, PacketId};
4use crate::error::ProtocolError;
5
6fn decode_legacy_string(src: &mut Bytes) -> Result<String, ProtocolError> {
7 if src.len() < 2 {
8 return Err(ProtocolError::UnexpectedEof);
9 }
10 let len = u16::from_be_bytes([src[0], src[1]]) as usize;
11 src.advance(2);
12 let byte_len = len * 2;
13 if src.len() < byte_len {
14 return Err(ProtocolError::UnexpectedEof);
15 }
16 let raw = src.copy_to_bytes(byte_len);
17 let chars: Vec<u16> = raw
18 .chunks(2)
19 .map(|c| u16::from_be_bytes([c[0], c[1]]))
20 .collect();
21 String::from_utf16(&chars).map_err(|_| ProtocolError::UnexpectedEof)
22}
23
24fn encode_legacy_string(s: &str, dst: &mut BytesMut) {
25 let utf16: Vec<u16> = s.encode_utf16().collect();
26 dst.extend_from_slice(&(utf16.len() as u16).to_be_bytes());
27 for ch in &utf16 {
28 dst.extend_from_slice(&ch.to_be_bytes());
29 }
30}
31
32fn need(src: &Bytes, n: usize) -> Result<(), ProtocolError> {
33 if src.remaining() < n {
34 Err(ProtocolError::UnexpectedEof)
35 } else {
36 Ok(())
37 }
38}
39
40#[derive(Debug, Clone, PartialEq)]
41pub struct ClientboundKeepAlive {
42 pub keep_alive_id: i32,
43}
44
45impl PacketId for ClientboundKeepAlive {
46 fn packet_id(_ver: u32) -> u8 {
47 0x00
48 }
49}
50
51impl Encode for ClientboundKeepAlive {
52 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
53 dst.extend_from_slice(&self.keep_alive_id.to_be_bytes());
54 Ok(())
55 }
56}
57
58impl Decode for ClientboundKeepAlive {
59 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
60 need(src, 4)?;
61 Ok(Self {
62 keep_alive_id: src.get_i32(),
63 })
64 }
65}
66
67#[derive(Debug, Clone, PartialEq)]
68pub struct ClientboundChatMessage {
69 pub message: String,
70}
71
72impl PacketId for ClientboundChatMessage {
73 fn packet_id(_ver: u32) -> u8 {
74 0x03
75 }
76}
77
78impl Encode for ClientboundChatMessage {
79 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
80 encode_legacy_string(&self.message, dst);
81 Ok(())
82 }
83}
84
85impl Decode for ClientboundChatMessage {
86 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
87 Ok(Self {
88 message: decode_legacy_string(src)?,
89 })
90 }
91}
92
93#[derive(Debug, Clone, PartialEq)]
94pub struct ClientboundPlayerPosition {
95 pub x: f64,
96 pub y: f64,
97 pub stance: f64,
98 pub z: f64,
99 pub yaw: f32,
100 pub pitch: f32,
101 pub on_ground: bool,
102}
103
104impl PacketId for ClientboundPlayerPosition {
105 fn packet_id(_ver: u32) -> u8 {
106 0x13
107 }
108}
109
110impl Encode for ClientboundPlayerPosition {
111 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
112 dst.put_f64(self.x);
113 dst.put_f64(self.y);
114 dst.put_f64(self.stance);
115 dst.put_f64(self.z);
116 dst.put_f32(self.yaw);
117 dst.put_f32(self.pitch);
118 dst.put_u8(self.on_ground as u8);
119 Ok(())
120 }
121}
122
123impl Decode for ClientboundPlayerPosition {
124 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
125 need(src, 8 + 8 + 8 + 8 + 4 + 4 + 1)?;
126 Ok(Self {
127 x: src.get_f64(),
128 y: src.get_f64(),
129 stance: src.get_f64(),
130 z: src.get_f64(),
131 yaw: src.get_f32(),
132 pitch: src.get_f32(),
133 on_ground: src.get_u8() != 0,
134 })
135 }
136}
137
138#[derive(Debug, Clone, PartialEq)]
139pub struct ClientboundHeldItemChange {
140 pub slot: i8,
141}
142
143impl PacketId for ClientboundHeldItemChange {
144 fn packet_id(_ver: u32) -> u8 {
145 0x09
146 }
147}
148
149impl Encode for ClientboundHeldItemChange {
150 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
151 dst.put_i8(self.slot);
152 Ok(())
153 }
154}
155
156impl Decode for ClientboundHeldItemChange {
157 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
158 need(src, 1)?;
159 Ok(Self { slot: src.get_i8() })
160 }
161}
162
163#[derive(Debug, Clone, PartialEq)]
164pub struct ClientboundPlayerAbilities {
165 pub flags: u8,
166 pub flying_speed: f32,
167 pub walking_speed: f32,
168}
169
170impl PacketId for ClientboundPlayerAbilities {
171 fn packet_id(_ver: u32) -> u8 {
172 0x43
173 }
174}
175
176impl Encode for ClientboundPlayerAbilities {
177 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
178 dst.put_u8(self.flags);
179 dst.put_f32(self.flying_speed);
180 dst.put_f32(self.walking_speed);
181 Ok(())
182 }
183}
184
185impl Decode for ClientboundPlayerAbilities {
186 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
187 need(src, 1 + 4 + 4)?;
188 Ok(Self {
189 flags: src.get_u8(),
190 flying_speed: src.get_f32(),
191 walking_speed: src.get_f32(),
192 })
193 }
194}
195
196#[derive(Debug, Clone, PartialEq)]
197pub struct ClientboundDisconnect {
198 pub reason: String,
199}
200
201impl PacketId for ClientboundDisconnect {
202 fn packet_id(_ver: u32) -> u8 {
203 0xFF
204 }
205}
206
207impl Encode for ClientboundDisconnect {
208 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
209 encode_legacy_string(&self.reason, dst);
210 Ok(())
211 }
212}
213
214impl Decode for ClientboundDisconnect {
215 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
216 Ok(Self {
217 reason: decode_legacy_string(src)?,
218 })
219 }
220}
221
222#[derive(Debug, Clone, PartialEq)]
223pub struct ClientboundSpawnPosition {
224 pub x: i32,
225 pub y: i32,
226 pub z: i32,
227}
228
229impl PacketId for ClientboundSpawnPosition {
230 fn packet_id(_ver: u32) -> u8 {
231 0x05
232 }
233}
234
235impl Encode for ClientboundSpawnPosition {
236 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
237 dst.put_i32(self.x);
238 dst.put_i32(self.y);
239 dst.put_i32(self.z);
240 Ok(())
241 }
242}
243
244impl Decode for ClientboundSpawnPosition {
245 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
246 need(src, 4 + 4 + 4)?;
247 Ok(Self {
248 x: src.get_i32(),
249 y: src.get_i32(),
250 z: src.get_i32(),
251 })
252 }
253}
254
255#[derive(Debug, Clone, PartialEq)]
256pub struct ClientboundUpdateHealth {
257 pub health: f32,
258 pub food: i16,
259 pub food_saturation: f32,
260}
261
262impl PacketId for ClientboundUpdateHealth {
263 fn packet_id(_ver: u32) -> u8 {
264 0x08
265 }
266}
267
268impl Encode for ClientboundUpdateHealth {
269 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
270 dst.put_f32(self.health);
271 dst.put_i16(self.food);
272 dst.put_f32(self.food_saturation);
273 Ok(())
274 }
275}
276
277impl Decode for ClientboundUpdateHealth {
278 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
279 need(src, 4 + 2 + 4)?;
280 Ok(Self {
281 health: src.get_f32(),
282 food: src.get_i16(),
283 food_saturation: src.get_f32(),
284 })
285 }
286}
287
288#[derive(Debug, Clone, PartialEq)]
289pub struct ClientboundRespawn {
290 pub dimension: i8,
291 pub difficulty: u8,
292 pub gamemode: u8,
293 pub world_height: i16,
294}
295
296impl PacketId for ClientboundRespawn {
297 fn packet_id(_ver: u32) -> u8 {
298 0x09
299 }
300}
301
302impl Encode for ClientboundRespawn {
303 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
304 dst.put_i8(self.dimension);
305 dst.put_u8(self.difficulty);
306 dst.put_u8(self.gamemode);
307 dst.put_i16(self.world_height);
308 Ok(())
309 }
310}
311
312impl Decode for ClientboundRespawn {
313 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
314 need(src, 1 + 1 + 1 + 2)?;
315 Ok(Self {
316 dimension: src.get_i8(),
317 difficulty: src.get_u8(),
318 gamemode: src.get_u8(),
319 world_height: src.get_i16(),
320 })
321 }
322}
323
324#[derive(Debug, Clone, PartialEq)]
325pub struct ClientboundEntityEquipment {
326 pub entity_id: i32,
327 pub slot: i16,
328 pub item_id: i16,
329}
330
331impl PacketId for ClientboundEntityEquipment {
332 fn packet_id(_ver: u32) -> u8 {
333 0x1C
334 }
335}
336
337impl Encode for ClientboundEntityEquipment {
338 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
339 dst.put_i32(self.entity_id);
340 dst.put_i16(self.slot);
341 dst.put_i16(self.item_id);
342 Ok(())
343 }
344}
345
346impl Decode for ClientboundEntityEquipment {
347 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
348 need(src, 4 + 2 + 2)?;
349 Ok(Self {
350 entity_id: src.get_i32(),
351 slot: src.get_i16(),
352 item_id: src.get_i16(),
353 })
354 }
355}
356
357#[derive(Debug, Clone, PartialEq)]
358pub struct ClientboundSpawnPlayer {
359 pub entity_id: i32,
360 pub username: String,
361 pub x: i32,
362 pub y: i32,
363 pub z: i32,
364 pub yaw: i8,
365 pub pitch: i8,
366 pub current_item: i16,
367}
368
369impl PacketId for ClientboundSpawnPlayer {
370 fn packet_id(_ver: u32) -> u8 {
371 0x14
372 }
373}
374
375impl Encode for ClientboundSpawnPlayer {
376 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
377 dst.put_i32(self.entity_id);
378 encode_legacy_string(&self.username, dst);
379 dst.put_i32(self.x);
380 dst.put_i32(self.y);
381 dst.put_i32(self.z);
382 dst.put_i8(self.yaw);
383 dst.put_i8(self.pitch);
384 dst.put_i16(self.current_item);
385 Ok(())
386 }
387}
388
389impl Decode for ClientboundSpawnPlayer {
390 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
391 let entity_id = src.get_i32();
392 let username = decode_legacy_string(src)?;
393 need(src, 4 + 4 + 4 + 1 + 1 + 2)?;
394 Ok(Self {
395 entity_id,
396 username,
397 x: src.get_i32(),
398 y: src.get_i32(),
399 z: src.get_i32(),
400 yaw: src.get_i8(),
401 pitch: src.get_i8(),
402 current_item: src.get_i16(),
403 })
404 }
405}
406
407#[derive(Debug, Clone, PartialEq)]
408pub struct ClientboundChunkData {
409 pub chunk_x: i32,
410 pub chunk_z: i32,
411 pub continuous: bool,
412 pub primary_bitmap: i16,
413 pub add_bitmap: i16,
414 pub compressed_data: Vec<u8>,
415}
416
417impl PacketId for ClientboundChunkData {
418 fn packet_id(_ver: u32) -> u8 {
419 0x33
420 }
421}
422
423impl Encode for ClientboundChunkData {
424 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
425 dst.put_i32(self.chunk_x);
426 dst.put_i32(self.chunk_z);
427 dst.put_u8(self.continuous as u8);
428 dst.put_i16(self.primary_bitmap);
429 dst.put_i16(self.add_bitmap);
430 dst.extend_from_slice(&(self.compressed_data.len() as i32).to_be_bytes());
431 dst.extend_from_slice(&self.compressed_data);
432 Ok(())
433 }
434}
435
436impl Decode for ClientboundChunkData {
437 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
438 need(src, 4 + 4 + 1 + 2 + 2 + 4)?;
439 let chunk_x = src.get_i32();
440 let chunk_z = src.get_i32();
441 let continuous = src.get_u8() != 0;
442 let primary_bitmap = src.get_i16();
443 let add_bitmap = src.get_i16();
444 let data_len = src.get_i32() as usize;
445 if src.remaining() < data_len {
446 return Err(ProtocolError::UnexpectedEof);
447 }
448 let compressed_data = src.copy_to_bytes(data_len).to_vec();
449 Ok(Self {
450 chunk_x,
451 chunk_z,
452 continuous,
453 primary_bitmap,
454 add_bitmap,
455 compressed_data,
456 })
457 }
458}
459
460#[derive(Debug, Clone, PartialEq)]
461pub struct ClientboundMultiBlockChange {
462 pub chunk_x: i32,
463 pub chunk_z: i32,
464 pub record_count: i32,
465 pub data: Vec<u8>,
466}
467
468impl PacketId for ClientboundMultiBlockChange {
469 fn packet_id(_ver: u32) -> u8 {
470 0x34
471 }
472}
473
474impl Encode for ClientboundMultiBlockChange {
475 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
476 dst.put_i32(self.chunk_x);
477 dst.put_i32(self.chunk_z);
478 dst.put_i32(self.record_count);
479 dst.extend_from_slice(&self.data);
480 Ok(())
481 }
482}
483
484impl Decode for ClientboundMultiBlockChange {
485 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
486 need(src, 4 + 4 + 4)?;
487 let chunk_x = src.get_i32();
488 let chunk_z = src.get_i32();
489 let record_count = src.get_i32();
490 let data = src.to_vec();
491 Ok(Self {
492 chunk_x,
493 chunk_z,
494 record_count,
495 data,
496 })
497 }
498}
499
500#[derive(Debug, Clone, PartialEq)]
501pub struct ClientboundBlockChange {
502 pub x: i32,
503 pub y: i8,
504 pub z: i32,
505 pub block_id: i16,
506 pub block_metadata: i8,
507}
508
509impl PacketId for ClientboundBlockChange {
510 fn packet_id(_ver: u32) -> u8 {
511 0x35
512 }
513}
514
515impl Encode for ClientboundBlockChange {
516 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
517 dst.put_i32(self.x);
518 dst.put_i8(self.y);
519 dst.put_i32(self.z);
520 dst.put_i16(self.block_id);
521 dst.put_i8(self.block_metadata);
522 Ok(())
523 }
524}
525
526impl Decode for ClientboundBlockChange {
527 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
528 need(src, 4 + 1 + 4 + 2 + 1)?;
529 Ok(Self {
530 x: src.get_i32(),
531 y: src.get_i8(),
532 z: src.get_i32(),
533 block_id: src.get_i16(),
534 block_metadata: src.get_i8(),
535 })
536 }
537}
538
539#[derive(Debug, Clone, PartialEq)]
540pub struct ClientboundNamedSoundEffect {
541 pub sound_name: String,
542 pub x: i32,
543 pub y: i32,
544 pub z: i32,
545 pub volume: f32,
546 pub pitch: u8,
547}
548
549impl PacketId for ClientboundNamedSoundEffect {
550 fn packet_id(_ver: u32) -> u8 {
551 0x3E
552 }
553}
554
555impl Encode for ClientboundNamedSoundEffect {
556 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
557 encode_legacy_string(&self.sound_name, dst);
558 dst.put_i32(self.x);
559 dst.put_i32(self.y);
560 dst.put_i32(self.z);
561 dst.put_f32(self.volume);
562 dst.put_u8(self.pitch);
563 Ok(())
564 }
565}
566
567impl Decode for ClientboundNamedSoundEffect {
568 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
569 let sound_name = decode_legacy_string(src)?;
570 need(src, 4 + 4 + 4 + 4 + 1)?;
571 Ok(Self {
572 sound_name,
573 x: src.get_i32(),
574 y: src.get_i32(),
575 z: src.get_i32(),
576 volume: src.get_f32(),
577 pitch: src.get_u8(),
578 })
579 }
580}
581
582#[derive(Debug, Clone, PartialEq)]
583pub struct ClientboundSetSlot {
584 pub window_id: i8,
585 pub slot: i16,
586 pub item_id: i16,
587 pub item_count: i8,
588 pub item_damage: i16,
589 pub nbt_data: Vec<u8>,
590}
591
592impl PacketId for ClientboundSetSlot {
593 fn packet_id(_ver: u32) -> u8 {
594 0x67
595 }
596}
597
598impl Encode for ClientboundSetSlot {
599 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
600 dst.put_i8(self.window_id);
601 dst.put_i16(self.slot);
602 dst.put_i16(self.item_id);
603 dst.put_i8(self.item_count);
604 dst.put_i16(self.item_damage);
605 dst.put_i16(self.nbt_data.len() as i16);
606 dst.extend_from_slice(&self.nbt_data);
607 Ok(())
608 }
609}
610
611impl Decode for ClientboundSetSlot {
612 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
613 need(src, 1 + 2 + 2 + 1 + 2 + 2)?;
614 let window_id = src.get_i8();
615 let slot = src.get_i16();
616 let item_id = src.get_i16();
617 let item_count = src.get_i8();
618 let item_damage = src.get_i16();
619 let nbt_len = src.get_i16() as usize;
620 if src.remaining() < nbt_len {
621 return Err(ProtocolError::UnexpectedEof);
622 }
623 let nbt_data = src.copy_to_bytes(nbt_len).to_vec();
624 Ok(Self {
625 window_id,
626 slot,
627 item_id,
628 item_count,
629 item_damage,
630 nbt_data,
631 })
632 }
633}
634
635#[derive(Debug, Clone, PartialEq)]
636pub struct ClientboundWindowItems {
637 pub window_id: i8,
638 pub items: Vec<(i16, i8, i16, Vec<u8>)>,
639}
640
641impl PacketId for ClientboundWindowItems {
642 fn packet_id(_ver: u32) -> u8 {
643 0x68
644 }
645}
646
647impl Encode for ClientboundWindowItems {
648 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
649 dst.put_i8(self.window_id);
650 dst.put_i16(self.items.len() as i16);
651 for (item_id, item_count, item_damage, nbt_data) in &self.items {
652 dst.put_i16(*item_id);
653 dst.put_i8(*item_count);
654 dst.put_i16(*item_damage);
655 dst.put_i16(nbt_data.len() as i16);
656 dst.extend_from_slice(nbt_data);
657 }
658 Ok(())
659 }
660}
661
662impl Decode for ClientboundWindowItems {
663 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
664 need(src, 1 + 2)?;
665 let window_id = src.get_i8();
666 let count = src.get_i16() as usize;
667 let mut items = Vec::with_capacity(count);
668 for _ in 0..count {
669 need(src, 2 + 1 + 2 + 2)?;
670 let item_id = src.get_i16();
671 let item_count = src.get_i8();
672 let item_damage = src.get_i16();
673 let nbt_len = src.get_i16() as usize;
674 if src.remaining() < nbt_len {
675 return Err(ProtocolError::UnexpectedEof);
676 }
677 let nbt_data = src.copy_to_bytes(nbt_len).to_vec();
678 items.push((item_id, item_count, item_damage, nbt_data));
679 }
680 Ok(Self { window_id, items })
681 }
682}
683
684#[derive(Debug, Clone, PartialEq)]
685pub struct ClientboundUpdateTime {
686 pub age: i64,
687 pub time: i64,
688}
689
690impl PacketId for ClientboundUpdateTime {
691 fn packet_id(_ver: u32) -> u8 {
692 0x04
693 }
694}
695
696impl Encode for ClientboundUpdateTime {
697 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
698 dst.put_i64(self.age);
699 dst.put_i64(self.time);
700 Ok(())
701 }
702}
703
704impl Decode for ClientboundUpdateTime {
705 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
706 need(src, 8 + 8)?;
707 Ok(Self {
708 age: src.get_i64(),
709 time: src.get_i64(),
710 })
711 }
712}
713
714#[derive(Debug, Clone, PartialEq)]
715pub struct ClientboundEntity {
716 pub entity_id: i32,
717}
718
719impl PacketId for ClientboundEntity {
720 fn packet_id(_ver: u32) -> u8 {
721 0x1E
722 }
723}
724
725impl Encode for ClientboundEntity {
726 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
727 dst.put_i32(self.entity_id);
728 Ok(())
729 }
730}
731
732impl Decode for ClientboundEntity {
733 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
734 need(src, 4)?;
735 Ok(Self {
736 entity_id: src.get_i32(),
737 })
738 }
739}
740
741#[derive(Debug, Clone, PartialEq)]
742pub struct ClientboundEntityRelativeMove {
743 pub entity_id: i32,
744 pub dx: i8,
745 pub dy: i8,
746 pub dz: i8,
747}
748
749impl PacketId for ClientboundEntityRelativeMove {
750 fn packet_id(_ver: u32) -> u8 {
751 0x15
752 }
753}
754
755impl Encode for ClientboundEntityRelativeMove {
756 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
757 dst.put_i32(self.entity_id);
758 dst.put_i8(self.dx);
759 dst.put_i8(self.dy);
760 dst.put_i8(self.dz);
761 Ok(())
762 }
763}
764
765impl Decode for ClientboundEntityRelativeMove {
766 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
767 need(src, 4 + 1 + 1 + 1)?;
768 Ok(Self {
769 entity_id: src.get_i32(),
770 dx: src.get_i8(),
771 dy: src.get_i8(),
772 dz: src.get_i8(),
773 })
774 }
775}
776
777#[derive(Debug, Clone, PartialEq)]
778pub struct ClientboundEntityLook {
779 pub entity_id: i32,
780 pub yaw: i8,
781 pub pitch: i8,
782}
783
784impl PacketId for ClientboundEntityLook {
785 fn packet_id(_ver: u32) -> u8 {
786 0x16
787 }
788}
789
790impl Encode for ClientboundEntityLook {
791 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
792 dst.put_i32(self.entity_id);
793 dst.put_i8(self.yaw);
794 dst.put_i8(self.pitch);
795 Ok(())
796 }
797}
798
799impl Decode for ClientboundEntityLook {
800 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
801 need(src, 4 + 1 + 1)?;
802 Ok(Self {
803 entity_id: src.get_i32(),
804 yaw: src.get_i8(),
805 pitch: src.get_i8(),
806 })
807 }
808}
809
810#[derive(Debug, Clone, PartialEq)]
811pub struct ClientboundEntityMoveLook {
812 pub entity_id: i32,
813 pub dx: i8,
814 pub dy: i8,
815 pub dz: i8,
816 pub yaw: i8,
817 pub pitch: i8,
818}
819
820impl PacketId for ClientboundEntityMoveLook {
821 fn packet_id(_ver: u32) -> u8 {
822 0x17
823 }
824}
825
826impl Encode for ClientboundEntityMoveLook {
827 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
828 dst.put_i32(self.entity_id);
829 dst.put_i8(self.dx);
830 dst.put_i8(self.dy);
831 dst.put_i8(self.dz);
832 dst.put_i8(self.yaw);
833 dst.put_i8(self.pitch);
834 Ok(())
835 }
836}
837
838impl Decode for ClientboundEntityMoveLook {
839 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
840 need(src, 4 + 1 + 1 + 1 + 1 + 1)?;
841 Ok(Self {
842 entity_id: src.get_i32(),
843 dx: src.get_i8(),
844 dy: src.get_i8(),
845 dz: src.get_i8(),
846 yaw: src.get_i8(),
847 pitch: src.get_i8(),
848 })
849 }
850}
851
852#[derive(Debug, Clone, PartialEq)]
853pub struct ClientboundEntityTeleport {
854 pub entity_id: i32,
855 pub x: i32,
856 pub y: i32,
857 pub z: i32,
858 pub yaw: i8,
859 pub pitch: i8,
860}
861
862impl PacketId for ClientboundEntityTeleport {
863 fn packet_id(_ver: u32) -> u8 {
864 0x18
865 }
866}
867
868impl Encode for ClientboundEntityTeleport {
869 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
870 dst.put_i32(self.entity_id);
871 dst.put_i32(self.x);
872 dst.put_i32(self.y);
873 dst.put_i32(self.z);
874 dst.put_i8(self.yaw);
875 dst.put_i8(self.pitch);
876 Ok(())
877 }
878}
879
880impl Decode for ClientboundEntityTeleport {
881 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
882 need(src, 4 + 4 + 4 + 4 + 1 + 1)?;
883 Ok(Self {
884 entity_id: src.get_i32(),
885 x: src.get_i32(),
886 y: src.get_i32(),
887 z: src.get_i32(),
888 yaw: src.get_i8(),
889 pitch: src.get_i8(),
890 })
891 }
892}
893
894#[derive(Debug, Clone, PartialEq)]
895pub struct ClientboundEntityHeadRotation {
896 pub entity_id: i32,
897 pub head_yaw: i8,
898}
899
900impl PacketId for ClientboundEntityHeadRotation {
901 fn packet_id(_ver: u32) -> u8 {
902 0x19
903 }
904}
905
906impl Encode for ClientboundEntityHeadRotation {
907 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
908 dst.put_i32(self.entity_id);
909 dst.put_i8(self.head_yaw);
910 Ok(())
911 }
912}
913
914impl Decode for ClientboundEntityHeadRotation {
915 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
916 need(src, 4 + 1)?;
917 Ok(Self {
918 entity_id: src.get_i32(),
919 head_yaw: src.get_i8(),
920 })
921 }
922}
923
924#[derive(Debug, Clone, PartialEq)]
925pub struct ClientboundSetExperience {
926 pub experience_bar: f32,
927 pub level: i16,
928 pub total_experience: i16,
929}
930
931impl PacketId for ClientboundSetExperience {
932 fn packet_id(_ver: u32) -> u8 {
933 0x2B
934 }
935}
936
937impl Encode for ClientboundSetExperience {
938 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
939 dst.put_f32(self.experience_bar);
940 dst.put_i16(self.level);
941 dst.put_i16(self.total_experience);
942 Ok(())
943 }
944}
945
946impl Decode for ClientboundSetExperience {
947 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
948 need(src, 4 + 2 + 2)?;
949 Ok(Self {
950 experience_bar: src.get_f32(),
951 level: src.get_i16(),
952 total_experience: src.get_i16(),
953 })
954 }
955}
956
957#[derive(Debug, Clone, PartialEq)]
958pub struct ClientboundMapData {
959 pub item_damage: i16,
960 pub scale: i8,
961 pub data: Vec<u8>,
962}
963
964impl PacketId for ClientboundMapData {
965 fn packet_id(_ver: u32) -> u8 {
966 0x36
967 }
968}
969
970impl Encode for ClientboundMapData {
971 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
972 dst.put_i16(self.item_damage);
973 dst.put_i8(self.scale);
974 dst.extend_from_slice(&self.data);
975 Ok(())
976 }
977}
978
979impl Decode for ClientboundMapData {
980 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
981 need(src, 2 + 1)?;
982 let item_damage = src.get_i16();
983 let scale = src.get_i8();
984 let data = src.to_vec();
985 Ok(Self {
986 item_damage,
987 scale,
988 data,
989 })
990 }
991}
992
993#[derive(Debug, Clone, PartialEq)]
994pub struct ClientboundOpenWindow {
995 pub window_id: i8,
996 pub inventory_type: i8,
997 pub window_title: String,
998 pub slots_count: i8,
999 pub use_provided_title: bool,
1000}
1001
1002impl PacketId for ClientboundOpenWindow {
1003 fn packet_id(_ver: u32) -> u8 {
1004 0x64
1005 }
1006}
1007
1008impl Encode for ClientboundOpenWindow {
1009 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1010 dst.put_i8(self.window_id);
1011 dst.put_i8(self.inventory_type);
1012 encode_legacy_string(&self.window_title, dst);
1013 dst.put_i8(self.slots_count);
1014 dst.put_u8(self.use_provided_title as u8);
1015 Ok(())
1016 }
1017}
1018
1019impl Decode for ClientboundOpenWindow {
1020 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1021 let window_id = src.get_i8();
1022 let inventory_type = src.get_i8();
1023 let window_title = decode_legacy_string(src)?;
1024 need(src, 1 + 1)?;
1025 let slots_count = src.get_i8();
1026 let use_provided_title = src.get_u8() != 0;
1027 Ok(Self {
1028 window_id,
1029 inventory_type,
1030 window_title,
1031 slots_count,
1032 use_provided_title,
1033 })
1034 }
1035}
1036
1037#[derive(Debug, Clone, PartialEq)]
1038pub struct ClientboundCloseWindow {
1039 pub window_id: i8,
1040}
1041
1042impl PacketId for ClientboundCloseWindow {
1043 fn packet_id(_ver: u32) -> u8 {
1044 0x65
1045 }
1046}
1047
1048impl Encode for ClientboundCloseWindow {
1049 fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
1050 dst.put_i8(self.window_id);
1051 Ok(())
1052 }
1053}
1054
1055impl Decode for ClientboundCloseWindow {
1056 fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
1057 need(src, 1)?;
1058 Ok(Self {
1059 window_id: src.get_i8(),
1060 })
1061 }
1062}