生成型副本
生成型副本没有模板世界。你一次性构建若干小房间,描述它们如何连接,生成器就会为每次运行组装一个新的布局:从起始房间出发,经过普通房间、宝藏房间和隐藏房间,直到 Boss 房间。
固定型和生成型副本共用相同的运行、菜单、箱子、NPC、怪物、事件和事实(fact)。不同的只是房间的来源。
组成部分
| 部分 | 条目 | 说明 |
|---|---|---|
| 门类型 | Dungeon Connector Type | 门洞的尺寸、封住未使用门的方块,以及哪些类型之间可以连接。 |
| 房间 | Dungeon Room Template | 保存下来的结构(以 artifact 形式保存的 Paper 结构 .nbt),带有分类、门和标记点。 |
| 房间池 | Dungeon Room Pool | 房间模板的加权列表。 |
| 生成器 | Dungeon Generator | 规则:使用哪些房间池、房间数量、Boss 的深度、路径分叉的频率。 |
| 词缀 | Dungeon Affix | 随机抽取的运行修饰,例如“快速怪物”。 |
| 副本 | Dungeon Instance | 它的 generator 字段使其成为生成型副本。 |
一步步构建
- 门类型。 至少添加一个 Dungeon Connector Type。设置它的
width和height(默认 3 × 3)、封住未使用门的sealBlock(默认minecraft:stone_bricks),如果有多种类型,还要设置compatibleWith。一种类型总是可以与自身连接。 - 房间。 为每个房间添加一个 Dungeon Room Template,并使用游戏内编辑器捕获它的方块,放置它的门和标记点。选择它的
category。 - 房间池。 为起始房间添加一个 Dungeon Room Pool,为 Boss 房间添加一个,为其他房间添加一个(或多个),还可以为走廊添加一个(可选)。起始、Boss 或走廊房间池只能包含该分类的模板。普通房间池可以混合
NORMAL、TREASURE和SECRET模板。 - 生成器。 添加一个 Dungeon Generator,并设置
startPool、bossPool、可选的corridorPool,以及各带一个权重的normalPools。 - 副本。 在你的 Dungeon Instance 上设置
generator。templateWorld留空:生成型副本没有模板世界。隔离模式必须是AUTO或WORLD_PER_RUN。 - 游戏逻辑。 使用房间模板的
onEnter和onClear触发器、TRIGGER 标记点、房间事件、位于 MOB 标记点上的 Dungeon Mob Spawn 条目,并用 Dungeon Complete 结束运行。
如果房间池和模板无法生成副本,启动会被拒绝,服务器日志会说明原因(例如房间池中没有任何起始房间,或模板没有可读取的捕获)。生成器的 messages 字段保存报告给你(作者)的原因。玩家只会看到取自 snippet content.dungeon_generated.refusal.setup(房间池和模板无法生成副本)和 content.dungeon_generated.refusal.paste(房间无法粘贴)的一小段文本,你可以在 Web 面板中编辑它们。不会因此收取任何东西。宣布某次运行词缀的那一行是 snippet content.dungeon_generated.affix.announcement。
房间分类
房间模板的 category 表明它可以扮演的角色。
| 分类 | 角色 |
|---|---|
START | 运行从这里开始。每个副本一个。必须包含一个 SPAWN 标记点。 |
NORMAL | 普通房间。 |
TREASURE | 总是在分支上,绝不在通往 Boss 的路径上。 |
CORRIDOR | 插入在两个无法直接相接的房间之间。 |
SECRET | 总是死胡同。 |
BOSS | 最后一个房间。每个副本一个。 |
房间门对门连接,所以没有门的房间只能是死胡同式的 START。开启了 required 的门必须与另一个房间连接:无法填满所有必需门的模板永远不会被使用。没有人通过的门,会用其类型的 sealBlock 封上。
标记点
标记点是房间内的一个兴趣点。每个标记点都有一个 kind:
| 种类 | 作用 | 需要填写的字段 |
|---|---|---|
SPAWN | 运行开始时玩家出现的位置。只使用起始房间的第一个 SPAWN。 | 无 |
CHEST | 这里会放置一个战利品箱。它的位置和偏航角(yaw)会替换条目的 location。由标记点指定的箱子总是会被放置,即使其条目处于 manualMode。 | chest:一个 Dungeon Loot Chest |
TRIGGER | 为到达该房间的玩家触发这些触发器。 | triggers |
NPC | 一个 Dungeon NPC Instance 站在这里,向该次运行的成员显示。 | npc |
MOB | 当该次运行的某位成员第一次进入房间时,Dungeon Mob Spawn 的怪物会在这里出现。 | mob |
标记点的 yaw 决定箱子(它朝向背对 yaw 的方向)和 NPC(它朝向 yaw 的方向)的朝向。标记点通过它在 markers 列表中的位置与其条目关联。
游戏中的房间
当玩家进入生成型副本的某个房间时,先触发其模板的 onEnter 触发器,然后触发它的 TRIGGER 标记点的触发器和 MOB 标记点的怪物。开启 enterOnce(模板的默认值)时,它们只会在每位玩家于一次运行中第一次进入该房间时触发。
当玩家站在房间内,执行 Dungeon Clear Room 动作时,onClear 触发器每次运行触发一次。平台绝不会自行判定房间已被清空:这由你决定,例如在最后一只怪物死亡时通过怪物死亡事件。
房间的触发器可以从上下文中读取这些值(通过 interaction_context_variable):
| 键 | 值 |
|---|---|
RUN_ID | 运行的 id。 |
SEED | 副本的种子,十进制。 |
ROOM | 房间编号:0 是起始房间,之后按生成器放置的顺序排列。 |
ROOM_TEMPLATE | 房间模板条目的 id。 |
DIFFICULTY | 生成器的 difficulty。 |
POSITION | 对于 TRIGGER 标记点,是该标记点的方块;否则是玩家的位置。 |
词缀的触发器只能读取 RUN_ID、SEED 和 DIFFICULTY。固定型副本不提供其中任何一个键。
种子、词缀与难度
相同的种子总是生成相同的副本,因此布局可以重放。每次运行都会抽取一个新的种子。种子会随运行一起保存,因此重载会在内存中重建相同的副本。如果无法重建,该运行会在启动时被关闭,而不是带着没人认得的房间被接管。
词缀在布局之后抽取:从生成器的 affixes 中按 weight 抽取 affixCount 个,不重复。抽取遵循种子,但绝不会改变布局。它们的修饰器和触发器会在运行开始时应用于每位成员。
difficulty 只是一个通过上下文交给你的触发器的数字:它本身不会改变布局。
重要的生成器设置
| 字段 | 默认值 | 说明 |
|---|---|---|
minRooms, maxRooms | 6, 10 | 房间总数,包括起始和 Boss,不含走廊。允许范围:2 到 256。 |
minBossDepth | 3 | Boss 距离起点至少这么多步。 |
branchRatePercent | 40 | 主路径之外的房间开出支路的概率,以百分比计。 |
quotas | 无 | 对 NORMAL、TREASURE 和 SECRET 房间数量的上下限。没有设置界限的分类不受限制。 |
trialBudget, replans | 20000, 5 | 搜索在失败前会尝试多久。试验预算乘以 (replans + 1) 必须保持在 5 000 000 以内。 |
baseY | 64 | 起始房间地板在运行世界中的高度。 |
roomsPerTick | 4 | 每个服务器 tick 粘贴的房间数。调低可使 tick 保持较短;调高则更快。 |
pasteTimeoutSeconds | 120 | 超过这个时间后,启动会被取消,费用被退还,世界被丢弃。 |
naturalSpawning | off | 怪物和动物会在运行世界中自行生成。默认关闭。 |
verticalMargin | 1.0 | 判断玩家是否在内部时,在每个房间的天花板之上和地板之下增加的方块数。 |
paster | STRUCTURE | 使用 Paper 结构 API:不需要其他插件。 |
一个房间模板每边最多 256 格,最多 64 扇门和 1024 个标记点。
游戏内编辑器
在 Web 面板中打开一个 Dungeon Room Template,点击 artifactId 字段的内容编辑器。你的快捷栏中会得到一组工具:
| 工具 | 用途 |
|---|---|
| 角点魔杖 | 左键点击一个方块设为角点 A,右键点击一个方块设为角点 B。 |
| 捕获 | 把盒子内的方块保存为模板的结构。 |
| 门工具 | 右键点击墙上的一个方块以添加一扇门(该方块是门洞底部的中心)。左键点击则移除那里的门。 |
| 门类型 | 右键切换到下一个连接器类型,左键切换到上一个。 |
| 必需开关 | 切换接下来放置的门是否为必需。 |
| 标记点工具 | 右键点击一个方块,在其前方添加一个标记点。左键点击则移除那里的标记点。 |
| 标记点种类 | 右键切换到下一个种类,左键切换到上一个。 |
| 保存 | 把门和标记点写入条目。 |
Boss 血条会显示盒子的大小、门和标记点的数量,以及你是否有未保存的工作。房间的大小是从保存的结构中读取的,而不是手动输入的。添加门之前,你必须至少创建并发布一个连接器类型。
捕获默认会跳过实体,因为活体实体会在每次捕获时改变房间,并且会在每个副本中作为游离的怪物回来。这些行为以及编辑器的所有文本,都是 content.dungeon_room_template. 之下的 Typewriter snippet,因此你可以在 Web 面板中修改或翻译它们:
| Snippet | 默认值 | 含义 |
|---|---|---|
capture.include_entities | false | 捕获时是否保存盒子内的实体。 |
capture.max_volume | 262144 | 一次捕获最多读取的方块数。它在一个服务器 tick 内读取:非常大的盒子会占住那个 tick。 |
capture.timeout_seconds | 30 | 放弃前等待捕获的秒数。 |
sound.confirm | entity.experience_orb.pickup | 捕获或保存之后播放的声音。留空:不播放。 |
限制与良好实践
- 生成型副本只使用
WORLD_PER_RUN:每次运行创建一个世界,之后将其删除。 - 固定房间(节点)的编辑器在
content.dungeon_room.之下有自己的 snippet(消息node.*、save.*、editor.*,工具tool.add、tool.remove、tool.save)。 - 构建房间时,要让两扇相连的同类型门对齐。偶数的门洞宽度,其多出的一格方块位于模板的 x 或 z 较大的一侧。当偶数门洞需要时,生成器会把房间平移一格。
- 整个副本必须从
baseY起算,容纳在世界的最低方块与最高方块之间。 - 不要依赖固定的房间数量:请使用标记点和事件,而不是房间编号。