diff --git a/core/src/com/unciv/logic/GameSaver.kt b/core/src/com/unciv/logic/GameSaver.kt index 0b815f3b39..7915b3b447 100644 --- a/core/src/com/unciv/logic/GameSaver.kt +++ b/core/src/com/unciv/logic/GameSaver.kt @@ -4,28 +4,14 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.utils.Json import com.unciv.GameSettings -import com.unciv.logic.map.TileMap -import com.unciv.ui.saves.Gzip import com.unciv.ui.utils.ImageGetter import java.io.File class GameSaver { private val saveFilesFolder = "SaveFiles" - private val mapsFolder = "maps" fun json() = Json().apply { setIgnoreDeprecated(true); ignoreUnknownFields = true } // Json() is NOT THREAD SAFE so we need to create a new one for each function - fun getMap(mapName:String) = Gdx.files.local("$mapsFolder/$mapName") - fun saveMap(mapName: String,tileMap: TileMap){ - getMap(mapName).writeString(Gzip.zip(json().toJson(tileMap)), false) - } - fun loadMap(mapName: String): TileMap { - val gzippedString = getMap(mapName).readString() - val unzippedJson = Gzip.unzip(gzippedString) - return json().fromJson(TileMap::class.java, unzippedJson) - } - fun getMaps() = Gdx.files.local(mapsFolder).list().map { it.name() } - fun getSave(GameName: String): FileHandle { return Gdx.files.local("$saveFilesFolder/$GameName") @@ -88,3 +74,4 @@ class GameSaver { } } + diff --git a/core/src/com/unciv/logic/MapSaver.kt b/core/src/com/unciv/logic/MapSaver.kt new file mode 100644 index 0000000000..925709129f --- /dev/null +++ b/core/src/com/unciv/logic/MapSaver.kt @@ -0,0 +1,25 @@ +package com.unciv.logic + +import com.badlogic.gdx.Gdx +import com.unciv.logic.map.TileMap +import com.unciv.ui.saves.Gzip + +class MapSaver(){ + fun json() = GameSaver().json() + private val mapsFolder = "maps" + + fun getMap(mapName:String) = Gdx.files.local("$mapsFolder/$mapName") + fun saveMap(mapName: String,tileMap: TileMap){ + getMap(mapName).writeString(Gzip.zip(json().toJson(tileMap)), false) + } + fun loadMap(mapName: String): TileMap { + val gzippedString = getMap(mapName).readString() + val unzippedJson = Gzip.unzip(gzippedString) + return json().fromJson(TileMap::class.java, unzippedJson) + } + + fun getMaps() = Gdx.files.local(mapsFolder).list().map { it.name() } + + fun mapFromJson(json:String): TileMap = json().fromJson(TileMap::class.java, json) + +} \ No newline at end of file diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index c899655a8a..c1b707cb4b 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -3,8 +3,8 @@ package com.unciv.logic.map import com.badlogic.gdx.math.Vector2 import com.unciv.GameParameters import com.unciv.logic.GameInfo -import com.unciv.logic.GameSaver import com.unciv.logic.HexMath +import com.unciv.logic.MapSaver import com.unciv.logic.civilization.CivilizationInfo import com.unciv.models.gamebasics.GameBasics @@ -36,7 +36,7 @@ class TileMap { val mapValues:Collection if(newGameParameters.mapType == MapType.File) - mapValues = GameSaver().loadMap(newGameParameters.mapFileName!!).values + mapValues = MapSaver().loadMap(newGameParameters.mapFileName!!).values else if(newGameParameters.mapType==MapType.Perlin) mapValues = PerlinNoiseRandomMapGenerator().generateMap(newGameParameters.mapRadius).values else diff --git a/core/src/com/unciv/ui/NewGameScreen.kt b/core/src/com/unciv/ui/NewGameScreen.kt index 4ea47eb904..60f5f30fcf 100644 --- a/core/src/com/unciv/ui/NewGameScreen.kt +++ b/core/src/com/unciv/ui/NewGameScreen.kt @@ -9,7 +9,7 @@ import com.unciv.GameSpeed import com.unciv.GameStarter import com.unciv.UnCivGame import com.unciv.logic.GameInfo -import com.unciv.logic.GameSaver +import com.unciv.logic.MapSaver import com.unciv.logic.map.MapType import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.VictoryType @@ -121,7 +121,7 @@ class NewGameScreen: PickerScreen(){ newGameOptionsTable.add("{Map type}:".tr()) val mapTypes = LinkedHashMap() for (type in MapType.values()) { - if (type == MapType.File && GameSaver().getMaps().isEmpty()) continue + if (type == MapType.File && MapSaver().getMaps().isEmpty()) continue mapTypes[type.toString()] = type } @@ -273,7 +273,7 @@ class NewGameScreen: PickerScreen(){ private fun getMapFileSelectBox(): SelectBox { val mapFileSelectBox = SelectBox(skin) val mapNames = Array() - for (mapName in GameSaver().getMaps()) mapNames.add(mapName) + for (mapName in MapSaver().getMaps()) mapNames.add(mapName) mapFileSelectBox.items = mapNames mapFileSelectBox.addListener(object : ChangeListener() { diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt b/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt index 601a3cecca..3941d80bde 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt @@ -6,11 +6,12 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextField import com.badlogic.gdx.utils.Json import com.unciv.Constants import com.unciv.UnCivGame -import com.unciv.logic.GameSaver +import com.unciv.logic.MapSaver import com.unciv.logic.map.RoadStatus import com.unciv.models.gamebasics.tr import com.unciv.ui.saves.Gzip import com.unciv.ui.utils.onClick +import com.unciv.ui.worldscreen.optionstable.DropBox import com.unciv.ui.worldscreen.optionstable.PopupTable class MapEditorOptionsTable(mapEditorScreen: MapEditorScreen): PopupTable(mapEditorScreen){ @@ -39,7 +40,7 @@ class MapEditorOptionsTable(mapEditorScreen: MapEditorScreen): PopupTable(mapEdi val saveMapButton = TextButton("Save".tr(), skin) saveMapButton.onClick { - GameSaver().saveMap(mapEditorScreen.mapName,mapEditorScreen.tileMap) + MapSaver().saveMap(mapEditorScreen.mapName,mapEditorScreen.tileMap) UnCivGame.Current.setWorldScreen() } add(saveMapButton).row() @@ -56,6 +57,17 @@ class MapEditorOptionsTable(mapEditorScreen: MapEditorScreen): PopupTable(mapEdi loadMapButton.onClick { MapScreenLoadTable(mapEditorScreen); remove() } add(loadMapButton).row() + val uploadMapButton = TextButton("Upload".tr(), skin) + uploadMapButton.onClick { + val gzippedMap = Gzip.zip(Json().toJson(mapEditorScreen.tileMap)) + DropBox().uploadFile("/Maps/"+mapEditorScreen.mapName,gzippedMap) + } + add(uploadMapButton).row() + + val downloadMapButton = TextButton("Download".tr(), skin) + downloadMapButton.onClick { MapDownloadTable(mapEditorScreen); remove() } + add(downloadMapButton).row() + val exitMapEditorButton = TextButton("Exit map editor".tr(), skin) exitMapEditorButton.onClick { UnCivGame.Current.setWorldScreen(); mapEditorScreen.dispose() } add(exitMapEditorButton ).row() @@ -64,6 +76,29 @@ class MapEditorOptionsTable(mapEditorScreen: MapEditorScreen): PopupTable(mapEdi closeOptionsButtton.onClick { remove() } add(closeOptionsButtton).row() + open() + } +} + +class MapDownloadTable(mapEditorScreen: MapEditorScreen):PopupTable(mapEditorScreen){ + init{ + val folderList: DropBox.FolderList + try{ + folderList = DropBox().getFolderList("/Maps") + for(downloadableMap in folderList.entries){ + addButton(downloadableMap.name){ + val mapJsonGzipped = DropBox().downloadFile(downloadableMap.path_display) + val decodedMapJson = Gzip.unzip(mapJsonGzipped) + val mapObject = MapSaver().mapFromJson(decodedMapJson) + MapSaver().saveMap(downloadableMap.name, mapObject) + UnCivGame.Current.screen = MapEditorScreen(mapObject) + } + } + } + catch (ex:Exception){ + addGoodSizedLabel("Could not get list of maps!") + } + addButton("Close"){remove()} open() } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt index 4f448282c1..b9f5ffb0b3 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt @@ -3,13 +3,14 @@ package com.unciv.ui.mapeditor import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.unciv.GameParameters -import com.unciv.logic.GameSaver +import com.unciv.logic.MapSaver import com.unciv.logic.map.TileMap import com.unciv.models.gamebasics.tr import com.unciv.ui.tilegroups.TileGroup import com.unciv.ui.tilegroups.TileSetStrings import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.onClick +import com.unciv.ui.utils.setFontSize import com.unciv.ui.worldscreen.TileGroupMap class MapEditorScreen(): CameraStageBaseScreen(){ @@ -22,13 +23,13 @@ class MapEditorScreen(): CameraStageBaseScreen(){ constructor(mapNameToLoad:String?):this(){ var mapToLoad = mapNameToLoad if (mapToLoad == null) { - val existingSaves = GameSaver().getMaps() + val existingSaves = MapSaver().getMaps() if(existingSaves.isNotEmpty()) mapToLoad = existingSaves.first() } if(mapToLoad!=null){ mapName=mapToLoad - tileMap=GameSaver().loadMap(mapName) + tileMap= MapSaver().loadMap(mapName) } initialize() } @@ -38,7 +39,7 @@ class MapEditorScreen(): CameraStageBaseScreen(){ initialize() } - fun initialize(){ + fun initialize() { tileMap.setTransients() val mapHolder = getMapHolder(tileMap) @@ -47,11 +48,17 @@ class MapEditorScreen(): CameraStageBaseScreen(){ stage.addActor(tileEditorOptions) - val saveMapButton = TextButton("Options".tr(),skin) - saveMapButton.onClick { + val optionsMenuButton = TextButton("Options".tr(), skin) + optionsMenuButton.onClick { MapEditorOptionsTable(this) } - stage.addActor(saveMapButton) + optionsMenuButton.label.setFontSize(24) + optionsMenuButton.labelCell.pad(20f) + optionsMenuButton.pack() + optionsMenuButton.x = 30f + optionsMenuButton.y = 30f + + stage.addActor(optionsMenuButton) } private fun getMapHolder(tileMap: TileMap): ScrollPane { diff --git a/core/src/com/unciv/ui/mapeditor/MapScreenLoadTable.kt b/core/src/com/unciv/ui/mapeditor/MapScreenLoadTable.kt index 2455855f85..6234b8c936 100644 --- a/core/src/com/unciv/ui/mapeditor/MapScreenLoadTable.kt +++ b/core/src/com/unciv/ui/mapeditor/MapScreenLoadTable.kt @@ -4,10 +4,8 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.scenes.scene2d.ui.SelectBox import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.utils.Array -import com.badlogic.gdx.utils.Json import com.unciv.UnCivGame -import com.unciv.logic.GameSaver -import com.unciv.logic.map.TileMap +import com.unciv.logic.MapSaver import com.unciv.models.gamebasics.tr import com.unciv.ui.saves.Gzip import com.unciv.ui.utils.CameraStageBaseScreen @@ -18,7 +16,7 @@ class MapScreenLoadTable(mapEditorScreen: MapEditorScreen): PopupTable(mapEditor init{ val mapFileSelectBox = SelectBox(CameraStageBaseScreen.skin) val mapNames = Array() - for (mapName in GameSaver().getMaps()) mapNames.add(mapName) + for (mapName in MapSaver().getMaps()) mapNames.add(mapName) mapFileSelectBox.items = mapNames add(mapFileSelectBox).row() @@ -32,7 +30,7 @@ class MapScreenLoadTable(mapEditorScreen: MapEditorScreen): PopupTable(mapEditor loadFromClipboardButton .onClick { val clipboardContentsString = Gdx.app.clipboard.contents.trim() val decoded = Gzip.unzip(clipboardContentsString) - val loadedMap = Json().fromJson(TileMap::class.java, decoded) + val loadedMap = MapSaver().mapFromJson(decoded) UnCivGame.Current.screen = MapEditorScreen(loadedMap) } add(loadFromClipboardButton).row() diff --git a/core/src/com/unciv/ui/worldscreen/optionstable/DropBox.kt b/core/src/com/unciv/ui/worldscreen/optionstable/DropBox.kt index 1ad4266878..5ea56f7e08 100644 --- a/core/src/com/unciv/ui/worldscreen/optionstable/DropBox.kt +++ b/core/src/com/unciv/ui/worldscreen/optionstable/DropBox.kt @@ -13,18 +13,20 @@ class DropBox(){ /** * @param dropboxApiArg If true, then the data will be sent via a Dropbox-Api-Arg header and not via the post body */ - fun dropboxApi(url:String, data:String="",dropboxApiArg:Boolean=false):String{ + fun dropboxApi(url:String, data:String="",contentType:String="",dropboxApiArg:String=""):String { with(URL(url).openConnection() as HttpURLConnection) { requestMethod = "POST" // optional default is GET - setRequestProperty("Authorization","Bearer LTdBbopPUQ0AAAAAAAACxh4_Qd1eVMM7IBK3ULV3BgxzWZDMfhmgFbuUNF_rXQWb") - if(!dropboxApiArg) setRequestProperty("Content-Type","application/json") - setRequestProperty("Dropbox-API-Arg", data) + setRequestProperty("Authorization", "Bearer LTdBbopPUQ0AAAAAAAACxh4_Qd1eVMM7IBK3ULV3BgxzWZDMfhmgFbuUNF_rXQWb") + + if (dropboxApiArg != "") setRequestProperty("Dropbox-API-Arg", dropboxApiArg) + if (contentType != "") setRequestProperty("Content-Type", contentType) + doOutput = true try { - if(!dropboxApiArg) { + if (data != "") { val postData: ByteArray = data.toByteArray(StandardCharsets.UTF_8) val outputStream = DataOutputStream(outputStream) outputStream.write(postData) @@ -34,13 +36,12 @@ class DropBox(){ val reader = BufferedReader(InputStreamReader(inputStream)) val output = reader.readText() - - println("\nSent 'GET' request to URL : $url; Response Code : $responseCode") println(output) return output - } - catch (ex:Exception){ + } catch (ex: Exception) { println(ex.message) + val reader = BufferedReader(InputStreamReader(errorStream)) + println(reader.readText()) return "Error!" } } @@ -48,16 +49,22 @@ class DropBox(){ fun getFolderList(folder:String):FolderList{ val response = dropboxApi("https://api.dropboxapi.com/2/files/list_folder", - "{\"path\":\"$folder\"}") + "{\"path\":\"$folder\"}","application/json") return GameSaver().json().fromJson(FolderList::class.java,response) } - fun getFileInfo(fileName:String):String{ + fun downloadFile(fileName:String):String{ val response = dropboxApi("https://content.dropboxapi.com/2/files/download", - "{\"path\":\"$fileName\"}",true) + dropboxApiArg = "{\"path\":\"$fileName\"}") return response } + fun uploadFile(fileName: String, data: String){ + val response = dropboxApi("https://content.dropboxapi.com/2/files/upload", + data,"application/octet-stream","{\"path\":\"$fileName\"}") + } + + class FolderList{ var entries = ArrayList() } diff --git a/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt b/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt index aa88ae25cc..9004f8ec51 100644 --- a/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt +++ b/core/src/com/unciv/ui/worldscreen/optionstable/WorldScreenOptionsTable.kt @@ -96,14 +96,15 @@ class WorldScreenOptionsTable(screen:WorldScreen) : PopupTable(screen){ scrollPane.setScrollingDisabled(true,false) add(scrollPane).maxHeight(screen.stage.height*0.6f).row() -/* + addButton("Dropbox Testing"){ // val folderList = DropBox().getFolderList("/Maps") // for(folder in folderList.entries) // print(folder.name) - DropBox().getFileInfo("/Maps/China starts on tundra") +// DropBox().downloadFile("/Maps/China starts on tundra") + DropBox().uploadFile("/Maps/Test","blabla") } - */ + addButton("Close"){ remove() }