#-1 前言
本文内容仅供参考,具体以官方文档和 Mojang 的史山为准。本文以开发锈湖主题的 Mod 为演示,后续会将其上传到 github 上。
阅读本文/模组开发你需要:
- 准备一台装有 Windows 系统且能带动 MC 的电脑(Linux和mac大概也行)
- 一双会写 Java 代码的手(一只也行)
- 一双用于阅读阅读文档和代码的眼睛(一只也行)
- 一个能大致理解 Java 代码的大脑
- 然后不知道了
注意本文为笔记,各种专业术语会及其的不专业(毕竟只是给自己看的),有些搞不懂的也只能直接写上去了(
#0 配置环境
因为环境只用配置一遍,而我已经配置好了,所以咕咕咕。
先放一个模组生成器(缺省源):https://fabricmc.net/develop/template/
在 Intellij IDEA 中打开下载好的文件,这是目录,做参考用:
RustyLakeMod-template-1.21 |- .gradle |- .idea |- build |- gradle |- run |- src |- main |- java |- top |- galno |- mixin |- TxampleMixin |- RustyLakeMod.java |- RustyLakeModClient.java |- RustyLakeModDataGenerator.java |- resources |- assets |- rustylakemod |- icon.png |- fabric.mod.json |- rustylakemod.mixins.json |- .gitattributes |- .gitignore |- build.gradle |- gradle.properties |- gradlew |- gradlew.bat |- LICENSE |- settings.gradle
以及我们需要下载 MC 源代码等东西,放在外部库中。通过阅读 Mojang 和 fabric 的代码来学习如何写代码。双击 shift 可以打开搜索框,可以在里面全局搜索文本、类等代码。
在 galno
这个文件夹下的 RustyLakeMod.java
中,有一个 public void onInitialize()
函数,这个函数在加载模组时会被调用到,类似于整个 mod 的“主函数”,因此如果我们想用别的类就需要在这个类下来加载和调用。
#1 物品(Items)
注册
Mojang 对类的命名方法一般为,-s
表示该类用于注册某些东西,例如 Item
类用来定义物品属性等内容,Items
这个类就用于注册物品。通过搜索框搜索到 Items
类,我们找一个功能最简单的物品例如 diamond,在这个类中搜索可以发现 diamond 是这样注册的:
public static final Item DIAMOND = register("diamond", new Item(new Item.Settings()));
Ctrl+左键查看一下这里的 register
函数,然后你就能看见 mojang 的史山;
public static Item register(String id, Item item) { return register(Identifier.ofVanilla(id), item); } public static Item register(Identifier id, Item item) { return register(RegistryKey.of(Registries.ITEM.getKey(), id), item); } public static Item register(RegistryKey<Item> key, Item item) { if (item instanceof BlockItem) { ((BlockItem)item).appendBlocks(Item.BLOCK_ITEMS, item); } return Registry.register(Registries.ITEM, key, item); }
可以看见 register(String id, Item item)
这个函数就是在 minecraft
这个命名空间下注册一个 id 为 id
的物品。那么我们如何在自己的命名空间下注册物品?
在 galno
这个文件夹下新建一个 item
文件,再在这个文件夹下面新建一个 ModItems.java
,这个类用来注册我们模组的物品。
先将 mojang 的三个 register
函数压缩一下,方便我们自己调用:
public static Item registerItems(String id,Item item){ return Registry.register(Registries.ITEM,RegistryKey.of(Registries.ITEM.getKey(),Identifier.of(RustyLakeMod.MOD_ID,id)),item); }
真长,我们可以将其缩短一下:
public static Item registerItems(String id, Item item){ return Registry.register(Registries.ITEM, Identifier.of(RustyLakeMod.MOD_ID,id), item); }
可以看见这里将 RegistryKey.of
以及里面的一大串参数替换成了 Identifier.of
,如果我们查看一下 register
这个函数可以发现这个位置的参数类型是 Identifier
,因此这里可以用 fabric 提供的一个函数来简化。
以注册锈湖的火柴(matches)为例,学习 mojang 注册钻石(diamond)的方式,我们便可这样写:
public static final Item MATCHES = registerItems("matches",new Item(new Item.Settings()));
现在我们还需要写一个函数来加载这个类:
public static void registerModIems(){ RustyLakeMod.LOGGER.info("Register Items");//该信息会在游戏加载mod时显示在命令行中 }
并在 RustyLakeMod.java
中调用:
ModItems.registerModIems();
基本属性
现在我们就成功的注册了这个物品,但是只是注册了,还没有写物品的属性。一个最普通的物品至少需要这三个东西:语言(lang),模型(models),贴图(textures)。
这些都被存在 resources/assets/rustylakemod
下,MC 玩的久的应该都能知道 assets
是游戏里的资源包,因此目录结构也就好说了:
rustylakemod |- lang |-en_us.json |-zh_cn.json |- models |- item |- matches.json |- textures |- item |- matches.png
几个文件的具体内容我们照着 MC 原版的物品来写就行了。
{ "item.rustylakemod.matches": "火柴", }//zh_cn.json(en_us.json同理)
{ "parent": "minecraft:item/generated", "textures": { "layer0": "rustylakemod:item/matches" } }//matches.json
matches.png
爱怎么画就怎么画。
现在我们就可以启动游戏了,在 IDEA 的右上角选择 Minecraft Client
并点击运行。启动游戏后可以通过 /give rustylakemod:matches
来获取这个物品。
#2 物品栏(ItemGroups)
原版物品栏
物品栏即创造模式中对物品分类、拿取的地方。比如打火石于工具(Tools)这个分类。
依旧以火柴为例,现在我们将它加入到原版的工具(Tools)这个物品栏里,这里需要用到 fabricAPI 中的类(mixin)FabricItemGroupEntries
中的功能,我们在 ModItems.java
中写入以下函数:
public static void addItemToIG(FabricItemGroupEntries fabricItemGroupEntries){ fabricItemGroupEntries.add(MATCHES); }
并在用于初始化的函数中调用这个函数,其中 .TOOLS
是原版物品栏 id:
ItemGroupEvents.modifyEntriesEvent(ItemGroups.TOOLS).register(ModItems::addItemToIG);
启动游戏后可以发现创造物品栏工具这一栏中的最下方可以拿取火柴。
模组物品栏
与上文注册 Item 同理,我们搜索 ItemGroups
这个类,找到 ItemGroups.java
,可以看见这里注册了所有的原版物品栏。我们直接照着抄就可以:
public static final RegistryKey<ItemGroup> RUSTYLAKE_GROUP = register("rustylake_group"); private static RegistryKey<ItemGroup> register(String id) { return RegistryKey.of(RegistryKeys.ITEM_GROUP, Identifier.of(RustyLakeMod.MOD_ID,id)); } public static void registerModItemGroups(){ Registry.register( Registries.ITEM_GROUP,//原版代码中注册物品栏的函数会传进来一个参数, //这里我们知道类型后直接写,就不用再传参数了 RUSTYLAKE_GROUP,//这里就是物品栏的名称 ItemGroup.create(ItemGroup.Row.TOP,7)//这里的参数对应游戏里物品栏按钮的位置 //若填写-1则加入末尾 .displayName(Text.translatable("itemGroup.rustylake_group")) .icon(() -> new ItemStack(ModItems.MATCHES))//这里的参数是物品栏的图标 .entries(((displayContext, entries) -> { entries.add(ModItems.MATCHES);//这里是物品栏中的物品 })) .build() ); RustyLakeMod.LOGGER.info("Registering Item Groups"); }
当然这一坨还是有点长了,fabricAPI 也提供了相应的接口,我们便可以将它稍微缩短一下(变长了(():
public static final ItemGroup RUSTYLAKE_GROUP = Registry.register(Registries.ITEM_GROUP,Identifier.of(RustyLakeMod.MOD_ID,"rustylake_group"), ItemGroup.create(null, -1).displayName(Text.translatable("itemGroup.rustylake_group")) .icon(() -> new ItemStack(ModItems.MATCHES)) .entries((displayContext, entries) -> { entries.add(ModItems.MATCHES); }).build());
这样就可以注册物品栏了,不要忘记将这个类初始化一下:
public static void registerModItemGroups(){ RustyLakeMod.LOGGER.info("Registering Item Groups"); }
并在 RustyLakeMod.java
中调用:
ModItemGroups.registerModItemGroups();
最后我们再在语言文件中写入物品栏的名称:
"itemGroup.rustylake_group": "锈湖"
## #3 方块(