想了想,我的教程必须要和别人的不一样才有存在的意义。我在这里不会一上来就介绍那种添加方块添加物品之类的,而不把原理什么的讲出来。要成为一个mod制作高手必须要了解minecraft和forge的运行方式。很幸运我们现在看过的代码都是经过mcp反混淆的了,我们没有必要像黑客一样的处理那种混淆之后的代码,但是看minecraft和forge的代码还是必要的。
在介绍forge的消息处理之前我们要先介绍一下forge是怎么运行的。我想相当多的mod制作者制作了低端mod好久却没有了解forge的运行原理。forge的运行原理就是在强奸字节码(比喻来自szszss的coremod教程)。要知道minecraft是基于java的,java的类加载器一旦加载了一个类到java虚拟机中,这个类就不可能被外部修改了,但是加载之前的类的字节码可不是这样被严格的保护的,那些字节码处于一种谁想强X就强X的程度。forge本身通过修改启动器的json(1.6以后是这样,而1.6之前是直接修改jar文件)而优先于minecraft加载,并且forge会在minecraft加载的时候调教那些正要被加载的字节码。
经过forge的一翻调教,安装完forge的minecraft就会在适当的时候去调用forge了。当然如果只做到这样的话那么也就是一个普通的mod了,既然是mod加载器就要有加载器的样子。forge不光自己强奸那些字节码,而且还允许基于forge的mod一起来调教minecraft。
如果一个mod只是在minecraft加载之后动一动minecraft提供的接口,那么这种mod就是普通mod。如果一个mod在minecraft加载的时候修改了minecraft本身的字节码被加载到jvm中那么这个mod就是所谓的coremod。简单的讲,coremod能够修改minecraft本身的类。当然了如果仅仅为了调用一些非公开的接口的话那么完全没有必要制作coremod,通过反射就可以的。我目前还不打算动coremod这种大坑。
上面扯了这么长一大段有的没的估计人都吓跑了吧,下面来讲一讲一个普通的mod是怎么被加载的。
forge会优先minecraft加载并且遍历mods文件夹中的压缩文件。forge会通过压缩文件里面的mcmod.info文件来判断mod的信息。如果符合mod加载条件的话forge就会加载整个mod的字节码到虚拟机里面。forge会通过asm来分析mod的字节码,如果发现mod的主类确实符合mod的要求,forge就会加载整个mod的类到jvm里面。
forge在加载了mod之后forge就会根据mod的订阅消息情况适时的发送消息。也就是说mod也是消息驱动的程序。当然开始一个mod的编程就要从消息处理开始。
forge提供了一个特殊的Annotation来订阅消息。这个Annotation 就是@EventHandler
当Mod主类(就是附上了@Mod的类)中的某个只接受一个参数的方法添加了@EventHandler 那么就说明这个方法是一个消息处理方法。处理的消息类型和方法名无关,但是和这个方法的参数类型有关。
下面给出了mod生命周期中可用的参数类型,通常来说你的mod将会按顺序被触发一下事件
- FMLPreInitializationEvent : 在所有事情之前运行。在这里读取配置文件、创建方块、创建物品等等。并且在这个通过GameRegistry注册它们。
- FMLInitializationEvent : 执行你的mod的设置。创建数据结构、注册合成、并且发送FMLInterModComms消息给其他mod。
- FMLPostInitializationEvent : 处理和其他mod的交互,并且完成你的mod的设置。
下面是服务器生命周期中的可用参数类型.
- FMLServerAboutToStartEvent : 在服务器开始之前被调用。
- FMLServerStartingEvent : 设定服务器的时候使用。用来注册命令,调整服务器。
- FMLServerStartedEvent : 在开始服务器的时候被调用。
- FMLServerStoppingEvent :在停止服务器的时候被调用。
- FMLServerStoppedEvent : 在服务器停止之后被调用
下面的两种用来接收特殊事件
- FMLFingerprintViolationEvent : 如果你的mod有问题的话,就会在FMLPreInitializationEvent之前被调用
- FMLInterModComms.IMCEvent : 在FMLInitializationEvent之后被触发如果你有来自其他mod的FMLInterModComms消息。
写在后面:尝试着写一点别的mod教程没有的东西,大概也算是创新吧。就是不知道大家喜不喜欢,这种一整页都没有一张图片的东西……毕竟是尝试吧。如果有错误还希望大家指正。滚回间隙睡觉了wwww
我一直不知道主文件裡面的這些名詞是什麼意思,非常感謝科普,受益匪淺
正在建设MC开发wiki。如果愿意,请帮助编辑
我才學做mod15天啊
虽然现在wiki的内容不是很多,不过至少索引了我所有能找到的中文资料,有事没事我也在更新词条到wiki上面。至于你说要解释名词,我总不能给你一个个的讲吧,只能给你讲一些你重点问的
不知该在哪里问,于是只好在这评论了= =
我写了这么一段代码用来自动在登陆服务器时打招呼:
public class LoginEventHandler
{
private static final Minecraft mc=Minecraft.getMinecraft();
@SubscribeEvent
public void onPlayerLogin(ClientConnectedToServerEvent event){
System.out.println("Logged In");
System.out.println(event.manager.getSocketAddress());
if(!event.isLocal) //We are on a server
{
mc.thePlayer.sendChatMessage("/say hi");
}
}
}
但是无法正常运行 请问大触有何解决方案? 谢谢!
log如下:
点击查看log
我记得Minecraft.thePlayer获得的是本地的player……这个大概就是空指针的原因吧。发送消息既然在服务端的话,那么应该需要EntityPlayer.addChatComponentMessage才可以吧
关于chat的部分没有仔细研究过呢,如果有错误请见谅
谢谢!Client Only mod也可这么操作吗?
还想问下是用EntityPlayer还是EntityPlayerMP呢?