附加包教程:54.拼图结构(六)
本帖最后由 Cat_Anchor 于 2024-11-16 21:21 编辑拼图结构自定义教程提醒:本教程仅适用于基岩版 1.21.50.26 及以后的版本,而且要开启“数据驱动的拼图结构(Data-Driven Jigsaw Structures)”实验性玩法。
前言
来,看着这张图片。
https://pic.imgdb.cn/item/6727523dd29ded1a8c82f5bb.jpg这是一个拼图结构。它的背后,是新版拼图结构系统。每个古迹废墟或试炼密室的生成都离不开它。
如何简单地自定义拼图结构?
https://klpbbs.com/static/image/hrline/line1.png
要定义拼图结构,首先要了解拼图方块。
https://pic.imgdb.cn/item/672b547ad29ded1a8cef2280.jpg
拼图方块是用于生成拼图结构的技术性方块,可以用命令获取:
/give @p jigsaw
就像拼图碎片一样,每个拼图方块都有它特定的“形状”,合适的拼图方块才能对接成功。
这是两个结构,它们之间用拼图方块连接。
https://pic.imgdb.cn/item/66ff9824d29ded1a8cb0ef60.png
它们为什么能连接?
首先,它们的纹理是对齐的。每个拼图方块都有一条粉红色的线,放置时应使其对齐。
https://pic.imgdb.cn/item/672ec5eed29ded1a8cf997de.png
仅仅是这样吗?显然,这样会导致拼图结构的混乱,各种结构将不知道何时被放置。还记得之前所说的“形状”吗?
https://pic.imgdb.cn/item/672eca62d29ded1a8cfd205d.jpg
拼图方块就是依靠这些“形状”来完成结构的拼接的。一个拼图方块的“形状”使用几个字段定义。
打开一个拼图方块,可以看到这样的画面。
https://pic.imgdb.cn/item/672ed06dd29ded1a8c02c456.jpg
这些字段都是用来干什么的?
“名称”是拼图方块的“形状”,“目标名称”是能与这个拼图方块拼接的拼图方块的“形状”,“目标池”则是这个拼图方块可以生成的结构组成的“池”。至于其他字段,用到时会讲。
https://klpbbs.com/static/image/hrline/line3.png
现在我们可以开始设计我们想要生成的拼图结构了。
比如,我要搭建一个树屋。这个树屋每次生成都不一样,有不同的房间,不同的树枝结构,等等。这时,我们要在整个树屋里挑选一个合适的部分,从这部分开始生成。
我选择了树根结构作为开始生成的结构,毕竟树都是从下向上长。由于 MC 里的树大多数没有树根,我就先做了底部的树干结构。
https://pic.imgdb.cn/item/672ed395d29ded1a8c066a71.jpg
说实话,我不怎么会建筑,不过这篇教程不是建筑教程,而是拼图结构教程。我用白桦木建了一个很粗的树干,还在树干里面加上了旋转楼梯。
https://pic.imgdb.cn/item/672ed401d29ded1a8c06f7a0.jpg
接下来,我又建造了一段树干。底部的树干生成之后要在上面继续生成树干。
https://pic.imgdb.cn/item/672ed554d29ded1a8c07ef43.jpg
建造这种含有楼梯的结构时,我们要注意,要让楼梯可以拼接起来。可以用结构方块保存这个结构,然后在这个结构的上方加载,让两个相同的结构挨在一起,看看里面的楼梯有没有断层。
是时候安装拼图方块了!首先,我们在底部树干那个结构的顶层放一个拼图方块。然后,在树干的相同 X 轴和 Z 轴位置的顶部和底部放两个拼图方块。放置拼图方块时,必须让要连接的两个拼图方块的粉红色的线在同一个方向上可以对齐,即使是向上或向下的拼图方块。
https://pic.imgdb.cn/item/672ed83bd29ded1a8c0a714a.jpg
https://pic.imgdb.cn/item/672ed851d29ded1a8c0a8858.jpg
我们现在要让底部树干和树干连接起来。那么首先设计一个模板池,里面包含树干这个结构。我给它的命名空间是 complementary:tree_house/trunk。
接下来,我们可以通过拼图方块的名称和目标名称这两个字段,把它们连接在一起。
假设↓和↑代表不同方向的拼图方块,那么下面这两个拼图方块:
↓
↑
要拼接起来,就需要填写名称和目标名称。
如果↓的名称是 a,↑的名称是 b,那么↓的目标名称是 b,↑的目标名称是 a。
可以看出,两个互相拼接的拼图方块,它们的名称和目标名称字段是相反的,你的名称是 a,我的名称就是 b,你的目标名称是 b,我的目标名称就是 a。
掌握了这个原理,我们就可以填写两个拼图方块了。
这是底部树干的拼图方块配置。它叫 complementary:trunk_bottom_anchor,要生成 complementary:tree_house/trunk 目标池里的结构,要与 complementary:trunk_top_anchor 对接。
https://pic.imgdb.cn/item/672edaffd29ded1a8c0d218d.jpg
这是树干的拼图方块配置。它叫 complementary:trunk_top_anchor,要生成 complementary:tree_house/trunk 目标池里的结构(因为要重复生成很多树干,这样树才会高),要与 complementary:trunk_bottom_anchor 对接。
https://pic.imgdb.cn/item/672edc04d29ded1a8c0e6cc1.jpg
然后,我们可以在树干结构的顶部放置一个与之前在底部树干放的拼图方块相同的拼图方块。由于它们都将向上生成树干,它们的目标池、名称和目标名称完全一致。
https://pic.imgdb.cn/item/672edc8ed29ded1a8c0f14f5.jpg
试炼密室就是用拼图方块生成的,为什么它里面没有拼图方块?之前我们放置底部树干的拼图方块时,用拼图方块替代了木板,结构生成之后怎么再用木板替代拼图方块?
这就是“转变为”字段的作用,让拼图方块用完之后变成其他方块,默认是空气。如果要变成白桦木板,填写 minecraft:birch_planks 即可。
拼图方块底部还有一个“拼接类型”的选项,默认是“可滚动”。但制作树干时,我们要把刚才放的拼图方块的拼接类型都调成“一致”。如果是“可滚动”,会有什么后果?
https://pic.imgdb.cn/item/672ede23d29ded1a8c10e85c.jpg
这张图片中,左边是“可滚动”,右边是“一致”。可以看出,“可滚动”会导致树干随机旋转,而“一致”生成出来的就是正常的树干。
做完这一切,我们就可以生成一个光秃秃的树干了。
但这还不够,我们还需要树枝和树顶。于是我基于树干结构建了两个新结构,一个在树干上挖了洞,另一个放置了生成树顶的拼图方块。我还建了树顶结构。
https://pic.imgdb.cn/item/672ee1a7d29ded1a8c14c349.jpg
https://pic.imgdb.cn/item/672ee1c2d29ded1a8c14e031.jpg
https://pic.imgdb.cn/item/672ee1ddd29ded1a8c14fc38.jpg
由于挖洞的树干需要在四个方向上生成结构,我在每个洞里各放置了一个拼图方块。
前两个新结构都在 complementary:tree_house/trunk 这个模板池里,它们有概率取代原本的树干生成。最后,我们要在会生成树顶的树干顶部放置拼图方块,并在树顶的底部放另一个拼图方块,让它们连接。
https://pic.imgdb.cn/item/672ee1f4d29ded1a8c15183d.jpg
生成树顶的拼图方块的目标池是 complementary:tree_house/roof,一个包含树顶结构的模板池。至于名称和目标名称的写法,自然是按照之前提到的相反原则,名称是上 a 下 b,目标名称是上 b 下 a。
回到我们挖的树洞的位置,那四个拼图方块要生成树枝,所以目标池是 complementary:tree_house/door(它的名称有误导性,实际上就是树枝)。我很快建出来几条树枝。
https://pic.imgdb.cn/item/672ee451d29ded1a8c1747e7.jpg
树枝末端有拼图方块,那是用来生成小树屋的。我又建了个树屋。
https://pic.imgdb.cn/item/672ee4e9d29ded1a8c17f3e9.jpg
我还做了一个只有几块叶子的结构。因为实际上生成树屋时空间有可能不够大,这时候会尝试放置后备结构,也就是几块白桦树叶。
最后,我做了一个去皮白桦原木组成的 3 * 3 墙。由于挖洞的树干在 4 个方向上都有洞,又不能在 4 个方向上都生成结构,于是我做了这个结构,有概率取代原本要放置的树枝,同时作为空间不足时的后备结构。
大体工作已经完成了,现在我们要检查拼图方块是否都在结构的最外面一圈。在这个例子中,我们只需要在结构边缘的拼图方块。如果一切顺利,那么所有拼图方块应该都符合要求。
现在,把所有结构都导出,游戏内的工作就告一段落了。
https://klpbbs.com/static/image/hrline/line8.png
接下来是技术性工作,很简单。首先做一个最基本的行为包,只有 manifest.json 的那种。可以参考下面的示例 manifest.json。
{
"format_version": 2,
"header": {
"description": "拼图结构测试。",
"name": "树屋",
"uuid": "自己填",
"version": [
1,
0,
0
],
"min_engine_version": [
1,
21,
50
]
},
"modules": [
{
"type": "data",
"uuid": "自己填",
"version": [
1,
0,
0
]
}
]
}
UUID 可以在这里获取。
然后在与 manifest.json 同级的地方新建一个 worldgen 文件夹,打开。如果你不清楚怎么写模板池、拼图结构、拼图结构集和处理器的 JSON 文件,可以看看我的前几期教程,点击上面的名词即可。
在 worldgen 文件夹里新建 template_pools 文件夹。打开,我们首先来定义最开始我们做的起始结构,底部树干。
{
"format_version": "1.21.40",
"minecraft:template_pool": {
"description": {
"identifier": "complementary:tree_house/base"
},
"elements": [
{
"projection": "rigid",
"element": {
"element_type": "minecraft:single_pool_element",
"location": "tree_house/base/base",
"processors": "complementary:tree_house_common"
},
"weight": 1
}
]
}
}
其中,complementary:tree_house/base 就是这个模板池的 ID,tree_house/base/base 就是结构文件的路径。
然后可以定义“树干”这个模板池。
{
"format_version": "1.21.40",
"minecraft:template_pool": {
"description": {
"identifier": "complementary:tree_house/trunk"
},
"elements": [
{
"projection": "rigid",
"element": {
"element_type": "minecraft:single_pool_element",
"location": "tree_house/trunk/trunk",
"processors": "complementary:tree_house_common"
},
"weight": 3
},
{
"projection": "rigid",
"element": {
"element_type": "minecraft:single_pool_element",
"location": "tree_house/trunk/trunk_has_door",
"processors": "complementary:tree_house_common"
},
"weight": 4
},
{
"projection": "rigid",
"element": {
"element_type": "minecraft:single_pool_element",
"location": "tree_house/trunk/trunk_to_roof",
"processors": "complementary:tree_house_common"
},
"weight": 2
}
],
"fallback": "complementary:tree_house/trunk_fallback"
}
}
可以看到,它使用了 fallback 字段指定后备模板池。
其他模板池也是这么定义出来的,这里不再赘述。
我们回到 worldgen 文件夹下,新建 jigsaw_structures 文件夹并打开,里面新建一个文件来定义我们的拼图结构。
{
"format_version": "1.21.40",
"minecraft:jigsaw": {
"description": {
"identifier": "complementary:tree_house"
},
"heightmap_projection": "world_surface",
"max_depth": 20,
"start_height": 0,
"start_pool": "complementary:tree_house/base",
"step": "surface_structures",
"terrain_adaptation": "none",
"biome_filters": [
{
"test": "has_biome_tag",
"operator": "==",
"value": "plains"
}
]
}
}
identifier 后面的 complementary:tree_house 是这个拼图结构的 ID,start_pool 后面填写起始模板池,biome_filters 决定这个拼图结构在哪里生成。
再回到 worldgen 文件夹,新建并打开 structure_sets 文件夹,里面新建文件,定义这个拼图结构的生成。
{
"format_version": "1.21.40",
"minecraft:structure_set": {
"description": {
"identifier": "complementary:tree_house"
},
"placement": {
"type": "minecraft:random_spread",
"salt": 17,
"separation": 7,
"spacing": 22,
"spread_type": "linear"
},
"structures": [
{
"structure": "complementary:tree_house",
"weight": 1
}
]
}
}
最后一次回到 worldgen 文件夹,新建并打开 processors 文件夹,里面新建文件,定义这个拼图结构的处理器。
{
"format_version": "1.21.20",
"minecraft:processor_list": {
"description": {
"identifier": "complementary:tree_house_common"
},
"processors": [
{
"processor_type": "minecraft:rule",
"rules": [
{
"input_predicate": {
"predicate_type": "minecraft:random_block_match",
"block": "minecraft:diamond_block",
"probability": 0.01
},
"output_state": {
"name": "minecraft:diamond_block"
}
}
]
}
]
}
}
最后把导出的结构文件放在之前模板池定义的地方就行了。
现在技术方面的工作差不多了,worldgen 文件夹应该是下面这样的。
https://pic.imgdb.cn/item/672eeaddd29ded1a8c1e9285.jpg
再打开游戏,进入带有这个附加包的存档,应该可以用 /locate 找到拼图结构,用 /place 放置拼图结构了。
后记
这一期,我们制作了一个拼图结构。我本来想在这里发一个模板包,但感觉还是直接发“树屋”这个附加包比较好。可以打开那个附加包,看看我写的拼图结构文件。
“树屋”附加包已发布,请去那里获取模板包。
https://pic.imgdb.cn/item/6727523dd29ded1a8c82f5bb.jpg
第五十三期 第五十四期 第五十五期 好绕啊...... 感谢楼主教程[哔哩_打call]
页: [1]