
Fallen Lib
提供运行时扩展工具的程序库
Fallen Lib 是一个小型开发者实用工具库。
目前用于 Fallen Gems & Affixes 的开发过程中。
对于 Fallen Gems & Affixes 2.0.7 及以下版本,请使用 1.2.0-hotfix 版本
此模组提供了一些 ASM 相关的 API 以及用于模组开发的运行时工具。
它不添加任何游戏内容,也不面向普通玩家。
开发环境
在 IDEA 中运行时,请使用带有 `core` 和 `runtime` 后缀的两个 JAR 文件(位于 附加文件 部分)。
对于正常游戏或分发,请使用普通 JAR 文件。
功能特性
FallenPatch
一个用于修补模组类的委托 API。
它可以挂钩精确的类或所有子类,
这有助于在扩展模组行为时减少重复修补。
要使用此 API,您必须实现 IFallenPatch 接口,并且该类必须带有参数正确的注解 @FallenPatch。
例如:
@FallenPatch(
priority = 1000,
targets = @Targets(
exact = {SomeClass.class},
subclass = {SuperClass.class}),
inserters = {FallenInserters.class})
public class FallenPatch implements IFallenPatch {
private final IPatchDescriptor desc;
// 这里必须提供一个这样的构造函数。
public FallenPatch(IFallenPatchCtorContext iFallenPatchCtorContext) {
desc = iFallenPatchCtorContext.currentPatch();
}
@Override
public void apply(ClassNode cn, IFallenPatchContext iFallenPatchContext) {
MethodInsnNode hook = iFallenPatchContext.getFallenInserter(
InserterKey.of("xxx.xxx.FallenInserters",
"hook",
InserterType.STANDARD_VOID));
for (MethodNode method : cn.methods) {
InsnList insns = method.instructions;
if (insns == null) continue;
PatchUtil.insertMethodHook(cn,
method,
m -> m instanceof MethodInsnNode mn
&& mn.owner.equals("xxx.xxx.ClassName")
&& mn.name.equals("methodName")
&& mn.desc.startsWith("(Ljava/lang/Object;")
&& Type.getReturnType(mn.desc).getSort() != Type.VOID,
InserterType.STANDARD_VOID,
hook,
false,
false);
}
}
}inserters 指向一个至少有一个方法带有 @FallenInserter 注解的类。
例如 FallenInserters.class:
public class FallenInserters {
@FallenInserter(type = InserterType.STANDARD_VOID)
public static void hook(IInserterContext<Object, Object> ctx, Object... args) {
Object rec = ctx.receiver();
}
}格式如下:
{
"required": true,
"min_version": "1.2.0",
"package": "xxx.package.name",
"fallen_patches": [
"FallenPatch",
"PatchClassName"
]
}
目前,FallenPatch 仅支持修补模组类。
未来可能会添加更多支持。
FallenInserter
与 FallenPatch 结合使用,在方法上使用参数类型和返回类型正确的 @FallenInserter 注解,
现在有 2 种 InserterType:
InserterType.STANDARD
InserterType.STANDARD_VOID
默认为 standard,其格式应如下所示:
@FallenInserter(type = InserterType.STANDARD)
public static Object hook(IInserterContext<Object, Object> ctx, Object... args) {
return ctx.ret();
}@FallenInserter(type = InserterType.STANDARD_VOID)
public static void hook(IInserterContext<Object, Object> ctx, Object... args) {
}ctx 具有 ctx.receiver() 和 ctx.ret() 方法,它们分别提供您插入的方法的 this(可能为 null) 和返回对象(如果它有返回值且方法中的 replaceReturn 标志为 true,则该返回值将替换原始方法的返回值)。您可以尝试使用以下工具类 ObjectModifierFactory 来修改此对象的数字字段并返回。
args 是一个 Object[],包含您插入方法的所有参数。InserterType.STANDARD 在方法之后调用,因此它们只是一个视图,请勿修改它们。
如果您正确配置并实现了带有正确注解的 IFallenPatch 接口,那么您可以:
MethodInsnNode hookMethod = iFallenPatchContext.getFallenInserter(
InserterKey.of("your.class.name",
"methodName",
InserterType));来获取您的 hookMethod(如果它们具有正确的参数类型和返回类型,它们将被 fallen lib 构建)。
然后使用
PatchUtil.insertMethodHook()
以简化修补过程(虽然不如 mixin 那么简单)。
RuntimeUtility
一些运行时工具。
ObjectModifierFactory:
复制一个对象
修改数字字段
使用缓存和字段名称过滤器
例如:
public class FallenInserters {
// 这需要一个 Predicate<String>
private static final ObjectModifierFactory FACTORY = new ObjectModifierFactory(s -> {
String filedName = s.toLowerCase();
if (name.contains("xxx")) return true;
return false;});
@FallenInserter(type = InserterType.STANDARD)
public static Object hook(IInserterContext<Object, Object> ctx, Object... args) {
Object ret = ctx.ret()
return FACTORY.doSomething(ret);
}
}
这主要用于在不修改原始对象的情况下进行运行时调整。
Delegated Mixin Connector Registry:(版本 1.3.2 及以上)
一个类似服务的注册表,这使得您可以通过在模组中实现官方的 IMixinConnector 类,在 IDEA 中使用条件加载的 mixin 配置进行测试。
使用方法如下,指向一个实现了 IMixinConnector 的类,然后在 资源根目录 中放置一个 JSON 配置文件,格式如下:
{
"required": true,
"min_version": "1.3.2",
"mixin_connector": "net.kayn.apotheotic_hostility.FGAMixinConnector"
}
键 "mixin_connector" 应该指向您的类引用。
Apotheosis 附加内容(仅安装 Apotheosis 时)
额外宝石加成
您现在可以在 apotheosis 1.20.1 中通过数据包注册额外的宝石加成,就像 1.21.1 一样。
结构应为 resources/namespace/extra_gem_bonuses/somegembonus.json
注意事项
此项目已达到可用的状态,
但 API 在后续开发中仍可能发生变化。
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。