本篇教程由作者设定未经允许禁止转载。
引言
目前制作匠魂3附属模组的主要方式有:纯Java代码、使用Json Things和使用MCreator。Json Things上手简单,无门槛,不包含Java代码,逻辑简单,但存在不小的局限性,只能用来编写较为简单的模组。
MCreator代码可视化,无门槛,局限性小,但容易出现低创模组和差评模组。
此教程主要针对如何使用纯Java代码,从安装IDE开始,创建一个1.18.2匠魂3的附属模组。
准备工作
安装Intellij IDEA
常用的Java IDE有Intellij IDEA、Eclipse等。从UI友好程度、直观性和美观性上来说,前者都是要优于后者的。
故此教程使用Intellij IDEA。
下载传送门->Download IntelliJ IDEA – The Leading Java and Kotlin IDE (jetbrains.com)
免费版即可,安装过程不再赘述,需要注意的是IDEA的系统资源消耗远大于Eclipse,电脑性能不佳的读者慎入。
准备Forge MDK
Forge MDK是一个项目模板,它是你的项目的基本框架。
下载传送门->Downloads for Minecraft Forge for Minecraft 1.18.2
注意:由于我们会安装多个非同一作者开发的模组,受作者更新频率等因素影响,其要求的Forge版本可能各不相同,如在启动时发现深红色的错误信息:cannot find …… in classpath,请按照“……”内的Forge版本更换MDK。(截至教程编写日期,所需版本为Forge 40.2.1),可在上图的“All Versions”中找到,如图:
点击后,进入如下页面
下载完成后,解压到一文件夹,文件夹名可以是你的项目名。需要注意的是文件夹名中不能包含中文或特殊字符。
更好的使用体验
汉化
用IDEA打开解压目录下的“build.gradle”文件,进入到如下页面
IDEA的默认界面语言是英语,为照顾部分英语水平欠佳的读者,这里提供安装简体中文语言包的教程。
点击左上角的“File”,在展开的页面中点击“Settings(图标为扳手)”
接下来,在设置页面中点击“Plugins”,按照下图操作:
安装完成后,第三步中的Install图标会变为绿底白字的“Restart IDE”。点击并按照提示重启,此时界面语言已变为中文,如图:
JDK
确保你指定了正确的Java SDK。点击“文件”选项卡下的“项目结构”,进入如下页面:
在左侧的选项卡下点击“项目”,为项目指定Java SDK。
实测Java 17.0.1可用,若构建时出现问题,请尝试使用JDK 8等版本。
更快地构建
为了在测试时拥有更快的构建速度你的时间非常宝贵,请按下图操作:
将这两项由“Gradle(默认)”改为“Intellij IDEA”,点击“应用”保留更改。
开发环境配置
build.gradle
打开文件选项卡下的“build.gradle”文件,在这里我们将进行构建最重要的一步。
由于我们是在编写匠魂的附属,那么我们就要声明匠魂为模组的运行库。
同时为了便于测试,这里建议将JEI添加进运行库中。
按照下文操作:
1.找到这三行字符
version = '1.0'
group = 'com.yourname.modid' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'modid'
将'com.yourname.modid'改为你的“域名”,例如slimeknights.tconstruct、com.james.tinkerscalibration,注意必须为英文
将'modid'改为你的模组名,例如tinkerscalibration,注意必须为英文
2.替换“examplemod”
这里为了操作简便,我们可以使用“编辑”选项卡下、“查找”子选项卡中的“替换”功能,将所有的“examplemod”改为你的模组名,注意必须为英文。
这部分需要特殊处理:
jar {
manifest {
attributes([
"Specification-Title" : "examplemod",
"Specification-Vendor" : "examplemodsareus",
"Specification-Version" : "1", // We are version 1 of ourselves
"Implementation-Title" : project.name,
"Implementation-Version" : project.jar.archiveVersion,
"Implementation-Vendor" : "examplemodsareus",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
}
将“examplemodsareus”替换为你的名字,例如“dddddsj”,最好为英文
此时“Date()”会报错,暂时不用管它。
3.添加匠魂和JEI的相关库
找到如下代码:
repositories {
// Put repositories for dependencies here
// ForgeGradle automatically adds the Forge maven and Maven Central for you
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
// flatDir {
// dir 'libs'
// }
}
将第一对大括号内的所有内容替换为:
mavenLocal()
maven { // SlimeKnights and JEI
name 'DVS1 Maven FS'
url 'https://dvs1.progwml6.com/files/maven'
}
这里同样提供几个其他热门模组的maven库,方便想要添加联动的读者:
待补充
然后找到下方的“dependencies {”,同样将其中所有内容替换为:
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
implementation fg.deobf("slimeknights.tconstruct:TConstruct:1.18.2-${tcon_version}")
implementation fg.deobf("slimeknights.mantle:Mantle:1.18.2-${mantle_version}")
implementation fg.deobf("mezz.jei:jei-${minecraft_version}:${jei_version}")
build.gradle修改完毕
mods.toml
转到src/main/resources/META-INF,打开“mods.toml”文件
将“modId="examplemod"”这一行中的“examplemod”改为你的模组名
将“displayName="Example Mod"”这一行中的“Example Mod”改为你的模组名的首字母大写带空格形式,注意必须为英文。
例如,“examplemod”修改为“tinkerscalibration”,“Example Mod”修改为“Tinkers Calibration”。
logoFile="examplemod.png"
credits="Thanks for this example mod goes to Java"
authors="Love, Cheese and small house plants"
description='''
This is a long form description of the mod. You can write whatever you want here
Have some lorem ipsum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis lacinia magna. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sagittis luctus odio eu tempus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque volutpat ligula eget lacus auctor sagittis. In hac habitasse platea dictumst. Nunc gravida elit vitae sem vehicula efficitur. Donec mattis ipsum et arcu lobortis, eleifend sagittis sem rutrum. Cras pharetra quam eget posuere fermentum. Sed id tincidunt justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
'''
以上几行代码分别是模组图标文件、鸣谢名单、作者团队和模组简介,可根据需要自行修改,可同时使用中文和英文。
[[dependencies.examplemod]] #optional
# the modid of the dependency
modId="forge" #mandatory
# Does this dependency have to exist - if not, ordering below must be specified
mandatory=true #mandatory
# The version range of the dependency
versionRange="[40,)" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
ordering="NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
side="BOTH"
# Here's another dependency
[[dependencies.examplemod]]
modId="minecraft"
mandatory=true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange="[1.18.2,1.19)"
ordering="NONE"
side="BOTH"
这里声明了模组的前置,以上代码分别声明了Forge和MC本体作为前置,需将“examplemod”改为你的模组名,然后添加如下代码:
[[dependencies.模组名]]
modId="tconstruct"
mandatory=true
versionRange="[1.18.2-3.6.4.113,)" //截至此教程编写日期,最新的tic版本
ordering="AFTER"
side="BOTH"
若要添加其他模组作为前置或联动,基本格式一致,需要注意的是若添加模组是本模组的前置,“mandatory”一行必须为“true”,否则为“false”。
gradle.properties
gralde.properties文件和build.gradle在同一目录下,打开它,把其中内容替换为如下代码:
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
mod_version=1.18.2-1.0.0
minecraft_base_version=1.18
minecraft_version=1.18.2
minecraft_range=[1.18.2,1.19)
forge_version=40.2.9 //如果你使用了其他版本的Forge MDK,修改此行至对应版本,例如40.2.1
mappings_version=2022.03.13
loader_range=[39.0,)
forge_range=[40.0.41,)
jei_version=9.7.1.255
tcon_version=3.6.4.113
mantle_version=1.9.44
tconstruct_range=[3.5.0.17,)
mantle_range=[1.9.20,)
这时build.gradle下的Date()不会报错了。
构建
按下图操作:
点击图标后,窗口左下角会提示“Gradle sync started(片刻之前)”,然后会开始下载MC的资源,这一过程受网络的影响可能会失败,没有关系,多试几次。
为了方便,这里建议进行如下操作:
当看到这行字时,即代表“genIntellijRuns”成功,此时就可以启动游戏了。
按下图操作,最后点击右侧绿色的“▶”或“🐞”图标,启动游戏。
这时运行或调试栏会自动弹出,DEBUG、INFO和WARNING都属正常,若在这个阶段出现ERROR,即代表你的设置不到位,请重新阅读这一节。
如果游戏启动后弹出错误:mods.toml missing metadata for modid ***,请完成“正式开发”章节的第一步,即修改文件夹名和类名提前,检查问题是否解决。
正式开发
恭喜你,你成功度过了会让大多数人放弃的阶段,正式开启了开发之旅!
也从这一步开始,下面的步骤需要一定的编程基础,不保证100%的人都能学会。
将com文件夹下的example和examplemod分别修改为你的名字和你的模组名,删掉默认的ExampleMod类,重建一个类:
在弹出的页面中给这个类一个名字,一般是你的模组名,需要英文,为了美观建议首字母大写。
注意,在以下内容中,直接复制粘贴的代码可能会报错,提示信息大多为“无法解析符号 '***'”。此时只需点击“导入类”。如果提示多选,选择有MC或匠魂的关键词的选项,例如“tconstruct”"minecraftforge"。
在主函数下,添加这一行代码:
public static final String MOD_ID = "*"; //*是你的模组名,需要英文
然后,在主函数前,添加如下代码:
@Mod(*.MOD_ID) //*是你的主类名,需要英文
注:在后面的步骤中,复制粘贴
第一个物品和创造模式物品栏
物品是MC的基础,也会在开发中不可避免地使用到,所以我们从添加物品开始。
在你的模组主类的文件夹下,建立一个新类,名字可以是“模组名”+“Items”。
在新类的主函数下,添加如下代码:
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, *.MODID); //*是你的主类名,需要英文
public static Item register() {
return new Item(new Item.Properties().tab(*.itemGroup));
}
此时代码会报错,暂时不用管它。
然后就要注册第一个物品了,例如我们要添加一个名为钢锭的物品,代码如下:
public static RegistryObject<Item> steel_ingot = ITEMS.register("steel_ingot", *::register); //*是这个类的名字
第一个物品注册成功,现在我们要给它添加材质和模型。
在resources文件夹下,新建这两个文件夹,注意后一个文件夹是前一个的子文件夹:assets、你的模组名(小写英文)。
接着,在后一个文件夹下,新建两个文件夹,两者是并列关系:models(模型)和textures(纹理)。
在models文件夹下,新建一个json文件,如图:
在随后弹出的窗口下给这个文件名字,它应该是“steel_ingot.json”。
注意IDEA的新建文件是不包含后缀名的,不要忘记输入后缀名。
在打开的steel_ingot.json下,输入如下代码:
{
"parent": "item/generated",
"textures": {
"layer0": "*:item/steel_ingot" //*是你的模组名
}
}
在texture文件夹下,粘贴你画好的材质,需要为16×16(或其整数倍)像素。
还记得上文的报错吗?需要如下处理:
在主类所在文件夹下,新建一个类,名为“模组名(英文大写)”+Group。
在后者中删掉自动创建的函数,添加如下代码:
public class * extends CreativeModeTab {
public *() {
super("*");
} //*是你的类名
@Override
public ItemStack makeIcon() {
return new ItemStack(#.steel_ingot.get()); //#是注册物品的类的名字
}
}
接下来,在主类的主函数下,添加如下代码:
public static final CreativeModeTab itemGroup = new *(); //*是上一个类名
但不要着急启动游戏,还有一步。
在模组主类的主函数下,输入如下代码:
public *() { //*是你的主类名
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
MinecraftForge.EVENT_BUS.register(this);
#.Items.register(bus);
}
此时就可以启动游戏了。
总结:目前我们的模组应该是如下结构:
main java com example examplemod ExampleMod.java
ExampleModItems.java
ExampleModGroup.java
ModGroup.java
resources assets examplemod models item steel_ingot.json
textures item steel_ingot.png
META-INF mods.toml
pack.mcmeta
模组主类的代码举例:
package com.example.examplemod;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@Mod(ExampleMod.MOD_ID)
public class ExampleMod {
public static final String MOD_ID = "examplemod";
public ExampleMod() {
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
MinecraftForge.EVENT_BUS.register(this);
ExampleModItems.ITEMS.register(bus);
}
public static final CreativeModeTab itemGroup = new ExampleModGroup();
}
如果我手滑把模组搞坏了怎么办?
在开发时,我们偶尔会因一些操作使游戏启动时报错,如果在撤销了这些操作后游戏仍然不能正常启动且错误信息难以理解,可以进行如下操作:
1.重新下载或解压一个相同版本的Forge MDK(如果你没有把原压缩文件删掉)。
2.将项目的以下文件复制粘贴到新项目下:build.gradle,gradle.properties和mods.toml。
3.按照教程构建项目,成功后再把原项目main文件夹下的所有内容复制粘贴过来。
这个方法可以解决部分项目的疑难杂症。如果不奏效,多半是代码问题,请借助翻译工具仔细分析问题原因。
第一个材料和强化
丰富的材料和强化是匠魂的魅力所在,也是大多数附属模组的核心。
材料
创建一个新类,名字可以为“模组名”+ Materials。
在这个新类下,输入如下代码,以创建“钢”材料为例:
public static final MaterialId steel = createMaterial("steel");
你会发现并不存在“createMaterial”函数,它的代码如下,同样放在这个类中:
public static MaterialId createMaterial(String name) {
return new MaterialId(new ResourceLocation(*.MODID, name)); //*是你的模组主类名
}
在模组主类的主函数前,添加如下代码:
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
在模组主类的主函数下,添加如下代码:
@SubscribeEvent
public static void gatherData(final GatherDataEvent event) {
DataGenerator gen = event.getGenerator();
ExistingFileHelper fileHelper = event.getExistingFileHelper();
if(event.includeClient()){}
if(event.includeServer()){} //两个大括号内的内容暂时不用填写
这样我们就成功创建了一种名为“steel”的新材料,但它目前仅仅是一个空壳。
想要给它添加渲染信息和等级、数据、材料特性,有两种方式,使用Java或Json。这里提供Json方法:
在resourses\assets\模组名下,新建一个名为tinkering的文件夹。在这个文件夹下,新建文件夹materials,在materials文件夹下新建一个名为steel的json文件。这个文件存放的是材料的渲染信息,详见纹理生成器及其相关内容使用教程 - [TiC3]匠魂3 (Tinkers' Construct 3) - MC百科|最大的Minecraft中文MOD百科 (mcmod.cn)。
在resources文件夹下新建一个名为data的文件夹,在这个文件夹下,用你的模组名新建文件夹,再新建tinkering和materials两个文件夹,均为嵌套关系。在materials文件夹下,新建三个并列文件夹:definition、stats和traits。
definition是材料的定义,包含是否可在部件制造台上制作、材料等级(1-4)、分类(主世界、下界、近程、远程等)和是否隐藏。以玛玉灵为例:
{
"craftable": false, //玛玉灵只可浇注
"tier": 4, //玛玉灵是四级材料
"sortOrder": 2, //玛玉灵主要用在武器上
"hidden": false //玛玉灵不是隐藏材料
}
注:“sortOrder”根据材料用途,共有如下分类:
0:普通 1:采掘 2:战斗 3:特殊(例如生铁) 4:战斗(仅远程,例如竹) 5:联动 10:下界 15:末地
20:仅绑定结 25:仅修复或材质用(用途未知,不建议使用)
stats是材料的属性数值,同样以玛玉灵为例:
{
"stats": {
"tconstruct:extra": {}, //附件,无数据
"tconstruct:handle": {
"durability": 1.1,
"miningSpeed": 0.9,
"attackSpeed": 0.95,
"attackDamage": 1.25 //近程手柄,均为倍率
},
"tconstruct:head": { //近程头部
"durability": 1250,
"miningSpeed": 6.5,
"harvestTier": "minecraft:netherite",
"attack": 3.5 //除采掘等级外均为具体数值,玛玉灵采掘等级为下界合金,采掘等级共有木、石、铁、金、钻石和下界合金六种,可自定义,后文涉及
},
"tconstruct:limb": { //弓臂
"durability": 1250, //具体数值
"drawSpeed": -0.35,
"velocity": 0.25,
"accuracy": -0.15 //这三项若增益则为正,不带负号;若减益则为负,带负号
},
"tconstruct:grip": { //弓把
"durability": 1.1, //倍率
"accuracy": -0.2,
"meleeAttack": 3.5 //具体数值
}
}
}
traits是材料的材料特性,有多种情况,这里以玛玉灵和银为例。
玛玉灵:
{
"default": [
{
"name": "tconstruct:insatiable", //贪婪
"level": 1
}
]
}
银:
{
"perStat": {
"tconstruct:ranged": [
{
"name": "tconstruct:holy", //神圣
"level": 1
}
],
"tconstruct:melee_harvest": [
{
"name": "tconstruct:smite", //亡灵杀手
"level": 1
}
]
}
}
当一种材料的近程和远程特性一致时,可以玛玉灵的形式使用“default”;不一致时,需使用“perStat”。若一种材料仅能作为近程或远程材料中的一种,建议使用“perStat”,参考铝:
{
"perStat": {
"tconstruct:ranged": [
{
"name": "tconstruct:featherweight", //轻盈
"level": 1
}
]
}
}
看到这里读者可能会产生疑惑,如果一种材料特性只有一级,不可叠加,该如何在“traits”中实现呢?
事实上,仅有一级的强化会在强化本身中实现,见后文。
强化
简单的强化可使用Json,但较复杂的(例如贪婪、黏液覆层)需使用Java。简单的强化Java也可以,总结就是Java无所不能但也有例外
为了整齐,在项目主类的文件夹下新建一个“modifiers”文件夹,强化就存放在这个文件夹。
让我们从最简单的强化开始。定义一种“坚固”强化,每级提高工具10%的耐久度。
要编写一种强化(Modifier),我们就要在这种强化中继承匠魂的Modifier类,如图:
导入类时,鼠标指针悬停在报错的“Modifier”上,点击浮窗中的“导入类”,操作如下:
导入类后,添加如下代码:
@Override
public void addToolStats(ToolRebuildContext context, int level, ModifierStatsBuilder builder) {
ToolStats.DURABILITY.multiply(builder, 1 + 0.1 * level);
}
这段代码是什么意思呢?
将鼠标指针悬停在“@Override”上,可以看到描述如下:“Indicates that a method declaration is intended to override a method declaration in a supertype……”大致意思是,“@Override”是一个注解,表示其下方的函数重写了超类中的函数。
此处“超类”即是匠魂的“Modifier”类。进行如下操作跳转到“Modifier”类:
或:
进入到Modifier类。可以看到这个类的代码很长,可以用查找功能找到“addToolStats”函数:
可以看到,Modifier类中的“addToolStats”是一个空函数,在我们的强化中,我们重写了这个函数使它具有功能。
匠魂3中与“addToolStats”类似的函数有很多个,下表给出了强化常用函数的源代码和作用等:(红色加粗下划线的函数名称为常用函数,需重点理解)
注意:由于作者KnightMiner正在将方法迁移至各个不同的“钩”,此表中的内容可能与最新版本的匠魂3有差异,请以代码实际内容为准!
名称 | 源代码 | 作用 | 运行条件 | 说明 | 示例 |
registerHooks | protected void registerHooks(ModifierHookMap.Builder hookBuilder) | 给强化注册“Hook”(钩) | 打上强化时 | 某些特殊强化的函数在“钩”内。这个函数给强化注册了“钩 ”使得这些强化的函数可以被运行。 | “贪婪”强化:@Override |
getPriority | public int getPriority() { | 决定此强化什么时候运行 | 工具使用时 | 优先级数值越高,强化运行越早。 | 在匠魂3中,不毁强化不能阻止黏液覆层消耗。因为不毁的优先级为125,黏液覆层的优先级为150。 黏液覆层运行更早,消耗更早(不毁的原理是取消耐久消耗事件)。 |
addInformation | public void addInformation(IToolStackView tool, int level, @Nullable Player player, List<Component> tooltip, slimeknights.tconstruct.library.utils.TooltipKey tooltipKey, TooltipFlag tooltipFlag) | 给工具添加额外的显示信息 | 按下Shift键或在工匠砧上时 | 按下Shift键时,会显示工具的额外信息,例如某些强化给予的攻击伤害等。 | “光照提速”强化: @Override addStatTooltip、addPercentTooltip等函数会稍后讲解 |
addVolatileData | public void addVolatileData(ToolRebuildContext context, int level, ModDataNBT volatileData) | 给工具添加动态数据 | 强化加载时 | 工具的某些数据会不断改变,例如黏液覆层和储存的流体(储液强化)。 | “厚积”强化: @Override |
addToolStats | public void addToolStats(ToolRebuildContext context, int level, ModifierStatsBuilder builder) | 更改工具的面板属性 | 强化加载时 | 直接更改工具的攻击伤害、采掘速度和采掘等级等面板属性。 | “晶固”强化: @Override |
beforeRemoved | public void beforeRemoved(IToolStackView tool, RestrictedCompoundTag tag) | 更改工具的NBT | 强化即将被移除时 | 更改强化施加时给工具添加的NBT。 | “火焰保护”强化: @Override |
onRemoved | public void onRemoved(IToolStackView tool) | 清理工具的“persistent data”(持久信息) | 强化移除后 | 清理强化施加时给工具添加的持久信息(黏液覆层等)。 | “装饰”强化: @Override |
onDamageTool | public int onDamageTool(IToolStackView tool, int level, int amount, @Nullable LivingEntity holder) { | 更改工具的耐久消耗 | 工具耐久消耗时 | 取消、减少或增加工具的耐久消耗。 | “不毁”强化: @Override |
getRepairFactor | public float getRepairFactor(IToolStackView toolStack, int level, float factor) { | 更改工具的耐久回复 | 工具修复时 | 取消、减少或增加工具的耐久回复。 | “培植”强化: @Override |
onInventoryTick | public void onInventoryTick(IToolStackView tool, int level, Level world, LivingEntity holder, int itemSlot, boolean isSelected, boolean isCorrectSlot, ItemStack stack) | 更新工具 | 游戏刷新玩家的物品栏时 | 在玩家的物品栏内更新工具,主要是回复耐久(自我修复)。 | “同调”强化(暮色森林联动): @Override |
processLoot | public List<ItemStack> processLoot(IToolStackView tool, int level, List<ItemStack> generatedLoot, LootContext context) { | 更改战利品 | 获取战利品时(击杀生物、破坏方块) | 增加或减少玩家获得的战利品。 | “美味”强化: @Override |
canPerformAction | public boolean canPerformAction(IToolStackView tool, int level, ToolAction toolAction) { | 检查工具是否能进行特殊动作 | 未知 | 若返回值为true,则工具可以进行特殊动作。 | “招架”强化: @Override |
onBreakSpeed | public void onBreakSpeed(IToolStackView tool, int level, BreakSpeed event, Direction sideHit, boolean isEffective, float miningSpeedModifier) | 更改工具采掘速度 | 采掘速度计算时 | 更改工具的实时采掘速度。 | “悬空”强化: @Override |
removeBlock | public Boolean removeBlock(IToolStackView tool, int level, ToolHarvestContext context) { | 移除方块 | 工具使用时 | 从世界中移除方块。 | “荧光”强化: @Nullable |
afterBlockBreak | public void afterBlockBreak(IToolStackView tool, int level, ToolHarvestContext context) | 施加特殊效果 | 方块破坏后 | 在方块被破坏后施加特殊效果。 | “动力”强化: @Override |
finishBreakingBlocks | public void finishBreakingBlocks(IToolStackView tool, int level, ToolHarvestContext context) | 施加特殊效果 | 方块破坏动作完成后 | 施加特殊效果。 | “末影传送”强化: @Override |
getEntityDamage | public float getEntityDamage(IToolStackView tool, int level, ToolAttackContext context, float baseDamage, float damage){ | 计算武器伤害 | 实体被攻击时 | 改变武器造成的伤害。 | “贪婪”强化: public float getEntityDamage(IToolStackView tool, int level, ToolAttackContext context, float baseDamage, float damage) { |
beforeEntityHit | public float beforeEntityHit(IToolStackView tool, int level, ToolAttackContext context, float damage, float baseKnockback, float knockback) { | 更改击退或施加特殊效果 | 实体被攻击前 | 更改击退或施加需要在实体被攻击前施加的特殊效果。 | @Override |
afterEntityHit | public int afterEntityHit(IToolStackView tool, int level, ToolAttackContext context, float damageDealt) { | 施加特殊效果 | 实体被攻击时 | 成功命中实体后施加特殊效果 | @Override |
failedEntityHit | public void failedEntityHit(IToolStackView tool, int level, ToolAttackContext context) {} | 施加特殊效果 | 实体被攻击但未造成任何伤害时 | 某些强化会在命中实体后施加特殊效果,但可能出现并未造成伤害的情况 ,此时需要通过此方法移除施加效果(非必要) | “怒火”强化: @Override |
getProtectionModifier | public float getProtectionModifier(IToolStackView tool, int level, EquipmentContext context, EquipmentSlot slotType, DamageSource source, float modifierValue) { | 获得盔甲的保护系数。使用者被攻击时(多用在盔甲上) | 穿戴者被攻击时(盔甲) | 每1点返回值减免4%伤害,相当于1级保护魔咒。 可正可负,正则减免伤害,负则增加伤害。 | “爆炸保护”强化: @Override |
isSourceBlocked | public boolean isSourceBlocked(IToolStackView tool, int level, EquipmentContext context, EquipmentSlot slotType, DamageSource source, float amount) { | 决定穿戴者是否免疫伤害 | 穿戴者被攻击时(盔甲) | 使玩家免疫某些类型的伤害。 | “远距防摔”强化: @Override |
onAttacked | public void onAttacked(IToolStackView tool, int level, EquipmentContext context, EquipmentSlot slotType, DamageSource source, float amount, boolean isDirectDamage) {} | 施加特殊效果 | 穿戴者被攻击后(盔甲) | 对攻击者或穿戴者施加特殊效果(反伤、施加DEBUFF等)。 | “润湿”强化: @Override |
attackWithArmor | public void attackWithArmor(IToolStackView tool, int level, EquipmentContext context, EquipmentSlot slotType, LivingEntity target, DamageSource source, float amount, boolean isDirectDamage) {} | 施加特殊效果 | 穿戴者主动攻击时(盔甲) | 对穿戴者(攻击者)或目标施加特殊效果(增伤、施加BUFF等)。 | “惊险”强化(未知黏液头颅特性) @Override |
onUnequip | public void onUnequip(IToolStackView tool, int level, EquipmentChangeContext context) {} | 移除特殊效果 | 卸下盔甲时 | 移除盔甲穿戴时施加的特殊效果。 | “远视”强化: @Override |
onEquip | public void onEquip(IToolStackView tool, int level, EquipmentChangeContext context) {} | 施加特殊效果 | 装备盔甲时 | 应用盔甲穿戴时施加的特殊效果。 | “金质”强化: @Override |
onEquipmentChange | 用法同上 | ||||
shouldDisplay | public boolean shouldDisplay(boolean advanced) { | 决定强化是否会在工具属性信息上显示 | 无(相当于控制器) | 若返回值为true,则会在所有界面上显示。 | 无需 |
getDamagePercentage | public double getDamagePercentage(IToolStackView tool, int level) { | 决定工具耐久条上的显示内容 | 无 | 返回值为Double.NaN则为默认。 为0则不显示(相当于满耐久)。 其他值(0~1)则为损坏率,1为彻底损坏。 | “耐久护盾”强化(是黏液覆层、石盾之类强化的API): @Override |
showDurabilityBar | @Nullable | 决定是否要显示工具耐久条 | 无(相当于控制器) | 返回值为true则显示,为false则不显示。 | “黏液覆层”强化: @Nullable |
getDurabilityRGB | public int getDurabilityRGB(IToolStackView tool, int level) { | 决定工具耐久条颜色 | 无 | 某些强化(不毁、黏液覆层)会改变工具的耐久条外观 | “不毁”强化: @Override |
完成了强化代码后,就需要对强化进行注册。
创建一个新类,名字可以为“模组名”+ Modifiers。
这里需要用到类似Forge延迟注册器的强化注册器,代码如下:
public static ModifierDeferredRegister MODIFIERS = ModifierDeferredRegister.create(*.MODID);