mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-30 15:30:43 -04:00
Mod management screen takes its list of mods from the Github API!
This commit is contained in:
parent
0074ebfdb5
commit
36f5d22a80
@ -4,19 +4,18 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.TextArea
|
import com.badlogic.gdx.scenes.scene2d.ui.TextArea
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener
|
|
||||||
import com.unciv.MainMenuScreen
|
import com.unciv.MainMenuScreen
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.utils.*
|
import com.unciv.ui.utils.*
|
||||||
import com.unciv.ui.worldscreen.mainmenu.Zip
|
import com.unciv.ui.worldscreen.mainmenu.Github
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class ModManagementScreen: PickerScreen() {
|
class ModManagementScreen: PickerScreen() {
|
||||||
|
|
||||||
val modTable = Table().apply { defaults().pad(10f) }
|
val modTable = Table().apply { defaults().pad(10f) }
|
||||||
val downloadTable = Table()
|
val downloadTable = Table().apply { defaults().pad(10f) }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setDefaultCloseAction(MainMenuScreen())
|
setDefaultCloseAction(MainMenuScreen())
|
||||||
@ -24,8 +23,32 @@ class ModManagementScreen: PickerScreen() {
|
|||||||
|
|
||||||
topTable.add(modTable).pad(10f)
|
topTable.add(modTable).pad(10f)
|
||||||
|
|
||||||
|
downloadTable.add(getDownloadButton()).row()
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val repoList: ArrayList<Github.Repo>
|
||||||
|
try {
|
||||||
|
repoList = Github.tryGetGithubReposWithTopic()
|
||||||
|
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ResponsePopup("Could not download mod list", this)
|
||||||
|
return@thread
|
||||||
|
}
|
||||||
|
|
||||||
|
for (repo in repoList) {
|
||||||
|
repo.name = repo.name.replace('-',' ')
|
||||||
|
val downloadButton = repo.name.toTextButton()
|
||||||
|
downloadButton.onClick {
|
||||||
|
descriptionLabel.setText(repo.description + "\n" + "[${repo.stargazers_count}] Stars".tr())
|
||||||
|
removeRightSideClickListeners()
|
||||||
|
rightSideButton.enable()
|
||||||
|
rightSideButton.setText("Download [${repo.name}]".tr())
|
||||||
|
rightSideButton.onClick { downloadMod(repo.svn_url) }
|
||||||
|
}
|
||||||
|
downloadTable.add(downloadButton).row()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
downloadTable.add(getDownloadButton())
|
|
||||||
topTable.add(downloadTable)
|
topTable.add(downloadTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,24 +60,9 @@ class ModManagementScreen: PickerScreen() {
|
|||||||
popup.add(textArea).width(stage.width/2).row()
|
popup.add(textArea).width(stage.width/2).row()
|
||||||
val downloadButton = "Download".toTextButton()
|
val downloadButton = "Download".toTextButton()
|
||||||
downloadButton.onClick {
|
downloadButton.onClick {
|
||||||
thread { // to avoid ANRs - we've learnt our lesson from previous download-related actions
|
downloadButton.setText("Downloading...")
|
||||||
try {
|
downloadButton.disable()
|
||||||
downloadButton.setText("Downloading...")
|
downloadMod(textArea.text) { popup.close() }
|
||||||
downloadButton.disable()
|
|
||||||
Zip.downloadAndExtract(textArea.text+"/archive/master.zip",
|
|
||||||
Gdx.files.local("mods"))
|
|
||||||
Gdx.app.postRunnable {
|
|
||||||
RulesetCache.loadRulesets()
|
|
||||||
refresh()
|
|
||||||
popup.close()
|
|
||||||
}
|
|
||||||
} catch (ex:Exception){
|
|
||||||
Gdx.app.postRunnable {
|
|
||||||
ResponsePopup("Could not download mod", this)
|
|
||||||
popup.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
popup.add(downloadButton).row()
|
popup.add(downloadButton).row()
|
||||||
popup.addCloseButton()
|
popup.addCloseButton()
|
||||||
@ -63,6 +71,27 @@ class ModManagementScreen: PickerScreen() {
|
|||||||
return downloadButton
|
return downloadButton
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun downloadMod(gitRepoUrl:String, postAction:()->Unit={}){
|
||||||
|
thread { // to avoid ANRs - we've learnt our lesson from previous download-related actions
|
||||||
|
try {
|
||||||
|
Github.downloadAndExtract(gitRepoUrl+"/archive/master.zip",
|
||||||
|
Gdx.files.local("mods"))
|
||||||
|
Gdx.app.postRunnable {
|
||||||
|
ResponsePopup("Downloaded!", this)
|
||||||
|
RulesetCache.loadRulesets()
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
} catch (ex:Exception){
|
||||||
|
Gdx.app.postRunnable {
|
||||||
|
ResponsePopup("Could not download mod", this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
postAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun refresh(){
|
fun refresh(){
|
||||||
modTable.clear()
|
modTable.clear()
|
||||||
val currentMods = RulesetCache.values.filter { it.name != "" }
|
val currentMods = RulesetCache.values.filter { it.name != "" }
|
||||||
@ -71,8 +100,7 @@ class ModManagementScreen: PickerScreen() {
|
|||||||
rightSideButton.setText("Delete [${mod.name}]".tr())
|
rightSideButton.setText("Delete [${mod.name}]".tr())
|
||||||
rightSideButton.enable()
|
rightSideButton.enable()
|
||||||
descriptionLabel.setText(mod.getSummary())
|
descriptionLabel.setText(mod.getSummary())
|
||||||
rightSideButton.listeners.filter { it != rightSideButton.clickListener }
|
removeRightSideClickListeners()
|
||||||
.forEach { rightSideButton.removeListener(it) }
|
|
||||||
rightSideButton.onClick {
|
rightSideButton.onClick {
|
||||||
YesNoPopup("Are you SURE you want to delete this mod?",
|
YesNoPopup("Are you SURE you want to delete this mod?",
|
||||||
{ deleteMod(mod) }, this).open()
|
{ deleteMod(mod) }, this).open()
|
||||||
|
@ -62,4 +62,9 @@ open class PickerScreen : CameraStageBaseScreen() {
|
|||||||
if(UncivGame.Current.worldScreen.isPlayersTurn) rightSideButton.enable()
|
if(UncivGame.Current.worldScreen.isPlayersTurn) rightSideButton.enable()
|
||||||
rightSideButton.setText(rightButtonText)
|
rightSideButton.setText(rightButtonText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeRightSideClickListeners(){
|
||||||
|
rightSideButton.listeners.filter { it != rightSideButton.clickListener }
|
||||||
|
.forEach { rightSideButton.removeListener(it) }
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.files.FileHandle
|
|||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.GameSaver
|
import com.unciv.logic.GameSaver
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
|
import com.unciv.models.metadata.GameSettings
|
||||||
import com.unciv.ui.saves.Gzip
|
import com.unciv.ui.saves.Gzip
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
@ -132,11 +133,12 @@ class OnlineMultiplayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Github {
|
||||||
object Zip {
|
// Consider merging this with the Dropbox function
|
||||||
fun downloadUrl(url:String): InputStream? {
|
fun download(url: String, action: (HttpURLConnection) -> Unit = {}): InputStream? {
|
||||||
with(URL(url).openConnection() as HttpURLConnection) {
|
with(URL(url).openConnection() as HttpURLConnection)
|
||||||
// requestMethod = "POST" // default is GET
|
{
|
||||||
|
action(this)
|
||||||
|
|
||||||
doOutput = true
|
doOutput = true
|
||||||
|
|
||||||
@ -153,17 +155,17 @@ object Zip {
|
|||||||
|
|
||||||
// This took a long time to get just right, so if you're changing this, TEST IT THOROUGHLY on both Desktop and Phone
|
// This took a long time to get just right, so if you're changing this, TEST IT THOROUGHLY on both Desktop and Phone
|
||||||
fun downloadAndExtract(url:String, folderFileHandle:FileHandle) {
|
fun downloadAndExtract(url:String, folderFileHandle:FileHandle) {
|
||||||
val inputStream = downloadUrl(url)
|
val inputStream = download(url)
|
||||||
if (inputStream == null) return
|
if (inputStream == null) return
|
||||||
//DropBox.downloadFile(dropboxFileLocation)
|
|
||||||
|
|
||||||
val tempZipFileHandle = folderFileHandle.child("tempZip.zip")
|
val tempZipFileHandle = folderFileHandle.child("tempZip.zip")
|
||||||
tempZipFileHandle.write(inputStream, false)
|
tempZipFileHandle.write(inputStream, false)
|
||||||
val unzipDestination = tempZipFileHandle.sibling("tempZip") // folder, not file
|
val unzipDestination = tempZipFileHandle.sibling("tempZip") // folder, not file
|
||||||
extractFolder(tempZipFileHandle, unzipDestination)
|
Zip.extractFolder(tempZipFileHandle, unzipDestination)
|
||||||
val innerFolder = unzipDestination.list().first() // tempZip/<repoName>-master/
|
val innerFolder = unzipDestination.list().first() // tempZip/<repoName>-master/
|
||||||
|
|
||||||
val finalDestination = folderFileHandle.child(innerFolder.name().replace("-master",""))
|
val finalDestinationName = innerFolder.name().replace("-master","").replace('-',' ')
|
||||||
|
val finalDestination = folderFileHandle.child(finalDestinationName)
|
||||||
finalDestination.mkdirs() // If we don't create this as a directory, it will think this is a file and nothing will work.
|
finalDestination.mkdirs() // If we don't create this as a directory, it will think this is a file and nothing will work.
|
||||||
for(innerFileOrFolder in innerFolder.list()){
|
for(innerFileOrFolder in innerFolder.list()){
|
||||||
innerFileOrFolder.moveTo(finalDestination)
|
innerFileOrFolder.moveTo(finalDestination)
|
||||||
@ -173,6 +175,27 @@ object Zip {
|
|||||||
unzipDestination.deleteDirectory()
|
unzipDestination.deleteDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun tryGetGithubReposWithTopic(): ArrayList<Repo> {
|
||||||
|
val inputStream = download("https://api.github.com/search/repositories?q=topic:unciv-mod")
|
||||||
|
if (inputStream == null) return ArrayList()
|
||||||
|
return GameSaver.json().fromJson(RepoSearch::class.java, inputStream!!.bufferedReader().readText()).items
|
||||||
|
}
|
||||||
|
|
||||||
|
class RepoSearch{
|
||||||
|
var items=ArrayList<Repo>()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Repo {
|
||||||
|
var name = ""
|
||||||
|
var description = ""
|
||||||
|
var svn_url = ""
|
||||||
|
var stargazers_count = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Zip {
|
||||||
|
|
||||||
// I went through a lot of similar answers that didn't work until I got to this gem by NeilMonday
|
// I went through a lot of similar answers that didn't work until I got to this gem by NeilMonday
|
||||||
// (with mild changes to fit the FileHandles)
|
// (with mild changes to fit the FileHandles)
|
||||||
// https://stackoverflow.com/questions/981578/how-to-unzip-files-recursively-in-java
|
// https://stackoverflow.com/questions/981578/how-to-unzip-files-recursively-in-java
|
||||||
|
@ -12,6 +12,7 @@ import com.unciv.models.ruleset.unit.BaseUnit
|
|||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
|
import com.unciv.ui.worldscreen.mainmenu.Http
|
||||||
import com.unciv.ui.worldscreen.mainmenu.Zip
|
import com.unciv.ui.worldscreen.mainmenu.Zip
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -89,4 +90,9 @@ class BasicTests {
|
|||||||
// Zip.downloadAndExtract("/Mods/Reasoures.zip", FileHandle("""C:\Users\LENOVO\Downloads"""))
|
// Zip.downloadAndExtract("/Mods/Reasoures.zip", FileHandle("""C:\Users\LENOVO\Downloads"""))
|
||||||
// Zip.downloadAndExtract("https://github.com/yairm210/Unciv-IV-mod/archive/master.zip", FileHandle("""C:\Users\LENOVO\Downloads"""))
|
// Zip.downloadAndExtract("https://github.com/yairm210/Unciv-IV-mod/archive/master.zip", FileHandle("""C:\Users\LENOVO\Downloads"""))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@Test // This should NOT run as part of the test suite!
|
||||||
|
fun tryGetGithubTopicInfo(){
|
||||||
|
println(Http.tryGetGithubTopic())
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user