Modscraper Modscraper Minecraft
Fallen Lib logo

Fallen Lib

Mod

by rtxyd

A library providing runtime extension utilities

Type

Mod

CurseForge Downloads

27,928

CurseForge ID

1404737

Last Updated

Apr 13, 2026

Description

Fallen Lib is a small developer utility library.
It is currently used during development of Fallen Gems & Affixes.

For Fallen Gems & Affixes 2.0.7 and below, please use verison 1.2.0-hotfix 

This mod provides some ASM realted APIs and also runtime utilities for mod development.
It does not add any gameplay content and is not intended for normal players.

Development environment

When running in an IDEA, please use the both JARs suffixed with `core` and 'runtime' (It's in the Additional Files section).

For normal gameplay or distribution, use the normal JAR.

Features

FallenPatch

A delegating API for patching mod classes.

It can hook exact classes or all subclasses,
which helps reduce repeated patches when extending mod behavior.

To use the API, you must implement the `IFallenPatch` interface, then the class must have the annotation `@FallenPatch` with correct parameters.

For example: 

@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); } } }

The `inserters` targets a class which has at least 1 method with `@FallenInserter` annotation.
For example the `FallenInserters.class`:

public class FallenInserters { @FallenInserter(type = InserterType.STANDARD_VOID) public static void hook(IInserterContext<Object, Object> ctx, Object... args) {
Object rec = ctx.receiver(); } } Then there should have an `xxx.fallen.json` file in your resource root.
Fomated as:  { "required": true, "min_version": "1.2.0", "package": "xxx.package.name", "fallen_patches": [ "FallenPatch", "PatchClassName" ] }

Currently, FallenPatch only supports patching mod classes.
Support for Minecraft classes may be added in the future.

 

 

FallenInserter

Along with FallenPatch, use `@FallenInserter` on a method with correct parameter types and return type,

There are now 2 types of InserterType:

`InserterType.STANDARD` 

`InserterType.STANDARD_VOID`

the default is standard, which should be like following formats: 

@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) { }


the `ctx` has `ctx.receiver()` and `ctx.ret()` methods, which gives you the `this(may be null)` and return Object of the method you inserted, if it has return value and `replaceReturn` flag is `true` in the method, the return will replace the return value of orginal method, you can try following util `ObjectModifierFactory` to modify the numeric fields of this Object and return.

the `args` is an `Object[]` which contains all parameters of the method you inserted, `InserterType.STANDARD` is invoked after the method, so they are just a view, do not change them.

If you correctly configured and implement the IFallenPatch interface with correct annotation and then you can 

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

To get your hookMethod (if they have correct parameter types and return type, they will be buit by fallen lib)

Then use

PatchUtil.insertMethodHook()

To make easier patch (not as easy as mixin tho).

 

 

RuntimeUtility

Some runtime utilities.

`ObjectModifierFactory`

 

Copies an object

Modifies numeric fields

Uses cache and field name filters

For example: 

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); } }

This is mainly used for runtime adjustments without modifying the original object.

 

`Delegated Mixin Connector Registry`: (above verison 1.3.2)

A service like registry, this makes you able to test in IDEA with conditionally loaded mixins configs by implementing the official IMixinConnector class in your mod.

Use like below, target a class that implements IMixinConnector, then config with a json in resources root with following format

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

the key "mixin_connector" should be your class reference.

 

Apotheosis Addon (Apotheosis installed only)

Extra Gem Bonus

You can now register extra gem bonuses in apotheosis 1.20.1 with a datapack just like 1.21.1

the structure should be `resources/namespace/extra_gem_bonuses/somegembonus.json

 

Notes

This project has reached a usable state,
but APIs may still change as development continues.

Similar Mods

Included in Modpacks

External Resources