Added support for old Alpha versions

This commit is contained in:
Nathan Adams 2013-08-01 15:01:46 +02:00
parent 326d47f0ce
commit bb61fb3f6d
6 changed files with 231 additions and 21 deletions

View file

@ -10,7 +10,7 @@ repositories {
group = 'net.minecraft'
archivesBaseName = 'launchwrapper'
version = '1.4'
version = '1.5'
dependencies {
compile 'net.sf.jopt-simple:jopt-simple:4.5'

View file

@ -0,0 +1,33 @@
package net.minecraft.launchwrapper;
import java.io.File;
import java.util.List;
public class AlphaVanillaTweaker implements ITweaker {
public static File gameDir;
public static File assetsDir;
private List<String> args;
@Override
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = args;
AlphaVanillaTweaker.gameDir = gameDir;
AlphaVanillaTweaker.assetsDir = assetsDir;
}
@Override
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
classLoader.registerTransformer("net.minecraft.launchwrapper.injector.AlphaVanillaTweakInjector");
}
@Override
public String getLaunchTarget() {
return "net.minecraft.launchwrapper.injector.AlphaVanillaTweakInjector";
}
@Override
public String[] getLaunchArguments() {
return args.toArray(new String[args.size()]);
}
}

View file

@ -18,7 +18,7 @@ public class Launch {
new Launch().launch(args);
}
private final LaunchClassLoader classLoader;
public static LaunchClassLoader classLoader;
private Launch() {
final URLClassLoader ucl = (URLClassLoader) getClass().getClassLoader();

View file

@ -35,8 +35,8 @@ public class LaunchClassLoader extends URLClassLoader {
private static final String[] RESERVED_NAMES = {"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"};
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("legacy.debugClassLoading", "false"));
private static final boolean DEBUG_FINER = DEBUG && Boolean.parseBoolean(System.getProperty("legacy.debugClassLoadingFiner", "false"));
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("legacy.debugClassLoading", "false")) || true;
private static final boolean DEBUG_FINER = DEBUG && Boolean.parseBoolean(System.getProperty("legacy.debugClassLoadingFiner", "false")) || true;
private static final boolean DEBUG_SAVE = DEBUG && Boolean.parseBoolean(System.getProperty("legacy.debugClassLoadingSave", "false"));
private static File tempFolder = null;

View file

@ -0,0 +1,178 @@
package net.minecraft.launchwrapper.injector;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.VanillaTweaker;
import org.lwjgl.opengl.Display;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.applet.Applet;
import java.applet.AppletStub;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.List;
import static org.objectweb.asm.Opcodes.*;
public class AlphaVanillaTweakInjector implements IClassTransformer {
private static String minecraftClass;
private static String minecraftField;
public AlphaVanillaTweakInjector() {
}
@Override
public byte[] transform(final String name, final String transformedName, final byte[] bytes) {
return bytes;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = getaClass("net.minecraft.client.MinecraftApplet");
System.out.println("AlphaVanillaTweakInjector.class.getClassLoader() = " + AlphaVanillaTweakInjector.class.getClassLoader());
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
for (Field field : clazz.getDeclaredFields()) {
String name = field.getType().getName();
if (!name.contains(".")) {
System.out.println("Found likely Minecraft candidate: " + field);
Field fileField = getWorkingDirField(name);
if (fileField != null) {
System.out.println("Found File, changing to " + Launch.minecraftHome);
fileField.setAccessible(true);
fileField.set(null, Launch.minecraftHome);
break;
}
}
}
startMinecraft((Applet) object, args);
}
private static void startMinecraft(final Applet applet, String[] args) {
final Map<String, String> params = new HashMap<String, String>();
// Extract params
String name = "Player" + System.currentTimeMillis() % 1000;
if (args.length > 0) name = args[0];
String sessionId = "-";
if (args.length > 1) sessionId = args[1];
params.put("username", name);
params.put("sessionid", sessionId);
final Frame launcherFrameFake = new Frame();
launcherFrameFake.setTitle("Minecraft");
launcherFrameFake.setBackground(Color.BLACK);
final JPanel panel = new JPanel();
launcherFrameFake.setLayout(new BorderLayout());
panel.setPreferredSize(new Dimension(854, 480));
launcherFrameFake.add(panel, BorderLayout.CENTER);
launcherFrameFake.pack();
launcherFrameFake.setLocationRelativeTo(null);
launcherFrameFake.setVisible(true);
launcherFrameFake.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(1);
}
});
class LauncherFake extends Applet implements AppletStub {
public void appletResize(int width, int height) {
// Actually empty as well
}
@Override
public boolean isActive() {
return true;
}
@Override
public URL getDocumentBase() {
try {
return new URL("http://www.minecraft.net/game/");
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
@Override
public String getParameter(String paramName) {
if (params.containsKey(paramName)) {
return params.get(paramName);
}
System.err.println("Client asked for parameter: " + paramName);
return null;
}
}
final LauncherFake fakeLauncher = new LauncherFake();
applet.setStub(fakeLauncher);
fakeLauncher.setLayout(new BorderLayout());
fakeLauncher.add(applet, BorderLayout.CENTER);
fakeLauncher.validate();
launcherFrameFake.removeAll();
launcherFrameFake.setLayout(new BorderLayout());
launcherFrameFake.add(fakeLauncher, BorderLayout.CENTER);
launcherFrameFake.validate();
applet.init();
applet.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
applet.stop();
}
});
VanillaTweakInjector.loadIconsOnFrames();
}
private static Class<?> getaClass(String name) throws ClassNotFoundException {
return Launch.classLoader.findClass(name);
}
private static Field getWorkingDirField(String name) throws ClassNotFoundException {
Class<?> clazz = getaClass(name);
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().getName().equals("java.io.File")) {
return field;
}
}
return null;
}
}

