ModLauncher
cpw制作,用于1.13FML加载的库,吸取了LaunchWrapper的经验,并使用了StreamAPI和ServiceLoader简化代码。
会记录每一个类被
ITransformationService
和ILaunchPluginService
请求修改的历史。
加载流程
Launcher类是ModLauncher的入口类:
在构造方法中,初始化了用于存储Transformer的
TransformStore
,以及用于初始化ITransformationService
的TransformationServicesHandler
在
run
方法中,调用TransformationServicesHandler
的初始化方法,并创建TransformingClassLoader
,最后启动游戏
在TransformationServicesHandler
中,初始化了ITransformationService
:
在构造器中,使用了ServiceLoader来获得
ITransformationService
实例,并创建对应的TransformationServiceDecorator
用来初始化前者在
initializeTransformationServices
方法中分别通过TransformationServiceDecorator
间接调用ITransformationService
对应的方法
在TransformationServiceDecorator
中:
gatherTransformers
方法从ITransformationService
的transformers
方法中获得了ITransformer
的实例,并在TransformStore
中根据targets
方法的返回值注册了Target
对应的ITransformer
ITransformer
的加载流程至此告一段落,现在看到TransformingClassLoader
在类加载时的行为:
TransformingClassLoader
是一个ClassLoader
的子类,其内部类DelegatedClassLoader
是URLClassLoader
的子类,大部分方法都会调用后者的方法loadClass
方法会通过多次调用最终调用DelegatedClassLoader
的findClass
方法,这个方法首先读入二进制的类文件,然后调用ClassTransformer
的transform
方法,这个方法会调用ITransformer
的transform
制作方法
通过以上简单的流程分析,我们可以获得三个相关的信息——ITransformationService
、ITransformer
与ServiceLoader。
ITransformationService
ITransformationService是一个用来预处理环境并提供ITransformer
实例的接口,需要实现以下方法:
name
,返回Service的名称arguments
,传入一个双参数Function
来指定需要读取的游戏参数,第一个参数代表着要读取的参数名,最终读取的参数会变为"Service名.参数名"的形式,第二个参数代表着参数的描述argumentValues
,传入读取参数的结果initialize
,初始化方法,传入环境,切记不要调用Minecraft、其他Mod、自己Mod的普通部分的任何代码,不然会导致类被提前加载而出错onLoad
,加载Service时调用,传入环境及其他Service的列表transformers
,返回ITransformer
的实例
一个简单的实例如下:
ITransformer
这个ITransformer
与LaunchWrapper的IClassTransformer
相比有两大不同:
不再接收二进制class文件,转为asm的node
提早声明将要修改的类,而不是等到
transform
方法中再确定
ITransformer
作为修改类的接口,需要实现以下方法:
transform
方法接收asm的node和node相关的信息,这个node的类型由泛型T来确定,一般为ClassNode或MethodNodecastVote
,返回TransformerVoteResult
来决定是否修改一个类或方法YES
会调用transform
方法NO
会跳过这个类修改器REJECT
会抛出VoteRejectedException
错误DEFER
会抛出VoteDeadlockException
错误
targets
,返回需要修改的目标Target
列表,需要统一Target的类型,只有在这里返回的目标才会调用另外两个方法
通过Java 8的接口默认方法,以下几个方法可选实现:
arguments
,接收一个处理游戏参数的双重映射函数,可以在这里添加自己的参数argumentValues
,接收游戏参数,可以在这里获得游戏参数additionalClassesLocator
,返回一个包名前缀和用于寻找类的类名映射URL函数的组合,可以通过这个方法可以往ClassLoader中增加自定义的用于类加载的URLadditionalClassesLocator
,返回一个文件路径和用于寻找文件的文件名映射URL函数的组合,可以通过这个方法可以往ClassLoader中增加自定义的用于类以外的资源加载的URL
一个没有修改任何类的实例:
ServiceLoader
完成编写了ITransformationService
以及ITransformer
以后,我们还需要声明ITransformationService
实现,以便ModLauncher使用ServiceLoader进行加载。
创建META-INF/services/cpw.mods.modlauncher.api.ITransformationService
,将ITransformationService
实现的完整类名写入,例如:
安装方法
库文件挂载
复制版本json到另一个版本文件夹中,并修改对应的名称
在
libraries
中加入ModLauncher及其依赖以及自己编写的CoreMod修改
mainClass
为cpw.mods.modlauncher.Launcher
使用Forge加载
从Forge 1.13.2-25.0.216开始,可以使用Forge来加载无论是否包含普通Mod的ModLauncher CoreMod。
放入
.minecraft/mods
文件夹即可
Last updated