Protocol updates, maps and rotation (#77)

* protocol updates
* Add clientbound map packet impl
* Add missing byte rotation implementation

* github: auto collapse generated diffs

* protocol doc fix

* protocol collision fix

* Fix map pixels
This commit is contained in:
extremeheat 2021-05-04 13:56:12 -04:00 committed by GitHub
commit ab8b6ddc0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 433 additions and 109 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
data/*/*.json linguist-generated

View file

@ -956,100 +956,92 @@
]
],
"TransactionActions": [
"container",
[
{
"name": "actions",
"type": [
"array",
"array",
{
"countType": "varint",
"type": [
"container",
[
{
"countType": "varint",
"name": "source_type",
"type": [
"container",
[
{
"name": "source_type",
"type": [
"mapper",
{
"type": "varint",
"mappings": {
"0": "container",
"1": "global",
"2": "world_interaction",
"3": "creative",
"100": "craft_slot",
"99999": "craft"
}
}
]
},
{
"anon": true,
"type": [
"switch",
{
"compareTo": "source_type",
"fields": {
"container": [
"container",
[
{
"name": "inventory_id",
"type": "varint"
}
]
],
"craft": [
"container",
[
{
"name": "action",
"type": "varint"
}
]
],
"world_interaction": [
"container",
[
{
"name": "flags",
"type": "varint"
}
]
],
"craft_slot": [
"container",
[
{
"name": "action",
"type": "varint"
}
]
]
},
"default": "void"
}
]
},
{
"name": "slot",
"type": "varint"
},
{
"name": "old_item",
"type": "Item"
},
{
"name": "new_item",
"type": "Item"
"mapper",
{
"type": "varint",
"mappings": {
"0": "container",
"1": "global",
"2": "world_interaction",
"3": "creative",
"100": "craft_slot",
"99999": "craft"
}
]
}
]
},
{
"anon": true,
"type": [
"switch",
{
"compareTo": "source_type",
"fields": {
"container": [
"container",
[
{
"name": "inventory_id",
"type": "WindowIDVarint"
}
]
],
"craft": [
"container",
[
{
"name": "action",
"type": "varint"
}
]
],
"world_interaction": [
"container",
[
{
"name": "flags",
"type": "varint"
}
]
],
"craft_slot": [
"container",
[
{
"name": "action",
"type": "varint"
}
]
]
},
"default": "void"
}
]
},
{
"name": "slot",
"type": "varint"
},
{
"name": "old_item",
"type": "Item"
},
{
"name": "new_item",
"type": "Item"
}
]
}
]
]
}
],
"TransactionLegacy": [
"container",
@ -2656,6 +2648,79 @@
}
]
],
"TrackedObject": [
"container",
[
{
"name": "type",
"type": [
"mapper",
{
"type": "li32",
"mappings": {
"0": "entity",
"1": "block"
}
}
]
},
{
"name": "entity_unique_id",
"type": [
"switch",
{
"compareTo": "type",
"fields": {
"entity": "zigzag64"
},
"default": "void"
}
]
},
{
"name": "block_position",
"type": [
"switch",
{
"compareTo": "type",
"fields": {
"block": "BlockCoordinates"
},
"default": "void"
}
]
}
]
],
"MapDecoration": [
"container",
[
{
"name": "type",
"type": "u8"
},
{
"name": "rotation",
"type": "u8"
},
{
"name": "x",
"type": "u8"
},
{
"name": "y",
"type": "u8"
},
{
"name": "label",
"type": "string"
},
{
"name": "color_abgr",
"type": "varint"
}
]
],
"WindowID": [
"mapper",
{
@ -5673,8 +5738,132 @@
"container",
[
{
"name": "mapinfo",
"type": "MapInfo"
"name": "map_id",
"type": "zigzag64"
},
{
"name": "update_flags",
"type": "UpdateMapFlags"
},
{
"name": "dimension",
"type": "u8"
},
{
"name": "locked",
"type": "bool"
},
{
"name": "included_in",
"type": [
"switch",
{
"compareTo": "update_flags.initialisation",
"fields": {
"true": [
"array",
{
"countType": "varint",
"type": "zigzag64"
}
]
},
"default": "void"
}
]
},
{
"name": "scale",
"type": [
"switch",
{
"compareTo": "update_flags.initialisation || update_flags.decoration || update_flags.texture",
"fields": {
"true": "u8"
},
"default": "void"
}
]
},
{
"name": "tracked",
"type": [
"switch",
{
"compareTo": "update_flags.decoration",
"fields": {
"true": [
"container",
[
{
"name": "objects",
"type": [
"array",
{
"countType": "varint",
"type": "TrackedObject"
}
]
},
{
"name": "decorations",
"type": [
"array",
{
"countType": "varint",
"type": "MapDecoration"
}
]
}
]
]
},
"default": "void"
}
]
},
{
"name": "texture",
"type": [
"switch",
{
"compareTo": "update_flags.texture",
"fields": {
"true": [
"container",
[
{
"name": "width",
"type": "zigzag32"
},
{
"name": "height",
"type": "zigzag32"
},
{
"name": "x_offset",
"type": "zigzag32"
},
{
"name": "y_offset",
"type": "zigzag32"
},
{
"name": "pixels",
"type": [
"array",
{
"countType": "varint",
"type": "varint"
}
]
}
]
]
},
"default": "void"
}
]
}
]
],
@ -8216,6 +8405,18 @@
}
}
],
"UpdateMapFlags": [
"bitflags",
{
"type": "varint",
"flags": [
"void",
"texture",
"decoration",
"initialisation"
]
}
],
"CommandFlags": [
"bitfield",
[

View file

@ -465,12 +465,22 @@ packet_take_item_entity:
runtime_entity_id: varint64
target: varint
# MoveActorAbsolute is sent by the server to move an entity to an absolute position. It is typically used
# for movements where high accuracy isn't needed, such as for long range teleporting.
packet_move_entity:
!id: 0x12
!bound: both
# EntityRuntimeID is the runtime ID of the entity. The runtime ID is unique for each world session, and
# entities are generally identified in packets using this runtime ID.
runtime_entity_id: varint64
# Flags is a combination of flags that specify details of the movement. It is a combination of the flags
# above.
flags: u8
# Position is the position to spawn the entity on. If the entity is on a distance that the player cannot
# see it, the entity will still show up if the player moves closer.
position: vec3f
# Rotation is a Vec3 holding the X, Y and Z rotation of the entity after the movement. This is a Vec3 for
# the reason that projectiles like arrows don't have yaw/pitch, but do have roll.
rotation: Rotation
# MovePlayer is sent by players to send their movement to the server, and by the server to update the
@ -1249,10 +1259,74 @@ packet_spawn_experience_orb:
position: vec3f
count: zigzag32
UpdateMapFlags: [ "bitflags", {
"type": "varint",
"flags": [
"void",
"texture",
"decoration",
"initialisation"
]
}]
# ClientBoundMapItemData is sent by the server to the client to update the data of a map shown to the client.
# It is sent with a combination of flags that specify what data is updated.
# The ClientBoundMapItemData packet may be used to update specific parts of the map only. It is not required
# to send the entire map each time when updating one part.
packet_clientbound_map_item_data:
!id: 0x43
!bound: client
mapinfo: MapInfo
# MapID is the unique identifier that represents the map that is updated over network. It remains
# consistent across sessions.
map_id: zigzag64
# UpdateFlags is a combination of flags found above that indicate what parts of the map should be updated
# client-side.
update_flags: UpdateMapFlags
# Dimension is the dimension of the map that should be updated, for example the overworld (0), the nether
# (1) or the end (2).
dimension: u8
# LockedMap specifies if the map that was updated was a locked map, which may be done using a cartography
# table.
locked: bool
# The following fields apply only for the MapUpdateFlagInitialisation.
# MapsIncludedIn holds an array of map IDs that the map updated is included in. This has to do with the
# scale of the map: Each map holds its own map ID and all map IDs of maps that include this map and have
# a bigger scale. This means that a scale 0 map will have 5 map IDs in this slice, whereas a scale 4 map
# will have only 1 (its own).
# The actual use of this field remains unknown.
included_in: update_flags.initialisation ?
if true: zigzag64[]varint
# Scale is the scale of the map as it is shown in-game. It is written when any of the MapUpdateFlags are
# set to the UpdateFlags field.
scale: update_flags.initialisation || update_flags.decoration || update_flags.texture ?
if true: u8
# The following fields apply only for the MapUpdateFlagDecoration.
# TrackedObjects is a list of tracked objects on the map, which may either be entities or blocks. The
# client makes sure these tracked objects are actually tracked. (position updated etc.)
tracked: update_flags.decoration ?
if true:
objects: TrackedObject[]varint
decorations: MapDecoration[]varint
# Updates to the map contents itself (texture)
texture: update_flags.texture ?
if true:
# Width is the width of the texture area that was updated. The width may be a subset of the total width
# of the map.
width: zigzag32
# Height is the height of the texture area that was updated. The height may be a subset of the total
# height of the map
height: zigzag32
# XOffset is the X offset in pixels at which the updated texture area starts. From this X, the updated
# texture will extend exactly Width pixels to the right.
x_offset: zigzag32
# YOffset is the Y offset in pixels at which the updated texture area starts. From this Y, the updated
# texture will extend exactly Height pixels up.
y_offset: zigzag32
# Pixels is a list of pixel colours for the new texture of the map. It is indexed as Pixels[y][x], with
# the length of the outer slice having to be exactly Height long and the inner slices exactly Width long.
# To access this array, use $width * y + x
pixels: varint[]varint
packet_map_info_request:
!id: 0x44

View file

@ -484,26 +484,25 @@ TransactionUseItem:
# these actions hold one slot in which one item was changed to another. In general, the combination of
# all of these actions results in a balanced inventory transaction. This should be checked to ensure that
# no items are cheated into the inventory.
TransactionActions:
actions: []varint
source_type: varint =>
0: container
1: global
2: world_interaction
3: creative
100: craft_slot
99999: craft
_: source_type?
if container or craft:
inventory_id: varint
if world_interaction:
flags: varint
if craft or craft_slot:
action: varint
default: void
slot: varint
old_item: Item
new_item: Item
TransactionActions: []varint
source_type: varint =>
0: container
1: global
2: world_interaction
3: creative
100: craft_slot
99999: craft
_: source_type?
if container or craft:
inventory_id: WindowIDVarint
if world_interaction:
flags: varint
if craft or craft_slot:
action: varint
default: void
slot: varint
old_item: Item
new_item: Item
# The Minecraft bedrock inventory system was refactored, but not all inventory actions use the new packet.
# This data structure holds actions that have not been updated to the new system.
@ -1011,6 +1010,39 @@ CommandOrigin:
if dev_console or test:
player_entity_id: zigzag64
# MapTrackedObject is an object on a map that is 'tracked' by the client, such as an entity or a block. This
# object may move, which is handled client-side.
TrackedObject:
# Type is the type of the tracked object. It is either MapObjectTypeEntity or MapObjectTypeBlock.
type: li32 =>
0: entity
1: block
# EntityUniqueID is the unique ID of the entity, if the tracked object was an entity. It needs not to be
# filled out if Type is not MapObjectTypeEntity.
entity_unique_id: type ?
if entity: zigzag64
# BlockPosition is the position of the block, if the tracked object was a block. It needs not to be
# filled out if Type is not MapObjectTypeBlock.
block_position: type ?
if block: BlockCoordinates
# MapDecoration is a fixed decoration on a map: Its position or other properties do not change automatically
# client-side.
MapDecoration:
type: u8
# Rotation is the rotation of the map decoration. It is byte due to the 16 fixed directions that the
# map decoration may face.
rotation: u8
# X is the offset on the X axis in pixels of the decoration.
x: u8
# Y is the offset on the Y axis in pixels of the decoration.
y: u8
# Label is the name of the map decoration. This name may be of any value.
label: string
# Colour is the colour of the map decoration. Some map decoration types have a specific colour set
# automatically, whereas others may be changed.
color_abgr: varint
# Some arbitrary definitions from CBMC, Window IDs are normally
# unique + sequential
WindowID: i8 =>

View file

@ -89,6 +89,22 @@ SizeOf.nbtLoop = ['context', (value, buffer, offset) => {
return size
}]
/**
* Read rotation float encoded as a byte
*/
Read.byterot = ['context', (buffer, offset) => {
const val = buffer.readUint8(buffer)
return { value: (val * (360 / 256)), size: 1 }
}]
Write.byterot = ['context', (value, buffer, offset) => {
const val = (value / (360 / 256))
buffer.writeUint8(val, offset)
return offset + 1
}]
SizeOf.byterot = ['context', (value, buffer, offset) => {
return 1
}]
/**
* NBT
*/