Worldgen¶
原文:Worldgen
🔗 联动:本章只负责「在已有世界里加矿石/湖等地物」。想搞自定义维度(新世界)或结构生成(放置建筑/村庄式结构)?KubeJS 1.20.1 的 WorldgenEvents 管不了这些,请看 36 · 维度与结构生成(数据包 JSON + KubeJS 联动)。
通用说明¶
生物群系过滤器:¶
生物群系过滤器的工作原理与_配方过滤器_类似,可用于创建复杂而精确的过滤器,以微调你的地物可以在世界的哪些位置生成、不能在哪些位置生成。它们用于地物的 biomes 字段,可能看起来像这样:
WorldgenEvents.add(event => {
event.addOre(ore => {
// let's look at all of the 'simple' filters first
ore.biomes = 'minecraft:plains' // only spawn in exactly this biome
ore.biomes = /^minecraft:.*/ // spawn in all biomes that match the given pattern
ore.biomes = '#minecraft:is_forest' // spawn in all biomes tagged as 'minecraft:is_forest'
// filters can be arbitrarily combined using AND, OR and NOT logic
ore.biomes = {} // empty AND filter, always true
ore.biomes = [] // empty OR filter, always true
ore.biomes = { not: 'minecraft:ocean' } // spawn in all biomes that are NOT 'minecraft:ocean'
// since AND filters are expressed as maps and expect string keys,
// all of the 'primitive' filters can also be expressed as such
ore.biomes = { // see above for an explanation of these filters
id: 'minecraft:plains',
id: /^minecraft:.*/, // regex (also technically an ID filter)
tag: 'minecraft:is_forest',
}
// note all of the above syntax may be mixed and matched individually
})
})
规则测试与目标:¶
在 1.18 中,Minecraft 世界生成已改为「基于目标」的替换系统,这意味着你可以在同一个地物配置中指定将特定方块替换为特定的其他方块。(例如,这用于将石头替换为普通矿石,将深板岩替换为深板岩矿石变种)。
每个目标都会接收一个「规则测试」作为输入(用于检查给定的方块状态是否应该被替换),并产生一个特定的输出方块状态。在编写脚本时,这两个概念都用同一个类来表示:BlockStatePredicate。
从语法上讲,BlockStatePredicate 与生物群系过滤器非常相似,因为它们也可以用 AND 或 OR 过滤器组合(这就是为什么我们不会在这里重复那一步),并且基本上可以用来匹配三种不同的东西:
- 方块: 这些被简单地解析为字符串,例如
'minecraft:stone'用于匹配石头 - 方块状态: 这些被解析为方块 ID 后跟一组属性。你可以使用类似
'minecraft:furnace[lit=true]'的内容来只匹配已点燃的熔炉方块。你可以使用F3来查看方块属性,也可以通过调试棒查看可能的值。 - 方块标签: 这些以「熟悉的」标签语法解析,因此你可以使用
'#minecraft:base_stone_overworld'来匹配主世界中可以在地下生成的所有类型的石头。
提示 请注意这些是方块标签,不是物品标签。它们可能(而且很可能)是不同的!(F3 是你的好朋友!) > 提示 你也可以在方块过滤器中使用正则表达式,因此 /^mekanism:.+_ore$/ 会匹配任何来自通用机械(Mekanism)的 ID 以 _ore 结尾的方块。请记住这不会匹配方块状态属性! > 提示 当需要 RuleTest 而不是 BlockStatePredicate 时,你也可以直接以 JavaScript 对象的形式提供该规则测试(它会像原版解析 JSON 或 NBT 对象一样被解析)。如果你想要有随机匹配几率的规则测试,这会很有用。
关于目标如何工作的更多示例可以在下面的示例脚本中找到。
高度提供器:¶
另一个乍看之下可能有点令人困惑的系统是「高度提供器」系统,它用于确定给定的矿石应该在哪个 Y 高度生成以及生成频率。与此特性配合使用的是所谓的「垂直锚点」,它可以用来获取某个东西相对于特定锚点(例如世界的顶部或底部)的高度。
在 KubeJS 中,这个系统被简化了一些,以便脚本开发者更容易使用。有两种常见的矿石放置类型:
- 均匀分布(Uniform):在两个锚点之间的任何位置生成的概率相同
- 三角形分布(Triangle):在两个锚点中心生成的可能性比在更靠外的位置生成的可能性更大
要使用这两种方式,你可以分别在 AddOreProperties 中使用 uniformHeight 和 traingleHeight 方法。垂直锚点也被简化了,你可以在 AddOreProperties 中使用 aboveBottom / belowTop 辅助方法。
同样,更多信息请参阅示例脚本!
¶
示例脚本¶
WorldgenEvents.add(event => {
// use the anchors helper from the event
const { anchors } = event
event.addOre(ore => {
ore.id = 'kubejs:glowstone_test_lmao' // (optional, but recommended) custom id for the feature
ore.biomes = {
not: 'minecraft:savanna' // biome filter, see above (technically also optional)
}
// examples on how to use targets
ore.addTarget('#minecraft:stone_ore_replaceables', 'minecraft:glowstone') // replace anything in the vanilla stone_ore_replaceables tag with Glowstone
ore.addTarget('minecraft:deepslate', 'minecraft:nether_wart_block') // replace Deepslate with Nether Wart Blocks
ore.addTarget([
'minecraft:gravel', // replace gravel...
/minecraft:(.*)_dirt/ // or any kind of dirt (including coarse, rooted, etc.)...
], 'minecraft:tnt') // with TNT (trust me, it'll be funny)
ore.count([15, 50]) // generate between 15 and 50 veins (chosen at random), you could use a single number here for a fixed amount of blocks
.squared() // randomly spreads the ores out across the chunk, instead of generating them in a column
.triangleHeight( // generate the ore with a triangular distribution, this means it will be more likely to be placed closer to the center of the anchors
anchors.aboveBottom(32), // the lower bound should be 32 blocks above the bottom of the world, so in this case, Y = -32 since minY = -64
anchors.absolute(96) // the upper bound, meanwhile is set to be just exactly at Y = 96
) // in total, the ore can be found between Y levels -32 and 96, and will be most likely at Y = (96 + -32) / 2 = 32
// more, optional parameters (default values are shown here)
ore.size = 9 // max. vein size
ore.noSurface = 0.5 // chance to discard if the ore would be exposed to air
ore.worldgenLayer = 'underground_ores' // what generation step the ores should be generated in (see below)
ore.chance = 0 // if != 0 and count is unset, the ore has a 1/n chance to generate per chunk
})
// oh yeah, and did I mention lakes exist, too?
// (for now at least, Vanilla is likely to remove them in the future)
event.addLake(lake => {
lake.id = 'kubejs:funny_lake' // BlockStatePredicate
lake.chance = 4
lake.fluid = 'minecraft:lava'
lake.barrier = 'minecraft:diamond_block'
})
})
WorldgenEvents.remove(event => {
// print all features for a given biome filter
event.printFeatures('', 'minecraft:plains')
event.removeOres(props => {
// much like ADDING ores, this supports filtering by worldgen layer...
props.worldgenLayer = 'underground_ores'
// ...and by biome
props.biomes = [
{ category: 'icy' },
{ category: 'savanna' },
{ category: 'mesa' }
]
// BlockStatePredicate to remove iron and copper ores from the given biomes
// Note tags may NOT be used here, unfortunately...
props.blocks = ['minecraft:iron_ore', 'minecraft:copper_ore']
})
// remove features by their id (first argument is a generation step)
event.removeFeatureById('underground_ores', ['minecraft:ore_coal_upper', 'minecraft:ore_coal_lower'])
})
生成步骤¶
raw_generationlakeslocal_modificationsunderground_structuressurface_structuresstrongholdsunderground_oresunderground_decorationfluid_springsvegetal_decorationtop_layer_modification