View file

@ -10,7 +10,6 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
@ -64,25 +63,21 @@ public class VanillaTweakInjector implements IClassTransformer {
}
// Prepare our injection code
final MethodNode methodNode = new MethodNode();
final MethodNode injectedMethod = new MethodNode();
final Label label = new Label();
methodNode.visitLabel(label);
methodNode.visitLineNumber(9001, label); // Linenumber which shows up in the stacktrace
injectedMethod.visitLabel(label);
injectedMethod.visitLineNumber(9001, label); // Linenumber which shows up in the stacktrace
// Call the method below
methodNode.visitMethodInsn(INVOKESTATIC, "net/minecraft/launchwrapper/injector/VanillaTweakInjector", "inject", "()Ljava/io/File;");
injectedMethod.visitMethodInsn(INVOKESTATIC, "net/minecraft/launchwrapper/injector/VanillaTweakInjector", "inject", "()Ljava/io/File;");
// Store the result in the workDir variable.
methodNode.visitFieldInsn(PUTSTATIC, "net/minecraft/client/Minecraft", workDirNode.name, "Ljava/io/File;");
injectedMethod.visitFieldInsn(PUTSTATIC, "net/minecraft/client/Minecraft", workDirNode.name, "Ljava/io/File;");
// Find the injection point and insert our code
final ListIterator<AbstractInsnNode> iterator = mainMethod.instructions.iterator();
while (iterator.hasNext()) {
final AbstractInsnNode insn = iterator.next();
if (insn.getOpcode() == INVOKEVIRTUAL) {
final MethodInsnNode mins = (MethodInsnNode) insn;
if (mins.owner.equals("java/awt/Frame") && mins.name.equals("validate")) {
mainMethod.instructions.insert(insn, methodNode.instructions);
break;
}
if (insn.getOpcode() == RETURN) {
mainMethod.instructions.insertBefore(insn, injectedMethod.instructions);
}
}
@ -96,8 +91,16 @@ public class VanillaTweakInjector implements IClassTransformer {
System.out.println("Turning of ImageIO disk-caching");
ImageIO.setUseCache(false);
// Load icon from disk
loadIconsOnFrames();
// Set the workdir, return value will get assigned
System.out.println("Setting gameDir to:" + VanillaTweaker.gameDir);
return VanillaTweaker.gameDir;
}
public static void loadIconsOnFrames() {
try {
// Load icon from disk
final File smallIcon = new File(VanillaTweaker.assetsDir, "icons/icon_16x16.png");
final File bigIcon = new File(VanillaTweaker.assetsDir, "icons/icon_32x32.png");
System.out.println("Loading current icons for window from: " + smallIcon + " and " + bigIcon);
@ -121,10 +124,6 @@ public class VanillaTweakInjector implements IClassTransformer {
} catch (IOException e) {
e.printStackTrace();
}
// Set the workdir, return value will get assigned
System.out.println("Setting gameDir to:" + VanillaTweaker.gameDir);
return VanillaTweaker.gameDir;
}
private static ByteBuffer loadIcon(final File iconFile) throws IOException {