# Created from MiNET and gophertunnel docs
# The version below is the latest version this protocol schema was updated for.
# The output protocol.json will be in the folder for the version
!version: 1.16.201

# Some ProtoDef aliases
string: ["pstring",{"countType":"varint"}]
ByteArray: ["buffer",{"countType":"varint"}]
SignedByteArray: ["buffer",{"countType":"zigzag32"}]
LittleString: ["pstring",{"countType":"li32"}]
varint32: varint
bool: native
zigzag32: native
zigzag64: native
uuid: native
byterot: native
MapInfo: native
nbt: native

# load the packet map file
!import: packet_map.yml

#todo: docs
!StartDocs: Packets

# # Login Sequence
# The login process is as follows:
#
# C→S: [Login](#packet_login)
# S→C: [Server To Client Handshake](#packet_server_to_client_handshake)
# C→S: [Client To Server Handshake](#packet_client_to_server_handshake)
# S→C: [Play Status (Login success)](#packet_play_status)
# To spawn, the following packets should be sent, in order, after the ones above:
#
# S→C: [Resource Packs Info](#packet_resource_packs_info)
# C→S: [Resource Pack Client Response](#packet_resource_pack_client_response)
# S→C: [Resource Pack Stack](#packet_resource_pack_stack)
# C→S: [Resource Pack Client Response](#packet_resource_pack_client_response)
# S→C: [Start Game](#packet_start_game)
# S→C: [Creative Content](#packet_creative_content)
# S→C: [Biome Definition List](#packet_biome_definition_list)
# S→C: [Chunks](#packet_level_chunk)
# S→C: [Play Status (Player spawn)](#packet_play_status)
# If there are no resource packs being sent, a Resource Pack Stack can be sent directly
#  after Resource Packs Info to avoid the client responses.


packet_login:
   !id: 0x01
   !bound: server
   # Protocol version (Big Endian!)
   protocol_version: i32
   # The combined size of the `chain` and `client_data`
   payload_size: varint
   # JSON array of JWT data: contains the display name, UUID and XUID
   # It should be signed by the Mojang public key
   chain: LittleString
   # Skin related data
   client_data: LittleString

packet_play_status:
   !id: 0x02
   !bound: client
   status: i32 =>
      # Sent after Login has been successfully decoded and the player has logged in
      0: login_success
      # Displays "Could not connect: Outdated client!"
      1: failed_client
      # Displays "Could not connect: Outdated server!"
      2: failed_spawn
      # Sent after world data to spawn the player
      3: player_spawn
      # Displays "Unable to connect to world. Your school does not have access to this server."
      4: failed_invalid_tenant
      # Displays "The server is not running Minecraft: Education Edition. Failed to connect."
      5: failed_vanilla_edu
      # Displays "The server is running an incompatible edition of Minecraft. Failed to connect."
      6: failed_edu_vanilla
      # Displays "Wow this server is popular! Check back later to see if space opens up. Server Full"
      7: failed_server_full


packet_server_to_client_handshake:
   !id: 0x03
   !bound: client
   # Contains the salt to complete the Diffie-Hellman key exchange
   token: string


# Sent by the client in response to a Server To Client Handshake packet 
# sent by the server. It is the first encrypted packet in the login handshake
# and serves as a confirmation that encryption is correctly initialized client side. 
# It has no fields.
packet_client_to_server_handshake:
   !id: 0x04
   !bound: server

# Sent by the server to disconnect a client.
packet_disconnect:
   !id: 0x05
   !bound: client
   # Specifies if the disconnection screen should be hidden when the client is disconnected, 
   # meaning it will be sent directly to the main menu.
   hide_disconnect_reason: bool
   # An optional message to show when disconnected.
   message: string


packet_resource_packs_info:
   !id: 0x06
   !bound: client
   # If the resource pack requires the client accept it.
   must_accept: bool
   # If scripting is enabled.
   has_scripts: bool
   # A list of behaviour packs that the client needs to download before joining the server. 
   # All of these behaviour packs will be applied together.
   behaviour_packs: BehaviourPackInfos
   # A list of resource packs that the client needs to download before joining the server. 
   # The order of these resource packs is not relevant in this packet. It is however important in the Resource Pack Stack packet.
   texture_packs: TexturePackInfos

packet_resource_pack_stack:
   !id: 0x07
   !bound: client
   # If the resource pack must be accepted for the player to join the server.
   must_accept: bool
   # [inline]
   behavior_packs: ResourcePackIdVersions
   # [inline]
   resource_packs: ResourcePackIdVersions
   game_version: string
   experiments: Experiments # ??? such random fields
   experiments_previously_used: bool

packet_resource_pack_client_response:
   !id: 0x08
   !bound: server
   response_status: u8 =>
      0: none
      1: refused
      2: send_packs
      3: have_all_packs
      4: completed
   # All of the pack IDs.
   resourcepackids: ResourcePackIds

# Sent by the client to the server to send chat messages, and by the server to the client 
# to forward or send messages, which may be chat, popups, tips etc.
## https://github.com/pmmp/PocketMine-MP/blob/a43b46a93cb127f037c879b5d8c29cda251dd60c/src/pocketmine/network/mcpe/protocol/TextPacket.php
## https://github.com/Sandertv/gophertunnel/blob/05ac3f843dd60d48b9ca0ab275cda8d9e85d8c43/minecraft/protocol/packet/text.go
packet_text:
   !id: 0x09
   !bound: both
   # TextType is the type of the text sent. When a client sends this to the server, it should always be
   # TextTypeChat. If the server sends it, it may be one of the other text types above.
   type: u8 =>
      0: raw
      1: chat
      2: translation
      3: popup
      4: jukebox_popup
      5: tip
      6: system
      7: whisper
      8: announcement
      9: json_whisper
      10: json
   # NeedsTranslation specifies if any of the messages need to be translated. It seems that where % is found
   # in translatable text types, these are translated regardless of this bool. Translatable text types
   # include TextTypeTip, TextTypePopup and TextTypeJukeboxPopup.
   needs_translation: bool
   _: type?
      if chat or whisper or announcement:
         source_name: string
         message: string
      if raw or tip or system or json_whisper or json:
         message: string
      if translation or popup or jukebox_popup:
         message: string
         paramaters: string[]varint
   # The XUID of the player who sent this message.
   xuid: string
   # PlatformChatID is an identifier only set for particular platforms when chatting (presumably only for
   # Nintendo Switch). It is otherwise an empty string, and is used to decide which players are able to
   # chat with each other.
   platform_chat_id: string
# For additional information and examples of all the chat types above, see here: https://imgur.com/a/KhcFscg


# Sent by the server to update the current time client-side. The client actually advances time
# client-side by itself, so this packet does not need to be sent each tick. It is merely a means
# of synchronizing time between server and client.
packet_set_time:
   !id: 0x0a
   !bound: client
   # Time is the current time. The time is not limited to 24000 (time of day), but continues 
   # progressing after that.
   time: zigzag32

