Cat_Anchor 发表于 2023-3-26 07:26:19

附加包教程:33.方块(五)

本帖最后由 Cat_Anchor 于 2023-3-31 22:11 编辑


坩埚https://pic.imgdb.cn/item/64032302f144a01007ae1112.png
稀有度常见
创造分类建筑
材料金属
合适挖掘工具镐
硬度5
爆炸抗性0
亮度0
窒息生物否
红石导体否
光照透明0.7
可被火破坏否
可被熔岩生成火否
可再生是
最大堆叠64
命名空间IDcrucible               





前言



所有我知道的关于附加包理论的知识几乎已经讲完了,但还有一些遗漏。不管怎样,我们从这一期开始进入教程后期。这一期的题目叫“方块(五)”,因为我要在这一期放出一些制作方块的例子。



https://klpbbs.com/static/image/hrline/line5.png


目标



今天我闲来无事,想要给我的附加包加一点新东西。思来想去,我觉得添加一口锅还有点意思。我要添加一口能盛水、熔岩、牛奶的锅,每个液体都应该可以有不同高度,而且肯定得反复使用,不能只用一次就歇菜。
除此之外,我添加这个锅和原版的炼药锅的区别是,这个锅可以做饭和混合黑曜石。相当于不用钻石镐就获得黑曜石的一种途径。
最后,我打算叫它“坩埚”。



https://klpbbs.com/static/image/hrline/line7.png


分析与解决



好的,那么既然是坩埚,第一件事就是给它确定一个命名空间ID。我把坩埚丢进了翻译器里,结果是“crucible”。校对了一下意思,发现没有很大的歧义,于是在本例子中,我就把它的ID定为“supplementary:crucible”吧!
于是我在行为包根目录/blocks/下创建crucible.json。打开它,首先把基本的方块格式写出来。
然后我注意到需要定义两个方块属性,一个用来管液体的类型,一个用来管液体的高度。然后要给两个属性确定类型。液体高度我设置了7层,0层代表没有,6层代表满,而第7层是预留给以后使用的。至于另一个液体类型,当然是设置成字符串,这让代码易懂了很多。虽然也可以设置成数字,然后记住0代表什么1代表什么;但这样写出的代码,时间一久,自己都忘了这些代码到底怎么运作的,更不要提优化或者是修复漏洞了。
至于题目说的“做饭功能”,我暂且用做甜菜根汤代替,因为这个最简单。当然也可以做蘑菇煲和兔肉汤,但那些涉及到添加原料时的一个hasitem选择器问题,这就容易闹出版本问题和一堆历史遗留问题。总之,液体类型就设置成none、water、lava、milk和beetroot吧。
然后需要一个坩埚模型,随便做一个就好了。记得在做液体层数时给对应的立方体命名“layerX”,X代表到底是哪一层。以上用于part_visibility组件,实际上就是用于显示液体高度。我放一个我做的模型示例吧。

{
        "format_version": "1.12.0",
        "minecraft:geometry": [
                {
                        "description": {
                                "identifier": "geometry.crucible",
                                "texture_width": 112,
                                "texture_height": 112,
                                "visible_bounds_width": 2,
                                "visible_bounds_height": 2.5,
                                "visible_bounds_offset":
                        },
                        "bones": [
                                {
                                        "name": "root",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-8, 1, -8], "size": , "uv": },
                                                {"origin": [-8, 0, -8], "size": , "uv": },
                                                {"origin": [-8, 2, 6], "size": , "uv": },
                                                {"origin": , "size": , "uv": },
                                                {"origin": [-8, 0, 3], "size": , "uv": },
                                                {"origin": , "size": , "uv": },
                                                {"origin": [-8, 2, -8], "size": , "uv": },
                                                {"origin": [-8, 2, -6], "size": , "uv": },
                                                {"origin": , "size": , "uv": }
                                        ]
                                },
                                {
                                        "name": "layer1",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-6, 2, -6], "size": , "uv": }
                                        ]
                                }, //第1层,叫layer1,以下同理
                                {
                                        "name": "layer6",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-6, 14.85, -6], "size": , "uv": }
                                        ]
                                }, //不要在意这个顺序
                                {
                                        "name": "layer3",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-6, 7.14, -6], "size": , "uv": }
                                        ]
                                },
                                {
                                        "name": "layer5",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-6, 12.28, -6], "size": , "uv": }
                                        ]
                                },
                                {
                                        "name": "layer4",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-6, 9.71, -6], "size": , "uv": }
                                        ]
                                },
                                {
                                        "name": "layer2",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-6, 4.57, -6], "size": , "uv": }
                                        ]
                                },
                                {
                                        "name": "layer7",
                                        "pivot": ,
                                        "cubes": [
                                                {"origin": [-6, 17.42, -6], "size": , "uv": }
                                        ]
                                }
                        ]
                }
        ]
}

