CptSpaceToaster / CptsModdingLight

Do What The F*ck You Want To Public License
39 stars 15 forks source link

The mapping process looks like it can be automated #12

Open CptSpaceToaster opened 10 years ago

CptSpaceToaster commented 10 years ago

First, some background Minecraft can exist in three unique states of obfuscation

  1. Notch names are what you get when you decompile the Minecraft jar from Mojang. Exe: aqz.b, where aqz could be a class, and b could be a method or field.
  2. Deobfuscated names come from the MCP, and take a very large step in producing readable code. Classes have a readable hierarchical structure, but all methods and fields are still given a non-descriptvie name. Exe: net.minecraft.client.renderer.tessellator.func_12345()
  3. Searge names (SRG-names, fully-deobfuscated) You normally only experience these in a development environment that mapped the odd function and field names to a more descriptive name: func_12345() -> draw()

While writing a normal mod, a mod writer shouldn't have to worry much about the state of obfuscation they are in, as any code they write will be compiled and mapped to deobfuscated names, and loaded once FML prepares Minecraft.

Coremod writers are not as fortunate. When a coremod wishes to transform a class, it's very important that it can identify where classes and methods are, and what they are called. This means that a coremod that works in the dev environment, may not be able to work outside if the transformers are not looking for the same function in a different state of obfuscation. tessellator.draw() may exist in the developer environment, but you'd have to also look for tessellator.func_12345() if you want the same thing to occur after you build.

There are two important steps that help a coremod author transform Minecraft classes:

  1. Setting a coremod's sorting index to a value over 1000 will allow FML to deobfuscate classes before a coremod has a chance to transform them. This effectively guarantees that any transformer you write will use the deobfuscated namespace. This is strongly encouraged. I ran into some odd bits of behavior when trying to operate in the Notch namespace. It's just easier to handle it this way.
  2. The FML repo has the mappings from the deobfuscated namespace to SRG for methods and fields in its conf folder.

With all that said and out of the way, it looks like this mod is only a couple of steps away from automating the entire process. The NameMapper could be written to accept SRG-names of fields and methods. The names could be used to create entries for the current deobfuscated namespace using the mappings provided by FML, while also keeping the SRG-names in store. The check for classnames would have to extend into the mapper (which is partially implemented already) and check against both the deobfuscated, and the SRG-name for a match. This provides an automated process by which the ColoredLightCore won't have to keep track of it's own mappings, while also relying on the SRG-namespace for readability and clear code. (And, it would let the same code to run in 1.7.10 and 1.7.2 given a copy of the FML mappings)

This may encounter some trouble if an SRG-mapping has two entries. For example, hasBrightness has two mappings to deobfuscated values since two different classes have a field named hasBrightness in SRG. The next steps will have to keep this in mind. I'd rather not use the system backwards and enter in the deobfuscated names into the NameMapper, as I ultimately wanted to avoid a manual process in the first place. More on this to come.

spacechase0 commented 10 years ago

If I understand the nocth-srg.srg and simillar files correctly, I think you might have 2. and 3. backwards.

I don't know if this will help any, but this is the sort of thing that I did when I needed to add some handling for the packet that handles horse jumps:

String className = ...;
MethodNode method = ...;

ObfuscatedMethod obfMethod = ObfuscatedMethod.fromObf( className, method.name, method.desc );
ObfuscatedMethod processFunc = ObfuscatedMethod.fromSrg( "net/minecraft/network/Packet", "func_148833_a", "(Lnet/minecraft/network/INetHandler;)V" ); // processPacket

if ( obfMethod.obfName.equals( processFunc.obfName ) && obfMethod.deobfDesc.equals( processFunc.deobfDesc ) )
{
    // Inject stuff
}

All the mapping for a method/field/class are stored in a single object, and the object can be retrieved from any of its mappings (inside MCP is a special case, but it is handled only in the from___ functions, not everywhere else). I don't have to change anything at all, it just works in and out of MCP.

I generate all the objects from mcp-srg.srg and notch-srg.srg I got from the Gradle cache, which I include my base mod that does all the ASM stuff.

I don't know if that made any sense, but hopefully it at least gives you an idea or two. :)

CptSpaceToaster commented 10 years ago

I've flip-flopped them twice... I'm convinced that Deobfuscated and Searge go by both names... When I have time to work on this some more, I'll definitly have to look at what you did. This feature is long overdue.