# Sent by the server to send information about the world the player will be spawned in.
packet_start_game:
   !id: 0x0b
   !bound: client
   # The unique ID of the player. The unique ID is a value that remains consistent across
   # different sessions of the same world, but most unofficial servers simply fill the
   # runtime ID of the entity out for this field.
   entity_id: zigzag64
   # The runtime ID of the player. The runtime ID is unique for each world session, 
   # and entities are generally identified in packets using this runtime ID.
   runtime_entity_id: varint64
   # PlayerGameMode is the game mode the player currently has. It is a value from 0-4, with 0 being
   # survival mode, 1 being creative mode, 2 being adventure mode, 3 being survival spectator and 4 being
   # creative spectator.
   # This field may be set to 5 to make the client fall back to the game mode set in the WorldGameMode
   # field.
   player_gamemode: GameMode
   # The spawn position of the player in the world. In servers this is often the same as the 
   # world's spawn position found below.
   spawn: vec3f
   # The pitch and yaw of the player
   rotation: vec2f
   # The seed used to generate the world. Unlike in Java edition, the seed is a 32bit Integer here.
   seed: zigzag32
   biome_type: li16
   biome_name: string
   # Dimension is the ID of the dimension that the player spawns in. It is a value from 0-2, 
   # with 0 being the overworld, 1 being the nether and 2 being the end.
   dimension: zigzag32
   # Generator is the generator used for the world. It is a value from 0-4, with 0 being old
   # limited worlds, 1 being infinite worlds, 2 being flat worlds, 3 being nether worlds and 
   # 4 being end worlds. A value of 0 will actually make the client stop rendering chunks you 
   # send beyond the world limit.
   generator: zigzag32
   # The world game mode that a player gets when it first spawns in the world. It is shown in the
   # settings and is used if the Player Gamemode is set to 5.
   world_gamemode: GameMode
   # Difficulty is the difficulty of the world. It is a value from 0-3, with 0 being peaceful,
   # 1 being easy, 2 being normal and 3 being hard.
   difficulty: zigzag32
   # The block on which the world spawn of the world. This coordinate has no effect on the place
   # that the client spawns, but it does have an effect on the direction that a compass poInts.
   spawn_position: BlockCoordinates
   # Defines if achievements are disabled in the world. The client crashes if this value is set 
   # to true while the player's or the world's game mode is creative, and it's recommended to simply
   # always set this to false as a server.
   achievements_disabled: bool
   # The time at which the day cycle was locked if the day cycle is disabled using the respective
   # game rule. The client will maIntain this time as Boolean as the day cycle is disabled.
   day_cycle_stop_time: zigzag32
   # Some Minecraft: Education Edition field that specifies what 'region' the world was from, 
   # with 0 being None, 1 being RestOfWorld, and 2 being China. The actual use of this field is unknown.
   edu_offer: zigzag32
   # Specifies if the world has education edition features enabled, such as the blocks or entities
   # specific to education edition.
   edu_features_enabled: bool
   edu_product_uuid: string
   # The level specifying the Intensity of the rain falling. When set to 0, no rain falls at all.
   rain_level: lf32
   lightning_level: lf32
   # The level specifying the Intensity of the thunder. This may actually be set independently
   # from the rain level, meaning dark clouds can be produced without rain.
   has_confirmed_platform_locked_content: bool
   # Specifies if the world is a multi-player game. This should always be set to true for servers.
   is_multiplayer: bool
   # Specifies if LAN broadcast was Intended to be enabled for the world.
   broadcast_to_lan: bool
   # The mode used to broadcast the joined game across XBOX Live.
   xbox_live_broadcast_mode: varint
   # The mode used to broadcast the joined game across the platform.
   platform_broadcast_mode: varint
   # If commands are enabled for the player. It is recommended to always set this to true on the
   # server, as setting it to false means the player cannot, under any circumstance, use a command.
   enable_commands: bool
   # Specifies if the texture pack the world might hold is required, meaning the client was
   #  forced to download it before joining.
   is_texturepacks_required: bool
   # Defines game rules currently active with their respective values. The value of these game
   #  rules may be either 'bool', 'Int32' or 'Float32'. Some game rules are server side only,
   #  and don't necessarily need to be sent to the client.
   gamerules: GameRules
   experiments: Experiments
   experiments_previously_used: bool
   # Specifies if the world had the bonus map setting enabled when generating it.
   # It does not have any effect client-side.
   bonus_chest: bool
   # Specifies if the world has the start with map setting enabled, meaning each
   # joining player obtains a map. This should always be set to false, because the
   # client obtains a map all on its own accord if this is set to true.
   map_enabled: bool
   # The permission level of the player. It is a value from 0-3, with 0 being visitor,
   # 1 being member, 2 being operator and 3 being custom.
   permission_level: zigzag32
   # The radius around the player in which chunks are ticked. Most servers set this value
   # to a fixed number, as it does not necessarily affect anything client-side.
   server_chunk_tick_range: li32
   # Specifies if the texture pack of the world is locked, meaning it cannot be disabled
   # from the world. This is typically set for worlds on the marketplace that have a dedicated
   # texture pack.
   has_locked_behavior_pack: bool
   # Specifies if the texture pack of the world is locked, meaning it cannot be disabled from the
   # world. This is typically set for worlds on the marketplace that have a dedicated texture pack.
   has_locked_resource_pack: bool
   # Specifies if the world from the server was from a locked world template.
   # For servers this should always be set to false.
   is_from_locked_world_template: bool
   msa_gamertags_only: bool
   # Specifies if the world from the server was from a locked world template. 
   # For servers this should always be set to false.
   is_from_world_template: bool
   # Specifies if the world was a template that locks all settings that change properties 
   # above in the settings GUI. It is recommended to set this to true for servers that
   # do not allow things such as setting game rules through the GUI.
   is_world_template_option_locked: bool
   # A hack that Mojang put in place to preserve backwards compatibility with old villagers. 
   # The his never actually read though, so it has no functionality.
   only_spawn_v1_villagers: bool
   # The version of the game from which Vanilla features will be used.
   # The exact function of this field isn't clear.
   game_version: string
   limited_world_width: li32
   limited_world_length: li32
   is_new_nether: bool
   experimental_gameplay_override: bool
   # A base64 encoded world ID that is used to identify the world.
   level_id: string
   # The name of the world that the player is joining. Note that this field shows up
   # above the player list for the rest of the game session, and cannot be changed.
   # Setting the server name to this field is recommended.
   world_name: string
   # A UUID specific to the premium world template that might have been used to
   # generate the world. Servers should always fill out an empty String for this.
   premium_world_template_id: string
   # Specifies if the world was a trial world, meaning features are limited and there 
   # is a time limit on the world.
   is_trial: bool
   # Specifies if the client or server is authoritative over the movement of the player, 
   # meaning it controls the movement of it. 
   ## https://github.com/pmmp/PocketMine-MP/blob/a43b46a93cb127f037c879b5d8c29cda251dd60c/src/pocketmine/network/mcpe/protocol/types/PlayerMovementType.php#L26
   movement_authority: zigzag32 =>
      0: client
      1: server
      # PlayerAuthInputPacket + a bunch of junk that solves a nonexisting problem
      2: server_v2_rewind
   # The total time in ticks that has elapsed since the start of the world.
   current_tick: li64
   # The seed used to seed the random used to produce enchantments in the enchantment table. 
   # Note that the exact correct random implementation must be used to produce the correct
   # results both client- and server-side.
   enchantment_seed: zigzag32

   ## This is not sent anymore in protocol versions > 419 (Bedrock Edition v1.16.100)
   ## A list of all blocks registered on the server.
   block_palette: BlockPalette
   # A list of all items with their legacy IDs which are available in the game.
   # Failing to send any of the items that are in the game will crash mobile clients.
   itemstates: Itemstates
   # A unique ID specifying the multi-player session of the player. 
   # A random UUID should be filled out for this field.
   multiplayer_correlation_id: string
   server_authoritative_inventory: bool


packet_add_player:
   !id: 0x0c
   !bound: client
   # UUID is the UUID of the player. It is the same UUID that the client sent in the
   # Login packet at the start of the session. A player with this UUID must exist
   # in the player list (built up using the Player List packet) for it to show up in-game.
   uuid: uuid
   # Username is the name of the player. This username is the username that will be
   # set as the initial name tag of the player.
   username: string
   # The unique ID of the player. The unique ID is a value that remains consistent
   #  across different sessions of the same world, but most unoffical servers simply 
   # fill the runtime ID of the player out for this field.
   entity_id_self: zigzag64
   # The runtime ID of the player. The runtime ID is unique for each world session,
   # and entities are generally identified in packets using this runtime ID.
   runtime_entity_id: varint
   # An identifier only set for particular platforms when chatting (presumably only for 
   # Nintendo Switch). It is otherwise an empty string, and is used to decide which players
   # are able to chat with each other.
   platform_chat_id: string
   x: lf32
   y: lf32
   z: lf32
   speed_x: lf32
   speed_y: lf32
   speed_z: lf32
   pitch: lf32
   yaw: lf32
   head_yaw: lf32
   held_item: Item
   metadata: MetadataDictionary
   flags: varint
   command_permission: varint
   action_permissions: varint
   permission_level: varint
   custom_stored_permissions: varint
   user_id: li64
   links: Links
   device_id: string
   device_os: li32

packet_add_entity:
   !id: 0x0d
   !bound: client
   entity_id_self: zigzag64
   runtime_entity_id: varint
   entity_type: string
   x: lf32
   y: lf32
   z: lf32
   speed_x: lf32
   speed_y: lf32
   speed_z: lf32
   pitch: lf32
   yaw: lf32
   head_yaw: lf32
   attributes: EntityAttributes
   metadata: MetadataDictionary
   links: Links

packet_remove_entity:
   !id: 0x0e
   !bound: client
   entity_id_self: zigzag64

packet_add_item_entity:
   !id: 0x0f
   !bound: client
   entity_id_self: zigzag64
   runtime_entity_id: varint
   item: Item
   x: lf32
   y: lf32
   z: lf32
   speed_x: lf32
   speed_y: lf32
   speed_z: lf32
   metadata: MetadataDictionary
   is_from_fishing: bool

packet_take_item_entity:
   !id: 0x11
   !bound: client
   runtime_entity_id: varint
   target: varint

packet_move_entity:
   !id: 0x12
   !bound: both
   runtime_entity_id: varint
   flags: u8
   position: vec3f
   rotation: Rotation

# MovePlayer is sent by players to send their movement to the server, and by the server to update the
# movement of player entities to other players.
packet_move_player:
   !id: 0x13
   !bound: both
   # EntityRuntimeID is the runtime ID of the player. The runtime ID is unique for each world session, and
   # entities are generally identified in packets using this runtime ID.
   runtime_id: varint
   # Position is the position to spawn the player on. If the player is on a distance that the viewer cannot
   # see it, the player will still show up if the viewer moves closer.
   position: vec3f
   # Pitch is the vertical rotation of the player. Facing straight forward yields a pitch of 0. Pitch is
   # measured in degrees.
   pitch: lf32
   # Yaw is the horizontal rotation of the player. Yaw is also measured in degrees
   yaw: lf32
   # HeadYaw is the same as Yaw, except that it applies specifically to the head of the player. A different
   # value for HeadYaw than Yaw means that the player will have its head turned
   head_yaw: lf32
   # Mode is the mode of the movement. It specifies the way the player's movement should be shown to other
   # players. It is one of the constants below.
   mode: u8 =>
      0: normal
      1: reset
      2: teleport
      3: rotation
   # OnGround specifies if the player is considered on the ground. Note that proxies or hacked clients could
   # fake this to always be true, so it should not be taken for granted.
   on_ground: bool
   # RiddenEntityRuntimeID is the runtime ID of the entity that the player might currently be riding. If not
   # riding, this should be left 0.
   ridden_runtime_id: varint
   teleport: mode ?
      if teleport:
         # TeleportCause is written only if Mode is MoveModeTeleport. It specifies the cause of the teleportation,
         # which is one of the constants above.
         cause: li32 =>
            0: unknown
            1: projectile
            2: chorus_fruit
            3: command
            4: behavior
         # TeleportSourceEntityType is the entity type that caused the teleportation, for example an ender pearl.
         # TODO: is this still a integer and not a string?
         source_entity_type: LegacyEntityType
   tick: varint64

