Difference between revisions of "Zh:Data types"
(Created page with "<noinclude>本文章定义了在协议中使用的'''数据类型'''。</noinclude>所有在网络上发送的数据(除VarInt和VarLong外)都是wikiped...") |
m |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
− | <noinclude>本文章定义了在[[ZH:Protocol|协议]]中使用的'''数据类型'''。</noinclude>所有在网络上发送的数据(除VarInt和VarLong外)都是[[wikipedia:zh:字节顺序#大端序|大字节序]] | + | <noinclude>本文章定义了在[[ZH:Protocol|协议]]中使用的'''数据类型'''。</noinclude>所有在网络上发送的数据(除VarInt和VarLong外)都是[[wikipedia:zh:字节顺序#大端序|大字节序]]的,也就是说,字节是从最高有效字节到最低有效字节发送。大多数日常遇到的电脑都是小字节序的,所以也许有必要在网络上发送数据前更改字节序。<includeonly> |
{{#ifeq: {{PAGEID}}|{{PAGEID:ZH:Protocol}}| {{#ifeq: {{REVISIONID}}|{{REVISIONID:ZH:Protocol}}||{{Warning2|注意:这一信息是来自[[ZH:Data types|数据类型]]一文的'''最新'''版本,也许并不适用于当前协议版本。查阅文章历史来看自这一版本起发生的变化。}}}}}} | {{#ifeq: {{PAGEID}}|{{PAGEID:ZH:Protocol}}| {{#ifeq: {{REVISIONID}}|{{REVISIONID:ZH:Protocol}}||{{Warning2|注意:这一信息是来自[[ZH:Data types|数据类型]]一文的'''最新'''版本,也许并不适用于当前协议版本。查阅文章历史来看自这一版本起发生的变化。}}}}}} | ||
</includeonly><noinclude> | </includeonly><noinclude> | ||
Line 293: | Line 293: | ||
<noinclude>== 定点数 ==</noinclude><includeonly>=== 定点数 ===</includeonly> | <noinclude>== 定点数 ==</noinclude><includeonly>=== 定点数 ===</includeonly> | ||
− | 一些字段被存储为[wikipedia:zh:定点数|定点数],其中一定数量的为用于表示有符号整数部分(小数点左侧的数字),其余表示小数部分(小数点右侧)。浮点数(float和double),相反,将数字本身(尾数)存储在内存块中,而小数点(指数)的位置存储在其一边。 | + | 一些字段被存储为[[wikipedia:zh:定点数|定点数]],其中一定数量的为用于表示有符号整数部分(小数点左侧的数字),其余表示小数部分(小数点右侧)。浮点数(float和double),相反,将数字本身(尾数)存储在内存块中,而小数点(指数)的位置存储在其一边。 |
本质上,虽然定点数有着比浮点数更小的范围,但是对于较大值来说它们的小数精度要更胜一筹。这使得它们用于表示Minecraft实体的全局坐标非常理想,因为比起将它们精确地定位在一个方块(或米)中,准确地保存它的整数部分要重要得多。 | 本质上,虽然定点数有着比浮点数更小的范围,但是对于较大值来说它们的小数精度要更胜一筹。这使得它们用于表示Minecraft实体的全局坐标非常理想,因为比起将它们精确地定位在一个方块(或米)中,准确地保存它的整数部分要重要得多。 |
Latest revision as of 08:45, 6 May 2020
本文章定义了在协议中使用的数据类型。所有在网络上发送的数据(除VarInt和VarLong外)都是大字节序的,也就是说,字节是从最高有效字节到最低有效字节发送。大多数日常遇到的电脑都是小字节序的,所以也许有必要在网络上发送数据前更改字节序。
定义
名称 | 大小(字节) | 编码 | 注释 |
---|---|---|---|
Boolean | 1 | false或true | True被编码为0x01 ,false为0x00 。
|
Byte | 1 | -128到127之间的整数 | 有符号8位整数,补码 |
Unsigned Byte | 1 | 0和255之间的整数 | 无符号8位整数 |
Short | 2 | -32768和32767之间的整数 | 有符号16位整数,补码 |
Unsigned Short | 2 | 0和65535之间的整数 | 无符号16位整数 |
Int | 4 | -2147483648和2147483647之间的整数 | 有符号32位整数,补码 |
Long | 8 | -9223372036854775808和9223372036854775807之间的整数 | 有符号64位整数,补码 |
Float | 4 | 单精度32位IEEE 754浮点数 | |
Double | 8 | 双精度64位IEEE 754浮点数 | |
String(n) | ≥ 1 ≤ (n×4) + 3 |
Unicode标量序列 | 以它的大小用字节为单位表示对VarInt为前缀的UTF-8字符串。n 字符的最大长度随上下文而变化,最多可以使用n × 4 字节来编码n 个字符,并同时检查这些限制。最大的n 值为32767。+ 3是因为有效长度VarInt的最大大小。
|
Chat | ≥ 1 ≤ (32767×4) + 3 |
见Chat | 编码为最大长度为32767的字符串。 |
Identifier | ≥ 1 ≤ (32767×4) + 3 |
见下方标识符 | 编码为最大长度为32767的字符串。 |
VarInt | ≥ 1 ≤ 5 |
-2147483648和2147483647之间的整数 | 编码补码32位整型的可变长度数据,更多信息参阅它们的部分 |
VarLong | ≥ 1 ≤ 10 |
-9223372036854775808和9223372036854775807之间的整数 | 编码补码64位整型的可变长度数据,更多信息参阅它们的部分 |
Entity Metadata | 可变 | 有关实体的杂项信息 | 见实体#实体元数据格式 |
Slot | 可变 | 在物品栏或容器中的一组物品 | 见槽数据 |
NBT Tag | 可变 | 取决于上下文 | 见NBT |
Position | 8 | 一个整型/方块位置: x(-33554432至33554431)、y(-2048至2047)、z(-33554432至33554431) | x为26位整数,后面跟着12位整数的y,以及26位整数的z(都是有符号的,补码)。另见下面的部分。 |
Angle | 1 | 一圈的1/256为步长的旋转角度 | 这是否是有符号的都无所谓,因为结果角度是相同的。 |
UUID | 16 | UUID | 编码为无符号128整数(或两个无符号64位整数:高64位和低64位) |
Optional X | 0或X的大小 | 类型X的字段,或什么都没有 | 该字段是否出现必须从上下文得知。 |
Array of X | 数量乘上X的大小 | 类型X的零或更多的字段 | 数量必须必须从上下文得知。 |
X Enum | X的大小 | 给定列表中特定的值 | 可能的值的列表和每个该如何编码为X都必须从上下文中得知。无论哪一边发送的无效值通常都会导致客户端断开连接并产生一个错误甚至崩溃。 |
Byte Array | 可变 | 取决于上下文 | 这通常是一个零或更多字节的序列,它的含义会在别的地方解释,例如数据包描述中。长度必须从上下文中得知。 |
标识符
标识符是一个以minecraft:thing
为形式的带命名空间的位置。如果没有提供命名空间,那么它默认为minecraft
(即,thing
变为minecraft:thing
。自定义内容应该总是在它自己的命名空间中,而不是默认的中。命名空间应该只使用这些字符:0123456789abcdefghijklmnopqrstuvwxyz-_
,实际的名称可能会包含更多符号。命名约定是lower_case_with_underscores
(蛇形命名法)。更多信息。
VarInt和VarLong
可变长度格式,就像较小的数会使用较少的字节。于Protocol Buffer Varints非常相似:7个最底位用于编码值而最高位用于指示在之后还有多少用于数字下一部分的字节。最低位的组写在最前面,后面跟着更高位的组;因此,VarInts实际上是小字节序的(然而,组是7位而不是8位的)。
VarInts永远不会多余5字节,VarLongs永远不会多于10字节。
读取并写入VarInts和VarLongs的伪代码:
public static int readVarInt() {
int numRead = 0;
int result = 0;
byte read;
do {
read = readByte();
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 5) {
throw new RuntimeException("VarInt is too big");
}
} while ((read & 0b10000000) != 0);
return result;
}
public static long readVarLong() {
int numRead = 0;
long result = 0;
byte read;
do {
read = readByte();
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 10) {
throw new RuntimeException("VarLong is too big");
}
} while ((read & 0b10000000) != 0);
return result;
}
public static void writeVarInt(int value) {
do {
byte temp = (byte)(value & 0b01111111);
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
writeByte(temp);
} while (value != 0);
}
public static void writeVarLong(long value) {
do {
byte temp = (byte)(value & 0b01111111);
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
writeByte(temp);
} while (value != 0);
}
注意Minecraft的VarInts不是使用Protocol Buffers编码的,它们只是相似罢了。如果你尝试将Protocol Buffers Varints用于Minecraft的VarInts,你会在某些情况下得到不正确的结果。主要的区别有:
- Minecraft的VarInts都是有符号的,但不使用ZigZag编码。Protocol buffers有三种类型Varints:
uint32
(普通编码、无符号)、sint32
(ZigZag编码、无符号)和int32
(普通编码、有符号)。 Minecraft的是int32
种类。因为Minecraft使用正常的编码而不是ZigZag编码,负值总是会使用字节的最大数字。 - Minecraft的VarInts永远不会多于5字节,VarLongs永不多于10字节,而Protocol Buffer Varints会总是使用10字节来编码负数,即使它是
int32
。
示例VarInts:
值 | 十六进制字节 | 十进制字节 |
---|---|---|
0 | 0x00 | 0 |
1 | 0x01 | 1 |
2 | 0x02 | 2 |
127 | 0x7f | 127 |
128 | 0x80 0x01 | 128 1 |
255 | 0xff 0x01 | 255 1 |
2147483647 | 0xff 0xff 0xff 0xff 0x07 | 255 255 255 255 7 |
-1 | 0xff 0xff 0xff 0xff 0x0f | 255 255 255 255 15 |
-2147483648 | 0x80 0x80 0x80 0x80 0x08 | 128 128 128 128 8 |
示例VarLongs:
值 | 十六进制字节 | 十进制字节 |
---|---|---|
0 | 0x00 | 0 |
1 | 0x01 | 1 |
2 | 0x02 | 2 |
127 | 0x7f | 127 |
128 | 0x80 0x01 | 128 1 |
255 | 0xff 0x01 | 255 1 |
2147483647 | 0xff 0xff 0xff 0xff 0x07 | 255 255 255 255 7 |
9223372036854775807 | 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x7f | 255 255 255 255 255 255 255 255 127 |
-1 | 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x01 | 255 255 255 255 255 255 255 255 255 1 |
-2147483648 | 0x80 0x80 0x80 0x80 0xf8 0xff 0xff 0xff 0xff 0x01 | 128 128 128 128 248 255 255 255 255 1 |
-9223372036854775808 | 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x01 | 128 128 128 128 128 128 128 128 128 1 |
位置
分隔位三个部分的64位值
- x:26个最高位
- z:26个中间位
- y:12个最低位
如下编码:
((x & 0x3FFFFFF) << 38) | ((z & 0x3FFFFFF) << 12) | (y & 0xFFF)
并如下解码:
val = read_unsigned_long(); x = val >> 38; y = val & 0xFFF; z = (val << 26 >> 38);
注意:位移的细节由语言决定,上述内容可能在Java中可以工作但可能不会不经修改就能在其他语言中工作。实际上,你通常会接受到正数,即使实际的坐标是负的。这可以通过加入如下内容修复:
if x >= 2^25 { x -= 2^26 } if y >= 2^11 { y -= 2^12 } if z >= 2^25 { z -= 2^26 }
定点数
一些字段被存储为定点数,其中一定数量的为用于表示有符号整数部分(小数点左侧的数字),其余表示小数部分(小数点右侧)。浮点数(float和double),相反,将数字本身(尾数)存储在内存块中,而小数点(指数)的位置存储在其一边。
本质上,虽然定点数有着比浮点数更小的范围,但是对于较大值来说它们的小数精度要更胜一筹。这使得它们用于表示Minecraft实体的全局坐标非常理想,因为比起将它们精确地定位在一个方块(或米)中,准确地保存它的整数部分要重要得多。
坐标经常被表示为32位整数,其中5个最低位用于小数部分,其余存储整数部分。
Java缺乏对分数整数的直接支持,但是你可以使用整数来表示它们。要将double转换成这种整数表示方法,使用以下公式:
abs_int = (int) (double * 32.0D);
以及反过来:
double = (double) (abs_int / 32.0D);
粒子
字段名称 | 字段类型 | 含义 |
---|---|---|
ID | VarInt | 粒子类型的ID,见下。 |
Data | 可变 | 根据粒子类型可变,见下。 |
粒子名称 | 粒子ID | 数据 | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
minecraft:ambient_entity_effect
|
0 | 无 | |||||||||||||||
minecraft:angry_villager
|
1 | 无 | |||||||||||||||
minecraft:barrier
|
2 | 无 | |||||||||||||||
minecraft:block
|
3 |
| |||||||||||||||
minecraft:bubble
|
4 | 无 | |||||||||||||||
minecraft:cloud
|
5 | 无 | |||||||||||||||
minecraft:crit
|
6 | 无 | |||||||||||||||
minecraft:damage_indicator
|
7 | 无 | |||||||||||||||
minecraft:dragon_breath
|
8 | 无 | |||||||||||||||
minecraft:dripping_lava
|
9 | 无 | |||||||||||||||
minecraft:falling_lava
|
10 | 无 | |||||||||||||||
minecraft:landing_lava
|
11 | 无 | |||||||||||||||
minecraft:dripping_water
|
12 | 无 | |||||||||||||||
minecraft:falling_water
|
13 | 无 | |||||||||||||||
minecraft:dust
|
14 |
| |||||||||||||||
minecraft:effect
|
15 | 无 | |||||||||||||||
minecraft:elder_guardian
|
16 | 无 | |||||||||||||||
minecraft:enchanted_hit
|
17 | 无 | |||||||||||||||
minecraft:enchant
|
18 | 无 | |||||||||||||||
minecraft:end_rod
|
19 | 无 | |||||||||||||||
minecraft:entity_effect
|
20 | 无 | |||||||||||||||
minecraft:explosion_emitter
|
21 | 无 | |||||||||||||||
minecraft:explosion
|
22 | 无 | |||||||||||||||
minecraft:falling_dust
|
23 |
| |||||||||||||||
minecraft:firework
|
24 | 无 | |||||||||||||||
minecraft:fishing
|
25 | 无 | |||||||||||||||
minecraft:flame
|
26 | 无 | |||||||||||||||
minecraft:flash
|
27 | 无 | |||||||||||||||
minecraft:happy_villager
|
28 | 无 | |||||||||||||||
minecraft:composter
|
29 | 无 | |||||||||||||||
minecraft:heart
|
30 | 无 | |||||||||||||||
minecraft:instant_effect
|
31 | 无 | |||||||||||||||
minecraft:item
|
32 |
| |||||||||||||||
minecraft:item_slime
|
33 | 无 | |||||||||||||||
minecraft:item_snowball
|
34 | 无 | |||||||||||||||
minecraft:large_smoke
|
35 | 无 | |||||||||||||||
minecraft:lava
|
36 | 无 | |||||||||||||||
minecraft:mycelium
|
37 | 无 | |||||||||||||||
minecraft:note
|
38 | 无 | |||||||||||||||
minecraft:poof
|
39 | 无 | |||||||||||||||
minecraft:portal
|
40 | 无 | |||||||||||||||
minecraft:rain
|
41 | 无 | |||||||||||||||
minecraft:smoke
|
42 | 无 | |||||||||||||||
minecraft:sneeze
|
43 | 无 | |||||||||||||||
minecraft:spit
|
44 | 无 | |||||||||||||||
minecraft:squid_ink
|
45 | 无 | |||||||||||||||
minecraft:sweep_attack
|
46 | 无 | |||||||||||||||
minecraft:totem_of_undying
|
47 | 无 | |||||||||||||||
minecraft:underwater
|
48 | 无 | |||||||||||||||
minecraft:splash
|
49 | 无 | |||||||||||||||
minecraft:witch
|
50 | 无 | |||||||||||||||
minecraft:bubble_pop
|
51 | 无 | |||||||||||||||
minecraft:current_down
|
52 | 无 | |||||||||||||||
minecraft:bubble_column_up
|
53 | 无 | |||||||||||||||
minecraft:nautilus
|
54 | 无 | |||||||||||||||
minecraft:dolphin
|
55 | 无 | |||||||||||||||
minecraft:campfire_cosy_smoke
|
56 | 无 | |||||||||||||||
minecraft:campfire_signal_smoke
|
57 | 无 |