用户:MashKJo/1.12.2模组开发教程/9.第一个方块:修订间差异

→‎添加一个新方块的流程:​ // Edit via Wikiplus
→‎添加一个新方块的流程:​ // Edit via Wikiplus
→‎添加一个新方块的流程:​ // Edit via Wikiplus
 
(未显示同一用户的4个中间版本)
第17行: 第17行:
* setResistance:传入一个float量,用于设置方块的爆炸抗性,实际抗性值为传入参数乘以3的结果
* setResistance:传入一个float量,用于设置方块的爆炸抗性,实际抗性值为传入参数乘以3的结果
* setHardness:传入一个float量,用于设置方块的挖掘硬度,注意这个setter也有可能影响爆炸抗性。特别地,还有一个该setter的特化版:setBlockUnbreakable,会把hardness设定为-1.0F,即让该方块变得像基岩一样不可破坏
* setHardness:传入一个float量,用于设置方块的挖掘硬度,注意这个setter也有可能影响爆炸抗性。特别地,还有一个该setter的特化版:setBlockUnbreakable,会把hardness设定为-1.0F,即让该方块变得像基岩一样不可破坏
* setUnlocalizedName、setCreativeTab:作用类似于Item类中的同名方法
* setUnlocalizedName、setCreativeTab:作用类似于Item类中的同名方法。注意:这里如果给setUnlocalizedName传入<code>"examplename"</code>,那么最终的本地化键名不是<code>item.examplename.name</code>,也不是<code>block.examplename.name</code>,而是<code>tile.examplename.name</code>
* setHarvestLevel:形参列表为<code>(String toolClass, int level)</code>,用于设定该方块的挖掘等级和应被什么种类的工具挖掘。实际上这个方法是Forge塞进去的——没错,Minecraft原版甚至没有挖掘等级这一概念,原版中某些方块需要特定等级的工具才能挖掘的例子纯属硬编码的结果。toolClass这个String代表工具类型,如<code>"picakxe"</code>、<code>"axe"</code>等等。而level的规则是:木制/金制工具的等级为0,石制为1,铁制为2,钻石工具则为3,-1则代表空手挖掘。另外注意:该方法的返回值类型为void,即不符合链式调用规则
* setHarvestLevel:形参列表为<code>(String toolClass, int level)</code>,用于设定该方块的挖掘等级和应被什么种类的工具挖掘。实际上这个方法是Forge塞进去的——没错,Minecraft原版甚至没有挖掘等级这一概念,原版中某些方块需要特定等级的工具才能挖掘的例子纯属硬编码的结果。toolClass这个String代表工具类型,如<code>"pickaxe"</code>、<code>"axe"</code>等等。而level的规则是:木制/金制工具的等级为0,石制为1,铁制为2,钻石工具则为3,-1则代表空手挖掘。另外注意:该方法的返回值类型为void,即不符合链式调用规则


例如,笔者新增了一个方块:红宝石块:
例如,笔者新增了一个方块:红宝石块:
第41行: 第41行:
  }
  }


最后,监听RegistryEvent.Register<Block>事件,把我们的新方块注册进游戏。
最后,先实例化,监听RegistryEvent.Register<Block>事件,把我们的新方块注册进游戏。


