
注:本文是Drovolon在github上文档的翻译,修改了图片并带有少量补充
(原文地址:https://gist.github.com/Drovolon/24bfaae00d57e7a8ca64b792e14fa7c6)
1.14版本的区块加载机制和之前版本不同。本文是1.14区块加载机制的概论。
在1.14中区块加载由“加载票”开始。一张“加载票”包含:
●“加载票”类型
●加载等级
●剩余存活时间(可以有/没有)
每个区块都有一组有序的“加载票”与其相关。所有被加载的区块都最终源于某种类型的“票”。
加载等级
加载等级的范围是22-44,在正常的游戏中,只会在22-33的范围里。理论上小于22的加载等级是可能的(不过原版不可行)。加载等级44以上是不可能的。
对于给定的区块,只有它的加载等级最低的“票”是有效的。(等级低=加载更多内容)
等级类型
加载等级决定了给定区块中,哪些任务能够被运算。有四种加载等级类型:
●计算实体(旧称“强加载区块”)- 在加载等级31及小于31时,会计算实体。这是玩家能体验到的主要的加载等级。所有的游戏特性都会运行,包括实体运算(生物游荡、刷出以及消失等等)
●基础运算(旧称“弱加载区块”) - 在加载等级32时,会进行基础运算。在这个加载等级,所有的游戏特性都正常运行,除了生物不会被运算。(它们不会游荡、消失等等)红石元器件在这种区块中可以正常运行。
●边界 - 在加载等级33时,是边界类型。这些区块被“加载”了,不过经典的游戏特性不能正常运行。红石元器件不能运行,命令方块不能运行,实体不运行等等。然而比方说,在边界的生物依然占用刷怪上限。
●不可访问 - 加载等级34及其以上。这些区块在各种意义上都没有被加载。然而世界生成会在这些区块中运行(我认为)。
因为不可访问的等级(34+)与正常游戏内容无关,在接下来的文章中会忽略这个等级(主要是为了让图片小一些)—不过从技术层面来讲,它们是存在于游戏中的。
等级传播
加载等级会传播到相邻(8邻接)的区块。对于每张“票”使用“flood fills”算法从“票”的位置传播,每向外一步,增加一级区块加载等级,直到达到上限44为止。例如,如果一个区块的“加载票”的加载等级为30,那么周围的区块是这个样子:

在上图中,灰色的34不会被加载,蓝色的33是边界(没有基础运算),黄色的32会有基础运算(不过没有实体运算),然后绿色的31和30是能运算实体的被加载区块。
注意:上边这个例子中只有一个区块“票”的加载等级为30。其他的区块被加载是由于这个等级为30的“票”。推论:“票”的加载等级越低,被加载范围就越大。
或者如下图所示:

图中“-”表示未加载,“BD”表示边界(BORDER),“TI”表示基础运算(TICKING),“ET”表示实体运算(ENTITY_TICKING)。
当“加载票”有重叠的影响范围,等级低的有效。想象“票”的等级以洪水填充(flood-filling)的形式从“票”中传播出来。它们之间不会结合或叠加。
巧合的是,等级30也是物品通过传送门后使用的等级。所以比方说,如果你将一个物品丢到传送门里,在传送门另一侧,会有3×3的区块可以计算实体,周围围绕一圈“基础运算”和“边界”的区块。
启示
伪和平
如果有人想要做一个伪和平,实现实体被加载,但是不进行运算(这样服务器没有负载)。理想的情况是,你把它们放到“基础运算”或“边界”区块中。可以定期地向地狱门中投掷物品,实现任意位置的永久区块加载。你需要将怪物放到距离地狱门2-3个区块远的位置,这样怪物会在“基础运算”或“边界”区块中。
没有区块加载等级提升(没有5×5加载机制)
注意,与之前版本不同,计算实体的区块(强加载区块)不是由周围有多少区块被加载决定的。如果你使用能修改“加载票”到任意等级的MOD,你可以做出一片任意大的区域,其中每个区块都是“边界”区块,然而没有一个区块会运算实体。
甚至在正常的游戏中也会出现周围5×5区块被加载,而不能运算实体的区块。例如,想象两个精准放置的地狱门,都在定期的向地狱门中投掷物品,使得它们在地狱的“加载票”形成了相邻但不重叠的两片区域:

注意上图中间红色框出部分的包含“基础运算”和“边界”的区块,按照旧版本的5×5加载规则,应该是计算实体的区块(ET),然而它们并没有被提升为计算实体的区块。
“票”范围重叠
在上面的例子中,两个等级为30的“票”距离的足够远,刚好不会互相影响。我们这里将上个例子中两个区块移动的更近一些,使其重叠:

注意,中间位置不像之前一样有“边界”区块(等级33)了。一侧原来应该是等级33的区块被另一侧等级32的区块“覆盖”了。
维度的闲置超时
每个维度(主世界、地狱、末地)都有自己的闲置超时时长。如果这个维度里面有玩家存在,或者有被强制加载的区块(使用/forceload),闲置超时会被禁用。除此之外,每次有实体进入/离开这个维度,闲置超时会被重置为0。如果在其计数到300之前都没有重置数值,服务器会停止进行这个维度的一些运算,直到超时值被重置(玩家进入,实体进入,或区块被强制加载)
●没有实体会被计算/运行
●末影龙不会被更新
●全局的实体不会被计算(不确定是用来干啥的 - 只有闪电?)
“加载票”的类型
这些类型是目前MC中实装了的:
强制
使用“/forceload”指令可以让任意区块获得等级31的“强制”类型加载票。被强制加载的区块被存储在服务器的“世界数据”文件中。在服务器备份的时候,会重设这些区块的强制类型加载票。(换句话说,“/forceload”的加载票能挺过重启)
加载等级31是固定的,会导致如下的加载效果:

或者换成更好的形式:

所以,被强制加载的区块是“计算实体”的,不过和平常一样,周围还会有一圈“基础运算”和“边界”的区块。
如果你想要使用“/forceload”做伪和平,你需要将怪物放在这些TI或者BD区块中。换句话说,强制加载距离怪物一到两个区块远的区块。
如果你愿意使用指令,“/forceload”是最好的强制加载区块的方式。如果不想用指令,请看下面的“传送门”类型加载票。
传送门
在实体通过地狱门时,会将区块的加载票设置为“传送门”类型。设置的区块是包含传送门的那个区块。如果你在主世界通过地狱门投掷一个物品,在地狱与之对应的传送门所在的区块会设置一个“传送门”类型的加载票。加载票的等级为30。
传送门加载票本身没有“剩余存活时间”,不过传送门系统会在传送门300gt内没有使用过之后,移除与之相关的加载票。(不卡的情况下300gt=15秒)
其加载区块的效果图在上文中的加载等级中有给出,那里使用了强度30作为示例。总结来讲:会产生3×3的强加载区块以及围绕一圈“基础运算”区块和“边界”区块。
定期的向地狱门中投掷物品,并在另一个维度定期往回投掷物品,可能是不使用指令的、最好的做永久区块加载器的方法了。(就是两个维度间使用对应的地狱门互相投物品,能同时永久加载主世界和地狱的区块)
传送门缓存和物品对齐
▼关于地狱门缓存的一些细节;如果不感兴趣请跳过
当实体通过地狱门的时候,游戏需要知道另一维度的对应地狱门在哪里。“传送门”加载票某种意义上是作为对应地狱门位置的缓存而出现的。
对于从主世界到地狱,对应的地狱门坐标使用键码值(floor(entity.x/8), floor(entity.z/8))来缓存。换句话说,这个键码值就是主世界映射到地狱的坐标。如果有另一个物品通过同一个地狱门,会进行一样的除法和取整操作。理想情况下,这两个物品算出来的坐标是相同的,第二个物品可以直接使用之前物品找到的地狱门进行传送,不用再次寻找另一侧的地狱门了。因为大多数地狱门小于8格宽,先除以8再取整意味着即使物品坐标有一些偏差,得到的结果也相同。它们都被“压扁”了:主世界的坐标(7.9999,0)和(0,0)对于对应地狱门用的键码值而言,都对应到(0,0)。所以两个在主世界不同位置的物品,都使用同一个缓存的地狱门。
而反过来就有问题了。从地狱到主世界,坐标被缓存在键码值(floor(entity.x*8), floor(entity.z*8))中。在这里,即使是实体位置有很小的差别,也会导致问题。例如,地狱的(0,0)对应主世界的(0,0),然而地狱的(0.2,0)对应主世界的(1,0)!因为它们映射到的键码值不同,这两个通过地狱门的物品,都会在另一侧进行对应地狱门的搜索,这对于服务器的性能而言是一个灾难。
(有多灾难?在地狱设置一个简单的投掷器指向地狱门,将物品传送到主世界的装置。定时地投掷物品,会非常频繁的产生游戏卡顿,以至于游戏没法玩了)
上面这些说的就是:如果你想保持主世界加载,然后你想通过向地狱门中投掷物品来实现这点。那么你需要对齐(比方说)从投掷器中出来的物品,因为不然的话,瞎往地狱门里丢物品,会由于位置不同,导致服务器卡顿。
玩家
“玩家”类型加载票的等级为31。是通过服务器添加给玩家周围一定范围的区块来实现的(周围区块的范围就是服务器的渲染距离)。默认情况下,这意味着10×10的区块会变成“计算实体”区块,外边围一圈“基础运算”区块,再围一圈“边界”区块。
至少这是我在实践中观察到的。这里有一个复杂的“节流”玩家类型加载票的算法,你的距离可能会有所不同。
出生点
“出生点”类型的加载票会被放置在世界的出生点区块,其加载强度为22,是正常游戏中最小的加载强度。这使得出生点周围区块被永久加载,包含19×19的“计算实体”型区块(警告:见上文的“闲置超时”)

或者换成更好的形式:

龙
“龙”加载票类型的加载强度为24。会在屠龙战开始时,给到末地的(0,0)区块,并且在屠龙战结束后移除。
瞬移后
“瞬移后”类型的加载票会在实体被瞬移时添加。无论是使用“/tp”指令,“/spreadplayers”指令,还是通过末地门时。加载票会给到实体的新位置。对于“/tp”指令,加载强度为32(基础运算),而“/spreadplayer”和末地门的加载强度为33(边界)。在这两种情况下,加载票都具有“剩余生存时间”属性,设置为5gt。5gt之后,会自动被加载票系统移除。
未知
我没有深入的调查这个“未知”加载票。这个票在游戏的任意一段代码调用“getChunk”时使用。如果游戏的代码认为这个区块应该被加载,它就会把这个“未知”票给到那个区块(可能在创建它之后)。它的“剩余生存时间”为1gt。
加载强度与游戏想加载区块的类型有关(是否是已经完成世界生成的区块)。它的强度至少会是33(边界)。不过在很多情况下会大于33,这以某种方式与世界生成有关。
例子:生物游荡AI在执行时,会检查某些方块是否有完整上表面。作为这个检查中的一部分,这个区块会有一个强度为33的“未知”类型加载票。
光
我不确定这个是干什么的。看起来是和世界生成相关的。
——翻译:hiback
感谢Fallen_Breath推荐的文章
2019/08/19