Skip to content

Commit

Permalink
Jar prepatcher created. Messy, but what do you expect on new year's?
Browse files Browse the repository at this point in the history
  • Loading branch information
N3X15 committed Jan 1, 2011
1 parent d9d8cf4 commit dec7420
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 37 deletions.
37 changes: 30 additions & 7 deletions src/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.*;
import java.util.Collections;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.logging.*;
import java.net.*;
import java.lang.reflect.*;
Expand All @@ -39,10 +43,9 @@ public class Main {
static Logger l = Logger.getLogger("Minecraft");

protected static ClassPool mcClassPool;
protected static ClassLoader mcClassLoader;
protected static PatchingClassLoader mcClassLoader;

public static void main(String[] arguments) throws Throwable {
Patches.initialize();

l.info("Stage-1 Boot Sequence Start");
l.info(" + Setting up SmartReflector classmappings...");
Expand All @@ -56,7 +59,7 @@ public static void main(String[] arguments) throws Throwable {

mcClassLoader = new PatchingClassLoader(
new URL[] {
mcServerJarURL
mcServerJarURL//, mcServerJarURLNew
}, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(mcClassLoader);
} catch (Exception e) {
Expand All @@ -65,13 +68,33 @@ public static void main(String[] arguments) throws Throwable {
}


l.info("Stage-2 Boot Sequence Start");
l.warning(" ! Stage-2 class patching setup not currently implemented.");
l.info("Stage 2: Patching server jar...");
l.info(" + Loading patches...");
Patches.initialize();
l.info(" + Creating minecraft_server.jar.new...");
File newMCServerJar = new File(String.format("lib/minecraft_server.jar.new"));
if(!newMCServerJar.exists())
{
newMCServerJar.mkdirs();
JarFile inJar = new JarFile("lib/minecraft_server.jar");
JarOutputStream outJar = new JarOutputStream(new FileOutputStream(newMCServerJar));
for(JarEntry e : Collections.list(inJar.entries())) {
if(e.getName().endsWith(".class")) {
// Strip off the .class
String className = e.getName().substring(0, e.getName().indexOf('.'));
Patches.Patch(className, outJar);
}
}
outJar.close();
}
l.info(" + Updating Classpath...");
mcClassLoader.addURI(newMCServerJar.toURI());

l.info("Stage-3 Boot Sequence Start");
l.info("Stage 3: Booting server!");
try {
// Bootstrap...
Class<?> mcBootClass =
Class.forName("net.minecraft.server.MinecraftServer", true, mcClassLoader);
Class.forName("net.minecraft.server.MinecraftServer", true, mcClassLoader);
Method mainMethod = mcBootClass.getMethod("main", String[].class);
mainMethod.invoke(null, new Object[] {arguments});
} catch (Exception e) {
Expand Down
59 changes: 30 additions & 29 deletions src/org/middlecraft/patcher/Patches.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.middlecraft.patcher;
import java.awt.List;
import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.logging.Logger;

import javassist.*;
import javassist.bytecode.ClassFile;

import org.middlecraft.patcher.reflect.*;
import org.middlecraft.server.*;
import org.middlecraft.server.SmartReflector;

/**
* Terribad class patcher.
Expand All @@ -45,14 +45,14 @@
public class Patches {
private static ClassPool pool=null;
private static Logger l = Logger.getLogger("Minecraft");

static Map<String,CtClass> patches = new HashMap<String,CtClass>();

public static void initialize() throws NotFoundException {
try {
pool=ClassPool.getDefault();
pool.appendClassPath("lib/*");
JarFile jar = new JarFile("bin/patches.jar");
JarFile jar = new JarFile("patches.jar");
for(JarEntry e : Collections.list(jar.entries())) {
if(e.getName().endsWith(".class")) {
patches.put(e.getName().replace(".class", ""),pool.makeClass(jar.getInputStream(e)));
Expand All @@ -63,45 +63,50 @@ public static void initialize() throws NotFoundException {
e.printStackTrace();
}
}

/**
* Patches the named class. Temporary measure until patching setup is complete.
* @param className Name of the victim class (obfuscated)
* @throws CannotCompileException
* @throws IOException
* @throws NotFoundException
*/
public static void Patch(String className) throws NotFoundException, IOException, CannotCompileException {
public static void Patch(String className, JarOutputStream outJar) throws NotFoundException, IOException, CannotCompileException {

/* Load our victim class. If possible. */
CtClass cc=null;
try {
cc = pool.get(className);
} catch(NotFoundException e) {
e.printStackTrace();
System.exit(1);
return;
}
/* NOT MC package? BAIL OUT. */
if(!isMinecraftPackage(cc.getPackageName())) return;

if(!isMinecraftPackage(cc.getPackageName())) {
//l.info(cc.getPackageName()+" is not the MC package.");
return;
}

//l.info(String.format("Processing [%s] %s...",cc.getPackageName(),className));

/* Check if superclass mappings are correct. */
SmartReflector.updateSuperclassInfo(cc);

/* Deobfuscate class name, assuming MCP mappings are installed... :/ */
String newClassName=SmartReflector.getNewClassName(className);
if(!newClassName.equals(className))
if(newClassName.equals(className))
{
cc.setName(newClassName);
l.fine(String.format("Renaming class %s to %s.",className,newClassName));
className=newClassName;
newClassName=className+"2"; // To ensure we get fresh classes.
}

cc.setName(newClassName);
l.info(String.format("Renaming class %s to %s.",className,newClassName));
className=newClassName;

/* Grab our patch, if possible, and load it. */
CtClass patch=patches.get("Patched"+className);
if(patch==null) return;

l.info("Patching "+className+"...");
try {
/* For each method in the patch, add or replace as needed. */
Expand Down Expand Up @@ -157,7 +162,12 @@ public static void Patch(String className) throws NotFoundException, IOException
return;
}
// Save.
cc.writeFile();
if(outJar==null)
cc.writeFile("classes/");
else {
ClassFile cf = cc.getClassFile();
cf.write(new DataOutputStream(outJar));
}
}
/**
* Determine if the named package is one of the Minecraft packages.
Expand All @@ -167,14 +177,5 @@ public static void Patch(String className) throws NotFoundException, IOException
private static boolean isMinecraftPackage(String packageName) {
return packageName==null || packageName.equals("") || packageName.equals("net.minecraft.server");
}
/**
* Get a patch's filename.
* @param className
* @return
*/
private static String getPatchFilename(String className) {
// TODO Use patches-src or whatever.
return String.format("data/server/%s/patches/Patched%s.java", SmartReflector.serverVersion, className);
}


}
13 changes: 12 additions & 1 deletion src/org/middlecraft/patcher/PatchingClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import java.util.*;
import java.util.logging.*;

import org.middlecraft.server.SmartReflector;

/**
* A custom ClassLoader that patches certain classes as they are loaded.
*
Expand All @@ -50,6 +52,14 @@
public class PatchingClassLoader extends URLClassLoader {
protected static final Logger l = Logger.getLogger("Minecraft");

public void addURI(URI uri) {
try {
this.addURL(uri.toURL());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Stores loaded and generated classes for faster lookup.
*/
Expand Down Expand Up @@ -113,7 +123,8 @@ protected synchronized Class<?> loadClass(String className, boolean resolve)
} else {
//l.info(String.format("[%s] Loaded via Patcher", className));
try {
Patches.Patch(className);
Patches.Patch(className, null);
className=SmartReflector.getNewClassName(className);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Expand Down

0 comments on commit dec7420

Please sign in to comment.