在 Minecraft 内部,方块也可以看作是可放置的物品,使用 Item
类的静态方法 getItemFromBlock(Block someBlock)
可以获得对应的物品。向游戏内注册该方块也是类似的使用 GameRegistry.registerBlock(Block blockToReg, String unlocalizedName)
。然而在处理渲染时需要多额外的一步。
以下为 Item
渲染
String nameToReg = MOD_ID + ':' + item.getUnlocalizedName().substring(5); Minecraft.getMinecraft() .getRenderItem().getItemModelMesher() .register(item, 0, new ModelResourceLocation(nameToReg, "inventory");
以下为 Block
渲染
Item item = Item.getItemFromBlock(block); // 从 Block 得到对应的 Item String nameToReg = MOD_ID + ':' + item.getUnlocalizedName().substring(5); Minecraft.getMinecraft() .getRenderItem().getItemModelMesher() .register(item, 0, new ModelResourceLocation(nameToReg, "inventory");
区别主要在于多了一句从 Block
获得 Item
。虽然是以 Item
注册了渲染,实际上这里和 Item
处理渲染的方法并不相同。
assets/<MOD_ID>/blockstates/<blockUnlocalizedName>.json
我所写的 mod 中许多方块都会根据不同的 BlockState
改变渲染模型,而 BlockState
中不同 IProperty
组合所对应状态所对应的模型在这里指定。关于 BlockState
,见上一篇 Forge API 详解。我在这里以 TransitRailMod 的电缆架作为例子。
在源代码中,WirePanel
是 CustomDirectionalBlock
的子类,因此继承其 EnumFacing FACING
的属性,这个方块又根据电缆架上是否插了日光灯改变 EnumBool LAMP
属性、是否是封闭的改变 EnumBool SHUT
属性。因此罗列一下:
FACING
指示方块朝向LAMP
决定是否有日光灯底座SHUT
决定电缆架是否有罩子封闭
在 assets/transitrailmod/blockstates/wire_panel.json
中:
{ "variants": { "facing=north,lamp=true,shut=false": { "model": "transitrailmod:wire_panel_with_lamp" }, "facing=north,lamp=false,shut=false": { "model": "transitrailmod:wire_panel" }, "facing=east,lamp=true,shut=false": { "model": "transitrailmod:wire_panel_with_lamp", "y": 90 }, ... "facing=east,lamp=false,shut=true": { "model": "transitrailmod:wire_panel_shut", "y": 90 }, "facing=south,lamp=true,shut=true": { "model": "transitrailmod:wire_panel_shut", "y": 180 }, ... } }
有 16 行不同的以 IProperty=value
的组合为键,以 model
和 y
作为值的 json
数据对,需要列出所有可能的组合。为了不需要为了不同的方块朝向单独建立模型,Minecraft 在这里提供了一个 y
,在此处输入 {0, 90, 180, 270}
中的一个就可以定义旋转角度,然而在游戏中,x
轴和 z
轴的正方向分别是 south
和 east
,朝向的值应该和模型的朝向一致。
然而万一你的方块非常 normal(不区分方向也没有别的属性,看上去就是个纯粹装饰性的方块也不会互动啊啥的),像 LogoBlock
这样写一个 normal
的键值对就可以了:
{ "variants": { "normal": { "model": "transitrailmod:logo_block" } } }
assets/<MOD_ID>/models/block/<model_name>.json
这里是存放模型文件的主要场所,在之前的 blockstates/<unlocalizedName>.json
中 model
键对应的值 <model_name>
应当在这里找到对应的 <model_name>.json
。关于建立方块模型,可以参照 Minecraft 原版的源代码,也可以使用第三方工具,比如 Mr Crayfish’s model editor(至少比全手动好得多然而然而不够好)。
assets/<MOD_ID>/models/item/<unlocalizedName>.json
如果你希望你的方块在物品栏、玩家手上(第一人称和第三人称)正确渲染,那么这里的 json
文件是必需的。这也就是说,如果是技术性方块(门的上下两半之类的)等不会在玩家手上和物品栏出现的的东西就可以没有这个文件。这里的文件对于物品和方块同样适用
Minecraft 自带的物品钻石剑:
{ "parent": "builtin/generated", "textures": { "layer0": "items/diamond_sword" }, "display": { "thirdperson": { "rotation": [ 0, 90, -35 ], "translation": [ 0, 1.25, -3.5 ], "scale": [ 0.85, 0.85, 0.85 ] }, "firstperson": { "rotation": [ 0, -135, 25 ], "translation": [ 0, 4, 2 ], "scale": [ 1.7, 1.7, 1.7 ] } } }
Minecraft 自带的泥土
{ "parent": "block/dirt", "display": { "thirdperson": { "rotation": [ 10, -45, 170 ], "translation": [ 0, 1.5, -2.75 ], "scale": [ 0.375, 0.375, 0.375 ] } } }
很容易发现和方块的模型一样,也有 parent
用于继承上一级别的物品, texture
用于指定贴图。然而作为 Item
模型,必须有 display
键,并根据需要写第一人称视角的 firstperson
或者第三人称视角的 thirdperson
。对于完整的方块,通常直接复制并修改内建的玩整方块模型即可,对于不完整的方块或者物品,可以参照类似性质的 json
修改。
然而注意到这里的 dirt
并没有 firstperson
键而只有 thirdperson
键。无论是 firstperson
还是 thirdperson
都有预先定义过的值。主要的点在于,其 scale
默认为 [ 1, 1, 1 ]
也就是方块放置下来时候的大小,对于第一人称视角,普通的方块大小正好所以无需指定,不完整的方块略小,所以对于火把一类的来说 scale
写 [ 2, 2, 2 ]
都是可以的,然而在第三人称视角,方块若还是按照原样渲染,将会导致拿在手上的方块在他人看来巨大无比麒麟臂,因此必须在 thirdperson
中指定缩小的 "scale": [ 0.375, 0.375, 0.375 ]
。