Skip to content

Getting Started

goshi-hider edited this page Jul 24, 2026 · 1 revision

Getting Started

Requirements

  • Minecraft 1.21
  • Fabric Loader 0.19.3 or newer
  • Fabric API
  • Java 21

OmniMixin is built against Yarn mappings 1.21+build.9. If you're using a different Yarn build for 1.21, most of this should still line up, but a handful of mixins target methods whose names can shift between mapping builds — see Known Limitations for the specific ones to double check.

Adding OmniMixin to your mod

OmniMixin isn't on a public Maven repository yet, so for now the straightforward path is a local Maven install:

git clone <this repo>
cd omnimixin
./gradlew publishToMavenLocal

Then in your own mod's build.gradle:

repositories {
    mavenLocal()
}

dependencies {
    modImplementation "dev.goshi:omnimixin:1.0.0"
}

If you'd rather not deal with Maven at all, you can also just build the jar and drop it straight into your dev environment's mods folder:

./gradlew build
# output lands in build/libs/omnimixin-1.0.0.jar

Either way, make sure whoever runs your mod also has OmniMixin installed — it's a real runtime dependency, not something that gets bundled into your jar.

Registering your first listener

Every OmniMixin event lives as a public static final Event<T> field on a Play* class, grouped by subsystem (PlayDamage, PlayBlock, PlaySpawn, and so on). You register a listener on it exactly like you would with any Fabric API event:

package com.example.mymod;

import dev.goshi.omnimixin.api.event.combat.PlayDamage;
import net.fabricmc.api.ModInitializer;

public class MyMod implements ModInitializer {
    @Override
    public void onInitialize() {
        PlayDamage.PRE_CALCULATE.register(ctx -> {
            System.out.println(ctx.victim().getName().getString() + " is about to take "
                    + ctx.originalDamage() + " damage from " + ctx.source().getName());
        });
    }
}

That's genuinely the whole registration story for common/server-side events — register from your normal ModInitializer.onInitialize().

Client-only events

Everything under dev.goshi.omnimixin.api.event.render (HUD, screens, camera, per-entity rendering) only exists on the client. Register those from your ClientModInitializer, not your regular one, the same way you would with any client-only Fabric API event:

package com.example.mymod;

import dev.goshi.omnimixin.api.event.render.PlayHud;
import net.fabricmc.api.ClientModInitializer;

public class MyModClient implements ClientModInitializer {
    @Override
    public void onInitializeClient() {
        PlayHud.POST_HUD.register(ctx -> {
            ctx.context().drawText(
                    MinecraftClient.getInstance().textRenderer,
                    "Hello from OmniMixin!", 10, 10, 0xFFFFFF, true
            );
        });
    }
}

Registering a render event from your common initializer will crash on a dedicated server, since those client-only classes won't exist there — keep the split clean.

The general shape of every event

Every OmniMixin event hands your listener a single context object (usually a record) describing what's happening, and most of them include one or both of:

  • a Cancellable — call context.cancel().cancel() to veto whatever vanilla was about to do
  • a Mutable* wrapper (MutableFloat, MutableDouble, MutableInt, or MutableReference<T>) — call .set(...), .add(...), or .multiply(...) on it to change the value vanilla ends up using

This pattern is explained in full, with the reasoning behind it, on the Architecture page — it's worth reading once before you start writing listeners, since it's identical across every subsystem.

What to read next

Once you're comfortable with the basic registration pattern, head to whichever subsystem page covers what you're building: Movement, Combat, World and Blocks, Items and Inventory, [[Entity Lifecycle and AI]], Rendering, or Networking and Data Sync.

An honest note about testing

This mod's mixins have been written and cross-checked line-by-line against the actual Yarn 1.21+build.9 mappings, but the development environment this was built in has no access to Minecraft's Maven repositories, so it has never actually been compiled or run inside a live game. Everything here should work — the target method signatures were individually verified — but until someone runs ./gradlew build and boots up a real instance, treat this as "carefully reviewed, not yet field-tested." If something doesn't compile or doesn't behave as documented, please file an issue with the specific mixin and Minecraft/Yarn version involved.

Clone this wiki locally