Setting up MCP + Forge with mcp_deobfuscate

This document will assume you've followed the base mcp_deobfuscate instructions and set up a Maven install, and ordered it to create the mcp_deobfuscate jar. Everything else will be provided.

Starting from scratch

Getting MCP and Forge

[narc@console ~]% mkdir -pv mcp/1.4.5 && cd mcp/1.4.5
[narc@console ~/mcp/1.4.5]% wget
[narc@console ~/mcp/1.4.5]% wget
[narc@console ~/mcp/1.4.5]% unzip
[narc@console ~/mcp/1.4.5]% unzip

All very straightforward: just get the files and unzip them.

Hooking up Forge into MCP and making a reobfuscated client jar

[narc@console ~/mcp/1.4.5]% cd forge
[narc@console ~/mcp/1.4.5/forge]% python
# Lots and lots of output... probably a whole bunch of time, too.
[narc@console ~/mcp/1.4.5/forge]% cd ..
[narc@console ~/mcp/1.4.5]% python runtime/
== MCP 7.23 (data: 7.23, client: 1.4.5, server: 1.4.5) ==
# found ff, ff patches, srgs, name csvs, doc csvs, param csvs, renumber csv, astyle, astyle config
> Creating Retroguard config files
== Reobfuscating client ==
> Cleaning reobf
> Generating md5s
> Packing jar
> Reobfuscating jar
> Extracting modified classes
- Done in 35.01 seconds
!! Can not find server md5s !!

There we go. We now have an environment suitable for dropping mcp_deobfuscate into. Yes, these preliminaries are all necessary.

Installing mcp_deobfuscate and mcp_interface into our MCP+Forge install

[narc@console ~/mcp/1.4.5]% cp /path/to/mcp_deobfuscate-1.2.jar runtime/bin
[narc@console ~/mcp/1.4.5]% cp ~/.m2/repository/asm/asm-all/3.3.1/asm-all-3.3.1.jar runtime/bin
[narc@console ~/mcp/1.4.5]% cp ~/.m2/repository/com/beust/jcommander/1.29/jcommander-1.29.jar runtime/bin

These are mcp_deobfuscate proper and its dependencies. Note that you may need to hunt down asm and jcommander if you didn't just use maven to compile mcp_deobfuscate yourself.

We still need the mcp_interface, too:

