mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2026-10-04 19:36:12 -04:00
1153 lines
34 KiB
Java
1153 lines
34 KiB
Java
package net.kdt.pojavlaunch;
|
|
|
|
import android.app.*;
|
|
import android.content.*;
|
|
import android.os.*;
|
|
import android.support.design.widget.*;
|
|
import android.support.v4.app.*;
|
|
import android.support.v4.view.*;
|
|
import android.support.v7.app.*;
|
|
import android.util.*;
|
|
import android.view.*;
|
|
import android.widget.*;
|
|
import android.widget.AdapterView.*;
|
|
import com.google.gson.*;
|
|
import com.kdt.filerapi.*;
|
|
import com.kdt.filermod.*;
|
|
import java.io.*;
|
|
import java.nio.charset.*;
|
|
import java.util.*;
|
|
import net.kdt.pojavlaunch.mcfragments.*;
|
|
import net.kdt.pojavlaunch.prefs.*;
|
|
import net.kdt.pojavlaunch.signer.*;
|
|
import net.kdt.pojavlaunch.util.*;
|
|
import net.kdt.pojavlaunch.value.*;
|
|
import org.lwjgl.opengl.*;
|
|
|
|
import android.app.AlertDialog;
|
|
import android.support.v4.app.Fragment;
|
|
import android.support.v4.app.FragmentManager;
|
|
import dalvik.system.*;
|
|
import java.lang.reflect.*;
|
|
import net.kdt.pojavlaunch.patcher.*;
|
|
import android.graphics.*;
|
|
import android.content.pm.*;
|
|
import optifine.*;
|
|
//import android.support.v7.view.menu.*;
|
|
//import net.zhuoweizhang.boardwalk.downloader.*;
|
|
|
|
public class MCLauncherActivity extends AppCompatActivity
|
|
{
|
|
//private FragmentTabHost mTabHost;
|
|
private LinearLayout fullTab;
|
|
private ViewPager viewPager;
|
|
private TabLayout tabLayout;
|
|
|
|
private TextView tvVersion, tvUsernameView;
|
|
private Spinner versionSelector;
|
|
private String[] availableVersions = Tools.versionList;
|
|
private MCProfile.Builder profile;
|
|
private String profilePath = null;
|
|
private CrashFragment crashView;
|
|
private ConsoleFragment consoleView;
|
|
private ViewPagerAdapter viewPageAdapter;
|
|
|
|
private ProgressBar launchProgress;
|
|
private TextView launchTextStatus;
|
|
private Button switchUsrBtn, logoutBtn; // MineButtons
|
|
private ViewGroup leftView, rightView;
|
|
private Button playButton;
|
|
|
|
private Gson gson;
|
|
|
|
private JMinecraftVersionList versionList;
|
|
private static volatile boolean isAssetsProcessing = false;
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState)
|
|
{
|
|
super.onCreate(savedInstanceState);
|
|
|
|
gson = new Gson();
|
|
|
|
DisplayMetrics dm = Tools.getDisplayMetrics(this);
|
|
AndroidDisplay.windowWidth = dm.widthPixels;
|
|
AndroidDisplay.windowHeight = dm.heightPixels;
|
|
viewInit();
|
|
}
|
|
// DEBUG
|
|
//new android.support.design.widget.NavigationView(this);
|
|
|
|
private String getStr(int id, Object... val) {
|
|
if (val != null && val.length > 0) {
|
|
return getResources().getString(id, val);
|
|
} else {
|
|
return getResources().getString(id);
|
|
}
|
|
}
|
|
|
|
private void viewInit() {
|
|
setContentView(R.layout.launcher_main);
|
|
|
|
fullTab = (LinearLayout) findViewById(R.id.launchermainFragmentTabView);
|
|
tabLayout = (TabLayout) findViewById(R.id.launchermainTabLayout);
|
|
viewPager = (ViewPager) findViewById(R.id.launchermainTabPager);
|
|
|
|
consoleView = new ConsoleFragment();
|
|
crashView = new CrashFragment();
|
|
|
|
viewPageAdapter = new ViewPagerAdapter(getSupportFragmentManager());
|
|
|
|
viewPageAdapter.addFragment(new LauncherFragment(), getStr(R.string.mcl_tab_news));
|
|
viewPageAdapter.addFragment(consoleView, getStr(R.string.mcl_tab_console));
|
|
viewPageAdapter.addFragment(crashView, getStr(R.string.mcl_tab_crash));
|
|
|
|
viewPager.setAdapter(viewPageAdapter);
|
|
tabLayout.setupWithViewPager(viewPager);
|
|
|
|
tvUsernameView = (TextView) findId(R.id.launcherMainUsernameView);
|
|
tvVersion = (TextView) findId(R.id.launcherMainVersionView);
|
|
|
|
try {
|
|
profilePath = PojavProfile.getCurrentProfilePath(this);
|
|
profile = PojavProfile.getCurrentProfileContent(this);
|
|
|
|
tvUsernameView.setText(profile.getUsername());
|
|
} catch(Exception e) {
|
|
//Tools.throwError(this, e);
|
|
e.printStackTrace();
|
|
toast(getStr(R.string.toast_login_error) + " " + e.getMessage());
|
|
finish();
|
|
}
|
|
|
|
//showProfileInfo();
|
|
|
|
List<String> versions = new ArrayList<String>();
|
|
final File fVers = new File(Tools.versnDir);
|
|
|
|
try {
|
|
if (fVers.listFiles().length < 1) {
|
|
throw new Exception(getStr(R.string.error_no_version));
|
|
}
|
|
|
|
for (File fVer : fVers.listFiles()) {
|
|
versions.add(fVer.getName());
|
|
}
|
|
} catch (Exception e) {
|
|
versions.add(getStr(R.string.global_error) + ":");
|
|
versions.add(e.getMessage());
|
|
|
|
} finally {
|
|
availableVersions = versions.toArray(new String[0]);
|
|
}
|
|
|
|
//availableVersions;
|
|
|
|
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, availableVersions);
|
|
adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
|
|
versionSelector = (Spinner) findId(R.id.launcherMainSelectVersion);
|
|
versionSelector.setAdapter(adapter);
|
|
|
|
launchProgress = (ProgressBar) findId(R.id.progressDownloadBar);
|
|
launchTextStatus = (TextView) findId(R.id.progressDownloadText);
|
|
LinearLayout exitLayout = (LinearLayout) findId(R.id.launcherMainExitbtns);
|
|
switchUsrBtn = (Button) exitLayout.getChildAt(0);
|
|
logoutBtn = (Button) exitLayout.getChildAt(1);
|
|
|
|
leftView = (LinearLayout) findId(R.id.launcherMainLeftLayout);
|
|
playButton = (Button) findId(R.id.launcherMainPlayButton);
|
|
rightView = (ViewGroup) findId(R.id.launcherMainRightLayout);
|
|
|
|
statusIsLaunching(false);
|
|
}
|
|
|
|
public class RefreshVersionListTask extends AsyncTask<Void, Void, ArrayList<String>>{
|
|
|
|
@Override
|
|
protected ArrayList<String> doInBackground(Void[] p1)
|
|
{
|
|
try{
|
|
versionList = gson.fromJson(DownloadUtils.downloadString("https://launchermeta.mojang.com/mc/game/version_manifest.json"), JMinecraftVersionList.class);
|
|
ArrayList<String> versionStringList = filter(versionList.versions, new File(Tools.versnDir).listFiles());
|
|
|
|
return versionStringList;
|
|
} catch (Exception e){
|
|
e.printStackTrace();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(ArrayList<String> result)
|
|
{
|
|
super.onPostExecute(result);
|
|
|
|
final PopupMenu popup = new PopupMenu(MCLauncherActivity.this, versionSelector);
|
|
popup.getMenuInflater().inflate(R.menu.menu_versionopt, popup.getMenu());
|
|
|
|
if(result != null && result.size() > 0) {
|
|
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MCLauncherActivity.this, android.R.layout.simple_spinner_item, result);
|
|
adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
|
|
versionSelector.setAdapter(adapter);
|
|
versionSelector.setSelection(selectAt(result.toArray(new String[0]), profile.getVersion()));
|
|
} else {
|
|
versionSelector.setSelection(selectAt(availableVersions, profile.getVersion()));
|
|
}
|
|
versionSelector.setOnItemSelectedListener(new OnItemSelectedListener(){
|
|
|
|
@Override
|
|
public void onItemSelected(AdapterView<?> p1, View p2, int p3, long p4)
|
|
{
|
|
String version = p1.getItemAtPosition(p3).toString();
|
|
profile.setVersion(version);
|
|
|
|
PojavProfile.setCurrentProfile(MCLauncherActivity.this, profile);
|
|
if (PojavProfile.isFileType(MCLauncherActivity.this)) {
|
|
PojavProfile.setCurrentProfile(MCLauncherActivity.this, MCProfile.build(profile));
|
|
}
|
|
|
|
tvVersion.setText(getStr(R.string.mcl_version_msg, version));
|
|
}
|
|
|
|
@Override
|
|
public void onNothingSelected(AdapterView<?> p1)
|
|
{
|
|
// TODO: Implement this method
|
|
}
|
|
});
|
|
versionSelector.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener(){
|
|
@Override
|
|
public boolean onItemLongClick(AdapterView<?> p1, View p2, int p3, long p4)
|
|
{
|
|
// Implement copy, remove, reinstall,...
|
|
popup.show();
|
|
return true;
|
|
}
|
|
});
|
|
|
|
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
return true;
|
|
}
|
|
});
|
|
|
|
tvVersion.setText(getStr(R.string.mcl_version_msg) + versionSelector.getSelectedItem());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onPostResume()
|
|
{
|
|
super.onPostResume();
|
|
}
|
|
|
|
private float updateWidthHeight() {
|
|
float leftRightWidth = (float) AndroidDisplay.windowWidth / 100f * 32f;
|
|
float playButtonWidth = AndroidDisplay.windowWidth - leftRightWidth * 2f;
|
|
LinearLayout.LayoutParams leftRightParams = new LinearLayout.LayoutParams((int) leftRightWidth, (int) Tools.dpToPx(this, AndroidDisplay.windowHeight / 9));
|
|
LinearLayout.LayoutParams playButtonParams = new LinearLayout.LayoutParams((int) playButtonWidth, (int) Tools.dpToPx(this, AndroidDisplay.windowHeight / 9));
|
|
leftView.setLayoutParams(leftRightParams);
|
|
rightView.setLayoutParams(leftRightParams);
|
|
playButton.setLayoutParams(playButtonParams);
|
|
|
|
return leftRightWidth;
|
|
}
|
|
|
|
private JMinecraftVersionList.Version findVersion(String version) {
|
|
if (versionList != null) {
|
|
for (JMinecraftVersionList.Version valueVer: versionList.versions) {
|
|
if (valueVer.id.equals(version)) {
|
|
return valueVer;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Custom version, inherits from base.
|
|
return Tools.getVersionInfo(version);
|
|
}
|
|
|
|
private ArrayList<String> filter(JMinecraftVersionList.Version[] list1, File[] list2) {
|
|
ArrayList<String> output = new ArrayList<String>();
|
|
|
|
for (JMinecraftVersionList.Version value1: list1) {
|
|
if ((value1.type.equals("release") && LauncherPreferences.PREF_VERTYPE_RELEASE) ||
|
|
(value1.type.equals("snapshot") && LauncherPreferences.PREF_VERTYPE_SNAPSHOT) ||
|
|
(value1.type.equals("old_alpha") && LauncherPreferences.PREF_VERTYPE_OLDALPHA) ||
|
|
(value1.type.equals("old_beta") && LauncherPreferences.PREF_VERTYPE_OLDBETA)) {
|
|
output.add(value1.id);
|
|
}
|
|
}
|
|
|
|
for (File value2: list2) {
|
|
if (!output.contains(value2.getName())) {
|
|
output.add(value2.getName());
|
|
}
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
private void toast(final String str) {
|
|
runOnUiThread(new Runnable(){
|
|
|
|
@Override
|
|
public void run()
|
|
{
|
|
Toast.makeText(MCLauncherActivity.this, str, Toast.LENGTH_SHORT).show();
|
|
}
|
|
});
|
|
}
|
|
|
|
public void mcaccSwitchUser(View view)
|
|
{
|
|
showProfileInfo();
|
|
}
|
|
|
|
public void mcaccLogout(View view)
|
|
{
|
|
//PojavProfile.reset();
|
|
finish();
|
|
}
|
|
|
|
private void showProfileInfo()
|
|
{
|
|
/*
|
|
new AlertDialog.Builder(this)
|
|
.setTitle("Info player")
|
|
.setMessage(
|
|
"AccessToken=" + profile.getAccessToken() + "\n" +
|
|
"ClientID=" + profile.getClientID() + "\n" +
|
|
"ProfileID=" + profile.getProfileID() + "\n" +
|
|
"Username=" + profile.getUsername() + "\n" +
|
|
"Version=" + profile.getVersion()
|
|
).show();
|
|
*/
|
|
}
|
|
|
|
private void selectTabPage(int pageIndex){
|
|
if (tabLayout.getSelectedTabPosition() != pageIndex) {
|
|
tabLayout.setScrollPosition(pageIndex,0f,true);
|
|
viewPager.setCurrentItem(pageIndex);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onResumeFragments()
|
|
{
|
|
super.onResumeFragments();
|
|
new RefreshVersionListTask().execute();
|
|
|
|
try{
|
|
final ProgressDialog barrier = new ProgressDialog(this);
|
|
barrier.setMessage("Waiting");
|
|
barrier.setProgressStyle(barrier.STYLE_SPINNER);
|
|
barrier.setCancelable(false);
|
|
barrier.show();
|
|
|
|
new Thread(new Runnable(){
|
|
|
|
@Override
|
|
public void run()
|
|
{
|
|
while (consoleView == null) {
|
|
try {
|
|
Thread.sleep(20);
|
|
} catch (Throwable th) {}
|
|
}
|
|
|
|
try {
|
|
Thread.sleep(100);
|
|
} catch (Throwable th) {}
|
|
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run()
|
|
{
|
|
try {
|
|
consoleView.putLog("");
|
|
barrier.dismiss();
|
|
} catch (Throwable th) {
|
|
startActivity(getIntent());
|
|
finish();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}).start();
|
|
|
|
File lastCrashFile = Tools.lastFileModified(Tools.crashPath);
|
|
if(CrashFragment.isNewCrash(lastCrashFile) || !crashView.getLastCrash().isEmpty()){
|
|
crashView.resetCrashLog = false;
|
|
selectTabPage(2);
|
|
} else throw new Exception();
|
|
} catch(Throwable e){
|
|
selectTabPage(tabLayout.getSelectedTabPosition());
|
|
}
|
|
}
|
|
|
|
public int selectAt(String[] strArr, String select)
|
|
{
|
|
int count = 0;
|
|
for(String str : strArr){
|
|
if(str.equals(select)){
|
|
return count;
|
|
}
|
|
else{
|
|
count++;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
@Override
|
|
protected void onResume()
|
|
{
|
|
super.onResume();
|
|
}
|
|
|
|
private boolean canBack = false;
|
|
private void statusIsLaunching(boolean isLaunching)
|
|
{
|
|
LinearLayout.LayoutParams reparam = new LinearLayout.LayoutParams((int) updateWidthHeight(), LinearLayout.LayoutParams.WRAP_CONTENT);
|
|
ViewGroup.MarginLayoutParams lmainTabParam = (ViewGroup.MarginLayoutParams) fullTab.getLayoutParams();
|
|
int launchVisibility = isLaunching ? View.VISIBLE : View.GONE;
|
|
launchProgress.setVisibility(launchVisibility);
|
|
launchTextStatus.setVisibility(launchVisibility);
|
|
lmainTabParam.bottomMargin = reparam.height;
|
|
leftView.setLayoutParams(reparam);
|
|
|
|
switchUsrBtn.setEnabled(!isLaunching);
|
|
logoutBtn.setEnabled(!isLaunching);
|
|
versionSelector.setEnabled(!isLaunching);
|
|
canBack = !isLaunching;
|
|
}
|
|
@Override
|
|
public void onBackPressed()
|
|
{
|
|
if (canBack) {
|
|
super.onBackPressed();
|
|
}
|
|
}
|
|
|
|
// Catching touch exception
|
|
@Override
|
|
public boolean onTouchEvent(MotionEvent event) {
|
|
try {
|
|
return super.onTouchEvent(event);
|
|
} catch (Throwable th) {
|
|
Tools.showError(this, th);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private GameRunnerTask mTask;
|
|
|
|
public void launchGame(View v)
|
|
{
|
|
if (!canBack && isAssetsProcessing) {
|
|
isAssetsProcessing = false;
|
|
statusIsLaunching(false);
|
|
} else if (canBack) {
|
|
v.setEnabled(false);
|
|
mTask = new GameRunnerTask();
|
|
mTask.execute(profile.getVersion());
|
|
crashView.resetCrashLog = true;
|
|
}
|
|
}
|
|
|
|
public class GameRunnerTask extends AsyncTask<String, String, Throwable>
|
|
{
|
|
private String convertStr;
|
|
private boolean launchWithError = false;
|
|
|
|
@Override
|
|
protected void onPreExecute()
|
|
{
|
|
launchProgress.setMax(39);
|
|
statusIsLaunching(true);
|
|
}
|
|
|
|
private int maxSubProgress = 1;
|
|
private int valSubProgress = 1;
|
|
@Override
|
|
protected Throwable doInBackground(final String[] p1)
|
|
{
|
|
Throwable throwable = null;
|
|
final StringBuilder currentLog = new StringBuilder();
|
|
LoggerJava.LoggerOutputStream logOut = new LoggerJava.LoggerOutputStream(System.out, new LoggerJava.OnStringPrintListener(){
|
|
@Override
|
|
public void onCharPrint(char c)
|
|
{
|
|
currentLog.append(c);
|
|
}
|
|
});
|
|
LoggerJava.LoggerOutputStream logErr = new LoggerJava.LoggerOutputStream(System.err, new LoggerJava.OnStringPrintListener(){
|
|
@Override
|
|
public void onCharPrint(char c)
|
|
{
|
|
currentLog.append(c);
|
|
}
|
|
});
|
|
System.setOut(new PrintStream(logOut));
|
|
System.setErr(new PrintStream(logErr));
|
|
|
|
try {
|
|
final String downVName = "/" + p1[0] + "/" + p1[0];
|
|
|
|
//Downloading libraries
|
|
String inputPath = Tools.versnDir + downVName + "_orig.jar";
|
|
String unpatchedPath = Tools.versnDir + downVName + "_unpatched.jar";
|
|
String patchedFile = Tools.versnDir + downVName + ".jar";
|
|
|
|
JMinecraftVersionList.Version verInfo;
|
|
|
|
try {
|
|
//com.pojavdx.dx.mod.Main.debug = true;
|
|
|
|
String verJsonDir = Tools.versnDir + downVName + ".json";
|
|
|
|
verInfo = findVersion(p1[0]);
|
|
|
|
if (verInfo.url != null) {
|
|
publishProgress("5", "Downloading " + p1[0] + " configuration...");
|
|
Tools.downloadFile(
|
|
verInfo.url,
|
|
verJsonDir,
|
|
true
|
|
);
|
|
}
|
|
|
|
zeroProgress();
|
|
|
|
verInfo = Tools.getVersionInfo(p1[0]);
|
|
|
|
DependentLibrary[] libList = verInfo.libraries;
|
|
setMax(libList.length * 2 + 5);
|
|
|
|
String libPathURL;
|
|
File outUndexLib, outDexedLib, outUnpatchedConvert;
|
|
|
|
for (final DependentLibrary libItem: libList) {
|
|
|
|
if (libItem.name.startsWith("com.google.code.gson:gson") ||
|
|
libItem.name.startsWith("com.mojang:realms") ||
|
|
libItem.name.startsWith("net.java.jinput") ||
|
|
libItem.name.startsWith("net.minecraft.launchwrapper") ||
|
|
libItem.name.startsWith("org.lwjgl") ||
|
|
libItem.name.startsWith("tv.twitch")
|
|
) { // Black list
|
|
publishProgress("1", "Ignored " + libItem.name);
|
|
//Thread.sleep(100);
|
|
} else {
|
|
currentLog.setLength(0);
|
|
|
|
String[] libInfo = libItem.name.split(":");
|
|
String libArtifact = Tools.artifactToPath(libInfo[0], libInfo[1], libInfo[2]);
|
|
outUndexLib = new File(Tools.libraries + "/" + libArtifact.replace(".jar", "_orig.jar"));
|
|
outUndexLib.getParentFile().mkdirs();
|
|
|
|
outDexedLib = new File(Tools.libraries + "/" + libArtifact); // Don't add ".jar"
|
|
if (!outDexedLib.exists()) {
|
|
publishProgress("1", getStr(R.string.mcl_launch_download_lib, libItem.name));
|
|
|
|
boolean skipIfFailed = false;
|
|
|
|
if (libItem.downloads == null) {
|
|
MinecraftLibraryArtifact artifact = new MinecraftLibraryArtifact();
|
|
artifact.url = "https://libraries.minecraft.net/" + libArtifact;
|
|
libItem.downloads = new DependentLibrary.LibraryDownloads(artifact);
|
|
|
|
skipIfFailed = true;
|
|
}
|
|
try {
|
|
libPathURL = libItem.downloads.artifact.url;
|
|
if (!outUndexLib.exists()) {
|
|
//toast(outUndexLib.getAbsolutePath());
|
|
Tools.downloadFile(
|
|
libPathURL,
|
|
outUndexLib.getAbsolutePath(),
|
|
true
|
|
);
|
|
}
|
|
} catch (Throwable th) {
|
|
if (!skipIfFailed) {
|
|
throw th;
|
|
} else {
|
|
th.printStackTrace();
|
|
}
|
|
}
|
|
|
|
convertStr = getStr(R.string.mcl_launch_convert_lib, libItem.name);
|
|
publishProgress("1", convertStr);
|
|
|
|
boolean isOptifine = libItem.name.startsWith(Tools.optifineLib);
|
|
Tools.runDx(MCLauncherActivity.this, outUndexLib.getAbsolutePath(), outDexedLib.getAbsolutePath(), isOptifine , new PojavDXManager.Listen(){
|
|
|
|
@Override
|
|
public void onReceived(String step, int maxProg, int currProg)
|
|
{
|
|
maxSubProgress = maxProg;
|
|
valSubProgress = currProg;
|
|
publishProgress("0", convertStr + ": (" + currProg + "/" + maxProg + ") " + step, "");
|
|
}
|
|
});
|
|
/*
|
|
if (!new File(outDexedLib + "/finish").exists()) {
|
|
toast("Unable to convert library " + libItem.name + " but still continue. Is it a wrong check?");
|
|
//throw new RuntimeException("Unable to convert library " + libItem.name);
|
|
}
|
|
*/
|
|
|
|
if (!outDexedLib.exists()) {
|
|
RuntimeException dxError = new RuntimeException(getResources().getString(R.string.error_convert_lib, libItem.name) + "\n" + currentLog.toString());
|
|
dxError.setStackTrace(new StackTraceElement[0]);
|
|
throw dxError;
|
|
}
|
|
|
|
outUndexLib.delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
publishProgress("5", getStr(R.string.mcl_launch_download_client) + p1[0]);
|
|
outUnpatchedConvert = new File(unpatchedPath);
|
|
boolean patchedExist = new File(patchedFile).exists();
|
|
if (!patchedExist) {
|
|
if (!outUnpatchedConvert.exists()) {
|
|
if (!new File(inputPath).exists()) {
|
|
currentLog.setLength(0);
|
|
|
|
Tools.downloadFile(
|
|
verInfo.downloads.values().toArray(new MinecraftClientInfo[0])[0].url,
|
|
inputPath,
|
|
true
|
|
);
|
|
}
|
|
|
|
convertStr = getStr(R.string.mcl_launch_convert_client, p1[0]);
|
|
publishProgress("5", convertStr);
|
|
addProgress = 0;
|
|
Tools.runDx(MCLauncherActivity.this, inputPath, outUnpatchedConvert.getAbsolutePath(), true, new PojavDXManager.Listen(){
|
|
|
|
@Override
|
|
public void onReceived(String step, int maxProg, int currProg)
|
|
{
|
|
maxSubProgress = maxProg;
|
|
valSubProgress = currProg;
|
|
publishProgress("0", convertStr + " (" + currProg + "/" + maxProg + ") " + step, "");
|
|
}
|
|
});
|
|
if (!outUnpatchedConvert.exists()) {
|
|
RuntimeException dxError = new RuntimeException(getResources().getString(R.string.error_convert_client) + "\n" + currentLog.toString());
|
|
dxError.setStackTrace(new StackTraceElement[0]);
|
|
throw dxError;
|
|
}
|
|
|
|
patchAndCleanJar(p1[0], outUnpatchedConvert.getAbsolutePath(), patchedFile);
|
|
outUnpatchedConvert.delete();
|
|
} else {
|
|
patchAndCleanJar(p1[0], outUnpatchedConvert.getAbsolutePath(), patchedFile);
|
|
outUnpatchedConvert.delete();
|
|
}
|
|
}
|
|
} catch (Throwable e) {
|
|
launchWithError = true;
|
|
throw e;
|
|
}
|
|
|
|
publishProgress("7", getStr(R.string.mcl_launch_cleancache));
|
|
// new File(inputPath).delete();
|
|
|
|
for (File f : new File(Tools.versnDir).listFiles()) {
|
|
if(f.getName().endsWith(".part")) {
|
|
Log.d(Tools.APP_NAME, "Cleaning cache: " + f);
|
|
f.delete();
|
|
}
|
|
}
|
|
|
|
isAssetsProcessing = true;
|
|
playButton.post(new Runnable(){
|
|
|
|
@Override
|
|
public void run()
|
|
{
|
|
playButton.setText("Skip");
|
|
playButton.setEnabled(true);
|
|
}
|
|
});
|
|
publishProgress("9", getStr(R.string.mcl_launch_download_assets));
|
|
try {
|
|
downloadAssets(verInfo.assets, new File(Tools.ASSETS_PATH));
|
|
} catch (Exception e) {
|
|
// Ignore it
|
|
launchWithError = false;
|
|
} finally {
|
|
isAssetsProcessing = false;
|
|
}
|
|
} catch (Throwable th){
|
|
throwable = th;
|
|
} finally {
|
|
System.setErr(logErr.getRootStream());
|
|
System.setOut(logOut.getRootStream());
|
|
return throwable;
|
|
}
|
|
}
|
|
private int addProgress = 0; // 34
|
|
|
|
public void zeroProgress()
|
|
{
|
|
addProgress = 0;
|
|
}
|
|
|
|
public void setMax(final int value)
|
|
{
|
|
launchProgress.post(new Runnable(){
|
|
|
|
@Override
|
|
public void run()
|
|
{
|
|
launchProgress.setMax(value);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void patchAndCleanJar(String version, String in, String out) throws Exception {
|
|
publishProgress("1", getStr(R.string.mcl_launch_patch_client, version));
|
|
JarSigner.sign(in, out);
|
|
new File(in).delete();
|
|
|
|
// Tools.clearDuplicateFiles(new File(out).getParentFile());
|
|
}
|
|
|
|
@Override
|
|
protected void onProgressUpdate(String... p1)
|
|
{
|
|
int addedProg = Integer.parseInt(p1[0]);
|
|
if (addedProg != -1) {
|
|
addProgress = addProgress + addedProg;
|
|
launchProgress.setProgress(addProgress);
|
|
|
|
launchTextStatus.setText(p1[1]);
|
|
}
|
|
|
|
if (p1.length < 3) consoleView.putLog(p1[1] + (p1.length < 3 ? "\n" : ""));
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(Throwable p1)
|
|
{
|
|
playButton.setText("Play");
|
|
playButton.setEnabled(true);
|
|
launchProgress.setMax(100);
|
|
launchProgress.setProgress(0);
|
|
statusIsLaunching(false);
|
|
if(p1 != null) {
|
|
p1.printStackTrace();
|
|
Tools.showError(MCLauncherActivity.this, p1);
|
|
}
|
|
if(!launchWithError) {
|
|
crashView.setLastCrash("");
|
|
|
|
try {
|
|
/*
|
|
List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
|
|
jvmArgs.add("-Xms128M");
|
|
jvmArgs.add("-Xmx1G");
|
|
*/
|
|
Intent mainIntent = new Intent(MCLauncherActivity.this, MainActivity.class);
|
|
// mainIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
|
|
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
|
mainIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
|
if (PojavPreferenceActivity.PREF_FREEFORM) {
|
|
DisplayMetrics dm = new DisplayMetrics();
|
|
getWindowManager().getDefaultDisplay().getMetrics(dm);
|
|
|
|
ActivityOptions options = (ActivityOptions) ActivityOptions.class.getMethod("makeBasic").invoke(null);
|
|
Rect freeformRect = new Rect(0, 0, dm.widthPixels / 2, dm.heightPixels / 2);
|
|
options.getClass().getDeclaredMethod("setLaunchBounds", Rect.class).invoke(options, freeformRect);
|
|
startActivity(mainIntent, options.toBundle());
|
|
} else {
|
|
startActivity(mainIntent);
|
|
}
|
|
}
|
|
catch (Throwable e) {
|
|
Tools.showError(MCLauncherActivity.this, e);
|
|
}
|
|
|
|
/*
|
|
FloatingIntent maini = new FloatingIntent(MCLauncherActivity.this, MainActivity.class);
|
|
maini.startFloatingActivity();
|
|
*/
|
|
}
|
|
|
|
mTask = null;
|
|
}
|
|
|
|
private Gson gsonss = gson;
|
|
public static final String MINECRAFT_RES = "http://resources.download.minecraft.net/";
|
|
|
|
public JAssets downloadIndex(String versionName, File output) throws Exception {
|
|
String versionJson = DownloadUtils.downloadString("http://s3.amazonaws.com/Minecraft.Download/indexes/" + versionName + ".json");
|
|
JAssets version = gsonss.fromJson(versionJson, JAssets.class);
|
|
output.getParentFile().mkdirs();
|
|
Tools.write(output.getAbsolutePath(), versionJson.getBytes(Charset.forName("UTF-8")));
|
|
return version;
|
|
}
|
|
public void downloadAsset(JAssetInfo asset, File objectsDir) throws IOException, Throwable {
|
|
String assetPath = asset.hash.substring(0, 2) + "/" + asset.hash;
|
|
File outFile = new File(objectsDir, assetPath);
|
|
if (!outFile.exists()) {
|
|
DownloadUtils.downloadFile(MINECRAFT_RES + assetPath, outFile);
|
|
}
|
|
}
|
|
|
|
public void downloadAssets(String assetsVersion, File outputDir) throws IOException, Throwable {
|
|
File hasDownloadedFile = new File(outputDir, "downloaded/" + assetsVersion + ".downloaded");
|
|
if (!hasDownloadedFile.exists()) {
|
|
System.out.println("Assets begin time: " + System.currentTimeMillis());
|
|
JAssets assets = downloadIndex(assetsVersion, new File(outputDir, "indexes/" + assetsVersion + ".json"));
|
|
Map<String, JAssetInfo> assetsObjects = assets.objects;
|
|
launchProgress.setMax(assetsObjects.size());
|
|
zeroProgress();
|
|
File objectsDir = new File(outputDir, "objects");
|
|
int downloadedSs = 0;
|
|
for (JAssetInfo asset : assetsObjects.values()) {
|
|
if (!isAssetsProcessing) {
|
|
return;
|
|
}
|
|
|
|
downloadAsset(asset, objectsDir);
|
|
publishProgress("1", getStr(R.string.mcl_launch_downloading, assetsObjects.keySet().toArray(new String[0])[downloadedSs]));
|
|
downloadedSs++;
|
|
}
|
|
hasDownloadedFile.getParentFile().mkdirs();
|
|
hasDownloadedFile.createNewFile();
|
|
System.out.println("Assets end time: " + System.currentTimeMillis());
|
|
}
|
|
}
|
|
}
|
|
public View findId(int id)
|
|
{
|
|
return findViewById(id);
|
|
}
|
|
private void mkToast(final String str)
|
|
{
|
|
runOnUiThread(new Runnable() {
|
|
public void run() {
|
|
Toast.makeText(MCLauncherActivity.this, str, Toast.LENGTH_LONG).show();
|
|
}
|
|
});
|
|
}
|
|
|
|
public void launcherMenu(View view)
|
|
{
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setTitle(R.string.mcl_options);
|
|
builder.setItems(R.array.mcl_options, new DialogInterface.OnClickListener(){
|
|
|
|
@Override
|
|
public void onClick(DialogInterface p1, int p2)
|
|
{
|
|
switch(p2){
|
|
case 0:{ // Mods manager
|
|
modManager();
|
|
} break;
|
|
case 1:{ // OptiFine installer
|
|
installOptiFine();
|
|
} break;
|
|
case 2:{ // Custom controls
|
|
if (Tools.enableDevFeatures) {
|
|
startActivity(new Intent(MCLauncherActivity.this, CustomControlsActivity.class));
|
|
}
|
|
} break;
|
|
case 3:{ // Settings
|
|
startActivity(new Intent(MCLauncherActivity.this, LauncherPreferenceActivity.class));
|
|
} break;
|
|
case 4:{ // About
|
|
final AlertDialog.Builder aboutB = new AlertDialog.Builder(MCLauncherActivity.this);
|
|
aboutB.setTitle(R.string.mcl_option_about);
|
|
try
|
|
{
|
|
aboutB.setMessage(String.format(Tools.read(getAssets().open("about_en.txt")),
|
|
Tools.APP_NAME,
|
|
Tools.usingVerName,
|
|
org.lwjgl.Sys.getVersion())
|
|
);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
aboutB.setPositiveButton(android.R.string.ok, null);
|
|
aboutB.show();
|
|
} break;
|
|
}
|
|
}
|
|
});
|
|
builder.show();
|
|
}
|
|
|
|
public void modManager()
|
|
{
|
|
/*
|
|
File file1 = new File(Tools.mpModEnable);
|
|
File file2 = new File(Tools.mpModDisable);
|
|
File file3 = new File(Tools.mpModAddNewMo);
|
|
file1.mkdirs();
|
|
file2.mkdir();
|
|
try
|
|
{
|
|
file3.createNewFile();
|
|
}
|
|
catch (IOException e){}
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setTitle("Mods manager (Forge)");
|
|
builder.setPositiveButton(android.R.string.cancel, null);
|
|
|
|
AlertDialog dialog = builder.create();
|
|
|
|
MFileListView flv = new MFileListView(this, dialog);
|
|
flv.listFileAt(Tools.datapath + "/ModsManager");
|
|
flv.setFileSelectedListener(new MFileSelectedListener(){
|
|
|
|
@Override
|
|
public void onFileLongClick(File file, String path, String nane, String extension)
|
|
{
|
|
// TODO: Implement this method
|
|
}
|
|
@Override
|
|
public void onFileSelected(File file, String path, String nane, String extension)
|
|
{
|
|
// TODO: Implement this method
|
|
if(extension.equals(".jar")) {
|
|
|
|
} else {
|
|
openSelectMod();
|
|
}
|
|
}
|
|
});
|
|
dialog.setView(flv);
|
|
dialog.show();
|
|
*/
|
|
|
|
Tools.dialogOnUiThread(this, "Mods manager", "This feature is not yet supported!");
|
|
}
|
|
|
|
public void openSelectMod()
|
|
{
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setTitle(R.string.alerttitle_installmod);
|
|
builder.setPositiveButton(android.R.string.cancel, null);
|
|
|
|
AlertDialog dialog = builder.create();
|
|
FileListView flv = new FileListView(this);
|
|
|
|
dialog.setView(flv);
|
|
dialog.show();
|
|
}
|
|
|
|
private void installOptiFine() {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setTitle(R.string.alerttitle_installoptifine);
|
|
builder.setPositiveButton(android.R.string.cancel, null);
|
|
|
|
final AlertDialog dialog = builder.create();
|
|
FileListView flv = new FileListView(this);
|
|
flv.setFileSelectedListener(new FileSelectedListener(){
|
|
|
|
@Override
|
|
public void onFileSelected(File file, String path, String name) {
|
|
if (name.endsWith(".jar")) {
|
|
doInstallOptiFine(file);
|
|
dialog.dismiss();
|
|
}
|
|
}
|
|
});
|
|
dialog.setView(flv);
|
|
dialog.show();
|
|
}
|
|
|
|
private void doInstallOptiFine(File optifineFile) {
|
|
new OptiFineInstaller().execute(optifineFile);
|
|
}
|
|
|
|
private class OptiFineInstaller extends AsyncTask<File, String, Throwable>
|
|
{
|
|
private ProgressDialog dialog;
|
|
@Override
|
|
protected void onPreExecute() {
|
|
super.onPreExecute();
|
|
dialog = new ProgressDialog(MCLauncherActivity.this);
|
|
dialog.setTitle("Installing OptiFine");
|
|
dialog.setMessage("Preparing");
|
|
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
|
dialog.setMax(5);
|
|
dialog.setCancelable(false);
|
|
dialog.show();
|
|
}
|
|
|
|
@Override
|
|
protected Throwable doInBackground(File[] file) {
|
|
final StringBuilder currentLog = new StringBuilder();
|
|
LoggerJava.LoggerOutputStream logOut = new LoggerJava.LoggerOutputStream(System.out, new LoggerJava.OnStringPrintListener(){
|
|
@Override
|
|
public void onCharPrint(char c)
|
|
{
|
|
currentLog.append(c);
|
|
}
|
|
});
|
|
LoggerJava.LoggerOutputStream logErr = new LoggerJava.LoggerOutputStream(System.err, new LoggerJava.OnStringPrintListener(){
|
|
@Override
|
|
public void onCharPrint(char c)
|
|
{
|
|
currentLog.append(c);
|
|
}
|
|
});
|
|
Throwable throwable = null;
|
|
File convertedFile = null;
|
|
try {
|
|
publishProgress("Preparing", "5");
|
|
|
|
String origMd5 = OptiFinePatcher.calculateMD5(file[0]);
|
|
convertedFile = new File(Tools.optifineDir, origMd5 + ".jar");
|
|
if (!convertedFile.exists()) {
|
|
publishProgress("Patching OptiFine Installer", null, "1", "true");
|
|
|
|
Tools.extractAssetFolder(MCLauncherActivity.this, "optifine_patch", Tools.optifineDir, true);
|
|
|
|
new File(Tools.optifineDir + "/optifine_patch/AndroidOptiFineUtilities.class.patch").delete();
|
|
|
|
String[] output = Tools.patchOptifineInstaller(MCLauncherActivity.this, file[0]);
|
|
File patchedFile = new File(output[1]);
|
|
|
|
publishProgress("Converting OptiFine", null, null, "false");
|
|
|
|
System.setOut(new PrintStream(logOut));
|
|
System.setErr(new PrintStream(logErr));
|
|
|
|
Tools.runDx(MCLauncherActivity.this, patchedFile.getAbsolutePath(), convertedFile.getAbsolutePath(), true, new PojavDXManager.Listen(){
|
|
@Override
|
|
public void onReceived(String msg, int max, int current)
|
|
{
|
|
publishProgress("Converting OptiFine: " + msg, Integer.toString(max), null);
|
|
}
|
|
});
|
|
|
|
if (!convertedFile.exists()) {
|
|
RuntimeException dxError = new RuntimeException(getResources().getString(R.string.error_convert_lib, "OptiFine") + "\n" + currentLog.toString());
|
|
dxError.setStackTrace(new StackTraceElement[0]);
|
|
throw dxError;
|
|
}
|
|
|
|
patchedFile.delete();
|
|
}
|
|
|
|
publishProgress("Launching OptiFine installer", null, null, "true");
|
|
|
|
File optDir = getDir("dalvik-cache", 0);
|
|
optDir.mkdir();
|
|
|
|
DexClassLoader loader = new DexClassLoader(convertedFile.getAbsolutePath(), optDir.getAbsolutePath(), getApplicationInfo().nativeLibraryDir, getClass().getClassLoader());
|
|
AndroidOptiFineUtilities.originalOptifineJar = convertedFile.getAbsolutePath();
|
|
|
|
Class installerClass = loader.loadClass("optifine.AndroidInstaller");
|
|
Method installerMethod = installerClass.getDeclaredMethod("doInstall", File.class);
|
|
installerMethod.invoke(null, new File(Tools.MAIN_PATH));
|
|
|
|
publishProgress("(4/5) Patching OptiFine Tweaker", null, null);
|
|
File optifineLibFile = new File(AndroidOptiFineUtilities.optifineOutputJar);
|
|
if (!optifineLibFile.exists()) {
|
|
throw new FileNotFoundException(optifineLibFile.getAbsolutePath() + "\n\n--- OptiFine installer log ---\n" + currentLog.toString());
|
|
}
|
|
new OptiFinePatcher(optifineLibFile).saveTweaker();
|
|
convertedFile.delete();
|
|
|
|
publishProgress("(5/5) Done!", null, null);
|
|
Thread.sleep(500);
|
|
} catch (Throwable th) {
|
|
throwable = th;
|
|
} finally {
|
|
System.setOut(logOut.getRootStream());
|
|
System.setErr(logErr.getRootStream());
|
|
/*
|
|
if (throwable != null && convertedFile != null) {
|
|
convertedFile.delete();
|
|
}
|
|
*/
|
|
return throwable;
|
|
}
|
|
}
|
|
/*
|
|
private Object fromConfig(DexClassLoader loader, String name) throws ReflectiveOperationException {
|
|
Field f = loader.loadClass("Config").getDeclaredField(name);
|
|
f.setAccessible(true);
|
|
return f.get(null);
|
|
}
|
|
*/
|
|
@Override
|
|
protected void onProgressUpdate(String[] text) {
|
|
super.onProgressUpdate(text);
|
|
dialog.setMessage(text[0]);
|
|
if (text.length > 1 && text[1] != null) {
|
|
dialog.setMax(Integer.valueOf(text[1]));
|
|
} if (text.length > 2) {
|
|
dialog.setProgress(dialog.getProgress() + 1);
|
|
} if (text.length > 3 && text[3] != null) {
|
|
dialog.setIndeterminate(Boolean.getBoolean(text[3]));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(Throwable th) {
|
|
super.onPostExecute(th);
|
|
dialog.dismiss();
|
|
|
|
new RefreshVersionListTask().execute();
|
|
|
|
if (th == null) {
|
|
Toast.makeText(MCLauncherActivity.this, R.string.toast_optifine_success, Toast.LENGTH_SHORT).show();
|
|
} else {
|
|
Tools.showError(MCLauncherActivity.this, th);
|
|
}
|
|
}
|
|
}
|
|
|
|
private class ViewPagerAdapter extends FragmentPagerAdapter {
|
|
|
|
List<Fragment> fragmentList = new ArrayList<>();
|
|
List<String> fragmentTitles = new ArrayList<>();
|
|
|
|
public ViewPagerAdapter(FragmentManager fragmentManager) {
|
|
super(fragmentManager);
|
|
}
|
|
|
|
@Override
|
|
public Fragment getItem(int position) {
|
|
return fragmentList.get(position);
|
|
}
|
|
|
|
@Override
|
|
public int getCount() {
|
|
return fragmentList.size();
|
|
}
|
|
|
|
@Override
|
|
public CharSequence getPageTitle(int position) {
|
|
return fragmentTitles.get(position);
|
|
}
|
|
|
|
public void addFragment(Fragment fragment, String name) {
|
|
fragmentList.add(fragment);
|
|
fragmentTitles.add(name);
|
|
}
|
|
|
|
public void setFragment(int index, Fragment fragment, String name) {
|
|
fragmentList.set(index, fragment);
|
|
fragmentTitles.set(index, name);
|
|
}
|
|
|
|
public void removeFragment(int index) {
|
|
fragmentList.remove(index);
|
|
fragmentTitles.remove(index);
|
|
}
|
|
}
|
|
}
|