master
mckuhei 2 years ago
commit 77e5f11979

6
.gitignore vendored

@ -0,0 +1,6 @@
/bin/
/eclipse/
/jars/
/reobf/
/temp/
/logs/

@ -0,0 +1,89 @@
== v7.0a ==
+ Still for client 1.3.1 & server 1.3.1
+ Added fernflower decompiler
== v7.0 ==
+ Updated to client 1.3.1 & server 1.3.1
+ Extended patches to remove herobrine code from decompiled classes
== v6.2 ==
+ Updated to client 1.2.5 & server 1.2.5
Update patches to work around worldgen crash in vanilla minecraft client and server,
and a client crash when clicking on chat history
== v6.1 ==
+ Updated to client 1.2.4 & server 1.2.4
Disabled rounding of float and double constants due to issues with getting stuck on respawn.
Updated client patches to work around OpenGL issues with main window on OSX and Linux.
You will need to cleanup and decompile again for these changes to take effect.
== v6.0 ==
+ Updated to client 1.2.3 & server 1.2.3
+ Added javadoc comments to the decompiled sourcecode
== v5.6 ==
+ Updated to client 1.1 & server 1.1
+ Run Artistic Style source beautifier on decompiled source code
== v5.0 ==
+ Updated to client 1.0.0 & server 1.0.1
== v4.5 ==
+ Updated to client & server v1.9 pre 5
+ Improved Retroguard and Exceptor tools
YOU NEED TO DOWNLOAD MCP FROM THE WIKI IF YOU ARE UPDATING FROM MCP 4.3, UPDATEMCP.BAT WILL NOT WORK FOR 4.3 TO 4.4 UPDATES!
+ Fixes to mapping of methods in EntityLiving
+ Bugfix for crashes when playing sounds due to issue in Block.java
== v4.4 ==
+ Updated to client & server v1.8.1
+ Improved Retroguard and Exceptor tools
== v4.3 ==
+ Updated to client & server v1.7.3
== v4.2 ==
+ Updated to client & server v1.7.2
* If you get compile errors for ik.java or ik.class, just delete conf/patches/ik.java
== v4.1 ==
+ Added an Eclipse workspace
+ Included a reobfuscation bugfix
== v4.0 ==
+ Added new tool Exceptor
+ Added alternative support for fernflower decompiler
== v3.4 ==
+ Updated to client & server v1.6.6
== v3.3 ==
+ Updated to client & server v1.6.5
== v3.2 ==
+ Updated to client & server v1.6.4
+ Added support for external jar files in recompile and reobfuscation
+ Finally updated the readme files
== v3.1.1 ==
+ Small bugfix for using mcp offline
== v3.1 ==
+ Updated to client v1.5_01 / server v1.5_02
+ some more bugfixes in the python scripts
== v3.0 ==
+ Complete rewrite of the scripts in python
+ RetroGuard used both for deof and reobf
+ Automatic detection of modified classes during reobfuscation
+ Protection on cleanup.bat/sh
+ Advanced logging system (logs/mcp.log, logs/mcperr.log)
+ Removed repackager.exe and mono dependancy on Linux
+ Cleaner directory structure
+ Out of the box decompilation compatibility with modded jars
+ Rolling update model on top of the usual full package distrib
+ Custom files in bin directory are preserved during recompilation
+ Custom files are automaticly copied to reobf directory during reobf

@ -0,0 +1,21 @@
MCP - Minecraft Coder Pack
MCP is (c) Copyright by the MCP Team
License and terms of use.
No warranties. If MCP does not work for you, or causes any damage, it's your problem. Use it at own risk.
You are allowed to:
- Use MCP to decompile the Minecraft client and server jar files.
- Use the decompiled source code to create mods for Minecraft.
- Recompile modified versions of Minecraft.
- Reobfuscate the classes of your mod for Minecraft.
You are NOT allowed to:
- Use MCP to do anything that violated Mojangs terms of use for Minecraft.
- Release Minecraft versions or modifications that allow you to play without having bought Minecraft from Mojang.
- Release modified or unmodified versions of MCP anywhere.
- Use any of MCPs scripts, tools or data files without explicit written permission.
- Make money with anything based on MCP (excluding Minecraft mods created by using MCP).
- Use MCP to create clients that are used for griefing or exploiting server bugs.
- Release the decompiled source code of Minecraft in any way.

@ -0,0 +1,3 @@
@echo off
runtime\bin\python\python_mcp runtime\cleanup.py %*
pause

@ -0,0 +1,2 @@
#!/bin/bash
python runtime/cleanup.py "$@"