packet_rider_jump:
   !id: 0x14
   !bound: both
   jump_strength: zigzag32

packet_update_block:
   !id: 0x15
   !bound: client
   coordinates: BlockCoordinates
   block_runtime_id: varint
   block_priority: varint
   storage: varint

packet_add_painting:
   !id: 0x16
   !bound: client
   entity_id_self: zigzag64
   runtime_entity_id: varint
   coordinates: BlockCoordinates
   direction: zigzag32
   title: string

# TickSync is sent by the client and the server to maintain a synchronized, server-authoritative tick between
# the client and the server. The client sends this packet first, and the server should reply with another one
# of these packets, including the response time.
packet_tick_sync:
   !id: 0x17
   !bound: both
   # ClientRequestTimestamp is the timestamp on which the client sent this packet to the server. The server
   # should fill out that same value when replying.
   # The ClientRequestTimestamp is always 0
   request_time: li64
   # ServerReceptionTimestamp is the timestamp on which the server received the packet sent by the client.
   # When the packet is sent by the client, this value is 0.
   # ServerReceptionTimestamp is generally the current tick of the server. It isn't an actual timestamp, as
   # the field implies
   response_time: li64

packet_level_sound_event_old:
   !id: 0x18
   !bound: both
   sound_id: u8
   position: vec3f
   block_id: zigzag32
   entity_type: zigzag32
   is_baby_mob: bool
   is_global: bool

packet_level_event:
   !id: 0x19
   !bound: client
   event: zigzag32 =>
      1000: sound_click  
      1001: sound_click_fail  
      1002: sound_shoot  
      1003: sound_door  
      1004: sound_fizz  
      1005: sound_ignite  
      1007: sound_ghast  
      1008: sound_ghast_shoot  
      1009: sound_blaze_shoot  
      1010: sound_door_bump  
      1012: sound_door_crash  
      1018: sound_enderman_teleport  
      1020: sound_anvil_break  
      1021: sound_anvil_use  
      1022: sound_anvil_fall  
      1030: sound_pop  
      1032: sound_portal  
      1040: sound_itemframe_add_item  
      1041: sound_itemframe_remove  
      1042: sound_itemframe_place  
      1043: sound_itemframe_remove_item  
      1044: sound_itemframe_rotate_item  
      1050: sound_camera  
      1051: sound_orb  
      1052: sound_totem  
      1060: sound_armor_stand_break  
      1061: sound_armor_stand_hit  
      1062: sound_armor_stand_fall  
      1063: sound_armor_stand_place  
      2000: particle_shoot   #TODO: check 2000-2017
      2001: particle_destroy  
      2002: particle_splash  
      2003: particle_eye_despawn  
      2004: particle_spawn  
      2006: guardian_curse  
      2008: particle_block_force_field  
      2009: particle_projectile_hit  
      2013: particle_enderman_teleport  
      2014: particle_punch_block  
      3001: start_rain  
      3002: start_thunder  
      3003: stop_rain  
      3004: stop_thunder  
      3005: pause_game   #data: 1 to pause, 0 to resume
      3006: pause_game_no_screen   #data: 1 to pause, 0 to resume - same effect as normal pause but without screen
      3007: set_game_speed   #x coordinate of pos = scale factor (default 1.0)
      3500: redstone_trigger  
      3501: cauldron_explode  
      3502: cauldron_dye_armor  
      3503: cauldron_clean_armor  
      3504: cauldron_fill_potion  
      3505: cauldron_take_potion  
      3506: cauldron_fill_water  
      3507: cauldron_take_water  
      3508: cauldron_add_dye  
      3509: cauldron_clean_banner  
      3600: block_start_break  
      3601: block_stop_break  
      4000: set_data  
      9800: players_sleeping  
      0x4000: add_particle_mask
   position: vec3f
   data: zigzag32

packet_block_event:
   !id: 0x1a
   !bound: client
   # Position is the position of the block that an event occurred at.
   position: BlockCoordinates
   # EventType is the type of the block event. 
   # The event type decides the way the event data that follows is used
   type: zigzag32 =>
      0: sound
      1: change_state
   # EventData holds event type specific data. For chests for example,
   # opening the chest means the data must be 1
   data: zigzag32

packet_entity_event:
   !id: 0x1b
   !bound: both
   runtime_entity_id: varint
   event_id: u8 =>
      1: jump 
      2: hurt_animation 
      3: death_animation 
      4: arm_swing 
      5: stop_attack 
      6: tame_fail 
      7: tame_success 
      8: shake_wet 
      9: use_item 
      10: eat_grass_animation 
      11: fish_hook_bubble 
      12: fish_hook_position 
      13: fish_hook_hook 
      14: fish_hook_tease 
      15: squid_ink_cloud 
      16: zombie_villager_cure 
      18: respawn 
      19: iron_golem_offer_flower 
      20: iron_golem_withdraw_flower 
      21: love_particles  #breeding
      22: villager_angry 
      23: villager_happy 
      24: witch_spell_particles 
      25: firework_particles 
      26: in_love_particles 
      27: silverfish_spawn_animation 
      28: guardian_attack 
      29: witch_drink_potion 
      30: witch_throw_potion 
      31: minecart_tnt_prime_fuse 
      32: creeper_prime_fuse 
      33: air_supply_expired 
      34: player_add_xp_levels 
      35: elder_guardian_curse 
      36: agent_arm_swing 
      37: ender_dragon_death 
      38: dust_particles  #not sure what this is
      39: arrow_shake 

      57: eating_item 

      60: baby_animal_feed  #green particles, like bonemeal on crops
      61: death_smoke_cloud 
      62: complete_trade 
      63: remove_leash  #data 1 = cut leash

      65: consume_totem 
      66: player_check_treasure_hunter_achievement  #mojang...
      67: entity_spawn  #used for MinecraftEventing stuff, not needed
      68: dragon_puke  #they call this puke particles
      69: item_entity_merge 
      70: start_swim 
      71: balloon_pop 
      72: treasure_hunt 
      73: agent_summon 
      74: charged_crossbow 
      75: fall 
   data: zigzag32

packet_mob_effect:
   !id: 0x1c
   !bound: client
   runtime_entity_id: varint
   event_id: u8
   effect_id: zigzag32
   amplifier: zigzag32
   particles: bool
   duration: zigzag32

packet_update_attributes:
   !id: 0x1d
   !bound: client
   runtime_entity_id: varint64
   attributes: PlayerAttributes
   tick: varint64

packet_inventory_transaction:
   !id: 0x1e
   !bound: both
   transaction: Transaction

packet_mob_equipment:
   !id: 0x1f
   !bound: both
   runtime_entity_id: varint
   item: Item
   slot: u8
   selected_slot: u8
   windows_id: WindowID

packet_mob_armor_equipment:
   !id: 0x20
   !bound: both
   runtime_entity_id: varint
   helmet: Item
   chestplate: Item
   leggings: Item
   boots: Item

# Interact is sent by the client when it interacts with another entity in some way. It used to be used for
# normal entity and block interaction, but this is no longer the case now.
packet_interact:
   !id: 0x21
   !bound: both
   # Action type is the ID of the action that was executed by the player. It is one of the constants that
   # may be found above.
   action_id: u8 =>
      3: leave_vehicle
      4: mouse_over_entity
      6: open_inventory
   # TargetEntityRuntimeID is the runtime ID of the entity that the player interacted with. This is empty
   # for the InteractActionOpenInventory action type.
   target_runtime_entity_id: varint
   # Position associated with the ActionType above. For the InteractActionMouseOverEntity, this is the
   # position relative to the entity moused over over which the player hovered with its mouse/touch. For the
   # InteractActionLeaveVehicle, this is the position that the player spawns at after leaving the vehicle.
   position: action_id ?
      if mouse_over_entity or leave_vehicle: vec3f

packet_block_pick_request:
   !id: 0x22
   !bound: server
   x: zigzag32
   y: zigzag32
   z: zigzag32
   add_user_data: bool
   selected_slot: u8

packet_entity_pick_request:
   !id: 0x23
   !bound: server
   runtime_entity_id: lu64
   selected_slot: u8

# PlayerAction is sent by the client when it executes any action, for example starting to sprint, swim,
# starting the breaking of a block, dropping an item, etc.
packet_player_action:
   !id: 0x24
   !bound: server
   # EntityRuntimeID is the runtime ID of the player. The runtime ID is unique for each world session, and
   # entities are generally identified in packets using this runtime ID.
   runtime_entity_id: varint
   # ActionType is the ID of the action that was executed by the player. It is one of the constants that may
   # be found above.
   action: zigzag32 =>
      0: start_break
      1: abort_break
      2: stop_break
      3: get_updated_block
      4: drop_item
      5: start_sleeping
      6: stop_sleeping
      7: respawn
      8: jump
      9: start_sprint
      10: stop_sprint
      11: start_sneak
      12: stop_sneak
      13: creative_player_destroy_block
      # sent when spawning in a different dimension to tell the server we spawned
      14: dimension_change_ack
      15: start_glide
      16: stop_glide
      17: build_denied
      18: continue_break
      19: change_skin
      # no longer used
      20: set_enchatnment_seed
      21: swimming
      22: stop_swimming
      23: start_spin_attack
      24: stop_spin_attack
      25: ineract_block
   # BlockPosition is the position of the target block, if the action with the ActionType set concerned a
   # block. If that is not the case, the block position will be zero.
   position: BlockCoordinates
   # BlockFace is the face of the target block that was touched. If the action with the ActionType set
   # concerned a block. If not, the face is always 0.
   face: zigzag32

packet_hurt_armor:
   !id: 0x26
   !bound: client
   health: zigzag32

