3,417
个编辑
MCBBS Wiki欢迎您共同参与编辑!在参与编辑之前请先阅读Wiki方针。
如果在编辑的过程中遇到了什么问题,可以去讨论板提问。
为了您能够无阻碍地参与编辑 未验证/绑定过邮箱的用户,请尽快绑定/验证。
MCBBS Wiki GitHub群组已上线!
您可以在回声洞中发表吐槽!
服务器状态监控。点击进入
本站由MCBBS用户自行搭建,与MCBBS及东银河系漫游指南(北京)科技有限公司没有从属关系。点此了解 MCBBS Wiki 不是什么>>
(// Edit via Wikiplus) |
(→Forge BlockStates V1模型文件格式: // Edit via Wikiplus) |
||
| (未显示同一用户的3个中间版本) | |||
| 第48行: | 第48行: | ||
== 模型文件的书写 == | == 模型文件的书写 == | ||
现在,blockstates JSON文件中的那个“variants”应该很好理解了——它实际上是囊括了该方块的所有IProperty。对于那些单BlockState方块而言,它们没有任何的额外IProperty,因此我们直接开个“normal”,再来指定它的模型文件路径即可,就这么简单。 | |||
但是对于多BlockState方块而言,显然我们期望不同的方块状态对应不同的样子,比如两种熔炉方块的外观会随着朝向的不同发生变化。这个时候就需要在variants下列出所有可能的IProperty的不同值之间的所有可能的组合情况了,我们来看看原版的熄灭的熔炉方块的blockstates JSON文件: | |||
{ | |||
"variants": { | |||
"facing=north": { "model": "furnace" }, | |||
"facing=south": { "model": "furnace", "y": 180 }, | |||
"facing=west": { "model": "furnace", "y": 270 }, | |||
"facing=east": { "model": "furnace", "y": 90 } | |||
} | |||
} | |||
熄灭的熔炉方块有且只有一个PropertyDirection,它被构造时传入的name是<code>"facing"</code>,而它实际上是一个PropertyEnum<EnumFacing>,EnumFacing实现了IStringSerializable,因此对于该方块,我们就可以列出"facing=[A certain EnumFacing instance.getName()]"这种式子表示一个BlockState,再指定它的具体模型情况即可。这里我们注意到朝向实际上不影响方块的材质,本质上模型只是转了一定的角度而已,因此这里model不变,而y(即方块模型绕过方块上下两面中心点的直线旋转的角度)则有所变化。注意这里指定模型文件路径时并没有指定域名(domain),那是因为这是原版blockstates文件,不写域名的话,域名默认为minecraft,而对于我们的模组的blockstates文件,域名必须得写——就是我们的模组的modid。 | |||
=== Forge BlockStates V1模型文件格式 === | |||
可能已经有读者注意到,原版的blockstates JSON文件格式是有优化空间的,比如在上面那个例子中,同样的“facing=”这种东西重复了四次,而且每种情况下模型文件实际上是相同的,只是绕y轴旋转的角度有所变化,但我们却依然要重复书写同样的模型文件路径,这实际上有些冗余。 | |||
而且当一个方块拥有的IProperty数量不只是一个时,情况往往会变得更加糟糕——比如再来一个有四种可能值的IProperty的话,我们真的就要把总共十六种情况全部列出来,真的就要在variants里写上十六行相差不大的东西。这听起来就让人头皮发麻。 | |||
所幸,Forge给我们提供了一个基于原版格式的blockstates文件格式——Forge BlockStates V1格式,让我们用它来重写原版的这一blockstates文件: | |||
{ | |||
"forge_marker": 1, | |||
"defaults": { "model": "furnace" }, | |||
"variants": { | |||
"facing": { | |||
"north": { "y": 0 }, | |||
"south": { "y": 180 }, | |||
"west": { "y": 270 }, | |||
"east": { "y": 90 } | |||
} | |||
} | |||
} | |||
首先,<code>"forge_marker": 1</code>代表这是一个符合Forge BlockStates V1格式的blockstates文件,这会告知Forge来处理它。然后我们可以通过设定defaults来设定该blockstates文件的一些默认值——毕竟四个方块状态共用一个模型文件,因此我们只需把它当成默认值写入即可。 | |||
然后就是variants中IProperty写法的简化了,也很容易让人明白。如果有多个IProperty,只需分开写即可,Forge会自动求出它们的所有可能值的所有可能的组合情况的。这就大大简化了blockstates的模型映射。 | |||
值得注意的是,虽然名字叫Forge BlockStates V1,但实际上这也可以用于方块的物品形式的模型的指定。还记得ModelResourceLocation构造方法中那个String类型的variantIn吗?我们传入的是<code>"inventory"</code>,所以这个inventory实际上就是一个variant,换言之,你只需要在variants中这么写即可: | |||
{ | |||
... | |||
"inventory": [{ | |||
"transform": "forge:default-block" | |||
}], | |||
... | |||
} | |||
甚至于和方块没什么关系的普通物品我们也可以写在blockstates文件中,只需要把transform改成forge:default-item,再指定一下textures即可。不过并不推荐这么做,因为普通的物品和方块既然没关系,那么放在blockstates文件中既多此一举,也容易造成歧义。 | |||
== 方块的Meta-hack == | |||
类似于ItemStack,方块也是可以有Meta-hack的——实际上是用同一个Block的不同BlockState及其对应的meta代表设定上不同的多种方块(实际上在代码层面都对应同一个Block对象)。和ItemStack的Meta-hack类似,方块的Meta-hack也是不推荐使用的。 | |||
首先我们需要一个区分方块类型的IProperty,一般是用PropertyEnum,用到的枚举类一般作为静态内部类的形式出现在方块类中;再设定该方块的hasSubtypes为true;然后在blockstates文件中,针对这个variant分别指定各自不同的模型文件路径,即可。没错,你没看错,就这么简单。 | |||
然而使用Meta-hack的方块对应的物品却不是这么简单——因为ItemBlock类的默认实现很可能不能满足我们的需求,为何?因为ItemBlock的默认逻辑是:若传入的Block的hasSubtypes为true,那么使用ItemBlock对应的某个ItemStack放置该方块时,该ItemStack的meta值和放置的BlockState对应的meta值,是相等的。因此如果你的方块只有这一个区分类型的IProperty,倒还没问题;但如果你同时还有其他几个IProperty呢,比如一个决定朝向的PropertyDirection?那就糟了,该ItemBlock的meta会影响到放置出来的方块的朝向,这显然不是我们所期望的,我们所期望的应当是:由放置该方块的实体的朝向来决定该方块的朝向。因此这个时候你就得覆写<code>Block#getStateForPlacement</code>才行,这个方法会传入对应的ItemStack,由此我们就可以手动指定符合我们自己的需求的BlockState和ItemStack的各自的metadata的正确对应关系。 | |||
另外,我们还得覆写<code>Block#getSubBlocks</code>方法,它的用途和之前提到过的getSubItems差不多,实际上ItemBlock类中的getSubItems方法就是代理给了getSubBlocks的。 | |||