跳到正文

Fallen Lib

作者:rtxyd

提供运行时扩展工具的前置库

收藏

介绍

介绍由机器翻译自 CurseForge 原页面,仅供参考。

Fallen Lib 是一个小型开发者工具前置库。
目前用于开发 Fallen Gems & Affixes。

此模组提供了一些 ASM 相关 API,以及用于模组开发的运行时工具。
它不会添加任何游戏内容,也不面向普通玩家。

开发环境

Gradle

repositories {
    maven { url "https://rtxyd.github.io/maven-repo" }
}
dependencies {
    implementation fg.deobf("io.github.rtxyd:fallen-lib:1.4.6:core")
    implementation fg.deobf("io.github.rtxyd:fallen-lib:1.4.6:runtime")
}

也可以在“附加文件”部分下载这些文件。

正常游玩或分发时,请使用普通 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;
    // Here you must provide a constructor like this.
    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 接口,就可以这样获取:

 MehtodInsnNode hookMethod = iFallenPatchContext.getFallenInserter(
                InserterKey.of("your.class.name", 
                               "methodName", 
                               InserterType));

这样即可获取 hookMethod(如果参数类型和返回类型正确,Fallen lib 会自动生成它们)

然后使用

PatchUtil.insertMethodHook()

让补丁编写更简单(不过还是没有 mixin 那么简单)。

 

 


RuntimeUtility

一些运行时工具。

`ObjectModifierFactory`: 

 

复制对象

修改数值字段

使用缓存和字段名称筛选器

例如: 

public class FallenInserters {
// this needs a 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); } }

此工具主要用于在运行时调整对象,而不修改原始对象。

 

`委托式 Mixin 连接器注册表`:(1.3.2 以上版本)

这是一个类似服务的注册表。通过在你的模组中实现官方的 IMixinConnector 类,你可以在 IDEA 中测试按条件加载的 mixin 配置。

使用方法如下:指定一个实现了 IMixinConnector 的类,然后在 resources 根目录中放置一个符合以下格式的 json 配置:

{
  "required": true,
  "min_version": "1.3.2",
  "mixin_connector": "net.kayn.apotheotic_hostility.FGAMixinConnector"
}

“mixin_connector” 键的值应为你的类引用。

 


Apotheosis 附属内容(仅安装 Apotheosis 时可用)

额外宝石加成

现在可以像 1.21.1 一样,在 Apotheosis 1.20.1 中通过数据包注册额外的宝石加成。

文件路径应为 `resources/namespace/extra_gem_bonuses/somegembonus.json` 

 


备注

该项目现已达到可用状态,
但随着开发继续,API 仍可能发生变化。

常见问题

Fallen Lib 支持哪些 Minecraft 版本?

Fallen Lib 支持 Minecraft Java 版 1.20.1,可用的加载器:Forge。下载时注意选择和你游戏版本一致的文件。

Fallen Lib 怎么安装?

先用 PCL2 或 HMCL 启动器安装对应版本的 Forge,再把下载的 .jar 文件放进游戏目录的 mods 文件夹,重新启动游戏即可。开启了版本隔离的,mods 文件夹在 versions/版本名 下面。

评论

登录后评论和评分