packet_set_entity_data:
   !id: 0x27
   !bound: both
   runtime_entity_id: varint
   metadata: MetadataDictionary
   tick: varint

packet_set_entity_motion:
   !id: 0x28
   !bound: both
   runtime_entity_id: varint
   velocity: vec3f

# SetActorLink is sent by the server to initiate an entity link client-side, meaning one entity will start
# riding another.
packet_set_entity_link:
   !id: 0x29
   !bound: client
   link: Link

packet_set_health:
   !id: 0x2a
   !bound: client
   health: zigzag32

packet_set_spawn_position:
   !id: 0x2b
   !bound: client
   spawn_type: zigzag32 =>
      0: player
      1: world
   player_position: BlockCoordinates
   dimension: zigzag32
   world_position: BlockCoordinates

packet_animate:
   !id: 0x2c
   !bound: both
   action_id: zigzag32
   runtime_entity_id: varint

packet_respawn:
   !id: 0x2d
   !bound: both
   x: lf32
   y: lf32
   z: lf32
   state: u8
   runtime_entity_id: varint

# ContainerOpen is sent by the server to open a container client-side. This container must be physically
# present in the world, for the packet to have any effect. Unlike Java Edition, Bedrock Edition requires that
# chests for example must be present and in range to open its inventory.
packet_container_open:
   !id: 0x2e
   !bound: client
   # WindowID is the ID representing the window that is being opened. It may be used later to close the
   # container using a ContainerClose packet.
   window_id: u8
   # ContainerType is the type ID of the container that is being opened when opening the container at the
   # position of the packet. It depends on the block/entity, and could, for example, be the window type of
   # a chest or a hopper, but also a horse inventory.
   window_type: WindowType
   # ContainerPosition is the position of the container opened. The position must point to a block entity
   # that actually has a container. If that is not the case, the window will not be opened and the packet
   # will be ignored, if a valid ContainerEntityUniqueID has not also been provided.
   coordinates: BlockCoordinates
   # ContainerEntityUniqueID is the unique ID of the entity container that was opened. It is only used if
   # the ContainerType is one that points to an entity, for example a horse.
   runtime_entity_id: zigzag64

# ContainerClose is sent by the server to close a container the player currently has opened, which was opened
# using the ContainerOpen packet, or by the client to tell the server it closed a particular container, such
# as the crafting grid.
packet_container_close:
   !id: 0x2f
   !bound: both
   # WindowID is the ID representing the window of the container that should be closed. It must be equal to
   # the one sent in the ContainerOpen packet to close the designated window.
   window_id: u8
   # ServerSide determines whether or not the container was force-closed by the server. If this value is
   # not set correctly, the client may ignore the packet and respond with a PacketViolationWarning.
   server: bool

# PlayerHotBar is sent by the server to the client. It used to be used to link hot bar slots of the player to
# actual slots in the inventory, but as of 1.2, this was changed and hot bar slots are no longer a free
# floating part of the inventory.
# Since 1.2, the packet has been re-purposed, but its new functionality is not clear.
packet_player_hotbar:
   !id: 0x30
   !bound: both
   selected_slot: varint
   window_id: WindowID
   select_slot: bool

# InventoryContent is sent by the server to update the full content of a particular inventory. It is usually
# sent for the main inventory of the player, but also works for other inventories that are currently opened
# by the player.
packet_inventory_content:
   !id: 0x31
   !bound: both
   # WindowID is the ID that identifies one of the windows that the client currently has opened, or one of
   # the consistent windows such as the main inventory.
   inventory_id: varint
   # Content is the new content of the inventory. The length of this slice must be equal to the full size of
   # the inventory window updated.
   input: ItemStacks

# InventorySlot is sent by the server to update a single slot in one of the inventory windows that the client
# currently has opened. Usually this is the main inventory, but it may also be the off hand or, for example,
# a chest inventory.
packet_inventory_slot:
   !id: 0x32
   !bound: both
   # WindowID is the ID of the window that the packet modifies. It must point to one of the windows that the
   # client currently has opened.
   window_id: varint
   # Slot is the index of the slot that the packet modifies. The new item will be set to the slot at this
   # index.
   slot: varint
   # NewItem is the item to be put in the slot at Slot. It will overwrite any item that may currently
   # be present in that slot.
   item: ItemStack

# ContainerSetData is sent by the server to update specific data of a single container, meaning a block such
# as a furnace or a brewing stand. This data is usually used by the client to display certain features
# client-side.
packet_container_set_data:
   !id: 0x33
   !bound: client
   # WindowID is the ID of the window that should have its data set. The player must have a window open with
   # the window ID passed, or nothing will happen.
   window_id: WindowID
   # Key is the key of the property. It is one of the constants that can be found above. Multiple properties
   # share the same key, but the functionality depends on the type of the container that the data is set to.
   property: zigzag32
   # Value is the value of the property. Its use differs per property. 
   value: zigzag32

packet_crafting_data:
   !id: 0x34
   !bound: client
   recipes: Recipes
   potion_type_recipes: PotionTypeRecipes
   potion_container_recipes: PotionContainerChangeRecipes
   is_clean: bool

# CraftingEvent is sent by the client when it crafts a particular item. Note that this packet may be fully
# ignored, as the InventoryTransaction packet provides all the information required.
packet_crafting_event:
   !id: 0x35
   !bound: both
   # WindowID is the ID representing the window that the player crafted in.
   window_id: WindowID
   # CraftingType is a type that indicates the way the crafting was done, for example if a crafting table
   # was used.
   recipe_type: zigzag32 =>
      0: inventory
      1: crafting
      2: workbench
   # RecipeUUID is the UUID of the recipe that was crafted. It points to the UUID of the recipe that was
   # sent earlier in the CraftingData packet.
   recipe_id: uuid
   # Input is a list of items that the player put into the recipe so that it could create the Output items.
   # These items are consumed in the process.
   input: Item[]varint
   # Output is a list of items that were obtained as a result of crafting the recipe.
   result: Item[]varint


packet_gui_data_pick_item:
   !id: 0x36
   !bound: client

# AdventureSettings is sent by the server to update game-play related features, in particular permissions to
# access these features for the client. It includes allowing the player to fly, build and mine, and attack
# entities. Most of these flags should be checked server-side instead of using this packet only.
# The client may also send this packet to the server when it updates one of these settings through the
# in-game settings interface. The server should verify if the player actually has permission to update those
# settings.
packet_adventure_settings:
   !id: 0x37
   !bound: both
   # Flags is a set of flags that specify certain properties of the player, such as whether or not it can
   # fly and/or move through blocks. It is one of the AdventureFlag constants above.
   flags: AdventureFlags
   # CommandPermissionLevel is a permission level that specifies the kind of commands that the player is
   # allowed to use.
   command_permission: varint32 =>
      0: normal
      1: operator
      2: host
      3: automation
      4: admin
   # ActionPermissions is, much like Flags, a set of flags that specify actions that the player is allowed
   # to undertake, such as whether it is allowed to edit blocks, open doors etc. It is a combination of the
   # ActionPermission constants above.
   action_permissions: ActionPermissions
   # PermissionLevel is the permission level of the player as it shows up in the player list built up using
   # the PlayerList packet. It is one of the PermissionLevel constants above.
   permission_level: varint =>
      0: visitor
      1: member
      2: operator
      3: custom
   # Custom permissions
   custom_stored_permissions: varint
   # PlayerUniqueID is a unique identifier of the player. It appears it is not required to fill this field
   # out with a correct value. Simply writing 0 seems to work.
   user_id: li64

AdventureFlags: [ "bitflags",
   {
      "type": "varint",
      "flags": {
         "world_immutable": 1,
         "no_pvp": 2,
         "auto_jump": 0x20,
         "allow_flight": 0x40,
         "no_clip": 0x80,
         "world_builder": 0x100,
         "flying": 0x200,
         "muted": 0x400
      }
   }
]

ActionPermissions: [ "bitflags",
   {
      "type": "varint",
      "flags": {
         "build_and_mine": 0x10001,
         "doors_and_switches": 0x10002,
         "open_containers": 0x10004,
         "attack_players": 0x10008,
         "attack_mobs": 0x10010,
         "operator": 0x10020,
         "teleport": 0x10080,
      }
   }
]

packet_block_entity_data:
   !id: 0x38
   !bound: both
   position: BlockCoordinates
   nbt: nbt

packet_player_input:
   !id: 0x39
   !bound: server
   motion_x: lf32
   motion_z: lf32
   jumping: bool
   sneaking: bool


# LevelChunk is sent by the server to provide the client with a chunk of a world data (16xYx16 blocks).
# Typically a certain amount of chunks is sent to the client before sending it the spawn PlayStatus packet,
# so that the client spawns in a loaded world.
packet_level_chunk:
   !id: 0x3a
   !bound: client
   # ChunkX is the X coordinate of the chunk sent. (To translate a block's X to a chunk's X: x >> 4)
   x: zigzag32
   # ChunkZ is the Z coordinate of the chunk sent. (To translate a block's Z to a chunk's Z: z >> 4)
   z: zigzag32
   # SubChunkCount is the amount of sub chunks that are part of the chunk sent. Depending on if the cache
   # is enabled, a list of blob hashes will be sent, or, if disabled, the sub chunk data.
   sub_chunk_count: varint
   # CacheEnabled specifies if the client blob cache should be enabled. This system is based on hashes of
   # blobs which are consistent and saved by the client in combination with that blob, so that the server
   # does not have to send the same chunk multiple times. If the client does not yet have a blob with the hash sent,
   # it will send a ClientCacheBlobStatus packet containing the hashes is does not have the data of.
   cache_enabled: bool
   blobs: cache_enabled?
      if true:
         # BlobHashes is a list of all blob hashes used in the chunk. It is composed of SubChunkCount + 1 hashes,
         # with the first SubChunkCount hashes being those of the sub chunks and the last one that of the biome
         # of the chunk.
         # If CacheEnabled is set to false, BlobHashes can be left empty.
         hashes: lu64[]varint
   # RawPayload is a serialised string of chunk data. The data held depends on if CacheEnabled is set to
   # true. If set to false, the payload is composed of multiple sub-chunks, each of which carry a version
   # which indicates the way they are serialised, followed by biomes, border blocks and tile entities. If
   # CacheEnabled is true, the payload consists out of the border blocks and tile entities only.
   payload: ByteArray

