世界生成
基本信息
| 属性 | 值 | 来源 |
|---|---|---|
| 注册点 | GameRegistry.registerWorldGenerator(new DraconicWorldGenerator(), 0) |
CommonProxy.java:258(registerWorldGen(),由 CommonProxy.java:156 调用) |
| 注册优先级 | 0 |
同上 |
| 实现类 | DraconicWorldGenerator implements IWorldGenerator |
common/world/DraconicWorldGenerator.java:16 |
| 源码规模 | common/world/ 4 个类:DraconicWorldGenerator / ChaosWorldGenHandler / WorldGenEnderComet / WorldGenEnderIsland |
目录枚举 |
| 产物 | 龙矿 draconiumOre、末影彗星、混沌岛 |
见下 |
本条目是本 wiki 中唯一记录世界生成的页面。生成逻辑全部在服务端侧(common/),客户端不做任何补偿。
三个分支的总入口
DraconicWorldGenerator.generate 按 world.provider.dimensionId 分派(DraconicWorldGenerator.java:23-66,switch 在 :25):
| dimensionId | 方法 | 生成内容 |
|---|---|---|
0(主世界) |
generateSurface |
仅龙矿 |
1(末地) |
generateEnd |
末影彗星 + 混沌岛 + 龙矿 |
-1(下界) |
generateNether |
仅龙矿 |
| 其它 | 匿名分支 | 仅龙矿,受黑白名单控制 |
主世界与下界不生成彗星与混沌岛 —— 这两项是末地专属。
龙矿生成
四个分支共用 addOreSpawn(block, world, random, chunkX*16, chunkZ*16, minVainSize, maxVainSize, chancesToSpawn, minY, maxY)(DraconicWorldGenerator.java:106-118)。
| 维度 | 最小矿脉 | 最大矿脉 | 生成权重 | minY | maxY | 开关配置项 | 权重配置项 |
|---|---|---|---|---|---|---|---|
| 主世界 | 3 | 4 | 2 | 2 | 8 | disableOreSpawnOverworld(默认 false) |
oreWeightOverworld(2) |
| 末地 | 4 | 5 | 10 | 1 | 70 | disableOreSpawnEnd(默认 false) |
oreWeightEnd(10) |
| 下界 | 3 | 4 | 5 | 1 | 125 | disableOreSpawnNether(默认 false) |
oreWeightNether(5) |
| 其它维度 | 3 | 4 | 2 | 2 | 8 | 黑白名单 | oreWeightDefault(2) |
引用:DraconicWorldGenerator.java:68-72(主世界)、74-86(末地)、88-101(下界)、53-65(其它维度)。全部权重与开关的默认值见配置项总览。
末地龙矿的权重(10)与垂直跨度(Y 1–70)都明显高于其它维度,是寻找龙矿的主战场。
addOreSpawn 的三宿主方块
addOreSpawn 的循环体对每一次尝试都连续生成三条矿脉(DraconicWorldGenerator.java:112-116):
| 宿主方块 | 矿脉大小 | 引用 |
|---|---|---|
Blocks.end_stone(末地石) |
minVainSize + random.nextInt(maxVainSize - minVainSize)(随机) |
DraconicWorldGenerator.java:112 |
Blocks.stone(石头) |
固定 3 | DraconicWorldGenerator.java:114 |
Blocks.netherrack(下界岩) |
随机(同 end_stone) | DraconicWorldGenerator.java:115-116 |
即:在任何维度中,代码都会尝试在末地石、石头、下界岩三种宿主上各替换一次。在主世界只有 stone 那一条会命中,另外两条因为世界里不存在对应方块而空转。这是无害的冗余,但读源码时容易误以为「主世界会生成末地石」。
坐标计算:posX = chunkXPos + random.nextInt(16),posZ 同理;posY = minY + random.nextInt(maxY - minY)(不含上界 maxY)。
自定义维度的黑白名单
其它维度分支(DraconicWorldGenerator.java:35-65)依次做两次判定:
- 白名单优先:
oreGenDimensionWhitelist长度 > 0 时,当前 dimensionId 不在其中则直接return(DraconicWorldGenerator.java:36-47) - 黑名单:
oreGenDimentionBlacklist中的任一维度则return(DraconicWorldGenerator.java:48-52)
两个列表默认为空 int[]。因为白名单先判定,同时填两者时白名单胜出。oreGenDimentionBlacklist 的拼写错误(Dimention)来自源码本身。
末影彗星
仅末地,DraconicWorldGenerator.generateEnd(DraconicWorldGenerator.java:74-86)。四个条件全部满足才生成:
| 条件 | 来源 |
|---|---|
cometsEnabled(静态开关,默认 true) |
DraconicWorldGenerator.java:19 |
ConfigHandler.generateEnderComets(配置项,默认 true) |
DraconicWorldGenerator.java:78 |
Math.sqrt(x * x + z * z) > 200 |
DraconicWorldGenerator.java:79 |
random.nextInt(Math.max(1, cometRarity)) == 0 |
DraconicWorldGenerator.java:80 |
cometRarity 默认 10000,即平均每 10000 次末地区块生成尝试才命中 1 次(ConfigHandler.java 的 cometRarity 声明)。
⚠️ 半径 200 的判定用的是区块角坐标:generateEnd 收到的 x / z 已经是 chunkX * 16 / chunkZ * 16(DraconicWorldGenerator.java:27),而彗星实际落点 x1 / z1 是该角坐标再加 random.nextInt(16)(DraconicWorldGenerator.java:75、:77)。因此判定与落点之间存在最多 16 格的偏差,且靠近半径边界时表现不是严格圆形。
落点高度:y = 20 + random.nextInt(170),即 Y 20–189(DraconicWorldGenerator.java:76)。
生成器为 WorldGenEnderComet(common/world/WorldGenEnderComet.java)。
混沌岛
仅末地,双开关同时打开才生成(DraconicWorldGenerator.java:82-83):chaosIslandsEnabled(静态,默认 true,DraconicWorldGenerator.java:18)与 ConfigHandler.generateChaosIslands(默认 true)。调用 ChaosWorldGenHandler.generateChunk(world, x / 16, z / 16, null, random),第三个参数 null 表示由网格自动决定岛屿中心。
岛屿中心网格
ChaosWorldGenHandler.getClosestChaosSpawn(ChaosWorldGenHandler.java:174-178):
new DataUtils.XZPair<>(
Utils.getNearestMultiple(chunkX * 16, ConfigHandler.chaosIslandSeparation),
Utils.getNearestMultiple(chunkZ * 16, ConfigHandler.chaosIslandSeparation))
即岛屿中心落在间距为 chaosIslandSeparation 的方格网上,间距默认 10000 格(ConfigHandler.java:290-295)。源码 Javadoc 写的是「a 10000 by 10000 grid」(ChaosWorldGenHandler.java:31-32)—— 这只是默认值,实际间距可配置。
⚠️ 原点 (0, 0) 处的岛屿永不生成:generateChunk 开头有 if (closestSpawn.x == 0 && closestSpawn.z == 0) return;(ChaosWorldGenHandler.java:39)。GeneratorOverride.getNearestChaosIslandCenter 也重复了这一约定。
地形与结构
generateChunk 先做 180 格的快速排除(copyStartDistance = 180,ChaosWorldGenHandler.java:42-44),随后按 y 从 0 到 254 遍历,用三层衰减函数算出 density,仅当 density > 0.1 时才在 y + 64 处放置方块(ChaosWorldGenHandler.java:51-99)。地形替换规则是 (dist > 60 || dist > random.nextInt(60)) ? end_stone : obsidian(ChaosWorldGenHandler.java:96)—— 距中心 60 格内大多被替换为黑曜石。
generateStructures 只在中心落在本区块范围内时被调用(ChaosWorldGenHandler.java:46-49),内容包括:
| 结构 | 参数 | 引用 |
|---|---|---|
| 混沌核心(洞窟) | shardY = 80(:106),coreHeight = 10(:108,核心跨 Y 70–90),coreWidth = 20(:109),outerRadius = 330(:103) |
ChaosWorldGenHandler.java:102-120 |
| 混沌晶体 | 中心放置 ModBlocks.chaosCrystal,并写入 locationHash |
ChaosWorldGenHandler.java:122-125 |
| 混沌守卫 | 晶体处生成并立刻 spawnEntityInWorld 一个 EntityChaosGuardian |
ChaosWorldGenHandler.java:127-129 |
| 4 圈环带 | rings = 4(:132),width = 20(:133),spacing = 8(:134),高度 90 + (islandCenter.x - x) * 0.1 + (random.nextInt(10) - 5)(:141,随机项取 -5…4) |
ChaosWorldGenHandler.java:131-147 |
| 方尖碑 | 内圈 7 座(半径 45,i * 0.9D 弧度,:182-187)+ 外圈 14 座(半径 90,i * 0.45D 弧度,:189-194),均从 Y 90 起;方法在 :180-195 |
ChaosWorldGenHandler.java:180-195 |
环带上每格有两次随机填充(注意 0.1F 与 0.001F 的量级差别):
| 概率 | 方块 | 引用 |
|---|---|---|
10%(0.1F) |
Blocks.end_stone |
ChaosWorldGenHandler.java:142 |
0.1%(0.001F) |
ModBlocks.draconiumOre |
ChaosWorldGenHandler.java:143 |
龙矿那 0.1% 是末地除常规龙矿外唯一的额外龙矿来源。
环带高度公式里用的是 islandCenter.x - x 而不是 islandCenter.z - z(ChaosWorldGenHandler.java:141),因此环带整体只沿 X 方向倾斜,沿 Z 方向是平的。
对外 API:GeneratorOverride
api/GeneratorOverride.java 是本模组 3 个 api/ 类之一(另两个为 IExtendedRFStorage 与 package-info),供附属模组接管生成逻辑。
| 方法 | 作用 | 引用 |
|---|---|---|
spawnCometAt(World, x, y, z, Random) |
实例方法,在指定坐标生成一颗彗星 | GeneratorOverride.java:25-27 |
generateChaosChunk(World, chunkX, chunkZ, centerX, centerZ, Random) |
静态,在指定中心生成混沌岛区块(绕过网格)。Javadoc 要求对 360×360 区块区域内的每个区块都调用一次(GeneratorOverride.java:37-47) |
GeneratorOverride.java:48-52 |
setChaosIslandsEnabled(boolean) |
静态,运行时改 chaosIslandsEnabled |
GeneratorOverride.java:57-59 |
setCometsEnabled(boolean) |
静态,运行时改 cometsEnabled |
GeneratorOverride.java:64-66 |
setOreEnabledInEnd(boolean) |
静态,运行时改 oreEnabledInEnd |
GeneratorOverride.java:72-74 |
getNearestChaosIslandCenter(chunkX, chunkZ) |
静态,查询某区块所属的岛屿中心,返回 ChunkCoordinates(x, 80, z) 或 null(Y 硬编码 80,见 :93) |
GeneratorOverride.java:88-94 |
spawnChaosIslendAt(...) |
@Deprecated(:32),Javadoc 自述「This nolonger dose anything!」(:30) |
GeneratorOverride.java:33-35 |
setOreEnabledInEnd 的参数名与实际字段不符
public static void setOreEnabledInEnd(boolean cometsEnabled) { // 参数名 cometsEnabled
DraconicWorldGenerator.oreEnabledInEnd = cometsEnabled;
}
参数名 cometsEnabled 是从上一个方法复制粘贴残留(GeneratorOverride.java:71-73)。赋值目标是正确的 oreEnabledInEnd,只是参数名会误导调用方 —— 位置参数不影响行为。
另外 WorldGenEnderIsland 类只被这个 @Deprecated 方法使用(GeneratorOverride.java:34);该方法被标注为无效,正常生成流程不经过它。
已知的 API 交互细节
GeneratorOverride 提供的三个 set*Enabled 直接写 DraconicWorldGenerator 的 public static 字段,因此必须在启动阶段调用(源码 Javadoc 明确写「Use this at startup」,GeneratorOverride.java:55,62,69)。运行中改值只会影响此后新生成的区块,不会回溯已有区块。
getNearestChaosIslandCenter 的 Y 固定返回 80,与 generateStructures 中 shardY = 80 一致(ChaosWorldGenHandler.java:106)。