# 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`中的`uniformHeight` 和 `traingleHeight`方法来使用两种最常见的矿石生成逻辑（Uniform：在两个锚点间的任意位置有等大的概率生成矿石。Triangle：生成概率从两个锚点的中点向两锚点递减）。垂直锚概念也被简化了，你可以使用`AddOreProperties`中的辅助方法`aboveBottom / belowTop`（在世界最低点以上 / 在世界最高点以下）或新版本KubeJS中的`VerticalAnchor`Wrapper 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'])
})
```
