Skip to content

Depending On Armor Hider

zannagh edited this page Aug 25, 2026 · 2 revisions

Depending On Armor Hider

This page is aimed at mod developers who want to compile against Armor Hider and have it present at runtime. For what the API actually offers once you have it on the classpath, see Api Overview.

What you get is the whole mod. There is no separate -api artifact and no API/impl split across jars: the production jar that ships to Modrinth contains the client render API (de.zannagh.armorhider.client.api.*), the common API (de.zannagh.armorhider.api.*), and everything else the mod is made of. You depend on the mod jar, exactly as a player would install it.

Which artifact you need

Artifacts follow one scheme on both routes:

Part Value
Group de.zannagh.armorhider
Artifact armor-hider-fabric, armor-hider-neoforge or armor-hider-paper
Version <semVer>+<display version>, e.g. 0.13.0+mc-1.21.5-8

The display-version suffix is the Minecraft group the jar was built for. The artifact must match the Minecraft version you are building against.

A build for +mc-1.21.5-8 and a build for +26.2 are not just different releases, they are compiled against different Minecraft namespaces:

  • Fabric builds for Minecraft up to and including 1.21.11 are remapped to the intermediary namespace, so their signatures name net.minecraft.class_1304 and net.minecraft.class_1799.
  • Fabric builds for 26.x are in the official (Mojang) namespace, because Minecraft stopped being obfuscated there and those variants are built deobfuscated.
  • NeoForge builds are in the official namespace on every version.

Picking the wrong one resolves cleanly and then fails later, at compile or link time, with confusing "cannot find symbol" or "incompatible types" errors. Gradle will not warn you. Match the suffix to your own target version.

Route A: Modrinth maven

This is the route for released versions and the one you want in a normal build.gradle.kts. Modrinth serves every published version out of its own maven, so no extra hosting is involved.

The coordinate is maven.modrinth:zannaghs-armor-hider:<version>, where <version> is a Modrinth version number (or version id). Version numbers are prefixed by loader, so they are unambiguous: fab-mc-… for Fabric, neo-mc-… for NeoForge, ppr-… for the Paper plugin. The semver tail is the API version: the render-rule API (ArmorHiderRenderApi, AhRenderRule) exists only from 0.13.0 onward, so pin a …-0.13.0 (or newer) version if you use it, or its classes will not resolve. The examples below use 0.13.0; check the Modrinth versions page for the newest matching your Minecraft version.

Fabric

repositories {
    maven("https://api.modrinth.com/maven") {
        content { includeGroup("maven.modrinth") }
    }
}

dependencies {
    modImplementation("maven.modrinth:zannaghs-armor-hider:fab-mc-1.21.5-8-0.13.0")
}

modImplementation is not a style choice here, it is required. For everything up to 1.21.11 the jar is in the intermediary namespace, and only Loom's remapping turns it into whatever mappings your project uses. Plain implementation will put intermediary class names on your compile classpath and your code will not compile against them. On 26.x the jar happens to already be in the official namespace, but modImplementation is still the correct declaration and works there too, so use it uniformly.

If Armor Hider is a soft dependency, use modCompileOnly instead and supply the jar yourself at runtime (drop it into run/mods, or add a modLocalRuntime entry).

Two things not to do:

  • Do not include(...) it. Jar-in-jar is for libraries you bundle; Armor Hider is a standalone mod the user installs, and nesting it will produce a duplicate-mod conflict.
  • Do not expect sources. Each Modrinth version publishes exactly one file, the mod jar. There is no -sources artifact on this route, so your IDE will show decompiled output. If you need real sources, use Route B.

NeoForge

repositories {
    maven("https://api.modrinth.com/maven") {
        content { includeGroup("maven.modrinth") }
    }
}

dependencies {
    implementation("maven.modrinth:zannaghs-armor-hider:neo-mc-1.21.5-8-0.13.0")

    // Dev-runtime only — see the note below. Only uncomment on ModDevGradle 2.x:
    // additionalRuntimeClasspath("maven.modrinth:zannaghs-armor-hider:neo-mc-1.21.5-8-0.13.0")
}

The compile side is straightforward: the NeoForge jar is already in the official namespace, so a plain implementation is all you need and no remapping happens. That single line is enough to resolve the API classes and compile against them.

Dev runtime is separate, and finicky. implementation puts Armor Hider on your compile classpath but does not load it when you hit runClient. additionalRuntimeClasspath is the documented ModDevGradle 2.x way to add it — but it is not a configuration on older ModDevGradle, where referencing it fails the build outright with an "additionalRuntimeClasspath not found" error. It has also not been verified here against an actually launched NeoForge dev client. So it is left commented out above: uncomment it only if you are on ModDevGradle 2.x. The reliable fallback that works on any setup is to copy the mod jar into your run directory's mods folder.

Route B: mavenLocal

Use this when you need to develop against changes that are not released yet, for example an API addition you are testing alongside your own mod.

On the Armor Hider side, publish the variant you need:

./gradlew :fabric:fabric-1.21.8:publishToMavenLocal
./gradlew :neoforge:neoforge-1.21.8:publishToMavenLocal