@ -0,0 +1,19 @@
# Artistic Style format configuration
# see http://astyle.sourceforge.net/astyle.html
style=allman
add-brackets
break-closing-brackets
indent-switches
max-instatement-indent=2
pad-oper
pad-header
unpad-paren
break-blocks
delete-empty-lines

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,155 @@
[DEFAULT]
DirTemp = temp
DirSrc = src
DirLogs = logs
DirBin = bin
DirJars = jars
DirReobf = reobf
DirConf = conf
DirRuntime = runtime
DirLib = lib
DirTempSrc = temp/src
DirTempCls = temp/cls
DirTempBin = temp/bin
DirModSrc = modsrc
DirEclipse = eclipse
[CSV]
Classes = %(DirConf)s/classes.csv
Methods = %(DirConf)s/methods.csv
Fields = %(DirConf)s/fields.csv
Params = %(DirConf)s/params.csv
NewIds = %(DirConf)s/newids.csv
[SRGS]
ConfClient = %(DirConf)s/client.srg
ConfServer = %(DirConf)s/server.srg
Client = %(DirTemp)s/client_rg.srg
Server = %(DirTemp)s/server_rg.srg
DeobfClient = %(DirTemp)s/client_deobf.srg
DeobfServer = %(DirTemp)s/server_deobf.srg
ReobfClient = %(DirTemp)s/client_ro.srg
ReobfServer = %(DirTemp)s/server_ro.srg
[JAR]
DirNatives = %(DirJars)s/bin/natives
Client = %(DirJars)s/bin/minecraft.jar
Server = %(DirJars)s/minecraft_server.jar
LWJGL = %(DirJars)s/bin/jinput.jar,%(DirJars)s/bin/lwjgl.jar,%(DirJars)s/bin/lwjgl_util.jar
MD5Client = 969699f13e5bbe7f12e40ac4f32b7d9a
MD5Server = c047f82522e53f2ec3c6b64304dfad0f
[RETROGUARD]
Location = %(DirRuntime)s/bin/retroguard.jar
RetroConf = %(DirTemp)s/retroguard.cfg
RetroReobConf = %(DirTemp)s/retroguard_ro.cfg
ClientConf = %(DirTemp)s/client_rg.cfg
ServerConf = %(DirTemp)s/server_rg.cfg
ClientReobConf = %(DirTemp)s/client_ro.cfg
ServerReobConf = %(DirTemp)s/server_ro.cfg
ClientOut = %(DirTemp)s/minecraft_rg.jar
ServerOut = %(DirTemp)s/minecraft_server_rg.jar
ClientLog = %(DirLogs)s/client_rg.log
ServerLog = %(DirLogs)s/server_rg.log
ClientDeobLog = %(DirLogs)s/client_deob.log
ServerDeobLog = %(DirLogs)s/server_deob.log
NullPkg = net/minecraft/src
[EXCEPTOR]
XClientCfg = %(DirConf)s/client.exc
XServerCfg = %(DirConf)s/server.exc
XClientOut = %(DirTemp)s/minecraft_exc.jar
XServerOut = %(DirTemp)s/minecraft_server_exc.jar
XClientLog = %(DirLogs)s/client_exc.log
XServerLog = %(DirLogs)s/server_exc.log
[DECOMPILE]
ClsClientTemp = %(DirTempCls)s/minecraft
ClsServerTemp = %(DirTempCls)s/minecraft_server
SrcClientTemp = %(DirTempSrc)s/minecraft
SrcServerTemp = %(DirTempSrc)s/minecraft_server
FFSource = net
[OUTPUT]
BinClientTemp = %(DirTempBin)s/minecraft
BinServerTemp = %(DirTempBin)s/minecraft_server
SrcClient = %(DirSrc)s/minecraft
SrcServer = %(DirSrc)s/minecraft_server
TestClient = net/minecraft/client/Minecraft
TestServer = net/minecraft/server/MinecraftServer
[PATCHES]
PatchClient = %(DirConf)s/patches/minecraft.patch
PatchServer = %(DirConf)s/patches/minecraft_server.patch
PatchTemp = %(DirTemp)s/temp.patch
FFPatchClient = %(DirConf)s/patches/minecraft_ff.patch
FFPatchServer = %(DirConf)s/patches/minecraft_server_ff.patch
PatchClient_osx = %(DirConf)s/patches/minecraft_osx.patch
PatchServer_osx = %(DirConf)s/patches/minecraft_server_osx.patch
[RECOMPILE]
BinClient = %(DirBin)s/minecraft
BinServer = %(DirBin)s/minecraft_server
LogClient = %(DirLogs)s/client_compile.log
LogServer = %(DirLogs)s/server_compile.log
ClassPathClient = %(DirLib)s/,%(DirLib)s/*,%(DirJars)s/bin/minecraft.jar,%(DirJars)s/bin/jinput.jar,%(DirJars)s/bin/lwjgl.jar,%(DirJars)s/bin/lwjgl_util.jar
ClassPathServer = %(DirLib)s/,%(DirLib)s/*,%(DirJars)s/minecraft_server.jar
ClientFixes = %(DirConf)s/patches
FixStart = Start
IgnorePkg = paulscode,com/jcraft,isom,ibxm,de/matthiasmann/twl,org/xmlpull,javax/xml
[REOBF]
MD5Client = %(DirTemp)s/client.md5
MD5Server = %(DirTemp)s/server.md5
MD5PreReobfClient = %(DirTemp)s/client_reobf.md5
MD5PreReobfServer = %(DirTemp)s/server_reobf.md5
RecompJarClient = %(DirTemp)s/client_recomp.jar
RecompJarServer = %(DirTemp)s/server_recomp.jar
ObfJarClient = %(DirTemp)s/client_reobf.jar
ObfJarServer = %(DirTemp)s/server_reobf.jar
ReobfDirClient = %(DirReobf)s/minecraft
ReobfDirServer = %(DirReobf)s/minecraft_server
ClientRoLog = %(DirLogs)s/client_ro.log
ServerRoLog = %(DirLogs)s/server_ro.log
ReobfClientLog = %(DirLogs)s/client_reob.log
ReobfServerLog = %(DirLogs)s/server_reob.log
[GETMODSOURCE]
OutSRCClient = %(DirModSrc)s/minecraft
OutSRCServer = %(DirModSrc)s/minecraft_server
[MCP]
LogFile = %(DirLogs)s/mcp.log
LogFileErr = %(DirLogs)s/mcperr.log
UpdateUrl = http://mcp.ocean-labs.de/files/mcprolling_{version}/
IgnoreUpdate = %(DirBin)s,%(DirLib)s,%(DirLogs)s,%(DirModSrc)s,%(DirReobf)s,%(DirSrc)s,%(DirTemp)s,%(DirEclipse)s/Client/bin,%(DirEclipse)s/Server/bin,%(DirJars)s/world,%(DirJars)s/saves,%(DirJars)s/resources
RGIndex = 80000
ParamIndex = 4000
[ASTYLE]
AstyleConfig = %(DirConf)s/astyle.cfg
[COMMANDS]
Wine = wine
Patcher_win = %(DirRuntime)s/bin/applydiff.exe
Patcher_linux = patch
Patcher_osx = patch
Jad_win = %(DirRuntime)s/bin/jad.exe
Jad_osx = %(DirRuntime)s/bin/jad-osx
AStyle_win = %(DirRuntime)s/bin/astyle.exe
AStyle_linux = astyle
AStyle_osx = %(DirRuntime)s/bin/astyle-osx
JadRetro = %(DirRuntime)s/bin/jadretro.jar
Fernflower = %(DirRuntime)s/bin/fernflower.jar
Exceptor = %(DirRuntime)s/bin/mcinjector.jar
CmdPatch = %s -p1 -u -i {patchfile} -d {srcdir}
CmdJad = %s -b -d {outdir} -dead -o -r -s .java -stat -ff {classes}
CmdAStyle = %s --suffix=none --quiet --options={conffile} {classes}
CmdRG = %s -cp "{classpath}" RetroGuard -searge {conffile}
CmdRGReobf = %s -cp "{classpath}" RetroGuard -notch {conffile}
CmdJadretro = %s -jar %s {targetdir}
CmdFernflower = %s -jar %s -din=0 -rbr=0 -dgs=1 -asc=1 -log=WARN {indir} {outdir}
CmdExceptor = %s -jar %s {input} {output} {conf} {log}
CmdRecomp = %s -Xlint:-options -deprecation -g -source 1.6 -target 1.6 -classpath "{classpath}" -sourcepath {sourcepath} -d {outpath} {pkgs}
CmdStartSrv = %s -Xincgc -Xms1024M -Xmx1024M -cp "{classpath}" net.minecraft.server.MinecraftServer
CmdStartClt = %s -Xincgc -Xms1024M -Xmx1024M -cp "{classpath}" -Djava.library.path={natives} Start

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,27 @@
import java.io.File;
import java.lang.reflect.Field;
import net.minecraft.client.Minecraft;
public class Start
{
public static void main(String[] args)
{
try
{
// set new minecraft data folder to prevent it from using the .minecraft folder
// this makes it a portable version
Field f = Minecraft.class.getDeclaredField("field_71463_am");
Field.setAccessible(new Field[] { f }, true);
f.set(null, new File("."));
}
catch (Exception e)
{
e.printStackTrace();
return;
}
// start minecraft game application
Minecraft.main(args);
}
}

@ -0,0 +1,184 @@
diff -r -U 3 minecraft\net\minecraft\client\Minecraft.java minecraft_patched\net\minecraft\client\Minecraft.java
--- minecraft\net\minecraft\client\Minecraft.java Tue Aug 14 20:15:26 2012
+++ minecraft_patched\net\minecraft\client\Minecraft.java Tue Aug 14 20:18:48 2012
@@ -539,9 +539,8 @@
return;
}
- while(true) {
try {
- if(this.field_71425_J) {
+ while(this.field_71425_J) {
if(this.field_71434_R && this.field_71433_S != null) {
this.func_71377_b(this.field_71433_S);
return;
@@ -559,7 +558,6 @@
this.func_71373_a(new GuiMemoryErrorScreen());
System.gc();
}
- continue;
}
} catch (MinecraftError var12) {
;
@@ -577,8 +575,6 @@
this.func_71405_e();
}
- return;
- }
}
private void func_71411_J() {
diff -r -U 3 minecraft\net\minecraft\src\CodecMus.java minecraft_patched\net\minecraft\src\CodecMus.java
--- minecraft\net\minecraft\src\CodecMus.java Tue Aug 14 20:15:26 2012
+++ minecraft_patched\net\minecraft\src\CodecMus.java Tue Aug 14 20:18:48 2012
@@ -1,5 +1,6 @@
package net.minecraft.src;
+import java.io.IOException;
import java.io.InputStream;
import net.minecraft.src.MusInputStream;
import paulscode.sound.codecs.CodecJOrbis;
@@ -7,6 +8,10 @@
public class CodecMus extends CodecJOrbis {
protected InputStream openInputStream() {
+ try {
return new MusInputStream(this, this.url, this.urlConnection.getInputStream());
+ } catch(IOException ex) {
+ return null;
+ }
}
}
diff -r -U 3 minecraft\net\minecraft\src\ComponentStrongholdRightTurn.java minecraft_patched\net\minecraft\src\ComponentStrongholdRightTurn.java
--- minecraft\net\minecraft\src\ComponentStrongholdRightTurn.java Tue Aug 14 20:15:26 2012
+++ minecraft_patched\net\minecraft\src\ComponentStrongholdRightTurn.java Tue Aug 14 20:18:48 2012
@@ -11,6 +11,10 @@
public class ComponentStrongholdRightTurn extends ComponentStrongholdLeftTurn {
+ public ComponentStrongholdRightTurn(int p_i3843_1_, Random p_i3843_2_, StructureBoundingBox p_i3843_3_, int p_i3843_4_) {
+ super(p_i3843_1_, p_i3843_2_, p_i3843_3_, p_i3843_4_);
+ }
+
public void func_74861_a(StructureComponent p_74861_1_, List p_74861_2_, Random p_74861_3_) {
if(this.field_74885_f != 2 && this.field_74885_f != 3) {
this.func_74989_b((ComponentStrongholdStairs2)p_74861_1_, p_74861_2_, p_74861_3_, 1, 1);
diff -r -U 3 minecraft\net\minecraft\src\DedicatedServer.java minecraft_patched\net\minecraft\src\DedicatedServer.java
--- minecraft\net\minecraft\src\DedicatedServer.java Tue Aug 14 20:15:26 2012
+++ minecraft_patched\net\minecraft\src\DedicatedServer.java Tue Aug 14 20:25:02 2012
@@ -183,7 +183,7 @@
}
- protected CrashReport func_71230_b(CrashReport p_71230_1_) {
+ public CrashReport func_71230_b(CrashReport p_71230_1_) {
p_71230_1_ = super.func_71230_b(p_71230_1_);
p_71230_1_.func_71500_a("Type", new CallableType(this));
return p_71230_1_;
@@ -193,7 +193,7 @@
System.exit(0);
}
- protected void func_71190_q() {
+ public void func_71190_q() {
super.func_71190_q();
this.func_71333_ah();
}
diff -r -U 3 minecraft\net\minecraft\src\FontRenderer.java minecraft_patched\net\minecraft\src\FontRenderer.java
--- minecraft\net\minecraft\src\FontRenderer.java Tue Aug 14 20:15:26 2012
+++ minecraft_patched\net\minecraft\src\FontRenderer.java Tue Aug 14 20:18:48 2012
@@ -711,8 +711,6 @@
for(boolean var7 = false; var5 < var3; ++var5) {
char var8 = p_78259_1_.charAt(var5);
switch(var8) {
- case 32:
- var6 = var5;
case 167:
if(var5 < var3 - 1) {
++var5;
@@ -726,6 +724,8 @@
}
}
break;
+ case 32:
+ var6 = var5;
default:
var4 += this.func_78263_a(var8);
if(var7) {
diff -r -U 3 minecraft\net\minecraft\src\IntegratedServer.java minecraft_patched\net\minecraft\src\IntegratedServer.java
--- minecraft\net\minecraft\src\IntegratedServer.java Tue Aug 14 20:15:26 2012
+++ minecraft_patched\net\minecraft\src\IntegratedServer.java Tue Aug 14 20:24:49 2012
@@ -98,7 +98,7 @@
return true;
}
- protected void func_71217_p() {
+ public void func_71217_p() {
boolean var1 = this.field_71348_o;
this.field_71348_o = this.field_71347_n.func_71752_f();
if(!var1 && this.field_71348_o) {
@@ -145,7 +145,7 @@
this.field_71349_l.func_71404_a(p_71228_1_);
}
- protected CrashReport func_71230_b(CrashReport p_71230_1_) {
+ public CrashReport func_71230_b(CrashReport p_71230_1_) {
p_71230_1_ = super.func_71230_b(p_71230_1_);
p_71230_1_.func_71500_a("Type", new CallableType3(this));
p_71230_1_.func_71500_a("Is Modded", new CallableIsModded(this));
diff -r -U 3 minecraft\net\minecraft\src\ItemMap.java minecraft_patched\net\minecraft\src\ItemMap.java
--- minecraft\net\minecraft\src\ItemMap.java Tue Aug 14 20:15:26 2012
+++ minecraft_patched\net\minecraft\src\ItemMap.java Tue Aug 14 20:18:48 2012
@@ -24,7 +24,6 @@
}
public static MapData func_77874_a(short p_77874_0_, World p_77874_1_) {
- "map_" + p_77874_0_;
MapData var3 = (MapData)p_77874_1_.func_72943_a(MapData.class, "map_" + p_77874_0_);
if(var3 == null) {
int var4 = p_77874_1_.func_72841_b("map");
@@ -37,7 +36,6 @@
}
public MapData func_77873_a(ItemStack p_77873_1_, World p_77873_2_) {
- "map_" + p_77873_1_.func_77960_j();
MapData var4 = (MapData)p_77873_2_.func_72943_a(MapData.class, "map_" + p_77873_1_.func_77960_j());
if(var4 == null) {
p_77873_1_.func_77964_b(p_77873_2_.func_72841_b("map"));
diff -r -U 3 minecraft\net\minecraft\src\RenderGlobal.java minecraft_patched\net\minecraft\src\RenderGlobal.java
--- minecraft\net\minecraft\src\RenderGlobal.java Tue Aug 14 20:15:27 2012
+++ minecraft_patched\net\minecraft\src\RenderGlobal.java Tue Aug 14 20:18:48 2012
@@ -1431,7 +1431,7 @@
double var15 = this.field_72777_q.field_71451_h.field_70165_t - p_72726_2_;
double var17 = this.field_72777_q.field_71451_h.field_70163_u - p_72726_4_;
double var19 = this.field_72777_q.field_71451_h.field_70161_v - p_72726_6_;
- Object var21 = null;
+ EntityFX var21 = null;
if(p_72726_1_.equals("hugeexplosion")) {
this.field_72777_q.field_71452_i.func_78873_a(var21 = new EntityHugeExplodeFX(this.field_72769_h, p_72726_2_, p_72726_4_, p_72726_6_, p_72726_8_, p_72726_10_, p_72726_12_));
} else if(p_72726_1_.equals("largeexplode")) {
diff -r -U 3 minecraft\net\minecraft\src\TcpMasterThread.java minecraft_patched\net\minecraft\src\TcpMasterThread.java
--- minecraft\net\minecraft\src\TcpMasterThread.java Tue Aug 14 20:15:27 2012
+++ minecraft_patched\net\minecraft\src\TcpMasterThread.java Tue Aug 14 20:18:48 2012
@@ -11,6 +11,7 @@
this.field_74504_a = p_i3285_1_;
}
+ @SuppressWarnings("deprecation")
public void run() {
try {
Thread.sleep(5000L);
diff -r -U 3 minecraft\net\minecraft\src\ThreadedFileIOBase.java minecraft_patched\net\minecraft\src\ThreadedFileIOBase.java
--- minecraft\net\minecraft\src\ThreadedFileIOBase.java Tue Aug 14 20:15:27 2012
+++ minecraft_patched\net\minecraft\src\ThreadedFileIOBase.java Tue Aug 14 20:18:48 2012
@@ -20,7 +20,9 @@
}
public void run() {
+ while(true) {
this.func_75736_b();
+ }
}
private void func_75736_b() {

@ -0,0 +1,70 @@
diff -r -U 3 minecraft_server\net\minecraft\src\ComponentStrongholdRightTurn.java minecraft_server_patched\net\minecraft\src\ComponentStrongholdRightTurn.java
--- minecraft_server\net\minecraft\src\ComponentStrongholdRightTurn.java Tue Aug 14 20:16:02 2012
+++ minecraft_server_patched\net\minecraft\src\ComponentStrongholdRightTurn.java Tue Aug 14 20:19:30 2012
@@ -11,6 +11,10 @@
public class ComponentStrongholdRightTurn extends ComponentStrongholdLeftTurn {
+ public ComponentStrongholdRightTurn(int p_i3843_1_, Random p_i3843_2_, StructureBoundingBox p_i3843_3_, int p_i3843_4_) {
+ super(p_i3843_1_, p_i3843_2_, p_i3843_3_, p_i3843_4_);
+ }
+
public void func_74861_a(StructureComponent p_74861_1_, List p_74861_2_, Random p_74861_3_) {
if(this.field_74885_f != 2 && this.field_74885_f != 3) {
this.func_74989_b((ComponentStrongholdStairs2)p_74861_1_, p_74861_2_, p_74861_3_, 1, 1);
diff -r -U 3 minecraft_server\net\minecraft\src\DedicatedServer.java minecraft_server_patched\net\minecraft\src\DedicatedServer.java
--- minecraft_server\net\minecraft\src\DedicatedServer.java Tue Aug 14 20:16:03 2012
+++ minecraft_server_patched\net\minecraft\src\DedicatedServer.java Tue Aug 14 20:24:26 2012
@@ -184,7 +184,7 @@
}
- protected CrashReport func_71230_b(CrashReport p_71230_1_) {
+ public CrashReport func_71230_b(CrashReport p_71230_1_) {
p_71230_1_ = super.func_71230_b(p_71230_1_);
p_71230_1_.func_71500_a("Type", new CallableType(this));
return p_71230_1_;
@@ -194,7 +194,7 @@
System.exit(0);
}
- protected void func_71190_q() {
+ public void func_71190_q() {
super.func_71190_q();
this.func_71333_ah();
}
diff -r -U 3 minecraft_server\net\minecraft\src\ItemMap.java minecraft_server_patched\net\minecraft\src\ItemMap.java
--- minecraft_server\net\minecraft\src\ItemMap.java Tue Aug 14 20:16:03 2012
+++ minecraft_server_patched\net\minecraft\src\ItemMap.java Tue Aug 14 20:19:30 2012
@@ -24,7 +24,6 @@
}
public MapData func_77873_a(ItemStack p_77873_1_, World p_77873_2_) {
- "map_" + p_77873_1_.func_77960_j();
MapData var4 = (MapData)p_77873_2_.func_72943_a(MapData.class, "map_" + p_77873_1_.func_77960_j());
if(var4 == null) {
p_77873_1_.func_77964_b(p_77873_2_.func_72841_b("map"));
diff -r -U 3 minecraft_server\net\minecraft\src\TcpMasterThread.java minecraft_server_patched\net\minecraft\src\TcpMasterThread.java
--- minecraft_server\net\minecraft\src\TcpMasterThread.java Tue Aug 14 20:16:03 2012
+++ minecraft_server_patched\net\minecraft\src\TcpMasterThread.java Tue Aug 14 20:19:30 2012
@@ -11,6 +11,7 @@
this.field_74504_a = p_i3285_1_;
}
+ @SuppressWarnings("deprecation")
public void run() {
try {
Thread.sleep(5000L);
diff -r -U 3 minecraft_server\net\minecraft\src\ThreadedFileIOBase.java minecraft_server_patched\net\minecraft\src\ThreadedFileIOBase.java
--- minecraft_server\net\minecraft\src\ThreadedFileIOBase.java Tue Aug 14 20:16:03 2012
+++ minecraft_server_patched\net\minecraft\src\ThreadedFileIOBase.java Tue Aug 14 20:19:30 2012
@@ -20,7 +20,9 @@
}
public void run() {
+ while(true) {
this.func_75736_b();
+ }
}
private void func_75736_b() {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,4 @@
[VERSION]
MCPVersion = 7.2
ClientVersion = 1.3.2
ServerVersion = 1.3.2

@ -0,0 +1,3 @@
@echo off
runtime\bin\python\python_mcp runtime\decompile.py %*
pause

@ -0,0 +1,2 @@
#!/bin/bash
python runtime/decompile.py "$@"

@ -0,0 +1,8 @@
To use eclipse with MCP, just do the following steps:
- Decompile the Minecraft sources
- Open Eclipse
- Select the "eclipse" folder in MCP as workspace
- Create a mod
- You can test the modified client and server in Eclipse, debug
settings are already prepared to start the game in the IDE
- Recompile and reobfuscate as usual

@ -0,0 +1,73 @@
To use the fernflower decompiler, just put the fernflower.jar file into the runtime/bin folder.
Only tested with fernflower 0.8.6, other versions may fail.
Hi Searge,
I was told you might be planning to distribute Fernflower as a part of
MCP. It looks like a very nice project to me (excellent work btw :))
so I'm happy to allow the integration. Below you'll find the necessary
supplement to the general license.
Based on the general Fernflower license the following additional
permissions are granted to the project Minecraft Coder Pack (MCP). As
long as the project remains non-commercial it may use, integrate and
distribute every binary version of the decompiler Fernflower in any
desired way as part of MCP tools. Custom patches to Fernflower are
generally possible after a brief consultation with me.
Cheers,
Stiver
Fernflower Freeware License 1.0
This license applies to the Fernflower decompiler (hereafter “Software")
including any associated files, information and examples.
You are hereby granted a non-exclusive and non-transferable license to
use and distribute the Software in binary form according to the following
terms and conditions.
1) Copies and Redistribution
You may copy and distribute unmodified binary copies of the Software
provided that you keep this license intact. You must NOT charge money
or fees for the Software except to cover the absolutely necessary
distribution costs.
Any other form of redistribution is prohibited. Especially you are not
allowed to redistribute the Software as part of any other software
collection or other product.
2) Use
You may use the Software "as is" in any commercial or non-commercial environment
for any purpose.
3) Contact Information
The sole author and owner of Fernflower is Stiver. Address all correspondence regarding
this license to:
fernflower.decompiler@gmail.com
http://www.reversed-java.com
4) Disclaimer of Warranty
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

@ -0,0 +1,9 @@
Things required to run:
- wine to run jad. We know, there are linux binaries of jad BUT those are
v1.5.8e, we need 1.5.8g
- python to run most of the tools
- patch to fix the decompiled sources
- minecraft.jar, lwjgl jars, and the linux version of the natives, these can
be found in your home dir under ".minecraft/bin", the entire bin folder
itself should be copied into the jars folder

@ -0,0 +1,310 @@
Minecraft Coder Pack 7.2 for Minecraft 1.3.2
============================================
MCP is (c) Copyright by the MCP Team
License and terms of use.
=========================
No warranties. If MCP does not work for you, or causes any damage, it's your problem. Use it at own risk.
You are allowed to:
- Use MCP to decompile the Minecraft client and server jar files.
- Use the decompiled source code to create mods for Minecraft.
- Recompile modified versions of Minecraft.
- Reobfuscate the classes of your mod for Minecraft.
You are NOT allowed to:
- Use MCP to do anything that violated Mojangs terms of use for Minecraft.
- Release Minecraft versions or modifications that allow you to play without having bought Minecraft from Mojang.
- Release modified or unmodified versions of MCP anywhere.
- Use any of MCPs scripts, tools or data files without explicit written permission.
- Make money with anything based on MCP (excluding Minecraft mods created by using MCP).
- Use MCP to create clients that are used for griefing or exploiting server bugs.
- Release the decompiled source code of Minecraft in any way.
Prerequisites:
==============
1.) Install Java SDK Standard Edition (short JDK).
Link: http://www.oracle.com/technetwork/java/javase/downloads/
2.) Add the paths to your JDK and JRE bin folders to the Environment Variable PATH.
Description where to find the variable:
http://www.java.com/en/download/help/path.xml
Example for Windows users of what you have to add to the variable (entries are seperated by ";" )
C:\Program Files\Java\jdk1.6.0_24\bin;C:\Program Files\Java\jre6\bin
We wont provide any help setting it up - this _is_ a prerequesite.
Note: MCP versions 4.4 and higher should also work properly with JDK 1.7
How to use:
===========
1) Prepare the files:
- Copy the "minecraft_server.jar" file into the "jars" folder.
- Copy the folders "bin" and "resources" from your "%APPDATA$\.minecraft" folder into the "jars" folder.
2) Decompilation and patching
- Start the "decompile.bat" script in this folder.
3) Modding
- Modify the sourcecode in the "src\minecraft" folder or in the "src\minecraft_server" folder.
4) Compile
- Start the "recompile.bat" script in this folder.
5) Testing
- To test the modified game, start the "startclient.bat" script
- To test the modified server, start the "startserver.bat" script
6) Obfuscation
- Decompile the code, modify and recompile.
- Start "reobfuscate.bat" to start the reobfuscation step, it will automatically detect changed classes and reobfuscate them.
- Your obfuscated classes are now available in "reobf\minecraft" and "reobf\minecraft_server", ready to be injected in MC.
- Make sure to delete the META-INF folder in minecraft.jar, otherwise the game will just black-screen when you start it.
WARNINGS:
=========
- Make sure that you backup the modified sources before you run "decompile.bat" again or all changes will be lost!
- The "cleanup.bat" file will delete most of the generated files and sources. Be careful with this one :)
Notes:
======
* If you want to include external libraries (either as .jar or .class) to the classpath during recompilation add them
to a folder called "lib" creating it first if required.
* Should mcp complain about "java.lang.NoClassDefFoundError: Start" when trying to run startclient.bat or startserver.bat
try cleanup.bat (make backups of you sources!), decompile again and recompile as the final step.
* Do not use this to release complete packages of minecraft jar, class or java files. They are copyrighted
material by Notch and mods should only contain small changes to some classes, never complete sets that
can be used by people who did not buy the game to play it.
* Make sure you use the original minecraft.jar and minecraft_server.jar files. If you have already modded them
they will NOT work with the patches in these scripts.
* The "startclient.bat" file uses the "Start.class" file to start the game. This will make sure the game will not
use your "%APPDATA%\.minecraft" folder, but instead use the "jars" folder for all saves. So any bugs in the modified
game will not corrupt your normal worlds.
* If you have any problems using this toolpack, put the "logs\*.log" files that the scripts generated into a
zip-file and send it to us (post it in the minecraft forum):
http://www.minecraftforum.net/viewtopic.php?f=25&t=58464
* This version of the MCP uses a deobfuscator to change all field and method names in the sources.
Look in the csv files in "conf", namely "conf\classes.csv", "conf\fields.csv" and "conf\methods.csv" files for a complete mapping of the names.
* There are currently no known bugs in the recompiled game or server, except those that were already in the original
game :)
* If your reobfuscated classes cause a black screen in Minecraft, make sure that you've deleted the META-INF folder
in the minecraft.jar file.
* To add new resources to the game, for example png files, put them in the bin folder tree, they will also get copied to the reob folder
automatically when you reobfuscate your changes.
Credits:
========
== Currently Active ==
Searge
* Creator of MCP
* Fixes all compile errors in the decompiled sourcecode
* Created the MCP mod system and API
* Created the Eclipse workspace for MCP 4.x
* Created the new RetroGuard deobfuscation module for MCP 3.0
* Created the new mod system
ProfMobius
* Creator of the renaming codes and re-obfuscation procedures
* Helped to port scripts to Linux
* Developer and maintainer of the MCP chan bot
* Is now bald after working too much with java constant pool and re-obfuscation
* Created the new workflow scripts and renamer for MCP 3.0
IngisKahn
* Creator of the bytecode compare tool that helps us to update the name mappings quickly for new minecraft versions
* Contributed to the de-obfuscation spreadsheet
* Working hard on creating better internal tools for mapping updates and decompiling
Fesh0r
* php/sql code monkey
* Uses his magic to create mappings, patches, and general release work
* Has Searge's approval to make official MCP releases ;)
* Makes sure we get proper patches for the sourcecode that JAD generates
* Maintains our scripts and toolkits
* Optimized the Retroguard and Exceptor tools
R4WK
* Works on MCP updates and contributes to the new mod system
* Helps ZeuX with Techne improvements
ZeuX
* Helps out in the IRC channels - Head of HR
* Did server patches for the most recent versions - if you run into any (patch-related) problems, it's his fault :P
* Created the famous Techne model editor for Minecraft
* Contributes features to the new mod system
303
* Wiki contributor
* Tries to help out newbies in the IRC channels
* Makes sure modloader mods can be created with MCP
Mr_okushama
* Wiki contributor
* Public Support Manager
* IRC Operator
* Savior of the 2011 April fools prank
Cryect
* Contributed a lot of deobfuscation mappings
* Created the awesome AdventureCraft mod
LexManos
* Helped Fesh0r to update MCP for Minecraft 1.0.0/1.0.1
Mysterio N
* Created the getmodsource scripts
== Former Contributors ==
Generic
* Works on improving IngisKahn's bytecode compare tool
* Added some important features to retroguard
Risugami
* The guy who created the first mods I (Searge) ever used in Minecraft
* The creator of modloader who gave us permission to include files from his system in MCP
fotoply
* Helped to improve the batch files
Cadde
* Community manager and Wiki manager
* Works on the de-obfuscation spreadsheet
* Mod support (making old mods work with MCP)
* All round handyman
Vaprtek
* Works on the de-obfuscation spreadsheet
* Knows how to make pet creepers
gronk
* Script support
n00bish
* Linux script maintenance
Sage Pourpre
* His thread in the forums inspired me (Searge) to create this toolpack in the first place
Tei
* Supported the MCP project since the first version was released
spec10
* The new linux scripts guy
Head
* Wiki contributor / Administrator
* Explains classes and their members on the Wiki
MissLil
* Various scripting stuff
* Lots of reverse engineering
* OpenGL constants annoting
ScottyDoesKnow
* obfuscathonCharmer, the obfuscathon GUI
Chase
* MCP Launcher Work
* External jar loading
* Scrollable mod list.
titegtnodI
* Wiki contributor
* IRC Operator
== Superspecial thanks to ==
Stiver - for allowing us to include the fernflower decompiler in MCP releases
== Special thanks to ==
UltraMoogleMan
Yamachi
and of course:
- Everybody who contributed to the google spreadsheet and MCPBot or who created some mods with MCP.
- NOTCH and JEB for creating a game that is just awesome, I hope they do not feel offended by our decompiling efforts.
Please, Notch, support our ambitions to mod your game. I know people who bought it just because of
some great mods.
History:
========
7.2 - Updated to support Minecraft 1.3.2 and MinecraftServer 1.3.2
7.0a - Added fernflower decompiler
7.0 - Updated to support Minecraft 1.3.1 and MinecraftServer 1.3.1
6.2 - Updated to support Minecraft 1.2.5 and MinecraftServer 1.2.5
6.1 - Updated to support Minecraft 1.2.4 and MinecraftServer 1.2.4
6.0 - Updated to support Minecraft 1.2.3 and MinecraftServer 1.2.3
5.6 - Updated to support Minecraft 1.1 and MinecraftServer 1.1
5.0 - Updated to support Minecraft 1.0.0 and MinecraftServer 1.0.1
4.5 - Updated to support Minecraft 1.9 pre 5 and MinecraftServer 1.9 pre 5
4.4 - Updated to support Minecraft 1.8.1 and MinecraftServer 1.8.1
4.3 - Updated to support Minecraft 1.7.3 and MinecraftServer 1.7.3
4.2 - Updated to support Minecraft 1.7.2 and MinecraftServer 1.7.2
4.1 - Added an Eclipse workspace and included a reobfuscation bugfix
4.0 - Added improved decompile scripts with new Exceptor tool
3.4 - Updated to support Minecraft 1.6.6 and MinecraftServer 1.6.6
3.3 - Updated to support Minecraft 1.6.5 and MinecraftServer 1.6.5
3.2 - Updated to support Minecraft 1.6.4 and MinecraftServer 1.6.4
3.1 - Complete rewrite of the framework, works with Minecraft 1.5_01 and MinecraftServer 1.5_02
2.12 - Updated to support Minecraft 1.5_01 and MinecraftServer 1.5_02
2.11 - Updated to support Minecraft 1.4_01 and MinecraftServer 1.4_01
2.10 - Updated to support Minecraft 1.4 and MinecraftServer 1.4
2.9a - Added MCP Mod System for 1.3_01, added mod loader support, updated mappings
2.9 - Updated to support Minecraft 1.3_01 and MinecraftServer 1.3
2.8 - Added the MCP mod system SDK and support for OSX
2.7 - Updated to support Minecraft 1.2_02 and MinecraftServer 1.2_01
2.6 - Updated to support Minecraft 1.1_02 and MinecraftServer 1.1_02
2.5 - Updated to support Minecraft 1.2.6 and MinecraftServer 0.2.8
2.4 - Updated to support Minecraft 1.2.5 and MinecraftServer 0.2.7
2.3 - Updated to support Minecraft 1.2.3_04 and MinecraftServer 0.2.5_02. Linux support beta.
2.2a - Bugfix release to improve the re-obfuscation tools
2.2 - The reobfuscation beta test release. Still for Minecraft 1.2.2
2.1 - Updated to support Minecraft 1.2.2
2.0a - Bugfix release
2.0 - Major updates to MCP and support for post-Halloween versions of Minecraft
1.6 - All classes have meaningful names now, the class name mappings and the field name mappings are applied
1.5 - Extend the scripts to also support decompiling, recompiling and testing the minecraft_server.jar file
1.4 - Using a deobfuscator to rename all fields and methods and jadretro to fix some decompile bugs
1.3 - Added upgrade scripts to decompile and recompile Minecraft.class, MinecraftApplet.class and MinecraftServer.class
1.2 - Redirect output of all tools to a logfile
1.1 - Fixed TNT bug
1.0 - First release
Roadmap:
========
7.3+ - New awesome features, improvements and updates :)
_________________________________________________________________________________________________________________
_________________________________________________________________________________________________________________
________,.--:=r=.._______________________________________________________________________________,,...___________
_ -:'` :^)-.!..[``P: ___________________________________________________________ ,.=~r?`[:_i=. `'~-._ _
_ . :=)~.|:.| [j ___________________________________________________________ l| [3 .:,[:. ! _
_ : :.[ .|:.( [| ______________________________________________________________[|=^): [_ | . ! _
__ :~)=.i..j [] ___________________________________________________________ )|:') [ _|;. ! _
_ . :.)..i._|;.)| ___________________________________________________________ [!:=[` |: | . ! _
_ ) _ :.[ .! | .[| ___________________________________________________________ )j:^[` (: | . ! _
_ :_ <=l:.____ . | ___________________________________________________________ [!:`` :.|:. . ! _
_ ._ _ __ __:..;.|,.) .[j ___________________________________________________________ [!3`T``l:. . ` ! _
____ [,...-+=c=f7l`!-( _____.~~~~~~~~._____=~~~~~~~/_____,>====~<.y=.__y~~~~~~~~~~=~.._ ```[j)=[=[.;,,_ _|'`` _
____ [ -~= ( '=r::::~( _____!<. L____F .=._ ,c ;>~~<. [_ F<. .>~~<. ".__ (.......!.( .. | ____
____ [`) [ ! !^) !') ______ [ JL (___F Z. ( ___/ ./ ____ ". J___ L ? ___J. J _ |-l ,.( !-| )-| ____
____ ) !` ( ```[ ( _____ :. [[ J__F /] .L___F .F _______"L L__J [____/ / _ | )~~~~ r- !~! | ____
____ [ . . [_) (___|_( _____ | :L! J.F / L J __[ | _________ _ [ =+~~=l ;/ __ |'[^^^( [ :'. ::( ____
____ [.. (.;.i.) ( ______L ? :. * / J. [__ L L______________:L ;...=+=^` ____ (`["[ l [`` ! ! | ____
____ ).. .... !.. ( _____J. L_ L / _[ :L__ [ [_________,.__ | .L_____________ ( . ! | ____
____ ).. --. --..!-( _____[ :.__| / _.L J ___"c ?.______,/.;F _L J._____________ [_[___ __ _| ____
____ )~)~r -)~r - ( ( __:tT ":LJ / r^` ")___ \. 7*==^`.;* r^` "tL___________ ! ( ,,[ ._].|_____
___ _z;! : = ( ( : !=( __'^^^^^^" ^^ *^^^^^^^^`____ "*~~~~^` __"^^^^^^^^" ___________ ;.) ( ( ..!.!.| ____
____F"*:P*si_(^^======.____________________________________________________________________j.....[.( !,.ztSP\ ___
_ _! 7*.) L L___________________________________________________________________: J :?x>'` l___
__[ ;~.! ; :=l .-<--~~[___________________________________________________________________|,J .__ !. :. _,_ . _
I :`~. `\[ (.J-= [___________________________________________________________________| ._L_)~\./ ..==`.
-.;`'=._ .L!;)-+--=-=-l___________________________________________________________________|___;__[_;=[\ ,>=`
_ =-: `` _ --:...-...___________________________________________________________________ :_: ._[ \=^ .-!
_ ` - L______-.- ..-___________________________________________________________________: ! ._____ -' _ -' _
_____ _________________________________________________________________________________ ______ ' _____
d8b db .d88b. db d8b db d888888b d888888b d888888b .d8888.
888o 88 .8P Y8. 88 I8I 88 `88' `~~88~~' `88' 88' YP
88V8o 88 88 88 88 I8I 88 88 88 88 `8bo.
88 V8o88 88 88 Y8 I8I 88 88 88 88 `Y8b.
88 V888 `8b d8' `8b d8'8b d8' .88. 88 .88. db 8D
VP V8P `Y88P' `8b8' `8d8' Y888888P YP Y888888P `8888Y'
db db .d88b. db db d8888b. .o88b. d8888b. .d8b. d88888b d888888b
`8b d8' .8P Y8. 88 88 88 `8D d8P Y8 88 `8D d8' `8b 88' `~~88~~'
`8bd8' 88 88 88 88 88oobY' 8P 88oobY' 88ooo88 88ooo 88
88 88 88 88 88 88`8b 8b 88`8b 88~~~88 88~~~ 88
88 `8b d8' 88b d88 88 `88. Y8b d8 88 `88. 88 88 88 88
YP `Y88P' ~Y8888P' 88 YD `Y88P' 88 YD YP YP YP YP
======================================================================================================================

@ -0,0 +1,7 @@
Things required to run:
- python to run most of the tools
- patch to fix the decompiled sources
- minecraft.jar, lwjgl jars, and the OSX version of the natives, these can be
found in your home folder under "Library/Application Support/minecraft/bin",
the entire bin folder itself should be copied into the jars folder

@ -0,0 +1,51 @@
Fernflower Freeware License 1.0
This license applies to the Fernflower decompiler (hereafter “Software")
including any associated files, information and examples.
You are hereby granted a non-exclusive and non-transferable license to
use and distribute the Software in binary form according to the following
terms and conditions.
1) Copies and Redistribution
You may copy and distribute unmodified binary copies of the Software
provided that you keep this license intact. You must NOT charge money
or fees for the Software except to cover the absolutely necessary
distribution costs.
Any other form of redistribution is prohibited. Especially you are not
allowed to redistribute the Software as part of any other software
collection or other product.
2) Use
You may use the Software "as is" in any commercial or non-commercial environment
for any purpose.
3) Contact Information
The sole author and owner of Fernflower is Stiver. Address all correspondence regarding
this license to:
fernflower.decompiler@gmail.com
http://www.reversed-java.com
4) Disclaimer of Warranty
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

@ -0,0 +1,86 @@
1. About the decompiler
Fernflower is the first actually working analytical decompiler for Java and
probably for a high-level programming language in general. Naturally it is still
under development, please send your bug reports and improvement suggestions at
fernflower.decompiler@gmail.com
2. License
See license_en.txt
3. Running from the command line
java -jar fernflower.jar [-<option>=<value>]* [<source>]+ <destination>
* means 0 or more times
+ means 1 or more times
<source>: file or directory with files to be decompiled. Directories are recursively scanned. Allowed file extensions are class, zip and jar.
Sources prefixed with -e= mean "library" files that won't be decompiled, but taken into account when analysing relationships between
classes or methods. Especially renaming of identifiers (s. option 'ren') can benefit from information about external classes.
<destination>: destination directory
<option>,<value>: command line option with the corresponding value, see 4.
Examples:
java -jar fernflower.jar -hes=0 -hdc=0 c:\Temp\binary\ -e=c:\Java\rt.jar c:\Temp\source\
java -jar fernflower.jar -dgs=1 c:\Temp\binary\library.jar c:\Temp\binary\Boot.class c:\Temp\source\
4. Command line options
With the exception of mpm and urc the value of 1 means the option is activated, 0 - deactivated. Default
value, if any, is given between parentheses.
Typically, the following options will be changed by user, if any: hes, hdc, dgs, mpm, ren, urc
The rest of options can be left as they are: they are aimed at professional reverse engineers.
rbr (1): hide bridge methods
rsy (0): hide synthetic class members
din (1): decompile inner classes
dc4 (1): collapse 1.4 class references
das (1): decompile assertions
hes (1): hide empty super invocation
hdc (1): hide empty default constructor
dgs (0): decompile generic signatures
occ (0): ouput copyright comment
ner (1): assume return not throwing exceptions
den (1): decompile enumerations
rgn (1): remove getClass() invocation, when it is part of a qualified new statement
bto (1): interpret int 1 as boolean true (workaround to a compiler bug)
nns (1): allow for not set synthetic attribute (workaround to a compiler bug)
uto (1): consider nameless types as java.lang.Object (workaround to a compiler architecture flaw)
udv (1): reconstruct variable names from debug information, if present
rer (1): remove empty exception ranges
fdi (1): deinline finally structures
asc (0): allow only ASCII characters in string literals. All other characters will be encoded using Unicode escapes (JLS 3.3). Default encoding is UTF8.
mpm (0): maximum allowed processing time per decompiled method, in seconds. 0 means no upper limit.
ren (0): rename ambiguous (resp. obfuscated) classes and class elements
urc : full name of user-supplied class implementing IIdentifierRenamer. It is used to determine which
class identifiers should be renamed and provides new identifier names. For more information
s. section 5
The default logging level is INFO. This value can be overwritten by setting the option 'log' as follows:
log (INFO): possible values TRACE, INFO, WARN, ERROR
5. Renaming identifiers
Some obfuscators give classes and their member elements short, meaningless and above all ambiguous names. Recompiling of such
code leads to a great number of conflicts. Therefore it is advisable to let the decompiler rename elements in its turn,
ensuring uniqueness of each identifier.
Option 'ren' (i.e. -ren=1) activates renaming functionality. Default renaming strategy goes as follows:
- rename an element if its name is a reserved word or is shorter than 3 characters
- new names are built according to a simple pattern: (class|method|field)_<consecutive unique number>
You can overwrite this rules by providing your own implementation of the 4 key methods invoked by the decompiler while renaming. Simply
pass a class that implements de.fernflower.main.extern.IIdentifierRenamer in the option 'urc' (e.g. -urc=com.mypackage.MyRenamer) to
Fernflower. The class must be available on the application classpath.
The meaning of each method should be clear from naming: toBeRenamed determine whether the element will be renamed, while the other three
provide new names for classes, methods and fields respectively.

Binary file not shown.

@ -0,0 +1,3 @@
@echo off
runtime\bin\python\python_mcp runtime\getchangedsrc.py %*
pause

@ -0,0 +1,2 @@
#!/bin/bash
python runtime/getchangedsrc.py "$@"

@ -0,0 +1,3 @@
@echo off
runtime\bin\python\python_mcp runtime\recompile.py %*
pause

@ -0,0 +1,2 @@
#!/bin/bash
python runtime/recompile.py "$@"

@ -0,0 +1,3 @@
@echo off
runtime\bin\python\python_mcp runtime\reformat.py %*
pause

@ -0,0 +1,2 @@
#!/bin/bash
python runtime/reformat.py "$@"

@ -0,0 +1,3 @@
@echo off
runtime\bin\python\python_mcp runtime\reobfuscate.py %*
pause

@ -0,0 +1,2 @@
#!/bin/bash
python runtime/reobfuscate.py "$@"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 9 13:51:48 2011
@author: ProfMobius & Searge
@version: v1.0
"""
import sys
import os
import glob
import logging
from optparse import OptionParser
from commands import Commands, reallyrmtree
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-f', '--force', action='store_true', dest='force', help='force cleanup', default=False)
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
cleanup(options.config, options.force)
def cleanup(conffile, force):
try:
commands = Commands(conffile)
if not force:
print 'WARNING:'
print 'The cleanup script will delete all folders created by MCP, including the'
print 'src folder which may contain changes you made to the code, along with any'
print 'saved worlds from the client or server.'
answer = raw_input('If you really want to clean up, enter "Yes" ')
if answer.lower() not in ['yes']:
print 'You have not entered "Yes", aborting the clean up process'
sys.exit(1)
commands.checkupdates()
try:
commands.logger.info('> Cleaning temp')
reallyrmtree(commands.dirtemp)
commands.logger.info('> Cleaning src')
reallyrmtree(commands.dirsrc)
commands.logger.info('> Cleaning bin')
reallyrmtree(commands.dirbin)
commands.logger.info('> Cleaning reobf')
reallyrmtree(commands.dirreobf)
commands.logger.info('> Cleaning lib')
reallyrmtree(commands.dirlib)
commands.logger.info('> Cleaning jars')
reallyrmtree(os.path.join(commands.dirjars, 'saves'))
reallyrmtree(os.path.join(commands.dirjars, 'stats'))
reallyrmtree(os.path.join(commands.dirjars, 'texturepacks'))
reallyrmtree(os.path.join(commands.dirjars, 'texturepacks-mp-cache'))
reallyrmtree(os.path.join(commands.dirjars, 'mcpworld'))
if os.path.exists(os.path.join(commands.dirjars, 'server.log')):
os.remove(os.path.join(commands.dirjars, 'server.log'))
for txt_file in glob.glob(os.path.join(commands.dirjars, '*.txt')):
os.remove(txt_file)
commands.logger.info('> Cleaning logs')
logging.shutdown()
reallyrmtree(commands.dirlogs)
except OSError as ex:
print >> sys.stderr, 'Cleanup FAILED'
if hasattr(ex, 'filename'):
print >> sys.stderr, 'Failed to remove ' + ex.filename
sys.exit(1)
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

Binary file not shown.

@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:54:36 2011
@author: ProfMobius
@version: v1.2
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER, CalledProcessError
from mcp import decompile_side, updatemd5_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-j', '--jad', dest='force_jad', action='store_true',
help='force use of JAD even if Fernflower available', default=False)
parser.add_option('-s', '--csv', dest='force_csv', action='store_true',
help='force use of CSVs even if SRGs available', default=False)
parser.add_option('-r', '--norecompile', dest='no_recompile', action='store_true',
help='disable recompile after decompile', default=False)
parser.add_option('-d', '--nocomments', dest='no_comments', action='store_true', help='disable javadoc',
default=False)
parser.add_option('-a', '--noreformat', dest='no_reformat', action='store_true',
help='disable source reformatting', default=False)
parser.add_option('-n', '--norenamer', dest='no_renamer', action='store_true',
help='disable field and method renaming', default=False)
parser.add_option('-l', '--lvt', dest='keep_lvt', action='store_true', help='preserve local variable table',
default=False)
parser.add_option('-g', '--generics', dest='keep_generics', action='store_true',
help='preserve generics as well as local variables', default=False)
parser.add_option('-o', '--onlypatch', dest='only_patch', action='store_true', help='only patch source',
default=False)
parser.add_option('-p', dest='no_patch', action='store_true', help='Undocumented magic', default=False)
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
decompile(options.config, options.force_jad, options.force_csv, options.no_recompile, options.no_comments,
options.no_reformat, options.no_renamer, options.no_patch, options.only_patch, options.keep_lvt,
options.keep_generics)
def decompile(conffile, force_jad, force_csv, no_recompile, no_comments, no_reformat, no_renamer, no_patch, only_patch,
keep_lvt, keep_generics):
try:
commands = Commands(conffile, verify=True, no_patch=no_patch)
commands.checkupdates()
use_ff = commands.has_ff and not force_jad
use_srg = commands.has_srg and not force_csv
if force_jad and not commands.has_jad:
commands.logger.error('!! forcing jad when not available !!')
sys.exit(1)
if force_csv and not commands.has_map_csv:
commands.logger.error('!! forcing csvs when not available !!')
sys.exit(1)
# always strip comments by default, turn off in update mode if required
strip_comments = True
# update only options
rg_update = False
exc_update = False
if no_patch:
# no_patch is basically update mode, disables everything
# and reuses a few different options to do update stuff
if only_patch:
# with only_patch then we actually do the patches, but not the comment stripping, for use when updating
# the fernflower patches
no_patch = False
strip_comments = False
if no_reformat:
# reuse -a no_reformat to switch rg to fullmap=1 startindex=RGIndex
rg_update = True
if no_renamer:
# reuse -n to switch mcinjector to outputing exc file, and adding new parameters
exc_update = True
no_comments = True
no_reformat = True
no_renamer = True
no_recompile = True
elif only_patch:
# if only_patch then disable everything but patching and comment stripping
no_comments = True
no_reformat = True
no_renamer = True
no_recompile = True
# if we have generics enabled we need the lvt as well
if keep_generics:
keep_lvt = True
commands.logger.info('> Creating Retroguard config files')
commands.creatergcfg(reobf=False, keep_lvt=keep_lvt, keep_generics=keep_generics, rg_update=rg_update)
try:
cltdecomp = decompile_side(commands, CLIENT, use_ff=use_ff, use_srg=use_srg, no_comments=no_comments,
no_reformat=no_reformat, no_renamer=no_renamer, no_patch=no_patch,
strip_comments=strip_comments, exc_update=exc_update)
srvdecomp = decompile_side(commands, SERVER, use_ff=use_ff, use_srg=use_srg, no_comments=no_comments,
no_reformat=no_reformat, no_renamer=no_renamer, no_patch=no_patch,
strip_comments=strip_comments, exc_update=exc_update)
except CalledProcessError:
# retroguard or other called process error so bail
commands.logger.error('Decompile failed')
sys.exit(1)
if not no_recompile:
if cltdecomp:
try:
updatemd5_side(commands, CLIENT)
except CalledProcessError:
commands.logger.error('Initial client recompile failed, correct source then run updatemd5')
if srvdecomp:
try:
updatemd5_side(commands, SERVER)
except CalledProcessError:
commands.logger.error('Initial server recompile failed, correct source then run updatemd5')
else:
commands.logger.info('!! recompile disabled !!')
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

Binary file not shown.

@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 13:44:42 2011
@author: ProfMobius
@version: 0.1
"""
import csv
import srgshandler
CLIENT = 0
SERVER = 1
def writesrgsfromcsvs(csvclass, csvmethods, csvfields, outsrgs, side, ignore_classes=None):
"""Reads 3 CSVs and output a srgs"""
if ignore_classes is None:
ignore_classes = []
packages = []
classes = []
methods = []
fields = []
# HINT: We are adding the package conversions
packages.append(['.', 'net/minecraft/src'])
packages.append(['net', 'net'])
packages.append(['net/minecraft', 'net/minecraft'])
if side == CLIENT:
packages.append(['net/minecraft/client', 'net/minecraft/client'])
packages.append(['net/minecraft/isom', 'net/minecraft/isom'])
elif side == SERVER:
packages.append(['net/minecraft/server', 'net/minecraft/server'])
else:
raise Exception("Side not recognized : %d" % side)
# HINT: We append the class elements. We also handle the special case of Minecraft, MinecraftApplet, MinecraftServer
with open(csvclass, 'rb') as fh:
csvreader = csv.DictReader(fh)
for row in csvreader:
if int(row['side']) == side:
# HINT : Those checks are here to append the proper packages to notch version of the Minecraft, etc.
# They are needed since we don't have notch package information (lost during recompilation)
# The skip on start is there because of a quirk of the bot updating process
# We use recompiled sources, so the bot catches the Start.class which have been added by Searge.
if row['notch'] in ['Minecraft', 'MinecraftApplet']:
row['notch'] = 'net/minecraft/client/%s' % row['notch']
if row['notch'] in ['IsomPreviewApplet']:
row['notch'] = 'net/minecraft/isom/%s' % row['notch']
if row['notch'] in ['MinecraftServer']:
row['notch'] = 'net/minecraft/server/%s' % row['notch']
if row['name'] in ignore_classes:
continue
classes.append([row['notch'], '%s/%s' % (row['package'], row['name'])])
# HINT: We append the method elements
with open(csvmethods, 'rb') as fh:
csvreader = csv.DictReader(fh)
for row in csvreader:
if int(row['side']) == side:
if row['classnotch'] in ['Minecraft', 'MinecraftApplet']:
row['classnotch'] = 'net/minecraft/client/%s' % row['classnotch']
if row['classnotch'] in ['IsomPreviewApplet']:
row['classnotch'] = 'net/minecraft/isom/%s' % row['classnotch']
if row['classnotch'] in ['MinecraftServer']:
row['classnotch'] = 'net/minecraft/server/%s' % row['classnotch']
if row['classname'] in ignore_classes:
continue
methods.append(['%s/%s %s' % (row['classnotch'], row['notch'], row['notchsig']),
'%s/%s/%s %s' % (row['package'], row['classname'], row['searge'], row['sig'])])
# HINT: We append the field elements
with open(csvfields, 'rb') as fh:
csvreader = csv.DictReader(fh)
for row in csvreader:
if int(row['side']) == side:
if row['classnotch'] in ['Minecraft', 'MinecraftApplet']:
row['classnotch'] = 'net/minecraft/client/%s' % row['classnotch']
if row['classnotch'] in ['IsomPreviewApplet']:
row['classnotch'] = 'net/minecraft/isom/%s' % row['classnotch']
if row['classnotch'] in ['MinecraftServer']:
row['classnotch'] = 'net/minecraft/server/%s' % row['classnotch']
if row['classname'] in ignore_classes:
continue
fields.append(['%s/%s' % (row['classnotch'], row['notch']),
'%s/%s/%s' % (row['package'], row['classname'], row['searge'])])
srgshandler.writesrgs(outsrgs, {'PK': packages, 'CL': classes, 'FD': fields, 'MD': methods})

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 12:50:02 2011
@author: ProfMobius
@version : v0.1
"""
def parse_srg(srg_filename):
"""Reads a SeargeRG file and returns a dictionary of lists for packages, classes, methods and fields"""
srg_types = {'PK:': ['obf_name', 'deobf_name'],
'CL:': ['obf_name', 'deobf_name'],
'FD:': ['obf_name', 'deobf_name'],
'MD:': ['obf_name', 'obf_desc', 'deobf_name', 'deobf_desc']}
parsed_dict = {'PK': [],
'CL': [],
'FD': [],
'MD': []}
def get_parsed_line(keyword, buf):
return dict(zip(srg_types[keyword], [i.strip() for i in buf]))
with open(srg_filename, 'r') as srg_file:
for buf in srg_file:
buf = buf.strip()
if buf == '' or buf[0] == '#':
continue
buf = buf.split()
parsed_dict[buf[0][:2]].append(get_parsed_line(buf[0], buf[1:]))
return parsed_dict
def writesrgs(filename, data):
"""Writes a srgs file based on data. Data is formatted similar to the output of readsrgs (dict of lists)"""
if not 'PK' in data or not 'CL' in data or not 'FD' in data or not 'MD' in data:
raise Exception("Malformed data for writesrgs. Keys should be in ['PK', 'CL', 'FD', 'MD']")
with open(filename, 'w') as srgsout:
# HINT: We write all the entries for a given key in order
for key in ['PK', 'CL', 'FD', 'MD']:
for entry in data[key]:
srgsout.write('%s: %s %s\n' % (key, entry[0], entry[1]))

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
"""
Created on Mon Oct 3 02:10:23 2011
@author: IxxI
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER
from mcp import getchangedsrc_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
getchangedsrc(options.config)
def getchangedsrc(conffile):
try:
commands = Commands(conffile)
getchangedsrc_side(commands, CLIENT)
getchangedsrc_side(commands, SERVER)
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 19 15:04:52 2012
@author: Fesh0r
@version: v1.0
"""
import time
from commands import CLIENT, SIDE_NAME
def decompile_side(commands, side, use_ff=False, use_srg=False, no_comments=False, no_reformat=False, no_renamer=False,
no_patch=False, strip_comments=True, exc_update=False):
if not commands.checkjars(side):
commands.logger.warning('!! Missing %s jar file. Aborting !!', SIDE_NAME[side])
return False
if commands.checksourcedir(side):
commands.logger.warning('!! %s already decompiled. Run cleanup before decompiling again !!', SIDE_NAME[side])
return False
starttime = time.time()
decompiler = 'JAD'
if use_ff:
decompiler = 'fernflower'
commands.logger.info('== Decompiling %s using %s ==', SIDE_NAME[side], decompiler)
commands.logger.info('> Creating SRGs')
commands.createsrgs(side, use_srg=use_srg)
commands.logger.info('> Applying Retroguard')
commands.applyrg(side)
commands.logger.info('> Applying MCInjector')
commands.applyexceptor(side, exc_update=exc_update)
commands.logger.info('> Unpacking jar')
commands.extractjar(side)
commands.logger.info('> Copying classes')
commands.copycls(side)
if use_ff:
commands.logger.info('> Decompiling')
commands.applyff(side)
else:
commands.logger.info('> Applying jadretro')
commands.applyjadretro(side)
commands.logger.info('> Decompiling')
commands.applyjad(side)
commands.logger.info('> Copying sources')
commands.copysrc(side)
if use_ff:
commands.logger.info('> Applying fernflower fixes')
commands.process_fffixes(side)
else:
commands.logger.info('> Applying JAD fixes')
commands.process_jadfixes(side)
if commands.osname == 'osx' and not no_patch:
commands.logger.info('> Applying OSX JAD fixes')
commands.applypatches(side, use_ff=False, use_osx=True)
if not no_patch:
commands.logger.info('> Applying patches')
commands.applypatches(side, use_ff=use_ff)
if strip_comments:
commands.logger.info('> Cleaning comments')
commands.process_comments(side)
else:
commands.logger.warning('!! comment cleaning disabled !!')
else:
commands.logger.warning('!! patches disabled !!')
commands.logger.info('- Done in %.2f seconds', time.time() - starttime)
if not no_reformat:
reformat_side(commands, side)
else:
commands.logger.warning('!! reformating disabled !!')
if not no_renamer:
updatenames_side(commands, side, no_comments=no_comments)
else:
commands.logger.warning('!! renaming disabled !!')
return True
def reformat_side(commands, side):
if not commands.checksourcedir(side):
return False
starttime = time.time()
commands.logger.info('== Reformating %s ==', SIDE_NAME[side])
commands.logger.info('> Cleaning sources')
commands.process_cleanup(side)
if side == CLIENT:
commands.logger.info('> Replacing OpenGL constants')
commands.process_annotate(side)
if commands.has_astyle:
commands.logger.info('> Reformating sources')
commands.applyastyle(side)
else:
commands.logger.warning('!! reformating disabled due to no astyle or config !!')
commands.logger.info('- Done in %.2f seconds', time.time() - starttime)
return True
def updatenames_side(commands, side, no_comments=False):
if not commands.checksourcedir(side):
return False
starttime = time.time()
commands.logger.info('== Updating %s ==', SIDE_NAME[side])
if not no_comments:
if commands.has_doc_csv:
commands.logger.info('> Adding javadoc')
commands.process_javadoc(side)
else:
commands.logger.warning('!! javadoc disabled due to no csvs !!')
else:
commands.logger.warning('!! javadoc disabled !!')
if commands.has_name_csv:
commands.logger.info('> Renaming sources')
commands.process_rename(side)
else:
commands.logger.warning('!! renaming disabled due to no csvs !!')
commands.logger.info('- Done in %.2f seconds', time.time() - starttime)
return True
def recompile_side(commands, side):
if not commands.checksources(side):
commands.logger.warning('!! Can not find %s sources, try decompiling !!', SIDE_NAME[side])
return False
starttime = time.time()
commands.logger.info('== Recompiling %s ==', SIDE_NAME[side])
commands.logger.info('> Cleaning bin')
commands.cleanbindirs(side)
commands.logger.info('> Recompiling')
commands.recompile(side)
commands.logger.info('- Done in %.2f seconds', time.time() - starttime)
return True
def updatemd5_side(commands, side):
recomp = recompile_side(commands, side)
if recomp:
commands.logger.info('> Generating %s md5s', SIDE_NAME[side])
commands.gathermd5s(side)
return True
return False
def reobfuscate_side(commands, side, reobf_all=False):
if not commands.checkmd5s(side):
commands.logger.warning('!! Can not find %s md5s !!', SIDE_NAME[side])
return False
if not commands.checkbins(side):
commands.logger.warning('!! Can not find %s bins, try recompiling !!', SIDE_NAME[side])
return False
starttime = time.time()
commands.logger.info('== Reobfuscating %s ==', SIDE_NAME[side])
commands.logger.info('> Cleaning reobf')
commands.cleanreobfdir(side)
commands.logger.info('> Generating md5s')
commands.gathermd5s(side, True)
commands.logger.info('> Packing jar')
commands.packbin(side)
commands.logger.info('> Reobfuscating jar')
commands.applyrg(side, True)
commands.logger.info('> Extracting modified classes')
commands.unpackreobfclasses(side, reobf_all)
commands.logger.info('- Done in %.2f seconds', time.time() - starttime)
return True
def getchangedsrc_side(commands, side):
if not commands.checkmd5s(side):
commands.logger.warning('!! Can not find %s md5s !!', SIDE_NAME[side])
return False
if not commands.checksources(side):
commands.logger.warning('!! Can not find %s sources !!', SIDE_NAME[side])
return False
commands.logger.info('> Getting changed %s source', SIDE_NAME[side])
commands.gathermd5s(side, True)
commands.unpackmodifiedclasses(side)
return True
def updateids_side(commands, side, no_comments=False):
if not commands.checksourcedir(side):
return False
starttime = time.time()
commands.logger.info('== Updating %s ==', SIDE_NAME[side])
if commands.has_renumber_csv:
commands.logger.info('> Renumbering sources')
commands.process_renumber(side)
else:
commands.logger.warning('!! renumbering disabled due to no csvs !!')
commands.logger.info('- Done in %.2f seconds', time.time() - starttime)
return True

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -0,0 +1,296 @@
import sys
import os
import re
import fnmatch
import shutil
from optparse import OptionParser
def strip_comments(src_dir):
"""Removes all C/C++/Java-style comments from files"""
regexps = {
# Remove C and C++ style comments
'comments': re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.MULTILINE | re.DOTALL),
# Remove trailing whitespace
'trailing': re.compile(r'[ \t]+$', re.MULTILINE),
# Remove repeated blank lines
'newlines': re.compile(r'^\n{2,}', re.MULTILINE),
}
def comment_replacer(match):
part = match.group(0)
if part.startswith('/'):
return ''
else:
return part
for path, _, filelist in os.walk(src_dir, followlinks=True):
for cur_file in fnmatch.filter(filelist, '*.java'):
src_file = os.path.normpath(os.path.join(path, cur_file))
tmp_file = src_file + '.tmp'
with open(src_file, 'r') as fh:
buf = fh.read()
buf = regexps['comments'].sub(comment_replacer, buf)
buf = regexps['trailing'].sub(r'', buf)
buf = regexps['newlines'].sub(r'\n', buf)
with open(tmp_file, 'w') as fh:
fh.write(buf)
shutil.move(tmp_file, src_file)
def src_cleanup(src_dir, fix_imports=True, fix_unicode=False, fix_charval=False, fix_pi=False, fix_round=False):
"""Do lots of random cleanups including stripping comments, trailing whitespace and extra blank lines"""
regexps = {
# Remove extra whitespace at start of file
'header': re.compile(r'^\s+'),
# Remove extra whitespace at end of file
'footer': re.compile(r'\s+$'),
# Remove trailing whitespace
'trailing': re.compile(r'[ \t]+$', re.MULTILINE),
# find package
'package': re.compile(r'^package (?P<package>[\w.]+);$', re.MULTILINE),
# find imports
'import': re.compile(r'^import (?:(?P<package>[\w.]*?)\.)?(?P<class>[\w]+);\n', re.MULTILINE),
# Remove repeated blank lines
'newlines': re.compile(r'^\n{2,}', re.MULTILINE),
# close up blanks in code like:
# {
#
# private
'blockstarts': re.compile(r'(?<={)\s+(?=\n[ \t]*\S)', re.MULTILINE),
# close up blanks in code like:
# }
#
# }
'blockends': re.compile(r'(?<=[;}])\s+(?=\n\s*})', re.MULTILINE),
# Remove GL comments and surrounding whitespace
'gl': re.compile(r'\s*/\*\s*GL_[^*]+\*/\s*'),
# convert unicode character constants back to integers
'unicode': re.compile(r"'\\u([0-9a-fA-F]{4})'"),
# strip out Character.valueof
'charval': re.compile(r"Character\.valueOf\(('.')\)"),
# 1.7976...E+308D to Double.MAX_VALUE
'maxD': re.compile(r'1\.7976[0-9]*[Ee]\+308[Dd]'),
# 3.1415...D to Math.PI
'piD': re.compile(r'3\.1415[0-9]*[Dd]'),
# 3.1415...F to (float)Math.PI
'piF': re.compile(r'3\.1415[0-9]*[Ff]'),
# 6.2831...D to (Math.PI * 2D)
'2piD': re.compile(r'6\.2831[0-9]*[Dd]'),
# 6.2831...F to ((float)Math.PI * 2F)
'2piF': re.compile(r'6\.2831[0-9]*[Ff]'),
# 1.5707...D to (Math.PI / 2D)
'pi2D': re.compile(r'1\.5707[0-9]*[Dd]'),
# 1.5707...F to ((float)Math.PI / 2F)
'pi2F': re.compile(r'1\.5707[0-9]*[Ff]'),
# 4.7123...D to (Math.PI * 3D / 2D)
'3pi2D': re.compile(r'4\.7123[0-9]*[Dd]'),
# 4.7123...F to ((float)Math.PI * 3F / 2F)
'3pi2F': re.compile(r'4\.7123[0-9]*[Ff]'),
# 0.7853...D to (Math.PI / 4D)
'pi4D': re.compile(r'0\.7853[0-9]*[Dd]'),
# 0.7853...F to ((float)Math.PI / 4F)
'pi4F': re.compile(r'0\.7853[0-9]*[Ff]'),
# 0.6283...D to (Math.PI / 5D)
'pi5D': re.compile(r'0\.6283[0-9]*[Dd]'),
# 0.6283...F to ((float)Math.PI / 5F)
'pi5F': re.compile(r'0\.6283[0-9]*[Ff]'),
# 57.295...D to (180D / Math.PI)
'180piD': re.compile(r'57\.295[0-9]*[Dd]'),
# 57.295...F to (180F / (float)Math.PI)
'180piF': re.compile(r'57\.295[0-9]*[Ff]'),
# 0.6981...D to (Math.PI * 2D / 9D)
'2pi9D': re.compile(r'0\.6981[0-9]*[Dd]'),
# 0.6981...F to ((float)Math.PI * 2F / 9F)
'2pi9F': re.compile(r'0\.6981[0-9]*[Ff]'),
# 0.3141...D to (Math.PI / 10D)
'pi10D': re.compile(r'0\.3141[0-9]*[Dd]'),
# 0.3141...F to ((float)Math.PI / 10F)
'pi10F': re.compile(r'0\.3141[0-9]*[Ff]'),
# 1.2566...D to (Math.PI * 2D / 5D)
'2pi5D': re.compile(r'1\.2566[0-9]*[Dd]'),
# 1.2566...F to ((float)Math.PI 2F / 5F)
'2pi5F': re.compile(r'1\.2566[0-9]*[Ff]'),
# 0.21991...D to (Math.PI * 7D / 100D)
'7pi100D': re.compile(r'0\.21991[0-9]*[Dd]'),
# 0.21991...F to ((float)Math.PI * 7F / 100F)
'7pi100F': re.compile(r'0\.21991[0-9]*[Ff]'),
# 5.8119...D to (Math.PI * 185D / 100D)
'185pi100D': re.compile(r'5\.8119[0-9]*[Dd]'),
# 5.8119...F to ((float)Math.PI * 185F / 100F)
'185pi100F': re.compile(r'0\.8119[0-9]*[Ff]'),
# 1.230000... to 1.23
'rounddown': re.compile(r'(?P<full>[0-9]+\.(?P<decimal>[0-9]+?)00000000[0-9]*)(?P<type>[Dd])'),
# 1.239999... to 1.24
'roundup': re.compile(r'(?P<full>[0-9]+\.(?P<decimal>[0-9]+?9)9999999[0-9]*)(?P<type>[Dd])'),
}
def unicode_replacer(match):
value = int(match.group(1), 16)
# work around the replace('\u00a7', '$') call in MinecraftServer and a couple of '\u0000'
if value > 255:
return str(value)
return match.group(0)
def rounddown_match(match):
# hackaround for GL11.glScalef(1.000001F, 1.000001F, 1.000001F) in WorldRenderer
if match.group(0) == '1.000001F':
return match.group(0)
val = float(match.group('full'))
return '%.*f%s' % (len(match.group('decimal')), val, match.group('type'))
def roundup_match(match):
val = float(match.group('full'))
return '%.*f%s' % (len(match.group('decimal')) - 1, val, match.group('type'))
# HINT: We pathwalk the sources
for path, _, filelist in os.walk(src_dir, followlinks=True):
for cur_file in fnmatch.filter(filelist, '*.java'):
src_file = os.path.normpath(os.path.join(path, cur_file))
tmp_file = src_file + '.tmp'
with open(src_file, 'r') as fh:
buf = fh.read()
if fix_imports:
# find the package for the current class
match = regexps['package'].search(buf)
if match:
package = match.group('package')
# if the import is for the same package as current class then delete it
def import_match(match):
if match.group('package') != package:
return match.group(0)
return ''
buf = regexps['import'].sub(import_match, buf)
buf = regexps['header'].sub(r'', buf)
buf = regexps['footer'].sub(r'\n', buf)
buf = regexps['trailing'].sub(r'', buf)
buf = regexps['newlines'].sub(r'\n', buf)
buf = regexps['blockstarts'].sub(r'', buf)
buf = regexps['blockends'].sub(r'', buf)
buf = regexps['gl'].sub(r'', buf)
buf = regexps['maxD'].sub(r'Double.MAX_VALUE', buf)
if fix_unicode:
buf = regexps['unicode'].sub(unicode_replacer, buf)
if fix_charval:
buf = regexps['charval'].sub(r'\1', buf)
if fix_pi:
buf = regexps['piD'].sub(r'Math.PI', buf)
buf = regexps['piF'].sub(r'(float)Math.PI', buf)
buf = regexps['2piD'].sub(r'(Math.PI * 2D)', buf)
buf = regexps['2piF'].sub(r'((float)Math.PI * 2F)', buf)
buf = regexps['pi2D'].sub(r'(Math.PI / 2D)', buf)
buf = regexps['pi2F'].sub(r'((float)Math.PI / 2F)', buf)
buf = regexps['3pi2D'].sub(r'(Math.PI * 3D / 2D)', buf)
buf = regexps['3pi2F'].sub(r'((float)Math.PI * 3F / 2F)', buf)
buf = regexps['pi4D'].sub(r'(Math.PI / 4D)', buf)
buf = regexps['pi4F'].sub(r'((float)Math.PI / 4F)', buf)
buf = regexps['pi5D'].sub(r'(Math.PI / 5D)', buf)
buf = regexps['pi5F'].sub(r'((float)Math.PI / 5F)', buf)
buf = regexps['180piD'].sub(r'(180D / Math.PI)', buf)
buf = regexps['180piF'].sub(r'(180F / (float)Math.PI)', buf)
buf = regexps['2pi9D'].sub(r'(Math.PI * 2D / 9D)', buf)
buf = regexps['2pi9F'].sub(r'((float)Math.PI * 2F / 9F)', buf)
buf = regexps['pi10D'].sub(r'(Math.PI / 10D)', buf)
buf = regexps['pi10F'].sub(r'((float)Math.PI / 10F)', buf)
buf = regexps['2pi5D'].sub(r'(Math.PI * 2D / 5D)', buf)
buf = regexps['2pi5F'].sub(r'((float)Math.PI * 2F / 5F)', buf)
buf = regexps['7pi100D'].sub(r'(Math.PI * 7D / 100D)', buf)
buf = regexps['7pi100F'].sub(r'((float)Math.PI * 7F / 100F)', buf)
buf = regexps['185pi100D'].sub(r'(Math.PI * 185D / 100D)', buf)
buf = regexps['185pi100F'].sub(r'((float)Math.PI * 185F / 100F)', buf)
if fix_round:
buf = regexps['rounddown'].sub(rounddown_match, buf)
buf = regexps['roundup'].sub(roundup_match, buf)
with open(tmp_file, 'w') as fh:
fh.write(buf)
shutil.move(tmp_file, src_file)
def cleanup_src(src_dir, clean_comments=True, clean_src=True, fix_imports=True, fix_unicode=False, fix_charval=False,
fix_pi=False, fix_round=False):
if clean_comments:
strip_comments(src_dir)
if clean_src:
src_cleanup(src_dir, fix_imports=fix_imports, fix_unicode=fix_unicode, fix_charval=fix_charval, fix_pi=fix_pi,
fix_round=fix_round)
def main():
usage = 'usage: %prog [options] src_dir'
version = '%prog 6.0'
parser = OptionParser(version=version, usage=usage)
parser.add_option('-c', '--nocomment', action='store_false', dest='clean_comments', help="don't strip comments",
default=True)
parser.add_option('-s', '--nocleanup', action='store_false', dest='clean_src', help="don't cleanup source",
default=True)
parser.add_option('-i', '--imports', action='store_true', dest='fix_imports', help='cleanup unneeded imports',
default=False)
parser.add_option('-u', '--unicode', action='store_true', dest='fix_unicode',
help='convert unicode character constant to integer', default=False)
parser.add_option('-v', '--charval', action='store_true', dest='fix_charval',
help='convert Character.valueof to constant', default=False)
parser.add_option('-p', '--pi', action='store_true', dest='fix_pi',
help='convert pi constants', default=False)
parser.add_option('-r', '--round', action='store_true', dest='fix_round',
help='round long float and double constants', default=False)
options, args = parser.parse_args()
if len(args) != 1:
print >> sys.stderr, 'src_dir required'
sys.exit(1)
cleanup_src(args[0], clean_comments=options.clean_comments, clean_src=options.clean_src,
fix_imports=options.fix_imports, fix_unicode=options.fix_unicode, fix_charval=options.fix_charval,
fix_pi=options.fix_pi, fix_round=options.fix_round)
if __name__ == '__main__':
main()