packet_set_commands_enabled:
   !id: 0x3b
   !bound: client
   enabled: bool

packet_set_difficulty:
   !id: 0x3c
   !bound: client
   difficulty: varint

packet_change_dimension:
   !id: 0x3d
   !bound: client
   dimension: zigzag32
   position: vec3f
   respawn: bool

# SetPlayerGameType is sent by the server to update the game type (game mode) of the player
packet_set_player_game_type:
   !id: 0x3e
   !bound: both
   # The new gamemode for the player. 
   # Some of these game types require additional flags to be set in an AdventureSettings packet for 
   # the game mode to obtain its full functionality.
   gamemode: GameMode

packet_player_list:
   !id: 0x3f
   !bound: client
   records: PlayerRecords

packet_simple_event:
   !id: 0x40
   !bound: client
   event_type: lu16

# Event is sent by the server to send an event with additional data. It is typically sent to the client for
# telemetry reasons, much like the SimpleEvent packet.
packet_event:
   !id: 0x41
   !bound: client
   runtime_id: varint64
   event_type: zigzag32 =>
      0: achievement_awarded 
      1: entity_interact 
      2: portal_built 
      3: portal_used 
      4: mob_killed 
      5: cauldron_used 
      6: player_death 
      7: boss_killed 
      8: agent_command 
      9: agent_created 
      10: banner_pattern_removed
      11: commaned_executed 
      12: fish_bucketed 
      13: mob_born 
      14: pet_died 
      15: cauldron_block_used 
      16: composter_block_used 
      17: bell_block_used 
   use_player_id: u8
   event_data: restBuffer # Unknown data, TODO: add

packet_spawn_experience_orb:
   !id: 0x42
   !bound: client
   position: vec3f
   count: zigzag32

packet_clientbound_map_item_data:
   !id: 0x43
   !bound: client
   mapinfo: MapInfo

packet_map_info_request:
   !id: 0x44
   !bound: both
   map_id: zigzag64

packet_request_chunk_radius:
   !id: 0x45
   !bound: both
   chunk_radius: zigzag32

packet_chunk_radius_update:
   !id: 0x46
   !bound: client
   chunk_radius: zigzag32

packet_item_frame_drop_item:
   !id: 0x47
   !bound: both
   coordinates: BlockCoordinates

packet_game_rules_changed:
   !id: 0x48
   !bound: client
   rules: GameRules

# Camera is sent by the server to use an Education Edition camera on a player. It produces an image
# client-side.
packet_camera:
   !id: 0x49
   !bound: client
   # CameraEntityUniqueID is the unique ID of the camera entity from which the picture was taken.
   camera_entity_unique_id: zigzag64
   # TargetPlayerUniqueID is the unique ID of the target player. The unique ID is a value that remains
   # consistent across different sessions of the same world, but most servers simply fill the runtime ID of
   # the player out for this field.
   target_player_unique_id: zigzag64

packet_boss_event:
   !id: 0x4a
   !bound: both
   boss_entity_id: zigzag64
   type: varint =>
      # S2C: Shows the boss-bar to the player.
      0: show_bar
      # C2S: Registers a player to a boss fight.
      1: register_player
      # S2C: Removes the boss-bar from the client.
      2: hide_bar
      # C2S: Unregisters a player from a boss fight.
      3: unregister_player
      # S2C: Sets the bar percentage.
      4: set_bar_progress
      # S2C: Sets title of the bar.
      5: set_bar_title
      # S2C: darkens the sky
      6: update_properties
      # S2C: Not implemented :( Intended to alter bar appearance, but these currently produce no effect on client-side whatsoever.
      7: texture
   _: type?
      if register_player or unregister_player:
         player_id: zigzag64
      if show:
         title: string
         bar_progress: lf32
      if update_properties:
         darkness_factor: li16
      if texture:
         color: varint
         overlay: varint
      if set_bar_progress:
         bar_progress: lf32
      if set_bar_title:
         title: string

packet_show_credits:
   !id: 0x4b
   !bound: client
   runtime_entity_id: varint
   status: zigzag32

# This packet sends a list of commands to the client. Commands can have
# arguments, and some of those arguments can have 'enum' values, which are a list of possible
# values for the argument. The serialization is rather complex and involves palettes like chunks.
## In bedrock-protocol, listen to on('client.commands') for a simpler representation
packet_available_commands:
   !id: 0x4c
   !bound: client
   # The length of the enums for all the command paramaters in this packet
   values_len: varint
   # Not read from stream: instead calculated from the `values_len` field
   # If the values_len < 0xff => byte
   # If the values_len < 0xffff => short
   # If the values_len < 0xffffff => int
   _enum_type: '["enum_size_based_on_values_len"]'
   # Here all the enum values for all of the possible commands are stored to one array palette
   enum_values: string[]$values_len
   # Integer paramaters may sometimes have a prefix, such as the XP command:
   # /xp <amount: int> [player: target] <- here, the xp command gives experience points
   # /xp <amount: int>L [player: target] <- here, the xp command gives experience levels
   # This is the palette of suffixes
   suffixes: string[]varint
   # The list of enum objects
   enums: []varint
      # The name of the enum
      name: string
      # The values in the enum 
      values: []varint
         # The indexes to value in the palette
         _: ../_enum_type?
            if byte: u8
            if short: lu16
            if int: lu32
   command_data: []varint
      name: string
      description: string
      flags: u8
      permission_level: u8
      alias: li32
      # The list of overload paramaters for this command
      overloads: []varint
         # Each of the paramaters gets an array of posible overloads
         _: []varint
            # The name of the paramater shown to the user (the `amount` in `/xp <amount: int>`)
            paramater_name: string
            value_type: lu16 =>
               1: int
               2: float
               3: value
               4: wildcard_int
               5: operator
               6: target
               14: file_path
               29: string
               37: position
               41: message
               43: raw_text
               46: json
               53: command
            # In MC, this + prior field are combined to one 32bit bitfield
            enum_type: lu16 =>
               0x10: valid
               0x20: enum
               0x100: suffixed
               0x400: soft_enum
            # Is this paramater required?
            optional: bool
            # Additinal options for this command (thanks macroshaft...)
            options: CommandFlags
   # There are two types of enums: static enums which cannot be changed after sending AvaliableCommands,
   # (unless you resend the whole packet) and 'soft' or 'dynamic' enums like below which is an array
   # that can be updated with the UpdateSoftEnum packet
   dynamic_enums: []varint
      name: string
      values: string[]varint
   enum_constraints: []varint
      value_index: li32
      enum_index: li32
      constraints: []varint
         constraint: u8 =>
            0: cheats_enabled

# ParamOptionCollapseEnum specifies if the enum (only if the Type is actually an enum type. If not,
# setting this to true has no effect) should be collapsed. This means that the options of the enum are
# never shown in the actual usage of the command, but only as auto-completion, like it automatically does
# with enums that have a big amount of options. To illustrate, it can make
# <false|true|yes|no> <$Name: bool>.
CommandFlags: [ "bitfield", [
   { "name": "unused", "size": 6, "signed": false }, # 6 unused upper bits
   { "name": "has_semantic_constraint", "size": 1, "signed": false },
   { "name": "collapse_enum", "size": 1, "signed": false }
]]

# enum_size_based_on_values_len: native

# CommandRequest is sent by the client to request the execution of a server-side command. Although some
# servers support sending commands using the Text packet, this packet is guaranteed to have the correct
# result.
packet_command_request:
   !id: 0x4d
   !bound: server
   # CommandLine is the raw entered command line. The client does no parsing of the command line by itself
   # (unlike it did in the early stages), but lets the server do that.
   command: string
   # Origin holds information about the command sender that will be returnd back in the command response
   origin: CommandOrigin
   # Internal specifies if the command request internal. Setting it to false seems to work and the usage of
   # this field is not known.
   interval: bool


packet_command_block_update:
   !id: 0x4e
   !bound: server
   is_block: bool

packet_command_output:
   !id: 0x4f
   !bound: client
   # CommandOrigin is the data specifying the origin of the command. In other words, the source that the
   # command request was from, such as the player itself or a websocket server. The client forwards the
   # messages in this packet to the right origin, depending on what is sent here.
   origin: CommandOrigin
   # OutputType specifies the type of output that is sent. The OutputType sent by vanilla games appears to
   # be 3, which seems to work.
   output_type: i8
   # SuccessCount is the amount of times that a command was executed successfully as a result of the command
   # that was requested. For servers, this is usually a rather meaningless fields, but for vanilla, this is
   # applicable for commands created with Functions.
   success_count: varint
   # OutputMessages is a list of all output messages that should be sent to the player. Whether they are
   # shown or not, depends on the type of the messages.
   output: []varint
      # Success indicates if the output message was one of a successful command execution. If set to true, the
      # output message is by default coloured white, whereas if set to false, the message is by default
      # coloured red.
      success: bool
      # Message is the message that is sent to the client in the chat window. It may either be simply a
      # message or a translated built-in string like 'commands.tp.success.coordinates', combined with specific
      # parameters below.
      message_id: string
      # Parameters is a list of parameters that serve to supply the message sent with additional information,
      # such as the position that a player was teleported to or the effect that was applied to an entity.
      # These parameters only apply for the Minecraft built-in command output.
      paramaters: string[]varint


