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