20.3.1 世界生成


一、群系过滤器

1.18.2中,你可以使用群系类别(Biome Categories)或者群系类型(Biome type,仅Forge可用)来作为群系过滤器。

下方示例以添加矿石为例展示的群系过滤器的使用方法。

onEvent('worldgen.add', event => {
	event.addOre((ore) => {
	  // 1.16.5 及以上版本:
      ore.biomes = "minecraft:plains" 		// 仅在单一群系生成
      ore.biomes = /^minecraft:.*/			// 在所有ID与给定格式相符的群系中生成(此处为在所有原版群系中生成)
      // 1.18.2 新增:
      ore.biomes = "^nether" 				// 在群系类别“nether”包含的所有群系中生成
      ore.biomes = "$hot"					// (仅Forge)在群系类型带有“hot”的所有群系中生成
      // 过滤器可以通过与、或、非三种逻辑任意组合
      ore.biomes = {}						// 空的“与”过滤器(默认为真)
      ore.biomes = []						// 空的“或”过滤器(默认为真)
      ore.biomes = {
        not: "minecraft:ocean"				// “非”过滤器(除"minecaraft:ocean"以外的群系)
      }
      // 因为“与”过滤器可以被表达为map,所以其还可以被表达为以下形式
      ore.biomes = {
        id: "minecraft:plains",
        id: /^minecraft:.*/,			// 正则表达式
        category: "^nether",
        biome_type: "$hot",
      }
      // 你可以将以上的各种过滤器组合起来,它们会被独立计算
      // 在下面这种情况中,矿石将在符合以下条件之一的群系中生成:
      // 1、平原 
      // 2、群系类型带有“hot”的非下界或热带草原类群系。
      ore.biomes = [
        "minecraft:plains",
        {
          biome_type: "$hot",
          not: [
            '#nether',
            {
            	category: "savanna"
            }
          ]
        },
      ]
	})
})

二、规则测试和目标方块

在1.18中,世界生成变更为了“基于目标”的替换系统,也就是说在同一种结构中,你可以指定以特定方块来替换特定的目标方块。(例如在原版的生成矿石中,石头被普通矿石替代,而深板岩则被深板岩矿石所替代)

每个目标方块都有一个“规则测试”(RuleTest)作为输入(用于检测目标方块的方块状态是否应被替换)并生成一个特定的输出方块状态。在KubeJS脚本层面上,这两个概念都被表达为相同的类:BlockStatePredicate

就格式上来说,BlockStatePredicate 与 群系过滤器 非常相似,即它们都能使用AND或者OR合并,并可用于匹配以下三种类型的条件:

  1. 方块(该类型被解析为字符串,使用形如 "minecraft:stone"来匹配石头)

  2. 方块状态(该类型被解析为后加数组形式的方块状态的方块ID字符串,使用形如"minecraft:furnace[lit=true]"来匹配燃烧中的熔炉方块。你可以使用F3界面来获得准星的方块状态,或者使用调试棒来获得方块状态可能的值。)

  3. 方块标签(该类型被解析为类似标签的形式,使用形如"#minecraft:base_stone_overworld"来匹配主世界中生成在地下的所有类型的石头。注意使用方块标签而不是物品标签,部分情况下他们可能不同,你可以在F3界面获得方块标签。)

注:

  • 你可以在方块过滤器中使用正则表达式,/^mekanism:.*_ore$/将匹配所有通用机械中以_ore结尾的方块。注意,这种写法不会匹配方块状态!

  • 你可以使用JavaScript Object来提供规则测试(它将会像原版解析JSON或NBT那样被解析)。例如,你可以通过这种方式设置匹配生效的概率。

三、高度提供器

另一个有些复杂的系统可能是“高度提供器”(Height Providers)系统,其被用于判定指定方块可能生成的Y坐标值和生成频率。与该系统同时使用的还有“垂直锚”(Vertical Anchors)概念,其可以用于获取相对于某锚点的相对高度(例如相对于世界最高点或最低点)。

