Tutorial 1 — Setting Up a Dependent Mod

This tutorial walks you through creating a Forge 1.20.1 mod that depends on Library of Exile. By the end you will have a skeleton mod that can register content and receive events from the library.

Prerequisites: Basic Forge modding knowledge, Java 17, Gradle.


1. Declare the dependency

In your mod's build.gradle, add Library of Exile as a compile-time dependency. The exact artifact coordinates depend on your local workspace setup. For a multi-project workspace, use a project reference. For a standalone mod, add the jar to your libs/ folder and use a file dependency:

dependencies {
    implementation fg.deobf(project(':Library-of-Exile-Rework'))
    // or, from a local jar:
    // implementation fg.deobf(files('libs/library_of_exile-2.1.3.jar'))
}

In mods.toml, declare the dependency:

[[dependencies.my_mod]]
    modId = "library_of_exile"
    mandatory = true
    versionRange = "[2.1.0,)"
    ordering = "AFTER"
    side = "BOTH"

2. Create your mod entry point

@Mod("my_mod")
public class MyMod {

    public MyMod(IEventBus modBus) {
        OrderedModConstructor.register(new MyModConstructor("my_mod"), modBus);
    }
}

OrderedModConstructor.register handles all init ordering for you. It replaces the need for scattered @SubscribeEvent methods during setup.


3. Implement OrderedModConstructor

Create MyModConstructor in your root package:

public class MyModConstructor extends OrderedModConstructor {

    private final String modid;

    // Forge DeferredRegister for items and blocks
    public static final DeferredRegister<Item> ITEMS =
        DeferredRegister.create(ForgeRegistries.ITEMS, "my_mod");

    public MyModConstructor(String modid) {
        this.modid = modid;
    }

    @Override
    public void registerDeferredContainers(IEventBus bus) {
        // Register DeferredRegister instances with the event bus here.
        ITEMS.register(bus);
    }

    @Override
    public void registerDeferredEntries() {
        // Nothing yet — items and blocks will go here later.
    }

    @Override
    public List<ExileKeyHolder> getAllKeyHolders() {
        // Return all your ExileKeyHolder instances here.
        return List.of();
    }

    @Override
    public List<ExileRegistryEventClass> getRegisterEvents() {
        // Return all your ExileRegistryEventClass instances here.
        return List.of();
    }

    @Override
    public void registerDatabases() {
        // Call Database.addRegistry() for any new ExileRegistryTypes you define.
        // You do not need to call this for built-in types.
    }

    @Override
    public void registerDatabaseEntries() {
        // Called after all registries are created. Used for hardcoded entries
        // that are not covered by ExileKeyHolder or ExileRegistryEventClass.
    }
}

4. Verify the setup

Run the Minecraft client:

./gradlew runClient

If Library of Exile loads before your mod and the game reaches the main menu without errors, your dependency is wired correctly.


Next steps