[narc@console ~/mcp/1.4.5]% git clone git:// -b mcp_interface
Cloning into 'mcp_deobfuscate'...
remote: Counting objects: 226, done.
remote: Compressing objects: 100% (117/117), done.
remote: Total 226 (delta 91), reused 195 (delta 60)
Receiving objects: 100% (226/226), 59.33 KiB, done.
Resolving deltas: 100% (91/91), done.
[narc@console ~/mcp/1.4.5]% cd mcp_deobfuscate
[narc@console ~/mcp/1.4.5/mcp_deobfuscate]% mv .* * ..
mv: cannot move `runtime' to `../runtime': Directory not empty
[narc@console ~/mcp/1.4.5/mcp_deobfuscate]% mv runtime/* ../runtime
[narc@console ~/mcp/1.4.5/mcp_deobfuscate]% rmdir runtime
[narc@console ~/mcp/1.4.5/mcp_deobfuscate]% cd .. && rmdir mcp_deobfuscate
[narc@console ~/mcp/1.4.5]% git status                                                                          Executed: 2012-12-10 22:46:32
# On branch mcp_interface
nothing to commit (working directory clean)

That last line tells us that mcp_interface is in place and we can therefore proceed with whatever we wanted to do.

Let's also have it make its directories:

[narc@console ~/mcp/1.4.5]% python runtime/
[narc@console ~/mcp/1.4.5]% python runtime/

The output doesn't matter much, we're just having them make the lib-obf/ and mods/ directories.

Now the fun part: using deobfuscate_libs to deobfuscate IC2

[narc@console ~/mcp/1.4.5]% cd lib-obf
[narc@console ~/mcp/1.4.5/lib-obf]% wget
[narc@console ~/mcp/1.4.5/lib-obf]% cd ..
[narc@console ~/mcp/1.4.5]% python runtime/

After this, we should have a deobfuscated IC2 jar in lib/.

To be really tricky, let's decompile it, too

[narc@console ~/mcp/1.4.5]% mkdir -pv mods/IC2/temp
mkdir: created directory `mods/IC2/temp'
[narc@console ~/mcp/1.4.5]% cd mods/IC2/temp
[narc@console ~/mcp/1.4.5/mods/IC2/temp]% unzip ../../../lib/industrialcraft-2_1.109.113-lf.jar
[narc@console ~/mcp/1.4.5/mods/IC2/temp]% cd ..
[narc@console ~/mcp/1.4.5/mods/IC2]% java -jar ../../runtime/bin/fernflower.jar -din=0 -rbr=0 -dgs=1 -asc=1 -log=WARN temp src

Whoo, golly, that last one was a long line. But it should give us decompiled, deobfuscated source in the src/ directory:

[narc@console ~/mcp/1.4.5/mods/IC2]% ls src
armor  ic2  META-INF

But, we can't recompile this yet -- it's got the wrong directory structure! And we still have that temp thing lying around. Let's fix all of these now:

[narc@console ~/mcp/1.4.5/mods/IC2]% rm -rf temp
[narc@console ~/mcp/1.4.5/mods/IC2]% mkdir -pv {src,resources}/common conf
mkdir: created directory `src/common'
mkdir: created directory `resources'
mkdir: created directory `resources/common'
mkdir: created directory `conf'
[narc@console ~/mcp/1.4.5/mods/IC2]% mv src/{armor,,META-INF} resources/common
[narc@console ~/mcp/1.4.5/mods/IC2]% mkdir resources/common/ic2
[narc@console ~/mcp/1.4.5/mods/IC2]% mv src/ic2/{sounds,sprites} resources/common/ic2
[narc@console ~/mcp/1.4.5/mods/IC2]% mv src/ic2 src/common
[narc@console ~/mcp/1.4.5/mods/IC2]% touch conf/NOT_MY_CODE
[narc@console ~/mcp/1.4.5/mods/IC2]% echo '1.109.113-custom' > conf/VERSION

That should have made the directory structure into what mcp_interface needs to see. Let's check this now by running recompile_mods:

[narc@console ~/mcp/1.4.5/mods/IC2]% cd ../..
[narc@console ~/mcp/1.4.5]% python runtime/

Woo, lots of errors! But that's a good sign, it means mcp_interface can find all our source files and pass them to javac.

The missing bits

First of all, we're missing lwjgl, and that's going to just hurt in error count. Luckily it's also extremely easily fixed:

[narc@console ~/mcp/1.4.5]% python runtime/
[narc@console ~/mcp/1.4.5]% ln -sv ../jars/bin/lwjgl.jar lib
`lib/lwjgl.jar' -> `../jars/bin/lwjgl.jar'

We're far from done, though. We've still got IC2's integration with a few other things... for this article, we'll just drop most of them:

[narc@console ~/mcp/1.4.5]% rm -rf mods/IC2/src/common/ic2/{cg,nei}Integration

And that just leaves us with... Buildcraft. Now, the CraftGuide and NEI integration modules weren't critical, so I felt safe dropping them, but dropping Buildcraft would really affect the gameplay, so let's do something clever with it instead. Let's get the Buildcraft API and make an APIs project while we're at it!

Buildcraft API (and APIs in general)

[narc@console ~/mcp/1.4.5]% cd mods
[narc@console ~/mcp/1.4.5/mods]% mkdir -pv APIs/{conf,src/common}
mkdir: created directory `APIs'
mkdir: created directory `APIs/conf'
mkdir: created directory `APIs/src'
mkdir: created directory `APIs/src/common'
[narc@console ~/mcp/1.4.5/mods]% cd APIs/src/common
[narc@console ~/mcp/1.4.5/mods/APIs/src/common]% git clone git:// 
[narc@console ~/mcp/1.4.5/mods/APIs/src/common]% mv BuildCraft/common/buildcraft/api .
[narc@console ~/mcp/1.4.5/mods/APIs/src/common]% rm -rf BuildCraft
[narc@console ~/mcp/1.4.5/mods/APIs/src/common]% mkdir buildcraft
[narc@console ~/mcp/1.4.5/mods/APIs/src/common]% mv api buildcraft
[narc@console ~/mcp/1.4.5/mods/APIs/src/common]% cd ../..
[narc@console ~/mcp/1.4.5/mods/APIs]% echo '*' > conf/API
[narc@console ~/mcp/1.4.5/mods/APIs]% echo 'DO.NOT.USE' > conf/VERSION
[narc@console ~/mcp/1.4.5/mods/APIs]% touch conf/NOT_MY_CODE
[narc@console ~/mcp/1.4.5/mods/APIs]% cd ../..
[narc@console ~/mcp/1.4.5]% python runtime/

If all went well, you... still have some errors, but they're a bit headache to handle in this article, and it's already growing a bit long. You should be getting an idea of the workflow involved now, too.