方块代码如下。
{
"format_version": "1.18.0",
"minecraft:block": {
    "description": {
      "identifier": "supplementary:crucible", //方块的命名空间ID,简称方块ID。
      "properties": {
      "supplementary:material_type": [ //液体类型
          "none", //没有液体
          "water", //水
          "lava", //熔岩
          "milk", //牛奶
          "beetroot" //甜菜根汤
      ],
      "supplementary:height": [ //液体高度
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7
      ]
      }
    },
    "components": {
      "tag:metal": {}, //暂时认为锅是金属的,添加一个金属标签
      "minecraft:on_interact": {
      "event": "fill_material" //交互时触发事件,事件名是fill_material,下文会讲
      },
      "minecraft:geometry": "geometry.crucible", //一口锅总得有个模型吧
      "minecraft:material_instances": {
      "*": {
          "texture": "crucible_empty", //有了模型,就可以用minecraft:material_instances组件直接定义纹理短名了。
          "render_method": "blend" //允许半透明,同时有防止它上面刷怪等效果
      }
      },
      "minecraft:destroy_time": 5, //设定破坏时间
      "minecraft:block_light_filter": 0.7,
      "minecraft:part_visibility": { //这个组件用于在对应的层数显示对应的高度。在1.19.80及以后,它被合并到了minecraft:geometry的bone_visibility中。
      "rules": {
          "layer0": "q.block_property('supplementary:height')==0",
          "layer1": "q.block_property('supplementary:height')==1",
          "layer2": "q.block_property('supplementary:height')==2",
          "layer3": "q.block_property('supplementary:height')==3",
          "layer4": "q.block_property('supplementary:height')==4",
          "layer5": "q.block_property('supplementary:height')==5",
          "layer6": "q.block_property('supplementary:height')==6",
          "layer7": "q.block_property('supplementary:height')==7"
      }
      }
    }, ...
}
}
然后,要让我们拿着水桶时点击坩埚,坩埚里得出现液体才行。所以在组件那里有minecraft:on_interact触发器组件,触发fill_material事件。这个事件会运用sequence来确定顺序,还有condition判定到底玩家手持的是什么。这个事件的代码如下。
...   "fill_material": {
      "sequence": [
          {
            "condition": "q.get_equipped_item_name=='water_bucket'", //如果玩家手里拿着水桶,那么...
            "set_block_property": { //设置方块属性。没错,可以像下面这样一次设置两个。
            "supplementary:material_type": "'water'", //液体类型设置为水。
            "supplementary:height": 6 //高度设置为满(6层高)
            },
            "run_command": { //运行命令
            "command": [
                "clear @p water_bucket 0 1",
                "give @p bucket"
            ] //清除水桶,给予空桶。记得限定只清除一个水桶。
            }
          },
          { //这部分用于熔岩
            "condition": "q.get_equipped_item_name=='lava_bucket'",
            "set_block_property": {
            "supplementary:material_type": "'lava'",
            "supplementary:height": 6
            },
            "run_command": {
            "command": [
                "clear @p lava_bucket 0 1",
                "give @p bucket"
            ]
            }
          },
          { //这部分用于牛奶
            "condition": "q.get_equipped_item_name=='milk_bucket'",
            "set_block_property": {
            "supplementary:material_type": "'milk'",
            "supplementary:height": 6
            },
            "run_command": {
            "command": [
                "clear @p milk_bucket 0 1",
                "give @p bucket"
            ]
            }
          }
      ]
      } ...
