Minecraft Forge 1.20.1 模组制作(4):Forge事件

上一章我们讲了Forge注册表的使用。本章我们讲一个Forge中非常重要的系统:事件系统。

1. 事件和事件总线

事件(Event)在Minecraft运行到特定位置时由事件总线(Event Bus)触发。目前可以暂时将事件总线理解为集中处理事件的处理器。

Forge在原版游戏代码的经常需要修改的位置插入了一些事件触发点(Hook)。当游戏运行到这些触发点时,事件总线触发相应事件,并且通过事件处理的结果(见第3节)调整相应游戏逻辑。

事件总线一共有两个:Forge和Mod。Forge总线用于发出绝大多数游戏运行中的事件;Mod总线用于在模组加载阶段执行一些初始化操作。要判断一个事件是Forge还是Mod总线触发,只需要看这个事件是否实现IModBusEvent即可。这个接口仅用于标记,实现该接口的是由Mod总线发出,否则为Forge总线。

2. 监听事件

事件的监听(Subscribe)即定义一些代码,并通知事件总线在特定事件发出时执行这些代码。将一个静态方法标记为事件监听器(即需要在某个事件时执行)需要通过以下方法:

1)事件的方法签名必须是:

public static void someSubscriber(SomeEvent event)

即静态方法,输入参数为需要监听的事件,返回void

2)用注解标记该方法为事件监听器。一种方法是在相应方法加上@SubscribeEvent注解。另一种方法是在方法所在类加上@Mod.EventBusSubscriber注解,这个注解表示将类中所有具有上述签名的方法视为事件监听器。实际操作时建议两个注解同时加上。即:

