protocol updates

Add some updates
This commit is contained in:
extremeheat 2021-02-21 15:22:04 -05:00
commit f3604fa9b5
4 changed files with 479 additions and 34 deletions

View file

@ -200,7 +200,18 @@ packet_start_game:
# 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
player_gamemode: zigzag32
# 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: zigzag32 =>
0: survival
1: creative
2: adventure
3: survival_spectator
4: creative_spectator
5: fallback
# 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
@ -680,11 +691,25 @@ packet_mob_armor_equipment:
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_id: u8
# 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
@ -865,16 +890,75 @@ 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: varint
command_permission: varint
action_permissions: varint
permission_level: varint
# 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
@ -1547,21 +1631,61 @@ packet_update_block_synced:
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
runtime_entity_id: varint
flags: lu16
# 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
runtime_entity_id: varint
# 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

View file

@ -328,25 +328,76 @@ Transaction:
default: void
transaction_data: transaction_type?
if normal or inventory_mismatch: void
# UseItemTransactionData represents an inventory transaction data object sent when the client uses an item on
# a block.
if item_use:
action_type: varint
# ActionType is the type of the UseItem inventory transaction. It is one of the action types found above,
# and specifies the way the player interacted with the block.
action_type: varint =>
0: click_block
1: click_air
2: break_block
# BlockPosition is the position of the block that was interacted with. This is only really a correct
# block position if ActionType is not UseItemActionClickAir.
block_position: BlockCoordinates
# BlockFace is the face of the block that was interacted with. When clicking the block, it is the face
# clicked. When breaking the block, it is the face that was last being hit until the block broke.
face: varint
# HotBarSlot is the hot bar slot that the player was holding while clicking the block. It should be used
# to ensure that the hot bar slot and held item are correctly synchronised with the server.
hotbar_slot: varint
item_in_hand: Item
# HeldItem is the item that was held to interact with the block. The server should check if this item
# is actually present in the HotBarSlot.
held_item: Item
# Position is the position of the player at the time of interaction. For clicking a block, this is the
# position at that time, whereas for breaking the block it is the position at the time of breaking.
player_pos: vec3f
# ClickedPosition is the position that was clicked relative to the block's base coordinate. It can be
# used to find out exactly where a player clicked the block.
click_pos: vec3f
# BlockRuntimeID is the runtime ID of the block that was clicked. It may be used by the server to verify
# that the player's world client-side is synchronised with the server's.
block_runtime_id: varint
# UseItemOnEntityTransactionData represents an inventory transaction data object sent when the client uses
# an item on an entity.
if item_use_on_entity:
# TargetEntityRuntimeID is the entity runtime ID of the target that was clicked. It is the runtime ID
# that was assigned to it in the AddEntity packet.
entity_runtime_id: varint64
action_type: varint
# ActionType is the type of the UseItemOnEntity inventory transaction. It is one of the action types
# found in the constants above, and specifies the way the player interacted with the entity.
action_type: varint =>
0: interact
1: attack
# HotBarSlot is the hot bar slot that the player was holding while clicking the entity. It should be used
# to ensure that the hot bar slot and held item are correctly synchronised with the server.
hotbar_slot: zigzag32
item_in_hand: Item
# HeldItem is the item that was held to interact with the entity. The server should check if this item
# is actually present in the HotBarSlot.
held_item: Item
# Position is the position of the player at the time of clicking the entity.
player_pos: vec3f
click_pos: vec3f
# ClickedPosition is the position that was clicked relative to the entity's base coordinate. It can be
# used to find out exactly where a player clicked the entity.
click_pos: vec3f
# ReleaseItemTransactionData represents an inventory transaction data object sent when the client releases
# the item it was using, for example when stopping while eating or stopping the charging of a bow.
if item_release:
action_type: varint
# ActionType is the type of the ReleaseItem inventory transaction. It is one of the action types found
# in the constants above, and specifies the way the item was released.
# As of 1.13, the ActionType is always 0. This field can be ignored, because releasing food (by consuming
# it) or releasing a bow (to shoot an arrow) is essentially the same.
action_type: varint =>
0: release
1: consume
# HotBarSlot is the hot bar slot that the player was holding while releasing the item. It should be used
# to ensure that the hot bar slot and held item are correctly synchronised with the server.
hotbar_slot: zigzag32
item_in_hand: Item
# HeldItem is the item that was released. The server should check if this item is actually present in the
# HotBarSlot.
held_item: Item
# HeadPosition is the position of the player's head at the time of releasing the item. This is used
# mainly for purposes such as spawning eating particles at that position.
head_pos: vec3f
ItemStacks: []varint

