Skip to content

Commit

Permalink
Fix[cf]: unable to load CurseForge entries in the modpack menu and un…
Browse files Browse the repository at this point in the history
…able to download modpacks
  • Loading branch information
artdeell committed Dec 16, 2023
1 parent c6a6c54 commit 1002c8a
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package net.kdt.pojavlaunch.modloaders.modpacks.api;

import android.util.Log;

import androidx.annotation.NonNull;

import net.kdt.pojavlaunch.PojavApplication;
Expand All @@ -11,7 +13,6 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
Expand Down Expand Up @@ -39,7 +40,6 @@ public SearchResult searchMod(SearchFilters searchFilters, SearchResult previous
new SearchResult[mModpackApis.length] : commonApiSearchResult.searchResults;

int totalSize = 0;
int totalTotalSize = 0;

Future<?>[] futures = new Future<?>[mModpackApis.length];
for(int i = 0; i < mModpackApis.length; i++) {
Expand Down Expand Up @@ -67,8 +67,7 @@ public SearchResult searchMod(SearchFilters searchFilters, SearchResult previous
SearchResult searchResult = results[i] = (SearchResult) future.get();
if(searchResult != null) hasSuccessful = true;
else continue;
totalSize += searchResult.results.length;
totalTotalSize += searchResult.totalResultCount;
totalSize += searchResult.totalResultCount;
}catch (Exception e) {
cancelAllFutures(futures);
e.printStackTrace();
Expand Down Expand Up @@ -97,13 +96,14 @@ public SearchResult searchMod(SearchFilters searchFilters, SearchResult previous
// Recycle or create new search result
if(commonApiSearchResult == null) commonApiSearchResult = new CommonApiSearchResult();
commonApiSearchResult.searchResults = results;
commonApiSearchResult.totalResultCount = totalTotalSize;
commonApiSearchResult.totalResultCount = totalSize;
commonApiSearchResult.results = concatenatedItems;
return commonApiSearchResult;
}

@Override
public ModDetail getModDetails(ModItem item) {
Log.i("CommonApi", "Invoking getModDetails on item.apiSource="+item.apiSource +" item.title="+item.title);
return getModpackApi(item.apiSource).getModDetails(item);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.kdt.pojavlaunch.modloaders.modpacks.models.SearchResult;
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
import net.kdt.pojavlaunch.utils.FileUtils;
import net.kdt.pojavlaunch.utils.GsonJsonUtils;
import net.kdt.pojavlaunch.utils.ZipUtils;

import java.io.File;
Expand Down Expand Up @@ -125,7 +126,7 @@ public ModDetail getModDetails(ModItem item) {
break;
}

hashes[i] = getSha1FromResponse(modDetail);
hashes[i] = getSha1FromModData(modDetail);
}
return new ModDetail(item, versionNames, mcVersionNames, versionUrls, hashes);
}
Expand All @@ -143,8 +144,7 @@ private int getPaginatedDetails(ArrayList<JsonObject> objectList, int index, Str
params.put("pageSize", CURSEFORGE_PAGINATION_SIZE);

JsonObject response = mApiHandler.get("mods/"+modId+"/files", params, JsonObject.class);
if(response == null) return CURSEFORGE_PAGINATION_ERROR;
JsonArray data = response.getAsJsonArray("data");
JsonArray data = GsonJsonUtils.getJsonArraySafe(response, "data");
if(data == null) return CURSEFORGE_PAGINATION_ERROR;

for(int i = 0; i < data.size(); i++) {
Expand Down Expand Up @@ -238,18 +238,22 @@ private String getDownloadUrl(long projectID, long fileID) {
private @Nullable String getDownloadSha1(long projectID, long fileID) {
// Try the api endpoint, die in the other case
JsonObject response = mApiHandler.get("mods/"+projectID+"/files/"+fileID, JsonObject.class);
if (response == null || response.get("data").isJsonNull()) return null;

return getSha1FromResponse(response);
JsonObject data = GsonJsonUtils.getJsonObjectSafe(response, "data");
if(data == null) return null;
return getSha1FromModData(data);
}

private String getSha1FromResponse(@NonNull JsonElement element) {
JsonArray hashes = element.getAsJsonObject().get("data").getAsJsonObject().getAsJsonArray("hashes");
private String getSha1FromModData(@NonNull JsonObject object) {
JsonArray hashes = GsonJsonUtils.getJsonArraySafe(object, "hashes");
if(hashes == null) return null;
for (JsonElement jsonElement : hashes) {
// The sha1 = 1; md5 = 2;
JsonElement algo = jsonElement.getAsJsonObject().get("algo");
if(algo != null && algo.getAsInt() == ALGO_SHA_1){
return jsonElement.getAsJsonObject().get("value").getAsString();
JsonObject jsonObject = GsonJsonUtils.getJsonObjectSafe(jsonElement);
if(GsonJsonUtils.getIntSafe(
jsonObject,
"algo",
-1) == ALGO_SHA_1) {
return GsonJsonUtils.getStringSafe(jsonObject, "value");
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public static <T> T ensureSha1(File outputFile, @Nullable String sha1, Callable<

int attempts = 0;
T result = null;
while (attempts < 5 && (!outputFile.exists() || Tools.compareSHA1(outputFile, sha1))){
while (attempts < 5 && (!outputFile.exists() || !Tools.compareSHA1(outputFile, sha1))){
attempts++;
try {
result = downloadFunction.call();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package net.kdt.pojavlaunch.utils;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public class GsonJsonUtils {
/**
* Safely converts a JsonElement into a JsonObject.
* @param element the input JsonElement
* @return the JsonObject if:
* the JsonElement is not null
* the JsonElement is not Json null
* the JsonElement is a JsonObjet
* null otherwise
*/
public static JsonObject getJsonObjectSafe(JsonElement element) {
if(element == null) return null;
if(element.isJsonNull() || !element.isJsonObject()) return null;
return element.getAsJsonObject();
}

/**
* Safely gets a JsonElement from a JsonObject
* @param jsonObject the input JsonObject
* @param memberName the member name of the JsonElement
* @return the JsonElement if:
* the input JsonObject is not null
* the input JsonObject contains an element with the specified memberName
* the JsonElement is not Json null
* null otherwise
*/
public static JsonElement getElementSafe(JsonObject jsonObject, String memberName) {
if(jsonObject == null) return null;
if(!jsonObject.has(memberName)) return null;
JsonElement element = jsonObject.get(memberName);
if(element.isJsonNull()) return null;
return element;
}

/**
* Safely gets a JsonObject from a JsonObject
* @param jsonObject the input JsonObject
* @param memberName the member name of the output JsonObject
* @return the output JsonObject if:
* the input JsonObject is not null
* the input JsonObject contains an element with the specified memberName
* the output JsonObject is not Json null
* the output JsonObject is a JsonObjet
* null otherwise
*/
public static JsonObject getJsonObjectSafe(JsonObject jsonObject, String memberName) {
return getJsonObjectSafe(getElementSafe(jsonObject, memberName));
}

/**
* Safely gets a JsonArray from a JsonObject
* @param jsonObject the input JsonObject
* @param memberName the member name of the JsonArray
* @return the JsonArray if:
* the input JsonObject is not null
* the input JsonObject contains an element with the specified memberName
* the JsonArray is not Json null
* the JsonArray is a JsonArray
* null otherwise
*/
public static JsonArray getJsonArraySafe(JsonObject jsonObject, String memberName) {
JsonElement jsonElement = getElementSafe(jsonObject, memberName);
if(jsonElement == null || !jsonElement.isJsonArray()) return null;
return jsonElement.getAsJsonArray();
}

/**
* Safely gets an int from a JsonObject
* @param jsonObject the input JsonObject
* @param memberName the member name of the int
* @param onNullValue the value that will be returned if any of the checks fail
* @return the int if:
* the input JsonObject is not null
* the input JsonObject contains an element with the specified memberName
* the int is not Json null
* the int is an actual integer
* onNullValue otherwise
*/
public static int getIntSafe(JsonObject jsonObject, String memberName, int onNullValue) {
JsonElement jsonElement = getElementSafe(jsonObject, memberName);
if(jsonElement == null || !jsonElement.isJsonPrimitive()) return onNullValue;
try {
return jsonElement.getAsInt();
}catch (ClassCastException e) {
return onNullValue;
}
}

/**
* Safely gets a String from a JsonObject
* @param jsonObject the input JsonObject
* @param memberName the member name of the int
* @return the String if:
* the input JsonObject is not null
* the input JsonObject contains an element with the specified memberName
* the String is not a Json null
* the String is an actual String
* null otherwise
*/
public static String getStringSafe(JsonObject jsonObject, String memberName) {
JsonElement jsonElement = getElementSafe(jsonObject, memberName);
if(jsonElement == null || !jsonElement.isJsonPrimitive()) return null;
try {
return jsonElement.getAsString();
}catch (ClassCastException e) {
return null;
}
}
}

0 comments on commit 1002c8a

Please sign in to comment.