Binary file not shown.

@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 19 16:29:03 2012
@author: Fesh0r
@version: v0.1
"""
import sys
import os
import fnmatch
import shutil
import re
from optparse import OptionParser
_MODIFIERS = r'public|protected|private|static|abstract|final|native|synchronized|transient|volatile|strictfp'
_REGEXP = {
# Remove trailing whitespace
'trailing': re.compile(r'[ \t]+$', re.MULTILINE),
# Remove repeated blank lines
'newlines': re.compile(r'^\n{2,}', re.MULTILINE),
'modifiers': re.compile(r'(' + _MODIFIERS + ') '),
'list': re.compile(r', '),
'enum_class': re.compile(r'^(?P<modifiers>(?:(?:' + _MODIFIERS + r') )*)(?P<type>enum) (?P<name>[\w$]+)(?: implements (?P<implements>[\w$.]+(?:, [\w$.]+)*))? \{\n(?P<body>(?:.*?\n)*?)(?P<end>\}\n+)', re.MULTILINE),
'enum_entries': re.compile(r'^ {3}(?P<name>[\w$]+)\("(?P=name)", [0-9]+(?:, (?P<body>.*?))?\)(?P<end>(?:;|,)\n+)', re.MULTILINE),
'empty_super': re.compile(r'^ +super\(\);\n', re.MULTILINE),
# strip trailing 0 from doubles and floats to fix decompile differences on OSX
# 0.0010D => 0.001D
'trailingzero': re.compile(r'(?P<value>[0-9]+\.[0-9]*[1-9])0+(?P<type>[DdFfEe])'),
}
_REGEXP_STR = {
'constructor': r'^ {3}(?P<modifiers>(?:(?:' + _MODIFIERS + r') )*)%s\((?P<parameters>.*?)\)(?: throws (?P<throws>[\w$.]+(?:, [\w$.]+)*))? \{(?:(?P<empty>\}\n+)|(?:(?P<body>\n(?:.*?\n)*?)(?P<end> {3}\}\n+)))',
'enum_values': r'^ {3}// \$FF: synthetic field\n {3}private static final %s\[\] [\w$]+ = new %s\[\]\{.*?\};\n',
}
class Error(Exception):
pass
class ParseError(Error):
pass
def fffix(srcdir):
for path, _, filelist in os.walk(srcdir, followlinks=True):
for cur_file in fnmatch.filter(filelist, '*.java'):
src_file = os.path.normpath(os.path.join(path, cur_file))
_process_file(src_file)
def _process_enum(class_name, class_type, modifiers, implements, body, end):
def _enum_entries_match(match):
entry_body = ''
if match.group('body'):
entry_body = '(' + match.group('body') + ')'
new_entry = ' ' + match.group('name') + entry_body + match.group('end')
return new_entry
body = _REGEXP['enum_entries'].sub(_enum_entries_match, body)
values_regex = re.compile(_REGEXP_STR['enum_values'] % (re.escape(class_name), re.escape(class_name)), re.MULTILINE)
body = values_regex.sub(r'', body)
# process constructors
def constructor_match(match):
modifiers = _REGEXP['modifiers'].findall(match.group('modifiers'))
if match.group('modifiers') and not modifiers:
raise ParseError('no modifiers match in %s \'%s\'' % (match.group('name'), match.group('modifiers')))
parameters = []
if match.group('parameters'):
parameters = _REGEXP['list'].split(match.group('parameters'))
throws = []
if match.group('throws'):
throws = _REGEXP['list'].split(match.group('throws'))
if match.group('empty') is not None:
method_body = ''
method_end = match.group('empty')
else:
method_body = match.group('body')
method_end = match.group('end')
return _process_constructor(class_name, modifiers, parameters, throws, method_body, method_end)
constructor_regex = re.compile(_REGEXP_STR['constructor'] % re.escape(class_name), re.MULTILINE)
body = constructor_regex.sub(constructor_match, body)
# rebuild enum
out = ''
if modifiers:
out += ' '.join(modifiers) + ' '
out += class_type + ' ' + class_name
if implements:
out += ' implements ' + ', '.join(implements)
out += ' {\n' + body + end
return out
def _process_constructor(class_name, modifiers, parameters, throws, body, end):
if len(parameters) >= 2:
if parameters[0].startswith('String ') and parameters[1].startswith('int '):
parameters = parameters[2:]
# empty constructor
if body == '' and len(parameters) == 0:
return ''
else:
raise ParseError('invalid initial parameters in enum %s: %s' % (class_name, str(parameters)))
else:
raise ParseError('not enough parameters in enum %s: %s' % (class_name, str(parameters)))
# rebuild constructor
out = ' '
if modifiers:
out += ' '.join(modifiers) + ' '
out += class_name + '(' + ', '.join(parameters) + ')'
if throws:
out += ' throws ' + ', '.join(throws)
out += ' {' + body + end
return out
def _process_file(src_file):
class_name = os.path.splitext(os.path.basename(src_file))[0]
tmp_file = src_file + '.tmp'
with open(src_file, 'r') as fh:
buf = fh.read()
buf = _REGEXP['trailing'].sub(r'', buf)
def enum_match(match):
if class_name != match.group('name'):
raise ParseError("file name and class name differ: '%s' '%s" % (class_name, match.group('name')))
modifiers = _REGEXP['modifiers'].findall(match.group('modifiers'))
if match.group('modifiers') and not modifiers:
raise ParseError("no modifiers match in %s '%s'" % (match.group('name'), match.group('modifiers')))
implements = []
if match.group('implements'):
implements = _REGEXP['list'].split(match.group('implements'))
return _process_enum(match.group('name'), match.group('type'), modifiers, implements, match.group('body'),
match.group('end'))
buf = _REGEXP['enum_class'].sub(enum_match, buf)
buf = _REGEXP['empty_super'].sub(r'', buf)
buf = _REGEXP['trailingzero'].sub(r'\g<value>\g<type>', buf)
buf = _REGEXP['newlines'].sub(r'\n', buf)
with open(tmp_file, 'w') as fh:
fh.write(buf)
shutil.move(tmp_file, src_file)
def main():
usage = 'usage: %prog [options] src_dir'
version = '%prog 6.0'
parser = OptionParser(version=version, usage=usage)
options, args = parser.parse_args()
if len(args) != 1:
print >> sys.stderr, 'src_dir required'
sys.exit(1)
fffix(args[0])
if __name__ == '__main__':
main()

Binary file not shown.

@ -0,0 +1,399 @@
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 19 16:29:03 2012
@author: Fesh0r
@version: v0.1
"""
import sys
import os
import fnmatch
import shutil
import re
from optparse import OptionParser
_MODIFIERS = r'public|protected|private|static|abstract|final|native|synchronized|transient|volatile|strictfp'
_REGEXP = {
# convert OSX double 1.23456789E-12D to Windows double 1.23456789E-012D
'fltexp': re.compile(r'(?<=[Ee][+-])([0-9]{2})(?=[DdFf])'),
# Remove trailing whitespace
'trailing': re.compile(r'[ \t]+$', re.MULTILINE),
# close up extends, and implements that JAD puts on a seperate line
'extends': re.compile(r'$\n {4}(?=extends|implements)', re.MULTILINE),
# close up throws that JAD puts on a seperate line
'throws': re.compile(r'$\n {8}(?=throws)', re.MULTILINE),
# close up method parameters that have wrapped
'params': re.compile(r'^ {4}(?P<main>\S.*?)(?P<wrapped>(?:\n {12}\S.*?)+)(?P<suffix>(?:\n {4}\{$)|;)', re.MULTILINE),
'params_sub': re.compile(r'\n {12}', re.MULTILINE),
# Remove repeated blank lines
'newlines': re.compile(r'^\n{2,}', re.MULTILINE),
# Rename variables called enum
'rename_enum': re.compile(r'(?<=\W)(enum)(?=\W)'),
'modifiers': re.compile(r'(' + _MODIFIERS + ') '),
'list': re.compile(r', '),
'deindent': re.compile(r'^ {4}(.*$)', re.MULTILINE),
# Class
'class': re.compile(r'^(?P<modifiers>(?:(?:' + _MODIFIERS + r') )*)(?P<type>class|interface|enum) (?P<name>[\w$]+)(?: extends (?P<extends>[\w$.]+(?:, [\w$.]+)*))?(?: implements (?P<implements>[\w$.]+(?:, [\w$.]+)*))?\n\{\n(?P<body>(?:.*?\n)*?)(?P<end>\}\n+)', re.MULTILINE),
# method regex
'method': re.compile(r'^ {4}(?P<modifiers>(?:(?:' + _MODIFIERS + r') )*)(?P<type>(?!' + _MODIFIERS + r')[\w$.[\]]+) (?P<name>[\w$]+)\((?P<parameters>.*?)\)(?: throws (?P<throws>[\w$.]+(?:, [\w$.]+)*))?\n {4}\{\n(?P<body>(?:.*?\n)*?)(?P<end> {4}\}\n+)', re.MULTILINE),
# abstract method regex
'method_abstract': re.compile(r'^ {4}(?P<modifiers>(?:(?:' + _MODIFIERS + r') )*)(?P<type>(?!' + _MODIFIERS + r')[\w$.[\]]+) (?P<name>[\w$]+)\((?P<parameters>.*?)\)(?: throws (?P<throws>[\w$.]+(?:, [\w$.]+)*))?(?P<end>;\n+)', re.MULTILINE),
# move super call to start of method
'fix_super': re.compile(r'(?P<before>(?:.*\n)*)(?P<super> {8}super\((?P<parameters>.*?)\);\n)(?P<after>(?:.*\n)*)', re.MULTILINE),
# remove super call in enum
'enum_super': re.compile(r' {8}super\(\w+, \w+\);\n', re.MULTILINE),
# static block
'static': re.compile(r'^ {4}static\n {4}\{\n(?P<body>(?:.*?\n)*?)(?P<end> {4}\}\n+)', re.MULTILINE),
# field_1234.field_5678 += abc + def;
'str1': re.compile(r'(?P<indent>^ +)new StringBuilder\(\);\n +(?P<dest1>.*?);\n +JVM INSTR dup_x1 ;\n +(?P<dest2>.*?);\n +append\(\);\n +(?P<src1>.*?);\n(:? +append\(\);\n +(?P<src2>.*?);\n)? +append\(\);\n +toString\(\);\n +(?P=dest2);$', re.MULTILINE),
# field_1234[field_5678] += abc + def;
'str2': re.compile(r'(?P<indent>^ +)new StringBuilder\(\);\n +(?P<dest1>.*?);\n +(?P<dest2>.*?);\n +JVM INSTR dup2_x1 ;\n +JVM INSTR aaload ;\n +append\(\);\n +(?P<src1>.*?);\n +append\(\);\n(:? +(?P<src2>.*?);\n +append\(\);\n)? +toString\(\);\n +JVM INSTR aastore ;$', re.MULTILINE),
# if(test) goto _L1; else goto _L2
'if_goto': re.compile(r'(?P<indent>^ +)if(?P<test>\(.*\)) goto (?P<label1>_L[0-9]+); else goto (?P<label2>_L[0-9]+)\n(?P<label3>_L[0-9]+):$', re.MULTILINE),
}
_REGEXP_STR = {
'constructor': r'^ {4}(?P<modifiers>(?:(?:' + _MODIFIERS + r') )*)%s\((?P<parameters>.*?)\)(?: throws (?P<throws>[\w$.]+(?:, [\w$.]+)*))?\n {4}\{\n(?P<body>(?:.*?\n)*?)(?P<end> {4}\}\n+)',
'enum_methods': r'^ {4}public static %s(?:\[\])? value(?:s|Of)\(.*?\)\n {4}\{\n(?:.*?\n)*? {4}\}\n+',
'enum_fields': r'^ {4}(?:public|private) static final %s [\w$.[\]]+;.*\n',
'enum_entries': r'^ {8}(?P<name>[\w$]+) = new %s\("(?P=name)", [0-9]+(?:, (?P<body>.*?))?\);\n+',
'enum_values': r'^ {8}(?P<name>[\w$]+)(?P<body> = \(new %s\[\] \{\n(?:.*\n)*? {8}\}\));\n+',
}
class Error(Exception):
pass
class ParseError(Error):
pass
def jadfix(srcdir):
for path, _, filelist in os.walk(srcdir, followlinks=True):
for cur_file in fnmatch.filter(filelist, '*.java'):
src_file = os.path.normpath(os.path.join(path, cur_file))
_process_file(src_file)
def _process_class(class_name, class_type, modifiers, extends, implements, body, end):
if class_type == 'class':
# if we have an enum class then fix the class declaration
if 'final' in modifiers and 'Enum' in extends:
modifiers.remove('final')
extends.remove('Enum')
class_type = 'enum'
if class_type == 'interface':
# is this an annotation type? still missing too much info for it to actually work
if 'Annotation' in extends:
extends.remove('Annotation')
class_type = '@interface'
if class_type == 'enum':
body = _process_enum(class_name, body)
# process normal methods
def method_match(match):
modifiers = _REGEXP['modifiers'].findall(match.group('modifiers'))
if match.group('modifiers') and not modifiers:
raise ParseError('no modifiers match in %s \'%s\'' % (match.group('name'), match.group('modifiers')))
parameters = []
if match.group('parameters'):
parameters = _REGEXP['list'].split(match.group('parameters'))
throws = []
if match.group('throws'):
throws = _REGEXP['list'].split(match.group('throws'))
return _process_method(class_name, match.group('name'), modifiers, match.group('type'), parameters, throws,
match.group('body'), match.group('end'))
body = _REGEXP['method'].sub(method_match, body)
# process abstract methods
def method_abstract_match(match):
modifiers = _REGEXP['modifiers'].findall(match.group('modifiers'))
if match.group('modifiers') and not modifiers:
raise ParseError('no modifiers match in %s \'%s\'' % (match.group('name'), match.group('modifiers')))
parameters = []
if match.group('parameters'):
parameters = _REGEXP['list'].split(match.group('parameters'))
throws = []
if match.group('throws'):
throws = _REGEXP['list'].split(match.group('throws'))
return _process_method_abstract(class_name, match.group('name'), modifiers, match.group('type'), parameters,
throws, match.group('end'))
body = _REGEXP['method_abstract'].sub(method_abstract_match, body)
# process constructors
def constructor_match(match):
modifiers = _REGEXP['modifiers'].findall(match.group('modifiers'))
if match.group('modifiers') and not modifiers:
raise ParseError('no modifiers match in %s \'%s\'' % (match.group('name'), match.group('modifiers')))
parameters = []
if match.group('parameters'):
parameters = _REGEXP['list'].split(match.group('parameters'))
throws = []
if match.group('throws'):
throws = _REGEXP['list'].split(match.group('throws'))
return _process_constructor(class_type, class_name, modifiers, parameters, throws, match.group('body'),
match.group('end'))
constructor_regex = re.compile(_REGEXP_STR['constructor'] % re.escape(class_name), re.MULTILINE)
body = constructor_regex.sub(constructor_match, body)
# rebuild class
out = ''
if modifiers:
out += ' '.join(modifiers) + ' '
out += class_type + ' ' + class_name
if extends:
out += ' extends ' + ', '.join(extends)
if implements:
out += ' implements ' + ', '.join(implements)
out += '\n{\n' + body + end
return out
def _process_enum(class_name, body):
# remove super call in constructor
body = _REGEXP['enum_super'].sub(r'', body)
# remove values and valueOf methods
methods_regex = re.compile(_REGEXP_STR['enum_methods'] % re.escape(class_name), re.MULTILINE)
body = methods_regex.sub(r'', body)
# remove enum fields and $VALUES
fields_regex = re.compile(_REGEXP_STR['enum_fields'] % re.escape(class_name), re.MULTILINE)
body = fields_regex.sub(r'', body)
# rebuild enum entries from static block
body = _process_enum_static(class_name, body)
return body
def _process_enum_static(class_name, enum_body):
# do we have a static block?
static_match = _REGEXP['static'].search(enum_body)
if not static_match:
return enum_body
body = static_match.group('body')
# for each enum field in the static build up a enum entry
enum_entries = ''
entries = []
def _enum_entries_match(match):
entry_body = ''
if match.group('body'):
entry_body = '(' + match.group('body') + ')'
new_entry = ' ' + match.group('name') + entry_body
new_entry = _REGEXP['deindent'].sub(r'\1', new_entry)
entries.append(new_entry)
return ''
entries_regex = re.compile(_REGEXP_STR['enum_entries'] % re.escape(class_name), re.MULTILINE | re.DOTALL)
body = entries_regex.sub(_enum_entries_match, body)
if entries:
enum_entries = '\n' + ',\n'.join(entries) + ';\n\n'
# remove the $VALUES array from the static block
values_regex = re.compile(_REGEXP_STR['enum_values'] % re.escape(class_name), re.MULTILINE)
body = values_regex.sub('', body)
# add the entries and $VALUES to start of body
enum_body = enum_entries + enum_body
# remove the entries and values from the static block
# and remove the block entirely if now empty
full_static = ''
if body:
full_static = ' static\n {\n' + body + static_match.group('end')
enum_body = _REGEXP['static'].sub(full_static, enum_body)
return enum_body
def _process_method(_class_name, method_name, modifiers, method_type, parameters, throws, body, end):
# kill off the wierd _mthclass$ methods that JAD sticks in for some reason
if method_name == '_mthclass$' and 'static' in modifiers:
return ''
body = _process_string(body)
body = _process_if_goto(body)
# rebuild method
out = ' '
if modifiers:
out += ' '.join(modifiers) + ' '
out += method_type + ' ' + method_name + '(' + ', '.join(parameters) + ')'
if throws:
out += ' throws ' + ', '.join(throws)
out += '\n {\n' + body + end
return out
def _process_method_abstract(_class_name, method_name, modifiers, method_type, parameters, throws, end):
# rebuild method
out = ' '
if modifiers:
out += ' '.join(modifiers) + ' '
out += method_type + ' ' + method_name + '(' + ', '.join(parameters) + ')'
if throws:
out += ' throws ' + ', '.join(throws)
out += end
return out
def _process_constructor(class_type, class_name, modifiers, parameters, throws, body, end):
if class_type == 'enum':
if len(parameters) >= 2:
if parameters[0].startswith('String ') and parameters[1].startswith('int '):
parameters = parameters[2:]
# empty constructor
if body == '' and len(parameters) == 0:
return ''
else:
raise ParseError('invalid initial parameters in enum %s: %s' % (class_name, str(parameters)))
else:
raise ParseError('not enough parameters in enum %s: %s' % (class_name, str(parameters)))
body = _process_string(body)
body = _process_if_goto(body)
# move super calls to start of constructor and remove empty super calls
def super_match(match):
if match.group('parameters'):
return match.group('super') + match.group('before') + match.group('after')
else:
return match.group('before') + match.group('after')
body = _REGEXP['fix_super'].sub(super_match, body)
# rebuild constructor
out = ' '
if modifiers:
out += ' '.join(modifiers) + ' '
out += class_name + '(' + ', '.join(parameters) + ')'
if throws:
out += ' throws ' + ', '.join(throws)
out += '\n {\n' + body + end
return out
def _process_string(body):
# fix up plain string appends
def string1_match(match):
indent = match.group('indent')
src = match.group('src1')
if match.group('src2'):
src = '%s + %s' % (src, match.group('src2'))
dest = match.group('dest2')
if match.group('dest1') != 'this':
dest = '%s.%s' % (match.group('dest1'), dest)
return '%s%s += %s;' % (indent, dest, src)
body = _REGEXP['str1'].sub(string1_match, body)
# fix up string appends to an array
def string2_match(match):
indent = match.group('indent')
src = match.group('src1')
if match.group('src2'):
src = '%s + %s' % (src, match.group('src2'))
dest = '%s[%s]' % (match.group('dest1'), match.group('dest2'))
return '%s%s += %s;' % (indent, dest, src)
body = _REGEXP['str2'].sub(string2_match, body)
return body
def _process_if_goto(body):
def if_goto_match(match):
indent = match.group('indent')
# depending on the following label negate the if test
if match.group('label3') == match.group('label2'):
test = 'if(!%s)' % match.group('test')
comment = '## JADFIX %s %s' % (match.group('label2'), match.group('label1'))
else:
test = 'if%s' % match.group('test')
comment = '## JADFIX %s %s' % (match.group('label1'), match.group('label2'))
label = '%s:' % match.group('label3')
return '%s%s\n%s\n%s' % (indent, test, comment, label)
body = _REGEXP['if_goto'].sub(if_goto_match, body)
return body
def _process_file(src_file):
class_name = os.path.splitext(os.path.basename(src_file))[0]
tmp_file = src_file + '.tmp'
with open(src_file, 'r') as fh:
buf = fh.read()
buf = _REGEXP['fltexp'].sub(r'0\1', buf)
buf = _REGEXP['trailing'].sub(r'', buf)
buf = _REGEXP['extends'].sub(r' ', buf)
buf = _REGEXP['throws'].sub(r' ', buf)
def params_match(match):
body = re.sub(_REGEXP['params_sub'], r' ', match.group('wrapped'))
return ' %s%s%s' % (match.group('main'), body, match.group('suffix'))
buf = _REGEXP['params'].sub(params_match, buf)
buf = _REGEXP['rename_enum'].sub(r'\1_', buf)
def class_match(match):
if class_name != match.group('name'):
raise ParseError("file name and class name differ: '%s' '%s" % (class_name, match.group('name')))
modifiers = _REGEXP['modifiers'].findall(match.group('modifiers'))
if match.group('modifiers') and not modifiers:
raise ParseError("no modifiers match in %s '%s'" % (match.group('name'), match.group('modifiers')))
extends = []
if match.group('extends'):
extends = _REGEXP['list'].split(match.group('extends'))
implements = []
if match.group('implements'):
implements = _REGEXP['list'].split(match.group('implements'))
return _process_class(match.group('name'), match.group('type'), modifiers, extends, implements,
match.group('body'), match.group('end'))
(buf, match_count) = _REGEXP['class'].subn(class_match, buf)
if not match_count:
raise ParseError('no class in %s' % class_name)
buf = _REGEXP['newlines'].sub(r'\n', buf)
with open(tmp_file, 'w') as fh:
fh.write(buf)
shutil.move(tmp_file, src_file)
def main():
usage = 'usage: %prog [options] src_dir'
version = '%prog 6.0'
parser = OptionParser(version=version, usage=usage)
options, args = parser.parse_args()
if len(args) != 1:
print >> sys.stderr, 'src_dir required'
sys.exit(1)
jadfix(args[0])
if __name__ == '__main__':
main()