View file

@ -918,7 +918,21 @@
[
{
"name": "action_type",
"type": "varint"
"type": [
"mapper",
{
"type": "varint",
"mappings": {
"0": "click_block",
"1": "click_air",
"2": "break_block"
}
}
]
},
{
"name": "block_position",
"type": "BlockCoordinates"
},
{
"name": "face",
@ -929,7 +943,7 @@
"type": "varint"
},
{
"name": "item_in_hand",
"name": "held_item",
"type": "Item"
},
{
@ -955,14 +969,23 @@
},
{
"name": "action_type",
"type": "varint"
"type": [
"mapper",
{
"type": "varint",
"mappings": {
"0": "interact",
"1": "attack"
}
}
]
},
{
"name": "hotbar_slot",
"type": "zigzag32"
},
{
"name": "item_in_hand",
"name": "held_item",
"type": "Item"
},
{
@ -980,14 +1003,23 @@
[
{
"name": "action_type",
"type": "varint"
"type": [
"mapper",
{
"type": "varint",
"mappings": {
"0": "release",
"1": "consume"
}
}
]
},
{
"name": "hotbar_slot",
"type": "zigzag32"
},
{
"name": "item_in_hand",
"name": "held_item",
"type": "Item"
},
{
@ -2993,7 +3025,20 @@
},
{
"name": "player_gamemode",
"type": "zigzag32"
"type": [
"mapper",
{
"type": "zigzag32",
"mappings": {
"0": "survival",
"1": "creative",
"2": "adventure",
"3": "survival_spectator",
"4": "creative_spectator",
"5": "fallback"
}
}
]
},
{
"name": "spawn",
@ -3926,11 +3971,35 @@
[
{
"name": "action_id",
"type": "u8"
"type": [
"mapper",
{
"type": "u8",
"mappings": {
"3": "leave_vehicle",
"4": "mouse_over_entity",
"6": "open_inventory"
}
}
]
},
{
"name": "target_runtime_entity_id",
"type": "varint"
},
{
"name": "position",
"type": [
"switch",
{
"compareTo": "action_id",
"fields": {
"mouse_over_entity": "vec3f",
"leave_vehicle": "vec3f"
},
"default": "void"
}
]
}
]
],
@ -4308,19 +4377,42 @@
[
{
"name": "flags",
"type": "varint"
"type": "AdventureFlags"
},
{
"name": "command_permission",
"type": "varint"
"type": [
"mapper",
{
"type": "varint32",
"mappings": {
"0": "normal",
"1": "operator",
"2": "host",
"3": "automation",
"4": "admin"
}
}
]
},
{
"name": "action_permissions",
"type": "varint"
"type": "ActionPermissions"
},
{
"name": "permission_level",
"type": "varint"
"type": [
"mapper",
{
"type": "varint",
"mappings": {
"0": "visitor",
"1": "member",
"2": "operator",
"3": "custom"
}
}
]
},
{
"name": "custom_stored_permissions",
@ -5611,11 +5703,89 @@
[
{
"name": "runtime_entity_id",
"type": "varint"
"type": "varint64"
},
{
"name": "flags",
"type": "lu16"
"type": "DeltaMoveFlags"
},
{
"name": "x",
"type": [
"switch",
{
"compareTo": "flags.has_x",
"fields": {
"true": "lf32"
},
"default": "void"
}
]
},
{
"name": "y",
"type": [
"switch",
{
"compareTo": "flags.has_y",
"fields": {
"true": "lf32"
},
"default": "void"
}
]
},
{
"name": "z",
"type": [
"switch",
{
"compareTo": "flags.has_z",
"fields": {
"true": "lf32"
},
"default": "void"
}
]
},
{
"name": "rot_x",
"type": [
"switch",
{
"compareTo": "flags.has_rot_x",
"fields": {
"true": "u8"
},
"default": "void"
}
]
},
{
"name": "rot_y",
"type": [
"switch",
{
"compareTo": "flags.has_rot_y",
"fields": {
"true": "u8"
},
"default": "void"
}
]
},
{
"name": "rot_z",
"type": [
"switch",
{
"compareTo": "flags.has_rot_z",
"fields": {
"true": "u8"
},
"default": "void"
}
]
}
]
],
@ -5633,7 +5803,7 @@
[
{
"name": "runtime_entity_id",
"type": "varint"
"type": "varint64"
}
]
],
@ -5994,6 +6164,37 @@
"countType": "li32"
}
],
"AdventureFlags": [
"bitflags",
{
"type": "varint",
"flags": {
"world_immutable": 1,
"no_pvp": 2,
"auto_jump": 32,
"allow_flight": 64,
"no_clip": 128,
"world_builder": 256,
"flying": 512,
"muted": 1024
}
}
],
"ActionPermissions": [
"bitflags",
{
"type": "varint",
"flags": {
"build_and_mine": 65537,
"doors_and_switches": 65538,
"open_containers": 65540,
"attack_players": 65544,
"attack_mobs": 65552,
"operator": 65568,
"teleport": 65664
}
}
],
"CommandFlags": [
"bitfield",
[
@ -6013,6 +6214,23 @@
"signed": false
}
]
],
"DeltaMoveFlags": [
"bitflags",
{
"type": "lu16",
"flags": {
"has_x": 1,
"has_y": 2,
"has_z": 4,
"has_rot_x": 8,
"has_rot_y": 16,
"has_rot_z": 32,
"on_ground": 64,
"teleport": 128,
"force_move": 256
}
}
]
}
}

