在 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 ]。