Fallen Lib

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(); } }
然后,在您的资源根目录中应该有一个 xxx.fallen.json 文件。
格式如下:
{
  "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 在后续开发中仍可能发生变化。