# UpdateTrade is sent by the server to update the trades offered by a villager to a player. It is sent at the
# moment that a player interacts with a villager.
packet_update_trade:
   !id: 0x50
   !bound: client
   # WindowID is the ID that identifies the trading window that the client currently has opened.
   window_id: u8
   # WindowType is an identifier specifying the type of the window opened. In vanilla, it appears this is
   # always filled out with 15.
   window_type: WindowType
   # Size is the amount of trading options that the villager has.
   size: varint
   # TradeTier is the tier of the villager that the player is trading with. The tier starts at 0 with a
   # first two offers being available, after which two additional offers are unlocked each time the tier
   # becomes one higher.
   trade_tier: varint
   # VillagerUniqueID is the unique ID of the villager entity that the player is trading with. The
   # TradeTier sent above applies to this villager.
   villager_unique_id: varint64
   # EntityUniqueID is the unique ID of the entity (usually a player) for which the trades are updated. The
   # updated trades may apply only to this entity.
   entity_unique_id: varint64
   # DisplayName is the name displayed at the top of the trading UI. It is usually used to represent the
   # profession of the villager in the UI.
   display_name: string
   # NewTradeUI specifies if the villager should be using the new trade UI (The one added in 1.11.) rather
   # than the old one. This should usually be set to true.
   new_trading_ui: bool
   # Trading based on Minecraft economy - specifies if the prices of the villager's offers are modified by an increase in
   # demand for the item. (A mechanic added in 1.11.) Buying more of the same item will increase the price
   # of that particular item.
   # https://minecraft.gamepedia.com/Trading#Economics
   economic_trades: bool
   # NBT serialised compound of offers that the villager has.
   offers: nbt

# UpdateEquip is sent by the server to the client upon opening a horse inventory. It is used to set the
# content of the inventory and specify additional properties, such as the items that are allowed to be put
# in slots of the inventory.
packet_update_equipment:
   !id: 0x51
   !bound: client
   # WindowID is the identifier associated with the window that the UpdateEquip packet concerns. It is the
   # ID sent for the horse inventory that was opened before this packet was sent.
   window_id: u8
   # WindowType is the type of the window that was opened. Generally, this is the type of a horse inventory,
   # as the packet is specifically made for that.
   window_type: WindowType
   # Size is the size of the horse inventory that should be opened. A bigger size does, in fact, change the
   # amount of slots displayed.
   size: u8
   # EntityUniqueID is the unique ID of the entity whose equipment was 'updated' to the player. It is
   # typically the horse entity that had its inventory opened.
   entity_id: zigzag64
   # `inventory` is a network NBT serialised compound holding the content of the inventory of
   # the entity (the equipment) and additional data such as the allowed items for a particular slot, used to
   # make sure only saddles can be put in the saddle slot etc.
   inventory: nbt

packet_resource_pack_data_info:
   !id: 0x52
   !bound: client
   package_id: string
   max_chunk_size: lu32
   chunk_count: lu32
   compressed_package_size: lu64
   hash: ByteArray
   is_premium: bool
   pack_type: u8

packet_resource_pack_chunk_data:
   !id: 0x53
   !bound: client
   package_id: string
   chunk_index: lu32
   progress: lu64
   payload: ByteArray

packet_resource_pack_chunk_request:
   !id: 0x54
   !bound: server
   package_id: string
   chunk_index: lu32

packet_transfer:
   !id: 0x55
   !bound: client
   server_address: string
   port: lu16

packet_play_sound:
   !id: 0x56
   !bound: client
   name: string
   coordinates: BlockCoordinates
   volume: lf32
   pitch: lf32

packet_stop_sound:
   !id: 0x57
   !bound: client
   name: string
   stop_all: bool

packet_set_title:
   !id: 0x58
   !bound: client
   type: zigzag32
   text: string
   fade_in_time: zigzag32
   stay_time: zigzag32
   fade_out_time: zigzag32

packet_add_behavior_tree:
   !id: 0x59
   !bound: client
   behaviortree: string

packet_structure_block_update:
   !id: 0x5a
   !bound: client

packet_show_store_offer:
   !id: 0x5b
   !bound: client
   unknown0: string
   unknown1: bool

packet_purchase_receipt:
   !id: 0x5c
   !bound: server

packet_player_skin:
   !id: 0x5d
   !bound: both
   uuid: uuid
   skin: Skin
   skin_name: string
   old_skin_name: string
   is_verified: bool

packet_sub_client_login:
   !id: 0x5e
   !bound: client

packet_initiate_web_socket_connection:
   !id: 0x5f
   !bound: client
   server: string

packet_set_last_hurt_by:
   !id: 0x60
   !bound: client
   unknown: varint

packet_book_edit:
   !id: 0x61
   !bound: client
   type: u8 =>
      0: replace_page
      1: add_page
      2: delete_page
      3: swap_pages
      4: sign
   slot: u8
   _: type?
      if replace_page or add_page:
         page_number: u8
         text: string
         photo_name: string
      if delete_page:
         page_number: u8
      if swap_pages:
         page1: u8
         page2: u8
      if sign:
         title: string
         author: string
         xuid: string


packet_npc_request:
   !id: 0x62
   !bound: both
   runtime_entity_id: varint
   unknown0: u8
   unknown1: string
   unknown2: u8

packet_photo_transfer:
   !id: 0x63
   !bound: server
   file_name: string
   image_data: string
   unknown2: string

packet_modal_form_request:
   !id: 0x64
   !bound: client
   form_id: varint
   data: string

packet_modal_form_response:
   !id: 0x65
   !bound: server
   form_id: varint
   data: string

packet_server_settings_request:
   !id: 0x66
   !bound: server

packet_server_settings_response:
   !id: 0x67
   !bound: client
   form_id: varint
   data: string

packet_show_profile:
   !id: 0x68
   !bound: client
   xuid: string

# SetDefaultGameType is sent by the client when it toggles the default game type in the settings UI, and is
# sent by the server when it actually changes the default game type, resulting in the toggle being changed
# in the settings UI.
packet_set_default_game_type:
   !id: 0x69
   !bound: client
   # GameType is the new game type that is set. When sent by the client, this is the requested new default
   # game type.
   gamemode: GameMode

packet_remove_objective:
   !id: 0x6a
   !bound: client
   objective_name: string

packet_set_display_objective:
   !id: 0x6b
   !bound: client
   display_slot: string
   objective_name: string
   display_name: string
   criteria_name: string
   sort_order: zigzag32

packet_set_score:
   !id: 0x6c
   !bound: client
   entries: ScoreEntries

packet_lab_table:
   !id: 0x6d
   !bound: both
   useless_byte: u8
   lab_table_x: varint
   lab_table_y: varint
   lab_table_z: varint
   reaction_type: u8

packet_update_block_synced:
   !id: 0x6e
   !bound: client
   coordinates: BlockCoordinates
   block_runtime_id: varint
   block_priority: varint
   data_layer_id: varint
   unknown0: varint
   unknown1: varint

# MoveActorDelta is sent by the server to move an entity. The packet is specifically optimised to save as
# much space as possible, by only writing non-zero fields.
# As of 1.16.100, this packet no longer actually contains any deltas.
packet_move_entity_delta:
   !id: 0x6f
   !bound: client
   # EntityRuntimeID is the runtime ID of the entity that is being moved. The packet works provided a
   # non-player entity with this runtime ID is present.
   runtime_entity_id: varint64
   # Flags is a list of flags that specify what data is in the packet.
   flags: DeltaMoveFlags
   x: flags.has_x?
      if true: lf32
   y: flags.has_y?
      if true: lf32
   z: flags.has_z?
      if true: lf32
   rot_x: flags.has_rot_x?
      if true: u8 # TODO: * implement ByteFloat
   rot_y: flags.has_rot_y?
      if true: u8
   rot_z: flags.has_rot_z?
      if true: u8

DeltaMoveFlags: [ "bitflags",
   {
      "type": "lu16",
      "flags": {
         "has_x": 0x01,
         "has_y": 0x02,
         "has_z": 0x04,
         "has_rot_x": 0x08,
         "has_rot_y": 0x10,
         "has_rot_z": 0x20,
         "on_ground": 0x40,
         "teleport": 0x80,
         "force_move": 0x100
      }
   }
]

packet_set_scoreboard_identity:
   !id: 0x70
   !bound: client
   entries: ScoreboardIdentityEntries

# SetLocalPlayerAsInitialised is sent by the client in response to a PlayStatus packet with the status set
# to spawn. The packet marks the moment at which the client is fully initialised and can receive any packet
# without discarding it.
packet_set_local_player_as_initialized:
   !id: 0x71
   !bound: server
   # EntityRuntimeID is the entity runtime ID the player was assigned earlier in the login sequence in the
   # StartGame packet.
   runtime_entity_id: varint64

packet_update_soft_enum:
   !id: 0x72
   !bound: client

packet_network_stack_latency:
   !id: 0x73
   !bound: both
   timestamp: lu64
   unknown_flag: u8

packet_script_custom_event:
   !id: 0x75
   !bound: both
   event_name: string
   event_data: string

packet_spawn_particle_effect:
   !id: 0x76
   !bound: client
   dimension_id: u8
   entity_id: zigzag64
   position: vec3f
   particle_name: string

packet_available_entity_identifiers:
   !id: 0x77
   !bound: client
   nbt: nbt

