1use crate::{types::*, uuid::*, *};
2use alloc::{string::{String, ToString}, vec::Vec, borrow::ToOwned, boxed::Box};
3use alloc::fmt;
4use fmt::Debug;
5
6#[cfg(all(test, feature = "std"))]
7use crate::protocol::TestRandom;
8
9define_protocol!(753, Packet753, RawPacket753, RawPacket753Body, Packet753Kind => {
10 Handshake, 0x00, Handshaking, ServerBound => HandshakeSpec {
12 version: VarInt,
13 server_address: String,
14 server_port: u16,
15 next_state: HandshakeNextState
16 },
17
18 StatusRequest, 0x00, Status, ServerBound => StatusRequestSpec {},
20 StatusPing, 0x01, Status, ServerBound => StatusPingSpec {
21 payload: i64
22 },
23 StatusResponse, 0x00, Status, ClientBound => StatusResponseSpec {
24 response: super::status::StatusSpec
25 },
26 StatusPong, 0x01, Status, ClientBound => StatusPongSpec {
27 payload: i64
28 },
29
30 LoginDisconnect, 0x00, Login, ClientBound => LoginDisconnectSpec {
32 message: Chat
33 },
34 LoginEncryptionRequest, 0x01, Login, ClientBound => LoginEncryptionRequestSpec {
35 server_id: String,
36 public_key: CountedArray<u8, VarInt>,
37 verify_token: CountedArray<u8, VarInt>
38 },
39 LoginSuccess, 0x02, Login, ClientBound => LoginSuccessSpec {
40 uuid: UUID4,
41 username: String
42 },
43 LoginSetCompression, 0x03, Login, ClientBound => LoginSetCompressionSpec {
44 threshold: VarInt
45 },
46 LoginPluginRequest, 0x04, Login, ClientBound => LoginPluginRequestSpec {
47 message_id: VarInt,
48 channel: String,
49 data: RemainingBytes
50 },
51 LoginStart, 0x00, Login, ServerBound => LoginStartSpec {
52 name: String
53 },
54 LoginEncryptionResponse, 0x01, Login, ServerBound => LoginEncryptionResponseSpec {
55 shared_secret: CountedArray<u8, VarInt>,
56 verify_token: CountedArray<u8, VarInt>
57 },
58 LoginPluginResponse, 0x02, Login, ServerBound => LoginPluginResponseSpec {
59 message_id: VarInt,
60 successful: bool,
61 data: RemainingBytes
62 },
63
64 PlaySpawnEntity, 0x00, Play, ClientBound => PlaySpawnEntitySpec {
67 entity_id: VarInt,
68 object_uuid: UUID4,
69 entity_type: VarInt,
70 position: Vec3<f64>,
71 pitch: Angle,
72 yaw: Angle,
73 data: i32,
74 velocity: Vec3<i16>
75 },
76 PlaySpawnExperienceOrb, 0x01, Play, ClientBound => PlaySpawnExperienceOrbSpec {
77 entity_id: VarInt,
78 position: Vec3<f64>,
79 count: i16
80 },
81 PlaySpawnLivingEntity, 0x02, Play, ClientBound => PlaySpawnLivingEntitySpec {
82 entity_id: VarInt,
83 entity_uuid: UUID4,
84 entity_type: VarInt,
85 location: EntityLocation<f64, Angle>,
86 head_pitch: Angle,
87 velocity: Vec3<i16>
88 },
89 PlaySpawnPainting, 0x03, Play, ClientBound => PlaySpawnPaintingSpec {
90 entity_id: VarInt,
91 entity_uuid: UUID4,
92 motive: VarInt,
93 location: IntPosition,
94 direction: CardinalDirection
95 },
96 PlaySpawnPlayer, 0x04, Play, ClientBound => PlaySpawnPlayerSpec {
97 entity_id: VarInt,
98 uuid: UUID4,
99 location: EntityLocation<f64, Angle>
100 },
101 PlayEntityAnimation, 0x05, Play, ClientBound => PlayEntityAnimationSpec {
102 entity_id: VarInt,
103 animation: EntityAnimationKind
104 },
105 PlayStatistics, 0x06, Play, ClientBound => PlayStatisticsSpec {
106 entries: CountedArray<Statistic, VarInt>
107 },
108 PlayAcknowledgePlayerDigging, 0x07, Play, ClientBound => PlayAcknowledgePlayerDiggingSpec {
109 location: IntPosition,
110 block: VarInt,
111 status: DiggingStatus,
112 successful: bool
113 },
114 PlayBlockBreakAnimation, 0x08, Play, ClientBound => PlayBlockBreakAnimationSpec {
115 entity_id: VarInt,
116 location: IntPosition,
117 destroy_stage: i8
118 },
119 PlayBlockEntityData, 0x09, Play, ClientBound => PlayBlockEntityDataSpec {
120 location: IntPosition,
121 action: BlockEntityDataAction,
122 nbt_data: NamedNbtTag
123 },
124 PlayBlockAction, 0x0A, Play, ClientBound => PlayBlockActionSpec {
125 location: IntPosition,
126 action_id: u8,
127 action_payload: u8,
128 block_type: VarInt
129 },
130 PlayBlockChange, 0x0B, Play, ClientBound => PlayBlockChangeSpec {
131 location: IntPosition,
132 block_id: VarInt
133 },
134 PlayBossBar, 0x0C, Play, ClientBound => PlayBossBarSpec {
135 uuid: UUID4,
136 action: BossBarAction
137 },
138 PlayServerDifficulty, 0x0D, Play, ClientBound => PlayServerDifficultySpec {
139 difficulty: Difficulty,
140 locked: bool
141 },
142 PlayServerChatMessage, 0x0E, Play, ClientBound => PlayServerChatMessageSpec {
143 message: Chat,
144 position: ChatPosition,
145 sender: UUID4
146 },
147 PlayTabComplete, 0x0F, Play, ClientBound => PlayTabCompleteSpec {
148 id: VarInt,
149 start: VarInt,
150 length: VarInt,
151 matches: CountedArray<TabCompleteMatch, VarInt>
152 },
153 PlayDeclareCommands, 0x10, Play, ClientBound => PlayDeclareCommandsSpec {
154 nodes: CountedArray<CommandNodeSpec, VarInt>,
155 root_index: VarInt
156 },
157 PlayServerWindowConfirmation, 0x11, Play, ClientBound => PlayServerWindowConfirmationSpec {
158 window_id: u8,
159 action_number: i16,
160 accepted: bool
161 },
162 PlayServerCloseWindow, 0x12, Play, ClientBound => PlayServerCloseWindowSpec {
163 window_id: u8
164 },
165 PlayWindowItems, 0x13, Play, ClientBound => PlayWindowItemsSpec {
166 window_id: u8,
167 slots: CountedArray<Slot, i16>
168 },
169 PlayWindowProperty, 0x14, Play, ClientBound => PlayWindowPropertySpec {
170 window_id: u8,
171 property: i16,
172 value: i16
173 },
174 PlaySetSlot, 0x15, Play, ClientBound => PlaySetSlotSpec {
175 window_id: u8,
176 slow: i16,
177 slot_data: Slot
178 },
179 PlaySetCooldown, 0x16, Play, ClientBound => PlaySetCooldownSpec {
180 item_id: VarInt,
181 cooldown_ticks: VarInt
182 },
183 PlayServerPluginMessage, 0x17, Play, ClientBound => PlayServerPluginMessageSpec {
184 channel: String,
185 data: RemainingBytes
186 },
187 PlayNamedSoundEffect, 0x18, Play, ClientBound => PlayNamedSoundEffectSpec {
188 sound_name: String,
189 sound_category: SoundCategory,
190 position: Vec3<FixedInt>,
191 volume: f32,
192 pitch: f32
193 },
194 PlayDisconnect, 0x19, Play, ClientBound => PlayDisconnectSpec {
195 reason: Chat
196 },
197 PlayEntityStatus, 0x1A, Play, ClientBound => PlayEntityStatusSpec {
198 entity_id: i32,
199 raw_status: u8 },
201 PlayExplosion, 0x1B, Play, ClientBound => PlayExplosionSpec {
202 position: Vec3<f32>,
203 strength: f32,
204 records: CountedArray<Vec3<i8>, i32>,
205 player_motion: Vec3<f32>
206 },
207 PlayUnloadChunk, 0x1C, Play, ClientBound => PlayUnloadChunkSpec {
208 position: ChunkPosition<i32>
209 },
210 PlayChangeGameState, 0x1D, Play, ClientBound => PlayChangeGameStateSpec {
211 reason: GameChangeReason
212 },
213 PlayOpenHorseWindow, 0x1E, Play, ClientBound => PlayOpenHorseWindowSpec {
214 window_id: u8,
215 number_of_slots: VarInt,
216 entity_id: i32
217 },
218 PlayServerKeepAlive, 0x1F, Play, ClientBound => PlayServerKeepAliveSpec {
219 id: i64
220 },
221 PlayChunkData, 0x20, Play, ClientBound => PlayChunkDataWrapper {
222 data: ChunkData
223 },
224 PlayEffect, 0x21, Play, ClientBound => PlayEffectSpec {
225 effect_id: i32,
226 location: IntPosition,
227 data: i32,
228 disable_relative_volume: bool
229 },
230 PlayParticle, 0x22, Play, ClientBound => PlayParticleSpec {
231 particle_id: i32,
232 long_distance: bool,
233 position: Vec3<f64>,
234 offset: Vec3<f32>,
235 particle_data: i32,
236 data: RemainingBytes },
238 PlayUpdateLight, 0x23, Play, ClientBound => PlayUpdateLightSpec {
239 chunk: ChunkPosition<VarInt>,
240 trust_edges: bool,
241 update: LightingUpdateSpec
242 },
243 PlayJoinGame, 0x24, Play, ClientBound => PlayJoinGameSpec {
244 entity_id: i32,
245 is_hardcore: bool,
246 gamemode: GameMode,
247 previous_gamemode: PreviousGameMode,
248 worlds: CountedArray<String, VarInt>,
249 dimension_codec: NamedNbtTag,
250 dimension: NamedNbtTag,
251 world_name: String,
252 hashed_seed: i64,
253 max_players: VarInt,
254 view_distance: VarInt,
255 reduced_debug_info: bool,
256 enable_respawn_screen: bool,
257 is_debug: bool,
258 is_flat: bool
259 },
260 PlayMapData, 0x25, Play, ClientBound => PlayMapDataSpec {
261 map_id: VarInt,
262 scale: i8,
263 tracking_position: bool,
264 locked: bool,
265 icons: CountedArray<MapIconSpec, VarInt>,
266 columns: MapColumns
267 },
268 PlayTradeList, 0x26, Play, ClientBound => PlayTradeListSpec {
269 window_id: VarInt,
270 trades: CountedArray<TradeSpec, i8>,
271 villager_level: VarInt,
272 experience: VarInt,
273 regular_villager: bool,
274 can_restock: bool
275 },
276 PlayEntityPosition, 0x27, Play, ClientBound => PlayEntityPositionSpec {
277 entity_id: VarInt,
278 delta: Vec3<i16>,
279 on_ground: bool
280 },
281 PlayEntityPositionAndRotation, 0x28, Play, ClientBound => PlayEntityPositionAndRotationSpec {
282 entity_id: VarInt,
283 delta: EntityLocation<i16, Angle>,
284 on_ground: bool
285 },
286 PlayEntityRotation, 0x29, Play, ClientBound => PlayEntityRotationSpec {
287 entity_id: VarInt,
288 rotation: EntityRotation<Angle>,
289 on_ground: bool
290 },
291 PlayEntityMovement, 0x2A, Play, ClientBound => PlayEntityMovementSpec {
292 entity_id: VarInt
293 },
294 PlayServerVehicleMove, 0x2B, Play, ClientBound => PlayEntityVehicleMoveSpec {
295 location: EntityLocation<f64, f32>
296 },
297 PlayOpenBook, 0x2C, Play, ClientBound => PlayOpenBookSpec {
298 hand: Hand
299 },
300 PlayOpenWindow, 0x2D, Play, ClientBound => PlayOpenWindowSpec {
301 id: VarInt,
302 kind: WindowType,
303 title: Chat
304 },
305 PlayOpenSignEditor, 0x2E, Play, ClientBound => PlayOpenSignEditorSpec {
306 location: IntPosition
307 },
308 PlayCraftRecipeResponse, 0x2F, Play, ClientBound => PlayCraftRecipeResponseSpec {
309 window_id: u8,
310 recipe: String
311 },
312 PlayServerPlayerAbilities, 0x30, Play, ClientBound => PlayServerPlayerAbilitiesSpec {
313 flags: PlayerAbilityFlags,
314 flying_speed: f32,
315 field_of_view_modifier: f32
316 },
317 PlayCombatEvent, 0x31, Play, ClientBound => PlayCombatEventSpec {
318 event: CombatEvent
319 },
320 PlayPlayerInfo, 0x32, Play, ClientBound => PlayPlayerInfoSpec {
321 actions: PlayerInfoActionList
322 },
323 PlayFacePlayer, 0x33, Play, ClientBound => PlayFacePlayerSpec {
324 face_kind: FacePlayerKind,
325 target: Vec3<f64>,
326 entity: Option<FacePlayerEntityTarget>
327 },
328 PlayServerPlayerPositionAndLook, 0x34, Play, ClientBound => PlayServerPlayerPositionAndLookSpec {
329 location: EntityLocation<f64, f32>,
330 flags: PositionAndLookFlags,
331 teleport_id: VarInt
332 },
333 PlayUnlockRecipes, 0x35, Play, ClientBound => PlayUnlockRecipesSpec {
334 action: RecipeUnlockAction,
335 crafting_book_open: bool,
336 crafting_book_active: bool,
337 smelting_book_open: bool,
338 smelting_book_active: bool,
339 blast_furnace_recipe_book_open: bool,
340 blast_furnace_recipe_book_active: bool,
341 smoke_recipe_book_open: bool,
342 smoke_recipe_book_active: bool,
343 recipe_ids: CountedArray<String, VarInt>,
344 other_recipe_ids: RemainingBytes },
346 PlayDestroyEntities, 0x36, Play, ClientBound => PlayDestroyEntitiesSpec {
347 entity_ids: CountedArray<VarInt, VarInt>
348 },
349 PlayRemoveEntityEffect, 0x37, Play, ClientBound => PlayRemoveEntityEffectSpec {
350 entity_id: VarInt,
351 effect: EntityEffectKind
352 },
353 PlayResourcePackSend, 0x38, Play, ClientBound => PlayResourcePackSendSpec {
354 url: String,
355 hash: String
356 },
357 PlayRespawn, 0x39, Play, ClientBound => PlayRespawnSpec {
358 dimension: NamedNbtTag,
359 world_name: String,
360 hashed_seed: i64,
361 gamemode: GameMode,
362 previous_gamemode: GameMode,
363 is_debug: bool,
364 is_flat: bool,
365 copy_metadata: bool
366 },
367 PlayEntityHeadLook, 0x3A, Play, ClientBound => PlayEntityHeadLookSpec {
368 entity_id: VarInt,
369 head_yaw: Angle
370 },
371 PlayMultiBlockChange, 0x3B, Play, ClientBound => PlayMultiBlockChangeSpec {
372 chunk: ChunkSectionPosition,
373 not_trust_edges: bool,
374 blocks: CountedArray<MultiBlockChangeRecord, VarInt>
375 },
376 PlaySelectAdvancementTab, 0x3C, Play, ClientBound => PlaySelectAdvancementTabSpec {
377 identifier: Option<String>
378 },
379 PlayWorldBorder, 0x3D, Play, ClientBound => PlayWorldBorderSpec {
380 action: WorldBorderAction
381 },
382 PlayCamera, 0x3E, Play, ClientBound => PlayCameraSpec {
383 camera_id: VarInt
384 },
385 PlayServerHeldItemChange, 0x3F, Play, ClientBound => PlayServerHeldItemChangeSpec {
386 slot: i8
387 },
388 PlayUpdateViewPosition, 0x40, Play, ClientBound => PlayUpdateViewPositionSpec {
389 chunk: ChunkPosition<VarInt>
390 },
391 PlayUpdateViewDistance, 0x41, Play, ClientBound => PlayUpdateViewDistanceSpec {
392 view_distance: VarInt
393 },
394 PlaySpawnPosition, 0x42, Play, ClientBound => PlaySpawnPositionSpec {
395 location: IntPosition
396 },
397 PlayDisplayScoreboard, 0x43, Play, ClientBound => PlayDisplayScoreboardSpec {
398 position: ScoreboardPosition,
399 score_name: String
400 },
401 PlayEntityMetadata, 0x44, Play, ClientBound => PlayEntityMetadataSpec {
402 entity_id: VarInt,
403 metadata: EntityMetadata
404 },
405 PlayAttachEntity, 0x45, Play, ClientBound => PlayAttachEntitySpec {
406 attached_entity_id: i32,
407 holding_entity_id: i32
408 },
409 PlayEntityVelocity, 0x46, Play, ClientBound => PlayEntityVelocitySpec {
410 entity_id: VarInt,
411 velocity: Vec3<i16>
412 },
413 PlayEntityEquipment, 0x47, Play, ClientBound => PlayEntityEquiptmentSpec {
414 entity_id: VarInt,
415 equipment: EntityEquipmentArray
416 },
417 PlaySetExperience, 0x48, Play, ClientBound => PlaySetExperienceSpec {
418 experience_bar: f32,
419 level: VarInt,
420 total_experience: VarInt
421 },
422 PlayUpdatehealth, 0x49, Play, ClientBound => PlayUpdateHealthSpec {
423 health: f32,
424 food: VarInt,
425 saturation: f32
426 },
427 PlayScoreboardObjective, 0x4A, Play, ClientBound => PlayScoreboardObjectiveSpec {
428 objective_name: String,
429 action: ScoreboardObjectiveAction
430 },
431 PlaySetPassengers, 0x4B, Play, ClientBound => PlaySetPassengersSpec {
432 entity_id: VarInt,
433 passenger_entitiy_ids: CountedArray<VarInt, VarInt>
434 },
435 PlayTeams, 0x4C, Play, ClientBound => PlayTeamsSpec {
436 team_name: String,
437 action: TeamAction
438 },
439 PlayUpdateScore, 0x4D, Play, ClientBound => PlayUpdateScoreSpec {
440 entity_name: TeamMember,
441 update: UpdateScoreSpec
442 },
443 PlayTimeUpdate, 0x4E, Play, ClientBound => PlayTimeUpdateSpec {
444 world_age: i64,
445 time_of_day: i64
446 },
447 PlayTitle, 0x4F, Play, ClientBound => PlayTitleSpec {
448 action: TitleActionSpec
449 },
450 PlayEntitySoundEffect, 0x50, Play, ClientBound => PlayEntitySoundEffectSpec {
451 sound_id: VarInt,
452 sound_category: SoundCategory,
453 entity_id: VarInt,
454 volume: f32,
455 pitch: f32
456 },
457 PlaySoundEffect, 0x51, Play, ClientBound => PlaySoundEffectSpec {
458 sound_id: VarInt,
459 sound_category: SoundCategory,
460 position: Vec3<FixedInt>,
461 volume: f32,
462 pitch: f32
463 },
464 PlayStopSound, 0x52, Play, ClientBound => PlayStopSoundSpec {
465 spec: StopSoundSpec
466 },
467 PlayerPlayerListHeaderAndFooter, 0x53, Play, ClientBound => PlayPlayerListHeaderAndFooterSpec {
468 header: Chat,
469 footer: Chat
470 },
471 PlayNbtQueryResponse, 0x54, Play, ClientBound => PlayNbtQueryResponseSpec {
472 transaction_id: VarInt,
473 nbt: NamedNbtTag
474 },
475 PlayCollectItem, 0x55, Play, ClientBound => PlayCollectItemSpec {
476 collected_entity_id: VarInt,
477 collector_entity_id: VarInt,
478 pickup_item_count: VarInt
479 },
480 PlayEntityTeleport, 0x56, Play, ClientBound => PlayEntityTeleportSpec {
481 entity_id: VarInt,
482 location: EntityLocation<f64, Angle>,
483 on_ground: bool
484 },
485 PlayAdvancements, 0x57, Play, ClientBound => PlayAdvancementsSpec {
486 reset: bool,
487 mappings: CountedArray<AdvancementMappingEntrySpec, VarInt>,
488 identifiers: CountedArray<String, VarInt>,
489 progress: CountedArray<AdvancementProgressEntrySpec, VarInt>
490 },
491 PlayEntityProperties, 0x58, Play, ClientBound => PlayEntityPropertiesSpec {
492 entity_id: VarInt,
493 properties: CountedArray<EntityPropertySpec, i32>
494 },
495 PlayEntityEffect, 0x59, Play, ClientBound => PlayEntityEffectSpec {
496 entity_id: VarInt,
497 effect_id: EntityEffectKind,
498 amplifier: i8,
499 duration_ticks: VarInt,
500 flags: EntityEffectFlags
501 },
502 PlayDeclareRecipes, 0x5A, Play, ClientBound => PlayDeclareRecipesSpec {
503 recipes: CountedArray<RecipeSpec, VarInt>
504 },
505 PlayTags, 0x5B, Play, ClientBound => PlayTagsSpec {
506 block_tags: CountedArray<TagSpec, VarInt>,
507 item_tags: CountedArray<TagSpec, VarInt>,
508 fluid_tags: CountedArray<TagSpec, VarInt>,
509 entity_tags: CountedArray<TagSpec, VarInt>
510 },
511
512 PlayTeleportConfirm, 0x00, Play, ServerBound => PlayTeleportConfirmSpec {
514 teleport_id: VarInt
515 },
516 PlayQueryBlockNbt, 0x01, Play, ServerBound => PlayQueryBlockNbtSpec {
517 transaction_id: VarInt,
518 location: IntPosition
519 },
520 PlayQueryEntityNbt, 0x0D, Play, ServerBound => PlayQueryEntityNbtSpec {
521 transaction_id: VarInt,
522 entity_id: VarInt
523 },
524 PlaySetDifficulty, 0x02, Play, ServerBound => PlaySetDifficultySpec {
525 new_difficulty: Difficulty
526 },
527 PlayClientChatMessage, 0x03, Play, ServerBound => PlayClientChatMessageSpec {
528 message: String
529 },
530 PlayClientStatus, 0x04, Play, ServerBound => PlayClientStatusSpec {
531 action: ClientStatusAction
532 },
533 PlayClientSettings, 0x05, Play, ServerBound => PlayClientSettingsSpec {
534 locale: String,
535 view_distance: i8,
536 chat_mode: ClientChatMode,
537 chat_colors: bool,
538 displayed_skin_parts: ClientDisplayedSkinParts,
539 main_hand: ClientMainHand
540 },
541 PlayClientTabComplete, 0x06, Play, ServerBound => PlayClientTabCompleteSpec {
542 transaction_id: VarInt,
543 text: String
544 },
545 PlayClientWindowConfirmation, 0x07, Play, ServerBound => PlayClientWindowConfirmationSpec {
546 window_id: i8,
547 action_num: i16,
548 accepted: bool
549 },
550 PlayClickWindowButton, 0x08, Play, ServerBound => PlayClickWindowButtonSpec {
551 window_id: i8,
552 button_id: i8
553 },
554 PlayClickWindow, 0x09, Play, ServerBound => PlayClickWindowSpec {
555 window_id: u8,
556 slot: i16,
557 button: i8,
558 action_number: i16,
559 mode: InventoryOperationMode,
560 clicked_item: Slot
561 },
562 PlayClientCloseWindow, 0x0A, Play, ServerBound => PlayClientCloseWindowSpec {
563 window_id: u8
564 },
565 PlayClientPluginMessage, 0x0B, Play, ServerBound => PlayClientPluginMessageSpec {
566 channel: String,
567 data: RemainingBytes
568 },
569 PlayEditBook, 0x0C, Play, ServerBound => PlayEditBookSpec {
570 new_book: Slot,
571 is_signing: bool,
572 hand: Hand
573 },
574 PlayInteractEntity, 0x0E, Play, ServerBound => PlayInteractEntitySpec {
575 entity_id: VarInt,
576 kind: InteractKind,
577 sneaking: bool
578 },
579 PlayGenerateStructure, 0x0F, Play, ServerBound => PlayGenerateStructureSpec {
580 location: IntPosition,
581 levels: VarInt,
582 keep_jigsaws: bool
583 },
584 PlayClientKeepAlive, 0x10, Play, ServerBound => PlayClientKeepAliveSpec {
585 id: i64
586 },
587 PlayLockDifficulty, 0x11, Play, ServerBound => PlayLockDifficultySpec {
588 locked: bool
589 },
590 PlayPlayerPosition, 0x12, Play, ServerBound => PlayPlayerPositionSpec {
591 feet_position: Vec3<f64>,
592 on_ground: bool
593 },
594 PlayClientPlayerPositionAndRotation, 0x13, Play, ServerBound => PlayClientPlayerPositionAndRotationSpec {
595 feet_location: EntityLocation<f64, f32>,
596 on_ground: bool
597 },
598 PlayPlayerRotation, 0x14, Play, ServerBound => PlayPlayerRotationSpec {
599 rotation: EntityRotation<f32>,
600 on_ground: bool
601 },
602 PlayPlayerMovement, 0x15, Play, ServerBound => PlayPlayerMovementSpec {
603 on_ground: bool
604 },
605 PlayClientVehicleMove, 0x16, Play, ServerBound => PlayClientVehicleMoveSpec {
606 location: EntityLocation<f64, f32>
607 },
608 PlaySteerBoat, 0x17, Play, ServerBound => PlaySteerBoatSpec {
609 left_paddle_turning: bool,
610 right_paddle_turning: bool
611 },
612 PlayPickItem, 0x18, Play, ServerBound => PlayPickItemSpec {
613 slot_idx: VarInt
614 },
615 PlayCraftRecipeRequest, 0x19, Play, ServerBound => PlayCraftRecipeRequestSpec {
616 window_id: i8,
617 recipe: String,
618 make_all: bool
619 },
620 PlayClientPlayerAbilities, 0x1A, Play, ServerBound => PlayClientPlayerAbilitiesSpec {
621 flags: ClientPlayerAbilities
622 },
623 PlayPlayerDigging, 0x1B, Play, ServerBound => PlayPlayerDiggingSpec {
624 status: PlayerDiggingStatus,
625 location: IntPosition,
626 face: DiggingFace
627 },
628 PlayEntityAction, 0x1C, Play, ServerBound => PlayEntityActionSpec {
629 entity_id: VarInt,
630 action: EntityActionKind,
631 jump_boot: VarInt
632 },
633 PlaySteerVehicle, 0x1D, Play, ServerBound => PlaySteerVehicleSpec {
634 sideways: f32,
635 forward: f32,
636 flags: SteerVehicleFlags
637 },
638 PlaySetDisplayedRecipe, 0x1E, Play, ServerBound => PlaySetDisplayedRecipeSpec {
639 recipe_id: String
640 },
641 PlaySetRecipeBookState, 0x1F, Play, ServerBound => PlaySetRecipeBookStateSpec {
642 book_id: RecipeBookType,
643 open: bool,
644 filtered: bool
645 },
646 PlayNameItem, 0x20, Play, ServerBound => PlayNameItemSpec {
647 name: String
648 },
649 PlayResourcePackStatus, 0x21, Play, ServerBound => PlayResourcePackStatusSpec {
650 status: ResourcePackStatus
651 },
652 PlayAdvancementTab, 0x22, Play, ServerBound => PlayAdvancementTabSpec {
653 action: AdvancementTabAction
654 },
655 PlaySelectTrade, 0x23, Play, ServerBound => PlaySelectTradeSpec {
656 selected_slot: VarInt
657 },
658 PlaySetBeaconEffect, 0x24, Play, ServerBound => PlaySetBeaconEffectSpec {
659 primary_effect: VarInt,
660 secondary_effect: VarInt
661 },
662 PlayClientHeldItemChange, 0x25, Play, ServerBound => PlayClientHeldItemChangeSpec {
663 slot: i16
664 },
665 PlayUpdateCommandBlock, 0x26, Play, ServerBound => PlayUpdateCommandBlockSpec {
666 location: IntPosition,
667 command: String,
668 mode: CommandBlockMode,
669 flags: CommandBlockFlags
670 },
671 PlayUpdateCommandBlockMinecart, 0x27, Play, ServerBound => PlayUpdateCommandBlockMinecartSpec {
672 entity_id: VarInt,
673 command: String,
674 track_output: bool
675 },
676 PlayUpdateJigsawBlock, 0x28, Play, ServerBound => PlayUpdateJigsawBlockSpec {
677 location: IntPosition,
678 attachment_type: String,
679 target_pool: String,
680 final_state: String
681 },
682 PlayCreativeInventoryAction, 0x29, Play, ServerBound => PlayCreativeInventoryActionSpec {
683 slot: i16,
684 clicked_item: Slot
685 },
686 PlayUpdateStructureBlock, 0x2A, Play, ServerBound => PlayUpdateStructureBlockSpec {
687 location: IntPosition,
688 action: UpdateStructureBlockAction,
689 mode: UpdateStructureBlockMode,
690 name: String,
691 offset: Vec3<i8>,
692 size: Vec3<i8>,
693 mirror: UpdateStructureBlockMirror,
694 rotation: UpdateStructureBlockRotation,
695 metadata: String,
696 integrity: f32,
697 seed: VarLong,
698 flags: UpdateStructureBlockFlags
699 },
700 PlayUpdateSign, 0x2B, Play, ServerBound => PlayUpdateSignSpec {
701 location: IntPosition,
702 line1: String,
703 line2: String,
704 line3: String,
705 line4: String
706 },
707 PlayClientAnimation, 0x2C, Play, ServerBound => PlayClientAnimationSpec {
708 hand: Hand
709 },
710 PlaySpectate, 0x2D, Play, ServerBound => PlaySpectateSpec {
711 target: UUID4
712 },
713 PlayBlockPlacement, 0x2E, Play, ServerBound => PlayBlockPlacementSpec {
714 hand: Hand,
715 location: IntPosition,
716 face: DiggingFace,
717 cursor_position: Vec3<f32>,
718 inside_block: bool
719 },
720 PlayUseItem, 0x2F, Play, ServerBound => PlayUseItemSpec {
721 hand: Hand
722 }
723});
724
725proto_byte_enum!(HandshakeNextState,
729 0x01 :: Status,
730 0x02 :: Login
731);
732
733proto_byte_enum!(CardinalDirection,
734 0x00 :: South,
735 0x01 :: West,
736 0x02 :: North,
737 0x03:: East
738);
739
740proto_byte_enum!(EntityAnimationKind,
741 0x00 :: SwingMainArm,
742 0x01 :: TakeDamage,
743 0x02 :: LeaveBed,
744 0x03 :: SwingOffHand,
745 0x04 :: CriticalEffect,
746 0x05 :: MagicCriticalEffect
747);
748
749proto_varint_enum!(StatisticCategory,
750 0x00 :: Mined(VarInt),
751 0x01 :: Crafted(VarInt),
752 0x02 :: Used(VarInt),
753 0x03 :: Broken(VarInt),
754 0x04 :: PickedUp(VarInt),
755 0x05 :: Dropped(VarInt),
756 0x06 :: Killed(VarInt),
757 0x07 :: KilledBy(VarInt),
758 0x08 :: Custom(StatisticKind)
759);
760
761proto_varint_enum!(StatisticKind,
762 0x00 :: LeaveGame,
763 0x01 :: PlayOneMinute,
764 0x02 :: TimeSinceDeath,
765 0x03 :: SneakTime,
766 0x04 :: WealkOneCm,
767 0x05 :: CrouchOneCm,
768 0x06 :: SprintOneCm,
769 0x07 :: SwimOneCm,
770 0x08 :: FallOneCm,
771 0x09 :: ClimbOneCm,
772 0x0A :: FlyOneCm,
773 0x0B :: DiveOneCm,
774 0x0C :: MinecartOneCm,
775 0x0D :: BoatOneCm,
776 0x0E :: PigOneCm,
777 0x0F :: HorseOneCm,
778 0x10 :: AviateOneCm,
779 0x11 :: Jumps,
780 0x12 :: Drops,
781 0x13 :: DamageDealt,
782 0x14 :: DamageTaken,
783 0x15 :: Deaths,
784 0x16 :: MobKills,
785 0x17 :: AnimalsBread,
786 0x18 :: PlayerKills,
787 0x19 :: FishCaught,
788 0x1A :: TalkedToVillager,
789 0x1B :: TradedWithVillager,
790 0x1C :: EatCakeSlice,
791 0x1D :: FillCauldron,
792 0x1E :: UseCauldron,
793 0x1F :: CleanArmor,
794 0x20 :: CleanBanner,
795 0x21 :: InteractWithBrewingStand,
796 0x22 :: InteractWithBeaccon,
797 0x23 :: InspectDropper,
798 0x24 :: InspectHopper,
799 0x25 :: InspectDispenser,
800 0x26 :: PlayNoteBlock,
801 0x27 :: TuneNoteBlock,
802 0x28 :: PotFlower,
803 0x29 :: TriggerTrappedChest,
804 0x2A :: OpenEnderChest,
805 0x2B :: EnchantItem,
806 0x2C :: PlayRecord,
807 0x2D :: InteractWithFurnace,
808 0x2E :: InteractWithCraftingTable,
809 0x2F :: OpenChest,
810 0x30 :: SleepInBed,
811 0x31 :: OpenShulkerBox
812);
813
814proto_struct!(Statistic {
815 kind: StatisticCategory,
816 value: VarInt
817});
818
819proto_byte_enum!(DiggingStatus,
820 0x00 :: Started,
821 0x01 :: Cancelled,
822 0x02 :: Finished
823);
824
825proto_byte_enum!(BlockEntityDataAction,
826 0x01 :: SetMobSpawnerData,
827 0x02 :: SetCommandBlockText,
828 0x03 :: SetBeaconLevelAndPower,
829 0x04 :: SetMobHeadRotationAndSkin,
830 0x05 :: DeclareConduit,
831 0x06 :: SetBannerColorAndPatterns,
832 0x07 :: SetStructureTileEntityData,
833 0x08 :: SetEndGatewayDestination,
834 0x09 :: SetSignText,
835 0x0B :: DeclareBed,
836 0x0C :: SetJigsawBlockData,
837 0x0D :: SetCampfireItems,
838 0x0E :: BeehiveInformation
839);
840
841proto_byte_enum!(Difficulty,
842 0x00 :: Peaceful,
843 0x01 :: Easy,
844 0x02 :: Normal,
845 0x03 :: Hard
846);
847
848proto_byte_enum!(ChatPosition,
849 0x00 :: ChatBox,
850 0x01 :: SystemMessage,
851 0x02 :: Hotbar
852);
853
854#[derive(Copy, Clone, PartialEq, Debug)]
855pub struct BlockChangeHorizontalPosition {
856 pub rel_x: u8,
857 pub rel_z: u8,
858}
859
860impl Serialize for BlockChangeHorizontalPosition {
861 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
862 to.serialize_byte((self.rel_x & 0xF) << 4 | (self.rel_z & 0xF))
863 }
864}
865
866impl Deserialize for BlockChangeHorizontalPosition {
867 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
868 Ok(
869 u8::mc_deserialize(data)?.map(move |b| BlockChangeHorizontalPosition {
870 rel_x: (b >> 4) & 0xF,
871 rel_z: b & 0xF,
872 }),
873 )
874 }
875}
876
877#[cfg(all(test, feature = "std"))]
878impl TestRandom for BlockChangeHorizontalPosition {
879 fn test_gen_random() -> Self {
880 BlockChangeHorizontalPosition {
881 rel_x: rand::random::<u8>() % 16,
882 rel_z: rand::random::<u8>() % 16,
883 }
884 }
885}
886
887#[derive(Debug, Clone, PartialEq, Copy)]
888pub struct ChunkSectionPosition {
889 pub x: i32,
890 pub y: i32,
891 pub z: i32,
892}
893
894impl Serialize for ChunkSectionPosition {
895 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
896 let num = (((self.x as u64) & 0x3FFFFF) << 42)
897 | (((self.z as u64) & 0x3FFFFF) << 20)
898 | ((self.y as u64) & 0xFFFFF);
899
900 to.serialize_other(&num)
901 }
902}
903
904impl Deserialize for ChunkSectionPosition {
905 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
906 let Deserialized { value: raw, data } = u64::mc_deserialize(data)?;
907 let y = (raw & 0xFFFFF) as i32;
908 let z = ((raw >> 20) & 0x3FFFFF) as i32;
909 let x = ((raw >> 42) & 0x3FFFFF) as i32;
910 Deserialized::ok(Self { x, y, z }, data)
911 }
912}
913
914#[cfg(all(test, feature = "std"))]
915impl TestRandom for ChunkSectionPosition {
916 fn test_gen_random() -> Self {
917 Self {
918 x: (u32::test_gen_random() & 0x3FFFFF) as i32,
919 y: (u32::test_gen_random() & 0xFFFFF) as i32,
920 z: (u32::test_gen_random() & 0x3FFFFF) as i32,
921 }
922 }
923}
924
925#[derive(Debug, Clone, PartialEq, Copy)]
926pub struct MultiBlockChangeRecord {
927 pub block_id: u64,
928 pub rel_position: Vec3<i8>,
929}
930
931impl Serialize for MultiBlockChangeRecord {
932 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
933 let raw = (self.block_id << 12)
934 | (((self.rel_position.x as u64) & 0xF) << 8)
935 | (((self.rel_position.y as u64) & 0xF) << 4)
936 | ((self.rel_position.z as u64) & 0xF);
937 let raw = VarLong(raw as i64);
938 to.serialize_other(&raw)
939 }
940}
941
942impl Deserialize for MultiBlockChangeRecord {
943 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
944 let Deserialized { value: raw, data } = VarLong::mc_deserialize(data)?;
945 let raw = raw.0 as u64;
946 let block_id = raw >> 12;
947 let x = ((raw >> 8) & 0xF) as i8;
948 let y = ((raw >> 4) & 0xF) as i8;
949 let z = (raw & 0xF) as i8;
950 let rel_position = (x, y, z).into();
951 Deserialized::ok(Self { block_id, rel_position }, data)
952 }
953}
954
955#[cfg(all(test, feature = "std"))]
956impl TestRandom for MultiBlockChangeRecord {
957 fn test_gen_random() -> Self {
958 let mut rel_position = <Vec3<i8>>::test_gen_random();
959 rel_position.x &= 0xF;
960 rel_position.y &= 0xF;
961 rel_position.z &= 0xF;
962 let block_id = u64::test_gen_random() & ((1 << 52) - 1);
963
964 Self {
965 block_id,
966 rel_position,
967 }
968 }
969}
970
971proto_varint_enum!(BossBarAction,
972 0x00 :: Add(BossBarAddSpec),
973 0x01 :: Remove,
974 0x02 :: UpdateHealth(BossBarUpdateHealthSpec),
975 0x03 :: UpdateTitle(BossBarUpdateTitleSpec),
976 0x04 :: UpdateStyle(BossBarUpdateStyleSpec),
977 0x05 :: UpdateFlags(BossBarUpdateFlagsSpec)
978);
979
980proto_varint_enum!(BossBarColor,
981 0x00 :: Pink,
982 0x01 :: Blue,
983 0x02 :: Red,
984 0x03 :: Green,
985 0x04 :: Yellow,
986 0x05 :: Purple,
987 0x06 :: White
988);
989
990proto_varint_enum!(BossBarDivision,
991 0x00 :: NoDivision,
992 0x01 :: SixNotches,
993 0x02 :: TenNotches,
994 0x03 :: TwelveNotches,
995 0x04 :: TwentyNotches
996);
997
998proto_byte_flag!(BossBarFlags,
999 0x01 :: is_darken_sky set_darken_sky,
1000 0x02 :: is_dragon_bar set_dragon_bar,
1001 0x04 :: is_create_fog set_create_fog
1002);
1003
1004proto_struct!(BossBarAddSpec {
1005 title: Chat,
1006 health: f32,
1007 color: BossBarColor,
1008 division: BossBarDivision,
1009 flags: BossBarFlags
1010});
1011
1012proto_struct!(BossBarUpdateHealthSpec { health: f32 });
1013
1014proto_struct!(BossBarUpdateTitleSpec { title: String });
1015
1016proto_struct!(BossBarUpdateStyleSpec {
1017 color: BossBarColor,
1018 dividers: BossBarDivision
1019});
1020
1021proto_struct!(BossBarUpdateFlagsSpec {
1022 flags: BossBarFlags
1023});
1024
1025proto_struct!(TabCompleteMatch {
1026 match_: String,
1027 tooltip: Option<Chat>
1028});
1029
1030#[derive(Clone, Debug, PartialEq)]
1031pub struct CommandNodeSpec {
1032 pub children_indices: CountedArray<VarInt, VarInt>,
1033 pub redirect_node: Option<VarInt>,
1034 pub is_executable: bool,
1035 pub node: CommandNode,
1036}
1037
1038#[derive(Clone, Debug, PartialEq)]
1039pub enum CommandNode {
1040 Root,
1041 Argument(CommandArgumentNodeSpec),
1042 Literal(CommandLiteralNodeSpec),
1043}
1044
1045impl Serialize for CommandNodeSpec {
1046 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1047 let mut flags: u8 = 0;
1048
1049 use CommandNode::*;
1050
1051 flags |= match &self.node {
1052 Root => 0x00,
1053 Literal(_) => 0x01,
1054 Argument(_) => 0x02,
1055 };
1056
1057 if self.is_executable {
1058 flags |= 0x04;
1059 }
1060
1061 if self.redirect_node.is_some() {
1062 flags |= 0x08;
1063 }
1064
1065 if let Argument(body) = &self.node {
1066 if body.suggestions_types.is_some() {
1067 flags |= 0x10
1068 }
1069 }
1070
1071 to.serialize_byte(flags)?;
1072 to.serialize_other(&self.children_indices)?;
1073 if let Some(redirect_node) = &self.redirect_node {
1074 to.serialize_other(redirect_node)?;
1075 }
1076
1077 match &self.node {
1078 Root => Ok(()),
1079 Argument(body) => body.serialize(to),
1080 Literal(body) => to.serialize_other(body),
1081 }
1082 }
1083}
1084
1085impl Deserialize for CommandNodeSpec {
1086 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1087 let Deserialized { value: flags, data } = u8::mc_deserialize(data)?;
1088 let Deserialized { value: children_indices, data } = <CountedArray<VarInt, VarInt>>::mc_deserialize(data)?;
1089 let (redirect_node, data) = if flags & 0x08 != 0 {
1090 let Deserialized { value: redirect_node, data } = VarInt::mc_deserialize(data)?;
1091 (Some(redirect_node), data)
1092 } else {
1093 (None, data)
1094 };
1095 let is_executable = flags & 0x04 != 0;
1096
1097 use CommandNode::*;
1098 let Deserialized { value: node, data } = match flags & 0x03 {
1099 0x00 => Deserialized::ok(Root, data),
1100 0x01 => Ok(CommandLiteralNodeSpec::mc_deserialize(data)?.map(move |body| Literal(body))),
1101 0x02 => Ok(CommandArgumentNodeSpec::deserialize(flags & 0x10 != 0, data)?.map(move |body| Argument(body))),
1102 other => panic!("impossible condition (bitmask) {}", other)
1103 }?;
1104
1105 Deserialized::ok(Self {
1106 children_indices,
1107 redirect_node,
1108 is_executable,
1109 node,
1110 }, data)
1111 }
1112}
1113
1114#[cfg(all(test, feature = "std"))]
1115impl TestRandom for CommandNodeSpec {
1116 fn test_gen_random() -> Self {
1117 let children_indices = <CountedArray<VarInt, VarInt>>::test_gen_random();
1118 let redirect_node = <Option<VarInt>>::test_gen_random();
1119 let is_executable = rand::random::<bool>();
1120 let idx = rand::random::<usize>() % 3;
1121 let node = match idx {
1122 0 => CommandNode::Root,
1123 1 => CommandNode::Argument(CommandArgumentNodeSpec::test_gen_random()),
1124 2 => CommandNode::Literal(CommandLiteralNodeSpec::test_gen_random()),
1125 other => panic!("impossible state {}", other)
1126 };
1127
1128 Self {
1129 children_indices,
1130 redirect_node,
1131 is_executable,
1132 node,
1133 }
1134 }
1135}
1136
1137#[derive(Clone, Debug, PartialEq)]
1138pub struct CommandArgumentNodeSpec {
1139 pub name: String,
1140 pub parser: CommandParserSpec,
1141 pub suggestions_types: Option<SuggestionsTypeSpec>,
1142}
1143
1144impl CommandArgumentNodeSpec {
1145 fn serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1146 to.serialize_other(&self.name)?;
1147 to.serialize_other(&self.parser)?;
1148 if let Some(suggestions_types) = &self.suggestions_types {
1149 to.serialize_other(suggestions_types)?;
1150 }
1151
1152 Ok(())
1153 }
1154
1155 fn deserialize(has_suggestion_types: bool, data: &[u8]) -> DeserializeResult<Self> {
1156 let Deserialized { value: name, data } = String::mc_deserialize(data)?;
1157 let Deserialized { value: parser, data } = CommandParserSpec::mc_deserialize(data)?;
1158 let (suggestions_types, data) = if has_suggestion_types {
1159 let Deserialized { value: suggestions_types, data } = SuggestionsTypeSpec::mc_deserialize(data)?;
1160 (Some(suggestions_types), data)
1161 } else {
1162 (None, data)
1163 };
1164
1165 Deserialized::ok(Self {
1166 name,
1167 parser,
1168 suggestions_types,
1169 }, data)
1170 }
1171}
1172
1173#[cfg(all(test, feature = "std"))]
1174impl TestRandom for CommandArgumentNodeSpec {
1175 fn test_gen_random() -> Self {
1176 let name = String::test_gen_random();
1177 let suggestions_types = <Option<SuggestionsTypeSpec>>::test_gen_random();
1178 let parser = CommandParserSpec::test_gen_random();
1179
1180 Self {
1181 name,
1182 parser,
1183 suggestions_types,
1184 }
1185 }
1186}
1187
1188proto_str_enum!(SuggestionsTypeSpec,
1189 "minecraft:ask_server" :: AskServer,
1190 "minecraft:all_recipes" :: AllRecipes,
1191 "minecraft:available_sounds" :: AvailableSounds,
1192 "minecraft:summonable_entities" :: SummonableEntities,
1193 "minecraft:available_biomes" :: AvailableBiomes
1194);
1195
1196proto_struct!(CommandLiteralNodeSpec {
1197 name: String
1198});
1199
1200proto_str_enum!(CommandParserSpec,
1201 "brigadier:bool" :: Bool,
1202 "brigadier:double" :: Double(DoubleParserProps),
1203 "brigadier:float" :: Float(FloatParserProps),
1204 "brigadier:integer" :: Integer(IntegerParserProps),
1205 "brigadier:string" :: StringParser(StringParserMode),
1206 "minecraft:entity" :: Entity(EntityParserFlags),
1207 "minecraft:game_profile" :: GameProfile,
1208 "minecraft:block_pos" :: BlockPosition,
1209 "minecraft:column_pos" :: ColumnPosition,
1210 "minecraft:vec3" :: Vec3,
1211 "minecraft:vec2" :: Vec2,
1212 "minecraft:block_state" :: BlockState,
1213 "minecraft:block_predicate" :: BlockPredicate,
1214 "minecraft:item_stack" :: ItemStack,
1215 "minecraft:item_predicate" :: ItemPredicate,
1216 "minecraft:color" :: Color,
1217 "minecraft:component" :: Component,
1218 "minecraft:message" :: Message,
1219 "minecraft:nbt" :: Nbt,
1220 "minecraft:nbt_path" :: NbtPath,
1221 "minecraft:objective" :: Objective,
1222 "minecraft:objective_criteria" :: ObjectiveCriteria,
1223 "minecraft:operation" :: Operation,
1224 "minecraft:particle" :: Particle,
1225 "minecraft:rotation" :: Rotation,
1226 "minecraft:angle" :: Angle,
1227 "minecraft:scoreboard_slot" :: ScoreboardSlot,
1228 "minecraft:score_holder" :: ScoreHolder(ScoreHolderFlags),
1229 "minecraft:swizzle" :: Swizzle,
1230 "minecraft:team" :: Team,
1231 "minecraft:item_slot" :: ItemSlot,
1232 "minecraft:resource_location" :: ResourceLocation,
1233 "minecraft:mob_effect" :: MobEffect,
1234 "minecraft:function" :: Function,
1235 "minecraft:entity_anchor" :: EntityAnchor,
1236 "minecraft:range" :: Range(RangeParserProps),
1237 "minecraft:int_range" :: IntRange,
1238 "minecraft:float_range" :: FloatRange,
1239 "minecraft:item_enchantment" :: ItemEnchantment,
1240 "minecraft:entity_summon" :: EntitySummon,
1241 "minecraft:dimension" :: Dimension,
1242 "minecraft:uuid" :: UUID,
1243 "minecraft:nbt_tag" :: NbtTag,
1244 "minecraft:nbt_compound_tag" :: NbtCompoundTag,
1245 "minecraft:time" :: Time
1246);
1247
1248pub struct NumParserProps<T> {
1249 pub min: Option<T>,
1250 pub max: Option<T>,
1251}
1252
1253pub type DoubleParserProps = NumParserProps<f64>;
1254
1255pub type FloatParserProps = NumParserProps<f32>;
1256
1257pub type IntegerParserProps = NumParserProps<i32>;
1258
1259impl<T> Copy for NumParserProps<T> where T: Copy {}
1260
1261impl<T> Clone for NumParserProps<T> where T: Clone {
1262 fn clone(&self) -> Self {
1263 Self {
1264 min: self.min.clone(),
1265 max: self.max.clone(),
1266 }
1267 }
1268}
1269
1270impl<T> Debug for NumParserProps<T> where T: Debug {
1271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1272 write!(f, "NumParserProps(min={:?}, max={:?})", self.min, self.max)
1273 }
1274}
1275
1276impl<T> PartialEq for NumParserProps<T> where T: PartialEq {
1277 fn eq(&self, other: &Self) -> bool {
1278 other.max.eq(&self.max) && other.min.eq(&self.min)
1279 }
1280}
1281
1282impl<T> Serialize for NumParserProps<T> where T: Serialize {
1283 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1284 let mut flags: u8 = 0;
1285 if self.min.is_some() {
1286 flags |= 0x01;
1287 }
1288
1289 if self.max.is_some() {
1290 flags |= 0x02;
1291 }
1292
1293 to.serialize_other(&flags)?;
1294 if let Some(min) = &self.min {
1295 to.serialize_other(min)?;
1296 }
1297
1298 if let Some(max) = &self.max {
1299 to.serialize_other(max)?;
1300 }
1301
1302 Ok(())
1303 }
1304}
1305
1306impl<T> Deserialize for NumParserProps<T> where T: Deserialize {
1307 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1308 let Deserialized { value: flags, data } = u8::mc_deserialize(data)?;
1309 let (min, data) = if flags & 0x01 != 0 {
1310 let Deserialized { value: min, data } = T::mc_deserialize(data)?;
1311 (Some(min), data)
1312 } else {
1313 (None, data)
1314 };
1315
1316 let (max, data) = if flags & 0x02 != 0 {
1317 let Deserialized { value: max, data } = T::mc_deserialize(data)?;
1318 (Some(max), data)
1319 } else {
1320 (None, data)
1321 };
1322
1323 let out = Self {
1324 min,
1325 max,
1326 };
1327 Deserialized::ok(out, data)
1328 }
1329}
1330
1331#[cfg(all(test, feature = "std"))]
1332impl<T> TestRandom for NumParserProps<T> where
1333 T: TestRandom + std::cmp::PartialOrd,
1334 rand::distributions::Standard: rand::distributions::Distribution<T>,
1335{
1336 fn test_gen_random() -> Self {
1337 let has_min = rand::random::<bool>();
1338 let has_max = rand::random::<bool>();
1339 let (min, max) = if has_min && has_max {
1340 let a = rand::random::<T>();
1341 let b = rand::random::<T>();
1342 if a < b {
1343 (Some(a), Some(b))
1344 } else {
1345 (Some(b), Some(a))
1346 }
1347 } else if !has_min && !has_max {
1348 (None, None)
1349 } else {
1350 let v = rand::random::<T>();
1351 if has_min {
1352 (Some(v), None)
1353 } else {
1354 (None, Some(v))
1355 }
1356 };
1357
1358 Self {
1359 min,
1360 max,
1361 }
1362 }
1363}
1364
1365proto_varint_enum!(StringParserMode,
1366 0x00 :: SingleWord,
1367 0x01 :: QuotablePharse,
1368 0x02 :: GreedyPhrase
1369);
1370
1371proto_byte_flag!(EntityParserFlags,
1372 0x01 :: is_single_target set_single_target,
1373 0x02 :: is_players_only set_players_only
1374);
1375
1376proto_byte_flag!(ScoreHolderFlags,
1377 0x01 :: is_multiple set_multiple
1378);
1379
1380proto_struct!(RangeParserProps {
1381 decimal: bool
1382});
1383
1384proto_byte_enum!(TeamAction,
1385 0x00 :: Create(TeamActionCreateSpec),
1386 0x01 :: Remove,
1387 0x02 :: UpdateInfo(TeamActionUpdateInfoSpec),
1388 0x03 :: AddPlayers(TeamActionPlayerList),
1389 0x04 :: RemovePlayers(TeamActionPlayerList)
1390);
1391
1392#[derive(Clone, Debug, PartialEq)]
1393pub enum TeamMember {
1394 Player(String),
1395 Entity(UUID4),
1396}
1397
1398impl Serialize for TeamMember {
1399 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1400 use TeamMember::*;
1401 match self {
1402 Player(username) => username.mc_serialize(to),
1403 Entity(entity_id) => entity_id.to_string().mc_serialize(to),
1404 }
1405 }
1406}
1407
1408impl Deserialize for TeamMember {
1409 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1410 use TeamMember::*;
1411
1412 Ok(String::mc_deserialize(data)?.map(move |raw| {
1413 if let Some(entity_id) = UUID4::parse(raw.as_str()) {
1414 Entity(entity_id)
1415 } else {
1416 Player(raw)
1417 }
1418 }))
1419 }
1420}
1421
1422#[cfg(all(test, feature = "std"))]
1423impl TestRandom for TeamMember {
1424 fn test_gen_random() -> Self {
1425 use TeamMember::*;
1426
1427 let rand_bool: bool = rand::random();
1428 if rand_bool {
1429 Player(String::test_gen_random())
1430 } else {
1431 Entity(UUID4::random())
1432 }
1433 }
1434}
1435
1436proto_str_enum!(TeamTagNameVisibility,
1437 "always" :: Always,
1438 "hideForOtherTeams" :: HideForOtherTeams,
1439 "hideForOwnTeam" :: HideForOwnTeam,
1440 "never" :: Never
1441);
1442
1443proto_str_enum!(TeamCollisionRule,
1444 "always" :: Always,
1445 "pushForOtherTeams" :: PushForOtherTeams,
1446 "pushOwnTeam" :: PushOwnTeam,
1447 "never" :: Never
1448);
1449
1450proto_struct!(TeamActionPlayerList {
1451 entities: CountedArray<TeamMember, VarInt>
1452});
1453
1454proto_struct!(TeamActionCreateSpec {
1455 display_name: Chat,
1456 friendly_flags: TeamFriendlyFlags,
1457 tag_name_visibility: TeamTagNameVisibility,
1458 collision_rule: TeamCollisionRule,
1459 color: VarInt,
1460 prefix: Chat,
1461 suffix: Chat,
1462 entities: CountedArray<TeamMember, VarInt>
1463});
1464
1465proto_struct!(TeamActionUpdateInfoSpec {
1466 display_name: Chat,
1467 friendly_flags: TeamFriendlyFlags,
1468 tag_name_visibility: TeamTagNameVisibility,
1469 collision_rule: TeamCollisionRule,
1470 color: VarInt,
1471 prefix: Chat,
1472 suffix: Chat
1473});
1474
1475proto_byte_flag!(TeamFriendlyFlags,
1476 0x01 :: allow_friendly_fire set_friendly_fire,
1477 0x02 :: show_invisible_teammates set_show_invisible_teammates
1478);
1479
1480proto_byte_enum!(UpdateScoreAction,
1481 0x00 :: Upsert(VarInt),
1482 0x01 :: Remove
1483);
1484
1485#[derive(Clone, Debug, PartialEq)]
1486pub struct UpdateScoreSpec {
1487 pub objective_name: String,
1488 pub action: UpdateScoreAction,
1489}
1490
1491impl Serialize for UpdateScoreSpec {
1492 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1493 to.serialize_byte(self.action.id())?;
1494 to.serialize_other(&self.objective_name)?;
1495 self.action.serialize_body(to)?;
1496
1497 Ok(())
1498 }
1499}
1500
1501impl Deserialize for UpdateScoreSpec {
1502 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1503 let Deserialized { value: action_id, data } = u8::mc_deserialize(data)?;
1504 let Deserialized { value: objective_name, data } = String::mc_deserialize(data)?;
1505
1506 Ok(UpdateScoreAction::deserialize_with_id(action_id, data)?.map(move |action| {
1507 Self {
1508 objective_name,
1509 action,
1510 }
1511 }))
1512 }
1513}
1514
1515#[cfg(all(test, feature = "std"))]
1516impl TestRandom for UpdateScoreSpec {
1517 fn test_gen_random() -> Self {
1518 Self {
1519 objective_name: String::test_gen_random(),
1520 action: UpdateScoreAction::test_gen_random(),
1521 }
1522 }
1523}
1524
1525proto_varint_enum!(TitleActionSpec,
1526 0x00 :: SetTitle(Chat),
1527 0x01 :: SetSubtitle(Chat),
1528 0x02 :: SetActionBar(Chat),
1529 0x03 :: SetTimesAndDisplay(TitleTimesSpec),
1530 0x04 :: Hide,
1531 0x05 :: Reset
1532);
1533
1534proto_struct!(TitleTimesSpec {
1535 fade_in: i32,
1536 stay: i32,
1537 fade_out: i32
1538});
1539
1540proto_varint_enum!(SoundCategory,
1541 0x00 :: Master,
1542 0x01 :: Music,
1543 0x02 :: Records,
1544 0x03 :: Weather,
1545 0x04 :: Block,
1546 0x05 :: Hostile,
1547 0x06 :: Neutral,
1548 0x07 :: Player,
1549 0x08 :: Ambient,
1550 0x09 :: Voice
1551);
1552
1553#[derive(Clone, Debug, PartialEq)]
1554pub struct StopSoundSpec {
1555 pub source: Option<SoundCategory>,
1556 pub sound: Option<String>,
1557}
1558
1559impl Serialize for StopSoundSpec {
1560 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1561 let has_sound = self.sound.is_some();
1562 let has_source = self.source.is_some();
1563 let mut flags = 0;
1564 if has_sound {
1565 flags |= 0x02;
1566 }
1567 if has_source {
1568 flags |= 0x01;
1569 }
1570
1571 to.serialize_byte(flags)?;
1572 if let Some(source) = &self.source {
1573 to.serialize_other(source)?;
1574 }
1575
1576 if let Some(sound) = &self.sound {
1577 to.serialize_other(sound)?;
1578 }
1579
1580 Ok(())
1581 }
1582}
1583
1584impl Deserialize for StopSoundSpec {
1585 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1586 let Deserialized { value: flags, data } = u8::mc_deserialize(data)?;
1587
1588 let is_source_present = flags & 0x01 != 0;
1589 let is_sound_present = flags & 0x02 != 0;
1590
1591 let (source, data) = if is_source_present {
1592 let Deserialized { value: source, data } = SoundCategory::mc_deserialize(data)?;
1593 (Some(source), data)
1594 } else {
1595 (None, data)
1596 };
1597
1598 let (sound, data) = if is_sound_present {
1599 let Deserialized { value: sound, data } = String::mc_deserialize(data)?;
1600 (Some(sound), data)
1601 } else {
1602 (None, data)
1603 };
1604
1605 Deserialized::ok(Self {
1606 source,
1607 sound,
1608 }, data)
1609 }
1610}
1611
1612#[cfg(all(test, feature = "std"))]
1613impl TestRandom for StopSoundSpec {
1614 fn test_gen_random() -> Self {
1615 let source = if rand::random::<bool>() {
1616 Some(SoundCategory::test_gen_random())
1617 } else {
1618 None
1619 };
1620
1621 let sound = if source.is_none() || rand::random::<bool>() {
1622 Some(String::test_gen_random())
1623 } else {
1624 None
1625 };
1626
1627 Self {
1628 source,
1629 sound,
1630 }
1631 }
1632}
1633
1634proto_byte_enum!(GameMode,
1635 0x00 :: Survival,
1636 0x01 :: Creative,
1637 0x02 :: Adventure,
1638 0x03 :: Spectator
1639);
1640
1641#[derive(Clone, Debug, PartialEq)]
1642pub enum PreviousGameMode {
1643 NoPrevious,
1644 Previous(GameMode)
1645}
1646
1647impl PreviousGameMode {
1648 pub fn id(&self) -> i8 {
1649 use PreviousGameMode::*;
1650 match self {
1651 NoPrevious => -1,
1652 Previous(mode) => mode.id() as i8,
1653 }
1654 }
1655}
1656
1657impl Serialize for PreviousGameMode {
1658 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1659 to.serialize_byte(self.id() as u8)
1660 }
1661}
1662
1663impl Deserialize for PreviousGameMode {
1664 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1665 let Deserialized{ value: id, data } = i8::mc_deserialize(data)?;
1666
1667 use PreviousGameMode::*;
1668 match id {
1669 -1 => Deserialized::ok(NoPrevious, data),
1670 other => Ok(GameMode::deserialize_with_id(other as u8, data)?.map(move |gm| Previous(gm)))
1671 }
1672 }
1673}
1674
1675impl Into<Option<GameMode>> for PreviousGameMode {
1676 fn into(self) -> Option<GameMode> {
1677 use PreviousGameMode::*;
1678 match self {
1679 NoPrevious => None,
1680 Previous(mode) => Some(mode),
1681 }
1682 }
1683}
1684
1685#[cfg(all(test, feature = "std"))]
1686impl TestRandom for PreviousGameMode {
1687 fn test_gen_random() -> Self {
1688 use PreviousGameMode::*;
1689 match <Option<GameMode> as TestRandom>::test_gen_random() {
1690 Some(gamemode) => Previous(gamemode),
1691 None => NoPrevious
1692 }
1693 }
1694}
1695
1696proto_byte_enum!(WinGameAction,
1697 0x00 :: Respawn,
1698 0x01 :: RollCreditsAndRespawn
1699);
1700
1701proto_byte_enum!(DemoEvent,
1702 0x00 :: ShowWelcomeScreen,
1703 0x65 :: TellMovementControls,
1704 0x66 :: TellJumpControl,
1705 0x67 :: TellInventoryControl,
1706 0x68 :: EndDemo
1707);
1708
1709proto_byte_enum!(RespawnRequestType,
1710 0x00 :: Screen,
1711 0x01 :: Immediate
1712);
1713
1714#[derive(Clone, Debug, PartialEq)]
1715pub enum GameChangeReason {
1716 NoRespawnAvailable,
1717 EndRaining,
1718 BeginRaining,
1719 ChangeGameMode(GameMode),
1720 WinGame(WinGameAction),
1721 Demo(DemoEvent),
1722 ArrowHitPlayer,
1723 RainLevelChange(f32),
1724 ThunderLevelChange(f32),
1725 PufferfishSting,
1726 ElderGuardianMobAppearance,
1727 Respawn(RespawnRequestType),
1728}
1729
1730impl Serialize for GameChangeReason {
1731 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1732 use GameChangeReason::*;
1733 to.serialize_byte(match self {
1734 NoRespawnAvailable => 0x00,
1735 EndRaining => 0x01,
1736 BeginRaining => 0x02,
1737 ChangeGameMode(_) => 0x03,
1738 WinGame(_) => 0x04,
1739 Demo(_) => 0x05,
1740 ArrowHitPlayer => 0x06,
1741 RainLevelChange(_) => 0x07,
1742 ThunderLevelChange(_) => 0x08,
1743 PufferfishSting => 0x09,
1744 ElderGuardianMobAppearance => 0x0A,
1745 Respawn(_) => 0x0B,
1746 })?;
1747
1748 let value = match self {
1749 ChangeGameMode(body) => body.id() as f32,
1750 WinGame(body) => body.id() as f32,
1751 Demo(body) => body.id() as f32,
1752 RainLevelChange(body) => *body,
1753 ThunderLevelChange(body) => *body,
1754 Respawn(body) => body.id() as f32,
1755 _ => 0 as f32,
1756 };
1757 to.serialize_other(&value)
1758 }
1759}
1760
1761impl Deserialize for GameChangeReason {
1762 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1763 let Deserialized {
1764 value: reason_id,
1765 data,
1766 } = u8::mc_deserialize(data)?;
1767 let Deserialized { value, data } = f32::mc_deserialize(data)?;
1768 use GameChangeReason::*;
1769 match reason_id {
1770 0x00 => Deserialized::ok(NoRespawnAvailable, data),
1771 0x01 => Deserialized::ok(EndRaining, data),
1772 0x02 => Deserialized::ok(BeginRaining, data),
1773 0x03 => Ok(GameMode::deserialize_with_id(value as u8, data)?.map(move |mode| ChangeGameMode(mode))),
1774 0x04 => Ok(WinGameAction::deserialize_with_id(value as u8, data)?.map(move |mode| WinGame(mode))),
1775 0x05 => Ok(DemoEvent::deserialize_with_id(value as u8, data)?.map(move |mode| Demo(mode))),
1776 0x06 => Deserialized::ok(ArrowHitPlayer, data),
1777 0x07 => Deserialized::ok(RainLevelChange(value), data),
1778 0x08 => Deserialized::ok(ThunderLevelChange(value), data),
1779 0x09 => Deserialized::ok(PufferfishSting, data),
1780 0x0A => Deserialized::ok(ElderGuardianMobAppearance, data),
1781 0x0B => Ok(RespawnRequestType::deserialize_with_id(value as u8, data)?.map(move |mode| Respawn(mode))),
1782 other => Err(DeserializeErr::CannotUnderstandValue(alloc::format!(
1783 "invalid game change reason id {}",
1784 other
1785 ))),
1786 }
1787 }
1788}
1789
1790#[cfg(all(test, feature = "std"))]
1791impl TestRandom for GameChangeReason {
1792 fn test_gen_random() -> Self {
1793 GameChangeReason::PufferfishSting
1795 }
1796}
1797
1798proto_varint_enum!(MapIconType,
1799 0x00 :: WhiteArrow,
1800 0x01 :: GreenArrow,
1801 0x02 :: RedArrow,
1802 0x03 :: BlueArrow,
1803 0x04 :: WhiteCross,
1804 0x05 :: RedPointer,
1805 0x06 :: WhiteCircle,
1806 0x07 :: SmallWhiteCircle,
1807 0x08 :: Mansion,
1808 0x09 :: Temple,
1809 0x0A :: WhiteBanner,
1810 0x0B :: OrangeBanner,
1811 0x0C :: MagentaBanner,
1812 0x0D :: YellowBanner,
1813 0x0E :: LimeBanner,
1814 0x0F :: PinkBanner,
1815 0x10 :: GrayBanner,
1816 0x11 :: LightGrayBanner,
1817 0x12 :: CyanBanner,
1818 0x13 :: PurpleBanner,
1819 0x14 :: BlueBanner,
1820 0x15 :: BrownBanner,
1821 0x16 :: GreenBanner,
1822 0x17 :: RedBanner,
1823 0x18 :: BlackBanner,
1824 0x19 :: TreasureMarker
1825);
1826
1827proto_struct!(MapIconSpec {
1828 kind: MapIconType,
1829 position: TopDownPosition<i8>,
1830 direction: i8,
1831 display_name: Option<Chat>
1832});
1833
1834#[derive(Clone, PartialEq, Debug)]
1835pub enum MapColumns {
1836 NoUpdates,
1837 Updated(MapColumnsSpec),
1838}
1839
1840proto_struct!(MapColumnsSpec {
1841 columns: u8,
1842 rows: u8,
1843 position: TopDownPosition<u8>,
1844 data: CountedArray<u8, VarInt>
1845});
1846
1847impl Serialize for MapColumns {
1848 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
1849 use MapColumns::*;
1850 match self {
1851 NoUpdates => to.serialize_other(&0u8),
1852 Updated(body) => to.serialize_other(body),
1853 }
1854 }
1855}
1856
1857impl Deserialize for MapColumns {
1858 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
1859 let Deserialized { value: columns, data: rest } = u8::mc_deserialize(data)?;
1860 use MapColumns::*;
1861 match columns {
1862 0x00 => Deserialized::ok(NoUpdates, rest),
1863 _ => Ok(MapColumnsSpec::mc_deserialize(data)?.map(move |v| Updated(v))),
1864 }
1865 }
1866}
1867
1868impl Into<Option<MapColumnsSpec>> for MapColumns {
1869 fn into(self) -> Option<MapColumnsSpec> {
1870 use MapColumns::*;
1871 match self {
1872 NoUpdates => None,
1873 Updated(body) => Some(body),
1874 }
1875 }
1876}
1877
1878impl From<Option<MapColumnsSpec>> for MapColumns {
1879 fn from(other: Option<MapColumnsSpec>) -> Self {
1880 use MapColumns::*;
1881 match other {
1882 Some(body) => {
1883 if body.columns == 0 {
1884 NoUpdates
1885 } else {
1886 Updated(body)
1887 }
1888 }
1889 None => NoUpdates,
1890 }
1891 }
1892}
1893
1894#[cfg(all(test, feature = "std"))]
1895impl TestRandom for MapColumns {
1896 fn test_gen_random() -> Self {
1897 <Option<MapColumnsSpec>>::test_gen_random().into()
1898 }
1899}
1900
1901proto_struct!(TradeSpec {
1902 input_item_1: Slot,
1903 output_item: Slot,
1904 input_item_2: Slot,
1905 trade_disabled: bool,
1906 trade_uses: i32,
1907 max_trade_uses: i32,
1908 xp: i32,
1909 special_price: i32,
1910 price_multiplier: f32,
1911 demand: i32
1912});
1913
1914proto_varint_enum!(Hand,
1915 0x00 :: MainHand,
1916 0x01 :: OffHand
1917);
1918
1919proto_varint_enum!(WindowType,
1920 0x00 :: GenericOneRow,
1921 0x01 :: GenericTwoRow,
1922 0x02 :: GenericThreeRow,
1923 0x03 :: GenericFourRow,
1924 0x04 :: GenericFiveRow,
1925 0x05 :: GenericSixRow,
1926 0x06 :: GenericSquare,
1927 0x07 :: Anvil,
1928 0x08 :: Beacon,
1929 0x09 :: BlastFurnace,
1930 0x0A :: BrewingStand,
1931 0x0B :: CraftingTable,
1932 0x0C :: EnchantmentTable,
1933 0x0D :: Furnace,
1934 0x0E :: Grindstone,
1935 0x0F :: Hopper,
1936 0x10 :: Lectern,
1937 0x11 :: Loom,
1938 0x12 :: Merchant,
1939 0x13 :: ShulkerBox,
1940 0x14 :: Smoker,
1941 0x15 :: Cartography,
1942 0x16 :: StoneCutter
1943);
1944
1945proto_byte_flag!(PlayerAbilityFlags,
1946 0x01 :: is_invulnerable set_invulnerable,
1947 0x02 :: is_flying set_flying,
1948 0x04 :: is_flight_allowed set_flight_allowed,
1949 0x08 :: is_instant_break set_instant_break
1950);
1951
1952proto_varint_enum!(CombatEvent,
1953 0x00 :: Enter,
1954 0x01 :: End(CombatEndSpec),
1955 0x02 :: EntityDead(CombatEntityDeadSpec)
1956);
1957
1958proto_struct!(CombatEndSpec {
1959 duration_ticks: VarInt,
1960 entity_id: i32
1961});
1962
1963proto_struct!(CombatEntityDeadSpec {
1964 player_id: VarInt,
1965 entity_id: i32,
1966 message: Chat
1967});
1968
1969proto_struct!(PlayerInfoAction<A> {
1970 uuid: UUID4,
1971 action: A
1972});
1973
1974proto_varint_enum!(PlayerInfoActionList,
1975 0x00 :: Add(CountedArray<PlayerInfoAction<PlayerAddActionSpec>, VarInt>),
1976 0x01 :: UpdateGameMode(CountedArray<PlayerInfoAction<GameMode>, VarInt>),
1977 0x02 :: UpdateLatency(CountedArray<PlayerInfoAction<VarInt>, VarInt>),
1978 0x03 :: UpdateDisplayName(CountedArray<PlayerInfoAction<Option<Chat>>, VarInt>),
1979 0x04 :: Remove(CountedArray<UUID4, VarInt>)
1980);
1981
1982proto_struct!(PlayerAddActionSpec {
1983 name: String,
1984 properties: CountedArray<PlayerAddProperty, VarInt>,
1985 game_mode: GameMode,
1986 ping_ms: VarInt,
1987 display_name: Option<Chat>
1988});
1989
1990proto_struct!(PlayerAddProperty {
1991 name: String,
1992 value: String,
1993 signature: Option<String>
1994});
1995
1996proto_varint_enum!(FacePlayerKind,
1997 0x00 :: Feet,
1998 0x01 :: Eyes
1999);
2000
2001proto_struct!(FacePlayerEntityTarget {
2002 entity_id: VarInt,
2003 kind: FacePlayerKind
2004});
2005
2006proto_byte_flag!(PositionAndLookFlags,
2007 0x01 :: is_x_rel set_x_rel,
2008 0x02 :: is_y_rel set_y_rel,
2009 0x04 :: is_z_rel set_z_rel,
2010 0x08 :: is_y_rotation_rel set_y_rotation_rel,
2011 0x10 :: is_x_rotation_rel set_x_rotation_rel
2012);
2013
2014proto_byte_enum!(EntityEffectKind,
2015 0x01 :: Speed,
2016 0x02 :: Slowness,
2017 0x03 :: Haste,
2018 0x04 :: MiningFatigue,
2019 0x05 :: Strength,
2020 0x06 :: InstantHealth,
2021 0x07 :: InstantDamage,
2022 0x08 :: JumpBoost,
2023 0x09 :: Nausea,
2024 0x0A :: Regeneration,
2025 0x0B :: Resistance,
2026 0x0C :: FireResistance,
2027 0x0D :: WaterBreathing,
2028 0x0E :: Invisibility,
2029 0x0F :: Blindness,
2030 0x10 :: NightVision,
2031 0x11 :: Hunger,
2032 0x12 :: Weakness,
2033 0x13 :: Poison,
2034 0x14 :: Wither,
2035 0x15 :: HealthBoost,
2036 0x16 :: Absorption,
2037 0x17 :: Saturation,
2038 0x18 :: Glowing,
2039 0x19 :: Levetation,
2040 0x1A :: Luck,
2041 0x1B :: Unluck,
2042 0x1C :: SlowFalling,
2043 0x1D :: ConduitPower,
2044 0x1E :: DolphinsGrace,
2045 0x1F :: BadOmen,
2046 0x20 :: HeroOfTheVillage
2047);
2048
2049proto_varint_enum!(WorldBorderAction,
2050 0x00 :: SetSize(WorldBorderSetSizeSpec),
2051 0x01 :: LerpSize(WorldBorderLerpSizeSpec),
2052 0x02 :: SetCenter(TopDownPosition<f64>),
2053 0x03 :: Initialize(WorldBorderInitiaializeSpec),
2054 0x04 :: SetWarningTime(WorldBorderWarningTimeSpec),
2055 0x05 :: SetWarningBlocks(WorldBorderWarningBlocksSpec)
2056);
2057
2058proto_struct!(WorldBorderSetSizeSpec {
2059 diameter: f64
2060});
2061
2062proto_struct!(WorldBorderLerpSizeSpec {
2063 old_diameter: f64,
2064 new_diameter: f64,
2065 speed: VarLong
2066});
2067
2068proto_struct!(WorldBorderInitiaializeSpec {
2069 position: TopDownPosition<f64>,
2070 old_diameter: f64,
2071 new_diameter: f64,
2072 speed: VarLong,
2073 portal_teleport_boundary: VarLong,
2074 warning_time: VarInt,
2075 warning_blocks: VarInt
2076});
2077
2078proto_struct!(WorldBorderWarningTimeSpec {
2079 warning_time: VarInt
2080});
2081
2082proto_struct!(WorldBorderWarningBlocksSpec {
2083 warning_blocks: VarInt
2084});
2085
2086proto_byte_enum!(ScoreboardPosition,
2087 0x00 :: List,
2088 0x01 :: Sidebar,
2089 0x02 :: BelowName,
2090 0x03 :: TeamSpecific(i8)
2091);
2092
2093#[derive(Clone, Debug, PartialEq)]
2094pub struct EntityEquipmentEntry {
2095 pub slot: EquipmentSlot,
2096 pub item: Slot
2097}
2098
2099#[derive(Clone, Debug, PartialEq)]
2100pub struct EntityEquipmentArray {
2101 data: Vec<EntityEquipmentEntry>
2102}
2103
2104impl Serialize for EntityEquipmentArray {
2105 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2106 if self.data.is_empty() {
2107 return Err(SerializeErr::CannotSerialize("entity equipment must be non-empty to send!".to_owned()));
2108 }
2109
2110 let n = self.data.len();
2111
2112 for i in 0..n {
2113 let is_last = i == n - 1;
2114 let entry = self.data.get(i).expect("iter in bounds");
2115 let mut slot_raw = entry.slot.id();
2116 if !is_last {
2117 slot_raw |= 0x80;
2118 }
2119 to.serialize_byte(slot_raw)?;
2120 to.serialize_other(&entry.item)?;
2121 }
2122
2123 Ok(())
2124 }
2125}
2126
2127impl Deserialize for EntityEquipmentArray {
2128 fn mc_deserialize(mut data: &[u8]) -> DeserializeResult<'_, Self> {
2129 if data.is_empty() {
2130 return DeserializeErr::Eof.into();
2131 }
2132
2133 let mut out = Vec::new();
2134 let mut has_next = true;
2135 while has_next {
2136 let Deserialized { value: raw_slot_id, data: rest } = u8::mc_deserialize(data)?;
2137 has_next = raw_slot_id & 0x80 != 0;
2138 let slot_id = raw_slot_id & 0x7F;
2139 let Deserialized { value: slot, data: rest } = EquipmentSlot::deserialize_with_id(slot_id, rest)?;
2140 let Deserialized { value: item, data: rest } = Slot::mc_deserialize(rest)?;
2141 out.push(EntityEquipmentEntry { slot, item });
2142 data = rest;
2143 }
2144
2145 Deserialized::ok(Self { data: out }, data)
2146 }
2147}
2148
2149impl core::ops::Deref for EntityEquipmentArray {
2150 type Target = Vec<EntityEquipmentEntry>;
2151
2152 fn deref(&self) -> &Self::Target {
2153 &self.data
2154 }
2155}
2156
2157impl core::ops::DerefMut for EntityEquipmentArray {
2158 fn deref_mut(&mut self) -> &mut Self::Target {
2159 &mut self.data
2160 }
2161}
2162
2163impl From<Vec<EntityEquipmentEntry>> for EntityEquipmentArray {
2164 fn from(data: Vec<EntityEquipmentEntry>) -> Self {
2165 Self { data }
2166 }
2167}
2168
2169impl From<EntityEquipmentArray> for Vec<EntityEquipmentEntry> {
2170 fn from(other: EntityEquipmentArray) -> Self {
2171 other.data
2172 }
2173}
2174
2175#[cfg(all(test, feature = "std"))]
2176impl TestRandom for EntityEquipmentArray {
2177 fn test_gen_random() -> Self {
2178 let mut out = Vec::new();
2179
2180 for slot in &[
2181 EquipmentSlot::MainHand,
2182 EquipmentSlot::OffHand,
2183 EquipmentSlot::ArmorBoots,
2184 EquipmentSlot::ArmorLeggings,
2185 EquipmentSlot::ArmorChestplate,
2186 EquipmentSlot::ArmorHelmet,
2187 ] {
2188 out.push(EntityEquipmentEntry{
2189 slot: slot.clone(),
2190 item: Slot::test_gen_random()
2191 });
2192 }
2193
2194 out.into()
2195 }
2196}
2197
2198proto_byte_enum!(EquipmentSlot,
2199 0x00 :: MainHand,
2200 0x01 :: OffHand,
2201 0x02 :: ArmorBoots,
2202 0x03 :: ArmorLeggings,
2203 0x04 :: ArmorChestplate,
2204 0x05 :: ArmorHelmet
2205);
2206
2207proto_byte_enum!(ScoreboardObjectiveAction,
2208 0x00 :: Create(ScoreboardObjectiveSpec),
2209 0x01 :: Remove,
2210 0x02 :: UpdateText(ScoreboardObjectiveSpec)
2211);
2212
2213proto_varint_enum!(ScoreboardObjectiveKind,
2214 0x00 :: Integer,
2215 0x01 :: Hearts
2216);
2217
2218proto_struct!(ScoreboardObjectiveSpec {
2219 text: Chat,
2220 kind: ScoreboardObjectiveKind
2221});
2222
2223proto_struct!(AdvancementMappingEntrySpec {
2224 key: String,
2225 value: AdvancementSpec
2226});
2227
2228proto_struct!(AdvancementSpec {
2229 parent: Option<String>,
2230 display: Option<AdvancementDisplaySpec>,
2231 criteria: CountedArray<String, VarInt>,
2232 requirements: CountedArray<CountedArray<String, VarInt>, VarInt>
2233});
2234
2235proto_struct!(AdvancementDisplaySpec {
2236 title: Chat,
2237 description: Chat,
2238 icon: Slot,
2239 frame_type: AdvancementFrameType,
2240 flags: AdvancementDisplayFlags,
2241 position: Vec2<f32>
2242});
2243
2244#[derive(Clone, Debug, PartialEq)]
2245pub struct AdvancementDisplayFlags {
2246 pub background_texture: Option<String>,
2247 pub show_toast: bool,
2248 pub hidden: bool,
2249}
2250
2251impl Serialize for AdvancementDisplayFlags {
2252 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2253 let mut raw_flags: i32 = 0;
2254 if self.background_texture.is_some() {
2255 raw_flags |= 0x01;
2256 }
2257 if self.show_toast {
2258 raw_flags |= 0x02;
2259 }
2260 if self.hidden {
2261 raw_flags |= 0x04;
2262 }
2263
2264 to.serialize_other(&raw_flags)?;
2265 if let Some(texture) = &self.background_texture {
2266 to.serialize_other(texture)?;
2267 }
2268
2269 Ok(())
2270 }
2271}
2272
2273impl Deserialize for AdvancementDisplayFlags {
2274 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
2275 let Deserialized { value: raw_flags, data } = i32::mc_deserialize(data)?;
2276 let has_background_texture = raw_flags & 0x01 != 0;
2277 let show_toast = raw_flags & 0x02 != 0;
2278 let hidden = raw_flags & 0x04 != 0;
2279
2280 Ok(if has_background_texture {
2281 String::mc_deserialize(data)?.map(move |id| Some(id))
2282 } else {
2283 Deserialized { value: None, data }
2284 }.map(move |background_texture| {
2285 Self {
2286 background_texture,
2287 show_toast,
2288 hidden,
2289 }
2290 }))
2291 }
2292}
2293
2294#[cfg(all(test, feature = "std"))]
2295impl TestRandom for AdvancementDisplayFlags {
2296 fn test_gen_random() -> Self {
2297 let background_texture = if rand::random::<bool>() {
2298 Some(String::test_gen_random())
2299 } else {
2300 None
2301 };
2302 let show_toast = rand::random::<bool>();
2303 let hidden = rand::random::<bool>();
2304
2305 Self {
2306 background_texture,
2307 show_toast,
2308 hidden,
2309 }
2310 }
2311}
2312
2313proto_varint_enum!(AdvancementFrameType,
2314 0x00 :: Task,
2315 0x01 :: Challenge,
2316 0x02 :: Goal
2317);
2318
2319proto_struct!(AdvancementProgressEntrySpec {
2320 key: String,
2321 value: AdvancementProgressSpec
2322});
2323
2324proto_struct!(AdvancementProgressSpec {
2325 criteria: CountedArray<AdvancementCriteriaSpec, VarInt>
2326});
2327
2328proto_struct!(AdvancementCriteriaSpec {
2329 identifier: String,
2330 progress: AdvancementCriterionProgressSpec
2331});
2332
2333proto_struct!(AdvancementCriterionProgressSpec {
2334 achieved_at: Option<i64>
2335});
2336
2337proto_struct!(EntityPropertySpec {
2338 key: String,
2339 value: f64,
2340 modifiers: CountedArray<EntityPropertyModifierSpec, VarInt>
2341});
2342
2343proto_struct!(EntityPropertyModifierSpec {
2344 uuid: UUID4,
2345 amount: f64,
2346 operation: EntityPropertyModifierOperation
2347});
2348
2349proto_byte_enum!(EntityPropertyModifierOperation,
2350 0x00 :: AddSubtractAmount,
2351 0x01 :: AddSubtractAmountPercentOfCurrent,
2352 0x02 :: MultiplyByAmountPercent
2353);
2354
2355proto_byte_flag!(EntityEffectFlags,
2356 0x01 :: is_ambient set_ambient,
2357 0x02 :: is_show_particles set_show_particles,
2358 0x04 :: is_show_icon set_show_icon
2359);
2360
2361proto_struct!(TagSpec {
2362 name: String,
2363 entries: CountedArray<VarInt, VarInt>
2364});
2365
2366proto_varint_enum!(ClientStatusAction,
2367 0x00 :: PerformRespawn,
2368 0x01 :: RequestStats
2369);
2370
2371proto_varint_enum!(ClientChatMode,
2372 0x00 :: Enabled,
2373 0x01 :: CommandsOnly,
2374 0x02 :: Hidden
2375);
2376
2377proto_varint_enum!(ClientMainHand,
2378 0x00 :: Left,
2379 0x01 :: Right
2380);
2381
2382proto_byte_flag!(ClientDisplayedSkinParts,
2383 0x01 :: is_cape_enabled set_cape_enabled,
2384 0x02 :: is_jacket_enabled set_jacket_enabled,
2385 0x04 :: is_left_sleeve_enabled set_left_sleeve_enabled,
2386 0x08 :: is_right_sleeve_enabled set_right_sleeve_enabled,
2387 0x10 :: is_left_pants_leg_enabled set_left_pants_leg_enabled,
2388 0x20 :: is_right_pant_legs_enabled set_right_pant_legs_enabled,
2389 0x40 :: is_hat_enabled set_hat_enabled
2390);
2391
2392proto_varint_enum!(InventoryOperationMode,
2393 0x00 :: MouseClick,
2394 0x01 :: ShiftClick,
2395 0x02 :: NumberClick,
2396 0x03 :: MiddleClick,
2397 0x04 :: DropClick,
2398 0x05 :: Drag,
2399 0x06 :: DoubleClick
2400);
2401
2402proto_struct!(InteractAtSpec {
2403 target_position: Vec3<f32>,
2404 hand: Hand
2405});
2406
2407proto_varint_enum!(InteractKind,
2408 0x00 :: Interact(Hand),
2409 0x01 :: Attack,
2410 0x02 :: InteractAt(InteractAtSpec)
2411);
2412
2413proto_byte_flag!(ClientPlayerAbilities,
2414 0x01 :: is_creative set_creative,
2415 0x02 :: is_flying set_flying,
2416 0x04 :: is_fly_enabled set_fly_enabled,
2417 0x08 :: is_damaged_disabled set_damaged_disabled
2418);
2419
2420proto_varint_enum!(PlayerDiggingStatus,
2421 0x00 :: Started,
2422 0x01 :: Cancelled,
2423 0x02 :: Finished,
2424 0x03 :: DropStack,
2425 0x04 :: DropItem,
2426 0x05 :: ShootArrowOrFishEating,
2427 0x06 :: SwapItemInHand
2428);
2429
2430proto_byte_enum!(DiggingFace,
2431 0x00 :: Bottom,
2432 0x01 :: Top,
2433 0x02 :: North,
2434 0x03 :: South,
2435 0x04 :: West,
2436 0x05 :: East
2437);
2438
2439proto_varint_enum!(EntityActionKind,
2440 0x00 :: StartSneaking,
2441 0x01 :: StopSneaking,
2442 0x02 :: LeaveBed,
2443 0x03 :: StartSprinting,
2444 0x04 :: StopSprinting,
2445 0x05 :: StartJumpWithHorse,
2446 0x06 :: StopJumpWithHorse,
2447 0x07 :: OpenHorseInventory,
2448 0x08 :: StartFlyingWithElytra
2449);
2450
2451proto_byte_flag!(SteerVehicleFlags,
2452 0x01 :: is_jump set_jump,
2453 0x02 :: is_unmount set_unmount
2454);
2455
2456proto_varint_enum!(RecipeBookType,
2457 0x00 :: Crafting,
2458 0x01 :: Furnace,
2459 0x02 :: BlastFurnace,
2460 0x03 :: Smoker
2461);
2462
2463proto_varint_enum!(ResourcePackStatus,
2464 0x00 :: Loaded,
2465 0x01 :: Declined,
2466 0x02 :: FailedDownload,
2467 0x03 :: Accepted
2468);
2469
2470proto_varint_enum!(AdvancementTabAction,
2471 0x00 :: Opened(String),
2472 0x01 :: Closed
2473);
2474
2475proto_varint_enum!(CommandBlockMode,
2476 0x00 :: Sequence,
2477 0x01 :: Auto,
2478 0x02 :: Redstone
2479);
2480
2481proto_byte_flag!(CommandBlockFlags,
2482 0x01 :: is_track_output set_track_output,
2483 0x02 :: is_conditional set_conditional,
2484 0x04 :: is_automatic set_automatic
2485);
2486
2487proto_varint_enum!(UpdateStructureBlockAction,
2488 0x00 :: UpdateData,
2489 0x01 :: SaveStructure,
2490 0x02 :: LoadStructure,
2491 0x03 :: DetectSize
2492);
2493
2494proto_varint_enum!(UpdateStructureBlockMode,
2495 0x00 :: Save,
2496 0x01 :: Load,
2497 0x02 :: Corner,
2498 0x03 :: Data
2499);
2500
2501proto_varint_enum!(UpdateStructureBlockMirror,
2502 0x00 :: NoMirror,
2503 0x01 :: LeftRight,
2504 0x02 :: FrontBack
2505);
2506
2507proto_varint_enum!(UpdateStructureBlockRotation,
2508 0x00 :: NoRotation,
2509 0x01 :: Clockwise90,
2510 0x02 :: Clockwise180,
2511 0x03 :: CounterClockwise90
2512);
2513
2514proto_byte_flag!(UpdateStructureBlockFlags,
2515 0x01 :: is_ignore_entities set_ignore_entities,
2516 0x02 :: is_show_air set_show_air,
2517 0x04 :: is_show_bounding_box set_show_bounding_box
2518);
2519
2520#[derive(Clone, PartialEq, Debug)]
2521pub struct RecipeSpec {
2522 pub recipe: Recipe,
2523 pub id: String,
2524}
2525
2526proto_str_enum!(Recipe,
2527 "minecraft:crafting_shapeless" :: CraftingShapeless(RecipeCraftingShapelessSpec),
2528 "minecraft:crafting_shaped" :: CraftingShaped(RecipeCraftingShapedSpec),
2529 "minecraft:crafting_special_armordye" :: CraftingArmorDye,
2530 "minecraft:crafting_special_bookcloning" :: CraftingBookCloning,
2531 "minecraft:crafting_special_mapcloning" :: CraftingMapCloning,
2532 "minecraft:crafting_special_mapextending" :: CraftingMapExtending,
2533 "minecraft:crafting_special_firework_rocket" :: CraftingFireworkRocket,
2534 "minecraft:crafting_special_firework_star" :: CraftingFireworkStar,
2535 "minecraft:crafting_special_firework_star_fade" :: CraftingFireworkStarFade,
2536 "minecraft:crafting_special_repairitem" :: CraftingRepairItem,
2537 "minecraft:crafting_special_tippedarrow" :: CraftingTippedArrow,
2538 "minecraft:crafting_special_bannerduplicate" :: CraftingBannerDuplicate,
2539 "minecraft:crafting_special_banneraddpattern" :: CraftingBannerAddPattern,
2540 "minecraft:crafting_special_shielddecoration" :: CraftingShieldDecoration,
2541 "minecraft:crafting_special_shulkerboxcoloring" :: CraftingShulkerBoxColoring,
2542 "minecraft:crafting_special_suspiciousstew" :: CraftingSuspiciousStew,
2543 "minecraft:smelting" :: Smelting(RecipeSmeltingSpec),
2544 "minecraft:blasting" :: Blasting(RecipeSmeltingSpec),
2545 "minecraft:smoking" :: Smoking(RecipeSmeltingSpec),
2546 "minecraft:campfire_cooking" :: CampfireCooking(RecipeSmeltingSpec),
2547 "minecraft:stonecutting" :: StoneCutting(RecipeStonecuttingSpec),
2548 "minecraft:smithing" :: Smithing(RecipeSmithingSpec)
2549);
2550
2551impl Serialize for RecipeSpec {
2552 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2553 let _type = self.recipe.id();
2554 to.serialize_other(&_type)?;
2555 to.serialize_other(&self.id)?;
2556 self.recipe.serialize_body(to)
2557 }
2558}
2559
2560impl Deserialize for RecipeSpec {
2561 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
2562 let Deserialized { value: _type, data } = String::mc_deserialize(data)?;
2563 let Deserialized {
2564 value: recipe_id,
2565 data,
2566 } = String::mc_deserialize(data)?;
2567
2568 Ok(Recipe::deserialize_with_id(_type.as_str(), data)?.map(move |recipe| {
2569 RecipeSpec {
2570 id: recipe_id,
2571 recipe,
2572 }
2573 }))
2574 }
2575}
2576
2577#[cfg(all(test, feature = "std"))]
2578impl TestRandom for RecipeSpec {
2579 fn test_gen_random() -> Self {
2580 RecipeSpec {
2581 recipe: Recipe::test_gen_random(),
2582 id: String::test_gen_random(),
2583 }
2584 }
2585}
2586
2587proto_struct!(RecipeIngredient {
2588 items: CountedArray<Slot, VarInt>
2589});
2590
2591proto_struct!(RecipeCraftingShapelessSpec {
2592 group: String,
2593 ingredients: CountedArray<RecipeIngredient, VarInt>,
2594 result: Slot
2595});
2596
2597#[derive(Debug, Clone, PartialEq)]
2598pub struct RecipeCraftingShapedSpec {
2599 pub width: VarInt,
2600 pub height: VarInt,
2601 pub group: String,
2602 pub ingredients: Vec<RecipeIngredient>,
2603 pub result: Slot,
2604}
2605
2606impl Serialize for RecipeCraftingShapedSpec {
2607 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2608 to.serialize_other(&self.width)?;
2609 to.serialize_other(&self.height)?;
2610 to.serialize_other(&self.group)?;
2611 for elem in &self.ingredients {
2612 to.serialize_other(elem)?;
2613 }
2614 to.serialize_other(&self.result)?;
2615 Ok(())
2616 }
2617}
2618
2619impl Deserialize for RecipeCraftingShapedSpec {
2620 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
2621 let Deserialized { value: width, data } = <VarInt>::mc_deserialize(data)?;
2622 let Deserialized { value: height, data } = <VarInt>::mc_deserialize(data)?;
2623 let Deserialized { value: group, mut data } = <String>::mc_deserialize(data)?;
2624
2625 let ingredients_count = width.0 as usize * height.0 as usize;
2626 let mut ingredients: Vec<RecipeIngredient> = Vec::with_capacity(ingredients_count);
2627 for _ in 0..ingredients_count {
2628 let Deserialized { value: elem, data: rest } = RecipeIngredient::mc_deserialize(data)?;
2629 data = rest;
2630 ingredients.push(elem);
2631 }
2632
2633 let Deserialized { value: result, data } = Slot::mc_deserialize(data)?;
2634
2635 Deserialized::ok(
2636 Self {
2637 width,
2638 height,
2639 group,
2640 ingredients,
2641 result,
2642 },
2643 data,
2644 )
2645 }
2646}
2647
2648#[cfg(all(test, feature = "std"))]
2649impl TestRandom for RecipeCraftingShapedSpec {
2650 fn test_gen_random() -> Self {
2651 use rand::distributions::Distribution;
2652 let size_distr = rand::distributions::Uniform::new(1, 9);
2653 let mut rng = rand::thread_rng();
2654
2655 let width: VarInt = size_distr.sample(&mut rng).into();
2656 let height: VarInt = size_distr.sample(&mut rng).into();
2657 let n_ingredients = (width.0 as usize) * (height.0 as usize);
2658 let mut ingredients = Vec::with_capacity(n_ingredients);
2659 for _ in 0..n_ingredients {
2660 ingredients.push(RecipeIngredient::test_gen_random());
2661 }
2662
2663 RecipeCraftingShapedSpec {
2664 width,
2665 height,
2666 group: String::test_gen_random(),
2667 ingredients,
2668 result: Some(ItemStack::test_gen_random()),
2669 }
2670 }
2671}
2672
2673proto_struct!(RecipeSmeltingSpec {
2674 group: String,
2675 ingredient: RecipeIngredient,
2676 result: Slot,
2677 experience: f32,
2678 cooking_time: VarInt
2679});
2680
2681proto_struct!(RecipeStonecuttingSpec {
2682 group: String,
2683 ingredient: RecipeIngredient,
2684 result: Slot
2685});
2686
2687proto_struct!(RecipeSmithingSpec {
2688 base: RecipeIngredient,
2689 addition: RecipeIngredient,
2690 result: Slot
2691});
2692
2693proto_varint_enum!(RecipeUnlockAction,
2694 0x00 :: Init,
2695 0x01 :: Add,
2696 0x02 :: Remove
2697);
2698
2699#[derive(Clone, PartialEq, Debug)]
2700pub struct ChunkData {
2701 pub position: ChunkPosition<i32>,
2702 pub primary_bit_mask: VarInt,
2703 pub heightmaps: NamedNbtTag,
2704 pub biomes: Option<CountedArray<VarInt, VarInt>>,
2705 pub data: CountedArray<u8, VarInt>,
2706 pub block_entities: Vec<NamedNbtTag>,
2707}
2708
2709impl Serialize for ChunkData {
2710 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2711 to.serialize_other(&self.position)?;
2712 let full_chunk = self.biomes.is_some();
2713 to.serialize_other(&full_chunk)?;
2714 to.serialize_other(&self.primary_bit_mask)?;
2715 to.serialize_other(&self.heightmaps)?;
2716
2717 if full_chunk {
2718 to.serialize_other(self.biomes.as_ref().unwrap())?;
2719 }
2720
2721 to.serialize_other(&self.data)?;
2722 let num_block_entities = VarInt(self.block_entities.len() as i32);
2723 to.serialize_other(&num_block_entities)?;
2724 for entity in &self.block_entities {
2725 to.serialize_other(entity)?;
2726 }
2727
2728 Ok(())
2729 }
2730}
2731
2732impl Deserialize for ChunkData {
2733 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
2734 let Deserialized { value: position, data } = <ChunkPosition<i32>>::mc_deserialize(data)?;
2735 let Deserialized { value: is_full_chunk, data } = bool::mc_deserialize(data)?;
2736 let Deserialized { value: primary_bit_mask, data } = VarInt::mc_deserialize(data)?;
2737 let Deserialized { value: heightmaps, mut data } = NamedNbtTag::mc_deserialize(data)?;
2738 let biomes = if is_full_chunk {
2739 let Deserialized { value: biomes, data: rest } = <CountedArray<VarInt, VarInt>>::mc_deserialize(data)?;
2740 data = rest;
2741 Some(biomes)
2742 } else {
2743 None
2744 };
2745 let Deserialized { value: chunk_data, data } = <CountedArray<u8, VarInt>>::mc_deserialize(data)?;
2746 let Deserialized { value: n_block_entities_raw, mut data } = VarInt::mc_deserialize(data)?;
2747 let n_block_entities = n_block_entities_raw.0 as usize;
2748 let mut block_entities = Vec::with_capacity(n_block_entities);
2749 for _ in 0..n_block_entities {
2750 let Deserialized { value: entity, data: rest } = NamedNbtTag::mc_deserialize(data)?;
2751 data = rest;
2752 block_entities.push(entity);
2753 }
2754
2755 Deserialized::ok(ChunkData {
2756 position,
2757 primary_bit_mask,
2758 heightmaps,
2759 biomes,
2760 data: chunk_data,
2761 block_entities,
2762 }, data)
2763 }
2764}
2765
2766#[cfg(all(test, feature = "std"))]
2767impl TestRandom for ChunkData {
2768 fn test_gen_random() -> Self {
2769 ChunkData {
2770 position: <ChunkPosition<i32>>::test_gen_random(),
2771 primary_bit_mask: VarInt::test_gen_random(),
2772 heightmaps: NamedNbtTag::test_gen_random(),
2773 biomes: None,
2774 data: <CountedArray<u8, VarInt>>::test_gen_random(),
2775 block_entities: vec![],
2776 }
2777 }
2778}
2779
2780pub const LIGHT_DATA_LENGTH: usize = 2048;
2781pub const LIGHT_DATA_SECTIONS: usize = 18;
2782
2783#[derive(Clone, PartialEq)]
2784pub struct LightingData {
2785 pub data: Box<[Option<[u8; LIGHT_DATA_LENGTH]>; LIGHT_DATA_SECTIONS]>,
2786}
2787
2788impl LightingData {
2789 fn deserialize(update_mask: VarInt, mut data: &[u8]) -> DeserializeResult<Self> {
2790 let mut out = Box::new([None; LIGHT_DATA_SECTIONS]);
2791 for i in 0..LIGHT_DATA_SECTIONS {
2792 if update_mask.0 & (1 << i) != 0 {
2794 let Deserialized { value: length, data: rest } = VarInt::mc_deserialize(data)?;
2795 if (length.0 as usize) != LIGHT_DATA_LENGTH {
2796 return Err(DeserializeErr::CannotUnderstandValue(alloc::format!("bad data length in light update {}", length)));
2797 }
2798
2799 data = rest;
2800 if data.len() < LIGHT_DATA_LENGTH {
2801 return Err(DeserializeErr::Eof);
2802 }
2803
2804 let (section, rest) = data.split_at(LIGHT_DATA_LENGTH);
2805 let mut to_vec = [0u8; LIGHT_DATA_LENGTH];
2806 to_vec.copy_from_slice(section);
2807 out[i] = Some(to_vec);
2808 data = rest;
2809 }
2810 }
2811
2812 let result = Self {
2813 data: out,
2814 };
2815
2816 Deserialized::ok(result, data)
2817 }
2818
2819 fn update_mask(&self) -> VarInt {
2820 self.compute_has_mask(true)
2821 }
2822
2823 fn reset_mask(&self) -> VarInt {
2824 self.compute_has_mask(false)
2825 }
2826
2827 fn compute_has_mask(&self, has: bool) -> VarInt {
2828 let mut out: u32 = 0;
2829 for i in 0..LIGHT_DATA_SECTIONS {
2830 if self.data[i].is_some() == has {
2831 out |= 1 << i;
2832 }
2833 }
2834
2835 VarInt(out as i32)
2836 }
2837
2838 fn serialize_data<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2839 for item in self.data.iter() {
2840 if let Some(contents) = item {
2841 to.serialize_other(&VarInt(2048))?;
2842 to.serialize_bytes(&contents[..])?;
2843 }
2844 }
2845
2846 Ok(())
2847 }
2848}
2849
2850impl fmt::Debug for LightingData {
2851 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2852 write!(
2853 f,
2854 "LightingData(update={:018b}, reset={:018b}, size={}, bytes={})",
2855 self.update_mask().0,
2856 self.reset_mask().0,
2857 self.data.iter().filter(move |v| v.is_some()).count(),
2858 self.data.iter()
2859 .filter_map(move |v| v.
2860 map(move |arr| arr.len()))
2861 .sum::<usize>())
2862 }
2863}
2864
2865impl fmt::Display for LightingData {
2866 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2867 <dyn fmt::Debug>::fmt(self, f)
2868 }
2869}
2870
2871#[cfg(all(test, feature = "std"))]
2872impl LightingData {
2873 fn gen_random_mask() -> i32 {
2874 let rand: u32 = rand::random();
2875 (rand & ((1 << 19) - 1)) as i32
2876 }
2877}
2878
2879#[cfg(all(test, feature = "std"))]
2880impl TestRandom for LightingData {
2881 fn test_gen_random() -> Self {
2882 let set_mask = Self::gen_random_mask();
2883 let mut data = Box::new([None; LIGHT_DATA_SECTIONS]);
2884 for i in 0..LIGHT_DATA_SECTIONS {
2885 if (set_mask & (1 << i)) != 0 {
2886 let mut data_arr = [0u8; LIGHT_DATA_LENGTH];
2887 for k in 0..LIGHT_DATA_LENGTH {
2888 data_arr[k] = rand::random();
2889 }
2890 data[i] = Some(data_arr);
2891 }
2892 }
2893
2894 Self {
2895 data,
2896 }
2897 }
2898}
2899
2900#[derive(Clone, PartialEq, Debug)]
2901pub struct LightingUpdateSpec {
2902 pub skylight_data: LightingData,
2903 pub blocklight_data: LightingData,
2904}
2905
2906impl Serialize for LightingUpdateSpec {
2907 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2908 self.skylight_data.update_mask().mc_serialize(to)?;
2909 self.blocklight_data.update_mask().mc_serialize(to)?;
2910 self.skylight_data.reset_mask().mc_serialize(to)?;
2911 self.blocklight_data.reset_mask().mc_serialize(to)?;
2912 self.skylight_data.serialize_data(to)?;
2913 self.blocklight_data.serialize_data(to)
2914 }
2915}
2916
2917impl Deserialize for LightingUpdateSpec {
2918 fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> {
2919 let Deserialized { value: skylight_update_mask, data } = VarInt::mc_deserialize(data)?;
2920 let Deserialized { value: blocklight_update_mask, data } = VarInt::mc_deserialize(data)?;
2921 let Deserialized { value: _, data } = VarInt::mc_deserialize(data)?;
2922 let Deserialized { value: _, data } = VarInt::mc_deserialize(data)?;
2923
2924 let Deserialized { value: skylight_data, data } = LightingData::deserialize(skylight_update_mask, data)?;
2925 let Deserialized { value: blocklight_data, data } = LightingData::deserialize(blocklight_update_mask, data)?;
2926
2927 Deserialized::ok(Self {
2928 skylight_data,
2929 blocklight_data,
2930 }, data)
2931 }
2932}
2933
2934#[cfg(all(test, feature = "std"))]
2935impl TestRandom for LightingUpdateSpec {
2936 fn test_gen_random() -> Self {
2937 Self {
2938 skylight_data: LightingData::test_gen_random(),
2939 blocklight_data: LightingData::test_gen_random(),
2940 }
2941 }
2942}
2943
2944#[derive(Clone, Debug, PartialEq, Default)]
2945pub struct EntityMetadata {
2946 pub fields: Vec<EntityMetadataField>
2947}
2948
2949impl Serialize for EntityMetadata {
2950 fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult {
2951 for field in &self.fields {
2952 to.serialize_byte(field.index)?;
2953 to.serialize_other(&field.data)?;
2954 }
2955 to.serialize_byte(0xFF)
2956 }
2957}
2958
2959impl Deserialize for EntityMetadata {
2960 fn mc_deserialize(mut data: &[u8]) -> DeserializeResult<'_, Self> {
2961 let mut fields = Vec::new();
2962 loop {
2963 let Deserialized { value: index, data: rest } = u8::mc_deserialize(data)?;
2964 data = rest;
2965 if index == 0xFF {
2966 break;
2967 }
2968
2969 let Deserialized { value: field, data: rest } = EntityMetadataFieldData::mc_deserialize(data)?;
2970 data = rest;
2971 fields.push(EntityMetadataField {
2972 index,
2973 data: field,
2974 });
2975 }
2976
2977 Deserialized::ok(Self {
2978 fields,
2979 }, data)
2980 }
2981}
2982
2983#[cfg(all(test, feature = "std"))]
2984impl TestRandom for EntityMetadata {
2985 fn test_gen_random() -> Self {
2986 let n_fields = rand::random::<usize>() % 10;
2987 let mut fields = Vec::with_capacity(n_fields);
2988 for i in 0..n_fields {
2989 fields.push(EntityMetadataField {
2990 index: i as u8,
2991 data: EntityMetadataFieldData::test_gen_random(),
2992 });
2993 }
2994
2995 Self {
2996 fields,
2997 }
2998 }
2999}
3000
3001impl EntityMetadata {
3002 pub fn set(&mut self, index: u8, data: EntityMetadataFieldData) {
3003 for field in &mut self.fields {
3004 if field.index == index {
3005 field.data = data;
3006 return;
3007 }
3008 }
3009
3010 self.fields.push(EntityMetadataField {
3011 index,
3012 data,
3013 })
3014 }
3015
3016 pub fn remove(&mut self, index: u8) -> bool {
3017 for i in 0..self.fields.len() {
3018 let field = self.fields
3019 .get(i)
3020 .expect("iterating through this vec, definitely have this index");
3021 if field.index == index {
3022 self.fields.remove(i);
3023 return true;
3024 }
3025 }
3026
3027 false
3028 }
3029
3030 pub fn get(&self, index: u8) -> Option<&EntityMetadataFieldData> {
3031 for field in &self.fields {
3032 if field.index == index {
3033 return Some(&field.data);
3034 }
3035 }
3036
3037 None
3038 }
3039
3040 pub fn get_mut(&mut self, index: u8) -> Option<&mut EntityMetadataFieldData> {
3041 for field in &mut self.fields {
3042 if field.index == index {
3043 return Some(&mut field.data);
3044 }
3045 }
3046
3047 None
3048 }
3049}
3050
3051impl<'a> core::iter::IntoIterator for &'a EntityMetadata {
3052 type Item = (u8, &'a EntityMetadataFieldData);
3053 type IntoIter = FieldIter<'a>;
3054
3055 fn into_iter(self) -> Self::IntoIter {
3056 FieldIter {
3057 data: self,
3058 at: 0,
3059 }
3060 }
3061}
3062
3063pub struct FieldIter<'a> {
3064 data: &'a EntityMetadata,
3065 at: usize,
3066}
3067
3068impl<'a> core::iter::Iterator for FieldIter<'a> {
3069 type Item = (u8, &'a EntityMetadataFieldData);
3070
3071 fn next(&mut self) -> Option<Self::Item> {
3072 self.data.fields.get(self.at).map(move |field| (field.index, &field.data))
3073 }
3074
3075 fn size_hint(&self) -> (usize, Option<usize>) {
3076 let len = self.data.fields.len();
3077 (len, Some(len))
3078 }
3079}
3080
3081#[derive(Clone, Debug, PartialEq)]
3082pub struct EntityMetadataField {
3083 pub index: u8,
3084 pub data: EntityMetadataFieldData,
3085}
3086
3087proto_varint_enum!(EntityMetadataFieldData,
3088 0x00 :: Byte(i8),
3089 0x01 :: VarInt(VarInt),
3090 0x02 :: Float(f32),
3091 0x03 :: String(String),
3092 0x04 :: Chat(Chat),
3093 0x05 :: OptChat(Option<Chat>),
3094 0x06 :: Slot(Slot),
3095 0x07 :: Boolean(bool),
3096 0x08 :: Rotation(Vec3<f32>),
3097 0x09 :: Position(IntPosition),
3098 0x0A :: OptPosition(Option<IntPosition>),
3099 0x0B :: Direction(EntityDirection),
3100 0x0C :: OptUUID(Option<UUID4>),
3101 0x0D :: OptBlockId(VarInt),
3102 0x0E :: NBT(NamedNbtTag),
3103 0x0F :: Particle(ParticleSpec),
3104 0x10 :: VillagerData(EntityVillagerData),
3105 0x11 :: OptVarInt(VarInt),
3106 0x12 :: Pose(EntityPose)
3107);
3108
3109proto_varint_enum!(EntityDirection,
3110 0x00 :: Down,
3111 0x01 :: Up,
3112 0x02 :: North,
3113 0x03 :: South,
3114 0x04 :: West,
3115 0x05 :: East
3116);
3117
3118proto_struct!(EntityVillagerData {
3119 villager_type: VillagerType,
3120 villager_profession: VillagerProfession,
3121 level: VarInt
3122});
3123
3124proto_varint_enum!(VillagerType,
3125 0x00 :: Desert,
3126 0x01 :: Jungle,
3127 0x02 :: Plains,
3128 0x03 :: Savanna,
3129 0x04 :: Snow,
3130 0x05 :: Swamp,
3131 0x06 :: Taiga
3132);
3133
3134proto_varint_enum!(VillagerProfession,
3135 0x00 :: None,
3136 0x01 :: Armorer,
3137 0x02 :: Butcher,
3138 0x03 :: Cartographer,
3139 0x04 :: Cleric,
3140 0x05 :: Farmer,
3141 0x06 :: Fisherman,
3142 0x07 :: Fletcher,
3143 0x08 :: LeatherWorker,
3144 0x09 :: Librarian,
3145 0x0A :: Mason,
3146 0x0B :: Nitwit,
3147 0x0C :: Shepherd,
3148 0x0D :: Toolsmith,
3149 0x0E :: Weaponsmith
3150);
3151
3152proto_varint_enum!(EntityPose,
3153 0x00 :: Standing,
3154 0x01 :: FallFlying,
3155 0x02 :: Sleeping,
3156 0x03 :: Swimming,
3157 0x04 :: SpinAttack,
3158 0x05 :: Sneaking,
3159 0x06 :: Dying
3160);
3161
3162proto_varint_enum!(ParticleSpec,
3163 0x00 :: AmbientEntityEffect,
3164 0x01 :: AngryVillager,
3165 0x02 :: Barrier,
3166 0x03 :: Block(BlockParticleData),
3167 0x04 :: Bubble,
3168 0x05 :: Cloud,
3169 0x06 :: Crit,
3170 0x07 :: DamageIndicator,
3171 0x08 :: DragonBreath,
3172 0x09 :: DrippingLava,
3173 0x0A :: FallingLava,
3174 0x0B :: LandingLava,
3175 0x0C :: DrippingWater,
3176 0x0D :: FallingWater,
3177 0x0E :: Dust(DustParticleData),
3178 0x0F :: Effect,
3179 0x10 :: ElderGuardian,
3180 0x11 :: EnchantedHit,
3181 0x12 :: Enchant,
3182 0x13 :: EndRod,
3183 0x14 :: EntityEffect,
3184 0x15 :: ExposionEmitter,
3185 0x16 :: Explosion,
3186 0x17 :: FallingDust(DustParticleData),
3187 0x18 :: Firework,
3188 0x19 :: Fishing,
3189 0x1A :: Flame,
3190 0x1B :: Flash,
3191 0x1C :: HappyVillager,
3192 0x1D :: Composter,
3193 0x1E :: Heart,
3194 0x1F :: InstantEffect,
3195 0x20 :: Item(Slot),
3196 0x21 :: ItemSlime,
3197 0x22 :: ItemSnowball,
3198 0x23 :: LargeSmoke,
3199 0x24 :: Lava,
3200 0x25 :: Mycelium,
3201 0x26 :: Note,
3202 0x27 :: Poof,
3203 0x28 :: Portal,
3204 0x29 :: Rain,
3205 0x2A :: Smoke,
3206 0x2B :: Sneeze,
3207 0x2C :: Spit,
3208 0x2D :: SquidInk,
3209 0x2E :: SweepAttack,
3210 0x2F :: TotemOfUndying,
3211 0x30 :: Underwater,
3212 0x31 :: Splash,
3213 0x32 :: Witch,
3214 0x33 :: BubblePop,
3215 0x34 :: CurrentDown,
3216 0x35 :: BubbleColumnUp,
3217 0x36 :: Nautilus,
3218 0x37 :: Dolphin,
3219 0x38 :: CampfireCosySmoke,
3220 0x39 :: CampfireSignalSmoke,
3221 0x3A :: DrippingHoney,
3222 0x3B :: FallingHoney,
3223 0x3C :: LandingHoney,
3224 0x3D :: FallingNectar
3225);
3226
3227proto_struct!(BlockParticleData {
3228 block_state: VarInt
3229});
3230
3231proto_struct!(DustParticleData {
3232 red: f32,
3233 green: f32,
3234 blue: f32,
3235 scale: f32
3236});
3237
3238#[cfg(all(test, feature = "std"))]
3239pub mod tests {
3240 use super::*;
3241 use crate::packet_test_cases;
3242
3243 packet_test_cases!(RawPacket753, Packet753, Handshake, HandshakeSpec,
3244 test_handshake, bench_write_handshake, bench_read_handshake);
3245
3246 packet_test_cases!(RawPacket753, Packet753, StatusRequest, StatusRequestSpec,
3247 test_status_request, bench_write_status_request, bench_read_status_request);
3248
3249 packet_test_cases!(RawPacket753, Packet753, StatusPing, StatusPingSpec,
3250 test_status_ping, bench_write_status_ping, bench_read_status_ping);
3251
3252 packet_test_cases!(RawPacket753, Packet753, StatusResponse, StatusResponseSpec,
3253 test_status_response, bench_write_status_response, bench_read_status_response);
3254
3255 packet_test_cases!(RawPacket753, Packet753, StatusPong, StatusPongSpec,
3256 test_status_pong, bench_write_status_pong, bench_read_status_pong);
3257
3258 packet_test_cases!(RawPacket753, Packet753, LoginDisconnect, LoginDisconnectSpec,
3259 test_login_disconnect, bench_write_login_disconnect, bench_read_login_disconnect);
3260
3261 packet_test_cases!(RawPacket753, Packet753, LoginEncryptionRequest, LoginEncryptionRequestSpec,
3262 test_login_encryption_request, bench_write_login_encryption_request, bench_read_login_encryption_request);
3263
3264 packet_test_cases!(RawPacket753, Packet753, LoginSuccess, LoginSuccessSpec,
3265 test_login_success, bench_write_login_success, bench_read_login_success);
3266
3267 packet_test_cases!(RawPacket753, Packet753, LoginSetCompression, LoginSetCompressionSpec,
3268 test_login_set_compression, bench_write_login_set_compression, bench_read_login_set_compression);
3269
3270 packet_test_cases!(RawPacket753, Packet753, LoginPluginRequest, LoginPluginRequestSpec,
3271 test_login_plugin_request, bench_write_login_plugin_request, bench_read_login_plugin_request);
3272
3273 packet_test_cases!(RawPacket753, Packet753, LoginStart, LoginStartSpec,
3274 test_login_start, bench_write_login_start, bench_read_login_start);
3275
3276 packet_test_cases!(RawPacket753, Packet753, LoginEncryptionResponse, LoginEncryptionResponseSpec,
3277 test_login_encryption_response, bench_write_login_encryption_response, bench_read_login_encryption_response);
3278
3279 packet_test_cases!(RawPacket753, Packet753, LoginPluginResponse, LoginPluginResponseSpec,
3280 test_login_plugin_response, bench_write_login_plugin_response, bench_read_login_plugin_response);
3281
3282 packet_test_cases!(RawPacket753, Packet753, PlaySpawnEntity, PlaySpawnEntitySpec,
3283 test_play_spawn_entity, bench_write_play_spawn_entity, bench_read_play_spawn_entity);
3284
3285 packet_test_cases!(RawPacket753, Packet753, PlaySpawnExperienceOrb, PlaySpawnExperienceOrbSpec,
3286 test_play_spawn_experience_orb, bench_write_play_spawn_experience_orb, bench_read_play_spawn_experience_orb);
3287
3288 packet_test_cases!(RawPacket753, Packet753, PlaySpawnLivingEntity, PlaySpawnLivingEntitySpec,
3289 test_play_spawn_living_entity, bench_write_play_spawn_living_entity, bench_read_play_spawn_living_entity);
3290
3291 packet_test_cases!(RawPacket753, Packet753, PlaySpawnPainting, PlaySpawnPaintingSpec,
3292 test_play_spawn_painting, bench_write_play_spawn_painting, bench_read_play_spawn_painting);
3293
3294 packet_test_cases!(RawPacket753, Packet753, PlaySpawnPlayer, PlaySpawnPlayerSpec,
3295 test_play_spawn_player, bench_write_play_spawn_player, bench_read_play_spawn_player);
3296
3297 packet_test_cases!(RawPacket753, Packet753, PlayEntityAnimation, PlayEntityAnimationSpec,
3298 test_play_entity_animation, bench_write_play_entity_animation, bench_read_play_entity_animation);
3299
3300 packet_test_cases!(RawPacket753, Packet753, PlayStatistics, PlayStatisticsSpec,
3301 test_play_statistics, bench_write_play_statistics, bench_read_play_statistics);
3302
3303 packet_test_cases!(RawPacket753, Packet753, PlayAcknowledgePlayerDigging, PlayAcknowledgePlayerDiggingSpec,
3304 test_play_acknowledge_player_digging, bench_write_play_acknowledge_player_digging, bench_read_play_acknowledge_player_digging);
3305
3306 packet_test_cases!(RawPacket753, Packet753, PlayBlockBreakAnimation, PlayBlockBreakAnimationSpec,
3307 test_play_block_break_animation, bench_write_play_block_break_animation, bench_read_play_block_break_animation);
3308
3309 packet_test_cases!(RawPacket753, Packet753, PlayBlockEntityData, PlayBlockEntityDataSpec,
3310 test_play_block_entity_data, bench_write_play_block_entity_data, bench_read_play_block_entity_data);
3311
3312 packet_test_cases!(RawPacket753, Packet753, PlayBlockAction, PlayBlockActionSpec,
3313 test_play_block_action, bench_write_play_block_action, bench_read_play_block_action);
3314
3315 packet_test_cases!(RawPacket753, Packet753, PlayBlockChange, PlayBlockChangeSpec,
3316 test_play_block_change, bench_write_play_block_change, bench_read_play_block_change);
3317
3318 packet_test_cases!(RawPacket753, Packet753, PlayBossBar, PlayBossBarSpec,
3319 test_play_boss_bar, bench_write_play_boss_bar, bench_read_play_boss_bar);
3320
3321 packet_test_cases!(RawPacket753, Packet753, PlayServerDifficulty, PlayServerDifficultySpec,
3322 test_play_server_difficulty, bench_write_play_server_difficulty, bench_read_play_server_difficulty);
3323
3324 packet_test_cases!(RawPacket753, Packet753, PlayServerChatMessage, PlayServerChatMessageSpec,
3325 test_play_server_chat_message, bench_write_play_server_chat_message, bench_read_play_server_chat_message);
3326
3327 packet_test_cases!(RawPacket753, Packet753, PlayTabComplete, PlayTabCompleteSpec,
3328 test_play_tab_complete, bench_write_play_tab_complete, bench_read_play_tab_complete);
3329
3330 packet_test_cases!(RawPacket753, Packet753, PlayDeclareCommands, PlayDeclareCommandsSpec,
3331 test_play_declare_commands, bench_write_play_declare_commands, bench_read_play_declare_commands);
3332
3333 packet_test_cases!(RawPacket753, Packet753, PlayServerWindowConfirmation, PlayServerWindowConfirmationSpec,
3334 test_play_server_window_confirmation, bench_write_play_server_window_confirmation, bench_read_play_server_window_confirmation);
3335
3336 packet_test_cases!(RawPacket753, Packet753, PlayServerCloseWindow, PlayServerCloseWindowSpec,
3337 test_play_server_close_window, bench_write_play_server_close_window, bench_read_play_server_close_window);
3338
3339 packet_test_cases!(RawPacket753, Packet753, PlayWindowItems, PlayWindowItemsSpec,
3340 test_play_window_items, bench_write_play_window_items, bench_read_play_window_items);
3341
3342 packet_test_cases!(RawPacket753, Packet753, PlayWindowProperty, PlayWindowPropertySpec,
3343 test_play_window_property, bench_write_play_window_property, bench_read_play_window_property);
3344
3345 packet_test_cases!(RawPacket753, Packet753, PlaySetSlot, PlaySetSlotSpec,
3346 test_play_set_slot, bench_write_play_set_slot, bench_read_play_set_slot);
3347
3348 packet_test_cases!(RawPacket753, Packet753, PlaySetCooldown, PlaySetCooldownSpec,
3349 test_play_set_cooldown, bench_write_play_set_cooldown, bench_read_play_set_cooldown);
3350
3351 packet_test_cases!(RawPacket753, Packet753, PlayServerPluginMessage, PlayServerPluginMessageSpec,
3352 test_play_server_plugin_message, bench_write_play_server_plugin_message, bench_read_play_server_plugin_message);
3353
3354 packet_test_cases!(RawPacket753, Packet753, PlayNamedSoundEffect, PlayNamedSoundEffectSpec,
3355 test_play_named_sound_effect, bench_write_play_named_sound_effect, bench_read_play_named_sound_effect);
3356
3357 packet_test_cases!(RawPacket753, Packet753, PlayDisconnect, PlayDisconnectSpec,
3358 test_play_disconnect, bench_write_play_disconnect, bench_read_play_disconnect);
3359
3360 packet_test_cases!(RawPacket753, Packet753, PlayEntityStatus, PlayEntityStatusSpec,
3361 test_play_entity_status, bench_write_play_entity_status, bench_read_play_entity_status);
3362
3363 packet_test_cases!(RawPacket753, Packet753, PlayExplosion, PlayExplosionSpec,
3364 test_play_explosion, bench_write_play_explosion, bench_read_play_explosion);
3365
3366 packet_test_cases!(RawPacket753, Packet753, PlayUnloadChunk, PlayUnloadChunkSpec,
3367 test_play_unload_chunk, bench_write_play_unload_chunk, bench_read_play_unload_chunk);
3368
3369 packet_test_cases!(RawPacket753, Packet753, PlayChangeGameState, PlayChangeGameStateSpec,
3370 test_play_change_game_state, bench_write_play_change_game_state, bench_read_play_change_game_state);
3371
3372 packet_test_cases!(RawPacket753, Packet753, PlayOpenHorseWindow, PlayOpenHorseWindowSpec,
3373 test_play_open_horse_window, bench_write_play_open_horse_window, bench_read_play_open_horse_window);
3374
3375 packet_test_cases!(RawPacket753, Packet753, PlayServerKeepAlive, PlayServerKeepAliveSpec,
3376 test_play_server_keep_alive, bench_write_play_server_keep_alive, bench_read_play_server_keep_alive);
3377
3378 packet_test_cases!(RawPacket753, Packet753, PlayChunkData, PlayChunkDataWrapper,
3379 test_play_chunk_data, bench_write_play_chunk_data, bench_read_play_chunk_data);
3380
3381 packet_test_cases!(RawPacket753, Packet753, PlayEffect, PlayEffectSpec,
3382 test_play_effect, bench_write_play_effect, bench_read_play_effect);
3383
3384 packet_test_cases!(RawPacket753, Packet753, PlayParticle, PlayParticleSpec,
3385 test_play_particle, bench_write_play_particle, bench_read_play_particle);
3386
3387 packet_test_cases!(RawPacket753, Packet753, PlayUpdateLight, PlayUpdateLightSpec,
3388 test_play_update_light, bench_write_play_update_light, bench_read_play_update_light);
3389
3390 packet_test_cases!(RawPacket753, Packet753, PlayJoinGame, PlayJoinGameSpec,
3391 test_play_join_game, bench_write_play_join_game, bench_read_play_join_game);
3392
3393 packet_test_cases!(RawPacket753, Packet753, PlayMapData, PlayMapDataSpec,
3394 test_play_map_data, bench_write_play_map_data, bench_read_play_map_data);
3395
3396 packet_test_cases!(RawPacket753, Packet753, PlayTradeList, PlayTradeListSpec,
3397 test_play_trade_list, bench_write_play_trade_list, bench_read_play_trade_list);
3398
3399 packet_test_cases!(RawPacket753, Packet753, PlayEntityPosition, PlayEntityPositionSpec,
3400 test_play_entity_position, bench_write_play_entity_position, bench_read_play_entity_position);
3401
3402 packet_test_cases!(RawPacket753, Packet753, PlayEntityPositionAndRotation, PlayEntityPositionAndRotationSpec,
3403 test_play_entity_position_and_rotation, bench_write_play_entity_position_and_rotation, bench_read_play_entity_position_and_rotation);
3404
3405 packet_test_cases!(RawPacket753, Packet753, PlayEntityRotation, PlayEntityRotationSpec,
3406 test_play_entity_rotation, bench_write_play_entity_rotation, bench_read_play_entity_rotation);
3407
3408 packet_test_cases!(RawPacket753, Packet753, PlayEntityMovement, PlayEntityMovementSpec,
3409 test_play_entity_movement, bench_write_play_entity_movement, bench_read_play_entity_movement);
3410
3411 packet_test_cases!(RawPacket753, Packet753, PlayServerVehicleMove, PlayEntityVehicleMoveSpec,
3412 test_play_server_vehicle_move, bench_write_play_server_vehicle_move, bench_read_play_server_vehicle_move);
3413
3414 packet_test_cases!(RawPacket753, Packet753, PlayOpenBook, PlayOpenBookSpec,
3415 test_play_open_book, bench_write_play_open_book, bench_read_play_open_book);
3416
3417 packet_test_cases!(RawPacket753, Packet753, PlayOpenWindow, PlayOpenWindowSpec,
3418 test_play_open_window, bench_write_play_open_window, bench_read_play_open_window);
3419
3420 packet_test_cases!(RawPacket753, Packet753, PlayOpenSignEditor, PlayOpenSignEditorSpec,
3421 test_play_open_sign_editor, bench_write_play_open_sign_editor, bench_read_play_open_sign_editor);
3422
3423 packet_test_cases!(RawPacket753, Packet753, PlayCraftRecipeResponse, PlayCraftRecipeResponseSpec,
3424 test_play_craft_recipe_response, bench_write_play_craft_recipe_response, bench_read_play_craft_recipe_response);
3425
3426 packet_test_cases!(RawPacket753, Packet753, PlayServerPlayerAbilities, PlayServerPlayerAbilitiesSpec,
3427 test_play_server_player_abilities, bench_write_play_server_player_abilities, bench_read_play_server_player_abilities);
3428
3429 packet_test_cases!(RawPacket753, Packet753, PlayCombatEvent, PlayCombatEventSpec,
3430 test_play_combat_event, bench_write_play_combat_event, bench_read_play_combat_event);
3431
3432 packet_test_cases!(RawPacket753, Packet753, PlayPlayerInfo, PlayPlayerInfoSpec,
3433 test_play_player_info, bench_write_play_player_info, bench_read_play_player_info);
3434
3435 packet_test_cases!(RawPacket753, Packet753, PlayFacePlayer, PlayFacePlayerSpec,
3436 test_play_face_player, bench_write_play_face_player, bench_read_play_face_player);
3437
3438 packet_test_cases!(RawPacket753, Packet753, PlayServerPlayerPositionAndLook, PlayServerPlayerPositionAndLookSpec,
3439 test_play_server_player_position_and_look, bench_write_play_server_player_position_and_look, bench_read_play_server_player_position_and_look);
3440
3441 packet_test_cases!(RawPacket753, Packet753, PlayUnlockRecipes, PlayUnlockRecipesSpec,
3442 test_play_unlock_recipes, bench_write_play_unlock_recipes, bench_read_play_unlock_recipes);
3443
3444 packet_test_cases!(RawPacket753, Packet753, PlayDestroyEntities, PlayDestroyEntitiesSpec,
3445 test_play_destroy_entities, bench_write_play_destroy_entities, bench_read_play_destroy_entities);
3446
3447 packet_test_cases!(RawPacket753, Packet753, PlayRemoveEntityEffect, PlayRemoveEntityEffectSpec,
3448 test_play_remove_entity_effect, bench_write_play_remove_entity_effect, bench_read_play_remove_entity_effect);
3449
3450 packet_test_cases!(RawPacket753, Packet753, PlayResourcePackSend, PlayResourcePackSendSpec,
3451 test_play_resource_pack_send, bench_write_play_resource_pack_send, bench_read_play_resource_pack_send);
3452
3453 packet_test_cases!(RawPacket753, Packet753, PlayRespawn, PlayRespawnSpec,
3454 test_play_respawn, bench_write_play_respawn, bench_read_play_respawn);
3455
3456 packet_test_cases!(RawPacket753, Packet753, PlayEntityHeadLook, PlayEntityHeadLookSpec,
3457 test_play_entity_head_look, bench_write_play_entity_head_look, bench_read_play_entity_head_look);
3458
3459 packet_test_cases!(RawPacket753, Packet753, PlayMultiBlockChange, PlayMultiBlockChangeSpec,
3460 test_play_multi_block_change, bench_write_play_multi_block_change, bench_read_play_multi_block_change);
3461
3462 packet_test_cases!(RawPacket753, Packet753, PlaySelectAdvancementTab, PlaySelectAdvancementTabSpec,
3463 test_play_select_advancement_tab, bench_write_play_select_advancement_tab, bench_read_play_select_advancement_tab);
3464
3465 packet_test_cases!(RawPacket753, Packet753, PlayWorldBorder, PlayWorldBorderSpec,
3466 test_play_world_border, bench_write_play_world_border, bench_read_play_world_border);
3467
3468 packet_test_cases!(RawPacket753, Packet753, PlayCamera, PlayCameraSpec,
3469 test_play_camera, bench_write_play_camera, bench_read_play_camera);
3470
3471 packet_test_cases!(RawPacket753, Packet753, PlayServerHeldItemChange, PlayServerHeldItemChangeSpec,
3472 test_play_server_held_item_change, bench_write_play_server_held_item_change, bench_read_play_server_held_item_change);
3473
3474 packet_test_cases!(RawPacket753, Packet753, PlayUpdateViewPosition, PlayUpdateViewPositionSpec,
3475 test_play_update_view_position, bench_write_play_update_view_position, bench_read_play_update_view_position);
3476
3477 packet_test_cases!(RawPacket753, Packet753, PlayUpdateViewDistance, PlayUpdateViewDistanceSpec,
3478 test_play_update_view_distance, bench_write_play_update_view_distance, bench_read_play_update_view_distance);
3479
3480 packet_test_cases!(RawPacket753, Packet753, PlaySpawnPosition, PlaySpawnPositionSpec,
3481 test_play_spawn_position, bench_write_play_spawn_position, bench_read_play_spawn_position);
3482
3483 packet_test_cases!(RawPacket753, Packet753, PlayDisplayScoreboard, PlayDisplayScoreboardSpec,
3484 test_play_display_scoreboard, bench_write_play_display_scoreboard, bench_read_play_display_scoreboard);
3485
3486 packet_test_cases!(RawPacket753, Packet753, PlayEntityMetadata, PlayEntityMetadataSpec,
3487 test_play_entity_metadata, bench_write_play_entity_metadata, bench_read_play_entity_metadata);
3488
3489 packet_test_cases!(RawPacket753, Packet753, PlayAttachEntity, PlayAttachEntitySpec,
3490 test_play_attach_entity, bench_write_play_attach_entity, bench_read_play_attach_entity);
3491
3492 packet_test_cases!(RawPacket753, Packet753, PlayEntityVelocity, PlayEntityVelocitySpec,
3493 test_play_entity_velocity, bench_write_play_entity_velocity, bench_read_play_entity_velocity);
3494
3495 packet_test_cases!(RawPacket753, Packet753, PlayEntityEquipment, PlayEntityEquiptmentSpec,
3496 test_play_entity_equipment, bench_write_play_entity_equipment, bench_read_play_entity_equipment);
3497
3498 packet_test_cases!(RawPacket753, Packet753, PlaySetExperience, PlaySetExperienceSpec,
3499 test_play_set_experience, bench_write_play_set_experience, bench_read_play_set_experience);
3500
3501 packet_test_cases!(RawPacket753, Packet753, PlayUpdatehealth, PlayUpdateHealthSpec,
3502 test_play_updatehealth, bench_write_play_updatehealth, bench_read_play_updatehealth);
3503
3504 packet_test_cases!(RawPacket753, Packet753, PlayScoreboardObjective, PlayScoreboardObjectiveSpec,
3505 test_play_scoreboard_objective, bench_write_play_scoreboard_objective, bench_read_play_scoreboard_objective);
3506
3507 packet_test_cases!(RawPacket753, Packet753, PlaySetPassengers, PlaySetPassengersSpec,
3508 test_play_set_passengers, bench_write_play_set_passengers, bench_read_play_set_passengers);
3509
3510 packet_test_cases!(RawPacket753, Packet753, PlayTeams, PlayTeamsSpec,
3511 test_play_teams, bench_write_play_teams, bench_read_play_teams);
3512
3513 packet_test_cases!(RawPacket753, Packet753, PlayUpdateScore, PlayUpdateScoreSpec,
3514 test_play_update_score, bench_write_play_update_score, bench_read_play_update_score);
3515
3516 packet_test_cases!(RawPacket753, Packet753, PlayTimeUpdate, PlayTimeUpdateSpec,
3517 test_play_time_update, bench_write_play_time_update, bench_read_play_time_update);
3518
3519 packet_test_cases!(RawPacket753, Packet753, PlayTitle, PlayTitleSpec,
3520 test_play_title, bench_write_play_title, bench_read_play_title);
3521
3522 packet_test_cases!(RawPacket753, Packet753, PlayEntitySoundEffect, PlayEntitySoundEffectSpec,
3523 test_play_entity_sound_effect, bench_write_play_entity_sound_effect, bench_read_play_entity_sound_effect);
3524
3525 packet_test_cases!(RawPacket753, Packet753, PlaySoundEffect, PlaySoundEffectSpec,
3526 test_play_sound_effect, bench_write_play_sound_effect, bench_read_play_sound_effect);
3527
3528 packet_test_cases!(RawPacket753, Packet753, PlayStopSound, PlayStopSoundSpec,
3529 test_play_stop_sound, bench_write_play_stop_sound, bench_read_play_stop_sound);
3530
3531 packet_test_cases!(RawPacket753, Packet753, PlayerPlayerListHeaderAndFooter, PlayPlayerListHeaderAndFooterSpec,
3532 test_player_player_list_header_and_footer, bench_write_player_player_list_header_and_footer, bench_read_player_player_list_header_and_footer);
3533
3534 packet_test_cases!(RawPacket753, Packet753, PlayNbtQueryResponse, PlayNbtQueryResponseSpec,
3535 test_play_nbt_query_response, bench_write_play_nbt_query_response, bench_read_play_nbt_query_response);
3536
3537 packet_test_cases!(RawPacket753, Packet753, PlayCollectItem, PlayCollectItemSpec,
3538 test_play_collect_item, bench_write_play_collect_item, bench_read_play_collect_item);
3539
3540 packet_test_cases!(RawPacket753, Packet753, PlayEntityTeleport, PlayEntityTeleportSpec,
3541 test_play_entity_teleport, bench_write_play_entity_teleport, bench_read_play_entity_teleport);
3542
3543 packet_test_cases!(RawPacket753, Packet753, PlayAdvancements, PlayAdvancementsSpec,
3544 test_play_advancements, bench_write_play_advancements, bench_read_play_advancements);
3545
3546 packet_test_cases!(RawPacket753, Packet753, PlayEntityProperties, PlayEntityPropertiesSpec,
3547 test_play_entity_properties, bench_write_play_entity_properties, bench_read_play_entity_properties);
3548
3549 packet_test_cases!(RawPacket753, Packet753, PlayEntityEffect, PlayEntityEffectSpec,
3550 test_play_entity_effect, bench_write_play_entity_effect, bench_read_play_entity_effect);
3551
3552 packet_test_cases!(RawPacket753, Packet753, PlayDeclareRecipes, PlayDeclareRecipesSpec,
3553 test_play_declare_recipes, bench_write_play_declare_recipes, bench_read_play_declare_recipes);
3554
3555 packet_test_cases!(RawPacket753, Packet753, PlayTags, PlayTagsSpec,
3556 test_play_tags, bench_write_play_tags, bench_read_play_tags);
3557
3558 packet_test_cases!(RawPacket753, Packet753, PlayTeleportConfirm, PlayTeleportConfirmSpec,
3559 test_play_teleport_confirm, bench_write_play_teleport_confirm, bench_read_play_teleport_confirm);
3560
3561 packet_test_cases!(RawPacket753, Packet753, PlayQueryBlockNbt, PlayQueryBlockNbtSpec,
3562 test_play_query_block_nbt, bench_write_play_query_block_nbt, bench_read_play_query_block_nbt);
3563
3564 packet_test_cases!(RawPacket753, Packet753, PlayQueryEntityNbt, PlayQueryEntityNbtSpec,
3565 test_play_query_entity_nbt, bench_write_play_query_entity_nbt, bench_read_play_query_entity_nbt);
3566
3567 packet_test_cases!(RawPacket753, Packet753, PlaySetDifficulty, PlaySetDifficultySpec,
3568 test_play_set_difficulty, bench_write_play_set_difficulty, bench_read_play_set_difficulty);
3569
3570 packet_test_cases!(RawPacket753, Packet753, PlayClientChatMessage, PlayClientChatMessageSpec,
3571 test_play_client_chat_message, bench_write_play_client_chat_message, bench_read_play_client_chat_message);
3572
3573 packet_test_cases!(RawPacket753, Packet753, PlayClientStatus, PlayClientStatusSpec,
3574 test_play_client_status, bench_write_play_client_status, bench_read_play_client_status);
3575
3576 packet_test_cases!(RawPacket753, Packet753, PlayClientSettings, PlayClientSettingsSpec,
3577 test_play_client_settings, bench_write_play_client_settings, bench_read_play_client_settings);
3578
3579 packet_test_cases!(RawPacket753, Packet753, PlayClientTabComplete, PlayClientTabCompleteSpec,
3580 test_play_client_tab_complete, bench_write_play_client_tab_complete, bench_read_play_client_tab_complete);
3581
3582 packet_test_cases!(RawPacket753, Packet753, PlayClientWindowConfirmation, PlayClientWindowConfirmationSpec,
3583 test_play_client_window_confirmation, bench_write_play_client_window_confirmation, bench_read_play_client_window_confirmation);
3584
3585 packet_test_cases!(RawPacket753, Packet753, PlayClickWindowButton, PlayClickWindowButtonSpec,
3586 test_play_click_window_button, bench_write_play_click_window_button, bench_read_play_click_window_button);
3587
3588 packet_test_cases!(RawPacket753, Packet753, PlayClickWindow, PlayClickWindowSpec,
3589 test_play_click_window, bench_write_play_click_window, bench_read_play_click_window);
3590
3591 packet_test_cases!(RawPacket753, Packet753, PlayClientCloseWindow, PlayClientCloseWindowSpec,
3592 test_play_client_close_window, bench_write_play_client_close_window, bench_read_play_client_close_window);
3593
3594 packet_test_cases!(RawPacket753, Packet753, PlayClientPluginMessage, PlayClientPluginMessageSpec,
3595 test_play_client_plugin_message, bench_write_play_client_plugin_message, bench_read_play_client_plugin_message);
3596
3597 packet_test_cases!(RawPacket753, Packet753, PlayEditBook, PlayEditBookSpec,
3598 test_play_edit_book, bench_write_play_edit_book, bench_read_play_edit_book);
3599
3600 packet_test_cases!(RawPacket753, Packet753, PlayInteractEntity, PlayInteractEntitySpec,
3601 test_play_interact_entity, bench_write_play_interact_entity, bench_read_play_interact_entity);
3602
3603 packet_test_cases!(RawPacket753, Packet753, PlayGenerateStructure, PlayGenerateStructureSpec,
3604 test_play_generate_structure, bench_write_play_generate_structure, bench_read_play_generate_structure);
3605
3606 packet_test_cases!(RawPacket753, Packet753, PlayClientKeepAlive, PlayClientKeepAliveSpec,
3607 test_play_client_keep_alive, bench_write_play_client_keep_alive, bench_read_play_client_keep_alive);
3608
3609 packet_test_cases!(RawPacket753, Packet753, PlayLockDifficulty, PlayLockDifficultySpec,
3610 test_play_lock_difficulty, bench_write_play_lock_difficulty, bench_read_play_lock_difficulty);
3611
3612 packet_test_cases!(RawPacket753, Packet753, PlayPlayerPosition, PlayPlayerPositionSpec,
3613 test_play_player_position, bench_write_play_player_position, bench_read_play_player_position);
3614
3615 packet_test_cases!(RawPacket753, Packet753, PlayClientPlayerPositionAndRotation, PlayClientPlayerPositionAndRotationSpec,
3616 test_play_client_player_position_and_rotation, bench_write_play_client_player_position_and_rotation, bench_read_play_client_player_position_and_rotation);
3617
3618 packet_test_cases!(RawPacket753, Packet753, PlayPlayerRotation, PlayPlayerRotationSpec,
3619 test_play_player_rotation, bench_write_play_player_rotation, bench_read_play_player_rotation);
3620
3621 packet_test_cases!(RawPacket753, Packet753, PlayPlayerMovement, PlayPlayerMovementSpec,
3622 test_play_player_movement, bench_write_play_player_movement, bench_read_play_player_movement);
3623
3624 packet_test_cases!(RawPacket753, Packet753, PlayClientVehicleMove, PlayClientVehicleMoveSpec,
3625 test_play_client_vehicle_move, bench_write_play_client_vehicle_move, bench_read_play_client_vehicle_move);
3626
3627 packet_test_cases!(RawPacket753, Packet753, PlaySteerBoat, PlaySteerBoatSpec,
3628 test_play_steer_boat, bench_write_play_steer_boat, bench_read_play_steer_boat);
3629
3630 packet_test_cases!(RawPacket753, Packet753, PlayPickItem, PlayPickItemSpec,
3631 test_play_pick_item, bench_write_play_pick_item, bench_read_play_pick_item);
3632
3633 packet_test_cases!(RawPacket753, Packet753, PlayCraftRecipeRequest, PlayCraftRecipeRequestSpec,
3634 test_play_craft_recipe_request, bench_write_play_craft_recipe_request, bench_read_play_craft_recipe_request);
3635
3636 packet_test_cases!(RawPacket753, Packet753, PlayClientPlayerAbilities, PlayClientPlayerAbilitiesSpec,
3637 test_play_client_player_abilities, bench_write_play_client_player_abilities, bench_read_play_client_player_abilities);
3638
3639 packet_test_cases!(RawPacket753, Packet753, PlayPlayerDigging, PlayPlayerDiggingSpec,
3640 test_play_player_digging, bench_write_play_player_digging, bench_read_play_player_digging);
3641
3642 packet_test_cases!(RawPacket753, Packet753, PlayEntityAction, PlayEntityActionSpec,
3643 test_play_entity_action, bench_write_play_entity_action, bench_read_play_entity_action);
3644
3645 packet_test_cases!(RawPacket753, Packet753, PlaySteerVehicle, PlaySteerVehicleSpec,
3646 test_play_steer_vehicle, bench_write_play_steer_vehicle, bench_read_play_steer_vehicle);
3647
3648 packet_test_cases!(RawPacket753, Packet753, PlaySetDisplayedRecipe, PlaySetDisplayedRecipeSpec,
3649 test_play_set_displayed_recipe, bench_write_play_set_displayed_recipe, bench_read_play_set_displayed_recipe);
3650
3651 packet_test_cases!(RawPacket753, Packet753, PlaySetRecipeBookState, PlaySetRecipeBookStateSpec,
3652 test_play_set_recipe_book_state, bench_write_play_set_recipe_book_state, bench_read_play_set_recipe_book_state);
3653
3654 packet_test_cases!(RawPacket753, Packet753, PlayNameItem, PlayNameItemSpec,
3655 test_play_name_item, bench_write_play_name_item, bench_read_play_name_item);
3656
3657 packet_test_cases!(RawPacket753, Packet753, PlayResourcePackStatus, PlayResourcePackStatusSpec,
3658 test_play_resource_pack_status, bench_write_play_resource_pack_status, bench_read_play_resource_pack_status);
3659
3660 packet_test_cases!(RawPacket753, Packet753, PlayAdvancementTab, PlayAdvancementTabSpec,
3661 test_play_advancement_tab, bench_write_play_advancement_tab, bench_read_play_advancement_tab);
3662
3663 packet_test_cases!(RawPacket753, Packet753, PlaySelectTrade, PlaySelectTradeSpec,
3664 test_play_select_trade, bench_write_play_select_trade, bench_read_play_select_trade);
3665
3666 packet_test_cases!(RawPacket753, Packet753, PlaySetBeaconEffect, PlaySetBeaconEffectSpec,
3667 test_play_set_beacon_effect, bench_write_play_set_beacon_effect, bench_read_play_set_beacon_effect);
3668
3669 packet_test_cases!(RawPacket753, Packet753, PlayClientHeldItemChange, PlayClientHeldItemChangeSpec,
3670 test_play_client_held_item_change, bench_write_play_client_held_item_change, bench_read_play_client_held_item_change);
3671
3672 packet_test_cases!(RawPacket753, Packet753, PlayUpdateCommandBlock, PlayUpdateCommandBlockSpec,
3673 test_play_update_command_block, bench_write_play_update_command_block, bench_read_play_update_command_block);
3674
3675 packet_test_cases!(RawPacket753, Packet753, PlayUpdateCommandBlockMinecart, PlayUpdateCommandBlockMinecartSpec,
3676 test_play_update_command_block_minecart, bench_write_play_update_command_block_minecart, bench_read_play_update_command_block_minecart);
3677
3678 packet_test_cases!(RawPacket753, Packet753, PlayUpdateJigsawBlock, PlayUpdateJigsawBlockSpec,
3679 test_play_update_jigsaw_block, bench_write_play_update_jigsaw_block, bench_read_play_update_jigsaw_block);
3680
3681 packet_test_cases!(RawPacket753, Packet753, PlayCreativeInventoryAction, PlayCreativeInventoryActionSpec,
3682 test_play_creative_inventory_action, bench_write_play_creative_inventory_action, bench_read_play_creative_inventory_action);
3683
3684 packet_test_cases!(RawPacket753, Packet753, PlayUpdateStructureBlock, PlayUpdateStructureBlockSpec,
3685 test_play_update_structure_block, bench_write_play_update_structure_block, bench_read_play_update_structure_block);
3686
3687 packet_test_cases!(RawPacket753, Packet753, PlayUpdateSign, PlayUpdateSignSpec,
3688 test_play_update_sign, bench_write_play_update_sign, bench_read_play_update_sign);
3689
3690 packet_test_cases!(RawPacket753, Packet753, PlayClientAnimation, PlayClientAnimationSpec,
3691 test_play_client_animation, bench_write_play_client_animation, bench_read_play_client_animation);
3692
3693 packet_test_cases!(RawPacket753, Packet753, PlaySpectate, PlaySpectateSpec,
3694 test_play_spectate, bench_write_play_spectate, bench_read_play_spectate);
3695
3696 packet_test_cases!(RawPacket753, Packet753, PlayBlockPlacement, PlayBlockPlacementSpec,
3697 test_play_block_placement, bench_write_play_block_placement, bench_read_play_block_placement);
3698
3699 packet_test_cases!(RawPacket753, Packet753, PlayUseItem, PlayUseItemSpec,
3700 test_play_use_item, bench_write_play_use_item, bench_read_play_use_item);
3701
3702 #[test]
3705 fn test_generate_test_cases() {
3706 Packet753::describe().packets.iter().map(move |packet| {
3707 let snake_case = to_snake_case(packet.name.clone());
3708 alloc::format!("packet_test_cases!(RawPacket753, Packet753, {}, {},\n test_{}, bench_write_{}, bench_read_{});\n",
3709 packet.name, packet.body_struct, snake_case, snake_case, snake_case).to_owned()
3710 }).for_each(move |line| {
3711 println!("{}", line)
3712 })
3713 }
3714
3715 fn to_snake_case(camel: String) -> String {
3716 let mut parts = Vec::new();
3717 let mut buf = String::new();
3718 for c in camel.chars() {
3719 if !buf.is_empty() && char::is_uppercase(c) {
3720 parts.push(buf);
3721 buf = String::new();
3722 }
3723
3724 buf.push(c.to_ascii_lowercase());
3725 }
3726
3727 if !buf.is_empty() {
3728 parts.push(buf);
3729 }
3730
3731 parts.join("_")
3732 }
3733}