View file

@ -45,18 +45,70 @@ Read.nbt = ['native', minecraft.nbt[0]]
Write.nbt = ['native', minecraft.nbt[1]]
SizeOf.nbt = ['native', minecraft.nbt[2]]
/**
* Bits
*/
// nvm,
// Read.bitflags = ['parametrizable', (compiler, { type, flags }) => {
// return compiler.wrapCode(`
// const { value, size } = ${compiler.callType('buffer, offset', type)}
// const val = {}
// for (let i = 0; i < size; i++) {
// const hi = (value >> i) & 1
// if ()
// const v = value &
// if (flags[i])
// }
// `
// }]
Read.bitflags = ['parametrizable', (compiler, { type, flags }) => {
return compiler.wrapCode(`
const { value: _value, size } = ${compiler.callType(type, 'offset')}
const value = { _value }
const flags = ${JSON.stringify(flags)}
for (const key in flags) {
value[key] = (_value & flags[key]) == flags[key]
}
return { value, size }
`.trim())
}]
Write.bitflags = ['parametrizable', (compiler, { type, flags }) => {
return compiler.wrapCode(`
const flags = ${JSON.stringify(flags)}
let val = value._value
for (const key in flags) {
if (value[key]) val |= flags[key]
}
return (ctx.${type})(val, buffer, offset)
`.trim())
}]
SizeOf.bitflags = ['parametrizable', (compiler, { type, flags }) => {
return compiler.wrapCode(`
const flags = ${JSON.stringify(flags)}
let val = value._value
for (const key in flags) {
if (value[key]) val |= flags[key]
}
return (ctx.${type})(val)
`.trim())
}]
/**
* Command Packet
* - used for determining the size of the following enum
*/
Read.enum_size_based_on_values_len = ['parametrizable', (compiler, array) => {
Read.enum_size_based_on_values_len = ['parametrizable', (compiler) => {
return compiler.wrapCode(js(() => {
if (values_len <= 0xff) return { value: 'byte', size: 0 }
if (values_len <= 0xffff) return { value: 'short', size: 0 }
if (values_len <= 0xffffff) return { value: 'int', size: 0 }
}))
}]
Write.enum_size_based_on_values_len = ['parametrizable', (compiler, array) => {
Write.enum_size_based_on_values_len = ['parametrizable', (compiler) => {
return str(() => {
if (value.values_len <= 0xff) _enum_type = 'byte'
else if (value.values_len <= 0xffff) _enum_type = 'short'
@ -64,7 +116,7 @@ Write.enum_size_based_on_values_len = ['parametrizable', (compiler, array) => {
return offset
})
}]
SizeOf.enum_size_based_on_values_len = ['parametrizable', (compiler, array) => {
SizeOf.enum_size_based_on_values_len = ['parametrizable', (compiler) => {
return str(() => {
if (value.values_len <= 0xff) _enum_type = 'byte'
else if (value.values_len <= 0xffff) _enum_type = 'short'