Upload sources

This commit is contained in:
khanhduytran0 committed 2020-03-19 16:42:25 +07:00
1 parent 86083535a8
commit e1ce65eb29
2887 files changed
+85891

No files matched your search

@@ -0,0 +1,25 @@
package net.kdt.pojavlaunch;
public class AccInfo
{
private String content;
public static AccInfo create(String path)
{
return new AccInfo(path);
}
private AccInfo(String path)
{
try
{
content = Tools.read(path);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
public String getUuid()
{
return null;
}
}
@@ -0,0 +1,138 @@
package net.kdt.pojavlaunch;
import android.util.*;
import android.view.*;
import java.util.*;
import org.lwjgl.input.*;
import org.lwjgl.opengl.*;
public class AndroidLWJGLKeycode {
private static final Map<Integer, Integer> androidToLwjglMap;
static {
androidToLwjglMap = new ArrayMap<Integer, Integer>();
androidToLwjglMap.put(KeyEvent.KEYCODE_0, Keyboard.KEY_0);
androidToLwjglMap.put(KeyEvent.KEYCODE_1, Keyboard.KEY_1);
androidToLwjglMap.put(KeyEvent.KEYCODE_2, Keyboard.KEY_2);
androidToLwjglMap.put(KeyEvent.KEYCODE_3, Keyboard.KEY_3);
androidToLwjglMap.put(KeyEvent.KEYCODE_4, Keyboard.KEY_4);
androidToLwjglMap.put(KeyEvent.KEYCODE_5, Keyboard.KEY_5);
androidToLwjglMap.put(KeyEvent.KEYCODE_6, Keyboard.KEY_6);
androidToLwjglMap.put(KeyEvent.KEYCODE_7, Keyboard.KEY_7);
androidToLwjglMap.put(KeyEvent.KEYCODE_8, Keyboard.KEY_8);
androidToLwjglMap.put(KeyEvent.KEYCODE_9, Keyboard.KEY_9);
androidToLwjglMap.put(KeyEvent.KEYCODE_A, Keyboard.KEY_A);
androidToLwjglMap.put(KeyEvent.KEYCODE_B, Keyboard.KEY_B);
androidToLwjglMap.put(KeyEvent.KEYCODE_C, Keyboard.KEY_C);
androidToLwjglMap.put(KeyEvent.KEYCODE_D, Keyboard.KEY_D);
androidToLwjglMap.put(KeyEvent.KEYCODE_E, Keyboard.KEY_E);
androidToLwjglMap.put(KeyEvent.KEYCODE_F, Keyboard.KEY_F);
androidToLwjglMap.put(KeyEvent.KEYCODE_G, Keyboard.KEY_G);
androidToLwjglMap.put(KeyEvent.KEYCODE_H, Keyboard.KEY_H);
androidToLwjglMap.put(KeyEvent.KEYCODE_I, Keyboard.KEY_I);
androidToLwjglMap.put(KeyEvent.KEYCODE_J, Keyboard.KEY_J);
androidToLwjglMap.put(KeyEvent.KEYCODE_K, Keyboard.KEY_K);
androidToLwjglMap.put(KeyEvent.KEYCODE_L, Keyboard.KEY_L);
androidToLwjglMap.put(KeyEvent.KEYCODE_M, Keyboard.KEY_M);
androidToLwjglMap.put(KeyEvent.KEYCODE_N, Keyboard.KEY_M);
androidToLwjglMap.put(KeyEvent.KEYCODE_O, Keyboard.KEY_O);
androidToLwjglMap.put(KeyEvent.KEYCODE_P, Keyboard.KEY_P);
androidToLwjglMap.put(KeyEvent.KEYCODE_Q, Keyboard.KEY_Q);
androidToLwjglMap.put(KeyEvent.KEYCODE_R, Keyboard.KEY_R);
androidToLwjglMap.put(KeyEvent.KEYCODE_S, Keyboard.KEY_S);
androidToLwjglMap.put(KeyEvent.KEYCODE_T, Keyboard.KEY_T);
androidToLwjglMap.put(KeyEvent.KEYCODE_U, Keyboard.KEY_U);
androidToLwjglMap.put(KeyEvent.KEYCODE_V, Keyboard.KEY_V);
androidToLwjglMap.put(KeyEvent.KEYCODE_W, Keyboard.KEY_W);
androidToLwjglMap.put(KeyEvent.KEYCODE_X, Keyboard.KEY_X);
androidToLwjglMap.put(KeyEvent.KEYCODE_Y, Keyboard.KEY_Y);
androidToLwjglMap.put(KeyEvent.KEYCODE_Z, Keyboard.KEY_Z);
androidToLwjglMap.put(KeyEvent.KEYCODE_ALT_LEFT, Keyboard.KEY_LMENU);
androidToLwjglMap.put(KeyEvent.KEYCODE_ALT_RIGHT, Keyboard.KEY_RMENU);
androidToLwjglMap.put(KeyEvent.KEYCODE_BACK, Keyboard.KEY_ESCAPE); // Might not be correctly!
androidToLwjglMap.put(KeyEvent.KEYCODE_BACKSLASH, Keyboard.KEY_BACKSLASH);
// androidToLwjglMap.put(KeyEvent.keyCode_del, Keyboard.KEY_DELETE);
androidToLwjglMap.put(KeyEvent.KEYCODE_BREAK, Keyboard.KEY_PAUSE);
androidToLwjglMap.put(KeyEvent.KEYCODE_CAPS_LOCK, Keyboard.KEY_CAPITAL);
androidToLwjglMap.put(KeyEvent.KEYCODE_COMMA, Keyboard.KEY_COMMA);
androidToLwjglMap.put(KeyEvent.KEYCODE_CTRL_LEFT, Keyboard.KEY_LCONTROL);
androidToLwjglMap.put(KeyEvent.KEYCODE_CTRL_RIGHT, Keyboard.KEY_RCONTROL);
androidToLwjglMap.put(KeyEvent.KEYCODE_DEL, Keyboard.KEY_BACK); // Backspace
androidToLwjglMap.put(KeyEvent.KEYCODE_ENTER, Keyboard.KEY_RETURN);
androidToLwjglMap.put(KeyEvent.KEYCODE_EQUALS, Keyboard.KEY_EQUALS);
androidToLwjglMap.put(KeyEvent.KEYCODE_ESCAPE, Keyboard.KEY_ESCAPE);
androidToLwjglMap.put(KeyEvent.KEYCODE_F1, Keyboard.KEY_F1);
androidToLwjglMap.put(KeyEvent.KEYCODE_F2, Keyboard.KEY_F2);
androidToLwjglMap.put(KeyEvent.KEYCODE_F3, Keyboard.KEY_F3);
androidToLwjglMap.put(KeyEvent.KEYCODE_F4, Keyboard.KEY_F4);
androidToLwjglMap.put(KeyEvent.KEYCODE_F5, Keyboard.KEY_F5);
androidToLwjglMap.put(KeyEvent.KEYCODE_F6, Keyboard.KEY_F6);
androidToLwjglMap.put(KeyEvent.KEYCODE_F7, Keyboard.KEY_F7);
androidToLwjglMap.put(KeyEvent.KEYCODE_F8, Keyboard.KEY_F8);
androidToLwjglMap.put(KeyEvent.KEYCODE_F9, Keyboard.KEY_F9);
androidToLwjglMap.put(KeyEvent.KEYCODE_F10, Keyboard.KEY_F10);
androidToLwjglMap.put(KeyEvent.KEYCODE_F11, Keyboard.KEY_F11);
androidToLwjglMap.put(KeyEvent.KEYCODE_F12, Keyboard.KEY_F12);
androidToLwjglMap.put(KeyEvent.KEYCODE_FUNCTION, Keyboard.KEY_FUNCTION);
androidToLwjglMap.put(KeyEvent.KEYCODE_FORWARD, Keyboard.KEY_UP); // Might not be correctly;
androidToLwjglMap.put(KeyEvent.KEYCODE_GRAVE, Keyboard.KEY_GRAVE);
androidToLwjglMap.put(KeyEvent.KEYCODE_HOME, Keyboard.KEY_HOME);
androidToLwjglMap.put(KeyEvent.KEYCODE_INSERT, Keyboard.KEY_INSERT);
androidToLwjglMap.put(KeyEvent.KEYCODE_KANA, Keyboard.KEY_KANA);
androidToLwjglMap.put(KeyEvent.KEYCODE_LEFT_BRACKET, Keyboard.KEY_LBRACKET);
androidToLwjglMap.put(KeyEvent.KEYCODE_MINUS, Keyboard.KEY_MINUS);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUM_LOCK, Keyboard.KEY_NUMLOCK);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_0, Keyboard.KEY_NUMPAD0);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_1, Keyboard.KEY_NUMPAD1);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_2, Keyboard.KEY_NUMPAD2);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_3, Keyboard.KEY_NUMPAD3);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_4, Keyboard.KEY_NUMPAD4);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_5, Keyboard.KEY_NUMPAD5);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_6, Keyboard.KEY_NUMPAD6);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_7, Keyboard.KEY_NUMPAD7);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_8, Keyboard.KEY_NUMPAD8);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_9, Keyboard.KEY_NUMPAD9);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_ENTER, Keyboard.KEY_NUMPADENTER);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_EQUALS, Keyboard.KEY_NUMPADEQUALS);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_COMMA, Keyboard.KEY_NUMPADCOMMA);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_ADD, Keyboard.KEY_ADD);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, Keyboard.KEY_DIVIDE);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_DOT, Keyboard.KEY_PERIOD);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, Keyboard.KEY_MULTIPLY);
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, Keyboard.KEY_SUBTRACT);
androidToLwjglMap.put(KeyEvent.KEYCODE_PAGE_DOWN, Keyboard.KEY_NEXT);
androidToLwjglMap.put(KeyEvent.KEYCODE_PAGE_UP, Keyboard.KEY_PRIOR);
androidToLwjglMap.put(KeyEvent.KEYCODE_PERIOD, Keyboard.KEY_PERIOD);
androidToLwjglMap.put(KeyEvent.KEYCODE_PLUS, Keyboard.KEY_ADD);
androidToLwjglMap.put(KeyEvent.KEYCODE_POWER, Keyboard.KEY_POWER);
androidToLwjglMap.put(KeyEvent.KEYCODE_RIGHT_BRACKET, Keyboard.KEY_RBRACKET);
androidToLwjglMap.put(KeyEvent.KEYCODE_SEMICOLON, Keyboard.KEY_SEMICOLON);
androidToLwjglMap.put(KeyEvent.KEYCODE_SHIFT_LEFT, Keyboard.KEY_LSHIFT);
androidToLwjglMap.put(KeyEvent.KEYCODE_SHIFT_RIGHT, Keyboard.KEY_RSHIFT);
androidToLwjglMap.put(KeyEvent.KEYCODE_SLASH, Keyboard.KEY_SLASH);
androidToLwjglMap.put(KeyEvent.KEYCODE_SLEEP, Keyboard.KEY_SLEEP);
androidToLwjglMap.put(KeyEvent.KEYCODE_SPACE, Keyboard.KEY_SPACE);
androidToLwjglMap.put(KeyEvent.KEYCODE_SYSRQ, Keyboard.KEY_SYSRQ);
androidToLwjglMap.put(KeyEvent.KEYCODE_TAB, Keyboard.KEY_TAB);
androidToLwjglMap.put(KeyEvent.KEYCODE_YEN, Keyboard.KEY_YEN);
}
public static void execKey(MainActivity mainActivity, KeyEvent keyEvent, int i, boolean isDown) {
for (Map.Entry<Integer, Integer> perKey : androidToLwjglMap.entrySet()) {
if (perKey.getKey() == i) {
mainActivity.sendKeyPress(perKey.getValue(), isDown);
}
}
if (!AndroidDisplay.grab) {
try {
// Old method works without dead chars:
if (isDown) {
mainActivity.sendKeyPress((char) keyEvent.getUnicodeChar());
}
} catch (Throwable th) {
th.printStackTrace();
}
}
}
}
@@ -0,0 +1,21 @@
package net.kdt.pojavlaunch;
public class ArchitectureCheck
{
public static String getArch() {
String arch = System.getProperty("os.arch");
String archConverted = null;
if (arch.equals("aarch64") ||
arch.endsWith("v8a") ||
arch.startsWith("arm64")) {
archConverted = "arm64";
} else if (arch.startsWith("arm") || arch.endsWith("v7a")) {
archConverted = "arm32";
} else if (arch.startsWith("x86") || arch.startsWith("amd")) {
archConverted = "x86";
}
return archConverted;
}
}
@@ -0,0 +1,40 @@
package net.kdt.pojavlaunch;
import android.support.annotation.*;
public abstract class AsyncThread<Params, Progress, Result> extends Thread
{
private boolean isCancelled = true;
@WorkerThread
protected abstract Result doInBackground(Params... params);
@MainThread
protected void onPreExecute() {}
@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onPostExecute(Result result) {}
@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onProgressUpdate(Progress... values) {}
@SuppressWarnings({"UnusedParameters"})
@MainThread
protected void onCancelled(Result result) {
onCancelled();
}
@MainThread
protected void onCancelled() {}
public final boolean isCancelled() {
return isCancelled;
}
public final boolean cancel() {
super.stop();
return true;
}
}
@@ -0,0 +1,14 @@
package net.kdt.pojavlaunch;
public class CancelException extends RuntimeException
{
@Override
public CancelException() {
super();
}
@Override
public CancelException(String msg) {
super(msg);
}
}
@@ -0,0 +1,14 @@
package net.kdt.pojavlaunch;
public class ClassesNotFoundException extends ClassNotFoundException
{
private static String mMessage = "Failed to find a class from classes list";
public ClassesNotFoundException()
{
super(mMessage);
}
public ClassesNotFoundException(String message)
{
super(message + ":" + mMessage);
}
}
@@ -0,0 +1,50 @@
package net.kdt.pojavlaunch;
import android.text.method.*;
import android.view.*;
import android.view.inputmethod.*;
import org.lwjgl.opengl.*;
import org.lwjgl.input.*;
public class DroidToJavaKey {
private static StringBuilder mComposing = new StringBuilder();
private static long mMetaState;
public static void execKey(MainActivity mainActivity, KeyEvent keyEvent, int i, boolean status) {
/*
if (i >= KeyEvent.KEYCODE_F1 && i <= KeyEvent.KEYCODE_F12) {
mainActivity.sendKeyPress(i - 72, status);
} else if (i == KeyEvent.KEYCODE_DEL) {
mainActivity.sendKeyPress(Keyboard.KEY_DELETE, status);
} else if (i == KeyEvent.KEYCODE_ENTER) {
mainActivity.sendKeyPress(Keyboard.KEY_RETURN, status);
} else if (i == KeyEvent.KEYCODE_SHIFT_LEFT) {
mainActivity.sendKeyPress(Keyboard.KEY_LSHIFT, status);
} else if (i == KeyEvent.KEYCODE_SHIFT_RIGHT) {
mainActivity.sendKeyPress(Keyboard.KEY_RSHIFT, status);
} else if (i == KeyEvent.KEYCODE_DPAD_LEFT) {
mainActivity.sendKeyPress(Keyboard.KEY_LEFT, status);
} else if (i == KeyEvent.KEYCODE_DPAD_UP) {
mainActivity.sendKeyPress(Keyboard.KEY_UP, status);
} else if (i == keyEvent.KEYCODE_DPAD_RIGHT) {
mainActivity.sendKeyPress(Keyboard.KEY_RIGHT, status);
} else if (i == KeyEvent.KEYCODE_DPAD_DOWN) {
mainActivity.sendKeyPress(Keyboard.KEY_DOWN, status);
} else if (i >= KeyEvent.KEYCODE_BUTTON_1 && i <= KeyEvent.KEYCODE_BUTTON_16) {
mainActivity.sendKeyPress(i - 188, status);
}
if (!AndroidDisplay.grab) {
try {
// Old method works without dead chars:
mainActivity.sendKeyPress(keyEvent.getDisplayLabel(), status);
} catch (Throwable th) {
th.printStackTrace();
}
}
*/
mainActivity.sendKeyPress(keyEvent.getDisplayLabel(), status);
}
}
@@ -0,0 +1,70 @@
package net.kdt.pojavlaunch;
import java.security.*;
import java.util.*;
public class FakeAccount
{
public static String[] generate()
{
String[] arr = {
UUID.randomUUID().toString(),
new RandomString(32).nextString()
};
return arr;
}
private static class RandomString {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lower = upper.toLowerCase(Locale.ROOT);
public static final String digits = "0123456789";
public static final String alphanum = upper + lower + digits;
private final Random random;
private final char[] symbols;
private final char[] buf;
public RandomString(int length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException();
if (symbols.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomString(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomString(int length) {
this(length, new SecureRandom());
}
/**
* Create session identifiers.
*/
public RandomString() {
this(21);
}
}
}
@@ -0,0 +1,25 @@
package net.kdt.pojavlaunch;
import java.net.*;
import java.io.*;
import dalvik.system.*;
public class FakeURLClassLoader extends URLClassLoader
{
private DexClassLoader m;
public FakeURLClassLoader(java.lang.String dexPath, java.lang.String optimizedDirectory, java.lang.String librarySearchPath, java.lang.ClassLoader parent) throws MalformedURLException {
super(new URL[] { new File("test.jar").toURI().toURL() }, null);
m = new DexClassLoader(dexPath, optimizedDirectory, librarySearchPath, parent);
}
@Override
public java.lang.String findLibrary(String name) {
return m.findLibrary(name);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException
{
return m.loadClass(name);
}
}
@@ -0,0 +1,46 @@
package net.kdt.pojavlaunch;
import android.content.res.*;
import android.graphics.*;
import android.view.*;
import android.widget.*;
public class FontChanger
{
private Typeface typeface;
public FontChanger(Typeface typeface)
{
this.typeface = typeface;
}
public FontChanger(AssetManager assets, String assetsFontFileName)
{
typeface = Typeface.createFromAsset(assets, assetsFontFileName);
}
public ViewGroup replaceFonts(ViewGroup viewTree)
{
View child;
for(int i = 0; i < viewTree.getChildCount(); ++i)
{
child = viewTree.getChildAt(i);
if(child instanceof ViewGroup)
{
// recursive call
replaceFonts((ViewGroup)child);
}
else if(child instanceof TextView)
{
// base case
replaceFont((TextView) child);
}
}
return viewTree;
}
public View replaceFont(TextView view) {
view.setTypeface(typeface);
return view;
}
}
@@ -0,0 +1,52 @@
package net.kdt.pojavlaunch;
import android.os.*;
public class InstallerTask extends AsyncTask<String, Void, String>
{
@Override
protected String doInBackground(String[] p1)
{
try
{
downloadLibraries(p1[0]);
dexMinecraftLibs();
downloadMinecraft(p1[0]);
dexMinecraftClient(p1[0]);
downloadAssets(p1[0]);
}
catch (Exception e)
{
return e.getMessage();
}
return null;
}
@Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
if(result == null){
//No errors
}
}
private void downloadLibraries(String versionName) throws Exception
{
}
private void dexMinecraftLibs() throws Exception
{
}
private void downloadMinecraft(String versionName) throws Exception
{
}
private void dexMinecraftClient(String version) throws Exception
{
}
private void downloadAssets(String versionName) throws Exception
{
}
}
@@ -0,0 +1,8 @@
package net.kdt.pojavlaunch;
public class JAssetInfo
{
public String hash;
public int size;
//public String objects;
}
@@ -0,0 +1,8 @@
package net.kdt.pojavlaunch;
import java.util.Map;
public class JAssets {
public Map<String, JAssetInfo> objects;
}
@@ -0,0 +1,24 @@
package net.kdt.pojavlaunch;
import java.util.Map;
public class JMinecraftVersionList {
public static final String TYPE_OLD_ALPHA = "old_alpha";
public static final String TYPE_OLD_BETA = "old_beta";
public static final String TYPE_RELEASE = "release";
public static final String TYPE_SNAPSHOT = "snapshot";
public Map<String, String> latest;
public Version[] versions;
public static class Version extends OfflineVersion {
public String url;
}
public static class OfflineVersion {
public String id;
public String releaseTime;
public String time;
public String type;
}
}
@@ -0,0 +1,43 @@
package net.kdt.pojavlaunch;
public class JVersion extends Object
{
private String version;
private JVersion(String version)
{
this.version = version;
}
public static JVersion from(String version)
{
return new JVersion(version);
}
public boolean isVersionCode()
{
return !version.contains(".");
}
public JVersion toVersionCode()
{
if(!isVersionCode()){
version = version.replace(".", "");
return this;
} else throw new RuntimeException("Can't convert version code to itself");
}
public JVersion toVersionName()
{
if(isVersionCode()){
StringBuilder charList = new StringBuilder();
for(int i=0; i<version.length(); i++){
charList.append(version.substring(i, i+1));
if(i != version.length() - 1){
charList.append(".");
}
}
version = charList.toString();
return this;
} else throw new RuntimeException("Can't convert version name to itself");
}
public String getVersion()
{
return version;
}
}
@@ -0,0 +1,13 @@
package net.kdt.pojavlaunch;
import dalvik.system.*;
public class LaunchClassLoaderAgruments
{
public static String launchDexPath, launchOptimizedDirectory, launchLibrarySearchPath;
public static void putAll(String dexPath, String optimizedDirectory, String librarySearchPath) {
launchDexPath = dexPath;
launchOptimizedDirectory = optimizedDirectory;
launchLibrarySearchPath = librarySearchPath;
}
}
@@ -0,0 +1,27 @@
package net.kdt.pojavlaunch;
import java.io.*;
public class LoggerJava
{
public static interface OnCharPrintListener {
public void onCharPrint(char c);
}
public static class LoggerOutputStream extends FilterOutputStream
{
private OnCharPrintListener mListener;
public LoggerOutputStream(OutputStream out, OnCharPrintListener listener)
{
super(out);
mListener = listener;
}
@Override
public void write(final int charCode) throws IOException
{
super.write(charCode);
mListener.onCharPrint((char) charCode);
}
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,183 @@
package net.kdt.pojavlaunch;
import android.app.*;
import android.content.*;
import android.util.*;
import android.view.*;
import com.kdt.mojangauth.*;
import java.io.*;
public class MCProfile
{
private static String[] emptyBuilder = new String[]{
"1.9", //Version
"ProfileIDEmpty",
"AccessToken",
"AccessTokenEmpty",
"Steve"
};
public static void launch(Activity ctx, Object o)
{
PojavProfile.setCurrentProfile(ctx, o);
Intent intent = new Intent(ctx, PojavV2ActivityManager.getLauncherRemakeVer(ctx)); //MCLauncherActivity.class);
ctx.startActivity(intent);
}
public static void updateTokens(final Activity ctx, final String pofFilePath, RefreshListener listen) throws Exception
{
new RefreshTokenTask(ctx, listen).execute(pofFilePath);
}
public static String build(MCProfile.Builder builder)
{
//System.out.println("build THE VER = " + builder.getVersion());
try {
byte[] bFull = toString(builder).getBytes("UTF-8");
Tools.write(Tools.mpProfiles + "/" + builder.getUsername(), bFull);
} catch (Exception e) {
e.printStackTrace();
}
return Tools.mpProfiles + "/" + builder.getUsername();
}
public static MCProfile.Builder load(String pofFilePath)
{
try {
//String th = new String(new byte[]{-128});
String pofContent = Tools.read(pofFilePath);
return parse(pofContent);
} catch (Exception e) {
throw new RuntimeException("Unable to load Profile " + pofFilePath, e);
}
}
public static MCProfile.Builder parse(String content) {
MCProfile.Builder builder = new MCProfile.Builder();
String[] profileInfos = content.split(":");
String cltk = profileInfos[0];
String prtk = profileInfos[1];
String acct = profileInfos[2];
String name = profileInfos[3];
String vers = profileInfos[4];
String isAc = profileInfos[5];
//System.out.println("parse THE VER = " + vers);
builder.setClientID(cltk);
builder.setProfileID(prtk);
builder.setAccessToken(acct);
builder.setUsername(name);
builder.setVersion(vers);
builder.setIsAccount(Boolean.parseBoolean(isAc));
return builder;
}
public static MCProfile.Builder loadSafety(String pofFilePath) {
try {
return load(pofFilePath);
} catch (Exception e) {
e.printStackTrace();
// return new MCProfile.Builder();
return null;
}
}
public static String toString(String pofFilePath) {
return toString(load(pofFilePath));
}
public static String toString(MCProfile.Builder builder) {
//System.out.println("TOSTRING THE VER = " + builder.getVersion());
return
builder.getClientID() + ":" +
builder.getProfileID() + ":" +
builder.getAccessToken() + ":" +
builder.getUsername() + ":" +
builder.getVersion() + ":" +
Boolean.toString(builder.isAccount());
}
public static class Builder implements Serializable
{
private String[] fullArgs = new String[6];
private boolean isAccount = true;
public Builder()
{
fullArgs = emptyBuilder;
String[] fakeTokens = FakeAccount.generate();
setClientID(fakeTokens[0]);
setProfileID(FakeAccount.generate()[0].replace("-", ""));
setAccessToken(fakeTokens[1]);
}
public boolean isAccount()
{
return isAccount;
}
public String getVersion()
{
return fullArgs[0];
}
public String getClientID()
{
return fullArgs[1];
}
public String getProfileID()
{
return fullArgs[2];
}
public String getAccessToken()
{
return fullArgs[3];
}
public String getUsername()
{
return fullArgs[4];
}
public void setIsAccount(boolean value)
{
isAccount = value;
}
public void setVersion(String value)
{
fullArgs[0] = value;
}
public void setClientID(String value)
{
fullArgs[1] = value;
}
public void setProfileID(String value)
{
fullArgs[2] = value;
}
public void setAccessToken(String value)
{
fullArgs[3] = value;
}
public void setUsername(String value)
{
fullArgs[4] = value;
}
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,48 @@
package net.kdt.pojavlaunch;
import android.content.*;
import android.util.*;
import android.view.*;
import com.kdt.glsupport.*;
public class MinecraftGLView extends GLTextureView
{
private View.OnTouchListener mTouchListener;
public MinecraftGLView(Context context) {
super(context);
//setPreserveEGLContextOnPause(true);
}
public MinecraftGLView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
//setPreserveEGLContextOnPause(true);
}
/*
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
//super.surfaceDestroyed(surfaceHolder);
System.out.println("Surface destroyed!");
//new Throwable("Surface destroyed!").printStackTrace();
}
*/
@Override
public void setOnTouchListener(View.OnTouchListener l)
{
super.setOnTouchListener(l);
mTouchListener = l;
}
@Override
public void setOnClickListener(View.OnClickListener l)
{
super.setOnClickListener(l);
}
@Override
public boolean onCapturedPointerEvent(MotionEvent event)
{
mTouchListener.onTouch(this, event);
return super.onCapturedPointerEvent(event);
}
}
@@ -0,0 +1,18 @@
package net.kdt.pojavlaunch;
public class MultidojManager
{
private static Listen li;
public static interface Listen {
public void onReceived(String msg, int max, int current);
}
public static void setListener(Listen l) {
li = l;
}
public static void call(String msg, int max, int current) {
if (li != null) li.onReceived(msg, max, current);
}
}
@@ -0,0 +1,26 @@
package net.kdt.pojavlaunch;
import android.app.Application;
import android.os.*;
import android.content.pm.PackageManager.*;
import android.content.pm.*;
public class PojavApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate();
try {
Tools.APP_NAME = getResources().getString(R.string.app_short_name);
PackageInfo thisApp = getPackageManager().getPackageInfo(getPackageName(), 0);
Tools.usingVerName = thisApp.versionName;
Tools.usingVerCode = thisApp.versionCode;
Tools.mainpath = getDir("files", MODE_PRIVATE).getParent();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,618 @@
package net.kdt.pojavlaunch;
import android.*;
import android.app.*;
import android.content.*;
import android.content.pm.*;
import android.os.*;
import android.support.annotation.*;
import android.support.v4.app.*;
import android.support.v4.content.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import com.kdt.filermod.*;
import com.kdt.mcgui.app.*;
import com.kdt.mojangauth.*;
import java.io.*;
import java.util.*;
import android.widget.CompoundButton.*;
import android.text.method.*;
import android.system.*;
import android.net.*;
import static android.view.ViewGroup.LayoutParams.*;
public class PojavLoginActivity extends MineActivity
{
private EditText edit2, edit3;
private int REQUEST_STORAGE_REQUEST_CODE = 1;
private ProgressBar prb;
private Switch sRemember, sOffline;
private boolean isPromptingGrant = false;
// private boolean isPermGranted = false;
private SharedPreferences firstLaunchPrefs;
private String PREF_IS_DONOTSHOWAGAIN_WARN = "isWarnDoNotShowAgain";
private String PREF_IS_INSTALLED_LIBRARIES = "isLibrariesExtracted";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState, false);
init();
}
private void init() {
firstLaunchPrefs = getSharedPreferences("pojav_extract", MODE_PRIVATE);
new File(Tools.mpProfiles).mkdir();
if (isAndroid7() && !firstLaunchPrefs.getBoolean(PREF_IS_DONOTSHOWAGAIN_WARN, false)) {
AlertDialog.Builder startDlg = new AlertDialog.Builder(PojavLoginActivity.this);
startDlg.setTitle(R.string.warning_title);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
LinearLayout conLay = new LinearLayout(this);
conLay.setLayoutParams(params);
conLay.setOrientation(LinearLayout.VERTICAL);
TextView conText = new TextView(this);
conText.setText(R.string.warning_msg);
conText.setLayoutParams(params);
final CheckBox conCheck = new CheckBox(this);
conCheck.setText(R.string.warning_noshowagain);
conCheck.setLayoutParams(params);
conLay.addView(conCheck);
conLay.addView(conText);
startDlg.setView(conLay);
startDlg.setCancelable(false);
startDlg.setPositiveButton(R.string.warning_action_install, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
setPref(PREF_IS_DONOTSHOWAGAIN_WARN, conCheck.isChecked());
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=com.vmos.glb"));
startActivity(intent);
}
});
startDlg.setNegativeButton(R.string.warning_action_tryanyway, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
setPref(PREF_IS_DONOTSHOWAGAIN_WARN, conCheck.isChecked());
new InitTask().execute();
}
});
startDlg.setNeutralButton(R.string.warning_action_exit, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
finish();
}
});
startDlg.show();
} else {
new InitTask().execute();
}
}
private class InitTask extends AsyncTask<Void, String, Integer>{
private AlertDialog startAle;
private ProgressBar progress;
private ProgressBar progressSpin;
private EditText progressLog;
private AlertDialog progDlg;
@Override
protected void onPreExecute()
{
LinearLayout startScr = new LinearLayout(PojavLoginActivity.this);
LayoutInflater.from(PojavLoginActivity.this).inflate(R.layout.start_screen, startScr);
replaceFonts(startScr);
progress = (ProgressBar) startScr.findViewById(R.id.startscreenProgress);
//startScr.addView(progress);
AlertDialog.Builder startDlg = new AlertDialog.Builder(PojavLoginActivity.this, R.style.AppTheme);
startDlg.setView(startScr);
startDlg.setCancelable(false);
startAle = startDlg.create();
startAle.show();
startAle.getWindow().setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT
);
}
private int revokeCount = -1;
@Override
protected Integer doInBackground(Void[] p1)
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
publishProgress("visible");
while (Build.VERSION.SDK_INT >= 23 && !isStorageAllowed()){
try {
revokeCount++;
if (revokeCount >= 3) {
Toast.makeText(PojavLoginActivity.this, R.string.toast_permission_denied, Toast.LENGTH_LONG).show();
finish();
}
isPromptingGrant = true;
requestStoragePermission();
while (isPromptingGrant) {
Thread.sleep(200);
}
} catch (InterruptedException e) {}
}
initMain();
return 0;
}
@Override
protected void onProgressUpdate(String... obj)
{
if (obj[0].equals("visible")) {
progress.setVisibility(View.VISIBLE);
} else if (obj.length == 2 && obj[1] != null) {
progressLog.append(obj[1]);
}
}
@Override
protected void onPostExecute(Integer obj) {
startAle.dismiss();
if (progressSpin != null) progressSpin.setVisibility(View.GONE);
if (obj == 0) {
if (progDlg != null) progDlg.dismiss();
uiInit();
} else if (progressLog != null) {
progressLog.setText(getResources().getString(R.string.error_checklog, "\n\n" + progressLog.getText()));
}
}
/*
private void appendlnToLog(String txt) {
publishProgress("", txt + "\n");
}
private void execCmd(String cmd) throws Exception {
appendlnToLog("> " + cmd);
ShellProcessOperation mainProcess = new ShellProcessOperation(new ShellProcessOperation.OnPrintListener(){
@Override
public void onPrintLine(String text)
{
publishProgress(text);
}
}, cmd);
mainProcess.initInputStream(MCLoginActivity.this);
String msgExit = cmd.split(" ")[0] + " has exited with code " + mainProcess.waitFor();
if (mainProcess.exitCode() != 0) {
throw new Error("(ERROR) " + msgExit);
} else {
appendlnToLog("(SUCCESS) " + msgExit);
}
}
*/
}
private void uiInit() {
setContentView(R.layout.launcher_login);
edit2 = (EditText) findViewById(R.id.launcherAccEmail);
edit3 = (EditText) findViewById(R.id.launcherAccPassword);
if(prb == null) prb = (ProgressBar) findViewById(R.id.launcherAccProgress);
sRemember = (Switch) findViewById(R.id.launcherAccRememberSwitch);
sOffline = (Switch) findViewById(R.id.launcherAccOffSwitch);
sOffline.setOnCheckedChangeListener(new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton p1, boolean p2)
{
// May delete later
edit3.setEnabled(!p2);
}
});
}
private boolean isAndroid7()
{
return Build.VERSION.SDK_INT >= 24;
}
/*
long lastTime = System.currentTimeMillis();
long lastDel = 0;
private void deAnr(String msg) {
long currt = System.currentTimeMillis();
lastDel = currt - lastTime;
lastTime = currt;
System.out.println("Time:" + lastDel + "ms||" + (lastDel / 1000) + "s: " + msg);
}
*/
@Override
public void onResume() {
super.onResume();
// Clear current profile
PojavProfile.setCurrentProfile(this, null);
}
/*
private boolean isOpenJDKInstalled() {
return firstLaunchPrefs.getBoolean(PREF_IS_INSTALLED_OPENJDK, false);
}
*/
private boolean isLibrariesExtracted() {
return firstLaunchPrefs.getBoolean(PREF_IS_INSTALLED_LIBRARIES, false);
}
private boolean setPref(String prefName, boolean value) {
return firstLaunchPrefs.edit().putBoolean(prefName, value).commit();
}
private void initMain()
{
File file0 = new File(Tools.mpProfiles);
File file1 = new File(Tools.mpModEnable);
File file2 = new File(Tools.mpModDisable);
File file3 = new File(Tools.mpModAddNewMo);
file0.mkdir();
file1.mkdirs();
file2.mkdir();
try {
file3.createNewFile();
} catch (IOException e){}
try {
mkdirs(Tools.MAIN_PATH);
Tools.copyAssetOptional(this, "options.txt", Tools.MAIN_PATH + "/gamedir");
//Tools.copyAssetToFolderIfNonExist(this, "dx-f" + (isAndroid7() ? "7" : "4") + ".0.jar", Tools.worksDir, "dx.jar");
Tools.copyAssetOptional(this, "multidoj.dex", Tools.worksDir);
// Copy ZIP!!!
//FileAccess.copyAssetToFolderIfNonExist(this, "1.0.jar", Tools.versnDir + "/1.0");
//FileAccess.copyAssetToFolderIfNonExist(this, "1.7.3.jar", Tools.versnDir + "/1.7.3");
//FileAccess.copyAssetToFolderIfNonExist(this, "1.7.10.jar", Tools.versnDir + "/1.7.10");
// Extract libraries
if (!isLibrariesExtracted()) {
mkdirs(Tools.worksDir);
mkdirs(Tools.versnDir);
Tools.extractAssetFolder(this, "libraries", Tools.worksDir);
setPref(PREF_IS_INSTALLED_LIBRARIES, true);
}
}
catch(Exception e){
Tools.showError(this, e);
}
}
private boolean mkdirs(String path)
{
File mFileeee = new File(path);
if(mFileeee.getParentFile().exists())
return mFileeee.mkdir();
else return mFileeee.mkdirs();
}
/*
public void loginUsername(View view)
{
LinearLayout mainLaun = new LinearLayout(this);
LayoutInflater.from(this).inflate(R.layout.launcher_user, mainLaun, true);
replaceFonts(mainLaun);
//edit1 = mainLaun.findViewById(R.id.launcherAccUsername);
new AlertDialog.Builder(this)
.setTitle("Register with username")
.setView(mainLaun)
.show();
}
*/
// developer methods
// end dev methods
public void loginSavedAcc(View view)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.login_select_account);
if (Tools.enableDevFeatures) {
/*
builder.setNegativeButton("Toggle v2", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
int ver = PojavV2ActivityManager.getLauncherRemakeInt(MCLoginActivity.this) == 0 ? 1 : 0;
PojavV2ActivityManager.setLauncherRemakeVer(MCLoginActivity.this, ver);
Toast.makeText(MCLoginActivity.this, "Changed to use v" + (ver + 1), Toast.LENGTH_SHORT).show();
}
});
*/
}
builder.setPositiveButton(android.R.string.cancel, null);
final AlertDialog dialog = builder.create();
/*
LinearLayout.LayoutParams lpHint, lpFlv;
lpHint = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lpFlv = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lpHint.weight = 1;
lpFlv.weight = 1;
*/
LinearLayout dialay = new LinearLayout(this);
dialay.setOrientation(LinearLayout.VERTICAL);
TextView fhint = new TextView(this);
fhint.setText(R.string.hint_select_account);
// fhint.setLayoutParams(lpHint);
final MFileListView flv = new MFileListView(this, dialog);
// flv.setLayoutParams(lpFlv);
flv.listFileAt(Tools.mpProfiles);
flv.setFileSelectedListener(new MFileSelectedListener(){
@Override
public void onFileLongClick(final File file, String path, String name, String extension)
{
AlertDialog.Builder builder2 = new AlertDialog.Builder(PojavLoginActivity.this);
builder2.setTitle(name);
builder2.setMessage(R.string.warning_remove_account);
builder2.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
// TODO: Implement this method
file.delete();
flv.refreshPath();
}
});
builder2.setNegativeButton(android.R.string.cancel, null);
builder2.show();
}
@Override
public void onFileSelected(File file, final String path, String nane, String extension)
{
try
{
if(MCProfile.load(path).isAccount()){
MCProfile.updateTokens(PojavLoginActivity.this, path, new RefreshListener(){
@Override
public void onFailed(Throwable e)
{
Tools.showError(PojavLoginActivity.this, e);
}
@Override
public void onSuccess()
{
MCProfile.launch(PojavLoginActivity.this, path);
}
});
} else {
MCProfile.launch(PojavLoginActivity.this, path);
}
dialog.hide();
//Tools.throwError(MCLoginActivity.this, new Exception(builder.getAccessToken() + "," + builder.getUUID() + "," + builder.getNickname() + "," + builder.getEmail() + "," + builder.getPassword()));
}
catch (Exception e)
{
Tools.showError(PojavLoginActivity.this, e);
}
}
});
dialay.addView(fhint);
dialay.addView(flv);
dialog.setView(dialay);
dialog.show();
}
private MCProfile.Builder loginOffline() {
new File(Tools.mpProfiles).mkdir();
String text = edit2.getText().toString();
if(text.isEmpty()){
edit2.setError(getResources().getString(R.string.login_error_empty_username));
} else if(text.length() <= 2){
edit2.setError(getResources().getString(R.string.login_error_short_username));
} else if(new File(Tools.mpProfiles + "/" + text).exists()){
edit2.setError(getResources().getString(R.string.login_error_exist_username));
} else{
MCProfile.Builder builder = new MCProfile.Builder();
builder.setIsAccount(false);
builder.setUsername(text);
return builder;
}
return null;
}
private MCProfile.Builder mProfile = null;
private AlertDialog warning;
public void loginMC(final View v)
{
/*skip it
String proFilePath = MCProfile.build(builder);
MCProfile.launchWithProfile(this, proFilePath);
end skip*/
if (sOffline.isChecked()) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(R.string.warning_title);
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
sRemember.setChecked(true);
mProfile = loginOffline();
playProfile();
}
});
alert.setNegativeButton(R.string.login_offline_alert_skip, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
mProfile = loginOffline();
playProfile();
}
});
alert.setNeutralButton(android.R.string.cancel, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
mProfile = null;
}
});
if (!sRemember.isChecked()) {
alert.setMessage(R.string.login_offline_warning_1);
warning = alert.show();
} else {
mProfile = loginOffline();
playProfile();
}
/*
while (warning != null && warning.isShowing()) {
}
*/
} else {
new LoginTask().setLoginListener(new LoginListener(){
@Override
public void onBeforeLogin()
{
// TODO: Implement this method
v.setEnabled(false);
prb.setVisibility(View.VISIBLE);
}
@Override
public void onLoginDone(String[] result)
{
// TODO: Implement this method
if(result[0].equals("ERROR")){
new AlertDialog.Builder(PojavLoginActivity.this)
.setTitle(R.string.error_title)
.setMessage(strArrToString(result))
.setPositiveButton(android.R.string.ok, null)
.show();
}
else{
MCProfile.Builder builder = new MCProfile.Builder();
builder.setAccessToken(result[1]);
builder.setClientID(result[2]);
builder.setProfileID(result[3]);
builder.setUsername(result[4]);
builder.setVersion("1.7.10");
mProfile = builder;
}
v.setEnabled(true);
prb.setVisibility(View.GONE);
playProfile();
}
}).execute(edit2.getText().toString(), edit3.getText().toString());
}
}
private void playProfile() {
if (mProfile != null) {
String profilePath = null;
if (sRemember.isChecked()) {
profilePath = MCProfile.build(mProfile);
}
MCProfile.launch(PojavLoginActivity.this, profilePath == null ? mProfile : profilePath);
}
}
public static String strArrToString(String[] strArr)
{
String[] strArrEdit = strArr;
strArrEdit[0] = "";
String str = Arrays.toString(strArrEdit);
str = str.substring(1, str.length() - 1).replace(",", "\n");
return str;
}
//We are calling this method to check the permission status
private boolean isStorageAllowed() {
//Getting the permission status
int result1 = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int result2 = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
//If permission is granted returning true
return result1 == PackageManager.PERMISSION_GRANTED &&
result2 == PackageManager.PERMISSION_GRANTED;
}
//Requesting permission
private void requestStoragePermission()
{
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_STORAGE_REQUEST_CODE);
}
//This method will be called when the user will tap on allow or deny
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//Checking the request code of our request
if(requestCode == REQUEST_STORAGE_REQUEST_CODE){
isPromptingGrant = false;
// isPermGranted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED;
}
}
}
@@ -0,0 +1,56 @@
package net.kdt.pojavlaunch;
import java.io.*;
import android.content.*;
public class PojavProfile
{
private static String PROFILE_PREF = "pojav_profile";
private static String PROFILE_PREF_FILE = "file";
private static String PROFILE_PREF_CONTENT = "content";
private static SharedPreferences getPrefs(Context ctx) {
return ctx.getSharedPreferences(PROFILE_PREF, Context.MODE_PRIVATE);
}
public static MCProfile.Builder getCurrentProfileContent(Context ctx) {
return MCProfile.parse(getPrefs(ctx).getString(PROFILE_PREF_CONTENT, ""));
}
public static String getCurrentProfilePath(Context ctx) {
return getPrefs(ctx).getString(PROFILE_PREF_FILE, "");
}
public static boolean setCurrentProfile(Context ctx, Object obj) {
SharedPreferences.Editor pref = getPrefs(ctx).edit();
try {
if (obj instanceof MCProfile.Builder) {
pref.putString(PROFILE_PREF_CONTENT, MCProfile.toString((MCProfile.Builder) obj));
} else if (obj instanceof String) {
pref.putString(PROFILE_PREF_FILE, (String) obj);
pref.putString(PROFILE_PREF_CONTENT, MCProfile.toString((String) obj));
} else if (obj == null) {
pref.putString(PROFILE_PREF_FILE, "");
pref.putString(PROFILE_PREF_CONTENT, "");
} else {
throw new IllegalArgumentException("Profile must be MCProfile.Builder.class, String.class or null");
}
} finally {
return pref.commit();
}
}
public static boolean isFileType(Context ctx) {
String profilePath = PojavProfile.getCurrentProfilePath(ctx);
String profileCon = MCProfile.toString(getCurrentProfileContent(ctx));
if (profileCon.equals(":::::")) {
throw new RuntimeException("Profile not set or reset.");
}
/*
if (true) {
throw new RuntimeException(profilePath + ":" + new File(profilePath).exists());
}
*/
return new File(profilePath).exists();
}
}
@@ -0,0 +1,37 @@
package net.kdt.pojavlaunch;
import android.content.*;
public class PojavV2ActivityManager
{
public static String CATEGORY_LAUNCHER = "launcher";
public static Class<?> LAUNCHER_V1 = MCLauncherActivity.class;
public static Class<?> LAUNCHER_V2 = LAUNCHER_V1; // PojavLauncherActivity.class;
public static boolean setLauncherRemakeClass(Context context, Class<?> cls) {
return setLauncherRemakeVer(context, cls.getName().equals(LAUNCHER_V1.getName()) ? 0 : 1);
}
public static boolean setLauncherRemakeVer(Context context, int i) {
Context context2 = context;
int i2 = i;
if (i2 >= 0 && i2 <= 1) {
return getPref(context2).edit().putInt(CATEGORY_LAUNCHER, i2).commit();
} else throw new IllegalArgumentException("ver must be 0 or 1");
}
public static int getLauncherRemakeInt(Context context) {
if (Tools.enableDevFeatures) {
return getPref(context).getInt(CATEGORY_LAUNCHER, 0);
} else {
return 0;
}
}
public static Class<?> getLauncherRemakeVer(Context context) {
return getLauncherRemakeInt(context) == 0 ? LAUNCHER_V1 : LAUNCHER_V2;
}
private static SharedPreferences getPref(Context ctx) {
return ctx.getSharedPreferences("remake", Context.MODE_PRIVATE);
}
}
@@ -0,0 +1,77 @@
package net.kdt.pojavlaunch;
import java.io.*;
import android.app.*;
public class ShellProcessOperation
{
private OnPrintListener listener;
private Process process;
public ShellProcessOperation(OnPrintListener listener) throws IOException {
this.listener = listener;
process = Runtime.getRuntime().exec("/system/bin/sh");
}
public ShellProcessOperation(OnPrintListener listener, String command) throws IOException {
this.listener = listener;
process = Runtime.getRuntime().exec(
command
); //"/system/bin/sh -c \"" + command + "\"");
}
public void writeToProcess(String cmd) throws IOException {
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes(cmd + "\n");
os.flush();
}
public void initInputStream(Activity ctx) {
ctx.runOnUiThread(new Runnable(){
@Override
public void run()
{
printStream(process.getInputStream());
printStream(process.getErrorStream());
}
});
}
public int exitCode() {
return process.exitValue();
}
public int waitFor() throws InterruptedException {
return process.waitFor();
}
public int exit() throws InterruptedException, IOException {
writeToProcess("exit");
return waitFor();
}
private void printStream(final InputStream stream) {
new Thread(new Runnable(){
@Override
public void run()
{
try {
BufferedReader buffStream = new BufferedReader(new InputStreamReader(stream));
String line = null;
while ((line = buffStream.readLine()) != null) {
listener.onPrintLine(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
listener.onPrintLine(e.getMessage() + "\n");
}
}
}).start();
}
public static interface OnPrintListener {
public void onPrintLine(String text);
}
}
@@ -0,0 +1,507 @@
package net.kdt.pojavlaunch;
import android.app.*;
import android.content.*;
import android.content.res.*;
import android.net.*;
import android.os.*;
import android.util.*;
import com.google.gson.*;
import dalvik.system.*;
import java.io.*;
import java.lang.reflect.*;
import java.nio.charset.*;
import java.util.*;
import java.util.zip.*;
import net.kdt.pojavlaunch.util.*;
import net.kdt.pojavlaunch.value.*;
import org.apache.commons.codec.digest.*;
import android.widget.*;
public final class Tools
{
public static boolean enableDevFeatures = true;
public static String APP_NAME = "null";
public static String MAIN_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/games/minecraft";
public static String ASSETS_PATH = MAIN_PATH + "/gamedir/assets";
public static int usingVerCode = 1;
public static String usingVerName = "2.0";
public static String mhomeUrl = "http://mineup.eu5.net"; // "http://kdtjavacraft.eu5.net";
public static String mainpath = "/data/data/net.kdt.pojavlaunch";
public static String worksDir = mainpath + "/app_working_dir";
public static String versnDir = worksDir + "/version";
public static String libraries = worksDir + "/libraries";
public static String mpProfiles = mainpath + "/Users";
public static String crashPath = Tools.MAIN_PATH + "/gamedir/crash-reports";
public static String mpModEnable = mainpath + "/ModsManager/✅Enabled";
public static String mpModDisable = mainpath + "/ModsManager/❌Disabled";
public static String mpModAddNewMo = mainpath + "/ModsManager/➕Add mod";
public static String[] versionList = {
"1.7.3",
"1.7.10",
"1.8",
"1.9"
};
public static String artifactToPath(String group, String artifact, String version) {
return group.replaceAll("\\.", "/") + "/" + artifact + "/" + version + "/" + artifact + "-" + version + ".jar";
}
public static String getPatchedFile(String version) {
return versnDir + "/" + version + "/multidoj/patched" + version + ".jar";
}
/*
* Implements to get multidoj dexed folder
*/
//private static boolean isPatched = false;
public static String returnMultidojOrFile(String jarPath, final boolean isClient)
{
//isPatched = false;
if (new File(jarPath).exists()) {
// Check if jar file is exists
return ":" + jarPath;// + ":";
}
StringBuilder sb = new StringBuilder();
File file = new File(jarPath.substring(0, jarPath.lastIndexOf("/")) + "/multidoj");
File[] classes = file.listFiles(new FilenameFilter(){
@Override
public boolean accept(File dir, String name)
{
if (isClient) {
if (name.endsWith(".dex") || name.startsWith("patched")) {
return true;
}
} else {
if (name.endsWith(".dex") || name.endsWith(".jar")) {
return true;
}
}
return false;
}
});
try {
for (File f : classes) {
sb.append(":" + f.getAbsolutePath());// + ":");
}
} catch (Exception e) {
// skip broken library
return "";
}
return ":" + sb.toString();
}
// May useless
public static boolean isOptifineInstalled(String version)
{
return new File(versnDir + "/" + version + "/multidoj/optifine.jar").exists();
}
public static String generate(String version) throws IOException
{
StringBuilder libStr = new StringBuilder(); //versnDir + "/" + version + "/" + version + ".jar:";
String[] classpath = Tools.generateLibClasspath(Tools.getVersionInfo(version).libraries);
libStr.append(returnMultidojOrFile(versnDir + "/" + version + "/" + version + ".jar", true).substring(1));
//libStr.append(getPatchedFile(version));
for (String perclass : classpath) {
libStr.append(returnMultidojOrFile(perclass, false));
}
return libStr.toString();
}
public static DisplayMetrics getDisplayMetrics(Activity ctx) {
DisplayMetrics displayMetrics = new DisplayMetrics();
ctx.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics;
}
public static void extractAssetFolder(Activity ctx, String path, String output) throws Exception
{
AssetManager assetManager = ctx.getAssets();
String assets[] = null;
try {
assets = assetManager.list(path);
if (assets.length == 0) {
Tools.copyAssetOptional(ctx, path, output);
} else {
String fullPath = output + "/" + path;
File dir = new File(fullPath);
if (!dir.exists())
dir.mkdir();
for (String sub : assets) {
extractAssetFolder(ctx, path + "/" + sub, output);
}
}
} catch (Exception e) {
showError(ctx, e);
}
}
/*
public static void extractLibraries(Activity ctx) throws Exception
{
extractAssetFolder(ctx, "libraries", worksDir);
}
*/
public static void showError(Activity ctx, Throwable e)
{
showError(ctx, e, false);
}
public static void showError(final Activity ctx, final Throwable e, final boolean exitIfOk)
{
showError(ctx, e, exitIfOk, false);
}
private static void showError(final Activity ctx, final Throwable e, final boolean exitIfOk, final boolean showMore)
{
ctx.runOnUiThread(new Runnable(){
@Override
public void run()
{
final String errMsg = showMore ? Log.getStackTraceString(e): e.getMessage();
new AlertDialog.Builder((Context) ctx)
.setTitle(R.string.error_title)
.setMessage(errMsg)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
if(exitIfOk) MainActivity.fullyExit();
}
})
.setNegativeButton(showMore ? R.string.error_show_less : R.string.error_show_more, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
showError(ctx, e, exitIfOk, !showMore);
}
})
.setNeutralButton(android.R.string.copy, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface p1, int p2)
{
ClipboardManager clipboard = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Error", errMsg);
clipboard.setPrimaryClip(clip);
Toast.makeText(ctx, "Copied to clipboard", Toast.LENGTH_SHORT).show();
if(exitIfOk) MainActivity.fullyExit();
}
})
//.setNegativeButton("Report (not available)", null)
.setCancelable(!exitIfOk)
.show();
}
});
}
public static void dialogOnUiThread(final Activity ctx, final CharSequence title, final CharSequence message)
{
ctx.runOnUiThread(new Runnable(){
@Override
public void run()
{
// TODO: Implement this method
new AlertDialog.Builder(ctx)
.setTitle(title)
.setMessage(message)
.setPositiveButton(android.R.string.ok, null)
.show();
}
});
}
public static void openURL(Activity act, String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
act.startActivity(browserIntent);
}
public static void clearDuplicateFiles(File f) throws IOException {
List<File> list = Arrays.asList(f.listFiles());
for (File file : list) {
if (!file.exists()) {
// The file was deleted by duplicate
list.remove(file);
continue;
}
String md5 = DigestUtils.md5Hex(new FileInputStream(file));
list.remove(file);
clearDuplicateFilesByMD5(list.toArray(new File[0]), md5);
}
}
public static void clearDuplicateFilesByMD5(File[] list, String md5Find) throws IOException {
for (File file : list) {
String md5Other = DigestUtils.md5Hex(new FileInputStream(file));
if (md5Find.equals(md5Other)) {
file.delete();
}
}
}
public static String[] generateLibClasspath(DependentLibrary[] libs)
{
List<String> libDir = new ArrayList<String>();
for (DependentLibrary libItem: libs) {
String[] libInfos = libItem.name.split(":");
if (libItem.name.equals("net.minecraft:launchwrapper:1.5")) {
libInfos[2] = "1.6";
libDir.add(Tools.libraries + "/" + Tools.artifactToPath(libInfos[0], libInfos[1], libInfos[2]));
} else {
libDir.add(Tools.libraries + "/" + Tools.artifactToPath(libInfos[0], libInfos[1], libInfos[2]));
}
}
return libDir.toArray(new String[0]);
}
public static void runDx(final Activity ctx, String fileIn, String fileOut, MultidojManager.Listen listener) throws Exception
{
MultidojManager.setListener(listener);
File optDir = ctx.getDir("dalvik-cache", 0);
optDir.mkdirs();
File out = new File(fileOut);
File newFileOut = new File(out.getParent() + File.separator + "multidoj" + File.separator + "resources" + (System.currentTimeMillis()) + ".jar");
newFileOut.getParentFile().mkdirs();
//Class
DexClassLoader mainLoader = new DexClassLoader(Tools.worksDir + "/multidoj.dex", optDir.getAbsolutePath(), ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).applicationInfo.nativeLibraryDir, MainActivity.class.getClassLoader());
String receiveMethod = "net.kdt.pojavlaunch.MultidojManager->call(message:String, max:Integer, current:Integer)";
mainLoader.loadClass("com.android.dx.observer.ObserverStatus").getMethod("setReceiver", String.class).invoke(null, receiveMethod);
Class mainClass = mainLoader.loadClass("com.android.dx.command.Main");
Method mainMethod = mainClass.getMethod("main", new String[]{}.getClass());
mainMethod.invoke(null, new Object[]{new String[]{"--dex", "--output", newFileOut.getAbsolutePath(), fileIn}});
//com.android.dx.mod.Main.dexTheJar(fileIn, fileOut, ctx.getCacheDir().getAbsolutePath(), listener);
//return Runtime.getRuntime().exec("echo IN:" + fileIn + ";OUT:" + fileOut);
}
public static MinecraftVersion getVersionInfo(String versionName) throws IOException {
File versionFile = new File(Tools.versnDir + "/" + versionName + "/" + versionName + ".json");
/*
if (!versionFile.exists()) {
return downloadVersionInfo(versionName);
}
*/
byte[] versionDat = new byte[((int) versionFile.length())];
FileInputStream is = new FileInputStream(versionFile);
is.read(versionDat);
is.close();
return new Gson().fromJson(new String(versionDat, Charset.forName("UTF-8")), MinecraftVersion.class);
}
public static String convertStream(InputStream inputStream, Charset charset) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
String line = null;
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, charset))) {
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
}
return stringBuilder.toString();
}
// Current Useless below but keep it for future usage.
public static void deleteRecursive(File fileOrDirectory) {
try {
if (fileOrDirectory.isDirectory()) {
for (File child : fileOrDirectory.listFiles()) {
deleteRecursive(child);
}
}
} finally {
fileOrDirectory.delete();
}
}
public static File lastFileModified(String dir) {
File fl = new File(dir);
File[] files = fl.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isFile();
}
});
long lastMod = Long.MIN_VALUE;
File choice = null;
for (File file : files) {
if (file.lastModified() > lastMod) {
choice = file;
lastMod = file.lastModified();
}
}
return choice;
}
public static byte[] getByteArray(String filePath) throws Exception
{
return getByteArray(new FileInputStream(filePath));
}
public static byte[] getByteArray(InputStream stream) throws IOException
{
byte[] bytes = new byte[stream.available()];
BufferedInputStream buf = new BufferedInputStream(stream);
buf.read(bytes, 0, bytes.length);
buf.close();
return bytes;
}
public static String read(String path) throws Exception
{
return new String(getByteArray(path));
}
public static void write(String path, byte[] content) throws Exception
{
FileOutputStream fos = new FileOutputStream(path);
fos.write(content);
fos.close();
}
public static void write(String path, String content) throws Exception
{
write(path, content.getBytes());
}
public static byte[] loadFromAssetToByte(Context ctx, String inFile) {
byte[] tContents = {};
try {
InputStream stream = ctx.getAssets().open(inFile);
int size = stream.available();
byte[] buffer = new byte[size];
stream.read(buffer);
stream.close();
tContents = buffer;
} catch (IOException e) {
// Handle exceptions here
e.printStackTrace();
}
return tContents;
}
public static void copyAssetOptional(Context ctx, String fileName, String output) throws Exception
{
copyAssetOptional(ctx, fileName, output, fileName);
}
public static void copyAssetOptional(Context ctx, String fileName, String output, String outputName) throws Exception
{
try {
File file = new File(output);
if(!file.exists()) file.mkdirs();
File file2 = new File(output + "/" + outputName);
if(!file2.exists()){
if (!file2.createNewFile()) throw new RuntimeException("Unable to write " + output + "/" + outputName);
write(file2.getAbsolutePath(), loadFromAssetToByte(ctx, fileName));
}
} catch (Throwable th) {
throw new RuntimeException("Unable to copy " + fileName + " to " + output + "/" + outputName, th);
}
}
public static void downloadFile(String urlInput, String nameOutput, boolean requireNonExist) throws Throwable
{
File fileDDD = new File(nameOutput);
if(requireNonExist && !fileDDD.exists())
{
DownloadUtils.downloadFile(urlInput, fileDDD);
}
}
public static class ZipTool
{
private ZipTool(){}
public static void zip(List<File> files, File zipFile) throws IOException {
final int BUFFER_SIZE = 2048;
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
try {
byte data[] = new byte[BUFFER_SIZE];
for (File file : files) {
FileInputStream fileInputStream = new FileInputStream( file );
origin = new BufferedInputStream(fileInputStream, BUFFER_SIZE);
try {
ZipEntry entry = new ZipEntry(file.getName());
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
}
finally {
origin.close();
}
}
} finally {
out.close();
}
}
public static void unzip(File zipFile, File targetDirectory) throws IOException {
final int BUFFER_SIZE = 1024;
ZipInputStream zis = new ZipInputStream(
new BufferedInputStream(new FileInputStream(zipFile)));
try {
ZipEntry ze;
int count;
byte[] buffer = new byte[BUFFER_SIZE];
while ((ze = zis.getNextEntry()) != null) {
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " +
dir.getAbsolutePath());
if (ze.isDirectory())
continue;
FileOutputStream fout = new FileOutputStream(file);
try {
while ((count = zis.read(buffer)) != -1)
fout.write(buffer, 0, count);
} finally {
fout.close();
}
/* if time should be restored as well
long time = ze.getTime();
if (time > 0)
file.setLastModified(time);
*/
}
} finally {
zis.close();
}
}
}
}
@@ -0,0 +1,62 @@
package net.kdt.pojavlaunch;
import android.app.*;
import android.graphics.*;
import android.os.*;
import android.widget.*;
import dalvik.system.*;
import java.io.*;
import java.lang.reflect.*;
import net.kdt.pojavlaunch.*;
import net.kdt.pojavlaunch.libs.*;
import android.util.*;
public class UpdateAppActivity extends Activity
{
private ProgressBar progress;
private TextView logView;
private boolean cancelable = false;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.launcher_update);
progress = (ProgressBar) findViewById(R.id.launcherupdateProgressBar);
logView = (TextView) findViewById(R.id.launcherupdateLogView);
logView.setTypeface(Typeface.MONOSPACE);
File inst = new File(Tools.worksDir + "/installer.jar");
try {
File optDir = getDir("dalvik-cache", 0);
optDir.mkdirs();
DexClassLoader mainLoader = new DexClassLoader(inst.getAbsolutePath(), optDir.getAbsolutePath(), getPackageManager().getPackageInfo(getPackageName(), 0).applicationInfo.nativeLibraryDir, MainActivity.class.getClassLoader());
Class mClass = mainLoader.loadClass("Main");
Method method = mClass.getMethod("main", UpdateAppActivity.class);
method.invoke(null, this);
} catch (Throwable th) {
putLog("----- AN ERROR OCCURRED -----");
putLog(Log.getStackTraceString(th));
putLog("----- FAILED TO UPDATE! -----");
} finally {
cancelable = true;
}
}
public void putLog(String message)
{
logView.append(message + "\n");
}
public ProgressBar getProgressBar()
{
return progress;
}
@Override
public void onBackPressed()
{
if (cancelable) super.onBackPressed();
}
}
@@ -0,0 +1,62 @@
package net.kdt.pojavlaunch;
import android.view.*;
public class WindowAnimation
{
public static void fadeIn(final View view, int duration) {
// 0.1 -> 1.0
doFade(view, true, duration);
}
public static void fadeOut(final View view, int duration) {
// 1.0 -> 0.1
doFade(view, false, duration);
}
private static void doFade(final View view, final boolean fadeIn, int duration) {
final long millis = ((long) duration) / 10l;
view.setVisibility(View.VISIBLE);
view.setAlpha(fadeIn ? 0 : 1);
view.setEnabled(false);
new Thread(new Runnable(){
private float alpha = fadeIn ? 0 : 1;
@Override
public void run()
{
try {
while (fadeIn ? alpha < 1 : alpha > 0) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {}
if (fadeIn) alpha += 0.1;
else alpha -= 0.1;
view.post(new Runnable(){
@Override
public void run()
{
view.setAlpha(alpha);
}
});
}
} finally {
view.post(new Runnable(){
@Override
public void run()
{
if (fadeIn) view.setEnabled(true);
else {
view.setVisibility(View.GONE);
}
}
});
}
}
}).start();
}
}
@@ -0,0 +1,69 @@
package net.kdt.pojavlaunch.exit;
import java.lang.reflect.*;
public class ExitManager {
private static boolean stopLoop = false;
private static ExitTrappedListener listener;
private static Thread exitTrappedHook = new Thread(new Runnable(){
@Override
public void run()
{
if (listener != null) listener.onExitTrapped();
// Pre-check
// if (stopLoop) stopLoop = false;
while (true) {
if (stopLoop) {
stopLoop = false;
break;
}
// Make Thread hook never stop, then System.exit() never continue!
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
stopLoop = false;
}
});
public static void setExitTrappedListener(ExitTrappedListener l) {
listener = l;
}
public static void stopExitLoop() {
stopLoop = true;
}
public static void disableSystemExit() // throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException
{
// changeRuntimeExitDisabled(true);
Runtime.getRuntime().addShutdownHook(exitTrappedHook);
}
public static void enableSystemExit() // throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException
{
// changeRuntimeExitDisabled(false);
Runtime.getRuntime().removeShutdownHook(exitTrappedHook);
}
// It's not safe. Add/Remove shutdown hooks will cause error.
private static void changeRuntimeExitDisabled(boolean value) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException {
Runtime run = Runtime.getRuntime();
Field shutdownField = run.getClass().getDeclaredField("shuttingDown");
shutdownField.setAccessible(true);
shutdownField.set(run, value);
}
public static interface ExitTrappedListener {
public void onExitTrapped();
}
}
@@ -0,0 +1,12 @@
package net.kdt.pojavlaunch.exit;
public class ExitTrappedException extends RuntimeException
{
public ExitTrappedException() {
super();
}
public ExitTrappedException(String message) {
super(message);
}
}
@@ -0,0 +1,15 @@
package net.kdt.pojavlaunch.libs;
import com.google.gson.*;
import java.io.*;
import java.nio.charset.*;
import net.kdt.pojavlaunch.value.*;
import net.kdt.pojavlaunch.*;
public class LibrariesManager
{
public static MinecraftVersion getVersionInfo(String versionJsonDir) throws Exception {
String versionStr = Tools.read(versionJsonDir);
return new Gson().fromJson(versionStr, MinecraftVersion.class);
}
}
@@ -0,0 +1,73 @@
package net.kdt.pojavlaunch.mcfragments;
import android.os.*;
import android.support.annotation.*;
import android.support.v4.app.*;
import android.view.*;
import android.widget.*;
import java.io.*;
import net.kdt.pojavlaunch.*;
import android.util.*;
import android.graphics.*;
public class ConsoleFragment extends Fragment
{
public TextView consoleView;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.lmaintab_consolelog, container, false);
consoleView = (TextView) view.findViewById(R.id.lmaintabconsoleLogTextView);
consoleView.setTypeface(Typeface.MONOSPACE);
consoleView.setHint("No log");
return view;
}
@Override
public void onActivityCreated(Bundle p1)
{
super.onActivityCreated(p1);
/*
new Thread(new Runnable(){
@Override
public void run()
{
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
final String popLog = ConsoleFragmentHelper.popLog();
if (!popLog.isEmpty()) {
getActivity().runOnUiThread(new Runnable(){
@Override
public void run()
{
consoleView.append(popLog);
System.out.println("OKAY? " + popLog);
}
});
}
}
}
}).start();
*/
}
@Override
public void onResume()
{
super.onResume();
consoleView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogTextView);
}
public void putLog(String str) {
if (consoleView == null) {
consoleView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogTextView);
}
consoleView.append(str);
}
}
@@ -0,0 +1,72 @@
package net.kdt.pojavlaunch.mcfragments;
import android.os.*;
import android.support.annotation.*;
import android.support.v4.app.*;
import android.view.*;
import android.widget.*;
import java.io.*;
import net.kdt.pojavlaunch.*;
import android.util.*;
import android.graphics.*;
public class CrashFragment extends Fragment
{
public static String lastCrashSaved = "";
private String crashContent;
public boolean resetCrashLog = false;
private TextView crashView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.lmaintab_crashlog, container, false);
return view;
}
@Override
public void onActivityCreated(Bundle p1)
{
super.onActivityCreated(p1);
crashView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogCrashTextView);
crashView.setTypeface(Typeface.MONOSPACE);
crashView.setHint("No crash detected.");
//new File(crashPath).mkdirs();
}
@Override
public void onResume()
{
super.onResume();
refreshCrashFile();
}
public static boolean isNewCrash(File crashLog) throws Exception {
String content = Tools.read(crashLog.getAbsolutePath());
return crashLog != null && content.startsWith("---- Minecraft Crash Report ----");
}
public void refreshCrashFile()
{
try {
if(!resetCrashLog){
File crashLog = Tools.lastFileModified(Tools.crashPath);
if (isNewCrash(crashLog)) {
crashContent = Tools.read(crashLog.getAbsolutePath());
Tools.write(crashLog.getAbsolutePath(), "\n" + crashContent);
lastCrashSaved = crashLog.getName();
crashView.setText(crashContent);
} else if(crashLog.getName().equals(lastCrashSaved)){
crashView.setText(crashContent);
}
else throw new Exception();
}
else throw new Exception();
} catch (Exception e) {
// Can't find crash or no NEW crashes
crashView.setText(""/*Log.getStackTraceString(e)*/);
}
}
}
@@ -0,0 +1,35 @@
package net.kdt.pojavlaunch.mcfragments;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.webkit.WebView;
import android.webkit.WebChromeClient;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.*;
public class LauncherFragment extends Fragment
{
private WebView webNews;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.lmaintab_news, container, false);
return view;
}
@Override
public void onActivityCreated(Bundle p1)
{
super.onActivityCreated(p1);
webNews = (WebView) getView().findViewById(R.id.lmaintabnewsNewsView);
webNews.setWebChromeClient(new WebChromeClient(){});
webNews.clearCache(true);
webNews.getSettings().setJavaScriptEnabled(true);
webNews.loadUrl(Tools.mhomeUrl + "/changelog.html");
}
}
@@ -0,0 +1,17 @@
package net.kdt.pojavlaunch.optifine;
import com.google.gson.*;
import java.nio.charset.*;
import net.kdt.pojavlaunch.value.*;
import net.kdt.pojavlaunch.util.*;
import java.io.*;
import net.kdt.pojavlaunch.*;
public class Optifine
{
public static OptifineVersion.VersionList getList() throws Exception
{
String optifineStr = DownloadUtils.downloadString(Tools.mhomeUrl + "/optifine.json");
return new Gson().fromJson(optifineStr, OptifineVersion.VersionList.class);
}
}
@@ -0,0 +1,10 @@
package net.kdt.pojavlaunch.optifine;
public class OptifineVersion
{
public VersionList[] versions;
public static class VersionList {
public String version;
public String linkUrl;
}
}
@@ -0,0 +1,107 @@
package net.kdt.pojavlaunch.signer;
import android.util.*;
import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
import net.kdt.pojavlaunch.*;
//import org.apache.commons.codec.digest.*;
import net.kdt.pojavlaunch.util.*;
public class JarSigner
{
private static final String DEX_IN_JAR_NAME = "classes.dex";
private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
private TreeMap<String, byte[]> outputResources = new TreeMap<String, byte[]>();
public static void sign(String inputJar, String outputJar) throws Exception
{
new JarSigner(inputJar, outputJar);
}
private JarSigner(String inputJar, String outputJar) throws Exception
{
ZipFile jarFile = new ZipFile(inputJar);
Enumeration<? extends ZipEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
outputResources.put(entry.getName(), Tools.getByteArray(jarFile.getInputStream(entry)));
}
createJar(outputJar);
}
private byte[] makeManifest() {
StringBuilder baos = new StringBuilder();
// First, put some general information:
baos.append("Manifest-Version: 1.0\n");
baos.append("Created-By: " + Tools.usingVerName + " (" + Tools.APP_NAME + ": JarSigner)\n");
baos.append("Build-Jdk: 1.6.0_29");
baos.append("Dex-Location: " + DEX_IN_JAR_NAME + "\n");
return baos.toString().getBytes();
}
private boolean createJar(String fileName) {
/*
* Make or modify the manifest (as appropriate), put the dex
* array into the resources map, and then process the entire
* resources map in a uniform manner.
*/
try {
byte[] manifest = makeManifest();
OutputStream out = new FileOutputStream(fileName);
JarOutputStream jarOut = new JarOutputStream(out);
try {
for (Map.Entry<String, byte[]> e : outputResources.entrySet()) {
String name = e.getKey();
byte[] contents = e.getValue();
JarEntry entry = new JarEntry(name);
int length = contents.length;
entry.setSize(length);
/*
if (args.verbose) {
context.out.println("writing " + name + "; size " + length + "...");
}
*/
if (name.endsWith(".SF") ||
name.endsWith(".RSA")) {
// Remove these files.
continue;
} else if (name.endsWith(MANIFEST_PATH)) {
length = manifest.length;
jarOut.putNextEntry(entry);
jarOut.write(manifest);
jarOut.closeEntry();
} else {
jarOut.putNextEntry(entry);
jarOut.write(contents);
jarOut.closeEntry();
}
}
} finally {
jarOut.finish();
jarOut.flush();
closeOutput(out);
}
} catch (Exception ex) {
throw new RuntimeException("Trouble writing output:", ex);
}
return true;
}
private void closeOutput(OutputStream stream) throws IOException {
if (stream == null) {
return;
}
stream.flush();
if (stream != System.out) {
stream.close();
}
}
}
@@ -0,0 +1,90 @@
package net.kdt.pojavlaunch.util;
import android.util.*;
import java.io.*;
import java.net.*;
import java.nio.charset.*;
import net.kdt.pojavlaunch.*;
public class DownloadUtils {
public static final String USER_AGENT = Tools.APP_NAME;
public static final Charset utf8 = Charset.forName("UTF-8");
public static void download(String url, OutputStream os) {
try {
download(new URL(url), os);
} catch (Throwable malformed) {
throw new RuntimeException(malformed);
}
}
public static void download(URL url, OutputStream os) throws Throwable {
InputStream is = null;
byte[] buf; // 16384
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("User-Agent", USER_AGENT);
conn.setConnectTimeout(2000);
conn.setDoInput(true);
conn.connect();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new RuntimeException("Server returned HTTP " + conn.getResponseCode()
+ ": " + conn.getResponseMessage());
}
buf = new byte[conn.getContentLength()];
is = conn.getInputStream();
IoUtil.pipe(is, os, buf);
} finally {
if (is != null) {
try {
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static String downloadString(String url) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
download(url, bos);
return new String(bos.toByteArray(), utf8);
}
public static void downloadFile(String url, File out) throws Throwable {
out.getParentFile().mkdirs();
File tempOut = File.createTempFile(out.getName(), ".part", out.getParentFile());
BufferedOutputStream bos = null;
try {
OutputStream bos2 = new BufferedOutputStream(new FileOutputStream(tempOut));
try {
download(url, bos2);
tempOut.renameTo(out);
if (bos2 != null) {
bos2.close();
}
if (tempOut.exists()) {
tempOut.delete();
}
} catch (Throwable th2) {
if (bos != null) {
bos.close();
}
if (tempOut.exists()) {
tempOut.delete();
}
throw th2;
}
} catch (Throwable th3) {
if (bos != null) {
bos.close();
}
if (tempOut.exists()) {
tempOut.delete();
}
throw th3;
}
}
}
@@ -0,0 +1,107 @@
package net.kdt.pojavlaunch.util;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import net.kdt.pojavlaunch.*;
import android.os.*;
public class IoUtil {
//public static volatile boolean cancel = false;
private IoUtil() {
}
public static void pipe( /*PojavLauncherActivity activity,*/ InputStream is, OutputStream out, byte[] buf) throws IOException {
while (true) {
//if (cancel) throw new CancelException();
int amt = is.read(buf);
if (amt >= 0) {
out.write(buf, 0, amt);
} else {
return;
}
}
}
public static void copy(File from, File to, byte[] buf) throws IOException {
InputStream in = new FileInputStream(from);
OutputStream out;
try {
out = new FileOutputStream(to);
pipe(in, out, buf);
out.close();
in.close();
} catch (Throwable th) {
in.close();
}
}
public static void copyZipWithoutEmptyDirectories(File inputFile, File outputFile) throws IOException {
byte[] buf = new byte[8192];
ZipFile inputZip = new ZipFile(inputFile);
ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(outputFile));
try {
Enumeration<? extends ZipEntry> e = inputZip.entries();
ArrayList<ZipEntry> sortedList = new ArrayList();
while (e.hasMoreElements()) {
sortedList.add((ZipEntry) e.nextElement());
}
Collections.sort(sortedList, new Comparator<ZipEntry>() {
public int compare(ZipEntry o1, ZipEntry o2) {
return o1.getName().compareTo(o2.getName());
}
});
for (int i = sortedList.size() - 1; i >= 0; i--) {
boolean isEmptyDirectory;
ZipEntry inputEntry = (ZipEntry) sortedList.get(i);
String name = inputEntry.getName();
if (!inputEntry.isDirectory()) {
isEmptyDirectory = false;
} else if (i == sortedList.size() - 1) {
isEmptyDirectory = true;
} else {
isEmptyDirectory = !((ZipEntry) sortedList.get(i + 1)).getName().startsWith(name);
}
if (isEmptyDirectory) {
sortedList.remove(inputEntry);
} else {
outputStream.putNextEntry(new ZipEntry(inputEntry));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = inputZip.getInputStream(inputEntry);
pipe(is, baos, buf);
is.close();
outputStream.write(baos.toByteArray());
}
}
} finally {
outputStream.close();
}
}
public static void clearDirectory(File dir) {
File[] fileList = dir.listFiles();
if (fileList != null) {
for (File f : fileList) {
if (f.isDirectory()) {
clearDirectory(f);
}
f.delete();
}
}
}
}
@@ -0,0 +1,12 @@
package net.kdt.pojavlaunch.value;
public class DependentLibrary {
public String name;
public MDownloads downloads;
public static class MDownloads
{
public MinecraftLibraryArtifact artifact;
}
}
@@ -0,0 +1,8 @@
package net.kdt.pojavlaunch.value;
public class MinecraftClientInfo
{
public String sha1;
public int size;
public String url;
}
@@ -0,0 +1,6 @@
package net.kdt.pojavlaunch.value;
public class MinecraftLibraryArtifact extends MinecraftClientInfo
{
public String path;
}
@@ -0,0 +1,13 @@
package net.kdt.pojavlaunch.value;
import java.util.Map;
public class MinecraftVersion
{
public String assets;
public Map<String, MinecraftClientInfo> downloads;
public DependentLibrary[] libraries;
public String mainClass;
public String minecraftArguments;
public int minimumLauncherVersion;
}
@@ -0,0 +1,5 @@
package net.kdt.pojavlaunch.views;
public class MineButton
{
}
@@ -0,0 +1,11 @@
package net.minecraft.client;
public class ClientBrandRetriever {
public ClientBrandRetriever() {
//ClientBrandRetriever clientBrandRetriever = this;
}
public static String getClientModName() {
return "PojavLauncher";
}
}
@@ -0,0 +1,25 @@
package net.minecraft.launchwrapper;
import java.io.File;
import java.util.List;
public class AlphaVanillaTweaker implements ITweaker {
private List<String> args;
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = args;
}
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
classLoader.registerTransformer("net.minecraft.launchwrapper.injector.AlphaVanillaTweakInjector");
}
public String getLaunchTarget() {
return "net.minecraft.launchwrapper.injector.AlphaVanillaTweakInjector";
}
public String[] getLaunchArguments() {
return (String[]) this.args.toArray(new String[this.args.size()]);
}
}
@@ -0,0 +1,8 @@
package net.minecraft.launchwrapper;
public interface IClassNameTransformer {
String remapClassName(String str);
String unmapClassName(String str);
}
@@ -0,0 +1,6 @@
package net.minecraft.launchwrapper;
public interface IClassTransformer {
byte[] transform(String str, String str2, byte[] bArr);
}
@@ -0,0 +1,15 @@
package net.minecraft.launchwrapper;
import java.io.File;
import java.util.List;
public interface ITweaker {
void acceptOptions(List<String> list, File file, File file2, String str);
String[] getLaunchArguments();
String getLaunchTarget();
void injectIntoClassLoader(LaunchClassLoader launchClassLoader);
}
@@ -0,0 +1,25 @@
package net.minecraft.launchwrapper;
import java.io.File;
import java.util.List;
public class IndevVanillaTweaker implements ITweaker {
private List<String> args;
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = args;
}
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
classLoader.registerTransformer("net.minecraft.launchwrapper.injector.IndevVanillaTweakInjector");
}
public String getLaunchTarget() {
return "net.minecraft.launchwrapper.injector.AlphaVanillaTweakInjector";
}
public String[] getLaunchArguments() {
return (String[]) this.args.toArray(new String[this.args.size()]);
}
}
@@ -0,0 +1,52 @@
package net.minecraft.launchwrapper;
import java.io.*;
import java.lang.reflect.*;
import java.util.logging.*;
import java.util.logging.Level;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
public class Launch {
private static final String DEFAULT_TWEAK = "net.minecraft.launchwrapper.VanillaTweaker";
public static File assetsDir;
public static LaunchClassLoader classLoader;
public static File minecraftHome;
public static void main(String[] args) {
new Launch().launch(args);
}
private Launch() {
classLoader = (LaunchClassLoader) Thread.currentThread().getContextClassLoader(); // getClass().getClassLoader(); //((URLClassLoader) getClass().getClassLoader()).getURLs());
}
private void launch(String[] args) {
OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();
OptionSpec<String> profileOption = parser.accepts("version", "The version we launched with").withRequiredArg();
OptionSpec<File> gameDirOption = parser.accepts("gameDir", "Alternative game directory").withRequiredArg().ofType(File.class);
OptionSpec<File> assetsDirOption = parser.accepts("assetsDir", "Assets directory").withRequiredArg().ofType(File.class);
OptionSpec<String> tweakClassOption = parser.accepts("tweakClass", "Tweak class to load").withRequiredArg().defaultsTo(DEFAULT_TWEAK, new String[0]);
OptionSpec<String> nonOption = parser.nonOptions();
OptionSet options = parser.parse(args);
minecraftHome = (File) options.valueOf(gameDirOption);
assetsDir = (File) options.valueOf(assetsDirOption);
String profileName = (String) options.valueOf(profileOption);
String tweakClassName = (String) options.valueOf(tweakClassOption);
try {
LogWrapper.log(Level.INFO, "Using tweak class name %s", new Object[]{tweakClassName});
classLoader.addClassLoaderExclusion(tweakClassName.substring(0, tweakClassName.lastIndexOf(46)));
ITweaker tweaker = (ITweaker) Class.forName(tweakClassName, true, classLoader).newInstance();
tweaker.acceptOptions(options.valuesOf(nonOption), minecraftHome, assetsDir, profileName);
tweaker.injectIntoClassLoader(classLoader);
Method mainMethod = Class.forName(tweaker.getLaunchTarget(), false, classLoader).getMethod("main", new Class[]{String[].class});
LogWrapper.info("Launching wrapped minecraft", new Object[0]);
mainMethod.invoke(null, new Object[]{tweaker.getLaunchArguments()});
} catch (Exception e) {
LogWrapper.log(Level.SEVERE, e, "Unable to launch", new Object[0]);
}
}
}
@@ -0,0 +1,489 @@
package net.minecraft.launchwrapper;
import dalvik.system.*;
import java.io.*;
import java.net.*;
import java.security.*;
import java.util.*;
import java.util.jar.*;
import java.util.jar.Attributes.*;
import java.util.logging.*;
import net.kdt.pojavlaunch.*;
public class LaunchClassLoader extends DexClassLoader {
public static final int BUFFER_SIZE = 4096;
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("legacy.debugClassLoading", "false"));
private static final boolean DEBUG_FINER;
private static final boolean DEBUG_SAVE;
private static final Manifest EMPTY = new Manifest();
private static final String[] RESERVED_NAMES = new String[]{"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"};
private static File tempFolder = null;
private Map<String, Class> cachedClasses = new HashMap<String, Class>(1000);
private Set<String> classLoaderExceptions = new HashSet<String>();
private Set<String> invalidClasses = new HashSet<String>(1000);
private final ThreadLocal<byte[]> loadBuffer = new ThreadLocal<byte[]>();
private Map<Package, Manifest> packageManifests = new HashMap<Package, Manifest>();
//private ClassLoader parent = getClass().getClassLoader();
private IClassNameTransformer renameTransformer;
private List<URL> sources;
private Set<String> transformerExceptions = new HashSet<String>();
private List<IClassTransformer> transformers = new ArrayList<IClassTransformer>(2);
static {
boolean z;
boolean z2 = true;
if (DEBUG && Boolean.parseBoolean(System.getProperty("legacy.debugClassLoadingFiner", "false"))) {
z = true;
} else {
z = false;
}
DEBUG_FINER = z;
if (!(DEBUG && Boolean.parseBoolean(System.getProperty("legacy.debugClassLoadingSave", "false")))) {
z2 = false;
}
DEBUG_SAVE = z2;
}
protected Package definePackage(String packageName, Manifest manifest,
URL url) throws IllegalArgumentException {
Attributes mainAttributes = manifest.getMainAttributes();
String dirName = packageName.replace('.', '/') + "/";
Attributes packageAttributes = manifest.getAttributes(dirName);
boolean noEntry = false;
if (packageAttributes == null) {
noEntry = true;
packageAttributes = mainAttributes;
}
String specificationTitle = packageAttributes
.getValue(Attributes.Name.SPECIFICATION_TITLE);
if (specificationTitle == null && !noEntry) {
specificationTitle = mainAttributes
.getValue(Attributes.Name.SPECIFICATION_TITLE);
}
String specificationVersion = packageAttributes
.getValue(Attributes.Name.SPECIFICATION_VERSION);
if (specificationVersion == null && !noEntry) {
specificationVersion = mainAttributes
.getValue(Attributes.Name.SPECIFICATION_VERSION);
}
String specificationVendor = packageAttributes
.getValue(Attributes.Name.SPECIFICATION_VENDOR);
if (specificationVendor == null && !noEntry) {
specificationVendor = mainAttributes
.getValue(Attributes.Name.SPECIFICATION_VENDOR);
}
String implementationTitle = packageAttributes
.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
if (implementationTitle == null && !noEntry) {
implementationTitle = mainAttributes
.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
}
String implementationVersion = packageAttributes
.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
if (implementationVersion == null && !noEntry) {
implementationVersion = mainAttributes
.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
}
String implementationVendor = packageAttributes
.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
if (implementationVendor == null && !noEntry) {
implementationVendor = mainAttributes
.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
}
return definePackage(packageName, specificationTitle,
specificationVersion, specificationVendor,
implementationTitle, implementationVersion,
implementationVendor, //isSealed(manifest, dirName) ? url : null);
isSealed(dirName, manifest) ? url : null);
}
// ENDED modding part
public LaunchClassLoader() { //String launchDexPath, String launchOptimizedDirectory, String launchLibrarySearchPath, ClassLoader parentClassLoader) {
super(LaunchClassLoaderAgruments.launchDexPath, LaunchClassLoaderAgruments.launchOptimizedDirectory, LaunchClassLoaderAgruments.launchLibrarySearchPath, LaunchClassLoader.class.getClassLoader());
//super(launchDexPath, launchOptimizedDirectory, launchLibrarySearchPath, parentClassLoader);
//System.out.println("MinecraftLaunchWrapper: How did Minecraft generated it: " + LaunchClassLoaderAgruments.launchDexPath);
this.sources = new ArrayList<URL>(Arrays.asList(sources));
Thread.currentThread().setContextClassLoader(this);
addClassLoaderExclusion("java.");
addClassLoaderExclusion("sun.");
addClassLoaderExclusion("org.lwjgl.");
addClassLoaderExclusion("net.minecraft.launchwrapper.");
addTransformerExclusion("javax.");
addTransformerExclusion("argo.");
addTransformerExclusion("org.objectweb.asm.");
addTransformerExclusion("com.google.common.");
addTransformerExclusion("org.bouncycastle.");
addTransformerExclusion("net.minecraft.launchwrapper.injector.");
if (DEBUG_SAVE) {
int x = 1;
tempFolder = new File(Launch.minecraftHome, "CLASSLOADER_TEMP");
while (tempFolder.exists() && x <= 10) {
int x2 = x + 1;
tempFolder = new File(Launch.minecraftHome, "CLASSLOADER_TEMP" + x);
x = x2;
}
if (tempFolder.exists()) {
LogWrapper.info("DEBUG_SAVE enabled, but 10 temp directories already exist, clean them and try again.", new Object[0]);
tempFolder = null;
return;
}
LogWrapper.info("DEBUG_SAVE Enabled, saving all classes to \"%s\"", new Object[]{tempFolder.getAbsolutePath().replace('\\', '/')});
tempFolder.mkdirs();
}
}
public void registerTransformer(String transformerClassName) {
try {
IClassTransformer transformer = (IClassTransformer) loadClass(transformerClassName).newInstance();
this.transformers.add(transformer);
if ((transformer instanceof IClassNameTransformer) && this.renameTransformer == null) {
this.renameTransformer = (IClassNameTransformer) transformer;
}
} catch (Exception e) {
LogWrapper.log(Level.SEVERE, e, "A critical problem occurred registering the ASM transformer class %s", new Object[]{transformerClassName});
}
}
public Class<?> findClass(String name) throws ClassNotFoundException {
if (this.invalidClasses.contains(name)) {
throw new ClassNotFoundException(name);
}
for (String exception : this.classLoaderExceptions) {
if (name.startsWith(exception)) {
return LaunchClassLoader.class.getClassLoader().loadClass(name);
}
}
if (this.cachedClasses.containsKey(name)) {
return (Class<?>) this.cachedClasses.get(name);
}
for (String exception2 : this.transformerExceptions) {
if (name.startsWith(exception2)) {
try {
Class<?> clazz = super.findClass(name);
this.cachedClasses.put(name, clazz);
return clazz;
} catch (ClassNotFoundException e) {
this.invalidClasses.add(name);
throw e;
}
}
}
try {
String packageName;
String transformedName = transformName(name);
String untransformedName = untransformName(name);
int lastDot = untransformedName.lastIndexOf(46);
if (lastDot == -1) {
packageName = "";
} else {
packageName = untransformedName.substring(0, lastDot);
}
String fileName = untransformedName.replace('.', '/').concat(".class");
URLConnection urlConnection = findCodeSourceConnectionFor(fileName);
CodeSigner[] signers = null;
if (lastDot > -1) {
if (!untransformedName.startsWith("net.minecraft.")) {
Package pkg;
if (urlConnection instanceof JarURLConnection) {
JarURLConnection jarURLConnection = (JarURLConnection) urlConnection;
JarFile jarFile = jarURLConnection.getJarFile();
if (!(jarFile == null || jarFile.getManifest() == null)) {
Manifest manifest = jarFile.getManifest();
JarEntry entry = jarFile.getJarEntry(fileName);
pkg = getPackage(packageName);
getClassBytes(untransformedName);
signers = entry.getCodeSigners();
if (pkg == null) {
this.packageManifests.put(definePackage(packageName, manifest, jarURLConnection.getJarFileURL()), manifest);
} else {//JarURLConnection aj;
if (pkg.isSealed()) {
if (!pkg.isSealed(jarURLConnection.getJarFileURL())) {
LogWrapper.severe("The jar file %s is trying to seal already secured path %s", new Object[]{jarFile.getName(), packageName});
}
}
if (isSealed(packageName, manifest)) {
LogWrapper.severe("The jar file %s has a security seal for path %s, but that path is defined and not secure", new Object[]{jarFile.getName(), packageName});
}
}
}
} else {
pkg = getPackage(packageName);
if (pkg == null) {
this.packageManifests.put(definePackage(packageName, null, null, null, null, null, null, null), EMPTY);
} else if (pkg.isSealed()) {
LogWrapper.severe("The URL %s is defining elements for sealed path %s", new Object[]{urlConnection.getURL(), packageName});
}
}
}
}
byte[] transformedClass = runTransformers(untransformedName, transformedName, getClassBytes(untransformedName));
if (DEBUG_SAVE) {
saveTransformedClass(transformedClass, transformedName);
}
try {
Class<?> clazz = defineClass(transformedName, transformedClass, 0, transformedClass.length); //, new ProtectionDomain(urlConnection == null ? null : new CodeSource(urlConnection.getURL(), signers), getClass().getProtectionDomain().getPermissions()));
this.cachedClasses.put(transformedName, clazz);
return clazz;
} catch (Throwable th) {
// MODDING HERE!
Class<?> clazz = loadClassAnyway(name);
this.cachedClasses.put(transformedName, clazz);
return clazz;
}
} catch (Throwable e2) {
this.invalidClasses.add(name);
if (DEBUG) {
LogWrapper.log(Level.FINEST, e2, "Exception encountered attempting classloading of %s", new Object[]{name});
}
//ClassNotFoundException classNotFoundException = new ClassNotFoundException(name, e2);
throw new ClassNotFoundException(name, e2);
}
}
// Mod:
private Class<?> loadClassAnyway(String pkg) {
try {
return Class.forName(pkg);
} catch (Throwable th) {}
try {
return super.findClass(pkg);
} catch (Throwable th) {}
try {
return super.loadClass(pkg, true);
} catch (Throwable th) {}
try {
return getClass().forName(pkg);
} catch (Throwable th) {}
try {
return getParent().loadClass(pkg);
} catch (Throwable th) {}
try {
return getSystemClassLoader().loadClass(pkg);
} catch (Throwable th) {}
try {
return getClass().getClassLoader().loadClass(pkg);
} catch (Throwable th) {}
try {
return Thread.currentThread().getContextClassLoader().loadClass(pkg);
} catch (Throwable th) {}
throw new RuntimeException("Unable to find class, out of 9 times");
}
private void saveTransformedClass(byte[] data, String transformedName) {
if (tempFolder != null) {
File outFile = new File(tempFolder, transformedName.replace('.', File.separatorChar) + ".class");
File outDir = outFile.getParentFile();
if (!outDir.exists()) {
outDir.mkdirs();
}
if (outFile.exists()) {
outFile.delete();
}
try {
LogWrapper.fine("Saving transformed class \"%s\" to \"%s\"", new Object[]{transformedName, outFile.getAbsolutePath().replace('\\', '/')});
OutputStream output = new FileOutputStream(outFile);
output.write(data);
output.close();
} catch (IOException ex) {
LogWrapper.log(Level.WARNING, ex, "Could not save transformed class \"%s\"", new Object[]{transformedName});
}
}
}
private String untransformName(String name) {
if (this.renameTransformer != null) {
return this.renameTransformer.unmapClassName(name);
}
return name;
}
private String transformName(String name) {
if (this.renameTransformer != null) {
return this.renameTransformer.remapClassName(name);
}
return name;
}
private boolean isSealed(String path, Manifest manifest) {
Attributes attributes = manifest.getAttributes(path);
String sealed = null;
if (attributes != null) {
sealed = attributes.getValue(Name.SEALED);
}
if (sealed == null) {
attributes = manifest.getMainAttributes();
if (attributes != null) {
sealed = attributes.getValue(Name.SEALED);
}
}
return "true".equalsIgnoreCase(sealed);
}
private URLConnection findCodeSourceConnectionFor(String name) {
URL resource = findResource(name);
if (resource == null) {
return null;
}
try {
return resource.openConnection();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private byte[] runTransformers(String name, String transformedName, byte[] basicClass) {
int i = 0;
if (DEBUG_FINER) {
String str = "Beginning transform of %s (%s) Start Length: %d";
Object[] objArr = new Object[3];
objArr[0] = name;
objArr[1] = transformedName;
objArr[2] = Integer.valueOf(basicClass == null ? 0 : basicClass.length);
LogWrapper.finest(str, objArr);
for (IClassTransformer transformer : this.transformers) {
int i2;
String transName = transformer.getClass().getName();
str = "Before Transformer %s: %d";
objArr = new Object[2];
objArr[0] = transName;
objArr[1] = Integer.valueOf(basicClass == null ? 0 : basicClass.length);
LogWrapper.finest(str, objArr);
basicClass = transformer.transform(name, transformedName, basicClass);
str = "After Transformer %s: %d";
objArr = new Object[2];
objArr[0] = transName;
if (basicClass == null) {
i2 = 0;
} else {
i2 = basicClass.length;
}
objArr[1] = Integer.valueOf(i2);
LogWrapper.finest(str, objArr);
}
String str2 = "Ending transform of %s (%s) Start Length: %d";
Object[] objArr2 = new Object[3];
objArr2[0] = name;
objArr2[1] = transformedName;
if (basicClass != null) {
i = basicClass.length;
}
objArr2[2] = Integer.valueOf(i);
LogWrapper.finest(str2, objArr2);
} else {
for (IClassTransformer transformer2 : this.transformers) {
basicClass = transformer2.transform(name, transformedName, basicClass);
}
}
return basicClass;
}
public void addURL(URL url) {
//super.addURL(url);
this.sources.add(url);
}
public List<URL> getSources() {
return this.sources;
}
private byte[] readFully(InputStream stream) {
try {
byte[] buffer = getOrCreateBuffer();
int totalLength = 0;
while (true) {
int read = stream.read(buffer, totalLength, buffer.length - totalLength);
if (read != -1) {
totalLength += read;
if (totalLength >= buffer.length - 1) {
byte[] newBuffer = new byte[(buffer.length + BUFFER_SIZE)];
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
buffer = newBuffer;
}
} else {
byte[] result = new byte[totalLength];
System.arraycopy(buffer, 0, result, 0, totalLength);
return result;
}
}
} catch (Throwable t) {
LogWrapper.log(Level.WARNING, t, "Problem loading class", new Object[0]);
return new byte[0];
}
}
private byte[] getOrCreateBuffer() {
byte[] buffer = (byte[]) this.loadBuffer.get();
if (buffer != null) {
return buffer;
}
this.loadBuffer.set(new byte[BUFFER_SIZE]);
return (byte[]) this.loadBuffer.get();
}
public List<IClassTransformer> getTransformers() {
return Collections.unmodifiableList(this.transformers);
}
public void addClassLoaderExclusion(String toExclude) {
this.classLoaderExceptions.add(toExclude);
}
public void addTransformerExclusion(String toExclude) {
this.transformerExceptions.add(toExclude);
}
public byte[] getClassBytes(String name) throws IOException {
byte[] data;
if (name.indexOf(46) == -1) {
for (String reservedName : RESERVED_NAMES) {
if (name.toUpperCase(Locale.ENGLISH).startsWith(reservedName)) {
data = getClassBytes("_" + name);
if (data != null) {
return data;
}
}
}
}
try {
URL classResource = findResource(name.replace('.', '/').concat(".class"));
if (classResource == null) {
if (DEBUG) {
LogWrapper.finest("Failed to find class resource"); // %s", new Object[]{resourcePath});
}
closeSilently(null);
return null;
}
InputStream classStream = classResource.openStream();
if (DEBUG) {
LogWrapper.finest("Loading class %s from resource %s", new Object[]{name, classResource.toString()});
}
data = readFully(classStream);
closeSilently(classStream);
return data;
} catch (Throwable th) {
closeSilently(null);
// Mod
return null;
}
}
private static void closeSilently(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
}
}
}
}
@@ -0,0 +1,102 @@
package net.minecraft.launchwrapper;
import java.util.logging.*;
import net.minecraft.launchwrapper.LogWrapper.*;
import java.text.*;
import java.util.*;
import android.util.*;
public class LogWrapper {
private static boolean configured;
public static LogWrapper log = new LogWrapper();
private Logger myLog;
private SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss");
// Make Android compatible with java logger
private LogWrapper.AndroidLogger androidLogger;
private static void configureLogging() {
log.myLog = Logger.getLogger("LaunchWrapper");
configured = true;
}
public static void retarget(Logger to) {
log.myLog = to;
}
public static void log(String logChannel, Level level, String format, Object... data) {
makeLog(logChannel);
String logData = String.format(format, data);
Logger.getLogger(logChannel).log(level, logData);
androidLog(logChannel, level.getName(), logData);
}
public static void log(Level level, String format, Object... data) {
if (!configured) {
configureLogging();
}
String logData = String.format(format, data);
log.myLog.log(level, logData);
androidLog("LaunchWrapper", level.getName(), logData);
}
public static void log(String logChannel, Level level, Throwable ex, String format, Object... data) {
makeLog(logChannel);
String logData = String.format(format, data);
Logger.getLogger(logChannel).log(level, logData, ex);
androidLog(logChannel, level.getName(), logData + "\n" + Log.getStackTraceString(ex));
}
public static void log(Level level, Throwable ex, String format, Object... data) {
if (!configured) {
configureLogging();
}
String logData = String.format(format, data);
log.myLog.log(level, logData, ex);
androidLog("LaunchWrapper", level.getName(), logData + "\n" + Log.getStackTraceString(ex));
}
public static void severe(String format, Object... data) {
log(Level.SEVERE, format, data);
}
public static void warning(String format, Object... data) {
log(Level.WARNING, format, data);
}
public static void info(String format, Object... data) {
log(Level.INFO, format, data);
}
public static void fine(String format, Object... data) {
log(Level.FINE, format, data);
}
public static void finer(String format, Object... data) {
log(Level.FINER, format, data);
}
public static void finest(String format, Object... data) {
log(Level.FINEST, format, data);
}
public static void makeLog(String logChannel) {
Logger.getLogger(logChannel).setParent(log.myLog);
}
// Android compatible add:
private static void androidLog(String name, String level, String data) {
String timeStr = log.time.format(new Date());
log.androidLogger.onPrint(timeStr, name, level, data);
}
public static void setAndroidLogReceiver(AndroidLogger logger) {
log.androidLogger = logger;
}
public static interface AndroidLogger {
public void onPrint(String time, String name, String level, String message);
}
}
@@ -0,0 +1,25 @@
package net.minecraft.launchwrapper;
import java.io.File;
import java.util.List;
public class VanillaTweaker implements ITweaker {
private List<String> args;
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = args;
}
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
classLoader.registerTransformer("net.minecraft.launchwrapper.injector.VanillaTweakInjector");
}
public String getLaunchTarget() {
return "net.minecraft.client.Minecraft";
}
public String[] getLaunchArguments() {
return (String[]) this.args.toArray(new String[this.args.size()]);
}
}
@@ -0,0 +1,155 @@
package net.minecraft.launchwrapper.injector;
import java.applet.Applet;
import java.applet.AppletStub;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
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.util.HashMap;
import java.util.Map;
import javax.swing.JPanel;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
public class AlphaVanillaTweakInjector implements IClassTransformer {
private static class LauncherFake extends Applet implements AppletStub {
final /* synthetic */ Map map;
public LauncherFake(Map map) {
this.map = map;
}
public void appletResize(int width, int height) {
}
public boolean isActive() {
return true;
}
public URL getDocumentBase() {
try {
return new URL("http://www.minecraft.net/game/");
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
public URL getCodeBase() {
try {
return new URL("http://www.minecraft.net/game/");
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
public String getParameter(String paramName) {
if (this.map.containsKey(paramName)) {
return (String) this.map.get(paramName);
}
System.err.println("Client asked for parameter: " + paramName);
return null;
}
}
public byte[] transform(String name, String transformedName, byte[] bytes) {
return bytes;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz;
try {
clazz = getaClass("net.minecraft.client.MinecraftApplet");
} catch (ClassNotFoundException e) {
clazz = getaClass("com.mojang.minecraft.MinecraftApplet");
}
System.out.println("AlphaVanillaTweakInjector.class.getClassLoader() = " + AlphaVanillaTweakInjector.class.getClassLoader());
Object object = clazz.getConstructor(new Class[0]).newInstance(new Object[0]);
for (Field field : clazz.getDeclaredFields()) {
String name = field.getType().getName();
if (!(name.contains("awt") || name.contains("java") || name.equals("long"))) {
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) {
Map<String, String> params = new HashMap<String, String>();
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);
Frame launcherFrameFake = new Frame();
launcherFrameFake.setTitle("Minecraft");
launcherFrameFake.setBackground(Color.BLACK);
JPanel panel = new JPanel();
launcherFrameFake.setLayout(new BorderLayout());
panel.setPreferredSize(new Dimension(854, 480));
launcherFrameFake.add(panel, "Center");
launcherFrameFake.pack();
launcherFrameFake.setLocationRelativeTo(null);
launcherFrameFake.setVisible(true);
launcherFrameFake.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(1);
}
});
LauncherFake fakeLauncher = new LauncherFake(params);
applet.setStub(fakeLauncher);
fakeLauncher.setLayout(new BorderLayout());
fakeLauncher.add(applet, "Center");
fakeLauncher.validate();
launcherFrameFake.removeAll();
launcherFrameFake.setLayout(new BorderLayout());
launcherFrameFake.add(fakeLauncher, "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.loadClass(name);
}
private static Field getWorkingDirField(String name) throws ClassNotFoundException {
for (Field field : getaClass(name).getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().getName().equals("java.io.File")) {
return field;
}
}
return null;
}
}
@@ -0,0 +1,86 @@
package net.minecraft.launchwrapper.injector;
import java.io.File;
import java.util.Iterator;
import java.util.ListIterator;
import javax.imageio.ImageIO;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TableSwitchInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
public class IndevVanillaTweakInjector implements IClassTransformer {
public byte[] transform(String name, String transformedName, byte[] bytes) {
if (bytes == null) {
return null;
}
ClassNode classNode = new ClassNode();
new ClassReader(bytes).accept(classNode, 8);
if (!classNode.interfaces.contains("java/lang/Runnable")) {
return bytes;
}
MethodNode runMethod = null;
Iterator i$ = classNode.methods.iterator();
while (true) {
if (!i$.hasNext()) {
break;
}
MethodNode methodNode = (MethodNode) i$.next();
if ("run".equals(methodNode.name)) {
runMethod = methodNode;
break;
}
}
if (runMethod == null) {
return bytes;
}
System.out.println("Probably the minecraft class (it has run && is applet!): " + name);
ListIterator<AbstractInsnNode> iterator = runMethod.instructions.iterator();
int firstSwitchJump = -1;
while (iterator.hasNext()) {
AbstractInsnNode instruction = (AbstractInsnNode) iterator.next();
if (instruction.getOpcode() == 170) {
firstSwitchJump = runMethod.instructions.indexOf((AbstractInsnNode) ((TableSwitchInsnNode) instruction).labels.get(0));
} else if (firstSwitchJump >= 0 && runMethod.instructions.indexOf(instruction) == firstSwitchJump) {
int endOfSwitch = -1;
while (true) {
if (!iterator.hasNext()) {
break;
}
instruction = (AbstractInsnNode) iterator.next();
if (instruction.getOpcode() == 167) {
endOfSwitch = runMethod.instructions.indexOf(((JumpInsnNode) instruction).label);
break;
}
}
if (endOfSwitch >= 0) {
while (runMethod.instructions.indexOf(instruction) != endOfSwitch && iterator.hasNext()) {
instruction = (AbstractInsnNode) iterator.next();
}
AbstractInsnNode instruction2 = (AbstractInsnNode) iterator.next();
runMethod.instructions.insertBefore(instruction2, new MethodInsnNode(184, "net/minecraft/launchwrapper/injector/IndevVanillaTweakInjector", "inject", "()Ljava/io/File;"));
runMethod.instructions.insertBefore(instruction2, new VarInsnNode(58, 2));
}
}
}
ClassWriter writer = new ClassWriter(3);
classNode.accept(writer);
return writer.toByteArray();
}
public static File inject() {
System.out.println("Turning of ImageIO disk-caching");
ImageIO.setUseCache(false);
VanillaTweakInjector.loadIconsOnFrames();
System.out.println("Setting gameDir to: " + Launch.minecraftHome);
return Launch.minecraftHome;
}
}
@@ -0,0 +1,111 @@
package net.minecraft.launchwrapper.injector;
import java.awt.Frame;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import javax.imageio.ImageIO;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
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;
public class VanillaTweakInjector implements IClassTransformer {
public byte[] transform(String name, String transformedName, byte[] bytes) {
if (bytes == null) {
return null;
}
if (!"net.minecraft.client.Minecraft".equals(name)) {
return bytes;
}
ClassNode classNode = new ClassNode();
new ClassReader(bytes).accept(classNode, 8);
MethodNode mainMethod = null;
for (MethodNode methodNode : classNode.methods) {
if ("main".equals(methodNode.name)) {
mainMethod = methodNode;
break;
}
}
if (mainMethod == null) {
return bytes;
}
FieldNode workDirNode = null;
for (FieldNode fieldNode : classNode.fields) {
if (Type.getDescriptor(File.class).equals(fieldNode.desc) && (fieldNode.access & 8) == 8) {
workDirNode = fieldNode;
break;
}
}
MethodNode injectedMethod = new MethodNode();
Label label = new Label();
injectedMethod.visitLabel(label);
injectedMethod.visitLineNumber(9001, label);
injectedMethod.visitMethodInsn(184, "net/minecraft/launchwrapper/injector/VanillaTweakInjector", "inject", "()Ljava/io/File;");
injectedMethod.visitFieldInsn(179, "net/minecraft/client/Minecraft", workDirNode.name, "Ljava/io/File;");
ListIterator<AbstractInsnNode> iterator = mainMethod.instructions.iterator();
while (iterator.hasNext()) {
AbstractInsnNode insn = (AbstractInsnNode) iterator.next();
if (insn.getOpcode() == 177) {
mainMethod.instructions.insertBefore(insn, injectedMethod.instructions);
}
}
ClassWriter writer = new ClassWriter(3);
classNode.accept(writer);
return writer.toByteArray();
}
public static File inject() {
System.out.println("Turning off ImageIO disk-caching");
ImageIO.setUseCache(false);
loadIconsOnFrames();
System.out.println("Setting gameDir to: " + Launch.minecraftHome);
return Launch.minecraftHome;
}
public static void loadIconsOnFrames() {
try {
File smallIcon = new File(Launch.assetsDir, "icons/icon_16x16.png");
File bigIcon = new File(Launch.assetsDir, "icons/icon_32x32.png");
System.out.println("Loading current icons for window from: " + smallIcon + " and " + bigIcon);
Display.setIcon(new ByteBuffer[]{loadIcon(smallIcon), loadIcon(bigIcon)});
Frame[] frames = Frame.getFrames();
if (frames != null) {
List<Image> icons = Arrays.asList(new Image[]{ImageIO.read(smallIcon), ImageIO.read(bigIcon)});
for (Frame frame : frames) {
try {
frame.setIconImages(icons);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static ByteBuffer loadIcon(File iconFile) throws IOException {
BufferedImage icon = ImageIO.read(iconFile);
int[] rgb = icon.getRGB(0, 0, icon.getWidth(), icon.getHeight(), null, 0, icon.getWidth());
ByteBuffer buffer = ByteBuffer.allocate(rgb.length * 4);
for (int color : rgb) {
buffer.putInt((color << 8) | ((color >> 24) & 255));
}
buffer.flip();
return buffer;
}
}
@@ -0,0 +1,37 @@
package net.zhuoweizhang.boardwalk;
import android.os.Build.VERSION;
public class DalvikTweaks {
public static native void crashTheLogger();
public static native void nativeSetDefaultStackSize(int i, int i2);
public static native void nativeSetHeapMaxFree(long j, int i);
public static native void nativeSetHeapMinFree(long j, int i);
public static native void setenv(String str, String str2, boolean z);
public static void setDefaultStackSize(int i) {
nativeSetDefaultStackSize(i, VERSION.SDK_INT);
}
public static void setHeapMaxFree(long j) {
nativeSetHeapMaxFree(j, VERSION.SDK_INT);
}
public static void setHeapMinFree(long j) {
nativeSetHeapMinFree(j, VERSION.SDK_INT);
}
public static boolean isDalvik() {
String property = System.getProperty("java.vm.version");
return property != null && property.startsWith("1");
}
static {
System.loadLibrary("boardwalk");
}
}