summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcflip <cflip@cflip.net>2023-08-24 08:44:43 -0600
committercflip <cflip@cflip.net>2023-08-24 08:44:54 -0600
commit5a7d6a1d7efb249fe3360330704e8ae647ae3a8f (patch)
treea00e1965cc5a9788e4229c9ee87f736bc5b6bc71 /src
Import decompiled source from 2010 launcher jar
Diffstat (limited to 'src')
-rw-r--r--src/net/minecraft/GameUpdater.java707
-rw-r--r--src/net/minecraft/Launcher.java218
-rw-r--r--src/net/minecraft/LauncherFrame.java140
-rw-r--r--src/net/minecraft/LoginForm.java380
-rw-r--r--src/net/minecraft/MinecraftLauncher.java40
-rw-r--r--src/net/minecraft/Util.java104
-rw-r--r--src/net/minecraft/dirt.pngbin0 -> 360 bytes
-rw-r--r--src/net/minecraft/favicon.pngbin0 -> 1374 bytes
8 files changed, 1589 insertions, 0 deletions
diff --git a/src/net/minecraft/GameUpdater.java b/src/net/minecraft/GameUpdater.java
new file mode 100644
index 0000000..1fb7f50
--- /dev/null
+++ b/src/net/minecraft/GameUpdater.java
@@ -0,0 +1,707 @@
+package net.minecraft;
+
+import java.applet.Applet;
+import java.io.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.*;
+import java.security.*;
+import java.security.cert.Certificate;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Pack200;
+
+
+public class GameUpdater implements Runnable {
+ public static final int STATE_INIT = 1;
+ public static final int STATE_DETERMINING_PACKAGES = 2;
+ public static final int STATE_CHECKING_CACHE = 3;
+ public static final int STATE_DOWNLOADING = 4;
+ public static final int STATE_EXTRACTING_PACKAGES = 5;
+ public static final int STATE_UPDATING_CLASSPATH = 6;
+ public static final int STATE_SWITCHING_APPLET = 7;
+ public static final int STATE_INITIALIZE_REAL_APPLET = 8;
+ public static final int STATE_START_REAL_APPLET = 9;
+ public static final int STATE_DONE = 10;
+ public int percentage;
+ public int currentSizeDownload;
+ public int totalSizeDownload;
+ public int currentSizeExtract;
+ public int totalSizeExtract;
+ protected URL[] urlList;
+ private static ClassLoader classLoader;
+ protected Thread loaderThread;
+ protected Thread animationThread;
+ public boolean fatalError;
+ public String fatalErrorDescription;
+ protected String subtaskMessage = "";
+ protected int state = 1;
+
+ protected boolean lzmaSupported = false;
+
+ protected boolean pack200Supported = false;
+ protected String[] genericErrorMessage = new String[]{"An error occured while loading the applet.", "Please contact support to resolve this issue.", "<placeholder for error message>"};
+
+ protected boolean certificateRefused;
+
+ protected String[] certificateRefusedMessage = new String[]{"Permissions for Applet Refused.", "Please accept the permissions dialog to allow", "the applet to continue the loading process."};
+
+ protected static boolean natives_loaded = false;
+ private final String latestVersion;
+ private final String mainGameUrl;
+
+ public GameUpdater(String latestVersion, String mainGameUrl) {
+ this.latestVersion = latestVersion;
+ this.mainGameUrl = mainGameUrl;
+ }
+
+ public void init() {
+ this.state = 1;
+
+ try {
+ Class.forName("LZMA.LzmaInputStream");
+ this.lzmaSupported = true;
+ } catch (Throwable throwable) {
+ }
+
+
+ try {
+ Pack200.class.getSimpleName();
+ this.pack200Supported = true;
+ } catch (Throwable throwable) {
+ }
+ }
+
+
+ private String generateStacktrace(Exception exception) {
+ Writer result = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(result);
+ exception.printStackTrace(printWriter);
+ return result.toString();
+ }
+
+
+ protected String getDescriptionForState() {
+ switch (this.state) {
+ case 1:
+ return "Initializing loader";
+ case 2:
+ return "Determining packages to load";
+ case 3:
+ return "Checking cache for existing files";
+ case 4:
+ return "Downloading packages";
+ case 5:
+ return "Extracting downloaded packages";
+ case 6:
+ return "Updating classpath";
+ case 7:
+ return "Switching applet";
+ case 8:
+ return "Initializing real applet";
+ case 9:
+ return "Starting real applet";
+ case 10:
+ return "Done loading";
+ }
+ return "unknown state";
+ }
+
+
+ protected String trimExtensionByCapabilities(String file) {
+ if (!this.pack200Supported) {
+ file = file.replaceAll(".pack", "");
+ }
+
+ if (!this.lzmaSupported) {
+ file = file.replaceAll(".lzma", "");
+ }
+ return file;
+ }
+
+ protected void loadJarURLs() throws Exception {
+ this.state = 2;
+ String jarList = "lwjgl.jar, jinput.jar, lwjgl_util.jar, " + this.mainGameUrl;
+ jarList = trimExtensionByCapabilities(jarList);
+
+ StringTokenizer jar = new StringTokenizer(jarList, ", ");
+ int jarCount = jar.countTokens() + 1;
+
+ this.urlList = new URL[jarCount];
+
+ URL path = new URL("http://s3.amazonaws.com/MinecraftDownload/");
+
+ for (int i = 0; i < jarCount - 1; i++) {
+ this.urlList[i] = new URL(path, jar.nextToken());
+ }
+
+ String osName = System.getProperty("os.name");
+ String nativeJar = null;
+
+ if (osName.startsWith("Win")) {
+ nativeJar = "windows_natives.jar.lzma";
+ } else if (osName.startsWith("Linux")) {
+ nativeJar = "linux_natives.jar.lzma";
+ } else if (osName.startsWith("Mac")) {
+ nativeJar = "macosx_natives.jar.lzma";
+ } else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
+ nativeJar = "solaris_natives.jar.lzma";
+ } else {
+ fatalErrorOccured("OS (" + osName + ") not supported", null);
+ }
+
+ if (nativeJar == null) {
+ fatalErrorOccured("no lwjgl natives files found", null);
+ } else {
+ nativeJar = trimExtensionByCapabilities(nativeJar);
+ this.urlList[jarCount - 1] = new URL(path, nativeJar);
+ }
+ }
+
+
+ public void run() {
+ init();
+ this.state = 3;
+
+ this.percentage = 5;
+
+ try {
+ loadJarURLs();
+
+ String path = AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
+ public Object run() throws Exception {
+ return Util.getWorkingDirectory() + File.separator + "bin" + File.separator;
+ }
+ });
+
+ File dir = new File(path);
+
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+
+ if (this.latestVersion != null) {
+ File versionFile = new File(dir, "version");
+
+ boolean cacheAvailable = false;
+ if (versionFile.exists() && (
+ this.latestVersion.equals("-1") || this.latestVersion.equals(readVersionFile(versionFile)))) {
+ cacheAvailable = true;
+ this.percentage = 90;
+ }
+
+
+ if (!cacheAvailable) {
+ downloadJars(path);
+ extractJars(path);
+ extractNatives(path);
+
+ if (this.latestVersion != null) {
+ this.percentage = 90;
+ writeVersionFile(versionFile, this.latestVersion);
+ }
+ }
+ }
+
+ updateClassPath(dir);
+ this.state = 10;
+ } catch (AccessControlException ace) {
+ fatalErrorOccured(ace.getMessage(), ace);
+ this.certificateRefused = true;
+ } catch (Exception e) {
+ fatalErrorOccured(e.getMessage(), e);
+ } finally {
+ this.loaderThread = null;
+ }
+ }
+
+ protected String readVersionFile(File file) throws Exception {
+ DataInputStream dis = new DataInputStream(new FileInputStream(file));
+ String version = dis.readUTF();
+ dis.close();
+ return version;
+ }
+
+ protected void writeVersionFile(File file, String version) throws Exception {
+ DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
+ dos.writeUTF(version);
+ dos.close();
+ }
+
+
+ protected void updateClassPath(File dir) throws Exception {
+ this.state = 6;
+
+ this.percentage = 95;
+
+ URL[] urls = new URL[this.urlList.length];
+ for (int i = 0; i < this.urlList.length; i++) {
+ urls[i] = (new File(dir, getJarName(this.urlList[i]))).toURI().toURL();
+ }
+
+ if (classLoader == null) {
+ classLoader = new URLClassLoader(urls) {
+ protected PermissionCollection getPermissions(CodeSource codesource) {
+ PermissionCollection perms = null;
+
+
+ try {
+ Method method = SecureClassLoader.class.getDeclaredMethod("getPermissions", CodeSource.class);
+ method.setAccessible(true);
+ perms = (PermissionCollection) method.invoke(getClass().getClassLoader(), new Object[]{codesource});
+
+ String host = "www.minecraft.net";
+
+ if (host != null && host.length() > 0) {
+ perms.add(new SocketPermission(host, "connect,accept"));
+ } else {
+ codesource.getLocation().getProtocol().equals("file");
+ }
+
+
+ perms.add(new FilePermission("<<ALL FILES>>", "read"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return perms;
+ }
+ };
+ }
+
+ String path = dir.getAbsolutePath();
+ if (!path.endsWith(File.separator)) path = path + File.separator;
+ unloadNatives(path);
+
+ System.setProperty("org.lwjgl.librarypath", path + "natives");
+ System.setProperty("net.java.games.input.librarypath", path + "natives");
+
+ natives_loaded = true;
+ }
+
+
+ private void unloadNatives(String nativePath) {
+ if (!natives_loaded) {
+ return;
+ }
+
+ try {
+ Field field = ClassLoader.class.getDeclaredField("loadedLibraryNames");
+ field.setAccessible(true);
+ Vector<String> libs = (Vector<String>) field.get(getClass().getClassLoader());
+
+ String path = (new File(nativePath)).getCanonicalPath();
+
+ for (int i = 0; i < libs.size(); i++) {
+ String s = libs.get(i);
+
+ if (s.startsWith(path)) {
+ libs.remove(i);
+ i--;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public Applet createApplet() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ Class<Applet> appletClass = (Class) classLoader.loadClass("net.minecraft.client.MinecraftApplet");
+ return appletClass.newInstance();
+ }
+
+
+ protected void downloadJars(String path) throws Exception {
+ this.state = 4;
+
+
+ int[] fileSizes = new int[this.urlList.length];
+
+
+ for (int i = 0; i < this.urlList.length; i++) {
+ System.out.println(this.urlList[i]);
+ URLConnection urlconnection = this.urlList[i].openConnection();
+ urlconnection.setDefaultUseCaches(false);
+ if (urlconnection instanceof HttpURLConnection) {
+ ((HttpURLConnection) urlconnection).setRequestMethod("HEAD");
+ }
+ fileSizes[i] = urlconnection.getContentLength();
+ this.totalSizeDownload += fileSizes[i];
+ }
+
+ int initialPercentage = this.percentage = 10;
+
+
+ byte[] buffer = new byte[65536];
+ for (int j = 0; j < this.urlList.length; j++) {
+
+ int unsuccessfulAttempts = 0;
+ int maxUnsuccessfulAttempts = 3;
+ boolean downloadFile = true;
+
+
+ while (downloadFile) {
+ downloadFile = false;
+
+ URLConnection urlconnection = this.urlList[j].openConnection();
+
+ if (urlconnection instanceof HttpURLConnection) {
+ urlconnection.setRequestProperty("Cache-Control", "no-cache");
+ urlconnection.connect();
+ }
+
+ String currentFile = getFileName(this.urlList[j]);
+ InputStream inputstream = getJarInputStream(currentFile, urlconnection);
+ FileOutputStream fos = new FileOutputStream(path + currentFile);
+
+
+ long downloadStartTime = System.currentTimeMillis();
+ int downloadedAmount = 0;
+ int fileSize = 0;
+ String downloadSpeedMessage = "";
+ int bufferSize;
+ while ((bufferSize = inputstream.read(buffer, 0, buffer.length)) != -1) {
+ fos.write(buffer, 0, bufferSize);
+ this.currentSizeDownload += bufferSize;
+ fileSize += bufferSize;
+ this.percentage = initialPercentage + this.currentSizeDownload * 45 / this.totalSizeDownload;
+ this.subtaskMessage = "Retrieving: " + currentFile + " " + (this.currentSizeDownload * 100 / this.totalSizeDownload) + "%";
+
+ downloadedAmount += bufferSize;
+ long timeLapse = System.currentTimeMillis() - downloadStartTime;
+
+ if (timeLapse >= 1000L) {
+
+ float downloadSpeed = downloadedAmount / (float) timeLapse;
+
+ downloadSpeed = (int) (downloadSpeed * 100.0F) / 100.0F;
+
+ downloadSpeedMessage = " @ " + downloadSpeed + " KB/sec";
+
+ downloadedAmount = 0;
+
+ downloadStartTime += 1000L;
+ }
+
+ this.subtaskMessage = this.subtaskMessage + downloadSpeedMessage;
+ }
+
+ inputstream.close();
+ fos.close();
+
+
+ if (urlconnection instanceof HttpURLConnection &&
+ fileSize != fileSizes[j]) {
+ if (fileSizes[j] > 0) {
+
+
+ unsuccessfulAttempts++;
+
+ if (unsuccessfulAttempts < maxUnsuccessfulAttempts) {
+ downloadFile = true;
+ this.currentSizeDownload -= fileSize;
+ continue;
+ }
+ throw new Exception("failed to download " + currentFile);
+ }
+ }
+ }
+ }
+
+ this.subtaskMessage = "";
+ }
+
+
+ protected InputStream getJarInputStream(String currentFile, final URLConnection urlconnection) throws Exception {
+ final InputStream[] is = new InputStream[1];
+
+
+ for (int j = 0; j < 3 && is[0] == null; j++) {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ is[0] = urlconnection.getInputStream();
+ } catch (IOException iOException) {
+ }
+ }
+ };
+
+
+ t.setName("JarInputStreamThread");
+ t.start();
+
+ int iterationCount = 0;
+ while (is[0] == null && iterationCount++ < 5) {
+ try {
+ t.join(1000L);
+ } catch (InterruptedException interruptedException) {
+ }
+ }
+
+
+ if (is[0] == null) {
+ try {
+ t.interrupt();
+ t.join();
+ } catch (InterruptedException interruptedException) {
+ }
+ }
+ }
+
+
+ if (is[0] == null) {
+ if (currentFile.equals("minecraft.jar")) {
+ throw new Exception("Unable to download " + currentFile);
+ }
+ throw new Exception("Unable to download " + currentFile);
+ }
+
+
+ return is[0];
+ }
+
+
+ protected void extractLZMA(String in, String out) throws Exception {
+ File f = new File(in);
+ FileInputStream fileInputHandle = new FileInputStream(f);
+
+
+ Class<?> clazz = Class.forName("LZMA.LzmaInputStream");
+ Constructor<?> constructor = clazz.getDeclaredConstructor(InputStream.class);
+ InputStream inputHandle = (InputStream) constructor.newInstance(new Object[]{fileInputHandle});
+
+
+ OutputStream outputHandle = new FileOutputStream(out);
+
+ byte[] buffer = new byte[16384];
+
+ int ret = inputHandle.read(buffer);
+ while (ret >= 1) {
+ outputHandle.write(buffer, 0, ret);
+ ret = inputHandle.read(buffer);
+ }
+
+ inputHandle.close();
+ outputHandle.close();
+
+ outputHandle = null;
+ inputHandle = null;
+
+
+ f.delete();
+ }
+
+
+ protected void extractPack(String in, String out) throws Exception {
+ File f = new File(in);
+ FileOutputStream fostream = new FileOutputStream(out);
+ JarOutputStream jostream = new JarOutputStream(fostream);
+
+ Pack200.Unpacker unpacker = Pack200.newUnpacker();
+ unpacker.unpack(f, jostream);
+ jostream.close();
+
+
+ f.delete();
+ }
+
+
+ protected void extractJars(String path) throws Exception {
+ this.state = 5;
+
+ float increment = 10.0F / this.urlList.length;
+
+ for (int i = 0; i < this.urlList.length; i++) {
+ this.percentage = 55 + (int) (increment * (i + 1));
+ String filename = getFileName(this.urlList[i]);
+
+ if (filename.endsWith(".pack.lzma")) {
+ this.subtaskMessage = "Extracting: " + filename + " to " + filename.replaceAll(".lzma", "");
+ extractLZMA(path + filename, path + filename.replaceAll(".lzma", ""));
+
+ this.subtaskMessage = "Extracting: " + filename.replaceAll(".lzma", "") + " to " + filename.replaceAll(".pack.lzma", "");
+ extractPack(path + filename.replaceAll(".lzma", ""), path + filename.replaceAll(".pack.lzma", ""));
+ } else if (filename.endsWith(".pack")) {
+ this.subtaskMessage = "Extracting: " + filename + " to " + filename.replace(".pack", "");
+ extractPack(path + filename, path + filename.replace(".pack", ""));
+ } else if (filename.endsWith(".lzma")) {
+ this.subtaskMessage = "Extracting: " + filename + " to " + filename.replace(".lzma", "");
+ extractLZMA(path + filename, path + filename.replace(".lzma", ""));
+ }
+ }
+ }
+
+
+ protected void extractNatives(String path) throws Exception {
+ this.state = 5;
+
+ int initialPercentage = this.percentage;
+
+ String nativeJar = getJarName(this.urlList[this.urlList.length - 1]);
+
+ Certificate[] certificate = Launcher.class.getProtectionDomain().getCodeSource().getCertificates();
+
+ if (certificate == null) {
+ URL location = Launcher.class.getProtectionDomain().getCodeSource().getLocation();
+
+ JarURLConnection jurl = (JarURLConnection) (new URL("jar:" + location.toString() + "!/net/minecraft/Launcher.class")).openConnection();
+ jurl.setDefaultUseCaches(true);
+ try {
+ certificate = jurl.getCertificates();
+ } catch (Exception exception) {
+ }
+ }
+
+
+ File nativeFolder = new File(path + "natives");
+ if (!nativeFolder.exists()) {
+ nativeFolder.mkdir();
+ }
+
+ JarFile jarFile = new JarFile(path + nativeJar, true);
+ Enumeration<JarEntry> entities = jarFile.entries();
+
+ this.totalSizeExtract = 0;
+
+
+ while (entities.hasMoreElements()) {
+ JarEntry entry = entities.nextElement();
+
+
+ if (entry.isDirectory() || entry.getName().indexOf('/') != -1) {
+ continue;
+ }
+ this.totalSizeExtract = (int) (this.totalSizeExtract + entry.getSize());
+ }
+
+ this.currentSizeExtract = 0;
+
+ entities = jarFile.entries();
+
+ while (entities.hasMoreElements()) {
+ JarEntry entry = entities.nextElement();
+
+ if (entry.isDirectory() || entry.getName().indexOf('/') != -1) {
+ continue;
+ }
+
+ File file = new File(path + "natives" + File.separator + entry.getName());
+ if (file.exists() &&
+ !file.delete()) {
+ continue;
+ }
+
+
+ InputStream in = jarFile.getInputStream(jarFile.getEntry(entry.getName()));
+ OutputStream out = new FileOutputStream(path + "natives" + File.separator + entry.getName());
+
+
+ byte[] buffer = new byte[65536];
+ int bufferSize;
+ while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1) {
+ out.write(buffer, 0, bufferSize);
+ this.currentSizeExtract += bufferSize;
+
+ this.percentage = initialPercentage + this.currentSizeExtract * 20 / this.totalSizeExtract;
+ this.subtaskMessage = "Extracting: " + entry.getName() + " " + (this.currentSizeExtract * 100 / this.totalSizeExtract) + "%";
+ }
+
+ validateCertificateChain(certificate, entry.getCertificates());
+
+ in.close();
+ out.close();
+ }
+ this.subtaskMessage = "";
+
+ jarFile.close();
+
+ File f = new File(path + nativeJar);
+ f.delete();
+ }
+
+
+ protected static void validateCertificateChain(Certificate[] ownCerts, Certificate[] native_certs) throws Exception {
+ if (ownCerts == null)
+ return;
+ if (native_certs == null)
+ throw new Exception("Unable to validate certificate chain. Native entry did not have a certificate chain at all");
+
+ if (ownCerts.length != native_certs.length)
+ throw new Exception("Unable to validate certificate chain. Chain differs in length [" + ownCerts.length + " vs " + native_certs.length + "]");
+
+ for (int i = 0; i < ownCerts.length; i++) {
+ if (!ownCerts[i].equals(native_certs[i])) {
+ throw new Exception("Certificate mismatch: " + ownCerts[i] + " != " + native_certs[i]);
+ }
+ }
+ }
+
+ protected String getJarName(URL url) {
+ String fileName = url.getFile();
+
+ if (fileName.contains("?")) {
+ fileName = fileName.substring(0, fileName.indexOf("?"));
+ }
+ if (fileName.endsWith(".pack.lzma")) {
+ fileName = fileName.replaceAll(".pack.lzma", "");
+ } else if (fileName.endsWith(".pack")) {
+ fileName = fileName.replaceAll(".pack", "");
+ } else if (fileName.endsWith(".lzma")) {
+ fileName = fileName.replaceAll(".lzma", "");
+ }
+
+ return fileName.substring(fileName.lastIndexOf('/') + 1);
+ }
+
+ protected String getFileName(URL url) {
+ String fileName = url.getFile();
+ if (fileName.contains("?")) {
+ fileName = fileName.substring(0, fileName.indexOf("?"));
+ }
+ return fileName.substring(fileName.lastIndexOf('/') + 1);
+ }
+
+ protected void fatalErrorOccured(String error, Exception e) {
+ e.printStackTrace();
+ this.fatalError = true;
+ this.fatalErrorDescription = "Fatal error occured (" + this.state + "): " + error;
+ System.out.println(this.fatalErrorDescription);
+ if (e != null) {
+ System.out.println(generateStacktrace(e));
+ }
+ }
+
+
+ public boolean canPlayOffline() {
+ try {
+ String path = AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
+ public Object run() throws Exception {
+ return Util.getWorkingDirectory() + File.separator + "bin" + File.separator;
+ }
+ });
+
+ File dir = new File(path);
+ if (!dir.exists()) return false;
+
+ dir = new File(dir, "version");
+ if (!dir.exists()) return false;
+
+ if (dir.exists()) {
+ String version = readVersionFile(dir);
+ if (version != null && version.length() > 0) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/src/net/minecraft/Launcher.java b/src/net/minecraft/Launcher.java
new file mode 100644
index 0000000..d2275df
--- /dev/null
+++ b/src/net/minecraft/Launcher.java
@@ -0,0 +1,218 @@
+package net.minecraft;
+
+import java.applet.Applet;
+import java.awt.*;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+
+public class Launcher extends Applet implements Runnable, AppletStub {
+ public Map<String, String> customParameters = new HashMap<String, String>();
+ private static final long serialVersionUID = 1L;
+ private GameUpdater gameUpdater;
+ private boolean gameUpdaterStarted = false;
+ private Applet applet;
+ private Image bgImage;
+ private boolean active = false;
+ private int context = 0;
+
+ private VolatileImage img;
+
+
+ public boolean isActive() {
+ if (this.context == 0) {
+ this.context = -1;
+ try {
+ if (getAppletContext() != null) this.context = 1;
+ } catch (Exception exception) {
+ }
+ }
+
+ if (this.context == -1) return this.active;
+ return super.isActive();
+ }
+
+
+ public void init(String userName, String latestVersion, String downloadTicket, String sessionId) {
+ try {
+ this.bgImage = ImageIO.read(LoginForm.class.getResource("dirt.png")).getScaledInstance(32, 32, 16);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ this.customParameters.put("username", userName);
+ this.customParameters.put("sessionid", sessionId);
+
+ this.gameUpdater = new GameUpdater(latestVersion, "minecraft.jar?user=" + userName + "&ticket=" + downloadTicket);
+ }
+
+ public boolean canPlayOffline() {
+ return this.gameUpdater.canPlayOffline();
+ }
+
+ public void init() {
+ if (this.applet != null) {
+ this.applet.init();
+ return;
+ }
+ init(getParameter("userName"), getParameter("latestVersion"), getParameter("downloadTicket"), getParameter("sessionId"));
+ }
+
+ public void start() {
+ if (this.applet != null) {
+ this.applet.start();
+ return;
+ }
+ if (this.gameUpdaterStarted)
+ return;
+ Thread t = new Thread() {
+ public void run() {
+ Launcher.this.gameUpdater.run();
+ try {
+ if (!Launcher.this.gameUpdater.fatalError) {
+ Launcher.this.replace(Launcher.this.gameUpdater.createApplet());
+ }
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ t.setDaemon(true);
+ t.start();
+
+ t = new Thread() {
+ public void run() {
+ while (Launcher.this.applet == null) {
+ Launcher.this.repaint();
+ try {
+ Thread.sleep(10L);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+ t.setDaemon(true);
+ t.start();
+
+ this.gameUpdaterStarted = true;
+ }
+
+ public void stop() {
+ if (this.applet != null) {
+ this.active = false;
+ this.applet.stop();
+ }
+ }
+
+ public void destroy() {
+ if (this.applet != null) {
+ this.applet.destroy();
+ }
+ }
+
+ public void replace(Applet applet) {
+ this.applet = applet;
+ applet.setStub(this);
+ applet.setSize(getWidth(), getHeight());
+
+ setLayout(new BorderLayout());
+ add(applet, "Center");
+
+ applet.init();
+ this.active = true;
+ applet.start();
+ validate();
+ }
+
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ public void paint(Graphics g2) {
+ if (this.applet != null)
+ return;
+ int w = getWidth() / 2;
+ int h = getHeight() / 2;
+ if (this.img == null || this.img.getWidth() != w || this.img.getHeight() != h) {
+ this.img = createVolatileImage(w, h);
+ }
+
+ Graphics g = this.img.getGraphics();
+ for (int x = 0; x <= w / 32; x++) {
+ for (int y = 0; y <= h / 32; y++)
+ g.drawImage(this.bgImage, x * 32, y * 32, null);
+ }
+ g.setColor(Color.LIGHT_GRAY);
+
+
+ String msg = "Updating Minecraft";
+ if (this.gameUpdater.fatalError) {
+ msg = "Failed to launch";
+ }
+
+ g.setFont(new Font(null, 1, 20));
+ FontMetrics fm = g.getFontMetrics();
+ g.drawString(msg, w / 2 - fm.stringWidth(msg) / 2, h / 2 - fm.getHeight() * 2);
+
+ g.setFont(new Font(null, 0, 12));
+ fm = g.getFontMetrics();
+ msg = this.gameUpdater.getDescriptionForState();
+ if (this.gameUpdater.fatalError) {
+ msg = this.gameUpdater.fatalErrorDescription;
+ }
+
+ g.drawString(msg, w / 2 - fm.stringWidth(msg) / 2, h / 2 + fm.getHeight());
+ msg = this.gameUpdater.subtaskMessage;
+ g.drawString(msg, w / 2 - fm.stringWidth(msg) / 2, h / 2 + fm.getHeight() * 2);
+
+ if (!this.gameUpdater.fatalError) {
+ g.setColor(Color.black);
+ g.fillRect(64, h - 64, w - 128 + 1, 5);
+ g.setColor(new Color(32768));
+ g.fillRect(64, h - 64, this.gameUpdater.percentage * (w - 128) / 100, 4);
+ g.setColor(new Color(2138144));
+ g.fillRect(65, h - 64 + 1, this.gameUpdater.percentage * (w - 128) / 100 - 2, 1);
+ }
+
+ g.dispose();
+
+
+ g2.drawImage(this.img, 0, 0, w * 2, h * 2, null);
+ }
+
+
+ public void run() {
+ }
+
+ public String getParameter(String name) {
+ String custom = this.customParameters.get(name);
+ if (custom != null) return custom;
+ try {
+ return super.getParameter(name);
+ } catch (Exception e) {
+ this.customParameters.put(name, null);
+ return null;
+ }
+ }
+
+
+ public void appletResize(int width, int height) {
+ }
+
+ public URL getDocumentBase() {
+ try {
+ return new URL("http://www.minecraft.net/game/");
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+
+ return null;
+ }
+ }
+}
diff --git a/src/net/minecraft/LauncherFrame.java b/src/net/minecraft/LauncherFrame.java
new file mode 100644
index 0000000..9d23071
--- /dev/null
+++ b/src/net/minecraft/LauncherFrame.java
@@ -0,0 +1,140 @@
+package net.minecraft;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+public class LauncherFrame extends Frame {
+ public static final int VERSION = 12;
+ private static final long serialVersionUID = 1L;
+
+ public LauncherFrame() {
+ super("Minecraft Launcher");
+
+ setBackground(Color.BLACK);
+ this.loginForm = new LoginForm(this);
+ setLayout(new BorderLayout());
+ add(this.loginForm, "Center");
+
+ this.loginForm.setPreferredSize(new Dimension(854, 480));
+ pack();
+ setLocationRelativeTo(null);
+
+ try {
+ setIconImage(ImageIO.read(LauncherFrame.class.getResource("favicon.png")));
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent arg0) {
+ (new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(30000L);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ System.out.println("FORCING EXIT!");
+ System.exit(0);
+ }
+ }).start();
+ if (LauncherFrame.this.launcher != null) {
+ LauncherFrame.this.launcher.stop();
+ LauncherFrame.this.launcher.destroy();
+ }
+ System.exit(0);
+ }
+ });
+ }
+
+ private Launcher launcher;
+ private LoginForm loginForm;
+
+ public void playCached(String userName) {
+ try {
+ if (userName == null || userName.length() <= 0) {
+ userName = "Player";
+ }
+ this.launcher = new Launcher();
+ this.launcher.customParameters.put("userName", userName);
+ this.launcher.init();
+ removeAll();
+ add(this.launcher, "Center");
+ validate();
+ this.launcher.start();
+ this.loginForm = null;
+ setTitle("Minecraft");
+ } catch (Exception e) {
+ e.printStackTrace();
+ showError(e.toString());
+ }
+ }
+
+ public void login(String userName, String password) {
+ try {
+ String parameters = "user=" + URLEncoder.encode(userName, "UTF-8") + "&password=" + URLEncoder.encode(password, "UTF-8") + "&version=" + '\f';
+ String result = Util.excutePost("http://www.minecraft.net/game/getversion.jsp", parameters);
+ if (result == null) {
+ showError("Can't connect to minecraft.net");
+ this.loginForm.setNoNetwork();
+ return;
+ }
+ if (!result.contains(":")) {
+ if (result.trim().equals("Bad login")) {
+ showError("Login failed");
+ } else if (result.trim().equals("Old version")) {
+ this.loginForm.setOutdated();
+ showError("Outdated launcher");
+ } else {
+ showError(result);
+ }
+ this.loginForm.setNoNetwork();
+ return;
+ }
+ String[] values = result.split(":");
+
+ System.out.println("Username is '" + values[2] + "'");
+
+ this.launcher = new Launcher();
+ this.launcher.customParameters.put("userName", values[2].trim());
+ this.launcher.customParameters.put("latestVersion", values[0].trim());
+ this.launcher.customParameters.put("downloadTicket", values[1].trim());
+ this.launcher.customParameters.put("sessionId", values[3].trim());
+ this.launcher.init();
+
+ removeAll();
+ add(this.launcher, "Center");
+ validate();
+ this.launcher.start();
+ this.loginForm.loginOk();
+ this.loginForm = null;
+ setTitle("Minecraft");
+ } catch (Exception e) {
+ e.printStackTrace();
+ showError(e.toString());
+ this.loginForm.setNoNetwork();
+ }
+ }
+
+ private void showError(String error) {
+ removeAll();
+ add(this.loginForm);
+ this.loginForm.setError(error);
+ validate();
+ }
+
+ public boolean canPlayOffline(String userName) {
+ Launcher launcher = new Launcher();
+ launcher.init(userName, null, null, null);
+ return launcher.canPlayOffline();
+ }
+
+ public static void main(String[] args) {
+ LauncherFrame launcherFrame = new LauncherFrame();
+ launcherFrame.setVisible(true);
+ }
+}
diff --git a/src/net/minecraft/LoginForm.java b/src/net/minecraft/LoginForm.java
new file mode 100644
index 0000000..d8f6873
--- /dev/null
+++ b/src/net/minecraft/LoginForm.java
@@ -0,0 +1,380 @@
+package net.minecraft;
+
+import javax.crypto.Cipher;
+import java.awt.*;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+
+public class LoginForm extends Panel {
+ private static final long serialVersionUID = 1L;
+ private final TextField userName = new TextField(20);
+ private final Image bgImage;
+ private final TextField password = new TextField(20);
+ private final Checkbox rememberBox = new Checkbox("Remember password");
+ private final Button launchButton = new Button("Login");
+ private final Button retryButton = new Button("Try again");
+ private final Button offlineButton = new Button("Play offline");
+ private final Label errorLabel = new Label("", 1);
+ private final LauncherFrame launcherFrame;
+ private boolean outdated = false;
+ private VolatileImage img;
+
+ public LoginForm(final LauncherFrame launcherFrame) {
+ this.launcherFrame = launcherFrame;
+
+ GridBagLayout gbl = new GridBagLayout();
+ setLayout(gbl);
+
+ add(buildLoginPanel());
+
+ try {
+ this.bgImage = ImageIO.read(LoginForm.class.getResource("dirt.png")).getScaledInstance(32, 32, 16);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ readUsername();
+
+ this.retryButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ LoginForm.this.errorLabel.setText("");
+ LoginForm.this.removeAll();
+ LoginForm.this.add(LoginForm.this.buildLoginPanel());
+ LoginForm.this.validate();
+ }
+ });
+
+ this.offlineButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ launcherFrame.playCached(LoginForm.this.userName.getText());
+ }
+ });
+
+ this.launchButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ launcherFrame.login(LoginForm.this.userName.getText(), LoginForm.this.password.getText());
+ }
+ });
+ }
+
+ private void readUsername() {
+ try {
+ DataInputStream dis;
+ File lastLogin = new File(Util.getWorkingDirectory(), "lastlogin");
+
+ Cipher cipher = getCipher(2, "passwordfile");
+ if (cipher != null) {
+ dis = new DataInputStream(new CipherInputStream(new FileInputStream(lastLogin), cipher));
+ } else {
+ dis = new DataInputStream(new FileInputStream(lastLogin));
+ }
+ this.userName.setText(dis.readUTF());
+ this.password.setText(dis.readUTF());
+ this.rememberBox.setState((this.password.getText().length() > 0));
+ dis.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void writeUsername() {
+ try {
+ DataOutputStream dos;
+ File lastLogin = new File(Util.getWorkingDirectory(), "lastlogin");
+
+ Cipher cipher = getCipher(1, "passwordfile");
+ if (cipher != null) {
+ dos = new DataOutputStream(new CipherOutputStream(new FileOutputStream(lastLogin), cipher));
+ } else {
+ dos = new DataOutputStream(new FileOutputStream(lastLogin));
+ }
+ dos.writeUTF(this.userName.getText());
+ dos.writeUTF(this.rememberBox.getState() ? this.password.getText() : "");
+ dos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private Cipher getCipher(int mode, String password) throws Exception {
+ Random random = new Random(43287234L);
+ byte[] salt = new byte[8];
+ random.nextBytes(salt);
+ PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 5);
+
+ SecretKey pbeKey = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(new PBEKeySpec(password.toCharArray()));
+ Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
+ cipher.init(mode, pbeKey, pbeParamSpec);
+ return cipher;
+ }
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+
+ public void paint(Graphics g2) {
+ int w = getWidth() / 2;
+ int h = getHeight() / 2;
+ if (this.img == null || this.img.getWidth() != w || this.img.getHeight() != h) {
+ this.img = createVolatileImage(w, h);
+ }
+
+ Graphics g = this.img.getGraphics();
+ for (int x = 0; x <= w / 32; x++) {
+ for (int y = 0; y <= h / 32; y++)
+ g.drawImage(this.bgImage, x * 32, y * 32, null);
+ }
+ g.setColor(Color.LIGHT_GRAY);
+
+
+ String msg = "Minecraft Launcher";
+ g.setFont(new Font(null, 1, 20));
+ FontMetrics fm = g.getFontMetrics();
+ g.drawString(msg, w / 2 - fm.stringWidth(msg) / 2, h / 2 - fm.getHeight() * 2);
+
+ g.dispose();
+ g2.drawImage(this.img, 0, 0, w * 2, h * 2, null);
+ }
+
+ private Panel buildLoginPanel() {
+ Panel panel = new Panel() {
+ private static final long serialVersionUID = 1L;
+ private final Insets insets = new Insets(12, 24, 16, 32);
+
+ public Insets getInsets() {
+ return this.insets;
+ }
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ public void paint(Graphics g) {
+ super.paint(g);
+ int hOffs = 0;
+
+ g.setColor(Color.BLACK);
+ g.drawRect(0, hOffs, getWidth() - 1, getHeight() - 1 - hOffs);
+ g.drawRect(1, 1 + hOffs, getWidth() - 3, getHeight() - 3 - hOffs);
+ g.setColor(Color.WHITE);
+
+ g.drawRect(2, 2 + hOffs, getWidth() - 5, getHeight() - 5 - hOffs);
+ }
+ };
+
+ panel.setBackground(Color.GRAY);
+ BorderLayout layout = new BorderLayout();
+ layout.setHgap(0);
+ layout.setVgap(8);
+ panel.setLayout(layout);
+
+
+ GridLayout gl1 = new GridLayout(0, 1);
+ GridLayout gl2 = new GridLayout(0, 1);
+ gl1.setVgap(2);
+ gl2.setVgap(2);
+ Panel titles = new Panel(gl1);
+ Panel values = new Panel(gl2);
+
+ titles.add(new Label("Username:", 2));
+ titles.add(new Label("Password:", 2));
+ titles.add(new Label("", 2));
+
+ this.password.setEchoChar('*');
+ values.add(this.userName);
+ values.add(this.password);
+ values.add(this.rememberBox);
+
+ panel.add(titles, "West");
+ panel.add(values, "Center");
+
+ Panel loginPanel = new Panel(new BorderLayout());
+
+ Panel registerPanel = new Panel(new BorderLayout());
+ try {
+ if (this.outdated) {
+ Label accountLink = new Label("You need to update the launcher!") {
+ private static final long serialVersionUID = 0L;
+
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ int x = 0;
+ int y = 0;
+
+
+ FontMetrics fm = g.getFontMetrics();
+ int width = fm.stringWidth(getText());
+ int height = fm.getHeight();
+
+ if (getAlignment() == 0) {
+ x = 0;
+ } else if (getAlignment() == 1) {
+ x = (getBounds()).width / 2 - width / 2;
+ } else if (getAlignment() == 2) {
+ x = (getBounds()).width - width;
+ }
+ y = (getBounds()).height / 2 + height / 2 - 1;
+
+ g.drawLine(x + 2, y, x + width - 2, y);
+ }
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+ };
+
+ accountLink.setCursor(Cursor.getPredefinedCursor(12));
+ accountLink.addMouseListener(new MouseAdapter() {
+ public void mousePressed(MouseEvent arg0) {
+ try {
+ Desktop.getDesktop().browse((new URL("http://www.minecraft.net/download.jsp")).toURI());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ accountLink.setForeground(Color.BLUE);
+ registerPanel.add(accountLink, "West");
+ registerPanel.add(new Panel(), "Center");
+ } else {
+ Label accountLink = new Label("Need account?") {
+ private static final long serialVersionUID = 0L;
+
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ int x = 0;
+ int y = 0;
+
+
+ FontMetrics fm = g.getFontMetrics();
+ int width = fm.stringWidth(getText());
+ int height = fm.getHeight();
+
+ if (getAlignment() == 0) {
+ x = 0;
+ } else if (getAlignment() == 1) {
+ x = (getBounds()).width / 2 - width / 2;
+ } else if (getAlignment() == 2) {
+ x = (getBounds()).width - width;
+ }
+ y = (getBounds()).height / 2 + height / 2 - 1;
+
+ g.drawLine(x + 2, y, x + width - 2, y);
+ }
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+ };
+
+ accountLink.setCursor(Cursor.getPredefinedCursor(12));
+ accountLink.addMouseListener(new MouseAdapter() {
+ public void mousePressed(MouseEvent arg0) {
+ try {
+ Desktop.getDesktop().browse((new URL("http://www.minecraft.net/register.jsp")).toURI());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ accountLink.setForeground(Color.BLUE);
+ registerPanel.add(accountLink, "West");
+ registerPanel.add(new Panel(), "Center");
+ }
+ } catch (Error error) {
+ }
+
+
+ loginPanel.add(registerPanel, "Center");
+ loginPanel.add(this.launchButton, "East");
+ panel.add(loginPanel, "South");
+
+ this.errorLabel.setFont(new Font(null, 2, 16));
+ this.errorLabel.setForeground(new Color(8388608));
+ panel.add(this.errorLabel, "North");
+
+
+ return panel;
+ }
+
+ private Panel buildOfflinePanel() {
+ Panel panel = new Panel() {
+ private static final long serialVersionUID = 1L;
+ private final Insets insets = new Insets(12, 24, 16, 32);
+
+ public Insets getInsets() {
+ return this.insets;
+ }
+
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ public void paint(Graphics g) {
+ super.paint(g);
+ int hOffs = 0;
+ g.setColor(Color.BLACK);
+ g.drawRect(0, hOffs, getWidth() - 1, getHeight() - 1 - hOffs);
+ g.drawRect(1, 1 + hOffs, getWidth() - 3, getHeight() - 3 - hOffs);
+ g.setColor(Color.WHITE);
+
+ g.drawRect(2, 2 + hOffs, getWidth() - 5, getHeight() - 5 - hOffs);
+ }
+ };
+
+ panel.setBackground(Color.GRAY);
+ BorderLayout layout = new BorderLayout();
+ panel.setLayout(layout);
+
+ Panel loginPanel = new Panel(new BorderLayout());
+ loginPanel.add(new Panel(), "Center");
+ panel.add(new Panel(), "Center");
+ loginPanel.add(this.retryButton, "East");
+ loginPanel.add(this.offlineButton, "West");
+
+ boolean canPlayOffline = this.launcherFrame.canPlayOffline(this.userName.getText());
+ this.offlineButton.setEnabled(canPlayOffline);
+ if (!canPlayOffline) {
+ panel.add(new Label("Play online once to enable offline"), "Center");
+ }
+ panel.add(loginPanel, "South");
+
+ this.errorLabel.setFont(new Font(null, 2, 16));
+ this.errorLabel.setForeground(new Color(8388608));
+ panel.add(this.errorLabel, "North");
+
+
+ return panel;
+ }
+
+ public void setError(String errorMessage) {
+ removeAll();
+ add(buildLoginPanel());
+ this.errorLabel.setText(errorMessage);
+ validate();
+ }
+
+ public void loginOk() {
+ writeUsername();
+ }
+
+ public void setNoNetwork() {
+ removeAll();
+ add(buildOfflinePanel());
+ validate();
+ }
+
+ public void checkAutologin() {
+ if (this.password.getText().length() > 0) {
+ this.launcherFrame.login(this.userName.getText(), this.password.getText());
+ }
+ }
+
+ public void setOutdated() {
+ this.outdated = true;
+ }
+}
diff --git a/src/net/minecraft/MinecraftLauncher.java b/src/net/minecraft/MinecraftLauncher.java
new file mode 100644
index 0000000..14d2e5f
--- /dev/null
+++ b/src/net/minecraft/MinecraftLauncher.java
@@ -0,0 +1,40 @@
+package net.minecraft;
+
+import java.util.ArrayList;
+
+public class MinecraftLauncher {
+ private static final int MIN_HEAP = 511;
+ private static final int RECOMMENDED_HEAP = 1024;
+
+ public static void main(String[] args) throws Exception {
+ float heapSizeMegs = (float) (Runtime.getRuntime().maxMemory() / 1024L / 1024L);
+
+ if (heapSizeMegs > 511.0F) {
+ LauncherFrame.main(args);
+ } else {
+ try {
+ String pathToJar = MinecraftLauncher.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
+
+ ArrayList<String> params = new ArrayList<String>();
+
+ params.add("javaw");
+ params.add("-Xmx1024m");
+ params.add("-Dsun.java2d.noddraw=true");
+ params.add("-Dsun.java2d.d3d=false");
+ params.add("-Dsun.java2d.opengl=false");
+ params.add("-Dsun.java2d.pmoffscreen=false");
+
+ params.add("-classpath");
+ params.add(pathToJar);
+ params.add("net.minecraft.LauncherFrame");
+ ProcessBuilder pb = new ProcessBuilder(params);
+ Process process = pb.start();
+ if (process == null) throw new Exception("!");
+ System.exit(0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ LauncherFrame.main(args);
+ }
+ }
+ }
+}
diff --git a/src/net/minecraft/Util.java b/src/net/minecraft/Util.java
new file mode 100644
index 0000000..9b21f9c
--- /dev/null
+++ b/src/net/minecraft/Util.java
@@ -0,0 +1,104 @@
+package net.minecraft;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.net.HttpURLConnection;
+
+public class Util {
+ private enum OS {
+ linux, solaris, windows, macos, unknown
+ }
+
+ private static File workDir = null;
+
+ public static File getWorkingDirectory() {
+ if (workDir == null) workDir = getWorkingDirectory("minecraft");
+ return workDir;
+ }
+
+ public static File getWorkingDirectory(String applicationName) {
+ File workingDirectory;
+ String applicationData, userHome = System.getProperty("user.home", ".");
+
+ switch (getPlatform()) {
+ case null:
+ case solaris:
+ workingDirectory = new File(userHome, '.' + applicationName + '/');
+ break;
+ case windows:
+ applicationData = System.getenv("APPDATA");
+ if (applicationData != null) {
+ workingDirectory = new File(applicationData, "." + applicationName + '/');
+ break;
+ }
+ workingDirectory = new File(userHome, '.' + applicationName + '/');
+ break;
+ case macos:
+ workingDirectory = new File(userHome, "Library/Application Support/" + applicationName);
+ break;
+ default:
+ workingDirectory = new File(userHome, String.valueOf(applicationName) + '/');
+ break;
+ }
+ if (!workingDirectory.exists() && !workingDirectory.mkdirs())
+ throw new RuntimeException("The working directory could not be created: " + workingDirectory);
+ return workingDirectory;
+ }
+
+ private static OS getPlatform() {
+ String osName = System.getProperty("os.name").toLowerCase();
+ if (osName.contains("win")) return OS.windows;
+ if (osName.contains("mac")) return OS.macos;
+ if (osName.contains("solaris")) return OS.solaris;
+ if (osName.contains("sunos")) return OS.solaris;
+ if (osName.contains("linux")) return OS.linux;
+ if (osName.contains("unix")) return OS.linux;
+ return OS.unknown;
+ }
+
+
+ public static String excutePost(String targetURL, String urlParameters) {
+ HttpURLConnection connection = null;
+
+ try {
+ URL url = new URL(targetURL);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+
+ connection.setRequestProperty("Content-Length", Integer.toString((urlParameters.getBytes()).length));
+ connection.setRequestProperty("Content-Language", "en-US");
+
+ connection.setUseCaches(false);
+ connection.setDoInput(true);
+ connection.setDoOutput(true);
+
+
+ DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
+ wr.writeBytes(urlParameters);
+ wr.flush();
+ wr.close();
+
+
+ InputStream is = connection.getInputStream();
+ BufferedReader rd = new BufferedReader(new InputStreamReader(is));
+
+ StringBuffer response = new StringBuffer();
+ String line;
+ while ((line = rd.readLine()) != null) {
+ response.append(line);
+ response.append('\r');
+ }
+ rd.close();
+ return response.toString();
+ } catch (Exception e) {
+
+ e.printStackTrace();
+ return null;
+ } finally {
+
+ if (connection != null)
+ connection.disconnect();
+ }
+ }
+}
diff --git a/src/net/minecraft/dirt.png b/src/net/minecraft/dirt.png
new file mode 100644
index 0000000..ef5288f
--- /dev/null
+++ b/src/net/minecraft/dirt.png
Binary files differ
diff --git a/src/net/minecraft/favicon.png b/src/net/minecraft/favicon.png
new file mode 100644
index 0000000..727eb76
--- /dev/null
+++ b/src/net/minecraft/favicon.png
Binary files differ