注:如果要用set_block_property设置一个字符串类型的方块属性,必须把要设置的值用''括起来才可以设置。例如"supplementary:material_type":"'water'"。
再注:我也不知道为啥要括起来,当时我不知道,没有括,结果报错了,于是就搁置了这个项目。后来看到一个附加包里用''括起来了,我也试了一下,居然成功了。
再再注:set_block_property可以一次设置两个属性,也是我突发奇想写的,没想到居然成功了。
到现在为止,一切都还好办。然后要定义方块排列(Permutations)。我也不知道为啥Permutations叫排列,可能是用翻译器翻译的吧。感觉好怪啊。
...
    "permutations": [
      {
      "condition": "q.block_property('supplementary:material_type')=='water'", //如果液体材料是水,那么用以下组件替换原来的组件。
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_water",
            "render_method": "blend"
            }
          }, //定义一个水的纹理。
          "minecraft:on_interact": {
            "event": "empty_water"
          } //玩家点击时触发事件empty_water。详情见下文。
      }
      },
      { //这个管熔岩
      "condition": "q.block_property('supplementary:material_type')=='lava'",
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_lava",
            "render_method": "blend"
            }
          },
          "minecraft:on_interact": {
            "event": "empty_lava"
          }
      }
      },
      { //牛奶
      "condition": "q.block_property('supplementary:material_type')=='milk'",
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_milk",
            "render_method": "blend"
            }
          },
          "minecraft:on_interact": {
            "event": "empty_milk"
          }
      }
      },
      { //甜菜根汤
      "condition": "q.block_property('supplementary:material_type')=='beetroot'",
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_beetroot",
            "render_method": "blend"
            }
          },
          "minecraft:on_interact": {
            "event": "empty_beetroot"
          }
      }
      }
    ]
...
我们已经完成了一大半,接下来就是定义如何清除坩埚里的液体了。刚才有empty_water等事件,以下是empty_water的代码。注:千万不要在清除液体时仅仅把液体高度设置为0,那样,这个坩埚还保持着水的液体类型,那这锅看起来是空了,实际上真就歇菜了,不能倒熔岩等其他液体了。这是因为锅还保持着水的液体类型,这个排列下,点击方块会触发empty_water事件而不是fill_material事件。
清除熔岩和牛奶比较简单,只需要把高度设为0,类型设为none,然后用命令把桶换成熔岩桶或牛奶桶就好了。但清除水时,有很多操作:加甜菜根可以变成甜菜汤,加熔岩可以变成黑曜石,用水瓶可以舀3瓶,用桶可以直接舀一锅。下面我放了我写的empty_water事件的示例。太长了,我折叠一下。

      "empty_water": {
      "sequence": [
          {
            "condition": "q.get_equipped_item_name=='beetroot'&&q.block_property('supplementary:height')==6", //如果锅里的水满了,而且玩家手持甜菜,那么...
            "set_block_property": { //把类型换成甜菜汤
            "supplementary:material_type": "'beetroot'",
            "supplementary:height": 6
            },
            "run_command": {
            "command": "clear @p beetroot 0 3" //清除3个甜菜根
            }
          }, //以上用于“加入甜菜根变成甜菜汤”功能
          {
            "condition": "q.get_equipped_item_name=='bucket'&&q.block_property('supplementary:height')==6",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p bucket 0 1",
                "give @p water_bucket"
            ]
            }
          }, //这个对象用于用桶舀水
          {
            "condition": "q.get_equipped_item_name=='glass_bottle'&&q.block_property('supplementary:height')>=3",
            "set_block_property": {
            "supplementary:height": "q.block_property('supplementary:height')-2"
            },
            "run_command": {
            "command": [
                "clear @p glass_bottle 0 1",
                "give @p potion"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='glass_bottle'&&q.block_property('supplementary:height')<=2",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p glass_bottle 0 1",
                "give @p potion"
            ]
            }
          }, //以上两个对象用于用水瓶舀水。因为可以舀3次,所以前两次减少液体层数,最后一次直接把液体类型设置为none,清空液体层数。如果不这么做会导致锅用一次就歇菜。
          {
            "condition": "q.get_equipped_item_name=='lava_bucket'&&q.block_property('supplementary:height')==6",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p lava_bucket 0 1",
                "give @p bucket",
                "give @p obsidian"
            ]
            }
          } //用于混合黑曜石
      ]
      }