Binary file not shown.

@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 11:19:07 2012
@author: Fesh0r
@version: v0.1
"""
import sys
import os
import fnmatch
import shutil
import re
from optparse import OptionParser
_REGEXP = {
# Remove trailing whitespace
'trailing': re.compile(r'[ \t]+$', re.MULTILINE),
# close up extends, and implements that JD-GUI puts on a seperate line
'extends': re.compile(r'$\n {2}(?=extends|implements)', re.MULTILINE),
# close up throws that JD-GUI puts on a seperate line
'throws': re.compile(r'$\n {4}(?=throws)', re.MULTILINE),
# Remove repeated blank lines
'newlines': re.compile(r'^\n{2,}', re.MULTILINE),
}
def jdfix(srcdir):
for path, _, filelist in os.walk(srcdir, followlinks=True):
for cur_file in fnmatch.filter(filelist, '*.java'):
src_file = os.path.normpath(os.path.join(path, cur_file))
_process_file(src_file)
def _process_file(src_file):
class_name = os.path.splitext(os.path.basename(src_file))[0]
tmp_file = src_file + '.tmp'
with open(src_file, 'r') as fh:
buf = fh.read()
buf = _REGEXP['trailing'].sub(r'', buf)
buf = _REGEXP['extends'].sub(r' ', buf)
buf = _REGEXP['throws'].sub(r' ', buf)
buf = _REGEXP['newlines'].sub(r'\n', buf)
with open(tmp_file, 'w') as fh:
fh.write(buf)
shutil.move(tmp_file, src_file)
def main():
usage = 'usage: %prog [options] src_dir'
version = '%prog 6.0'
parser = OptionParser(version=version, usage=usage)
options, args = parser.parse_args()
if len(args) != 1:
print >> sys.stderr, 'src_dir required'
sys.exit(1)
jdfix(args[0])
if __name__ == '__main__':
main()

@ -0,0 +1,72 @@
import sys
import os
import shutil
import fnmatch
import re
from optparse import OptionParser
def normaliselines(in_filename, out_filename=None):
in_filename = os.path.normpath(in_filename)
if out_filename is None:
tmp_filename = in_filename + '.tmp'
else:
out_filename = os.path.normpath(out_filename)
tmp_filename = out_filename
dir_name = os.path.dirname(out_filename)
if dir_name:
if not os.path.exists(dir_name):
os.makedirs(dir_name)
regex_ending = re.compile(r'\r?\n')
with open(in_filename, 'rb') as in_file:
with open(tmp_filename, 'wb') as out_file:
buf = in_file.read()
if os.linesep == '\r\n':
buf = regex_ending.sub(r'\r\n', buf)
else:
buf = buf.replace('\r\n', '\n')
out_file.write(buf)
if out_filename is None:
shutil.move(tmp_filename, in_filename)
def normaliselines_dir(in_dirname, out_dirname=None):
in_dirname = os.path.normpath(in_dirname)
if out_dirname is not None:
out_dirname = os.path.normpath(out_dirname)
for path, _, filelist in os.walk(in_dirname, followlinks=True):
sub_dir = os.path.relpath(path, in_dirname)
for cur_file in fnmatch.filter(filelist, '*.java'):
src_file = os.path.normpath(os.path.join(path, cur_file))
if out_dirname is not None:
dest_file = os.path.join(out_dirname, sub_dir, cur_file)
else:
dest_file = None
normaliselines(src_file, dest_file)
def main():
usage = 'usage: %prog [options] src_file|src_dir [dest_file|dest_dir]'
version = '%prog 6.0'
parser = OptionParser(version=version, usage=usage)
options, args = parser.parse_args()
if len(args) == 1:
in_name = args[0]
out_name = None
elif len(args) == 2:
in_name = args[0]
out_name = args[1]
else:
print >> sys.stderr, 'src_file or src_dir required'
sys.exit(1)
if not os.path.exists(in_name):
print >> sys.stderr, 'src_file or src_dir not found'
sys.exit(1)
if os.path.isfile(in_name):
normaliselines(in_name, out_name)
elif os.path.isdir(in_name):
normaliselines_dir(in_name, out_name)
if __name__ == '__main__':
main()

Binary file not shown.

@ -0,0 +1,48 @@
import sys
import os
import shutil
from optparse import OptionParser
def normalisepatch(in_filename, out_filename=None):
in_filename = os.path.normpath(in_filename)
if out_filename is None:
tmp_filename = in_filename + '.tmp'
else:
out_filename = os.path.normpath(out_filename)
tmp_filename = out_filename
dir_name = os.path.dirname(out_filename)
if dir_name:
if not os.path.exists(dir_name):
os.makedirs(dir_name)
with open(in_filename, 'rb') as inpatch:
with open(tmp_filename, 'wb') as outpatch:
for line in inpatch:
line = line.rstrip('\r\n')
if line[:3] in ['+++', '---', 'Onl', 'dif']:
outpatch.write(line.replace('\\', os.sep).replace('/', os.sep) + os.linesep)
else:
outpatch.write(line + os.linesep)
if out_filename is None:
shutil.move(tmp_filename, in_filename)
def main():
usage = 'usage: %prog [options] src_file [dest_file]'
version = '%prog 6.0'
parser = OptionParser(version=version, usage=usage)
options, args = parser.parse_args()
if len(args) == 1:
in_file = args[0]
out_file = None
elif len(args) == 2:
in_file = args[0]
out_file = args[1]
else:
print >> sys.stderr, 'src_file required'
sys.exit(1)
normalisepatch(in_file, out_file)
if __name__ == '__main__':
main()

Binary file not shown.

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:36:26 2011
@author: ProfMobius
@version: v0.1
"""
import os
import logging
def whereis(filename, rootdir):
if not os.path.exists(rootdir):
return []
logging.info('> Searching for %s in %s', filename, rootdir)
results = []
for path, _, filelist in os.walk(rootdir):
if filename in filelist:
results.append(path)
return results

