提示

此教程仅适应用于 IntelliJ IDEA。

项目的构建与运行

首先打开 IDEA 的插件页面搜索插件 Minecraft Development,并安装重启 IDEA。

1.18模组开发-第1张图片

重启后,首先点击新建项目然后选择生成器 Minecraft,然后依次选择 Mod,Forge,1.18.1,其中 Use Mixins 可选,高级配置中可设置模组简绍,作者,网址,与更新地址,选填,其他可自由填写。

1.18模组开发-第2张图片创建并等待构建,若项目构建失败或构建速度太慢,可使用 DevSidecar 加速构建,构建完成后可能会对 com.mojang.logging.LogUtils 进行报错,并打开报错的文件,这时只需将报错的文件中的内容删除成大概以下这样即可:

package cn.ksmcbrigade.em;   //packet

import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@Mod("em")  //mod id
public class ExampleMod {

    private static Logger LOGGER = LogManager.getLogger(); //logger

    public ExampleMod() {  //main
        MinecraftForge.EVENT_BUS.register(this);
    }
}

然后点击 IDEA 右侧的 Gradle,然后依次打开 Tasks,forgegradle runs最后点击 RunClient 即可启动游戏。

1.18模组开发-第3张图片

简易功能实现

首先注册玩家刻事件:

package cn.ksmcbrigade.em;  //packet

import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@Mod("em")
@Mod.EventBusSubscriber //event bus
public class ExampleMod {

    private static Logger LOGGER = LogManager.getLogger();  //logger

    public ExampleMod() {  //main
        MinecraftForge.EVENT_BUS.register(this);
    }
    
    @SubscribeEvent
    public void PlayerTick(TickEvent.PlayerTickEvent event){  //player tick event
        
    }
}

接下来以 NoFall 功能为例,首先在玩家刻事件中判断玩家摔落高度是否大于等于 3,若大于则发送 OnGround 数据包以重置摔落高度:

@SubscribeEvent
public void PlayerTick(TickEvent.PlayerTickEvent event){  //player tick event
    if(event.player.fallDistance>=3){  //if >= 3
        ClientPacketListener connection = Minecraft.getInstance().getConnection(); //get connection
        if(connection!=null){  //if != null
            connection.getConnection().send(new ServerboundMovePlayerPacket.StatusOnly(true));  //send pakcet
        }
    }
}

最后再次运行 RunClient 进行测试是否成功。

以下是完整代码:

package cn.ksmcbrigade.em; //packet

import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@Mod("em")  //mod id
@Mod.EventBusSubscriber //event bus
public class ExampleMod {

    private static Logger LOGGER = LogManager.getLogger(); //logger

    public ExampleMod() {  //main
        MinecraftForge.EVENT_BUS.register(this);
    }

    @SubscribeEvent
    public void PlayerTick(TickEvent.PlayerTickEvent event){  //player tick event
        if(event.player.fallDistance>=3){  //if >=3
            ClientPacketListener connection = Minecraft.getInstance().getConnection();  //get connection
            if(connection!=null){  //if != null
                connection.getConnection().send(new ServerboundMovePlayerPacket.StatusOnly(true));  //send pakcet
            }
        }
    }
}

其他文件说明

mods.toml

# This is an example mods.toml file. It contains the data relating to the loading mods.
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
# The overall format is standard TOML format, v0.5.0.
# Note that there are a couple of TOML lists in this file.
# Find more information on toml format here:  https://github.com/toml-lang/toml
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader = "javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion = "${loader_version_range}" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license = "${mod_license}" 
#模组所使用的开源协议
# A URL to refer people to when problems occur with this mod
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId = "${mod_id}" #mandatory
#模组ID
# The version number of the mod
version = "${mod_version}" #mandatory
#模组版本
# A display name for the mod
displayName = "${mod_name}" #mandatory
#模组显示的名称
# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
#logoFile="em.png" #optional
#模组详细页面显示的图片
# A text field displayed in the mod UI
#credits="Thanks for this example mod goes to Java" #optional
# A text field displayed in the mod UI
authors = "${mod_authors}" #optional
#模组作者
# The description text for the mod (multi line!) (#mandatory)
description = '''${mod_description}'''
#模组简绍
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies.${ mod_id }]] #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 = "${forge_version_range}" #mandatory
#模组所需的Forge版本
# 模组的加载顺序
# BEFORE - 提前加载
# AFTER - 最后加载
ordering = "NONE"
# Side this dependency is applied on - BOTH, CLIENT, or SERVER
#BOTH 服务器和客户端都要加
#CLIENT 仅客户端需要,比如以上的NoFall就只需要CLIENT即可实现。
#SERVER 仅服务器需要
side = "CLIENT"# Here's another dependency
[[dependencies.${ mod_id }]]
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 = "${minecraft_version_range}"
#模组所需的游戏版本
ordering = "NONE"
side = "BOTH"

modid.mixins.json

{
  "required": true,
  "minVersion": "0.8",
  "package": "cn.ksmcbrigade.em.mixin",  //包含mixin文件的目录
  "compatibilityLevel": "JAVA_8",
  "refmap": "modid.refmap.json",  //这里的和文件名中的modid改为你的 modid。
  "mixins": [  //双端都要加载的mixin。
  ],
  "client": [  //仅在客户端需要加载的mixin。
  ],
  "injectors": {
    "defaultRequire": 1
  }
}