Tutorial 3 — Adding Your First Relic

A relic is a special equippable item with procedurally rolled stat modifiers. A complete relic system requires four pieces: a RelicItem, a RelicType, at least one RelicStat, and at least one RelicAffix. This tutorial builds all four.

Prerequisites: Complete Tutorial 1.


1. Register a RelicItem

A RelicItem is a plain Item subclass. Register it with Forge's DeferredRegister:

// In MyModConstructor:
public static final DeferredRegister<Item> ITEMS =
    DeferredRegister.create(ForgeRegistries.ITEMS, "my_mod");

public static final RegistryObject<Item> AMULET_ITEM =
    ITEMS.register("amulet", RelicItem::new);

Wire the DeferredRegister in registerDeferredContainers:

@Override
public void registerDeferredContainers(IEventBus bus) {
    ITEMS.register(bus);
}

2. Define a RelicType via JSON

A RelicType entry tells the library which Item is used for this relic and how many can be equipped simultaneously.

Create the file:

src/main/resources/data/my_mod/library_of_exile_relic_type/amulet.json
{
  "id": "my_mod:amulet",
  "item_id": "my_mod:amulet",
  "weight": 1000,
  "max_equipped": 1
}
  • item_id must match the ResourceLocation of the RegistryObject you registered above.
  • max_equipped limits how many relics of this type a player can wear at once.

3. Define a RelicStat via JSON

A RelicStat is a named numeric quantity. Create:

src/main/resources/data/my_mod/library_of_exile_relic_stat/life_regen.json
{
  "id": "my_mod:life_regen",
  "serializer": "manual_stat",
  "is_percent": false,
  "min": 0,
  "max": 500,
  "base": 0
}

manual_stat is the generic stat type. If you need a stat that influences map content spawning weights, use "content_weight" instead (see the Relics reference).


4. Define a RelicAffix via JSON

A RelicAffix bundles one or more stat rolls onto a specific relic type. Create:

src/main/resources/data/my_mod/library_of_exile_relic_affix/amulet_life_regen.json
{
  "id": "my_mod:amulet_life_regen",
  "weight": 800,
  "relic_type": "my_mod:amulet",
  "mods": [
    {
      "stat": "my_mod:life_regen",
      "min": 10.0,
      "max": 50.0
    }
  ]
}
  • relic_type must match the id of your RelicType JSON.
  • mods is a list of RelicMod entries, each pairing a stat with a value range.

5. Read stat values at runtime

When the library rolls a relic, it produces a list of ExactRelicStat objects. You read the aggregated total using RelicStatsContainer:

List<ExactRelicStat> mods = // ... from the relic's capability data
RelicStatsContainer stats = RelicStatsContainer.calculate(mods);

// Look up by GUID string:
float regenValue = stats.get(Database.get(LibDatabase.RELIC_STAT, "my_mod:life_regen"));

// Or look up by ExileKey reference:
float regenValue = stats.get(MY_RELIC_STAT_KEY);

6. Test in-game

After running the client with /reload, your relic type, stat, and affix should be registered. You can give yourself a relic item with /give @s my_mod:amulet and inspect its rolled affixes through whatever display system your dependent mods provide.


What you learned

  • How to register a RelicItem with Forge's DeferredRegister.
  • How to link it to a RelicType JSON entry.
  • How to define RelicStat and RelicAffix entries via JSON datapacks.
  • How to read rolled stat values with RelicStatsContainer.

Next steps