packet_level_sound_event_v2:
   !id: 0x78
   !bound: both
   sound_id: u8
   position: vec3f
   block_id: zigzag32
   entity_type: string
   is_baby_mob: bool
   is_global: bool

packet_network_chunk_publisher_update:
   !id: 0x79
   !bound: client
   coordinates: BlockCoordinates
   radius: varint

packet_biome_definition_list:
   !id: 0x7a
   !bound: client
   nbt: nbt

packet_level_sound_event:
   !id: 0x7b
   !bound: both
   sound_id: varint
   position: vec3f
   block_id: zigzag32
   entity_type: string
   is_baby_mob: bool
   is_global: bool

# LevelEventGeneric is sent by the server to send a 'generic' level event to the client. This packet sends an
# NBT serialised object and may for that reason be used for any event holding additional data.
packet_level_event_generic:
   !id: 0x7c
   !bound: client
   # EventID is a unique identifier that identifies the event called. The data that follows has fields in
   # the NBT depending on what event it is.
   event_id: varint
   # SerialisedEventData is a network little endian serialised object of event data, with fields that vary
   # depending on EventID.
   # Unlike many other NBT structures, this data is not actually in a compound but just loosely floating
   # NBT tags. To decode using the nbt package, you would need to append 0x0a00 at the start (compound id
   # and name length) and add 0x00 at the end, to manually wrap it in a compound. Likewise, you would have
   # to remove these bytes when encoding.
   nbt: nbtLoop

# LecternUpdate is sent by the client to update the server on which page was opened in a book on a lectern,
# or if the book should be removed from it.
packet_lectern_update:
   !id: 0x7d
   !bound: client
   # Page is the page number in the book that was opened by the player on the lectern.
   page: u8
   # PageCount is the number of pages that the book opened in the lectern has.
   page_count: u8
   # Position is the position of the lectern that was updated. If no lectern is at the block position,
   # the packet should be ignored.
   position: vec3i
   # DropBook specifies if the book currently set on display in the lectern should be dropped server-side.
   drop_book: bool

packet_video_stream_connect:
   !id: 0x7e
   !bound: client
   server_uri: string
   frame_send_frequency: lf32
   action: u8
   resolution_x: li32
   resolution_y: li32

# This is NOT a Minecraft entity, but an entity in the Entity Component System (ECS)
# for the game engine Minecrat Bedrock uses. Internally, all 'Minecraft entities' are
# known as Actors including in packet names and fields. However, these are irrelevant
# internal details so we don't do the renames in these protocol definitions, for simplicity we just use Entity.
# 
# AddEntity is sent by the server to the client. Its function is not entirely clear: It does not add an
# entity in the sense of an in-game entity, but has to do with the ECS that Minecraft uses.
packet_add_ecs_entity:
   !id: 0x7f
   !bound: client
   # EntityNetworkID is the network ID of the entity that should be added.
   network_id: varint64

# RemoveEntity is sent by the server to the client. Its function is not entirely clear: It does not remove an
# entity in the sense of an in-game entity, but has to do with the ECS that Minecraft uses
packet_remove_ecs_entity:
   !id: 0x80
   !bound: client
   # EntityNetworkID is the network ID of the entity that should be removed.
   network_id: varint64

packet_client_cache_status:
   !id: 0x81
   !bound: both
   enabled: bool

packet_on_screen_texture_animation:
   !id: 0x82
   !bound: client

packet_map_create_locked_copy:
   !id: 0x83
   !bound: client

packet_structure_template_data_export_request:
   !id: 0x84
   !bound: client

packet_structure_template_data_export_response:
   !id: 0x85
   !bound: client

packet_update_block_properties:
   !id: 0x86
   !bound: client
   nbt: nbt

# ClientCacheBlobStatus is part of the blob cache protocol. It is sent by the client to let the server know
# what blobs it needs and which blobs it already has, in an ACK type system.
packet_client_cache_blob_status:
   !id: 0x87
   !bound: client
   # The number of MISSes in this packet
   misses: varint
   # The number of HITs in this packet
   haves: varint
   # A list of blob hashes that the client does not have a blob available for. The server
   # should send the blobs matching these hashes as soon as possible.
   missing: lu64[]$misses
   # A list of hashes that the client does have a cached blob for. Server doesn't need to send.
   have: lu64[]$haves

# ClientCacheMissResponse is part of the blob cache protocol. It is sent by the server in response to a
# ClientCacheBlobStatus packet and contains the blob data of all blobs that the client acknowledged not to
# have yet.
packet_client_cache_miss_response:
   !id: 0x88
   !bound: client
   blobs: Blob[]varint

# EducationSettings is a packet sent by the server to update Minecraft: Education Edition related settings.
# It is unused by the normal base game.
packet_education_settings:
   !id: 0x89
   !bound: client
   # CodeBuilderDefaultURI is the default URI that the code builder is ran on. Using this, a Code Builder
   # program can make code directly affect the server.
   CodeBuilderDefaultURI: string
   # CodeBuilderTitle is the title of the code builder shown when connected to the CodeBuilderDefaultURI.
   CodeBuilderTitle: string
   # CanResizeCodeBuilder specifies if clients connected to the world should be able to resize the code
   # builder when it is opened.
   CanResizeCodeBuilder: bool
   HasOverrideURI: bool
   OverrideURI: HasOverrideURI?
      if true: string
   # HasQuiz specifies if the world has a quiz connected to it.
   HasQuiz: bool

# MultiPlayerSettings is sent by the client to update multi-player related settings server-side and sent back
# to online players by the server.
# The MultiPlayerSettings packet is a Minecraft: Education Edition packet. It has no functionality for the
# base game.
packet_multiplayer_settings:
   !id: 0x8b
   !bound: server
   # ActionType is the action that should be done when this packet is sent. It is one of the constants that
   # may be found above.
   action_type: zigzag32 =>
      0: enable_multiplayer
      1: disable_multiplayer
      2: refresh_join_code

# SettingsCommand is sent by the client when it changes a setting in the settings that results in the issuing
# of a command to the server, such as when Show Coordinates is enabled.
packet_settings_command:
   !id: 0x8c
   !bound: server
   # CommandLine is the full command line that was sent to the server as a result of the setting that the
   # client changed.
   command_line: string
   # SuppressOutput specifies if the client requests the suppressing of the output of the command that was
   # executed. Generally this is set to true, as the client won't need a message to confirm the output of
   # the change.
   suppress_output: bool

# AnvilDamage is sent by the client to request the dealing damage to an anvil. This packet is completely
# pointless and the server should never listen to it.
packet_anvil_damage:
   !id: 0x8d
   !bound: server
   # Damage is the damage that the client requests to be dealt to the anvil.
   damage: u8
   # AnvilPosition is the position in the world that the anvil can be found at.
   position: BlockCoordinates

# CompletedUsingItem is sent by the server to tell the client that it should be done using the item it is
# currently using.
packet_completed_using_item:
   !id: 0x8e
   !bound: client
   # UsedItemID is the item ID of the item that the client completed using. This should typically be the
   # ID of the item held in the hand.
   used_item_id: li16
   # UseMethod is the method of the using of the item that was completed. It is one of the constants that
   # may be found above.
   use_method: li32 =>
      0: equip_armor
      1: eat
      2: attack
      3: consume
      4: throw
      5: shoot
      6: place
      7: fill_bottle
      8: fill_bucket
      9: pour_bucket
      10: use_tool
      11: interact
      12: retrieved
      13: dyed
      14: traded

# NetworkSettings is sent by the server to update a variety of network settings. These settings modify the
# way packets are sent over the network stack.
packet_network_settings:
   !id: 0x8f
   !bound: both
   # CompressionThreshold is the minimum size of a packet that is compressed when sent. If the size of a
   # packet is under this value, it is not compressed.
   # When set to 0, all packets will be left uncompressed.
   compression_threshold: u16


# PlayerAuthInput is sent by the client to allow for server authoritative movement. It is used to synchronise
# the player input with the position server-side.
# The client sends this packet when the ServerAuthoritativeMovementMode field in the StartGame packet is set
# to true, instead of the MovePlayer packet. The client will send this packet once every tick.
packet_player_auth_input:
   !id: 0x90
   !bound: server
   # Pitch that the player reports it has.
   pitch: lf32
   # Yaw that player reports it has.
   yaw: lf32
   # Position holds the position that the player reports it has.
   position: vec3f
   # MoveVector is a Vec2 that specifies the direction in which the player moved, as a combination of X/Z
   # values which are created using the WASD/controller stick state.
   move_vector: vec2f
   # HeadYaw is the horizontal rotation of the head that the player reports it has.
   head_yaw: lf32
   # InputData is a combination of bit flags that together specify the way the player moved last tick. It
   # is a combination of the flags above.
   input_data: InputFlag
   # InputMode specifies the way that the client inputs data to the screen. It is one of the constants that
   # may be found above.
   input_mode: varint =>
      0: mouse
      1: touch
      2: game_pad
      3: motion_controller
   # PlayMode specifies the way that the player is playing. The values it holds, which are rather random,
   # may be found above.
   play_mode: varint =>
      0: normal
      1: teaser
      2: screen
      3: viewer
      4: reality
      5: placement
      6: living_room
      7: exit_level
      8: exit_level_living_room
      9: num_modes
   # GazeDirection is the direction in which the player is gazing, when the PlayMode is PlayModeReality: In
   # other words, when the player is playing in virtual reality.
   gaze_direction: play_mode ?
      if reality: vec3f
   # Tick is the server tick at which the packet was sent. It is used in relation to
   # CorrectPlayerMovePrediction.
   tick: varint64
   # Delta was the delta between the old and the new position. There isn't any practical use for this field
   # as it can be calculated by the server itself.
   delta: vec3f

