世界生成 (Worldgen)

预计阅读时间: 12 分钟

如何使用 KubeJS 修改世界生成

1.16.5此事件不完整,只能做基本的事情。 1.18.2生物群系过滤器 1.19.2生物群系过滤器 1.20.11.20.1上的KubeJS世界生成不太好。(不起作用)

1.19.2

生物群系过滤器 (Biome Filters)

生物群系过滤器的工作方式类似于配方过滤器(请参阅 /tutorials/recipes#removing-recipes)。

它们可用于创建复杂且精确的过滤器,以微调您的特性在世界中可能或不可能生成的确切位置。

它们用于特性的 biomes 字段,可能如下所示:

onEvent('worldgen.add', event => {
  event.addOre(ore => {
    // 首先让我们看一下所有的"简单"过滤器
    ore.biomes = 'minecraft:plains' 		// 仅在这个生物群系中生成
    ore.biomes = /^minecraft:.*/			// 在所有匹配给定模式的生物群系中生成(这里:任何以 minecraft: 开头的)
    ore.biomes = '#minecraft:is_forest' 	// [1.19+] 在所有标记为 'minecraft:is_forest' 的生物群系中生成
    ore.biomes = '^nether' 				// [仅1.18!] 在 'nether' 类别中的所有生物群系中生成(请参阅生物群系类别)
    ore.biomes = '$hot'					// [仅Forge 1.18!] 在所有具有 'hot' 生物群系类型的生物群系中生成(请参阅生物群系词典)
    // 过滤器可以使用 AND、OR 和 NOT 逻辑任意组合
    ore.biomes = {}						// 空的 AND 过滤器,始终为 true
    ore.biomes = []						// 空的 OR 过滤器,也始终为 true
    ore.biomes = { not: 'minecraft:ocean' } // 在所有不是 'minecraft:ocean' 的生物群系中生成
    // 由于 AND 过滤器表示为映射并期望字符串键,
    // 所有"原始"过滤器也可以表示为这样
    ore.biomes = {					// 请参阅上面了解这些过滤器的解释
      id: 'minecraft:plains',
      id: /^minecraft:.*/,			// 正则表达式(技术上也是 ID 过滤器)
      tag: '#minecraft:is_forest',
      category: '^nether',
      biome_type: '$hot',
    }
    // 请注意,上述所有语法可以单独混合和匹配
    // 例如,这将在任何生物群系中生成特性,该生物群系
    // 要么是平原,要么是不在下界或热带草原类别的炎热生物群系
    ore.biomes = [
      'minecraft:plains', {
        biome_type: '$hot',
        not: [
          '#nether',
          { category: 'savanna' }
        ]
      },
    ]
  })
})

规则测试和目标 (Rule Tests and Targets)

在1.18中,Minecraft世界生成已更改为基于 target 的替换系统。

这意味着您可以在同一个特性配置中指定要替换为其他方块的特定方块。

例如,这用于将石头替换为普通矿石,将深板岩替换为深板岩矿石变体。

每个目标都获取一个"规则集"作为输入(检查给定方块状态是否应该被替换)并产生特定的输出方块状态。

在KubeJS脚本端,这两个概念都在同一个类中表示 - BlockStatePredicate

从语法上讲,BlockStatePredicate 与生物群系过滤器非常相似,因为它们也可以使用 AND/OR 过滤器组合(这就是为什么我们不会在这里重复这一步)。

它们可用于匹配三种不同的东西:

  1. 方块

    • 这些被解析为字符串,即 'minecraft:stone' 来匹配石头。
  2. 方块状态

    • 这些被解析为方块ID后跟属性数组,即 "minecraft:furnace[lit=true]" 来匹配激活(点燃)的熔炉方块。

    • 您可以使用F3以及调试棒来找出方块属性以及可能的值。

  3. 方块标签

    • 这些以"熟悉的"标签语法解析,即 "#minecraft:base_stone_overworld" 来匹配地下可以找到的所有类型的石头。

    • 请注意,这些是方块标签,而不是物品标签,因此它们可能会有所不同。

您也可以对块过滤器使用正则表达式,即 /^mekanism:.*_ore$/。但是,这不会匹配方块状态属性!

当需要 RuleTest 而不是 BlockStatePredicate 时,您也可以直接以JS对象的形式提供该规则测试。

然后它将像原版解析JSON或NBT对象一样进行解析。

高度提供器 (Height Providers)

另一个最初可能看起来有点令人困惑的系统是"高度提供器"系统,用于确定给定矿石应该在哪个Y级别生成以及以什么频率生成。

与此功能一起使用的是所谓的"垂直锚点",用于获取相对于特定锚点(即世界顶部或底部)的高度。

在KubeJS中,这个系统已经简化了一些。最常见的矿石放置类型是:

  • uniform(均匀)

    • 特性在两个锚点之间的任何位置都有相同的生成机会。
  • triangle(三角形)

    • 特性更可能在两个锚点的中心生成,而不是在更外围生成。

要使用这些,您可以在 AddOreProperties 中使用 uniformHeighttriangleHeight

垂直锚点也已简化,因为您可以在 AddOreProperties 中使用 aboveBottom / belowTop 辅助方法。

如果您想将绝对高度指定为简单数字,您也可以在新版本的KubeJS中使用 VerticalAnchor

生物群系类别 (Biome Categories)

生物群系类别是一个原版系统,可用于将生物群系大致分类到预定义类别中,包括:

  • taiga(针叶林)

  • extreme_hills(极端山丘)

  • jungle(丛林)

  • mesa(平顶山)

  • plains(平原)

  • savanna(热带草原)

  • icy(冰原)

  • the_end(末地)

  • beach(海滩)

  • forest(森林)

  • ocean(海洋)

  • desert(沙漠)

  • river(河流)

  • swamp(沼泽)

  • mushroom(蘑菇岛)

  • nether(下界)

其他模组可能会添加更多类别。

生物群系词典(仅Forge)(Biome Dictionary)

与原版生物群系类别非常相似,Forge使用"生物群系词典"根据生物群系的属性对其进行分类,这些属性包括:

  • hot(炎热)

  • cold(寒冷)

  • wet(潮湿)

  • dry(干燥)

  • sparse(稀疏)

  • dense(茂密)

  • spooky(阴森)

  • dead(死寂)

  • lush(葱郁)

有关更多信息,请参见 BiomeDictionary

这个系统设计用于被模组扩展。

在1.19中,这两个系统都已被移除且没有替代品,转而支持生物群系标签!

生成步骤 (Generation Steps)

  1. raw_generation(原始生成)

  2. lakes(湖泊)

  3. local_modifications(局部修改)

  4. underground_structures(地下结构)

  5. surface_structures(地表结构)

  6. strongholds(要塞)

  7. underground_ores(地下矿石)

  8. underground_decoration(地下装饰)

  9. vegetal_decoration(植被装饰)

  10. top_layer_modification(顶层修改)

下界矿石在 underground_decoration 步骤中生成!

您可能无法在其层中生成某些东西,例如泥土中的矿石,因为泥土还没有生成。

在这种情况下,您可能必须通过调用 ore.worldgenLayer = 'top_layer_modification' 将层更改为上述生成步骤之一。

但是,不建议这样做。

示例脚本 (Example Script)

onEvent('worldgen.add', event => {
  // 使用事件中的 anchors 辅助方法(注意:这需要较新版本的 KubeJS)
  // 如果您使用的是旧版本的 KubeJS,可以使用矿石属性类中的方法
  const { anchors } = event

  event.addOre(ore => {
    ore.id = 'kubejs:glowstone_test_lmao' // (可选,但推荐) 特性的自定义ID
    ore.biomes = {
      not: '^savanna' // 生物群系过滤器,见上文(技术上也是可选的)
    }

    // 如何使用目标的示例
    ore.addTarget('#minecraft:stone_ore_replaceables', 'minecraft:glowstone') // 将原版 stone_ore_replaceables 标签中的任何东西替换为荧石
    ore.addTarget('minecraft:deepslate', 'minecraft:nether_wart_block')       // 将深板岩替换为地狱疣方块
    ore.addTarget([
      'minecraft:gravel',     // 替换沙砾...
      /minecraft:(.*)_dirt/   // 或任何种类的泥土(包括粗泥土、缠根泥土等)...
    ], 'minecraft:tnt')       // 用 TNT 替换(相信我,会很有趣)

    ore.count([15, 50])             // 生成15到50个矿脉(随机选择),您可以在这里使用单个数字来表示固定数量的方块
      .squared()                    // 随机将矿石分散在区块中,而不是在一列中生成它们
      .triangleHeight(				    // 以三角形分布生成矿石,这意味着它更可能放置在锚点中心附近
        anchors.aboveBottom(32),    // 下限应该是世界底部上方32个方块,因此在这种情况下,Y = -32,因为 minY = -64
        anchors.absolute(96)	      // 上限恰好设置为 Y = 96
      )								            // 总的来说,矿石可以在 Y 级别 -32 和 96 之间找到,最可能在 Y = (96 + -32) / 2 = 32

    // 更多可选参数(此处显示默认值)
    ore.size = 9                            // 最大矿脉大小
    ore.noSurface = 0.5                     // 如果矿石暴露在空气中,丢弃的几率
    ore.worldgenLayer = 'underground_ores'  // 矿石应该在哪个生成步骤中生成(见下文)
    ore.chance = 0							// 如果 != 0 且 count 未设置,矿石每个区块有 1/n 的生成几率
  })

  // 哦对了,我提到湖泊也存在吗?
  // (至少目前是这样,Vanilla 将来可能会移除它们)
  event.addLake(lake => {
    lake.id = 'kubejs:funny_lake' // BlockStatePredicate
    lake.chance = 4
    lake.fluid = 'minecraft:lava'
    lake.barrier = 'minecraft:diamond_block'
  })
})

onEvent('worldgen.remove', event => {
  console.info('HELP')
  //console.debugEnabled = true

  // 打印给定生物群系过滤器的所有特性
  event.printFeatures('', 'minecraft:plains')

  event.removeOres(props => {
    // 与添加矿石非常相似,这支持按世界生成层过滤...
    props.worldgenLayer = 'underground_ores'
    // ...和按生物群系过滤
    props.biomes = [
      { category: 'icy' },
      { category: 'savanna' },
      { category: 'mesa' }
    ]

    // BlockStatePredicate 从给定生物群系中移除铁矿石和铜矿石
    // 不幸的是,这里不能使用标签...
    props.blocks = ['minecraft:iron_ore', 'minecraft:copper_ore']
  })

  // 按ID移除特性(第一个参数是生成步骤)
  event.removeFeatureById('underground_ores', ['minecraft:ore_coal_upper', 'minecraft:ore_coal_lower'])
})