本篇教程由作者设定未经允许禁止转载。
1 前情提要
在上期教程中,我们成功搭建了开发环境,也成功以Fabric Mod的方式输出了Hello World。
当然,仅仅只会这些是完全不够用的。
2 创世之力
“原初之神创造了这片方块堆砌的世界,
后日的子民能否重续前神之荣光?”
2.1 标识符
众所周知,Minecraft几乎给任何东西都标上了一个ID(Identifier,即标识符)。
标识符用于区分事物之间的差异,就好比一样事物的名称。
不过与真正用于称呼的名称相比,Minecraft要求每一个标识符只能特指一件事物,
不允许重名。(教程结束后可以自行尝试会发生什么)
如果你有浅显地接触过原版指令的话,你应该就能看懂后面那部分是什么了:
/give @s minecraft:apple
看不懂也没有关系,自己动手试一试就知道了。
苹果的ID就是“minecraft:apple”。
首先,我们需要知道,Minecraft中所有的物品,都继承自一个名为“物品”(Item)的类,
其包含了一个物品应该具有的属性与行为。
该如何创建一个新的物品呢?
非常简单,只需要new一下就好了。
“什么,你不知道new是什么意思?
也不知道什么是类?
那就赶紧去翻阅Java基础教程吧!
什么,你懒得去找……”
【PS:如无需要Java基础教程内容,请跳转至2.3小节】
2.2 世界运转的奥妙
2.2.1 Java
(PS:由于实力有限,以及对Java的了解程度较为浅显,或许某些地方存在漏错,还请指正)
Java是一门完全面向对象的高级程序设计语言,运行在JVM(Java Visual Machine,即Java虚拟机)。
教程请参阅:Java速成。
2.2.2 关于类的补充说明
在Java中,最小的代码单位(能够编写代码)是类。类或许对于编程初学者而言不那么容易理解,
但请不要放弃,这是一个必然经过的过程。
类被用来描述一类具有共同/相似性质与行为的事物,即使其在具体行为上或许存在差异,但大体上没有偏离。
而类之间允许继承,继承一个类可以原封不动地继承其性质和行为,也可以进行修改。
关于类更好的解析……请看下图:
这是一幅猫的画像
这也是一副猫的画像
这两幅画像描绘的都是猫,所以可以归类到一个“猫画像类”。
这是一幅人类的画像
而这是另一幅人类的画像(AI生成的,所以画风有些突兀)
这两幅描绘的都是人类,所以可以归类到一个“人画像类”。
然后,这两个类的共同点是什么?都是画像,对吧。
没错,所以这两个类继承自“画像类”。
一个类只是一个抽象的概念,并非一个实际存在的东西,所以需要将其实例化(new)才能够使用(静态方法除外)。
实例化后的类被称作实例,实例都属于这个类,但可能拥有不同的属性。
比方说:现在有一个“人类”,
“张三”是一个“人类”的实例,“身份”是“法外狂徒”
“李四”也是一个“人类”的实例,“身份”是“五星公民”
区别是什么?具有属性不同。
当然,某些类有一些共同的特性,这时便需要用static将其修饰为静态。
静态的方法/字段可以在任何时候被调用,并且可以节省内存开销。
2.2.3 访问权限等级表
✔代表可以访问、✘代表不可访问。
访问修饰符 | 该类本身 | 该类所处的包 | 该类的子类 | 全局 |
public | ✔ | ✔ | ✔ | ✔ |
protected | ✔ | ✔ | ✔ | ✘ |
无 | ✔ | ✔ | ✘ | ✘ |
private | ✔ | ✘ | ✘ | ✘ |
原表格如下:
2.3 注册器
诺要让一个事物具有名称,则必须要在“登记处”(Registry,正式名:注册器)登记。
注册方法如下:
Registry.register(<注册器实例>, <ID>, <注册物体>);
(我不做Forge教程的原因,是因为光是这一步就过于复杂)
2.4 添加物品
2.4.1 例子
让我们添加一个新的食物吧:
// package声明省略
import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExampleMod implements ModInitializer {
// ...
public static final Logger LOGGER = LoggerFactory.getLogger("template-mod");
@Override
public void onInitialize() {
// ...
// 已经不再需要打印此消息
// LOGGER.info("Hello Fabric world!");
LOGGER.info("Example Mod is load!");
}
// 用于存放这个被注册的物品,
// 方便引用。
public static final Item TEST_FOOD;
static{
// 实际的注册动作。
TEST_FOOD = Registry.register(BuiltInRegistries.ITEM, new ResourceLocation("modid","test_food"), new Item(
// 物品属性:食物属性:饱食度+999
new Item.Properties().food(new FoodProperties.Builder().nutrition(999).build())
));
}
/* 除了像上面那样注册以外,还可以这样:
*
* public static Item TEST_FOOD;
*
* public void onInitialize() {
* // 在Mod初始化时注册
* TEST_FOOD = Registry.register(...);
* }
*
*/
/* 这样:
*
* public void onInitialize() {
* // 直接注册,不使用变量代理:
* Registry.register(...);
* }
*/
}
这样我们就成功将物品的注册写好了,接下来,我们需要为我们的食物添加纹理与模型,路径如下(文件/文件夹不存在就自己创建):
物品模型: src/main/resources/assets/<modis>/models/item/test_food.json
物品纹理: src/main/resources/assets/<modis>/textures/item/test_food.png
一般情况下,物品模型需要继承"item/generated",这是标准的物品模型。
所有这里也不例外,直接继承:
{
"parent": "item/generated",
"textures": {
"":"纹理位置"
"layer0": "modid:item/test_food"
}
}
纹理使用的图片可以随意,这里使用Fabric的图标作为演示(由于百科的显示问题,图片必须居中,所以可能没有那么醒目):
(吃个布头【】)
然后,还需要添加对应的物品名称:
语言文件(简体中文): src/main/resources/assets/<modis>/lang/zh_cn.json
语言文件(English): src/main/resources/assets/<modis>/lang/en_us.json
格式如下:
{
"item.modid.test_food":"测试用食物"
}
然后就可以放入游戏中试试看了。
2.4.2 物品属性剖析
【未完待续】