mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-29 15:01:09 -04:00
Added Unzip functionality - we should soon be ready for mod management from within the game!
This commit is contained in:
parent
16356f9d36
commit
a253a97940
BIN
android/Images/OtherIcons/Mods.png
Normal file
BIN
android/Images/OtherIcons/Mods.png
Normal file
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 |
@ -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)
|
val autosaveGame = GameSaver.getSave(autosave, false)
|
||||||
if (autosaveGame.exists()) {
|
if (autosaveGame.exists()) {
|
||||||
val resumeTable = getTableBlock("Resume","OtherIcons/Resume") { autoLoadGame() }
|
val resumeTable = getTableBlock("Resume","OtherIcons/Resume") { autoLoadGame() }
|
||||||
table.add(resumeTable).row()
|
column1.add(resumeTable).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
val quickstartTable = getTableBlock("Quickstart", "OtherIcons/Quickstart") { quickstartNewGame() }
|
val quickstartTable = getTableBlock("Quickstart", "OtherIcons/Quickstart") { quickstartNewGame() }
|
||||||
table.add(quickstartTable).row()
|
column1.add(quickstartTable).row()
|
||||||
|
|
||||||
val newGameButton = getTableBlock("Start new game", "OtherIcons/New") {
|
val newGameButton = getTableBlock("Start new game", "OtherIcons/New") {
|
||||||
game.setScreen(NewGameScreen(this))
|
game.setScreen(NewGameScreen(this))
|
||||||
dispose()
|
dispose()
|
||||||
}
|
}
|
||||||
table.add(newGameButton).row()
|
column1.add(newGameButton).row()
|
||||||
|
|
||||||
if (GameSaver.getSaves(false).any()) {
|
if (GameSaver.getSaves(false).any()) {
|
||||||
val loadGameTable = getTableBlock("Load game", "OtherIcons/Load")
|
val loadGameTable = getTableBlock("Load game", "OtherIcons/Load")
|
||||||
{ game.setScreen(LoadGameScreen(this)) }
|
{ game.setScreen(LoadGameScreen(this)) }
|
||||||
table.add(loadGameTable).row()
|
column1.add(loadGameTable).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
val multiplayerTable = getTableBlock("Multiplayer", "OtherIcons/Multiplayer")
|
val multiplayerTable = getTableBlock("Multiplayer", "OtherIcons/Multiplayer")
|
||||||
{ game.setScreen(MultiplayerScreen(this)) }
|
{ game.setScreen(MultiplayerScreen(this)) }
|
||||||
table.add(multiplayerTable).row()
|
column2.add(multiplayerTable).row()
|
||||||
|
|
||||||
val mapEditorScreenTable = getTableBlock("Map editor", "OtherIcons/MapEditor")
|
val mapEditorScreenTable = getTableBlock("Map editor", "OtherIcons/MapEditor")
|
||||||
{ if(stage.actors.none { it is MapEditorMainScreenPopup }) MapEditorMainScreenPopup(this) }
|
{ if(stage.actors.none { it is MapEditorMainScreenPopup }) MapEditorMainScreenPopup(this) }
|
||||||
table.add(mapEditorScreenTable).padBottom(0f)
|
column2.add(mapEditorScreenTable).row()
|
||||||
|
|
||||||
// set the same width for all buttons
|
// val modsTable = getTableBlock("Mods", "OtherIcons/Mods")
|
||||||
table.cells.first().padTop(0f)
|
// { if(stage.actors.none { it is MapEditorMainScreenPopup }) MapEditorMainScreenPopup(this) }
|
||||||
table.pack()
|
// column2.add(modEditorTable).row()
|
||||||
table.children.filterIsInstance<Table>().forEach {
|
|
||||||
it.align(Align.left)
|
|
||||||
it.moveBy((it.width - table.width) / 2, 0f)
|
|
||||||
it.width = table.width
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
val table=Table().apply { defaults().pad(10f) }
|
||||||
|
table.add(column1)
|
||||||
|
table.add(column2)
|
||||||
table.pack()
|
table.pack()
|
||||||
|
|
||||||
val scroll = ScrollPane(table)
|
val scroll = ScrollPane(table)
|
||||||
scroll.setSize(table.width, stage.height * 0.98f)
|
scroll.setSize(table.width, stage.height * 0.98f)
|
||||||
scroll.center(stage)
|
scroll.center(stage)
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
package com.unciv.ui.worldscreen.mainmenu
|
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.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.ui.saves.Gzip
|
import com.unciv.ui.saves.Gzip
|
||||||
import java.io.BufferedReader
|
import java.io.*
|
||||||
import java.io.DataOutputStream
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.InputStreamReader
|
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipFile
|
||||||
|
|
||||||
|
|
||||||
object DropBox {
|
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) {
|
with(URL(url).openConnection() as HttpURLConnection) {
|
||||||
requestMethod = "POST" // default is GET
|
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>()
|
val folderList = ArrayList<FolderListEntry>()
|
||||||
// The DropBox API returns only partial file listings from one request. list_folder and
|
// 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
|
// list_folder/continue return similar responses, but list_folder/continue requires a cursor
|
||||||
// instead of the path.
|
// instead of the path.
|
||||||
val response = dropboxApi("https://api.dropboxapi.com/2/files/list_folder",
|
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)
|
var currentFolderListChunk = GameSaver.json().fromJson(FolderList::class.java, response)
|
||||||
folderList.addAll(currentFolderListChunk.entries)
|
folderList.addAll(currentFolderListChunk.entries)
|
||||||
while (currentFolderListChunk.has_more) {
|
while (currentFolderListChunk.has_more) {
|
||||||
val continuationResponse = dropboxApi("https://api.dropboxapi.com/2/files/list_folder/continue",
|
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)
|
currentFolderListChunk = GameSaver.json().fromJson(FolderList::class.java, continuationResponse)
|
||||||
folderList.addAll(currentFolderListChunk.entries)
|
folderList.addAll(currentFolderListChunk.entries)
|
||||||
}
|
}
|
||||||
return folderList
|
return folderList
|
||||||
}
|
}
|
||||||
|
|
||||||
fun downloadFile(fileName:String): InputStream {
|
fun downloadFile(fileName: String): InputStream {
|
||||||
val response = dropboxApi("https://content.dropboxapi.com/2/files/download",
|
val response = dropboxApi("https://content.dropboxapi.com/2/files/download",
|
||||||
contentType = "text/plain",dropboxApiArg = "{\"path\":\"$fileName\"}")
|
contentType = "text/plain", dropboxApiArg = "{\"path\":\"$fileName\"}")
|
||||||
return response!!
|
return response!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun downloadFileAsString(fileName:String): String {
|
fun downloadFileAsString(fileName: String): String {
|
||||||
val inputStream = downloadFile(fileName)
|
val inputStream = downloadFile(fileName)
|
||||||
val text = BufferedReader(InputStreamReader(inputStream)).readText()
|
val text = BufferedReader(InputStreamReader(inputStream)).readText()
|
||||||
return text
|
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"}"""
|
val overwriteModeString = if(!overwrite) "" else ""","mode":{".tag":"overwrite"}"""
|
||||||
dropboxApi("https://content.dropboxapi.com/2/files/upload",
|
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",
|
dropboxApi("https://api.dropboxapi.com/2/files/delete_v2",
|
||||||
"{\"path\":\"$fileName\"}","application/json")
|
"{\"path\":\"$fileName\"}", "application/json")
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// fun createTemplate(): String {
|
// fun createTemplate(): String {
|
||||||
@ -108,11 +110,11 @@ object DropBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OnlineMultiplayer {
|
class OnlineMultiplayer {
|
||||||
fun getGameLocation(gameId:String) = "/MultiplayerGames/$gameId"
|
fun getGameLocation(gameId: String) = "/MultiplayerGames/$gameId"
|
||||||
|
|
||||||
fun tryUploadGame(gameInfo: GameInfo){
|
fun tryUploadGame(gameInfo: GameInfo){
|
||||||
val zippedGameInfo = Gzip.zip(GameSaver.json().toJson(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 {
|
fun tryDownloadGame(gameId: String): GameInfo {
|
||||||
@ -130,3 +132,62 @@ class OnlineMultiplayer {
|
|||||||
return GameSaver.currentTurnCivFromString(Gzip.unzip(zippedGameInfo))
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
* [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
|
* [Multiplayer](https://thenounproject.com/search/?q=multiplayer&i=1215652) by Roy Charles
|
||||||
* [Options](https://thenounproject.com/search/?q=options&i=866090) By Thengakola
|
* [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
|
# Sound credits
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
package com.unciv.testing
|
package com.unciv.testing
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.UncivGameParameters
|
import com.unciv.UncivGameParameters
|
||||||
import com.unciv.models.metadata.GameSettings
|
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.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.Zip
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
@RunWith(GdxTestRunner::class)
|
@RunWith(GdxTestRunner::class)
|
||||||
class BasicTests {
|
class BasicTests {
|
||||||
@ -79,4 +82,10 @@ class BasicTests {
|
|||||||
val x = "+1 Gold, +2 Production".tr()
|
val x = "+1 Gold, +2 Production".tr()
|
||||||
print(x)
|
print(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun tryUnzip(){
|
||||||
|
// Zip.extractFolder("""C:\Users\LENOVO\Downloads\Rebuild.rar""")
|
||||||
|
Zip.downloadAndExtract("/Mods/Reasoures.zip", FileHandle("""C:\Users\LENOVO\Downloads"""))
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user