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:
khanhduytran0 committed 2022-04-20 20:45:47 +07:00
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);
}
}
*/
}