本篇教程由作者设定未经允许禁止转载。

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中,最小的代码单位(能够编写代码)是类。类或许对于编程初学者而言不那么容易理解,

但请不要放弃,这是一个必然经过的过程。


类被用来描述一类具有共同/相似性质与行为的事物,即使其在具体行为上或许存在差异,但大体上没有偏离。

而类之间允许继承,继承一个类可以原封不动地继承其性质和行为,也可以进行修改。


关于类更好的解析……请看下图:

这是一幅猫的画像

Fabric Mod开发教程-02 创世之力(一)-第1张图片

这也是一副猫的画像

Fabric Mod开发教程-02 创世之力(一)-第2张图片

这两幅画像描绘的都是猫,所以可以归类到一个“猫画像类”。


这是一幅人类的画像

Fabric Mod开发教程-02 创世之力(一)-第3张图片

而这是另一幅人类的画像(AI生成的,所以画风有些突兀)
Fabric Mod开发教程-02 创世之力(一)-第4张图片


这两幅描绘的都是人类,所以可以归类到一个“人画像类”。

然后,这两个类的共同点是什么?都是画像,对吧。

没错,所以这两个类继承自“画像类”。

一个类只是一个抽象的概念,并非一个实际存在的东西,所以需要将其实例化(new)才能够使用(静态方法除外)。

实例化后的类被称作实例,实例都属于这个类,但可能拥有不同的属性。

比方说:现在有一个“人类”,

“张三”是一个“人类”的实例,“身份”是“法外狂徒”

“李四”也是一个“人类”的实例,“身份”是“五星公民”

区别是什么?具有属性不同。


当然,某些类有一些共同的特性,这时便需要用static将其修饰为静态。

静态的方法/字段可以在任何时候被调用,并且可以节省内存开销。


2.2.3 访问权限等级表

代表可以访问、代表不可访问。

访问修饰符该类本身该类所处的包该类的子类全局
public
protected
private

原表格如下:

Fabric Mod开发教程-02 创世之力(一)-第5张图片


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的图标作为演示(由于百科的显示问题,图片必须居中,所以可能没有那么醒目):

Fabric Mod开发教程-02 创世之力(一)-第6张图片(吃个布头【】)

然后,还需要添加对应的物品名称:

语言文件(简体中文): 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 物品属性剖析

【未完待续】