一番操作猛如虎,经过好几次T&E之后,我终于做好了坩埚。以下代码就是我的crucible.json里写的内容,供大家参考。

{
"format_version": "1.18.0",
"minecraft:block": {
    "description": {
      "identifier": "supplementary:crucible",
      "properties": {
      "supplementary:material_type": [
          "none",
          "water",
          "lava",
          "milk",
          "beetroot"
      ],
      "supplementary:height": [
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7
      ]
      }
    },
    "components": {
      "tag:metal": {},
      "minecraft:on_interact": {
      "event": "fill_material"
      },
      "minecraft:geometry": "geometry.crucible",
      "minecraft:material_instances": {
      "*": {
          "texture": "crucible_empty",
          "render_method": "blend"
      }
      },
      "minecraft:destroy_time": 5,
      "minecraft:block_light_filter": 0.7,
      "minecraft:part_visibility": {
      "rules": {
          "layer0": "q.block_property('supplementary:height')==0",
          "layer1": "q.block_property('supplementary:height')==1",
          "layer2": "q.block_property('supplementary:height')==2",
          "layer3": "q.block_property('supplementary:height')==3",
          "layer4": "q.block_property('supplementary:height')==4",
          "layer5": "q.block_property('supplementary:height')==5",
          "layer6": "q.block_property('supplementary:height')==6",
          "layer7": "q.block_property('supplementary:height')==7"
      }
      }
    },
    "events": {
      "empty_water": {
      "sequence": [
          {
            "condition": "q.get_equipped_item_name=='beetroot'&&q.block_property('supplementary:height')==6",
            "set_block_property": {
            "supplementary:material_type": "'beetroot'",
            "supplementary:height": 6
            },
            "run_command": {
            "command": "clear @p beetroot 0 3"
            }
          },
          {
            "condition": "q.get_equipped_item_name=='bucket'&&q.block_property('supplementary:height')==6",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p bucket 0 1",
                "give @p water_bucket"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='glass_bottle'&&q.block_property('supplementary:height')>=3",
            "set_block_property": {
            "supplementary:height": "q.block_property('supplementary:height')-2"
            },
            "run_command": {
            "command": [
                "clear @p glass_bottle 0 1",
                "give @p potion"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='glass_bottle'&&q.block_property('supplementary:height')<=2",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p glass_bottle 0 1",
                "give @p potion"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='lava_bucket'&&q.block_property('supplementary:height')==6",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p lava_bucket 0 1",
                "give @p bucket",
                "give @p obsidian"
            ]
            }
          }
      ]
      },
      "empty_lava": {
      "sequence": [
          {
            "condition": "q.get_equipped_item_name=='bucket'&&q.block_property('supplementary:height')==6",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p bucket 0 1",
                "give @p lava_bucket"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='water_bucket'&&q.block_property('supplementary:height')==6",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p water_bucket 0 1",
                "give @p bucket",
                "give @p obsidian"
            ]
            }
          }
      ]
      },
      "empty_milk": {
      "sequence": [
          {
            "condition": "q.get_equipped_item_name=='bucket'&&q.block_property('supplementary:height')>5",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p bucket 0 1",
                "give @p milk_bucket"
            ]
            }
          }
      ]
      },
      "empty_beetroot": {
      "sequence": [
          {
            "condition": "q.get_equipped_item_name=='bowl'&&q.block_property('supplementary:height')>=3",
            "set_block_property": {
            "supplementary:height": "q.block_property('supplementary:height')-2"
            },
            "run_command": {
            "command": [
                "clear @p bowl 0 1",
                "give @p beetroot_soup"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='bowl'&&q.block_property('supplementary:height')<=2",
            "set_block_property": {
            "supplementary:material_type": "'none'",
            "supplementary:height": 0
            },
            "run_command": {
            "command": [
                "clear @p bowl 0 1",
                "give @p beetroot_soup"
            ]
            }
          }
      ]
      },
      "fill_material": {
      "sequence": [
          {
            "condition": "q.get_equipped_item_name=='water_bucket'",
            "set_block_property": {
            "supplementary:material_type": "'water'",
            "supplementary:height": 6
            },
            "run_command": {
            "command": [
                "clear @p water_bucket 0 1",
                "give @p bucket"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='lava_bucket'",
            "set_block_property": {
            "supplementary:material_type": "'lava'",
            "supplementary:height": 6
            },
            "run_command": {
            "command": [
                "clear @p lava_bucket 0 1",
                "give @p bucket"
            ]
            }
          },
          {
            "condition": "q.get_equipped_item_name=='milk_bucket'",
            "set_block_property": {
            "supplementary:material_type": "'milk'",
            "supplementary:height": 6
            },
            "run_command": {
            "command": [
                "clear @p milk_bucket 0 1",
                "give @p bucket"
            ]
            }
          }
      ]
      }
    },
    "permutations": [
      {
      "condition": "q.block_property('supplementary:material_type')=='water'",
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_water",
            "render_method": "blend"
            }
          },
          "minecraft:on_interact": {
            "event": "empty_water"
          }
      }
      },
      {
      "condition": "q.block_property('supplementary:material_type')=='lava'",
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_lava",
            "render_method": "blend"
            }
          },
          "minecraft:on_interact": {
            "event": "empty_lava"
          }
      }
      },
      {
      "condition": "q.block_property('supplementary:material_type')=='milk'",
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_milk",
            "render_method": "blend"
            }
          },
          "minecraft:on_interact": {
            "event": "empty_milk"
          }
      }
      },
      {
      "condition": "q.block_property('supplementary:material_type')=='beetroot'",
      "components": {
          "minecraft:material_instances": {
            "*": {
            "texture": "crucible_beetroot",
            "render_method": "blend"
            }
          },
          "minecraft:on_interact": {
            "event": "empty_beetroot"
          }
      }
      }
    ]
}
}

