Experimental Minecraft Downloader
This is not yet finished, there are 3 main things left - Make sure everything works - (Assets) download old structure - Cleanup What are implemented? - Downloading file is handled with AFNetworking - SHA1 validation, can be turned off in Preferences - inheritsFrom support (need testing) - Downloading assets with 20 jobs parallel Known issue - Assets SHA1 validating freezes the UI Additional things - [Custom controls] Dynamic position error is now handled instead of just crashes - [Custom controls] The editor animation is now changed to fade in/out (for now, later might change) - VGPU renderer is now made hidden, since it's too limited on iOS, removal planned - [Code cleanup] Use NSDictionary instead of a set of fields for renderer list; Fix wrong field name. - Some more stuff...
This commit is contained in:
1 parent
f377789e91
commit
1d7e8a8214
39 files changed
+3809
-401
No files matched your search
@@ -58,8 +58,8 @@ public class PLaunchApp {
|
||||
try {
|
||||
if (AccountJNI.CURRENT_ACCOUNT == null) {
|
||||
AccountJNI.CURRENT_ACCOUNT = MinecraftAccount.load(System.getProperty("pojav.selectedAccount"));
|
||||
mVersion = Tools.getVersionInfo(getSelectedVersion());
|
||||
}
|
||||
mVersion = Tools.getVersionInfo(getSelectedVersion());
|
||||
System.out.println("Launching Minecraft " + mVersion.id);
|
||||
String configPath;
|
||||
if (mVersion.logging != null) {
|
||||
@@ -78,186 +78,8 @@ public class PLaunchApp {
|
||||
}
|
||||
}
|
||||
|
||||
public static void installMinecraft(final String versionPath) {
|
||||
new Thread(() -> {
|
||||
|
||||
currProgress = 0;
|
||||
maxProgress = 0;
|
||||
|
||||
UIKit.updateProgressSafe(0, "Finding a version");
|
||||
String mcver = getSelectedVersion();
|
||||
|
||||
AccountJNI.CURRENT_ACCOUNT.selectedVersion = mcver;
|
||||
try {
|
||||
AccountJNI.CURRENT_ACCOUNT.save();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
UIKit.updateProgressSafe(0, "Selected Minecraft version: " + mcver);
|
||||
|
||||
new File(Tools.DIR_HOME_VERSION + "/" + mcver).mkdirs();
|
||||
|
||||
try {
|
||||
final String downVName = "/" + mcver + "/" + mcver;
|
||||
String minecraftMainJar = Tools.DIR_HOME_VERSION + downVName + ".jar";
|
||||
String verJsonDir = Tools.DIR_HOME_VERSION + downVName + ".json";
|
||||
|
||||
JAssets assets = null;
|
||||
|
||||
if (AccountJNI.CURRENT_ACCOUNT.accessToken.equals("0")) {
|
||||
if (!new File(verJsonDir).exists()) {
|
||||
// Local account: disallow install new version
|
||||
UIKit.showError("Error", "Minecraft can't be legally installed when logged in with a local account. Please switch to an online account to continue.", false);
|
||||
return;
|
||||
} else {
|
||||
// Local account: jump to launch Minecraft, not download anything
|
||||
mVersion = Tools.getVersionInfo(mcver);
|
||||
UIKit.launchMinecraftSurface(mVersion.arguments != null);
|
||||
return;
|
||||
}
|
||||
} else if (versionPath.startsWith("http") && !new File(verJsonDir).exists()) {
|
||||
UIKit.updateProgressSafe(0, "Downloading " + mcver + ".json");
|
||||
Tools.downloadFile(versionPath, verJsonDir);
|
||||
}
|
||||
|
||||
mVersion = Tools.getVersionInfo(mcver);
|
||||
try {
|
||||
UIKit.updateProgressSafe(0, "Downloading " + mcver + ".json assets info");
|
||||
assets = downloadIndex(mVersion.assets, new File(Tools.ASSETS_PATH, "indexes/" + mVersion.assets + ".json"));
|
||||
} catch (IOException e) {
|
||||
UIKit.updateProgressSafe(0, "Error: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (mVersion.logging != null && !mVersion.logging.client.file.id.equals("client-1.12.xml")) {
|
||||
UIKit.updateProgressSafe(0, "Downloading " + mVersion.logging.client.file.id);
|
||||
String configPath = Tools.DIR_GAME_NEW + "/" + mVersion.logging.client.file.id;
|
||||
Tools.downloadFile(mVersion.logging.client.file.url, configPath);
|
||||
}
|
||||
|
||||
maxProgress = mVersion.libraries.length + 1 + (assets == null ? 0 : assets.objects.size());
|
||||
|
||||
File outLib;
|
||||
String libPathURL;
|
||||
|
||||
Tools.preProcessLibraries(mVersion.libraries);
|
||||
for (final DependentLibrary libItem : mVersion.libraries) {
|
||||
if (libItem._skip) {
|
||||
currProgress++;
|
||||
UIKit.updateProgressSafe(currProgress / maxProgress, "Skipped " + libItem.name);
|
||||
// Thread.sleep(100);
|
||||
|
||||
String[] libInfo = libItem.name.split(":");
|
||||
String libArtifact = Tools.artifactToPath(libInfo[0], libInfo[1], libInfo[2]);
|
||||
outLib = new File(Tools.DIR_HOME_LIBRARY + "/" + libArtifact);
|
||||
outLib.delete();
|
||||
} else {
|
||||
String[] libInfo = libItem.name.split(":");
|
||||
String libArtifact = Tools.artifactToPath(libInfo[0], libInfo[1], libInfo[2]);
|
||||
outLib = new File(Tools.DIR_HOME_LIBRARY + "/" + libArtifact);
|
||||
outLib.getParentFile().mkdirs();
|
||||
|
||||
if (!outLib.exists()) {
|
||||
currProgress++;
|
||||
UIKit.updateProgressSafe(currProgress / maxProgress, "Downloading " + libItem.name);
|
||||
|
||||
if (libItem.downloads == null || libItem.downloads.artifact == null) {
|
||||
MinecraftLibraryArtifact artifact = new MinecraftLibraryArtifact();
|
||||
artifact.url = (libItem.url == null ? "https://libraries.minecraft.net/" : libItem.url) + libArtifact;
|
||||
libItem.downloads = new DependentLibrary.LibraryDownloads(artifact);
|
||||
}
|
||||
try {
|
||||
libPathURL = libItem.downloads.artifact.url;
|
||||
Tools.downloadFile(libPathURL, outLib.getAbsolutePath());
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
UIKit.updateProgressSafe(currProgress / maxProgress, "Download failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currProgress++;
|
||||
File minecraftMainFile = new File(minecraftMainJar);
|
||||
if (!minecraftMainFile.exists() || minecraftMainFile.length() == 0l) {
|
||||
UIKit.updateProgressSafe(currProgress / maxProgress, "Downloading " + mcver + ".jar");
|
||||
Tools.downloadFile(mVersion.downloads.values().toArray(new MinecraftClientInfo[0])[0].url, minecraftMainJar);
|
||||
}
|
||||
|
||||
if (assets != null) {
|
||||
mIsAssetsProcessing = true;
|
||||
downloadAssets(assets, mVersion.assets, assets.map_to_resources ? new File(Tools.OBSOLETE_RESOURCES_PATH) : new File(Tools.ASSETS_PATH));
|
||||
}
|
||||
|
||||
// TODO download assets
|
||||
|
||||
} catch (IOException e) {
|
||||
UIKit.updateProgressSafe(currProgress / maxProgress, "Download error, skipping");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
UIKit.launchMinecraftSurface(mVersion.arguments != null);
|
||||
|
||||
}).start();
|
||||
}
|
||||
|
||||
private static int downloaded = 0;
|
||||
public static void downloadAssets(final JAssets assets, String assetsVersion, final File outputDir) throws IOException {
|
||||
LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
|
||||
final ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 500, TimeUnit.MILLISECONDS, workQueue);
|
||||
|
||||
File hasDownloadedFile = new File(outputDir, "downloaded/" + assetsVersion + ".downloaded");
|
||||
if (!hasDownloadedFile.exists()) {
|
||||
System.out.println("Assets begin time: " + System.currentTimeMillis());
|
||||
Map<String, JAssetInfo> assetsObjects = assets.objects;
|
||||
File objectsDir = new File(outputDir, "objects");
|
||||
for (JAssetInfo asset : assetsObjects.values()) {
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
String assetName = assetsObjects.keySet().toArray(new String[0])[downloaded];
|
||||
if(!assets.map_to_resources) downloadAsset(assetName, asset, objectsDir);
|
||||
else downloadAssetMapped(assetName, asset, outputDir);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
mIsAssetsProcessing = false;
|
||||
}
|
||||
currProgress++;
|
||||
downloaded++;
|
||||
});
|
||||
}
|
||||
executor.shutdown();
|
||||
try {
|
||||
while ((!executor.awaitTermination(250, TimeUnit.MILLISECONDS)) && mIsAssetsProcessing) {}
|
||||
executor.shutdownNow();
|
||||
while (!executor.awaitTermination(250, TimeUnit.MILLISECONDS)) {}
|
||||
System.out.println("Fully shut down!");
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("Assets end time: " + System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final String MINECRAFT_RES = "https://resources.download.minecraft.net/";
|
||||
|
||||
public static JAssets downloadIndex(String versionName, File output) throws IOException {
|
||||
if (!output.exists()) {
|
||||
output.getParentFile().mkdirs();
|
||||
DownloadUtils.downloadFile(mVersion.assetIndex != null ? mVersion.assetIndex.url : "https://s3.amazonaws.com/Minecraft.Download/indexes/" + versionName + ".json", output);
|
||||
}
|
||||
|
||||
return Tools.GLOBAL_GSON.fromJson(Tools.read(output.getAbsolutePath()), JAssets.class);
|
||||
}
|
||||
|
||||
public static void downloadAsset(String assetName, JAssetInfo asset, File objectsDir) throws IOException {
|
||||
String assetPath = asset.hash.substring(0, 2) + "/" + asset.hash;
|
||||
File outFile = new File(objectsDir, assetPath);
|
||||
if (!outFile.exists()) {
|
||||
UIKit.updateProgressSafe(currProgress / maxProgress, "Downloading " + assetName);
|
||||
DownloadUtils.downloadFile(MINECRAFT_RES + assetPath, outFile);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
/*
|
||||
public static void downloadAssetMapped(String assetName, JAssetInfo asset, File resDir) throws IOException {
|
||||
String assetPath = asset.hash.substring(0, 2) + "/" + asset.hash;
|
||||
File outFile = new File(resDir,"/"+assetName);
|
||||
@@ -266,4 +88,5 @@ public class PLaunchApp {
|
||||
DownloadUtils.downloadFile(MINECRAFT_RES + assetPath, outFile);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public final class Tools
|
||||
|
||||
// System.out.println("Minecraft Args: " + Arrays.toString(launchArgs));
|
||||
|
||||
final String launchClassPath = generateLaunchClassPath(profile.selectedVersion);
|
||||
final String launchClassPath = generateLaunchClassPath(versionInfo);
|
||||
|
||||
List<String> javaArgList = new ArrayList<String>();
|
||||
//javaArgList.add(versionInfo.logging.client.argument.replace("${path}", DIR_GAME_NEW.getAbsolutePath() + "/" + mVersion.logging.client.file.id));
|
||||
@@ -251,9 +251,6 @@ public final class Tools
|
||||
return group.replaceAll("\\.", "/") + "/" + artifact + "/" + version + "/" + artifact + "-" + version + ".jar";
|
||||
}
|
||||
|
||||
public static String getPatchedFile(String version) {
|
||||
return DIR_HOME_VERSION + "/" + version + "/" + version + ".jar";
|
||||
}
|
||||
/*
|
||||
private static String getLWJGL3ClassPath() {
|
||||
StringBuilder libStr = new StringBuilder();
|
||||
@@ -271,10 +268,9 @@ public final class Tools
|
||||
}
|
||||
*/
|
||||
private static boolean isClientFirst = false;
|
||||
public static String generateLaunchClassPath(String version) {
|
||||
public static String generateLaunchClassPath(JMinecraftVersionList.Version info) {
|
||||
StringBuilder libStr = new StringBuilder(); //versnDir + "/" + version + "/" + version + ".jar:";
|
||||
|
||||
JMinecraftVersionList.Version info = getVersionInfo(version);
|
||||
String[] classpath = generateLibClasspath(info);
|
||||
|
||||
// Debug: LWJGL 3 override
|
||||
@@ -298,7 +294,7 @@ public final class Tools
|
||||
*/
|
||||
|
||||
if (isClientFirst) {
|
||||
libStr.append(getPatchedFile(version));
|
||||
libStr.append(DIR_HOME_VERSION + "/" + info.id + "/" + info.id + ".jar");
|
||||
}
|
||||
for (String perJar : classpath) {
|
||||
if (!new File(perJar).exists()) {
|
||||
@@ -308,7 +304,7 @@ public final class Tools
|
||||
libStr.append((isClientFirst ? ":" : "") + perJar + (!isClientFirst ? ":" : ""));
|
||||
}
|
||||
if (!isClientFirst) {
|
||||
libStr.append(getPatchedFile(version));
|
||||
libStr.append(DIR_HOME_VERSION + "/" + info.id + "/" + info.id + ".jar");
|
||||
}
|
||||
|
||||
return libStr.toString();
|
||||
|
||||
@@ -31,20 +31,18 @@ public class AccountJNI {
|
||||
e.printStackTrace();
|
||||
// ignore, since it's likely that the user is offline
|
||||
}
|
||||
break;
|
||||
return (CURRENT_ACCOUNT.accessToken.equals("0") ? "-" : "$") + CURRENT_ACCOUNT.username;
|
||||
|
||||
case TYPE_MICROSOFT:
|
||||
CURRENT_ACCOUNT = new MicrosoftAuthTask().run("false", data);
|
||||
break;
|
||||
return "$" + CURRENT_ACCOUNT.username;
|
||||
|
||||
case TYPE_OFFLINE:
|
||||
CURRENT_ACCOUNT = new MinecraftAccount();
|
||||
CURRENT_ACCOUNT.username = data;
|
||||
CURRENT_ACCOUNT.save();
|
||||
break;
|
||||
return "-" + CURRENT_ACCOUNT.username;
|
||||
}
|
||||
|
||||
return CURRENT_ACCOUNT.username;
|
||||
} catch (Throwable th) {
|
||||
Tools.showError(th);
|
||||
}
|
||||
|
||||
@@ -85,10 +85,6 @@ public class UIKit {
|
||||
}
|
||||
}, "ModInstallerThread").start();
|
||||
}
|
||||
|
||||
public static void callback_LauncherViewController_installMinecraft(String versionPath) {
|
||||
PLaunchApp.installMinecraft(versionPath);
|
||||
}
|
||||
|
||||
public static void callback_SurfaceViewController_launchMinecraft(int width, int height, String rendererLibName) {
|
||||
MCOptionUtils.load();
|
||||
@@ -146,11 +142,6 @@ public class UIKit {
|
||||
}
|
||||
updateMCGuiScale(guiScale);
|
||||
}
|
||||
|
||||
public static void updateProgressSafe(final float progress, final String message) {
|
||||
System.out.println(message);
|
||||
updateProgress(progress, ((int) (progress * 100)) + "% - " + message);
|
||||
}
|
||||
|
||||
static {
|
||||
System.load(System.getenv("BUNDLE_PATH") + "/PojavLauncher");
|
||||
@@ -164,10 +155,4 @@ public class UIKit {
|
||||
public static native void showError(String title, String message, boolean exitIfOk);
|
||||
|
||||
private static native void updateMCGuiScale(int scale);
|
||||
|
||||
// Update progress
|
||||
public static native void updateProgress(float progress, String message);
|
||||
|
||||
// Start SurfaceViewController
|
||||
public static native void launchMinecraftSurface(boolean isUseStackQueueBool);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user