if you’re getting into minecraft cheat development, you’ve probably heard about mappings but aren’t sure what they actually are or how to use them. this guide breaks down everything you need to know about minecraft mappings, specifically focusing on mojang’s official mappings.
the problem: obfuscation
mojang historically shipped minecraft with obfuscated code using proguard. instead of readable class and method names, everything is replaced with meaningless identifiers:
public class gfj {
private static gfj A;
private float c;
public void d() {
this.c -= 0.08f;
}
}
this makes reverse engineering harder, but it also makes development nearly impossible. how do you know what gfj is? what does field A represent? this is where mappings come in.
important note: as of version 1.21.11 and beyond, mojang now releases deobfuscated builds alongside obfuscated ones. read more about this change here. however, for versions before 1.21.11, you’ll still need to work with obfuscated code and mappings.
what are mappings?
mappings are translation files that tell you what the obfuscated names actually mean. they’re essentially a dictionary:
net.minecraft.client.Minecraft -> gfj
instance -> A
level -> r
player -> s
this tells you that the class gfj is really Minecraft, field A is instance, and so on.
critical understanding: mappings don’t modify minecraft’s runtime. the jvm is still running obfuscated code. mappings are just a reference sheet for developers to understand what’s what.
getting mappings (version 1.14.4 - 1.21.11)
mojang provides official mappings for minecraft versions 1.14.4 through 1.21.11. here’s how to get them:
step 1: access the version manifest
go to mojang’s version manifest at https://piston-meta.mojang.com/mc/game/version_manifest_v2.json and find your target version. for example, version 1.21.11:
{
"id": "1.21.11",
"type": "release",
"url": "https://piston-meta.mojang.com/v1/packages/30bb79802dcf36de95322ef6a055960c88131d2b/1.21.11.json"
}
step 2: get version-specific metadata
open the url from step 1 in your browser and search for client_mappings:
"client_mappings": {
"sha1": "031a68bebf55d824f66d6573d8c752f0e1bf232a",
"size": 11779287,
"url": "https://piston-data.mojang.com/v1/objects/031a68bebf55d824f66d6573d8c752f0e1bf232a/client.txt"
}
step 3: access the mappings
open the client.txt url in your browser. this is your mapping file in proguard format (proguard is the obfuscator minecraft uses).
community mappings for older versions
for versions before 1.14.4, you’ll need community-created mappings like mcp (minecraft coder pack), available at http://www.modcoderpack.com/.
using mappings: practical example
let’s say you want to get the minecraft instance via jni. first, search the mappings file for net.minecraft.client.Minecraft:
net.minecraft.client.Minecraft -> gfj:
net.minecraft.client.Minecraft instance -> A
net.minecraft.client.multiplayer.ClientLevel level -> r
net.minecraft.client.player.LocalPlayer player -> s
now you know:
Minecraftclass → obfuscated togfjinstancefield → obfuscated toAlevelfield → obfuscated torplayerfield → obfuscated tos
the jni code
here’s how you’d access the minecraft instance using these mappings:
// find the minecraft class using its OBFUSCATED name
jclass minecraftClass = env->FindClass("gfj");
// get the static 'instance' field using its OBFUSCATED name 'A'
jfieldID instanceField = env->GetStaticFieldID(
minecraftClass,
"A", // obfuscated name from mappings
"Lgfj;" // type signature
);
// retrieve the instance
jobject minecraftInstance = env->GetStaticObjectField(minecraftClass, instanceField);
why you use obfuscated names
when minecraft is running, the jvm only knows about gfj and A. it has no concept of Minecraft or instance. those readable names only exist in the mappings file.
think of it like this:
- what you want to access:
Minecraft.instance - what actually exists in memory:
gfj.A - what mappings do: tell you that
Minecraft=gfjandinstance=A
you can’t write env->FindClass("Minecraft") because no class named Minecraft exists in the running jvm. you must use the obfuscated name gfj.
understanding the java side
the minecraft class uses a singleton pattern. before obfuscation:
public class Minecraft {
private static Minecraft instance;
public static Minecraft getInstance() {
return instance;
}
}
after obfuscation (what’s actually running):
public class gfj {
private static gfj A;
public static gfj a() {
return A;
}
}
when you inject a dll and use jni, you’re interacting with the obfuscated version. mappings just help you understand what you’re looking at.
jni breakdown
here’s what each jni call does:
- FindClass(“gfj”) - searches loaded classes for
gfj - GetStaticFieldID(…) - gets a reference to field
Ain classgfj - GetStaticObjectField(…) - reads the value of that field
that’s it. mappings told you what to search for, but the actual interaction is with obfuscated names.
wrapping up
mappings are essential for minecraft development because they let you understand obfuscated code. remember:
- mappings are reference files, not runtime modifiers
- always use obfuscated names in your jni code
- mojang mappings work for 1.14.4+, use community mappings for older versions
- the jvm has no knowledge of deobfuscated names at runtime