Binary file not shown.

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:54:36 2011
@author: ProfMobius
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER, CalledProcessError
from mcp import recompile_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
recompile(options.config)
def recompile(conffile):
try:
commands = Commands(conffile, verify=True)
try:
recompile_side(commands, CLIENT)
except CalledProcessError:
pass
try:
recompile_side(commands, SERVER)
except CalledProcessError:
pass
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 19 12:34:12 2012
@author: Fesh0r
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER, CalledProcessError
from mcp import reformat_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
reformat(options.config)
def reformat(conffile):
try:
commands = Commands(conffile, verify=True)
try:
reformat_side(commands, CLIENT)
reformat_side(commands, SERVER)
except CalledProcessError:
# astyle failed
commands.logger.error('Reformat failed')
sys.exit(1)
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:54:36 2011
@author: ProfMobius
@version: v1.1
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER
from mcp import reobfuscate_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-a', '--all', action='store_true', dest='reobf_all', help='output all classes', default=False)
parser.add_option('-n', '--nolvt', dest='keep_lvt', action='store_false', help='strip local variable table',
default=True)
parser.add_option('-g', '--generics', dest='keep_generics', action='store_true',
help='preserve generics as well as local variables', default=False)
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
reobfuscate(options.config, options.reobf_all, options.keep_lvt, options.keep_generics)
def reobfuscate(conffile, reobf_all, keep_lvt, keep_generics):
try:
commands = Commands(conffile, verify=True)
if keep_generics:
keep_lvt = True
commands.logger.info('> Creating Retroguard config files')
commands.creatergcfg(reobf=True, keep_lvt=keep_lvt, keep_generics=keep_generics)
reobfuscate_side(commands, CLIENT, reobf_all=reobf_all)
reobfuscate_side(commands, SERVER, reobf_all=reobf_all)
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:54:36 2011
@author: ProfMobius
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
startclient(options.config)
def startclient(conffile):
try:
commands = Commands(conffile)
if not commands.checkbins(CLIENT):
commands.logger.warning('!! Can not find client bins !!')
sys.exit(1)
commands.startclient()
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:54:36 2011
@author: ProfMobius
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, SERVER
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
startserver(options.config)
def startserver(conffile):
try:
commands = Commands(conffile)
if not commands.checkbins(SERVER):
commands.logger.warning('!! Can not find server bins !!')
sys.exit(1)
commands.startserver()
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
"""
Created on Tue Jul 31 12:16:43 2012
@author: Fesh0r
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER
from mcp import updateids_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-f', '--force', action='store_true', dest='force', help='force update', default=False)
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
updateids(options.config, options.force)
def updateids(conffile, force):
try:
commands = Commands(conffile)
if not force:
print 'WARNING:'
print 'The updateids script is unsupported, not recommended, and can break your'
print 'code in hard to detect ways.'
print 'Only use this script if you absolutely know what you are doing, or when a'
print 'MCP team member asks you to do so.'
answer = raw_input('If you really want to update all classes, enter "Yes" ')
if answer.lower() not in ['yes']:
print 'You have not entered "Yes", aborting the update process'
sys.exit(1)
updateids_side(commands, CLIENT)
updateids_side(commands, SERVER)
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:54:36 2011
@author: ProfMobius
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-f', '--force', action='store_true', dest='force', help='force update', default=False)
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
updatemcp(options.config, options.force)
def updatemcp(conffile, force):
try:
commands = Commands(conffile)
commands.logger.info('== Updating MCP ==')
commands.downloadupdates(force)
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
"""
Created on Fri May 22 23:32:36 2011
@author: Searge
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER, CalledProcessError
from mcp import updatemd5_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-f', '--force', action='store_true', dest='force', help='force update', default=False)
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
updatemd5(options.config, options.force)
def updatemd5(conffile, force):
try:
commands = Commands(conffile)
if (commands.checkmd5s(CLIENT) or commands.checkmd5s(SERVER)) and not force:
print 'WARNING:'
print 'The updatemd5 script is unsupported and should only be run in special'
print 'cases, such as if there were compile errors in the last decompile which'
print 'have now been corrected. It will reset the changed status of all classes'
print 'for reobfuscation, and only classes modified afterwards will end up in'
print 'the reobf directory.'
print 'Only use this script if you absolutely know what you are doing, or when a'
print 'MCP team member asks you to do so.'
answer = raw_input('If you really want to update all classes, enter "Yes" ')
if answer.lower() not in ['yes']:
print 'You have not entered "Yes", aborting the update process'
sys.exit(1)
try:
updatemd5_side(commands, CLIENT)
except CalledProcessError:
commands.logger.error('Client recompile failed, correct source then rerun updatemd5')
try:
updatemd5_side(commands, SERVER)
except CalledProcessError:
commands.logger.error('Server recompile failed, correct source then rerun updatemd5')
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 8 16:54:36 2011
@author: Searge
@version: v1.0
"""
import sys
import logging
from optparse import OptionParser
from commands import Commands, CLIENT, SERVER
from mcp import updatenames_side
def main():
parser = OptionParser(version='MCP %s' % Commands.fullversion())
parser.add_option('-f', '--force', action='store_true', dest='force', help='force update', default=False)
parser.add_option('-c', '--config', dest='config', help='additional configuration file')
options, _ = parser.parse_args()
updatenames(options.config, options.force)
def updatenames(conffile, force):
try:
commands = Commands(conffile)
if not force:
print 'WARNING:'
print 'The updatenames script is unsupported, not recommended, and can break your'
print 'code in hard to detect ways.'
print 'Only use this script if you absolutely know what you are doing, or when a'
print 'MCP team member asks you to do so.'
answer = raw_input('If you really want to update all classes, enter "Yes" ')
if answer.lower() not in ['yes']:
print 'You have not entered "Yes", aborting the update process'
sys.exit(1)
updatenames_side(commands, CLIENT)
updatenames_side(commands, SERVER)
except Exception: # pylint: disable-msg=W0703
logging.exception('FATAL ERROR')
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,24 @@
import java.io.File;
import java.lang.reflect.Field;
import net.minecraft.client.Minecraft;
public class Start
{
public static void main(String[] args)
{
try
{
Field f = Minecraft.class.getDeclaredField("minecraftDir");
Field.setAccessible(new Field[] { f }, true);
f.set(null, new File("."));
}
catch (Exception e)
{
e.printStackTrace();
return;
}
Minecraft.main(args);
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save