Added Unzip functionality - we should soon be ready for mod management from within the game!

This commit is contained in:
Yair Morgenstern 2020-08-25 16:38:55 +03:00
parent 16356f9d36
commit a253a97940
8 changed files with 702 additions and 623 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 869 KiB

After

Width:  |  Height:  |  Size: 871 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 KiB

After

Width:  |  Height:  |  Size: 482 KiB

View file

@ -70,46 +70,47 @@ class MainMenuScreen: CameraStageBaseScreen() {
}
}
val table = Table().apply { defaults().pad(10f) }
val column1 = Table().apply { defaults().pad(10f) }
val column2 = Table().apply { defaults().pad(10f) }
val autosaveGame = GameSaver.getSave(autosave, false)
if (autosaveGame.exists()) {
val resumeTable = getTableBlock("Resume","OtherIcons/Resume") { autoLoadGame() }
table.add(resumeTable).row()
column1.add(resumeTable).row()
}
val quickstartTable = getTableBlock("Quickstart", "OtherIcons/Quickstart") { quickstartNewGame() }
table.add(quickstartTable).row()
column1.add(quickstartTable).row()
val newGameButton = getTableBlock("Start new game", "OtherIcons/New") {
game.setScreen(NewGameScreen(this))
dispose()
}
table.add(newGameButton).row()
column1.add(newGameButton).row()
if (GameSaver.getSaves(false).any()) {
val loadGameTable = getTableBlock("Load game", "OtherIcons/Load")
{ game.setScreen(LoadGameScreen(this)) }
table.add(loadGameTable).row()
column1.add(loadGameTable).row()
}
val multiplayerTable = getTableBlock("Multiplayer", "OtherIcons/Multiplayer")
{ game.setScreen(MultiplayerScreen(this)) }
table.add(multiplayerTable).row()
column2.add(multiplayerTable).row()
val mapEditorScreenTable = getTableBlock("Map editor", "OtherIcons/MapEditor")
{ if(stage.actors.none { it is MapEditorMainScreenPopup }) MapEditorMainScreenPopup(this) }
table.add(mapEditorScreenTable).padBottom(0f)
{ if(stage.actors.none { it is MapEditorMainScreenPopup }) MapEditorMainScreenPopup(this) }
column2.add(mapEditorScreenTable).row()
// set the same width for all buttons
table.cells.first().padTop(0f)
table.pack()
table.children.filterIsInstance<Table>().forEach {
it.align(Align.left)
it.moveBy((it.width - table.width) / 2, 0f)
it.width = table.width
}
// val modsTable = getTableBlock("Mods", "OtherIcons/Mods")
// { if(stage.actors.none { it is MapEditorMainScreenPopup }) MapEditorMainScreenPopup(this) }
// column2.add(modEditorTable).row()
val table=Table().apply { defaults().pad(10f) }
table.add(column1)
table.add(column2)
table.pack()
val scroll = ScrollPane(table)
scroll.setSize(table.width, stage.height * 0.98f)
scroll.center(stage)

View file