Scope the task to a single variant like that rather than running a bare root-level publishToMavenLocal. Armor Hider is a Stonecutter project with a variant per loader and Minecraft version, and the root task fans out over all of them, which is far more work than you want for one artifact.

Two things about the version it produces:

  • It defaults to 0.0.1-preview.0+<display version> unless you pass -PsemVer=…. The real release numbers come from CI, not from a local build.
  • Because of that, don't hardcode the coordinate from this page. Look at what actually landed:
ls ~/.m2/repository/de/zannagh/armorhider/armor-hider-fabric/

A Fabric 1.21.8 publish, for instance, produces de.zannagh.armorhider:armor-hider-fabric:0.0.1-preview.0+mc-1.21.5-8, and unlike Route A it does include a sources jar. On Fabric the published artifact is the remapped jar, the same one that ships to Modrinth, so all the namespace rules above still apply.

On the consumer side:

repositories {
    mavenLocal {
        content { includeGroup("de.zannagh.armorhider") }
    }
}

dependencies {
    // Fabric
    modImplementation("de.zannagh.armorhider:armor-hider-fabric:0.0.1-preview.0+mc-1.21.5-8")

    // NeoForge
    // implementation("de.zannagh.armorhider:armor-hider-neoforge:0.0.1-preview.0+mc-1.21.5-8")
}

The content { includeGroup(...) } filter is worth keeping. An unscoped mavenLocal() is consulted for every group in your build, which makes resolution non-reproducible: a stale local copy of some unrelated library silently wins over the one from a real repository. Restricting it to de.zannagh.armorhider means it only ever answers for Armor Hider.

Local publishing requires a checkout that includes the maven-publish support in buildSrc; older tags do not have it.

Supported API surface

Two packages are the supported integration surface:

  • de.zannagh.armorhider.api.*, common (client and server)
  • de.zannagh.armorhider.client.api.*, client-only

Everything under de.zannagh.armorhider.client.api.impl is shipped in the jar, because it has to be for the mod to run, but it is internal. It carries no compatibility promise and can change in any release without notice. The same goes for anything marked @ApiStatus.Internal, and for the rest of the mod's packages (render, net, mixin, and so on). Reach the implementations through the public static facades described in Api Overview.

The API was introduced in 0.12.0 and types carry @since Javadoc, so if you are supporting a range of Armor Hider versions you can tell when a given method appeared. The predicate-driven render-rule API (ArmorHiderRenderApi and friends, see Using The Render Api) is newer: it landed in 0.13.0 and is still marked @ApiStatus.Experimental.

Soft versus hard dependency

The mod ids differ per loader, which is easy to get wrong: it is armor-hider on Fabric and armor_hider on NeoForge.

Pick the version floor to match the API you actually use: 0.12.0 for the combat, render-interception, color-transformer, render-type and player-config APIs, 0.13.0 if you touch ArmorHiderRenderApi. The examples below use 0.13.0; drop them to 0.12.0 if you want to keep working against older installs and stay off the render-rule API.

On Fabric, in your fabric.mod.json:

"depends": {
  "armor-hider": ">=0.13.0"
}

for a hard dependency, or "recommends" / "suggests" in place of "depends" for a soft one.

On NeoForge, in your neoforge.mods.toml:

[[dependencies.yourmodid]]
modId = "armor_hider"
type = "required"     # or "optional" for a soft dependency
versionRange = "[0.13.0,)"
ordering = "AFTER"
side = "BOTH"

Class-Loading

Declaring the dependency optional in metadata is only half the job. If a class that gets loaded unconditionally - your ModInitializer, your @Mod class, a mixin, an event handler registered at startup - so much as mentions an Armor Hider type in a field, parameter, return type or import, the JVM will try to resolve it and throw NoClassDefFoundError when the mod is absent.

Keep the integration in its own class and only touch it behind a presence check:

if (FabricLoader.getInstance().isModLoaded("armor-hider")) {
    ArmorHiderIntegration.init();   // the only place that imports AH types
}

The NeoForge equivalent is ModList.get().isLoaded("armor_hider").

For most integrations you can sidestep this entirely. ArmorHiderInitializer is discovered by Armor Hider itself through ServiceLoader, so your implementation is only ever loaded when Armor Hider is present and doing the loading. Putting your registration there gives you a safe soft dependency for free, with no presence check to write. See Api Overview for the service-file setup.

Troubleshooting

cannot find symbol: class EquipmentSlot, or method signatures that reference types you have never heard of. You have the wrong Minecraft namespace. Check the +mc-… suffix on the artifact against the Minecraft version you are building for. Remember that Fabric artifacts up to 1.21.11 are intermediary while 26.x is official, so a jar built for the wrong side of that line will not link even if the Minecraft versions look close.

incompatible types: net.minecraft.world.entity.EquipmentSlot cannot be converted to net.minecraft.class_1304 (or the reverse). On Fabric, you declared the dependency with plain implementation instead of modImplementation, so Loom never remapped it and the intermediary names leaked onto your compile classpath. Change the configuration; you do not need to change the coordinate.

It compiles, but Armor Hider is not loaded in the dev client. You used a compile-only configuration (modCompileOnly, or implementation on NeoForge without a runtime entry). Add the runtime side, or drop the jar into your run directory's mods folder.

See also

Clone this wiki locally