史莱姆区块判定
基本信息
| 属性 | 值 |
|---|---|
| 类 | 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),这一点与随机性无关,是确定性的。