@ -1,20 +1,22 @@
package com.unciv.ui.worldscreen.mainmenu
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
import com.unciv.logic.GameInfo
import com.unciv.logic.GameSaver
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.ui.saves.Gzip
import java.io.BufferedReader
import java.io.DataOutputStream
import java.io.InputStream
import java.io.InputStreamReader
import java.io.*
import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.Charset
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
object DropBox {
fun dropboxApi(url:String, data:String="",contentType:String="",dropboxApiArg:String=""): InputStream? {
fun dropboxApi(url: String, data: String = "", contentType: String = "", dropboxApiArg: String = ""): InputStream? {
with(URL(url).openConnection() as HttpURLConnection) {
requestMethod = "POST" // default is GET
@ -45,45 +47,45 @@ object DropBox {
}
}
fun getFolderList(folder:String): ArrayList<FolderListEntry> {
fun getFolderList(folder: String): ArrayList<FolderListEntry> {
val folderList = ArrayList<FolderListEntry>()
// The DropBox API returns only partial file listings from one request. list_folder and
// list_folder/continue return similar responses, but list_folder/continue requires a cursor
// instead of the path.
val response = dropboxApi("https://api.dropboxapi.com/2/files/list_folder",
"{\"path\":\"$folder\"}","application/json")
"{\"path\":\"$folder\"}", "application/json")
var currentFolderListChunk = GameSaver.json().fromJson(FolderList::class.java, response)
folderList.addAll(currentFolderListChunk.entries)
while (currentFolderListChunk.has_more) {
val continuationResponse = dropboxApi("https://api.dropboxapi.com/2/files/list_folder/continue",
"{\"cursor\":\"${currentFolderListChunk.cursor}\"}","application/json")
"{\"cursor\":\"${currentFolderListChunk.cursor}\"}", "application/json")
currentFolderListChunk = GameSaver.json().fromJson(FolderList::class.java, continuationResponse)
folderList.addAll(currentFolderListChunk.entries)
}
return folderList
}
fun downloadFile(fileName:String): InputStream {
fun downloadFile(fileName: String): InputStream {
val response = dropboxApi("https://content.dropboxapi.com/2/files/download",
contentType = "text/plain",dropboxApiArg = "{\"path\":\"$fileName\"}")
contentType = "text/plain", dropboxApiArg = "{\"path\":\"$fileName\"}")
return response!!
}
fun downloadFileAsString(fileName:String): String {
fun downloadFileAsString(fileName: String): String {
val inputStream = downloadFile(fileName)
val text = BufferedReader(InputStreamReader(inputStream)).readText()
return text
}
fun uploadFile(fileName: String, data: String, overwrite:Boolean=false){
fun uploadFile(fileName: String, data: String, overwrite: Boolean = false){
val overwriteModeString = if(!overwrite) "" else ""","mode":{".tag":"overwrite"}"""
dropboxApi("https://content.dropboxapi.com/2/files/upload",
data,"application/octet-stream", """{"path":"$fileName"$overwriteModeString}""")
data, "application/octet-stream", """{"path":"$fileName"$overwriteModeString}""")
}
fun deleteFile(fileName:String){
fun deleteFile(fileName: String){
dropboxApi("https://api.dropboxapi.com/2/files/delete_v2",
"{\"path\":\"$fileName\"}","application/json")
"{\"path\":\"$fileName\"}", "application/json")
}
//
// fun createTemplate(): String {
@ -108,11 +110,11 @@ object DropBox {
}
class OnlineMultiplayer {
fun getGameLocation(gameId:String) = "/MultiplayerGames/$gameId"
fun getGameLocation(gameId: String) = "/MultiplayerGames/$gameId"
fun tryUploadGame(gameInfo: GameInfo){
val zippedGameInfo = Gzip.zip(GameSaver.json().toJson(gameInfo))
DropBox.uploadFile(getGameLocation(gameInfo.gameId),zippedGameInfo,true)
DropBox.uploadFile(getGameLocation(gameInfo.gameId), zippedGameInfo, true)
}
fun tryDownloadGame(gameId: String): GameInfo {
@ -130,3 +132,62 @@ class OnlineMultiplayer {
return GameSaver.currentTurnCivFromString(Gzip.unzip(zippedGameInfo))
}
}
object Zip {
fun downloadAndExtract(dropboxFileLocation:String, folderFileHandle:FileHandle){
val fileFromDropbox = DropBox.downloadFile(dropboxFileLocation)
val tempZipFileHandle = folderFileHandle.child("tempZip.zip")
tempZipFileHandle.write(fileFromDropbox, false)
extractFolder(tempZipFileHandle.path())
}
// I went through a lot of similar answers that didn't work until I got to this gem by NeilMonday
// https://stackoverflow.com/questions/981578/how-to-unzip-files-recursively-in-java
fun extractFolder(zipFile: String) {
println(zipFile)
val BUFFER = 2048
val file = File(zipFile)
val zip = ZipFile(file)
val newPath = zipFile.substring(0, zipFile.length - 4)
File(newPath).mkdir()
val zipFileEntries = zip.entries()
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
val entry = zipFileEntries.nextElement() as ZipEntry
val currentEntry = entry.name
val destFile = File(newPath, currentEntry)
//destFile = new File(newPath, destFile.getName());
val destinationParent = destFile.parentFile
// create the parent directory structure if needed
destinationParent.mkdirs()
if (!entry.isDirectory) {
val inputStream = BufferedInputStream(zip
.getInputStream(entry))
var currentByte: Int
// establish buffer for writing file
val data = ByteArray(BUFFER)
// write the current file to disk
val fos = FileOutputStream(destFile)
val dest = BufferedOutputStream(fos,
BUFFER)
// read and write until last byte is encountered
while (inputStream.read(data, 0, BUFFER).also { currentByte = it } != -1) {
dest.write(data, 0, currentByte)
}
dest.flush()
dest.close()
inputStream.close()
}
if (currentEntry.endsWith(".zip")) {
// found a zip file, try to open
extractFolder(destFile.absolutePath)
}
}
}
}

View file

@ -528,6 +528,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Go back](https://thenounproject.com/search/?q=go%20back&i=1901947) by Salvia Santos for Resume
* [Multiplayer](https://thenounproject.com/search/?q=multiplayer&i=1215652) by Roy Charles
* [Options](https://thenounproject.com/search/?q=options&i=866090) By Thengakola
* [Package](https://thenounproject.com/search/?q=package&i=1886048) by shashank singh
# Sound credits

View file

@ -2,6 +2,7 @@
package com.unciv.testing
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
import com.unciv.UncivGame
import com.unciv.UncivGameParameters
import com.unciv.models.metadata.GameSettings
@ -11,10 +12,12 @@ import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr
import com.unciv.ui.worldscreen.mainmenu.Zip
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.io.File
@RunWith(GdxTestRunner::class)
class BasicTests {
@ -79,4 +82,10 @@ class BasicTests {
val x = "+1 Gold, +2 Production".tr()
print(x)
}
@Test
fun tryUnzip(){
// Zip.extractFolder("""C:\Users\LENOVO\Downloads\Rebuild.rar""")
Zip.downloadAndExtract("/Mods/Reasoures.zip", FileHandle("""C:\Users\LENOVO\Downloads"""))
}
}