API
世界生成
矿石、树木、花、结构和生物群系会自动出现在世界中。你声明是什么、在哪里,新的区块就会生成它们。
矿石
block "ruby_ore" { hardness: 3, tool: "pickaxe", tier: "iron" }
ore "ruby_ore" {
replaces: "stone_and_deepslate"
size: 9
per_chunk: 8
height: [-60, 60]
}| 属性 | 取值 | 默认值 |
|---|---|---|
block |
要放置的方块:"mymod:other" |
与矿石同名的方块 |
replaces |
stone、deepslate、stone_and_deepslate(主世界)、netherrack(下界)或 end_stone(末地) |
stone_and_deepslate |
size |
每个矿脉的方块数,1–64 | 8 |
per_chunk |
每个区块尝试生成的矿脉数 | 8 |
height |
[min, max],高度范围 |
[-64, 64] |
biomes |
只在这些生物群系中,用 id 或标签指定 | 它所在岩石存在的每个生物群系 |
没有 biomes 时,矿石会出现在 replaces 所属维度的每个生物群系中;end_stone 矿石则出现在末地的每个生物群系中。方块本身和其他方块一样声明,带有硬度、工具和战利品;见方块、物品与配方。
ore "void_ore" {
replaces: "end_stone"
size: 5
per_chunk: 6
height: [10, 80]
biomes: ["mymod:crystal_glade"]
}树木
树由笔直的树干和一个树叶球组成。先声明两个方块,再声明树。
block "ruby_log" { hardness: 2, tool: "axe", sound: "wood" }
block "ruby_leaves" { hardness: 0.2, transparent: true, sound: "grass" }
tree "ruby_tree" {
trunk: "ruby_log"
leaves: "ruby_leaves"
height: 6
height_variation: 2
leaves_radius: 2
per_chunk: 2
biomes: ["#minecraft:is_forest", "minecraft:plains"]
}| 属性 | 取值 | 默认值 |
|---|---|---|
trunk |
树干方块,来自模组或游戏:"ruby_log", "minecraft:oak_log" |
— |
leaves |
树叶方块 | — |
height |
树干高度(方块数) | 5 |
height_variation |
每棵树高度的变化幅度 | 2 |
leaves_radius |
树叶球的半径(方块数) | 2 |
per_chunk |
每个区块尝试生成的树数 | 1 |
biomes |
出现的生物群系(id 或标签) | — |
生物群系可以用 id(minecraft:plains)或标签(#minecraft:is_forest)指定,可任意混用。树干和树叶可以是模组的方块,也可以是游戏的方块。
植物与花丛
植物是一种方块,绘制成两张交叉的图像,就像花:没有东西会与它碰撞,光线可以穿过。它的贴图是 textures/block/ruby_flower.png,背景透明。
block "ruby_flower" { plant: true, hardness: 0 }
patch "ruby_flowers" {
block: "ruby_flower"
biomes: ["#minecraft:is_overworld"]
rarity: 4
size: 32
spread: 7
}花丛会把植物散布到世界中:
| 属性 | 取值 | 默认值 |
|---|---|---|
block |
植物方块 | — |
biomes |
出现的生物群系(id 或标签) | — |
rarity |
每隔这么多区块出现一处花丛 | 4 |
size |
每处花丛尝试放置的植物数 | 32 |
spread |
距花丛中心的最大距离(方块数) | 7 |
植物只会放置在主世界地面(草方块、泥土、苔藓和泥巴)上方的空气中。若想让植物长在其他地面上、墙上或从天花板垂下,请编写一个地物:见用代码生成。
结构
结构是你自己建造的建筑:
- 在游戏中建造它。
- 用结构方块保存它。
- 把
.nbt文件复制到模组的structures/文件夹:CraftScript 模组放在脚本旁边,Kotlin 或 Java 的 jar 放在assets/<模组 id>/structures/。
然后声明它:
structure "ruby_shrine" {
file: "ruby_shrine"
biomes: ["#minecraft:is_overworld"]
spacing: 24
separation: 8
buried: false
}| 属性 | 取值 | 默认值 |
|---|---|---|
file |
不带扩展名的 .nbt 文件名 | 第一个 variant,或结构的名称 |
biomes |
出现的生物群系(id 或标签) | — |
spacing |
大约每隔这么多区块出现一个结构 | 24 |
separation |
彼此至少相距这么多区块;小于 spacing | 8 |
buried |
true 会把它沉入地下,适合做废墟 | false |
offset_y |
比它所立足的地表高出的格数;为负数则下沉 | 0 |
adapt_ground |
true 会填平它下面的地面并清理它周围;false 则原样放置 | true |
heights |
[min, max]:不贴着地表,而是无论地表在哪里,都放在这个范围内的随机高度(空中的房子) |
在地表上 |
用 /locate structure <模组 id>:ruby_shrine 查找,用 /place structure <模组 id>:ruby_shrine 放置。
变体、替换与风化
一个结构可以来自多个文件,它的方块也可以在放置时改变。这样做出的遗迹每次都不完全相同:
structure "old_ruins" {
variants: [{ file: "ruins_small", weight: 3 }, "ruins_tower"]
biomes: ["#minecraft:is_forest"]
spacing: 20
separation: 6
offset_y: -2
skip: ["minecraft:air"]
replace: [{ block: "minecraft:stone_bricks", with: "minecraft:cracked_stone_bricks", chance: 0.3 }]
decay: { left: 0.8, blocks: ["minecraft:stone_bricks", "minecraft:cracked_stone_bricks"] }
}| 属性 | 取值 | 默认值 |
|---|---|---|
variants |
它可能是其中之一的文件:名称,或 { file, weight };按权重随机选出一个 |
只有 file,权重 1 |
skip |
它的文件中不放置的方块。"minecraft:air" 会在文件为空气的地方保留世界原有的方块 |
— |
replace |
[{ block, with, chance }]:它文件中的某个方块以该概率(大于 0,最大为 1)变成另一个方块 |
chance 1 |
decay |
{ left, blocks }:blocks(id 或标签)中只保留 left(0–1)的比例;没有 blocks 时,对任何方块都适用 |
全部保留 |
由相连的部件组成的结构
村庄或地牢由相连的部件组成:街道通向房子,走廊通向房间。每个部件是一个含有游戏拼图方块的文件,每个拼图方块用 <模组 id>:<池> 的形式写出下一个部件从哪个池中取。声明这些池;结构从第一个池开始。
structure "hamlet" {
biomes: ["minecraft:plains"]
spacing: 34
separation: 8
depth: 6
pools: [
{ name: "hamlet/square", pieces: [{ file: "hamlet/square" }] },
{ name: "hamlet/streets", fallback: "hamlet/street_ends",
pieces: [{ file: "hamlet/street_straight", weight: 3, follows_ground: true },
{ file: "hamlet/street_corner", follows_ground: true }],
replace: [{ block: "minecraft:stone_bricks", with: "minecraft:oak_planks", where: "minecraft:water" }] },
{ name: "hamlet/street_ends", pieces: [{ file: "hamlet/street_end", follows_ground: true }] },
{ name: "hamlet/houses", none: 2,
pieces: [{ file: "hamlet/house_small", weight: 4 }, { file: "hamlet/house_big" }] },
]
}| 属性 | 取值 | 默认值 |
|---|---|---|
pools |
部件的池;第一个是它的起点 | 来自 variants 或 file 的一个部件 |
depth |
它从第一个部件起向外延伸多少个部件 | 1 |
每个池有:
| 键 | 取值 | 默认值 |
|---|---|---|
name |
它的拼图方块所使用的名称,如 hamlet/streets |
— |
pieces |
[{ file, weight, follows_ground }]。follows_ground: true 会让部件顺着其下方的地面弯曲,适用于街道和小路;false 则保持笔直,适用于房子 |
权重 1,false |
features |
[{ id, weight }]:作为部件的地物,你的或游戏的(minecraft:chorus_plant) |
— |
none |
完全不放部件的权重,用来留出空地 | 0 |
fallback |
在没有合适部件的地方(如街道的尽头)使用的池 | 无 |
skip、replace |
与单个结构相同。在池中,替换可以加上 where:只在世界原本就有那种方块的地方(水上街道的砖变成木板) |
— |
所有部件都保持在距第一个部件 80 格以内。
目前有两个选项只在 Kotlin 中提供:salt,一个数字,决定结构落在每 spacing 个区块的范围内的哪个位置(spacing 和 salt 都相同的两个结构会落在相同的位置;不设置时,由结构的 id 生成一个);以及 aboveBottom,它的部件必须保持在世界底部之上多少格(在某处会延伸到更低的地方,结构就不会生成)。
由你的代码逐块建造的结构见用代码生成页面。
生物群系
自定义生物群系会占据游戏生物群系的一部分位置。那里生长的、生活的和被挖出的内容都会保留,同时带有自己的气候和颜色。
biome "ruby_meadow" {
replaces: "minecraft:plains"
share: 0.5
temperature: 0.8
downfall: 0.4
precipitation: true
grass_color: "#d05070"
foliage_color: "#c04060"
sky_color: "#ff9fb0"
fog_color: "#ffd0d8"
water_color: "#ff6080"
water_fog_color: "#a03050"
}| 属性 | 取值 | 默认值 |
|---|---|---|
replaces |
它占据其位置的游戏生物群系:"minecraft:plains" |
"minecraft:plains" |
share |
它占据这些位置的比例,大于 0 且最大为 1 | 0.5 |
temperature |
气候的温度 | 0.8 |
downfall |
降水量 | 0.4 |
precipitation |
下雨为 true,不下雨为 false |
true |
grass_color |
草的颜色,#rrggbb |
被替换生物群系的值 |
foliage_color |
树叶的颜色 | 被替换生物群系的值 |
sky_color |
天空的颜色 | 被替换生物群系的值 |
fog_color |
雾的颜色 | 被替换生物群系的值 |
water_color |
水的颜色 | #3f76e4 |
water_fog_color |
水下雾的颜色 | 被替换生物群系的值 |
share 会均匀分布在被替换生物群系原本所在的位置:0.5 占一半,即每两处取一处。新生物群系继承那里生长的、生活的和被挖出的内容(植被、矿石、洞穴、生物、音乐),以及其他模组添加到该生物群系的内容。未指定的颜色保持为被替换生物群系的颜色。
多个生物群系可以替换同一个生物群系,它们会分享其位置。用 /locate biome <模组 id>:ruby_meadow 找到你的生物群系。
声音、地面与生物
生物群系还可以有自己的音乐和氛围,用你的方块覆盖它的地面,并选择谁住在那里:
biome "glow_marsh" {
replaces: "minecraft:swamp"
share: 0.4
music: "mymod:music.marsh"
ambient_sound: "mymod:ambient.marsh_hum"
particle: { id: "minecraft:glow", chance: 0.005 }
surface: "mymod:glow_moss"
spawns: [
{ creature: "minecraft:frog", weight: 10, group: [2, 5] },
{ creature: "mymod:marsh_wisp", weight: 4, group: [1, 2] },
]
}| 属性 | 取值 | 默认值 |
|---|---|---|
music |
一个声音 id,作为该生物群系的音乐播放 | 被取代生物群系的 |
ambient_sound |
在那里持续响着的声音(风声、嗡嗡声) | 被取代生物群系的 |
particle |
{ id, chance }:飘浮在它空气中的粒子;chance 是每刻玩家附近每个位置的概率(0.001 是少量) |
被取代生物群系的;chance 0.01 |
surface |
覆盖它地面的方块(每层地面最上面的方块) | 维度通常的地面 |
spawns |
[{ creature, weight, group }]:住在那里的生物;一旦指定任何一个,就只有这些而没有其他 |
被取代生物群系的;weight 10,group [1, 4] |
inherits |
false:只有给予这个生物群系的内容才会在那里生成(它的 features、它的 carvers、模组放在其中的东西),而不包括在被取代生物群系中生成的内容 |
true |
features |
[{ id, step }]:已经存在的地物,游戏的或数据的,放置在其中。step 是 lakes、surface、ores、underground 或 vegetation |
— |
carvers |
挖空它洞穴的雕刻器的 id,你的或游戏的;它们按给定顺序运行,先于被取代生物群系的 | — |
使用 inherits: false 时,该生物群系仍然占据被取代生物群系的位置,除非你另外指定,否则也保留它的生物和声音;只是那里生长和被挖空的东西不再随之而来。逐块生成的地面和你自己的雕刻器见用代码生成页面。
末地的生物群系
在末地,生物群系占据的是整片约 200 格宽的区域,而不是按气候划分的位置。取代 minecraft:end_highlands 时,它占据其区域内所有的岛屿陆地(高地、中地和荒地);取代 minecraft:small_end_islands 时,占据岛屿之间的虚空。中央岛仍属于游戏,区域在每个世界中都不同。
biome "crystal_glade" {
replaces: "minecraft:end_highlands"
share: 0.3
sky_color: "#2a1840"
fog_color: "#3c2a5a"
surface: "mymod:crystal_moss"
inherits: false
features: [{ id: "minecraft:end_gateway_return", step: "surface" }]
}注意事项
- 仅限新区块。 已生成的区块不会改变;只有安装模组之后生成的区块才会出现矿石、树木、植物、结构和生物群系。探索新的地形来找到它们。
- 不存在的名称会被忽略。
biomes中不存在的生物群系或标签(比如另一个未安装的模组的)会被跳过,而不是报错。 - 没有地面就没有结构。 立在地表的结构不会生成在该列完全没有地面的地方,比如末地岛屿之间的虚空。
- 用代码编写的地物、结构、地形、生物群系地图、雕刻器和地面见用代码生成页面。
- 完整的自定义世界见维度页面。
Kotlin 中
ore("ruby_ore") {
replaces = OreHost.STONE_AND_DEEPSLATE
size = 9
perChunk = 8
minY = -60
maxY = 60
}
ore("void_ore") {
replaces = OreHost.END_STONE
biome("mymod:crystal_glade")
}
tree("ruby_tree") {
trunk = "ruby_log"
leaves = "ruby_leaves"
height = 6
perChunk = 2
biome("#minecraft:is_forest")
}
block("ruby_flower") { plant = true }
patch("ruby_flowers") {
block = "ruby_flower"
rarity = 4
biome("#minecraft:is_overworld")
}
structure("old_ruins") {
variant("ruins_small", weight = 3)
variant("ruins_tower")
biome("#minecraft:is_forest")
spacing = 20
offsetY = -2
skip("minecraft:air")
replace("minecraft:stone_bricks", "minecraft:cracked_stone_bricks", chance = 0.3)
decay(0.8, "minecraft:stone_bricks", "minecraft:cracked_stone_bricks")
salt = 120457
}
structure("hamlet") {
biome("minecraft:plains")
spacing = 34
depth = 6
pool("hamlet/square") { piece("hamlet/square") }
pool("hamlet/streets") {
piece("hamlet/street_straight", weight = 3, followsGround = true)
piece("hamlet/street_corner", followsGround = true)
fallback = "hamlet/street_ends"
replace("minecraft:stone_bricks", "minecraft:oak_planks", where = "minecraft:water")
}
pool("hamlet/street_ends") { piece("hamlet/street_end", followsGround = true) }
pool("hamlet/houses") {
piece("hamlet/house_small", weight = 4)
piece("hamlet/house_big")
none = 2
}
}
biome("glow_marsh") {
replaces = "minecraft:swamp"
share = 0.4
music = "mymod:music.marsh"
ambientSound = "mymod:ambient.marsh_hum"
particle("minecraft:glow", chance = 0.005)
surface = "mymod:glow_moss"
spawn("minecraft:frog", weight = 10, group = 2..5)
}
biome("crystal_glade") {
replaces = "minecraft:end_highlands"
share = 0.3
surface = "mymod:crystal_moss"
inherits = false
feature("minecraft:end_gateway_return", FeatureStep.SURFACE)
}