Tribulation

Developers

Tribulation exposes a stable, read-only API and a level-change event so other mods can read a player's difficulty level and react to it — without a hard dependency.

Soft Dependency Setup

Compile against Tribulation with modCompileOnly so it stays optional at runtime, then guard every call with a mod-loaded check.

Gradle:

dependencies {
    modCompileOnly "maven.modrinth:tribulation:<version>"
}

Guard calls so your mod loads cleanly whether or not Tribulation is present:

if (FabricLoader.getInstance().isModLoaded("tribulation")) {
    // safe to touch the Tribulation API here
}

TribulationAPI

Static entry points on com.rfizzle.tribulation.api.TribulationAPI. Server-side methods are authoritative; the client method reads the last value synced to that client.

Method Returns Side Description
getLevel(ServerPlayer)intServerThe player's authoritative difficulty level (0–maxLevel).
getTier(ServerPlayer)intServerThe player's current tier (0–5), derived from level and the tier thresholds.
getEffectiveLevel(Entity)intServerThe level that would drive scaling for this entity's position (nearest-player based). Returns 0 off-server.
getClientLevel()intClientThe local player's last-synced level. Returns −1 if unknown or the mod isn't present.
getScaledTier(Entity)OptionalIntServerThe tier the entity was scaled to at spawn. Empty if never scaled.
wasScaledByTribulation(Entity)booleanServerCheck if an entity was scaled by Tribulation.

Loot Control API

Control the drop chance of armor and weapons equipped by Tribulation. This allows external loot-modifying mods to override the default drop rules.

Armor Drop Chance

TribulationAPI.setArmorDropChanceProvider(
    (mob, tier, slot, stack, defaultChance) -> {
        // return 2.0f for guaranteed pristine drop
        return 0.085f;
    }
);

Weapon Drop Chance

TribulationAPI.setWeaponDropChanceProvider(
    (mob, tier, stack, defaultChance) -> {
        return 0.085f;
    }
);

Providers are "last writer wins". If a provider throws an exception or returns a non-finite value (NaN/Infinity), the API automatically falls back to the configured default chance.

Usage Examples

Read a player's level & tier (server)

import com.rfizzle.tribulation.api.TribulationAPI;

if (FabricLoader.getInstance().isModLoaded("tribulation")) {
    int level = TribulationAPI.getLevel(serverPlayer);
    int tier  = TribulationAPI.getTier(serverPlayer);
    // scale your own content off the same difficulty curve
}

Listen for level changes (server)

import com.rfizzle.tribulation.api.TribulationLevelCallback;

if (FabricLoader.getInstance().isModLoaded("tribulation")) {
    TribulationLevelCallback.EVENT.register((player, oldLevel, newLevel) -> {
        player.sendSystemMessage(
            Component.literal("Level: " + oldLevel + " → " + newLevel));
    });
}

The callback fires server-side whenever a player's level changes — from playtime, death relief, Shatter Shards, or an operator command.

Read the local level (client)

import com.rfizzle.tribulation.api.TribulationAPI;

// Safe on the client; returns -1 if unknown or the mod isn't loaded.
int clientLevel = TribulationAPI.getClientLevel();
if (clientLevel >= 0) {
    // e.g. drive your own HUD element
}

Notes

  • The API package is com.rfizzle.tribulation.api — everything outside it is internal and may change without notice.
  • Server-side methods require a ServerPlayer/Entity on a running server; call them from server logic, not client rendering.
  • getClientLevel() is reflection-backed so the server-side API surface carries no compile-time dependency on client-only classes — it's safe to reference from common code.
  • Tribulation uses official Mojang mappings (e.g. ServerPlayer, Component), matching a standard 1.21.1 Fabric + Loom setup.

Building an integration and something's missing? Open an issue — the API surface grows based on real integration needs.