Wiki看了,但是比较粗略,没看明白咋回事。
为啥问这个,拆着玩。
我要问的东西:
※ BlockStates标签究竟有多少个long数字?(写提问帖时逐渐感觉到,应该是数目可变,但必定是256的整倍数?可变数目目的是省空间?)
※ 如何从BlockStates标签的long数字查找到Palette里的方块描述?
※ BlockStates标签的long数字和方块坐标的数学关系?
给一个样例:
这个样例是Sections里面的元素之一,也就是“子区块”,是一个复合标签。由于(已确诊)强迫症,byte[]型我给全部转16进制了,所有标签全部铺展开。
子区块提取自r.0.0.mca,xPos = 0,zPos = 0,提取器按照自己的阅读习惯写的。
Section_acquired.txt
(18.79 KB, 下载次数: 17)
为啥问这个,拆着玩。
我要问的东西:
※ BlockStates标签究竟有多少个long数字?(写提问帖时逐渐感觉到,应该是数目可变,但必定是256的整倍数?可变数目目的是省空间?)
※ 如何从BlockStates标签的long数字查找到Palette里的方块描述?
※ BlockStates标签的long数字和方块坐标的数学关系?
给一个样例:
这个样例是Sections里面的元素之一,也就是“子区块”,是一个复合标签。由于(已确诊)强迫症,byte[]型我给全部转16进制了,所有标签全部铺展开。
子区块提取自r.0.0.mca,xPos = 0,zPos = 0,提取器按照自己的阅读习惯写的。
什么都不会,以下内容是看着 wiki 糊纠出来的。
以下所有序数(如「第」、「[索引]」)都是从 0 开始。
※ BlockStates 标签究竟有多少个 long 数字?(写提问帖时逐渐感觉到,应该是数目可变,但必定是256的整倍数?可变数目目的是省空间?)
BlockStates 标签永远要包含 4096(一个子区块所能包含的方块总数,16×16×16=4096)个 Palette 索引,因此其包含多少个 long 数字由每个索引的大小决定.假设每个索引占用 x bits,由于一个 long 可储存 64 bits 的数据,BlockStates 标签含有的总 long 数字个数应当为(索引总数)×(每个索引大小)/(long 储存能力)= 4096・x / 64 = 64x 个(从这里可以看出它一定是 64 的整倍数).而 x 的具体取值每个子区块都可能不同,因为它只需要能存下 Palette 中最大的索引就行了,不然就是浪费空间,易得 x = max(4, log2(Palette 中最大的索引)).以你所贴示例为例,Palette 有 13 个复合标签,因此 x = max(4, log2(13 - 1【这里真的要减一吗?我不知道】)) = 4,BlockStates 总 long 个数 = 64 × 4 = 256.假设 Palette 有 114514 个复合标签,x = 17,BlockStates 总 long 个数 = 64 × 17 = 1088.不过现实里似乎不会出现 114514 个复合标签,因为就算每个坐标上的方块都不一样那也才 4096 种可能…
※ 如何从 BlockStates 标签的 long 数字查找到 Palette 里的方块描述?
不要把它们看成 long 数字.将 BlockStates 里所有玩意打成二进制然后全部串起来,再按照上面得到的 x 重新分割,然后以 BlockStates 索引 =((相对 y 坐标) << 8) + ((相对 z 坐标) << 4) + (相对 x 坐标) 访问分割过后的 BlockStates 数组得到 Palette 索引,最后访问 Palette[Palette 索引] 得到相关数据.
举个例子,我们要访问这个子区块中位于 (1, 2, 3) 的方块,BlockStates 索引 = (1 << 8) + (2 << 4) + 3 = 291,将 BlockStates 按 x = 4 重新分割(即每个 64 bits 的 long 数字分成 16 个 4 bits 的数字),取分割过后的 BlockStates 中的第 291 个元素(即原 BlockStates 中的第 291 / 16 = 18 个 long 数字的第 291 % 16 = 3 组 4 bits )为 Palette 索引.原 BlockStates 的第 18 个 long 数字为 1229782938247303441L,二进制 0b0001000100010001000100010001000100010001000100010001000100010001,分成 16 个 4 bits 数字为 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001,转回十进制为 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,第 3 个数字是 1,因此 Palette 索引为 1.Palette[1] 对应的是基岩,因此 (1, 2, 3) 是基岩.
※ BlockStates 标签的 long 数字和方块坐标的数学关系?
Wiki 有 伪代码,基本上就是我上面做的那一堆事儿,自己看。
以下所有序数(如「第」、「[索引]」)都是从 0 开始。
※ BlockStates 标签究竟有多少个 long 数字?(写提问帖时逐渐感觉到,应该是数目可变,但必定是256的整倍数?可变数目目的是省空间?)
BlockStates 标签永远要包含 4096(一个子区块所能包含的方块总数,16×16×16=4096)个 Palette 索引,因此其包含多少个 long 数字由每个索引的大小决定.假设每个索引占用 x bits,由于一个 long 可储存 64 bits 的数据,BlockStates 标签含有的总 long 数字个数应当为(索引总数)×(每个索引大小)/(long 储存能力)= 4096・x / 64 = 64x 个(从这里可以看出它一定是 64 的整倍数).而 x 的具体取值每个子区块都可能不同,因为它只需要能存下 Palette 中最大的索引就行了,不然就是浪费空间,易得 x = max(4, log2(Palette 中最大的索引)).以你所贴示例为例,Palette 有 13 个复合标签,因此 x = max(4, log2(13 - 1【这里真的要减一吗?我不知道】)) = 4,BlockStates 总 long 个数 = 64 × 4 = 256.假设 Palette 有 114514 个复合标签,x = 17,BlockStates 总 long 个数 = 64 × 17 = 1088.不过现实里似乎不会出现 114514 个复合标签,因为就算每个坐标上的方块都不一样那也才 4096 种可能…
※ 如何从 BlockStates 标签的 long 数字查找到 Palette 里的方块描述?
不要把它们看成 long 数字.将 BlockStates 里所有玩意打成二进制然后全部串起来,再按照上面得到的 x 重新分割,然后以 BlockStates 索引 =((相对 y 坐标) << 8) + ((相对 z 坐标) << 4) + (相对 x 坐标) 访问分割过后的 BlockStates 数组得到 Palette 索引,最后访问 Palette[Palette 索引] 得到相关数据.
举个例子,我们要访问这个子区块中位于 (1, 2, 3) 的方块,BlockStates 索引 = (1 << 8) + (2 << 4) + 3 = 291,将 BlockStates 按 x = 4 重新分割(即每个 64 bits 的 long 数字分成 16 个 4 bits 的数字),取分割过后的 BlockStates 中的第 291 个元素(即原 BlockStates 中的第 291 / 16 = 18 个 long 数字的第 291 % 16 = 3 组 4 bits )为 Palette 索引.原 BlockStates 的第 18 个 long 数字为 1229782938247303441L,二进制 0b0001000100010001000100010001000100010001000100010001000100010001,分成 16 个 4 bits 数字为 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001,转回十进制为 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,第 3 个数字是 1,因此 Palette 索引为 1.Palette[1] 对应的是基岩,因此 (1, 2, 3) 是基岩.
※ BlockStates 标签的 long 数字和方块坐标的数学关系?
Wiki 有 伪代码,基本上就是我上面做的那一堆事儿,自己看。
SPGoding 发表于 2021-5-20 02:38
什么都不会,以下内容是看着 wiki 糊纠出来的。
以下所有序数(如「第」、「[索引]」)都是从 0 开始。
说点新发现,这次24种BlockStates拆出了342个long(不能被64整除),每一个long似乎都最高四位不储存数值(上述截图低位在左)
最后一个long应该只存了4个5位二进制数字,且341 * 12 + 4 == 4096;因而我估计这种情况似乎是每一个long用12 * 5 = 60位用来存索引,剩下四个吃干饭。
进一步结论还得等我实现“把拆出来的long数组还原回去,并且还原结果能正常被MC读出来”之后,才能得到验证……
ItIsEnderman 发表于 2021-5-21 18:44
说点新发现,这次24种BlockStates拆出了342个long(不能被64整除),每一个long似乎都最高四位不储 ...
可以回顾一下1.16快照20w17a的更新日志,mojang牺牲了存档大小来提升效率,所以多出来的空位不再使用