史莱姆区块判定

基本信息

属性 值
类 com.github.lunatrius.core.world.chunk.ChunkHelper
唯一方法 public static boolean isSlimeChunk(long seed, int x, int z)
内部状态 private static final Random RANDOM = new Random();
内部调用方 无(grep -rn "ChunkHelper" 只命中自身声明)

实现

源码逐行如下(seed + (long) (x * x * 0x4c1906) + (long) (x * 0x5ac0db) + (long) (z * z) * 0x4307a7L + (long) (z * 0x5f24f) ^ 0x3ad8025fL):

步骤 源码
1. 设种子 RANDOM.setSeed(...)
2. 判定 return RANDOM.nextInt(10) == 0;

源码自带一条注释解释了那些 (long) 强转的用意:

// noinspection IntegerMultiplicationImplicitCastToLong - we want to do the casts as integers and *then* cast

即乘法先在 int 精度下溢出,再转 long——必须保留原版行为,不能改成全程 long 运算。

常量表

常量 值 出现次数
0x4c1906 4977926 乘 x * x
0x5ac0db 5947611 乘 x
0x4307a7L 4394407 乘 z * z
0x5f24f 389711 乘 z
0x3ad8025fL 987274911 异或收尾
判定阈值 — nextInt(10) == 0,即 1/10 概率

移位与异或

整个表达式为 (seed + …) ^ 0x3ad8025fL:四项加法全部在 long 下求和,最后才与常量异或(^ 的优先级低于 +)。

语义

属性 值
参数 x / z 区块坐标(非方块坐标)
返回值 该区块是否满足史莱姆方块生成条件
依赖世界种子 是,传入 seed 即为当前世界种子

本方法不检查史莱姆方块是否实际生成,只复现原版的随机判定部分——与原版 SlimeChunk 判定逻辑一致,但原版还额外要求 Y 坐标在 10 以下。

[!WARNING] RANDOM 是所有调用方共享的一个静态 Random 实例,而 isSlimeChunk 内部会 setSeed 改写它的状态。因此该方法不是线程安全的:多线程并发调用会互相污染种子。类中已有一条注释说明乘法的精度意图,但共享 Random 的线程安全问题未作处理。

[!NOTE] 连续两次以相同 (seed, x, z) 调用会得到相同结果(因为每次都重新 setSeed),这一点与随机性无关,是确定性的。

相关条目