@Mod.EventBusSubscriber(modid = ForgeTutorial.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class EventSubscribers {
	@SubscribeEvent
	public static void someSubscriber(SomeEvent event) {
		someAction();
	}
}

此时,当SomeEvent每次被触发时,someSubscriber就会被执行一次,输入参数为正在被触发的事件实例。

@Mod.EventBusSubscriber的两个参数分别为模组ID和想要监听的事件总线,建议都填上,不要省略,以防出现难以排查的故障。

当游戏加载时,Forge会扫描并收集所有事件监听器,并在当事件触发时执行对应事件监听器的代码。

注意:尽可能不要监听有子类的事件类。如果监听器监听的是父事件类,则任一子事件类被触发时都会执行该监听器代码,这很可能会造成监听器被错误地多次调用,产生难以发现的bug。有些事件类的子类定义在父类内部,在监听事件前应当仔细阅读事件的类定义。

注意:个别事件会在某段代码执行前后各触发一次,其中一般有一个phase变量确认目前在哪个阶段,例如LevelTickEvent。监听事件(尤其是和世界tick相关的事件)时应当先确认是否有这个问题,否则有可能因为监听器错误地被执行两次而产生难以发现的bug。

3. 事件的结果和取消

有时,事件会有一些执行结果,这些结果会影响事件触发点之后的游戏逻辑。事件的执行结果(若有)可以在事件监听器中通过对参数传入的事件实例进行操作来修改。事件的执行结果主要有2种:取消(Cancel)和结果(Result)。

*事件的执行结果并非必须具有某种特定意义。*每个事件的执行结果所造成的影响都可能不同,要确定事件的取消或结果会带来什么影响,需要找到源码中的事件触发点(通常可以在事件处进行Alt+F7查找使用位置以跳转)并分析其代码。事件的类声明上方通常也有Javadoc注释,但有时表述并不是很明确。

3.1 事件的取消

带有@Cancelable的事件可以取消。在事件监听器中执行setCanceled(true)可以设置使事件取消。事件取消时,通常会导致触发点之后的一些代码被跳过。

例如:事件LivingHurtEvent在有生实体(LivingEntity,包括玩家、生物、盔甲架)受到伤害时触发,当被取消时,整个受伤害处理过程被跳过,实体不会受到该伤害。

注意:对不带有@Cancelable的事件执行setCanceled会导致抛出异常。

3.2 事件的结果

带有@HasResult的事件有结果。结果可以通过setResultgetResult设置和获取。结果共有三种:ALLOW, DEFAULT, DENY. 结果并不必然地具有某种特定含义,其含义在每个事件和触发点处可能不同。通常在涉及到某种判断时,事件的结果ALLOW表示判断恒定为“是”,DENY表示恒定为“否”,DEFAULT表示为使用原逻辑判断。(但并非必然如此)

需要说明的是,事件的执行结果并不局限于取消和结果两种,也可以自定义。例如一些和右键互动相关的事件会另外定义一个InteractionResult作为结果。

4. 自定义事件及触发

要自定义事件,首先创建一个新的事件类:

@Cancelable
public class MyEvent extends Event {
	...
}

如果是Mod加载事件,加上implements IModBusEvent

随后触发该事件:

public void foo() {
	doSomething();
	MyEvent event = new MyEvent();
	MinecraftForge.EVENT_BUS.post(new MyEvent());		// 如果事件可以取消,post方法在事件被取消时返回true,未被取消时返回false
	if (event.isCanceled()) return;
	doSomethingElse();
}

MinecraftForge.EVENT_BUS.post方法中将该事件的所有监听器各执行一次,在这个过程中事件可能会被修改(例如取消、设置结果等)。在调用post后再查询上面的事件实例即可获得其是否被取消、结果等信息。

在上述代码中,如果事件被取消,则直接中断foo()的执行,其后的doSomethingElse被跳过。

如果是Mod总线事件,使用如下代码触发事件:

ModLoader.get().postEvent(event);	// 这个方法没有返回值

自定义事件的监听和第2节所述完全相同。

<think>嗯,用户遇到了Minecraft服务器启动时无法加载主类@user_jvm_args.txt的错误。我需要先分析可能的原因。根据引用[1]中的启动命令,用户可能没有正确配置Java参数文件。首先,检查user_jvm_args.txt是否存在,路径是否正确。用户可能在启动命令中引用了这个文件,但文件可能被误删或路径错误。 接下来,查看引用[3]提到的客户端mod问题,虽然这个错误通常与主类加载有关,但也不能完全排除mod冲突的可能性。不过,主类加载错误更可能与Java参数文件有关。需要确认用户是否在服务端安装了仅客户端的mod,如Optifine,这可能导致类加载错误,但报错信息可能不同。 然后,检查Java版本是否兼容。例如,某些Minecraft版本需要特定的Java版本,如果版本不匹配,也可能导致类加载失败。此外,启动命令中的参数是否正确,比如是否遗漏了-jar或其他必要的参数。 还要查看文件权限问题,用户可能没有足够的权限访问user_jvm_args.txt或相关目录。使用sudo或更改文件权限可能解决这个问题。同时,确保所有依赖库和Forge文件正确安装,没有损坏。 最后,建议用户逐步排查:验证文件结构、检查Java参数、确认Java版本、检查mod兼容性、测试基本启动命令。这样分步骤排除可能的原因,找到具体问题所在。</think>### 分步解决方案:Minecraft服务器启动时"找不到或无法加载主类 @user_jvm_args.txt"错误 1. **验证文件路径与内容** - 检查文件`user_jvm_args.txt`是否存在且路径正确,默认位置应为: ```bash /home/[用户名]/MinecraftServer/user_jvm_args.txt ``` - 确认文件内容格式正确,每行一个JVM参数,例如: ```properties -Xmx4G -Xms2G ``` 2. **检查启动命令格式** - 确保启动命令包含完整的参数链,参考引用[1]的标准命令格式: ```bash /usr/bin/java @/home/zxy/MinecraftServer/user_jvm_args.txt @/home/zxy/MinecraftServer/libraries/net/minecraftforge/forge/1.20.1-47.3.5/unix_args.txt nogui ``` - 验证`unix_args.txt`是否存在且包含正确的启动主类信息,例如: ```properties -DlibraryDirectory=libraries -jar forge-1.20.1-47.3.5.jar ``` 3. **排查MOD冲突(引用[3]相关)** - 移除`mods`目录下所有纯客户端MOD(如Optifine) - 使用二分法逐个添加MOD测试,直到复现错误 4. **检查Java环境** - 确认Java版本匹配(Forge 1.20.1需要Java 17): ```bash java -version ``` - 重新安装JDK: ```bash sudo apt install openjdk-17-jdk ``` 5. **文件权限修复** - 递归设置目录权限: ```bash chmod -R 755 /home/[用户名]/MinecraftServer ``` 6. **完整测试流程** - 新建空白目录测试最小化启动: ```bash mkdir test_server && cd test_server wget https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.3.5/forge-1.20.1-47.3.5-installer.jar java -jar forge-1.20.1-47.3.5-installer.jar --installServer ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值