mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-15 15:48:26 -04:00
CurseForge modpack download (WIP) + more generalization
This commit is contained in:
parent
b430edbc0b
commit
19a781ad18
@ -987,6 +987,12 @@ public final class Tools {
|
|||||||
return prefixedName.substring(Tools.LAUNCHERPROFILES_RTPREFIX.length());
|
return prefixedName.substring(Tools.LAUNCHERPROFILES_RTPREFIX.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getFileName(String pathOrUrl) {
|
||||||
|
int lastSlashIndex = pathOrUrl.lastIndexOf('/');
|
||||||
|
if(lastSlashIndex == -1) return null;
|
||||||
|
return pathOrUrl.substring(lastSlashIndex);
|
||||||
|
}
|
||||||
|
|
||||||
public static String getSelectedRuntime(MinecraftProfile minecraftProfile) {
|
public static String getSelectedRuntime(MinecraftProfile minecraftProfile) {
|
||||||
String runtime = LauncherPreferences.PREF_DEFAULT_RUNTIME;
|
String runtime = LauncherPreferences.PREF_DEFAULT_RUNTIME;
|
||||||
String profileRuntime = getRuntimeName(minecraftProfile.javaDir);
|
String profileRuntime = getRuntimeName(minecraftProfile.javaDir);
|
||||||
|
@ -5,14 +5,16 @@ import android.util.Log;
|
|||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.kdt.mcgui.ProgressLayout;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.Constants;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.Constants;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.CurseManifest;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.CurseManifest;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModDetail;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModDetail;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModItem;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModItem;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModrinthIndex;
|
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.SearchFilters;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.SearchFilters;
|
||||||
|
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||||
import net.kdt.pojavlaunch.utils.ZipUtils;
|
import net.kdt.pojavlaunch.utils.ZipUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -31,6 +33,8 @@ public class CurseforgeApi implements ModpackApi{
|
|||||||
// https://api.curseforge.com/v1/categories?gameId=432 and search for "Mods" (case-sensitive)
|
// https://api.curseforge.com/v1/categories?gameId=432 and search for "Mods" (case-sensitive)
|
||||||
private static final int CURSEFORGE_MOD_CLASS_ID = 6;
|
private static final int CURSEFORGE_MOD_CLASS_ID = 6;
|
||||||
private static final int CURSEFORGE_PAGINATION_SIZE = 50;
|
private static final int CURSEFORGE_PAGINATION_SIZE = 50;
|
||||||
|
private static final int CURSEFORGE_PAGINATION_END_REACHED = -1;
|
||||||
|
private static final int CURSEFORGE_PAGINATION_ERROR = -2;
|
||||||
|
|
||||||
private final ApiHandler mApiHandler = new ApiHandler("https://api.curseforge.com/v1", "$2a$10$Vxkj4kH1Ekf8EsS4Mx8b2eVTHsht107Lk2erVEUtnbqvojsLy.jYq");
|
private final ApiHandler mApiHandler = new ApiHandler("https://api.curseforge.com/v1", "$2a$10$Vxkj4kH1Ekf8EsS4Mx8b2eVTHsht107Lk2erVEUtnbqvojsLy.jYq");
|
||||||
|
|
||||||
@ -71,10 +75,11 @@ public class CurseforgeApi implements ModpackApi{
|
|||||||
public ModDetail getModDetails(ModItem item) {
|
public ModDetail getModDetails(ModItem item) {
|
||||||
ArrayList<JsonObject> allModDetails = new ArrayList<>();
|
ArrayList<JsonObject> allModDetails = new ArrayList<>();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while(index != -1 && index != -2) {
|
while(index != CURSEFORGE_PAGINATION_END_REACHED &&
|
||||||
|
index != CURSEFORGE_PAGINATION_ERROR) {
|
||||||
index = getPaginatedDetails(allModDetails, index, item.id);
|
index = getPaginatedDetails(allModDetails, index, item.id);
|
||||||
}
|
}
|
||||||
if(index == -2) return null;
|
if(index == CURSEFORGE_PAGINATION_ERROR) return null;
|
||||||
int length = allModDetails.size();
|
int length = allModDetails.size();
|
||||||
String[] versionNames = new String[length];
|
String[] versionNames = new String[length];
|
||||||
String[] mcVersionNames = new String[length];
|
String[] mcVersionNames = new String[length];
|
||||||
@ -99,8 +104,8 @@ public class CurseforgeApi implements ModpackApi{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void installMod(ModDetail modDetail, int selectedVersion) {
|
public void installMod(ModDetail modDetail, int selectedVersion) {
|
||||||
String versionUrl = modDetail.versionUrls[selectedVersion];
|
//TODO considering only modpacks for now
|
||||||
File modpackFile = new File(Tools.DIR_CACHE, modDetail.id+".zip");
|
ModpackInstaller.installModpack(modDetail, selectedVersion, this::installCurseforgeZip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -109,16 +114,16 @@ public class CurseforgeApi implements ModpackApi{
|
|||||||
params.put("index", index);
|
params.put("index", index);
|
||||||
params.put("pageSize", CURSEFORGE_PAGINATION_SIZE);
|
params.put("pageSize", CURSEFORGE_PAGINATION_SIZE);
|
||||||
JsonObject response = mApiHandler.get("mods/"+modId+"/files", params, JsonObject.class);
|
JsonObject response = mApiHandler.get("mods/"+modId+"/files", params, JsonObject.class);
|
||||||
if(response == null) return -2;
|
if(response == null) return CURSEFORGE_PAGINATION_ERROR;
|
||||||
JsonArray data = response.getAsJsonArray("data");
|
JsonArray data = response.getAsJsonArray("data");
|
||||||
if(data == null) return -2;
|
if(data == null) return CURSEFORGE_PAGINATION_ERROR;
|
||||||
for(int i = 0; i < data.size(); i++) {
|
for(int i = 0; i < data.size(); i++) {
|
||||||
JsonObject fileInfo = data.get(i).getAsJsonObject();
|
JsonObject fileInfo = data.get(i).getAsJsonObject();
|
||||||
if(fileInfo.get("isServerPack").getAsBoolean()) continue;
|
if(fileInfo.get("isServerPack").getAsBoolean()) continue;
|
||||||
objectList.add(fileInfo);
|
objectList.add(fileInfo);
|
||||||
}
|
}
|
||||||
if(data.size() < CURSEFORGE_PAGINATION_SIZE) {
|
if(data.size() < CURSEFORGE_PAGINATION_SIZE) {
|
||||||
return -1; // we read the remainder! yay!
|
return CURSEFORGE_PAGINATION_END_REACHED; // we read the remainder! yay!
|
||||||
}
|
}
|
||||||
return index + data.size();
|
return index + data.size();
|
||||||
}
|
}
|
||||||
@ -128,7 +133,72 @@ public class CurseforgeApi implements ModpackApi{
|
|||||||
CurseManifest curseManifest = Tools.GLOBAL_GSON.fromJson(
|
CurseManifest curseManifest = Tools.GLOBAL_GSON.fromJson(
|
||||||
Tools.read(ZipUtils.getEntryStream(modpackZipFile, "manifest.json")),
|
Tools.read(ZipUtils.getEntryStream(modpackZipFile, "manifest.json")),
|
||||||
CurseManifest.class);
|
CurseManifest.class);
|
||||||
|
if(!verifyManifest(curseManifest)) {
|
||||||
|
Log.i("CurseforgeApi","manifest verification failed");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModDownloader modDownloader = new ModDownloader(new File(instanceDestination,"mods"), true);
|
||||||
|
int fileCount = curseManifest.files.length;
|
||||||
|
for(int i = 0; i < fileCount; i++) {
|
||||||
|
CurseManifest.CurseFile curseFile = curseManifest.files[i];
|
||||||
|
String downloadUrl = getDownloadUrl(curseFile.projectID, curseFile.fileID);
|
||||||
|
if(downloadUrl == null && curseFile.required) throw new IOException("Failed to obtain download URL for "+curseFile.projectID+" "+curseFile.fileID);
|
||||||
|
else if(downloadUrl == null) continue;
|
||||||
|
modDownloader.submitDownload(Tools.getFileName(downloadUrl), downloadUrl);
|
||||||
|
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, (int) Math.max((float)i/fileCount*100,0), R.string.modpack_download_getting_links, i, fileCount);
|
||||||
|
}
|
||||||
|
modDownloader.awaitFinish((c,m)->{ // insert joke about semen
|
||||||
|
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, (int) Math.max((float)c/m*100,0), R.string.modpack_download_downloading_mods_fc, c, m);
|
||||||
|
});
|
||||||
|
String overridesDir = "overrides";
|
||||||
|
if(curseManifest.overrides != null) overridesDir = curseManifest.overrides;
|
||||||
|
ZipUtils.zipExtract(modpackZipFile, overridesDir, instanceDestination);
|
||||||
|
return createInfo(curseManifest.minecraft);
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
private ModLoaderInfo createInfo(CurseManifest.CurseMinecraft minecraft) {
|
||||||
|
CurseManifest.CurseModLoader primaryModLoader = null;
|
||||||
|
for(CurseManifest.CurseModLoader modLoader : minecraft.modLoaders) {
|
||||||
|
if(modLoader.primary) {
|
||||||
|
primaryModLoader = modLoader;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(primaryModLoader == null) primaryModLoader = minecraft.modLoaders[0];
|
||||||
|
String modLoaderId = primaryModLoader.id;
|
||||||
|
int dashIndex = modLoaderId.indexOf('-');
|
||||||
|
String modLoaderName = modLoaderId.substring(0, dashIndex);
|
||||||
|
String modLoaderVersion = modLoaderId.substring(dashIndex+1);
|
||||||
|
int modLoaderTypeInt = -1;
|
||||||
|
switch (modLoaderName) {
|
||||||
|
case "forge":
|
||||||
|
modLoaderTypeInt = ModLoaderInfo.MOD_LOADER_FORGE;
|
||||||
|
break;
|
||||||
|
case "fabric":
|
||||||
|
modLoaderTypeInt = ModLoaderInfo.MOD_LOADER_FABRIC;
|
||||||
|
break;
|
||||||
|
//TODO: Quilt is also Forge? How does that work?
|
||||||
|
}
|
||||||
|
if(modLoaderTypeInt == -1) return null;
|
||||||
|
return new ModLoaderInfo(modLoaderTypeInt, modLoaderVersion, minecraft.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDownloadUrl(long projectID, long fileID) {
|
||||||
|
JsonObject response = mApiHandler.get("mods/"+projectID+"/files/"+fileID+"/download-url", JsonObject.class);
|
||||||
|
if(response == null) return null;
|
||||||
|
JsonElement data = response.get("data");
|
||||||
|
if(data == null || data.isJsonNull()) return null;
|
||||||
|
return data.getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean verifyManifest(CurseManifest manifest) {
|
||||||
|
if(!"minecraftModpack".equals(manifest.manifestType)) return false;
|
||||||
|
if(manifest.manifestVersion != 1) return false;
|
||||||
|
if(manifest.minecraft == null) return false;
|
||||||
|
if(manifest.minecraft.version == null) return false;
|
||||||
|
if(manifest.minecraft.modLoaders == null) return false;
|
||||||
|
if(manifest.minecraft.modLoaders.length < 1) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,28 @@ public class ModDownloader {
|
|||||||
private final AtomicLong mDownloadSize = new AtomicLong(0);
|
private final AtomicLong mDownloadSize = new AtomicLong(0);
|
||||||
private final Object mExceptionSyncPoint = new Object();
|
private final Object mExceptionSyncPoint = new Object();
|
||||||
private final File mDestinationDirectory;
|
private final File mDestinationDirectory;
|
||||||
|
private final boolean mUseFileCount;
|
||||||
private IOException mFirstIOException;
|
private IOException mFirstIOException;
|
||||||
private long mTotalSize;
|
private long mTotalSize;
|
||||||
|
|
||||||
public ModDownloader(File destinationDirectory) {
|
public ModDownloader(File destinationDirectory) {
|
||||||
|
this(destinationDirectory, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModDownloader(File destinationDirectory, boolean useFileCount) {
|
||||||
this.mDestinationDirectory = destinationDirectory;
|
this.mDestinationDirectory = destinationDirectory;
|
||||||
|
this.mUseFileCount = useFileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void submitDownload(int fileSize, String relativePath, String... url) {
|
public void submitDownload(int fileSize, String relativePath, String... url) {
|
||||||
mTotalSize += fileSize;
|
if(mUseFileCount) mTotalSize += 1;
|
||||||
|
else mTotalSize += fileSize;
|
||||||
|
mDownloadPool.execute(new DownloadTask(url, new File(mDestinationDirectory, relativePath)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void submitDownload(String relativePath, String... url) {
|
||||||
|
if(!mUseFileCount) throw new RuntimeException("This method can only be used in a file-counting ModDownloader");
|
||||||
|
mTotalSize += 1;
|
||||||
mDownloadPool.execute(new DownloadTask(url, new File(mDestinationDirectory, relativePath)));
|
mDownloadPool.execute(new DownloadTask(url, new File(mDestinationDirectory, relativePath)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +108,7 @@ public class ModDownloader {
|
|||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
try {
|
try {
|
||||||
DownloadUtils.downloadFileMonitored(sourceUrl, mDestination, getThreadLocalBuffer(), this);
|
DownloadUtils.downloadFileMonitored(sourceUrl, mDestination, getThreadLocalBuffer(), this);
|
||||||
|
if(mUseFileCount) mDownloadSize.addAndGet(1);
|
||||||
return null;
|
return null;
|
||||||
} catch (InterruptedIOException e) {
|
} catch (InterruptedIOException e) {
|
||||||
throw new InterruptedException();
|
throw new InterruptedException();
|
||||||
@ -102,14 +116,17 @@ public class ModDownloader {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
exception = e;
|
exception = e;
|
||||||
}
|
}
|
||||||
mDownloadSize.addAndGet(-last);
|
if(!mUseFileCount) {
|
||||||
last = 0;
|
mDownloadSize.addAndGet(-last);
|
||||||
|
last = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return exception;
|
return exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateProgress(int curr, int max) {
|
public void updateProgress(int curr, int max) {
|
||||||
|
if(mUseFileCount) return;
|
||||||
mDownloadSize.addAndGet(curr - last);
|
mDownloadSize.addAndGet(curr - last);
|
||||||
last = curr;
|
last = curr;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package net.kdt.pojavlaunch.modloaders.modpacks.api;
|
package net.kdt.pojavlaunch.modloaders.modpacks.api;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.JavaGUILauncherActivity;
|
||||||
|
|
||||||
public class ModLoaderInfo {
|
public class ModLoaderInfo {
|
||||||
public static final int MOD_LOADER_FORGE = 0;
|
public static final int MOD_LOADER_FORGE = 0;
|
||||||
public static final int MOD_LOADER_FABRIC = 1;
|
public static final int MOD_LOADER_FABRIC = 1;
|
||||||
@ -21,7 +26,7 @@ public class ModLoaderInfo {
|
|||||||
case MOD_LOADER_FABRIC:
|
case MOD_LOADER_FABRIC:
|
||||||
return "fabric-loader-"+modLoaderVersion+"-"+minecraftVersion;
|
return "fabric-loader-"+modLoaderVersion+"-"+minecraftVersion;
|
||||||
case MOD_LOADER_QUILT:
|
case MOD_LOADER_QUILT:
|
||||||
// TODO
|
throw new RuntimeException("Quilt is gay af");
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
package net.kdt.pojavlaunch.modloaders.modpacks.api;
|
||||||
|
|
||||||
|
import com.kdt.mcgui.ProgressLayout;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.R;
|
||||||
|
import net.kdt.pojavlaunch.Tools;
|
||||||
|
import net.kdt.pojavlaunch.modloaders.modpacks.imagecache.ModIconCache;
|
||||||
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModDetail;
|
||||||
|
import net.kdt.pojavlaunch.progresskeeper.DownloaderProgressWrapper;
|
||||||
|
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
||||||
|
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
|
||||||
|
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class ModpackInstaller {
|
||||||
|
|
||||||
|
public static void installModpack(ModDetail modDetail, int selectedVersion, InstallFunction installFunction) {
|
||||||
|
String versionUrl = modDetail.versionUrls[selectedVersion];
|
||||||
|
String modpackName = modDetail.title.toLowerCase(Locale.ROOT).trim().replace(" ", "_" );
|
||||||
|
|
||||||
|
// Build a new minecraft instance, folder first
|
||||||
|
|
||||||
|
// Get the modpack file
|
||||||
|
File modpackFile = new File(Tools.DIR_CACHE, modpackName + ".cf"); // Cache File
|
||||||
|
ModLoaderInfo modLoaderInfo;
|
||||||
|
try {
|
||||||
|
byte[] downloadBuffer = new byte[8192];
|
||||||
|
DownloadUtils.downloadFileMonitored(versionUrl, modpackFile, downloadBuffer,
|
||||||
|
new DownloaderProgressWrapper(R.string.modpack_download_downloading_metadata,
|
||||||
|
ProgressLayout.INSTALL_MODPACK));
|
||||||
|
// Install the modpack
|
||||||
|
modLoaderInfo = installFunction.installModpack(modpackFile, new File(Tools.DIR_GAME_HOME, "custom_instances/"+modpackName));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
modpackFile.delete();
|
||||||
|
ProgressLayout.clearProgress(ProgressLayout.INSTALL_MODPACK);
|
||||||
|
}
|
||||||
|
if(modLoaderInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the instance
|
||||||
|
MinecraftProfile profile = new MinecraftProfile();
|
||||||
|
profile.gameDir = "./custom_instances/" + modpackName;
|
||||||
|
profile.name = modDetail.title;
|
||||||
|
profile.lastVersionId = modLoaderInfo.getVersionId();
|
||||||
|
profile.icon = ModIconCache.getBase64Image(modDetail.getIconCacheTag());
|
||||||
|
|
||||||
|
|
||||||
|
LauncherProfiles.mainProfileJson.profiles.put(modpackName, profile);
|
||||||
|
LauncherProfiles.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InstallFunction {
|
||||||
|
ModLoaderInfo installModpack(File modpackFile, File instanceDestination) throws IOException;
|
||||||
|
}
|
||||||
|
}
|
@ -6,22 +6,17 @@ import com.kdt.mcgui.ProgressLayout;
|
|||||||
|
|
||||||
import net.kdt.pojavlaunch.R;
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.imagecache.ModIconCache;
|
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.Constants;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.Constants;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModDetail;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModDetail;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModItem;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModItem;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModrinthIndex;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModrinthIndex;
|
||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.SearchFilters;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.SearchFilters;
|
||||||
import net.kdt.pojavlaunch.progresskeeper.DownloaderProgressWrapper;
|
import net.kdt.pojavlaunch.progresskeeper.DownloaderProgressWrapper;
|
||||||
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
|
||||||
import net.kdt.pojavlaunch.utils.ZipUtils;
|
import net.kdt.pojavlaunch.utils.ZipUtils;
|
||||||
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
|
|
||||||
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
@ -93,41 +88,7 @@ public class ModrinthApi implements ModpackApi{
|
|||||||
@Override
|
@Override
|
||||||
public void installMod(ModDetail modDetail, int selectedVersion) {
|
public void installMod(ModDetail modDetail, int selectedVersion) {
|
||||||
//TODO considering only modpacks for now
|
//TODO considering only modpacks for now
|
||||||
String versionUrl = modDetail.versionUrls[selectedVersion];
|
ModpackInstaller.installModpack(modDetail, selectedVersion, this::installMrpack);
|
||||||
String modpackName = modDetail.title.toLowerCase(Locale.ROOT).trim().replace(" ", "_" );
|
|
||||||
|
|
||||||
// Build a new minecraft instance, folder first
|
|
||||||
|
|
||||||
// Get the mrpack
|
|
||||||
File modpackFile = new File(Tools.DIR_CACHE, modpackName + ".mrpack");
|
|
||||||
ModLoaderInfo modLoaderInfo;
|
|
||||||
try {
|
|
||||||
byte[] downloadBuffer = new byte[8192];
|
|
||||||
DownloadUtils.downloadFileMonitored(versionUrl, modpackFile, downloadBuffer,
|
|
||||||
new DownloaderProgressWrapper(R.string.modpack_download_downloading_metadata,
|
|
||||||
ProgressLayout.INSTALL_MODPACK));
|
|
||||||
ModrinthIndex modrinthIndex = installMrpack(modpackFile, new File(Tools.DIR_GAME_HOME, "custom_instances/"+modpackName));
|
|
||||||
modLoaderInfo = createInfo(modrinthIndex);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
modpackFile.delete();
|
|
||||||
ProgressLayout.clearProgress(ProgressLayout.INSTALL_MODPACK);
|
|
||||||
}
|
|
||||||
if(modLoaderInfo == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the instance
|
|
||||||
MinecraftProfile profile = new MinecraftProfile();
|
|
||||||
profile.gameDir = "./custom_instances/" + modpackName;
|
|
||||||
profile.name = modDetail.title;
|
|
||||||
profile.lastVersionId = modLoaderInfo.getVersionId();
|
|
||||||
profile.icon = ModIconCache.getBase64Image(modDetail.getIconCacheTag());
|
|
||||||
|
|
||||||
|
|
||||||
LauncherProfiles.mainProfileJson.profiles.put(modpackName, profile);
|
|
||||||
LauncherProfiles.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ModLoaderInfo createInfo(ModrinthIndex modrinthIndex) {
|
private static ModLoaderInfo createInfo(ModrinthIndex modrinthIndex) {
|
||||||
@ -143,13 +104,12 @@ public class ModrinthApi implements ModpackApi{
|
|||||||
return new ModLoaderInfo(ModLoaderInfo.MOD_LOADER_FABRIC, modLoaderVersion, mcVersion);
|
return new ModLoaderInfo(ModLoaderInfo.MOD_LOADER_FABRIC, modLoaderVersion, mcVersion);
|
||||||
}
|
}
|
||||||
if((modLoaderVersion = dependencies.get("quilt-loader")) != null) {
|
if((modLoaderVersion = dependencies.get("quilt-loader")) != null) {
|
||||||
throw new RuntimeException("Quilt is gay af");
|
return new ModLoaderInfo(ModLoaderInfo.MOD_LOADER_QUILT, modLoaderVersion, mcVersion);
|
||||||
//return new ModLoaderInfo(ModLoaderInfo.MOD_LOADER_QUILT, modLoaderVersion, mcVersion);
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModrinthIndex installMrpack(File mrpackFile, File instanceDestination) throws IOException {
|
private ModLoaderInfo installMrpack(File mrpackFile, File instanceDestination) throws IOException {
|
||||||
try (ZipFile modpackZipFile = new ZipFile(mrpackFile)){
|
try (ZipFile modpackZipFile = new ZipFile(mrpackFile)){
|
||||||
ModrinthIndex modrinthIndex = Tools.GLOBAL_GSON.fromJson(
|
ModrinthIndex modrinthIndex = Tools.GLOBAL_GSON.fromJson(
|
||||||
Tools.read(ZipUtils.getEntryStream(modpackZipFile, "modrinth.index.json")),
|
Tools.read(ZipUtils.getEntryStream(modpackZipFile, "modrinth.index.json")),
|
||||||
@ -164,7 +124,7 @@ public class ModrinthApi implements ModpackApi{
|
|||||||
ZipUtils.zipExtract(modpackZipFile, "overrides/", instanceDestination);
|
ZipUtils.zipExtract(modpackZipFile, "overrides/", instanceDestination);
|
||||||
ProgressLayout.setProgress(ProgressLayout.INSTALL_MODPACK, 50, R.string.modpack_download_applying_overrides, 2, 2);
|
ProgressLayout.setProgress(ProgressLayout.INSTALL_MODPACK, 50, R.string.modpack_download_applying_overrides, 2, 2);
|
||||||
ZipUtils.zipExtract(modpackZipFile, "client-overrides/", instanceDestination);
|
ZipUtils.zipExtract(modpackZipFile, "client-overrides/", instanceDestination);
|
||||||
return modrinthIndex;
|
return createInfo(modrinthIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ public class CurseManifest {
|
|||||||
public static class CurseFile {
|
public static class CurseFile {
|
||||||
public long projectID;
|
public long projectID;
|
||||||
public long fileID;
|
public long fileID;
|
||||||
|
public boolean required;
|
||||||
}
|
}
|
||||||
public static class CurseMinecraft {
|
public static class CurseMinecraft {
|
||||||
public String version;
|
public String version;
|
||||||
|
@ -416,5 +416,7 @@
|
|||||||
|
|
||||||
<string name="modpack_download_downloading_metadata">Downloading modpack metadata (%.2f MB / %.2f MB)</string>
|
<string name="modpack_download_downloading_metadata">Downloading modpack metadata (%.2f MB / %.2f MB)</string>
|
||||||
<string name="modpack_download_downloading_mods">Downloading mods (%.2f MB / %.2f MB)</string>
|
<string name="modpack_download_downloading_mods">Downloading mods (%.2f MB / %.2f MB)</string>
|
||||||
|
<string name="modpack_download_getting_links">Downloading mod links (%d/%d)</string>
|
||||||
|
<string name="modpack_download_downloading_mods_fc">Downloading mods (File %d out of %d)</string>
|
||||||
<string name="modpack_download_applying_overrides">Applying overrides (%d/%d)</string>
|
<string name="modpack_download_applying_overrides">Applying overrides (%d/%d)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user