== 添加方块对应的物品形式 ==
== 添加方块对应的物品形式 ==
进入游戏后,读者可能会感到奇怪:创造模式物品栏里,并没有我们的新方块,用/give指令也得不到,只有用/setblock指令才能把该方块放置在世界中。那是因为我们还没有注册该方块的物品形式。
方块的物品形式首先是物品,实际上是ItemBlock——这是Item的一个子类,构造器接受一个Block参数的传入,这种设计很易于理解。我们直接实例化ItemBlock类,再通过监听RegistryEvent.Register<Item>事件即可把它注册进游戏。注意:我们不需要给方块的物品形式的实例调用一系列setter方法,但必须调用setRegistryName——且它的registryName和对应方块的registryName必须相同。
可能会有读者对前面Block类的setUnlocalizedName和setCreativeTab这两个setter感到奇怪——因为其实这两个方法只对物品有意义——毕竟放在世界中的方块需要什么对应的创造模式物品栏?是这样,这两个方法是为ItemBlock服务的。我们用我们的Block对象构造出一个ItemBlock后,该ItemBlock对象中的对应的创造模式物品栏、unlocalizedName这些信息会自动等于对应的Block对象中的对应信息的,这也是为什么我们不需要给ItemBlock调用一大堆的setter。
ItemBlock类中覆写了Item类中的一些方法,导致了ItemBlock对象的通用逻辑为:玩家在世界中对着非空气方块右键时,如果坐标合法(如Y坐标在0~255这个范围内),就会在该处放置一个对应的方块,同时手上的ItemStack的数量这一字段减一。除非你真的有特殊需求,否则你只需要直接实例化ItemBlock类得到方块的物品形式就好了,不用去先继承ItemBlock。
好了,现在再运行游戏,应该可以在创造模式物品栏中看到我们的方块的物品形式了。


== 为方块和ItemBlock提供模型和材质文件 ==
== 为方块和ItemBlock提供模型和材质文件 ==
和物品不同,方块的模型文件,并不是通过代码来指定的,而是通过<code>assets/[modid]/blockstates</code>路径下的与方块注册名同名的.json文件来指定的,例如,对于我们给前文添加的红宝石块:
<code>src/main/resources/assets/tutorial_mod/blockstates/ruby_block.json:</code>
{
    "variants":{
        "normal":{
            "model":"tutorial_mod:ruby_block"
        }
    }
}
这个文件的各部分内容都是什么意思,会在后面讲到,不过有一处是显而易见的:该文件把我们的方块的模型文件映射到了<code>assets/[modid]/models/block/ruby_block.json</code>这个文件。那么,再来看看模型文件的内容:
<code>src/main/resources/assets/tutorial_mod/models/block/ruby_block.json:</code>
{
    "parent": "block/cube_all",
    "textures":{
        "all": "tutorial_mod:blocks/ruby_block"
    }
}
由于我们要添加的红宝石块是类似于原版的铁块、金块等方块的——六个面的材质都一样,所以我们直接指定该模型文件的父模型为<code>assets/minecraft/models/block/cube_all.json</code>,然后我们就可以指定所有(all)面的材质文件了。我们可以看出,"parent"用于指定模型的父模型文件。之前讲过的物品模型文件,其父模型文件实际上是<code>assets/minecraft/models/item/generated.json</code>,这个模型文件主要设定了物品材质的默认几何变换。
读者翻阅原版的模型文件时,会发现这些模型的最终父模型是"builtin/generated",这实际上不指代一个具体的模型文件,它的意思是“交给相关的渲染代码处理”。
如果我想新增一个六个面材质不是全相同的方块呢?你可以继承原版其他的模型文件,如:<code>block/cube_column</code>、<code>block/cube_directional</code>等等。或者你就可以直接继承<code>block/cube</code>,然后你手动指定方块的六个面的材质和粒子效果材质的文件路径,也可以,但是一般没必要。
把绘制好的材质文件放到对应路径中,进入游戏,就可以看到世界中的方块的材质已经被正确渲染了。
但是,方块的物品形式仍然是紫黑色的,我们还需要给它声明模型。首先用<code>ModelLoader#setCustomModelResourceLocation</code>将它和一个ModelResourceLocation绑定,再:
<code>src/main/resources/assets/tutorial_mod/models/item/ruby_block.json:</code>
{
    "parent": "tutorial_mod:block/ruby_block"
}
没错,我们把它的父模型指定为之前的方块模型即可,MC的相关代码会自动把该物品的样子渲染成方块斜着放的样子的。
现在进入游戏测试,应该真的没什么问题了。
行政员、​优秀编辑者、​界面管理员、​监督员、​管理员、​小部件编辑者
3,417

个编辑