diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index 4ef6adc2ea..3e1ea99a1d 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -320,7 +320,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion checksum = "" // Checksum calculation cannot include old checksum, obvs val bytes = MessageDigest .getInstance("SHA-1") - .digest(json().toJson(this).toByteArray()) + .digest(json().toJson(this).toByteArray(Charsets.UTF_8)) checksum = oldChecksum return Gzip.encode(bytes) } diff --git a/core/src/com/unciv/logic/files/LinuxX11SaverLoader.kt b/core/src/com/unciv/logic/files/LinuxX11SaverLoader.kt index 959151a492..daabc5c25a 100644 --- a/core/src/com/unciv/logic/files/LinuxX11SaverLoader.kt +++ b/core/src/com/unciv/logic/files/LinuxX11SaverLoader.kt @@ -17,7 +17,7 @@ class LinuxX11SaverLoader : PlatformSaverLoader { success, file -> if (!success) return@createSaveDialog try { - file.writeString(data, false, "UTF-8") + file.writeString(data, false, Charsets.UTF_8.name()) onSaved(file.path()) } catch (ex: Exception) { onError(ex) @@ -34,7 +34,7 @@ class LinuxX11SaverLoader : PlatformSaverLoader { FileChooser.createLoadDialog(stage, "Load game") { success, file -> if (!success) return@createLoadDialog try { - val data = file.readString("UTF-8") + val data = file.readString(Charsets.UTF_8.name()) onLoaded(data, file.path()) } catch (ex: Exception) { onError(ex) diff --git a/core/src/com/unciv/logic/files/MapSaver.kt b/core/src/com/unciv/logic/files/MapSaver.kt index b3e807cac0..f06fd853b4 100644 --- a/core/src/com/unciv/logic/files/MapSaver.kt +++ b/core/src/com/unciv/logic/files/MapSaver.kt @@ -6,7 +6,6 @@ import com.unciv.json.json import com.unciv.logic.map.MapParameters import com.unciv.logic.map.TileMap import com.unciv.ui.screens.savescreens.Gzip -import com.unciv.utils.Log object MapSaver { @@ -30,11 +29,11 @@ object MapSaver { } fun saveMap(mapName: String, tileMap: TileMap) { - getMap(mapName).writeString(mapToSavedString(tileMap), false) + getMap(mapName).writeString(mapToSavedString(tileMap), false, Charsets.UTF_8.name()) } fun loadMap(mapFile: FileHandle): TileMap { - return mapFromSavedString(mapFile.readString()) + return mapFromSavedString(mapFile.readString(Charsets.UTF_8.name())) } fun getMaps(): Array = Gdx.files.local(mapsFolder).list() diff --git a/core/src/com/unciv/logic/files/UncivFiles.kt b/core/src/com/unciv/logic/files/UncivFiles.kt index db20695e9f..4458f46751 100644 --- a/core/src/com/unciv/logic/files/UncivFiles.kt +++ b/core/src/com/unciv/logic/files/UncivFiles.kt @@ -4,6 +4,7 @@ import com.badlogic.gdx.Files import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.utils.JsonReader +import com.badlogic.gdx.utils.GdxRuntimeException // Kdoc import com.badlogic.gdx.utils.SerializationException import com.unciv.UncivGame import com.unciv.json.fromJsonFile @@ -84,7 +85,7 @@ class UncivFiles( } else { files.local(path) } - return file.writer(append) + return file.writer(append, Charsets.UTF_8.name()) } fun getMultiplayerSaves(): Sequence { @@ -226,7 +227,7 @@ class UncivFiles( loadGameFromFile(getSave(gameName)) fun loadGameFromFile(gameFile: FileHandle): GameInfo { - val gameData = gameFile.readString() + val gameData = gameFile.readString(Charsets.UTF_8.name()) if (gameData.isNullOrBlank()) { throw emptyFile(gameFile) } @@ -304,7 +305,7 @@ class UncivFiles( } fun setGeneralSettings(gameSettings: GameSettings) { - getGeneralSettingsFile().writeString(json().toJson(gameSettings), false) + getGeneralSettingsFile().writeString(json().toJson(gameSettings), false, Charsets.UTF_8.name()) } companion object { diff --git a/core/src/com/unciv/logic/multiplayer/storage/DropBox.kt b/core/src/com/unciv/logic/multiplayer/storage/DropBox.kt index 68559d5927..fccbeeb8eb 100644 --- a/core/src/com/unciv/logic/multiplayer/storage/DropBox.kt +++ b/core/src/com/unciv/logic/multiplayer/storage/DropBox.kt @@ -38,8 +38,7 @@ object DropBox: FileStorage { try { if (data != "") { - // StandardCharsets.UTF_8 requires API 19 - val postData: ByteArray = data.toByteArray(Charset.forName("UTF-8")) + val postData: ByteArray = data.toByteArray(Charsets.UTF_8) val outputStream = DataOutputStream(outputStream) outputStream.write(postData) outputStream.flush() @@ -48,7 +47,7 @@ object DropBox: FileStorage { return inputStream } catch (ex: Exception) { debug("Dropbox exception", ex) - val reader = BufferedReader(InputStreamReader(errorStream)) + val reader = BufferedReader(InputStreamReader(errorStream, Charsets.UTF_8)) val responseString = reader.readText() debug("Response: %s", responseString) @@ -63,7 +62,7 @@ object DropBox: FileStorage { return null } catch (error: Error) { Log.error("Dropbox error", error) - debug("Error stream: %s", { BufferedReader(InputStreamReader(errorStream)).readText() }) + debug("Error stream: %s", { BufferedReader(InputStreamReader(errorStream, Charsets.UTF_8)).readText() }) return null } } @@ -86,7 +85,7 @@ object DropBox: FileStorage { data="{\"path\":\"${getLocalGameLocation(fileName)}\"}", contentType="application/json" )!! - val reader = BufferedReader(InputStreamReader(stream)) + val reader = BufferedReader(InputStreamReader(stream, Charsets.UTF_8)) return json().fromJson(MetaData::class.java, reader.readText()) } @@ -101,7 +100,7 @@ object DropBox: FileStorage { override fun loadFileData(fileName: String): String { val inputStream = downloadFile(getLocalGameLocation(fileName)) - return BufferedReader(InputStreamReader(inputStream)).readText() + return BufferedReader(InputStreamReader(inputStream, Charsets.UTF_8)).readText() } override fun authenticate(userId: String, password: String): Boolean { @@ -148,7 +147,7 @@ object DropBox: FileStorage { // val result = dropboxApi("https://api.dropboxapi.com/2/file_properties/templates/add_for_user", // "{\"name\": \"Security\",\"description\": \"These properties describe how confidential this file or folder is.\",\"fields\": [{\"name\": \"Security Policy\",\"description\": \"This is the security policy of the file or folder described.\nPolicies can be Confidential, Public or Internal.\",\"type\": \"string\"}]}" // ,"application/json") -// return BufferedReader(InputStreamReader(result)).readText() +// return BufferedReader(InputStreamReader(result, Charsets.UTF_8)).readText() // } // private class FolderList{ diff --git a/core/src/com/unciv/logic/multiplayer/storage/SimpleHttp.kt b/core/src/com/unciv/logic/multiplayer/storage/SimpleHttp.kt index b38ff938a8..589a8ad046 100644 --- a/core/src/com/unciv/logic/multiplayer/storage/SimpleHttp.kt +++ b/core/src/com/unciv/logic/multiplayer/storage/SimpleHttp.kt @@ -51,19 +51,18 @@ object SimpleHttp { try { if (content.isNotEmpty()) { doOutput = true - // StandardCharsets.UTF_8 requires API 19 - val postData: ByteArray = content.toByteArray(Charset.forName("UTF-8")) + val postData: ByteArray = content.toByteArray(Charsets.UTF_8) val outputStream = DataOutputStream(outputStream) outputStream.write(postData) outputStream.flush() } - val text = BufferedReader(InputStreamReader(inputStream)).readText() + val text = BufferedReader(InputStreamReader(inputStream, Charsets.UTF_8)).readText() action(true, text, responseCode) } catch (t: Throwable) { debug("Error during HTTP request", t) val errorMessageToReturn = - if (errorStream != null) BufferedReader(InputStreamReader(errorStream)).readText() + if (errorStream != null) BufferedReader(InputStreamReader(errorStream, Charsets.UTF_8)).readText() else t.message!! debug("Returning error message [%s]", errorMessageToReturn) action(false, errorMessageToReturn, responseCode) diff --git a/core/src/com/unciv/models/metadata/ModCategories.kt b/core/src/com/unciv/models/metadata/ModCategories.kt index 5dc0d68d73..bf2e9b8fdc 100644 --- a/core/src/com/unciv/models/metadata/ModCategories.kt +++ b/core/src/com/unciv/models/metadata/ModCategories.kt @@ -59,7 +59,7 @@ class ModCategories : ArrayList() { val json = json() val compact = json.toJson(this, ModCategories::class.java, Category::class.java) val verbose = json.prettyPrint(compact) - Gdx.files.local(fileLocation).writeString(verbose, false, "UTF-8") + Gdx.files.local(fileLocation).writeString(verbose, false, Charsets.UTF_8.name()) } fun fromSelectBox(selectBox: TranslatedSelectBox): Category { diff --git a/core/src/com/unciv/models/translations/TranslationFileReader.kt b/core/src/com/unciv/models/translations/TranslationFileReader.kt index e523a341b0..72270b1ff7 100644 --- a/core/src/com/unciv/models/translations/TranslationFileReader.kt +++ b/core/src/com/unciv/models/translations/TranslationFileReader.kt @@ -2,13 +2,12 @@ package com.unciv.models.translations import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle -import java.nio.charset.Charset import kotlin.collections.set object TranslationFileReader { const val percentagesFileLocation = "jsons/translations/completionPercentages.properties" - val charset: String = Charset.forName("UTF-8").name() + val charset: String = Charsets.UTF_8.name() fun read(file: FileHandle): LinkedHashMap { val translations = LinkedHashMap() diff --git a/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt b/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt index 5b293398b3..fdc5b32147 100644 --- a/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt +++ b/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt @@ -57,7 +57,7 @@ object Github { } catch (ex: Exception) { // No error handling, just log the message. // NOTE that this 'read error stream' CAN ALSO fail, but will be caught by the big try/catch - val reader = BufferedReader(InputStreamReader(errorStream)) + val reader = BufferedReader(InputStreamReader(errorStream, Charsets.UTF_8)) Log.error("Message from GitHub: %s", reader.readText()) throw ex } diff --git a/core/src/com/unciv/ui/screens/savescreens/Gzip.kt b/core/src/com/unciv/ui/screens/savescreens/Gzip.kt index 22cfeb0d0c..07b4f46ca2 100644 --- a/core/src/com/unciv/ui/screens/savescreens/Gzip.kt +++ b/core/src/com/unciv/ui/screens/savescreens/Gzip.kt @@ -10,8 +10,8 @@ import java.util.zip.GZIPOutputStream object Gzip { - fun zip(data:String):String = encode(compress(data)) - fun unzip(data:String):String = decompress(decode(data)) + fun zip(data: String): String = encode(compress(data)) + fun unzip(data: String): String = decompress(decode(data)) private fun compress(data: String): ByteArray { val bos = ByteArrayOutputStream(data.length) @@ -26,7 +26,7 @@ object Gzip { private fun decompress(compressed: ByteArray): String { val bis = ByteArrayInputStream(compressed) val gis = GZIPInputStream(bis) - val br = BufferedReader(InputStreamReader(gis, "UTF-8")) + val br = BufferedReader(InputStreamReader(gis, Charsets.UTF_8)) val sb = StringBuilder() var line: String? = br.readLine() while (line != null) { @@ -40,11 +40,11 @@ object Gzip { } - fun encode(bytes:ByteArray): String{ + fun encode(bytes: ByteArray): String { return String(Base64Coder.encode(bytes)) } - private fun decode(base64Str: String): ByteArray{ + private fun decode(base64Str: String): ByteArray { return Base64Coder.decode(base64Str) } } diff --git a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt index bc361b10b3..e3f9171899 100644 --- a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt +++ b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt @@ -65,7 +65,7 @@ internal object DesktopLauncher { width = maximumWindowBounds.width, height = maximumWindowBounds.height ) - FileHandle(SETTINGS_FILE_NAME).writeString(json().toJson(settings), false) // so when we later open the game we get fullscreen + FileHandle(SETTINGS_FILE_NAME).writeString(json().toJson(settings), false, Charsets.UTF_8.name()) // so when we later open the game we get fullscreen } // Kludge! This is a workaround - the matching call in DesktopDisplay doesn't "take" quite permanently, // the window might revert to the "config" values when the user moves the window - worse if they diff --git a/desktop/src/com/unciv/app/desktop/ImagePacker.kt b/desktop/src/com/unciv/app/desktop/ImagePacker.kt index 2f2ffd2852..db4b4a2430 100644 --- a/desktop/src/com/unciv/app/desktop/ImagePacker.kt +++ b/desktop/src/com/unciv/app/desktop/ImagePacker.kt @@ -121,7 +121,7 @@ internal object ImagePacker { // An image folder can optionally have a TexturePacker settings file val settingsFile = File("$input${File.separator}TexturePacker.settings") val settings = if (settingsFile.exists()) - Json().fromJson(TexturePacker.Settings::class.java, settingsFile.reader()) + Json().fromJson(TexturePacker.Settings::class.java, settingsFile.reader(Charsets.UTF_8)) else defaultSettings TexturePacker.process(settings, input, output, packFileName) diff --git a/desktop/src/com/unciv/app/desktop/SystemUtils.kt b/desktop/src/com/unciv/app/desktop/SystemUtils.kt index 4fde41f678..8fae5a58ae 100644 --- a/desktop/src/com/unciv/app/desktop/SystemUtils.kt +++ b/desktop/src/com/unciv/app/desktop/SystemUtils.kt @@ -39,6 +39,9 @@ object SystemUtils { builder.appendLine("Max Memory: $maxMemory MB") } + // Encoding used by Java when not explicitly specified/-able (such as atlas loader) + builder.appendLine("System default encoding: " + Charset.defaultCharset().name()) + return builder.toString() }