InputFlag: [ "bitflags", {
   "type": "varint",
   "flags": {
      "ascend": 0b1,
      "descend": 0b10,
      "north_jump": 0b100,
      "jump_down": 0b1000,
      "sprint_down": 0b10000,
      "change_height": 0b100000,
      "jumping": 0b1000000,
      "auto_jumping_in_water": 0b10000000,
      "sneaking": 0b100000000,
      "sneak_down": 0b1000000000,
      "up": 0b10000000000,
      "down": 0b100000000000,
      "left": 0b1000000000000,
      "right": 0b10000000000000,
      "up_left": 0b100000000000000,
      "up_right": 0b1000000000000000,
      "want_up": 0b10000000000000000,
      "want_down": 0b100000000000000000,
      "want_down_slow": 0b1000000000000000000,
      "want_up_slow": 0b10000000000000000000,
      "sprinting": 0b100000000000000000000,
      "ascend_scaffolding": 0b1000000000000000000000,
      "descend_scaffolding": 0b10000000000000000000000,
      "sneak_toggle_down": 0b100000000000000000000000,
      "persist_sneak": 0b1000000000000000000000000,
   }
}]

packet_creative_content:
   !id: 0x91
   !bound: client
   items: ItemStacks

packet_player_enchant_options:
   !id: 0x92
   !bound: client
   enchant_options: EnchantOptions

packet_item_stack_request:
   !id: 0x93
   !bound: server
   requests: ItemStackRequests

packet_item_stack_response:
   !id: 0x94
   !bound: client
   responses: ItemStackResponses

# PlayerArmourDamage is sent by the server to damage the armour of a player. It is a very efficient packet,
# but generally it's much easier to just send a slot update for the damaged armour.
packet_player_armor_damage:
   !id: 0x95
   !bound: client
   # Bitset holds a bitset of 4 bits that indicate which pieces of armour need to have damage dealt to them.
   # The first bit, when toggled, is for a helmet, the second for the chestplate, the third for the leggings
   # and the fourth for boots.
   type: ArmorDamageType
   helmet_damage: type.head ?
      if true: zigzag32
   chestplate_damage: type.chest ?
      if true: zigzag32
   leggings_damage: type.legs ?
      if true: zigzag32
   boots_damage: types.feet ?
      if true: zigzag32

ArmorDamageType: [ "bitflags",
   {
      "type": "u8",
      "flags": {
         "head": 0b1,
         "chest": 0b10,
         "legs": 0b100,
         "feet": 0b1000
      }
   }
]

# UpdatePlayerGameType is sent by the server to change the game mode of a player. It is functionally
# identical to the SetPlayerGameType packet.
packet_update_player_game_type:
   !id: 0x97
   !bound: server
   # GameType is the new game type of the player. It is one of the constants that can be found in
   # set_player_game_type.go. Some of these game types require additional flags to be set in an
   # AdventureSettings packet for the game mode to obtain its full functionality.
   gamemode: GameMode
   # PlayerUniqueID is the entity unique ID of the player that should have its game mode updated. If this
   # packet is sent to other clients with the player unique ID of another player, nothing happens.
   player_unique_id: zigzag64


# PositionTrackingDBClientRequest is a packet sent by the client to request the position and dimension of a
# 'tracking ID'. These IDs are tracked in a database by the server. In 1.16, this is used for lodestones.
# The client will send this request to find the position a lodestone compass needs to point to. If found, it
# will point to the lodestone. If not, it will start spinning around.
# A PositionTrackingDBServerBroadcast packet should be sent in response to this packet.
packet_position_tracking_db_request:
   !id: 0x9a
   !bound: server
   # RequestAction is the action that should be performed upon the receiving of the packet. It is one of the
   # constants found above.
   action: u8 =>
      0: query
   # TrackingID is a unique ID used to identify the request. The server responds with a
   # PositionTrackingDBServerBroadcast packet holding the same ID, so that the client can find out what that
   # packet was in response to.
   tracking_id: zigzag32

# PositionTrackingDBServerBroadcast is sent by the server in response to the
# PositionTrackingDBClientRequest packet. This packet is, as of 1.16, currently only used for lodestones. The
# server maintains a database with tracking IDs and their position and dimension. The client will request
# these tracking IDs, (NBT tag set on the lodestone compass with the tracking ID?) and the server will
# respond with the status of those tracking IDs.
# What is actually done with the data sent depends on what the client chooses to do with it. For the
# lodestone compass, it is used to make the compass point towards lodestones and to make it spin if the
# lodestone at a position is no longer there.
packet_position_tracking_db_broadcast:
   !id: 0x99
   !bound: client
   # BroadcastAction specifies the status of the position tracking DB response. It is one of the constants
   # above, specifying the result of the request with the ID below.
   # The Update action is sent for setting the position of a lodestone compass, the Destroy and NotFound to
   # indicate that there is not (no longer) a lodestone at that position.
   broadcast_action: u8 =>
      0: update
      1: destory
      2: not_found
   # TrackingID is the ID of the PositionTrackingDBClientRequest packet that this packet was in response to.
   # The tracking ID is also present as the 'id' field in the SerialisedData field.
   tracking_id: zigzag32
   nbt: nbt

# PacketViolationWarning is sent by the client when it receives an invalid packet from the server. It holds
# some information on the error that occurred.
packet_packet_violation_warning:
   !id: 0x9c
   !bound: server
   violation_type: zigzag32 =>
      0: malformed
   # Severity specifies the severity of the packet violation. The action the client takes after this
   # violation depends on the severity sent.
   severity: zigzag32 =>
      0: warning
      1: final_warning
      2: terminating
   # PacketID is the ID of the invalid packet that was received.
   packet_id: zigzag32
   # ViolationContext holds a description on the violation of the packet.
   reason: string


# MotionPredictionHints is sent by the server to the client. There is a predictive movement component for
# entities. This packet fills the "history" of that component and entity movement is computed based on the
# points. Vanilla sends this packet instead of the SetActorMotion packet when 'spatial optimisations' are
# enabled.
packet_motion_prediction_hints:
   !id: 0x9d
   !bound: client
   # EntityRuntimeID is the runtime ID of the entity whose velocity is sent to the client.
   entity_runtime_id: varint64
   # Velocity is the server-calculated velocity of the entity at the point of sending the packet.
   velocity: vec3f
   # OnGround specifies if the server currently thinks the entity is on the ground.
   on_ground: bool


# AnimateEntity is sent by the server to animate an entity client-side. It may be used to play a single
# animation, or to activate a controller which can start a sequence of animations based on different
# conditions specified in an animation controller.
# Much of the documentation of this packet can be found at
# https://minecraft.gamepedia.com/Bedrock_Edition_beta_animation_documentation.
packet_animate_entity:
   !id: 0x9e
   !bound: client
   # Animation is the name of a single animation to start playing.
   animation: string
   # NextState is the first state to start with. These states are declared in animation controllers (which,
   # in themselves, are animations too). These states in turn may have animations and transitions to move to
   # a next state.
   next_state: string
   # StopCondition is a MoLang expression that specifies when the animation should be stopped.
   stop_condition: string
   # Controller is the animation controller that is used to manage animations. These controllers decide when
   # to play which animation.
   controller: string
   # BlendOutTime does not currently seem to be used.
   blend_out_time: lf32
   # EntityRuntimeIDs is list of runtime IDs of entities that the animation should be applied to.
   runtime_entity_ids: varint64[]varint

# CameraShake is sent by the server to make the camera shake client-side. This feature was added for map-
# making partners.
packet_camera_shake:
   !id: 0x9f
   !bound: client
   # Intensity is the intensity of the shaking. The client limits this value to 4, so anything higher may
   # not work.
   intensity: lf32
   # Duration is the number of seconds the camera will shake for.
   duration: lf32
   # Type is the type of shake, and is one of the constants listed above. The different type affects how
   # the shake looks in game.
   type: u8

# PlayerFog is sent by the server to render the different fogs in the Stack. The types of fog are controlled
# by resource packs to change how they are rendered, and the ability to create custom fog.
packet_player_fog:
   !id: 0xa0
   !bound: client
   # Stack is a list of fog identifiers to be sent to the client. Examples of fog identifiers are
   # "minecraft:fog_ocean" and "minecraft:fog_hell".
   stack: string[]varint


# CorrectPlayerMovePrediction is sent by the server if and only if StartGame.ServerAuthoritativeMovementMode
# is set to AuthoritativeMovementModeServerWithRewind. The packet is used to correct movement at a specific
# point in time.
packet_correct_player_move_prediction:
   !id: 0xa1
   !bound: client
   # Position is the position that the player is supposed to be at at the tick written in the field below.
   # The client will change its current position based on movement after that tick starting from the
   # Position.
   position: vec3f
   # Delta is the change in position compared to what the client sent as its position at that specific tick.
   delta: vec3f
   # OnGround specifies if the player was on the ground at the time of the tick below.
   on_ground: bool
   # Tick is the tick of the movement which was corrected by this packet.
   tick: varint64

# ItemComponent is sent by the server to attach client-side components to a custom item.
packet_item_component:
   !id: 0xa2
   !bound: client
   # `entries` holds a list of all custom items with their respective components set.
   entries: ItemComponentList

# FilterText is sent by the both the client and the server. The client sends the packet to the server to
# allow the server to filter the text server-side. The server then responds with the same packet and the
# safer version of the text.
packet_filter_text_packet:
   !id: 0xa3
   !bound: client
   # Text is either the text from the client or the safer version of the text sent by the server.
   text: string
   # FromServer indicates if the packet was sent by the server or not.
   from_server: bool