模型文件在教程开头已经给出了,我会把我制作的方块纹理打包放在下方,有需要的可以参考。




https://klpbbs.com/static/image/hrline/line3.png


总结



这一期,我们制作了一个坩埚方块,可以盛装液体,也可以制作黑曜石和甜菜根汤。下期我们继续示范方块制作。
同时,这也是到目前为止我写的最长的一篇教程,大小达到了25KB,这个大小可能还会被超越。





第三十二期 第三十三期 第三十四期

Yu_Zhuohao 发表于 2025-1-20 14:56:14

Cat_Anchor 发表于 2023-3-26 10:38
就是坩埚在游戏内的样子(去除了背景)

现在1.21.5版本好像用不了了,请问可以更新一下教程吗?

Yu_Zhuohao 发表于 2025-1-20 14:54:59

Cat_Anchor 发表于 2023-3-26 10:38
就是坩埚在游戏内的样子(去除了背景)

可以发一下完整的addon包吗?自己做的addon中方块和实体无法显示和调出

Cat_Anchor 发表于 2023-3-26 10:38:40

嗷呜不生电 发表于 2023-3-26 07:34
一开始那个图片是啥

就是坩埚在游戏内的样子(去除了背景)

承挨 发表于 2023-3-26 07:41:35

苦力怕论坛感谢有你!

嗷呜不生电 发表于 2023-3-26 07:34:19

一开始那个图片是啥
页: [1]
查看完整版本: 附加包教程:33.方块(五)