在KubeJS中,该系统被简化以使其更容易在脚本开发中被使用:你可以使用AddOreProperties中的uniformHeighttraingleHeight方法来使用两种最常见的矿石生成逻辑(Uniform:在两个锚点间的任意位置有等大的概率生成矿石。Triangle:生成概率从两个锚点的中点向两锚点递减)。垂直锚概念也被简化了,你可以使用AddOreProperties中的辅助方法aboveBottom / belowTop(在世界最低点以上 / 在世界最高点以下)或新版本KubeJS中的VerticalAnchorWrapper Class;此外,你还可以以数字形式直接指定绝对高度

四、群系类别(Biome Categories)

群系类别是可用于将群系大致分为预定义的类别(具体类型见下)的原版系统(其他模组也可能添加更多的类别)

原版中的群系类别:
taiga
extreme_hills
jungle
mesa
plains
savanna
icy
the_end
beach
forest
ocean
desert
river
swamp
mushroom
nether

五、群系类型(Biome type,仅Forge可用)

类似于原版的群系类别(Biome Categories),Forge使用”群系字典“来根据群系的属性分类群系(其他模组也可能添加更多的类型)

基于温度的标签,均不指定则默认为温带:
HOT
COLD

基于群系的植被密度的标签,均不指定则默认为中等密度:
SPARSE
DENSE

基于群系的湿度的标签,均不指定则默认为中等湿度:
WET
DRY

基于群系的树类型的标签,SAVANNA指沙漠类型的树木(比如金合欢),CONIFEROUS指积雪的树木(如云杉树),JUNGLE指从林木,均不指定则默认为温带树木(例如橡树):
SAVANNA
CONIFEROUS
JUNGLE

基于群系的性质的标签:
SPOOKY
DEAD
LUSH
MUSHROOM
MAGICAL
RARE
PLATEAU
MODIFIED
OCEAN
RIVER

OCEAN和RIVER的合并标签:
WATER

通用类型标签
MESA
FOREST
PLAINS
HILLS
SWAMP
SANDY
SNOWY
WASTELAND
BEACH
VOID
UNDERGROUND

基于山地类型的标签
PEAK
SLOPE
MOUNTAIN

基于群系所处维度的标签
OVERWORLD
NETHER
END

六、示例脚本

onEvent('worldgen.add', event => {
	// 获取垂直锚
	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') // 将目标(#minecraft:stone_ore_replaceables标签下的方块)替换为minecraft:glowstone
		ore.addTarget('minecraft:deepslate', 'minecraft:nether_wart_block')       // 将目标(minecraft:deepslate)替换为minecraft:nether_wart_block
		ore.addTarget([
			'minecraft:gravel',
			/minecraft:(.*)_dirt/
		], 'minecraft:tnt')       // 将目标(minecraft:gravel和所有类型的泥土)替换为minecraft:tnt

		ore.count([15, 50])                      // 设置矿簇的大小(15~50中随机选择),在此处你可以使用单个数字来生成固定数量的方块。
				.squared()                       // 设置跨区块生成矿石
				.triangleHeight(				 // (高度提供器)使用Triangular分布模式生成矿石(具体见上文)
						anchors.aboveBottom(32), // 下边界锚,在世界最低高度(Y=-64)以上32格(即Y=-32)
						anchors.absolute(96)	 // 上边界锚,固定高度(Y = 96)
				)								 // 总的来说,矿石可能在Y = -32 ~ 96范围内生成,概率最大高度为Y = (-32 + 96) / 2 = 32
	    
        // 更多可选的参数,以下均为默认值
        ore.size = 9                            // 最大矿簇大小
        ore.noSurface = 0.5                     // 暴露于空气中的概率
        ore.worldgenLayer = "underground_ores"  // 矿石生成于世界生成中的阶段
      	ore.chance = 0							// 当该选项不为0且ore.count未被设置矿石将有1/n的概率在每个区块中生成
    })

	// 添加湖
	// 该功能将要于原版中废弃
	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",
		}];

		// 在上述给定的群系中移除铁矿和铜矿
		// 注:此处无法使用标签
		props.blocks = ["minecraft:iron_ore", "minecraft:copper_ore"]
	})

	// 通过指定ID来移除结构(第一个参数为生成步骤)
	event.removeFeatureById('underground_ores', ['minecraft:ore_coal_upper', 'minecraft:ore_coal_lower'])
})