mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-31 15:19:29 +07:00
Better mod download and error display (#4396)
* Better mod download and error display * Fix Android Studio Insubordinations
This commit is contained in:
@ -2,6 +2,7 @@ package com.unciv.ui.newgamescreen
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.Ruleset.CheckModLinksResult
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.translations.tr
|
||||
@ -39,21 +40,19 @@ class ModCheckboxTable(val mods:LinkedHashSet<String>, val screen: CameraStageBa
|
||||
mods.remove(oldBaseRuleset)
|
||||
mods.add(mod.name)
|
||||
|
||||
var isCompatibleWithCurrentRuleset = true
|
||||
var complexModLinkCheck = CheckModLinksResult()
|
||||
try {
|
||||
val newRuleset = RulesetCache.getComplexRuleset(mods)
|
||||
newRuleset.modOptions.isBaseRuleset = true // This is so the checkModLinks finds all connections
|
||||
complexModLinkCheck = newRuleset.checkModLinks()
|
||||
isCompatibleWithCurrentRuleset = !complexModLinkCheck.isError()
|
||||
} catch (x: Exception) {
|
||||
} catch (ex: Exception) {
|
||||
// This happens if a building is dependent on a tech not in the base ruleset
|
||||
// because newRuleset.updateBuildingCosts() in getComplexRuleset() throws an error
|
||||
isCompatibleWithCurrentRuleset = false
|
||||
complexModLinkCheck = CheckModLinksResult(Ruleset.CheckModLinksStatus.Error, ex.localizedMessage)
|
||||
}
|
||||
|
||||
if (!isCompatibleWithCurrentRuleset) {
|
||||
ToastPopup("The mod you selected is incompatible with the defined ruleset!\n\n$complexModLinkCheck", screen)
|
||||
if (complexModLinkCheck.isError()) {
|
||||
ToastPopup("{The mod you selected is incompatible with the defined ruleset!}\n\n{$complexModLinkCheck}", screen)
|
||||
checkBox.isChecked = false
|
||||
mods.clear()
|
||||
mods.addAll(previousMods)
|
||||
|
@ -317,13 +317,14 @@ class ModManagementScreen: PickerScreen(disableScroll = true) {
|
||||
val downloadButton = "Download mod from URL".toTextButton()
|
||||
downloadButton.onClick {
|
||||
val popup = Popup(this)
|
||||
popup.addGoodSizedLabel("Please enter the mod repository -or- archive zip url:").row()
|
||||
val textArea = TextArea("https://github.com/...", skin)
|
||||
popup.add(textArea).width(stage.width / 2).row()
|
||||
val actualDownloadButton = "Download".toTextButton()
|
||||
actualDownloadButton.onClick {
|
||||
actualDownloadButton.setText("Downloading...".tr())
|
||||
actualDownloadButton.disable()
|
||||
downloadMod(Github.Repo().apply { html_url = textArea.text; default_branch = "master" }) { popup.close() }
|
||||
downloadMod(Github.Repo().parseUrl(textArea.text)) { popup.close() }
|
||||
}
|
||||
popup.add(actualDownloadButton).row()
|
||||
popup.addCloseButton()
|
||||
@ -354,13 +355,13 @@ class ModManagementScreen: PickerScreen(disableScroll = true) {
|
||||
addModInfoToActionTable(repo)
|
||||
}
|
||||
|
||||
/** Download and install a mod in the background, called from the right-bottom button */
|
||||
/** Download and install a mod in the background, called both from the right-bottom button and the URL entry popup */
|
||||
private fun downloadMod(repo: Github.Repo, postAction: () -> Unit = {}) {
|
||||
thread(name="DownloadMod") { // to avoid ANRs - we've learnt our lesson from previous download-related actions
|
||||
try {
|
||||
val modFolder = Github.downloadAndExtract(repo.html_url, repo.default_branch,
|
||||
Gdx.files.local("mods"))
|
||||
?: return@thread
|
||||
?: throw Exception() // downloadAndExtract returns null for 404 errors and the like -> display something!
|
||||
rewriteModOptions(repo, modFolder)
|
||||
Gdx.app.postRunnable {
|
||||
ToastPopup("Downloaded!", this)
|
||||
|
@ -57,7 +57,7 @@ object Github {
|
||||
defaultBranch: String,
|
||||
folderFileHandle: FileHandle
|
||||
): FileHandle? {
|
||||
// Initiate download - the helper returns null when it fails
|
||||
// Initiate download - the helper returns null when it fails
|
||||
val zipUrl = "$gitRepoUrl/archive/$defaultBranch.zip"
|
||||
val inputStream = download(zipUrl) ?: return null
|
||||
|
||||
@ -247,6 +247,38 @@ object Github {
|
||||
//var stargazers_url = ""
|
||||
//var homepage: String? = null // might use instead of go to repo?
|
||||
//var has_wiki = false // a wiki could mean proper documentation for the mod?
|
||||
|
||||
/**
|
||||
* Initialize `this` with an url, extracting all possible fields from it.
|
||||
*
|
||||
* Allows basic repo url or complete 'zip' url from github's code->download zip menu
|
||||
*
|
||||
* @return `this` to allow chaining
|
||||
*/
|
||||
fun parseUrl(url: String): Repo {
|
||||
// Allow url formats
|
||||
// https://github.com/author/repoName
|
||||
// or
|
||||
// https://github.com/author/repoName/archive/refs/heads/branchName.zip
|
||||
// and extract author, repoName, branchName
|
||||
|
||||
html_url = url
|
||||
default_branch = "master"
|
||||
val matchZip = Regex("""^(.*/(.*)/(.*))/archive/(?:.*/)?([^.]+).zip$""").matchEntire(url)
|
||||
if (matchZip != null && matchZip.groups.size > 3) {
|
||||
html_url = matchZip.groups[1]!!.value
|
||||
owner.login = matchZip.groups[2]!!.value
|
||||
name = matchZip.groups[3]!!.value
|
||||
default_branch = matchZip.groups[4]!!.value
|
||||
} else {
|
||||
val matchRepo = Regex("""^.*/(.*)/(.*)/?$""").matchEntire(url)
|
||||
if (matchRepo != null && matchRepo.groups.size > 2) {
|
||||
owner.login = matchRepo.groups[1]!!.value
|
||||
name = matchRepo.groups[2]!!.value
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
/** Part of [Repo] in Github API response */
|
||||
|
Reference in New Issue
Block a user