CurseForge · Hytale mod
MixinTale - Developer Tools
MixinTale's compile-time half: the annotations, and the processor that checks your patches. Mod authors only
Quick answer
Which MixinTale - Developer Tools release should I use?
MixinTale - Developer Tools MixinTale-Developer-Tools-3.0.0.zip targets 0.6. Do not install it as a separate client mod. Enable it on the world host—the local server in singleplayer or the dedicated server in multiplayer. No required dependencies listed for this file.
Where it goes
Where should MixinTale - Developer Tools be installed in Hytale?
Do not install it as a separate client mod. Enable it on the world host—the local server in singleplayer or the dedicated server in multiplayer.
Put Hytale mods on the world host or dedicated server. Singleplayer runs a local server too; Hytale does not use separate client mods.
What else does MixinTale - Developer Tools MixinTale-Developer-Tools-3.0.0.zip need?
MixinTale-Developer-Tools-3.0.0.zip. Change the file and its required mods may change too.
This file does not list any required mods. Do not add a library just because a different file uses it.
This file does not list any required or optional project dependencies. Check the creator notes before changing an existing world.
Before you install it
Add MixinTale - Developer Tools without breaking your instance.
Built for MixinTale - Developer Tools MixinTale-Developer-Tools-3.0.0.zip. Pick another file and the loader, install side or required mods may change.
- 01
Stick to this file
Use MixinTale-Developer-Tools-3.0.0.zip. It targets 0.6; another release may target a different game build or dependency set.
- 02
Bring the mods it needs
This file does not list any required mods. Do not add a library just because a different file uses it.
- 03
Enable it on the world host
Do not install it as a separate client mod. Enable it on the world host—the local server in singleplayer or the dedicated server in multiplayer.
- 04
Pick the file you checked
Use the “Get this file” button beside MixinTale-Developer-Tools-3.0.0.zip. It opens that exact file at the source.
About this project
What does MixinTale - Developer Tools add?
MixinTale — Developer Tools
The compile-time half of MixinTale. Mod authors only — players and server owners do not need this, and should install MixinTale instead
What's in the zip
| File | What it is |
|---|---|
MixinTale-API-3.0.0.jar |
5 KB. The annotations: @Patch, @Prefix, @Postfix, @Replace, @RedirectCall, @Accessor, @Invoker, and the parameter markers @This, @Arg, @Result |
MixinTale-Processor-3.0.0.jar |
49 KB. The annotation processor. Validates your patches while you compile and writes a mixintale.index.json manifest into your jar. No ASM, no weaver — nothing that could collide with a bytecode library your own build already uses |
MIXINTALE.md |
The full manual, same as the one on GitHub |
manifest.json |
Metadata for the archive itself. Nothing here is installed into Mods or EarlyPlugins |
Neither jar ships inside your mod. The annotations have CLASS retention and the engine reads the generated index, never annotations at runtime
Setup
// build.gradle.kts
java {
// Hytale 0.6.3 ships class-file version 69. javac refuses to *read* class files newer than
// its --release setting, so anything compiling against the game needs 25 or above.
toolchain { languageVersion = JavaLanguageVersion.of(25) }
}
tasks.withType<JavaCompile> {
options.release = 25
options.compilerArgs.add("-parameters")
}
val hytale = "D:/Games/Hytale/Hytale Game/install/release/package/game/latest/Server/HytaleServer.jar"
dependencies {
compileOnly(files("MixinTale-API-3.0.0.jar"))
annotationProcessor(files("MixinTale-Processor-3.0.0.jar"))
compileOnly(files(hytale))
}
Groovy DSL, Maven and a plain javac -processorpath invocation all work the same way; the manual has each.
One thing that is not about MixinTale but will cost you an hour
Your manifest.json needs a ServerVersion range, and a bare version is not a range:
"ServerVersion": ">=0.6.0 <0.7.0"
"0.6.3" is rejected — Hytale answers "Bare version '0.6.3' is not a valid range. Use '=0.6.3' for an exact match, or '^0.6.3' / '~0.6.3' for a range." The rejection is an exception thrown while the manifest is decoded, so it does not merely warn: it takes the plugin load pass down with it, and none of your patches apply. *, ^0.6.0, ~0.6.1, >=0.6.0 <0.7.0 and 0.6 all parse
If you keep the version in one place, expand it into the manifest at build time:
tasks.named<ProcessResources>("processResources") {
val values = mapOf("version" to project.version.toString())
inputs.properties(values)
filesMatching("manifest.json") { expand(values) }
}
Write a patch
@Patch(ItemStack.class)
public final class DoubleDurabilityPatch {
private DoubleDurabilityPatch() {
}
@Postfix("getMaxDurability")
public static double doubled(@This ItemStack self, @Result double original) {
return original * 2.0D;
}
}
No descriptor anywhere. The processor reads your handler's parameter types, works out that the target is ()D, and fails the build if getMaxDurability does not exist or is ambiguous. Then confirm the manifest landed:
jar tf your-mod.jar | grep mixintale.index.json
Processor options
| Option | Effect |
|---|---|
-Amixintale.allowedPackages=a.b,c.d |
extra package prefixes a handler signature may reference |
-Amixintale.verbose=true |
confirm what was generated; silent otherwise |
Notes are off by default so a clean build stays clean. An index that cannot be written is always a build error, never a warning
Documentation
https://github.com/Traktool/MixinTale — every primitive with a worked example, signature inference, parameter binding, gating, priority, the runtime switches, troubleshooting, and what to do after a game update
Every Java example on that page is compiled against the real game classes before publication
Requirements
- JDK 25 or later, and Gradle 9.1 or later if you use Gradle (earlier Gradle cannot run on Java 25 — its embedded Kotlin compiler fails to parse the version)
- A Hytale 0.6.x install to compile against
- Your users need MixinTale in
EarlyPluginsDeclare it in your mod page's requirements: there is no dependency mechanism for early plugins, so nothing will install it for them
Migrating from 2.0.0
Every annotation changed shape. Nothing is deprecated-but-working: 2.x sources do not compile against 3.0.0, and that is deliberate — the old API could not survive dropping the Mixin dependency, and there is far less to write now
| 2.0.0 | 3.0.0 |
|---|---|
@Patch(targetClass = "com/hypixel/hytale/…/Foo") |
@Patch(Foo.class) — the compiler checks it. className = "…" still takes a name, in dots or slashes, for targets off your compile path |
@Prefix(targetMethod = "m", targetDesc = "(I)Z") |
@Prefix("m") — the descriptor is inferred from your handler. Pass descriptor = "(I)Z" only to pick between overloads |
@Postfix(targetMethod = …, targetDesc = …) |
@Postfix("m") |
@Replace(targetMethod = …, targetDesc = …) |
@Replace("m") |
@RedirectCall(targetMethod, targetDesc, owner, name, desc, ordinal, require) |
@RedirectCall(value = "m", target = Owner.class, name = "called"). ordinal and require are unchanged; descriptor, ownerName and callDescriptor are the optional overrides for the three inferred parts |
@Accessor("field") |
Same, and it now does setters, static fields and instance fields alike — told apart by the signature you declare |
| — | @Invoker("method") is new: calls a private method of the target |
@WrapCall + Operation<R> |
Removed. Use @RedirectCall |
@This, @Arg(n), @Result |
Unchanged in spelling. See the two notes below |
What @WrapCall becomes
A wrap injection needs an interface that both your mod and the woven game class can load, and by construction no MixinTale class is visible from the game's class loader. @RedirectCall reaches the same place from the other side: its body is relocated into the target class, so it can perform the original invocation itself, on its own terms
// 2.0.0
@WrapCall(targetMethod = "compareTo", targetDesc = "(…)I",
owner = "java/lang/Long", name = "compare", desc = "(JJ)I", ordinal = 1)
public static int wrap(Operation<Integer> original, @Arg(0) long l, @Arg(1) long r) throws Throwable {
return original.call(l, r);
}
// 3.0.0
@RedirectCall(value = "compareTo", target = Long.class, name = "compare", ordinal = 1)
public static int lenientMinor(@Arg(0) long left, @Arg(1) long right) {
if (left == SENTINEL) {
return 0;
}
return Long.compare(left, right); // the original call, whenever you decide to make it
}
You gain the ability to skip the original entirely, and lose the Object... boxing that Operation.call forced on every argument
Two behaviours to re-check
@Prefixcontrol flow. Returnvoidto observe; returnbooleanandfalseto skip the original body. To supply a return value when you cancel, take a@Resultone-element array and writeresult[0]- Priority direction. Higher priority runs closer to the original — for prefixes as well as postfixes. A prefix-ordering bug meant this did not hold in 2.x; if you shipped two patches on one method and tuned their priorities around the old behaviour, check them
Your users
They need MixinTale 3.0.0 in EarlyPlugins. A mod compiled against 3.0.0 will not be applied by a 2.0.0 bootstrap, and vice versa — the index format changed. Bump the MixinTale version in your page's Relations → Dependencies at the same time you upload
Project description from CurseForge.
Pick your setup
MixinTale - Developer Tools releases for each Hytale build.
Choose the version and loader you play, then open the matching release.
Check the dependencies, then try the file in a copied instance before changing a world you care about.
Recent files
MixinTale - Developer Tools releases and Hytale builds
MixinTale-Developer-Tools-3.0.0.zip
13 Sept 2026
MixinTale-Developer-Tools-2.0.0.zip
22 Feb 2026
MixinTale-Developer-Tools-1.0.0.zip
30 Jan 2026
Looking for an older file? The official CurseForge project page is in Resources.