mirror of
https://github.com/yairm210/Unciv.git
synced 2025-08-03 20:48:49 -04:00
- Desktop: Allow specifying data directory (for "local" files, in GDX terms) separate from installed files directory (What GDX terms "internal").
- Added helper functions for common paths - Does not include a way to specify said directory - pending tests
This commit is contained in:
parent
ab2ae35cf9
commit
f03c30ed5c
@ -66,7 +66,7 @@ class AndroidFont : FontImplementation {
|
||||
|
||||
private fun createTypefaceCustom(path: String): Typeface {
|
||||
return try {
|
||||
Typeface.createFromFile(Gdx.files.local(path).file())
|
||||
Typeface.createFromFile(UncivGame.Current.files.getLocalFile(path).file())
|
||||
} catch (e: Exception) {
|
||||
Log.error("Failed to create typeface, falling back to default", e)
|
||||
// Falling back to default
|
||||
|
@ -60,6 +60,7 @@ import kotlin.reflect.KClass
|
||||
open class UncivGame(val isConsoleMode: Boolean = false) : Game(), PlatformSpecific {
|
||||
|
||||
var deepLinkedMultiplayerGame: String? = null
|
||||
override var customDataDirectory: String? = null
|
||||
|
||||
/** The game currently in progress */
|
||||
var gameInfo: GameInfo? = null
|
||||
@ -93,10 +94,10 @@ open class UncivGame(val isConsoleMode: Boolean = false) : Game(), PlatformSpeci
|
||||
DebugUtils.VISIBLE_MAP = false
|
||||
}
|
||||
Current = this
|
||||
files = UncivFiles(Gdx.files)
|
||||
files = UncivFiles(Gdx.files, customDataDirectory)
|
||||
Concurrency.run {
|
||||
// Delete temporary files created when downloading mods
|
||||
val tempFiles = Gdx.files.local("mods").list().filter { !it.isDirectory && it.name().startsWith("temp-") }
|
||||
val tempFiles = files.getLocalFile("mods").list().filter { !it.isDirectory && it.name().startsWith("temp-") }
|
||||
for (file in tempFiles) file.delete()
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.widgets.UncivTextField
|
||||
@ -88,7 +89,7 @@ open class FileChooser(
|
||||
|
||||
// operational
|
||||
private val maxHeight = stageToShowOn.height * 0.6f
|
||||
private val absoluteLocalPath = Gdx.files.local("").file().absoluteFile.canonicalPath
|
||||
private val absoluteLocalPath = UncivGame.Current.files.getDataFolder().file().absoluteFile.canonicalPath
|
||||
private val absoluteExternalPath = if (Gdx.files.isExternalStorageAvailable)
|
||||
Gdx.files.external("").file().absoluteFile.canonicalPath
|
||||
else "/\\/\\/" // impossible placeholder
|
||||
@ -204,7 +205,7 @@ open class FileChooser(
|
||||
if (file.type() != Files.FileType.Absolute) return file
|
||||
val path = file.path()
|
||||
if (path.startsWith(absoluteLocalPath))
|
||||
return Gdx.files.local(path.removePrefix(absoluteLocalPath).removePrefix(File.separator))
|
||||
return UncivGame.Current.files.getLocalFile(path.removePrefix(absoluteLocalPath).removePrefix(File.separator))
|
||||
if (path.startsWith(absoluteExternalPath))
|
||||
return Gdx.files.external(path.removePrefix(absoluteExternalPath).removePrefix(File.separator))
|
||||
return file
|
||||
|
@ -113,7 +113,7 @@ interface IMediaFinder {
|
||||
//////////////////////////////////////////// Internal helpers
|
||||
|
||||
fun getModMediaFolder(modName: String): FileHandle =
|
||||
Gdx.files.local("mods").child(modName).child(mediaSubFolderName)
|
||||
UncivGame.Current.files.getModFolder(modName).child(mediaSubFolderName)
|
||||
|
||||
private fun FileHandle.directoryExists() = when {
|
||||
type() != Files.FileType.Internal -> exists() && isDirectory
|
||||
|
@ -23,7 +23,7 @@ class LinuxX11SaverLoader : PlatformSaverLoader {
|
||||
val startLocation =
|
||||
if (suggestedLocation.startsWith(File.separator)) Gdx.files.absolute(suggestedLocation)
|
||||
else if (Gdx.files.external(suggestedLocation).parent().exists()) Gdx.files.external(suggestedLocation)
|
||||
else Gdx.files.local(suggestedLocation)
|
||||
else UncivGame.Current.files.getLocalFile(suggestedLocation)
|
||||
FileChooser.createSaveDialog(stage, "Save game", startLocation) {
|
||||
success, file ->
|
||||
if (!success)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.unciv.logic.files
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.map.MapParameters
|
||||
import com.unciv.logic.map.TileMap
|
||||
@ -12,7 +12,7 @@ object MapSaver {
|
||||
const val mapsFolder = "maps"
|
||||
var saveZipped = true
|
||||
|
||||
private fun getMap(mapName: String) = Gdx.files.local("$mapsFolder/$mapName")
|
||||
private fun getMap(mapName: String) = UncivGame.Current.files.getLocalFile("$mapsFolder/$mapName")
|
||||
|
||||
fun mapFromSavedString(mapString: String): TileMap {
|
||||
val unzippedJson = try {
|
||||
@ -36,7 +36,7 @@ object MapSaver {
|
||||
return mapFromSavedString(mapFile.readString(Charsets.UTF_8.name()))
|
||||
}
|
||||
|
||||
fun getMaps(): Array<FileHandle> = Gdx.files.local(mapsFolder).list()
|
||||
fun getMaps(): Array<FileHandle> = UncivGame.Current.files.getLocalFile(mapsFolder).list()
|
||||
|
||||
private fun mapFromJson(json: String): TileMap = json().fromJson(TileMap::class.java, json)
|
||||
|
||||
|
@ -40,7 +40,10 @@ class UncivFiles(
|
||||
* This is necessary because the Android turn check background worker does not hold any reference to the actual [com.badlogic.gdx.Application],
|
||||
* which is normally responsible for keeping the [Gdx] static variables from being garbage collected.
|
||||
*/
|
||||
private val files: Files
|
||||
private val files: Files,
|
||||
|
||||
/** If not null, this is the path to the directory in which to store the local files - mods, saves, maps, etc */
|
||||
val customDataDirectory: String?
|
||||
) {
|
||||
init {
|
||||
debug("Creating UncivFiles, localStoragePath: %s, externalStoragePath: %s",
|
||||
@ -51,6 +54,17 @@ class UncivFiles(
|
||||
|
||||
//region Helpers
|
||||
|
||||
fun getLocalFile(fileName: String): FileHandle {
|
||||
return if (customDataDirectory == null) files.local(fileName)
|
||||
else files.absolute(customDataDirectory + File.separator + fileName)
|
||||
}
|
||||
|
||||
fun getModsFolder() = getLocalFile("mods")
|
||||
fun getModFolder(modName: String) = getModsFolder().child(modName)
|
||||
|
||||
/** The folder that holds data that the game changes while running - all the mods, maps, save files, etc */
|
||||
fun getDataFolder() = getLocalFile("")
|
||||
|
||||
fun getSave(gameName: String): FileHandle {
|
||||
return getSave(SAVE_FILES_FOLDER, gameName)
|
||||
}
|
||||
@ -62,7 +76,7 @@ class UncivFiles(
|
||||
debug("Getting save %s from folder %s, preferExternal: %s",
|
||||
gameName, saveFolder, preferExternalStorage, files.externalStoragePath)
|
||||
val location = "${saveFolder}/$gameName"
|
||||
val localFile = files.local(location)
|
||||
val localFile = getLocalFile(location)
|
||||
val externalFile = files.external(location)
|
||||
|
||||
val toReturn = if (files.isExternalStorageAvailable && (
|
||||
@ -88,7 +102,7 @@ class UncivFiles(
|
||||
|
||||
fun pathToFileHandler(path: String): FileHandle {
|
||||
return if (preferExternalStorage && files.isExternalStorageAvailable) files.external(path)
|
||||
else files.local(path)
|
||||
else getLocalFile(path)
|
||||
}
|
||||
|
||||
|
||||
@ -106,9 +120,9 @@ class UncivFiles(
|
||||
|
||||
private fun getSaves(saveFolder: String): Sequence<FileHandle> {
|
||||
debug("Getting saves from folder %s, externalStoragePath: %s", saveFolder, files.externalStoragePath)
|
||||
val localFiles = files.local(saveFolder).list().asSequence()
|
||||
val localFiles = getLocalFile(saveFolder).list().asSequence()
|
||||
|
||||
val externalFiles = if (files.isExternalStorageAvailable && files.local("").file().absolutePath != files.external("").file().absolutePath) {
|
||||
val externalFiles = if (files.isExternalStorageAvailable && getDataFolder().file().absolutePath != files.external("").file().absolutePath) {
|
||||
files.external(saveFolder).list().asSequence()
|
||||
} else {
|
||||
emptySequence()
|
||||
@ -205,7 +219,7 @@ class UncivFiles(
|
||||
onSaved: () -> Unit,
|
||||
onError: (Exception) -> Unit
|
||||
) {
|
||||
val saveLocation = game.customSaveLocation ?: Gdx.files.local(gameName).path()
|
||||
val saveLocation = game.customSaveLocation ?: UncivGame.Current.files.getLocalFile(gameName).path()
|
||||
|
||||
try {
|
||||
val data = gameInfoToString(game)
|
||||
@ -286,7 +300,7 @@ class UncivFiles(
|
||||
|
||||
private fun getGeneralSettingsFile(): FileHandle {
|
||||
return if (UncivGame.Current.isConsoleMode) FileHandle(SETTINGS_FILE_NAME)
|
||||
else files.local(SETTINGS_FILE_NAME)
|
||||
else getLocalFile(SETTINGS_FILE_NAME)
|
||||
}
|
||||
|
||||
fun getGeneralSettings(): GameSettings {
|
||||
|
@ -69,13 +69,13 @@ object Github {
|
||||
|
||||
/**
|
||||
* Download a mod and extract, deleting any pre-existing version.
|
||||
* @param folderFileHandle Destination handle of mods folder - also controls Android internal/external
|
||||
* @param modsFolder Destination handle of mods folder - also controls Android internal/external
|
||||
* @author **Warning**: This took a long time to get just right, so if you're changing this, ***TEST IT THOROUGHLY*** on _both_ Desktop _and_ Phone
|
||||
* @return FileHandle for the downloaded Mod's folder or null if download failed
|
||||
*/
|
||||
fun downloadAndExtract(
|
||||
repo: GithubAPI.Repo,
|
||||
folderFileHandle: FileHandle
|
||||
modsFolder: FileHandle
|
||||
): FileHandle? {
|
||||
var modNameFromFileName = repo.name
|
||||
|
||||
@ -102,7 +102,7 @@ object Github {
|
||||
} ?: return null
|
||||
|
||||
// Download to temporary zip
|
||||
val tempZipFileHandle = folderFileHandle.child("$tempName.zip")
|
||||
val tempZipFileHandle = modsFolder.child("$tempName.zip")
|
||||
tempZipFileHandle.write(inputStream, false)
|
||||
|
||||
// prepare temp unpacking folder
|
||||
@ -122,7 +122,7 @@ object Github {
|
||||
// modName can be "$repoName-$defaultBranch"
|
||||
val finalDestinationName = modName.replace("-$defaultBranch", "").repoNameToFolderName()
|
||||
// finalDestinationName is now the mod name as we display it. Folder name needs to be identical.
|
||||
val finalDestination = folderFileHandle.child(finalDestinationName)
|
||||
val finalDestination = modsFolder.child(finalDestinationName)
|
||||
|
||||
// prevent mixing new content with old
|
||||
var tempBackup: FileHandle? = null
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.unciv.models.metadata
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.github.GithubAPI
|
||||
import com.unciv.ui.components.widgets.TranslatedSelectBox
|
||||
import com.unciv.logic.github.Github
|
||||
import com.unciv.models.translations.tr
|
||||
|
||||
|
||||
class ModCategories : ArrayList<ModCategories.Category>() {
|
||||
@ -61,7 +61,7 @@ class ModCategories : ArrayList<ModCategories.Category>() {
|
||||
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, Charsets.UTF_8.name())
|
||||
UncivGame.Current.files.getLocalFile(fileLocation).writeString(verbose, false, Charsets.UTF_8.name())
|
||||
}
|
||||
|
||||
fun fromSelectBox(selectBox: TranslatedSelectBox): Category {
|
||||
|
@ -2,6 +2,7 @@ package com.unciv.models.ruleset
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.logic.map.MapParameters
|
||||
import com.unciv.models.metadata.BaseRuleset
|
||||
@ -41,7 +42,7 @@ object RulesetCache : HashMap<String, Ruleset>() {
|
||||
val errorLines = ArrayList<String>()
|
||||
if (!noMods) {
|
||||
val modsHandles = if (consoleMode) FileHandle("mods").list()
|
||||
else Gdx.files.local("mods").list()
|
||||
else UncivGame.Current.files.getModsFolder().list()
|
||||
|
||||
for (modFolder in modsHandles) {
|
||||
if (modFolder.name().startsWith('.')) continue
|
||||
|
@ -3,6 +3,7 @@ package com.unciv.models.ruleset.validation
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.json.fromJsonFile
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.map.tile.RoadStatus
|
||||
@ -151,7 +152,7 @@ class RulesetValidator(val ruleset: Ruleset) {
|
||||
if (mapSelectUniques.size > 1)
|
||||
lines.add("Specifying more than one map as preselection makes no sense", RulesetErrorSeverity.WarningOptionsOnly, sourceObject = null)
|
||||
if (mapSelectUniques.isNotEmpty()) {
|
||||
val mapsFolder = Gdx.files.local("mods").child(ruleset.name).child("maps")
|
||||
val mapsFolder = UncivGame.Current.files.getModFolder(ruleset.name).child("maps")
|
||||
if (mapsFolder.exists()) {
|
||||
val maps = mapsFolder.list().map { it.name().lowercase() }
|
||||
for (unique in mapSelectUniques) {
|
||||
|
@ -102,7 +102,7 @@ object TileSetCache : HashMap<String, TileSet>() {
|
||||
* Available before initialization finishes.
|
||||
*/
|
||||
fun getAvailableTilesets(imageGetterTilesets: Sequence<String>): Set<String> {
|
||||
val modTilesetConfigFiles = Gdx.files.local("mods").list().asSequence()
|
||||
val modTilesetConfigFiles = UncivGame.Current.files.getModsFolder().list().asSequence()
|
||||
.filter { it.isDirectory && !it.name().startsWith('.') }
|
||||
.flatMap { it.child("jsons/TileSets").list().asSequence() }
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.unciv.models.translations
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.json.fromJsonFile
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
|
||||
@ -72,7 +72,7 @@ object TranslationFileWriter {
|
||||
|
||||
// See #5168 for some background on this
|
||||
for ((modName, modTranslations) in translations.modsWithTranslations) {
|
||||
val modFolder = Gdx.files.local("mods").child(modName)
|
||||
val modFolder = UncivGame.Current.files.getModFolder(modName)
|
||||
val modPercentages = generateTranslationFiles(modTranslations, modFolder, translations)
|
||||
writeLanguagePercentages(modPercentages, modFolder) // unused by the game but maybe helpful for the mod developer
|
||||
}
|
||||
@ -86,7 +86,7 @@ object TranslationFileWriter {
|
||||
|
||||
private fun getFileHandle(modFolder: FileHandle?, fileLocation: String) =
|
||||
if (modFolder != null) modFolder.child(fileLocation)
|
||||
else Gdx.files.local(fileLocation)
|
||||
else UncivGame.Current.files.getLocalFile(fileLocation)
|
||||
|
||||
/**
|
||||
* Writes new language files per Mod or for BaseRuleset - only each language that exists in [translations].
|
||||
@ -108,7 +108,7 @@ object TranslationFileWriter {
|
||||
linesToTranslate.addAll(templateFile.reader(TranslationFileReader.charset).readLines())
|
||||
|
||||
linesToTranslate += "\n\n#################### Lines from Unique Types #######################\n"
|
||||
for (uniqueType in UniqueType.values()) {
|
||||
for (uniqueType in UniqueType.entries) {
|
||||
val deprecationAnnotation = uniqueType.getDeprecationAnnotation()
|
||||
if (deprecationAnnotation != null) continue
|
||||
if (uniqueType.flags.contains(UniqueFlag.HiddenToUsers)) continue
|
||||
@ -116,37 +116,37 @@ object TranslationFileWriter {
|
||||
linesToTranslate += "${uniqueType.getTranslatable()} = "
|
||||
}
|
||||
|
||||
for (uniqueParameterType in UniqueParameterType.values()) {
|
||||
for (uniqueParameterType in UniqueParameterType.entries) {
|
||||
val strings = uniqueParameterType.getTranslationWriterStringsForOutput()
|
||||
if (strings.isEmpty()) continue
|
||||
linesToTranslate += "\n######### ${uniqueParameterType.displayName} ###########\n"
|
||||
linesToTranslate.addAll(strings.map { "$it = " })
|
||||
}
|
||||
|
||||
for (uniqueTarget in UniqueTarget.values())
|
||||
for (uniqueTarget in UniqueTarget.entries)
|
||||
linesToTranslate += "$uniqueTarget = "
|
||||
|
||||
linesToTranslate += "\n\n#################### Lines from spy actions #######################\n"
|
||||
for (spyAction in SpyAction.values())
|
||||
for (spyAction in SpyAction.entries)
|
||||
linesToTranslate += "${spyAction.displayString} = "
|
||||
|
||||
linesToTranslate += "\n\n#################### Lines from diplomatic modifiers #######################\n"
|
||||
for (diplomaticModifier in DiplomaticModifiers.values())
|
||||
for (diplomaticModifier in DiplomaticModifiers.entries)
|
||||
linesToTranslate += "${diplomaticModifier.text} = "
|
||||
|
||||
linesToTranslate += "\n\n#################### Lines from key bindings #######################\n"
|
||||
for (bindingLabel in KeyboardBinding.getTranslationEntries())
|
||||
linesToTranslate += "$bindingLabel = "
|
||||
|
||||
for (baseRuleset in BaseRuleset.values()) {
|
||||
for (baseRuleset in BaseRuleset.entries) {
|
||||
val generatedStringsFromBaseRuleset =
|
||||
GenerateStringsFromJSONs(Gdx.files.local("jsons/${baseRuleset.fullName}"))
|
||||
GenerateStringsFromJSONs(UncivGame.Current.files.getLocalFile("jsons/${baseRuleset.fullName}"))
|
||||
for (entry in generatedStringsFromBaseRuleset)
|
||||
fileNameToGeneratedStrings[entry.key + " from " + baseRuleset.fullName] = entry.value
|
||||
}
|
||||
|
||||
// Tutorials reside one level above the base rulesets - if they were per-ruleset the following lines would be unnecessary
|
||||
val tutorialStrings = GenerateStringsFromJSONs(Gdx.files.local("jsons")) { it.name == "Tutorials.json" }
|
||||
val tutorialStrings = GenerateStringsFromJSONs(UncivGame.Current.files.getLocalFile("jsons")) { it.name == "Tutorials.json" }
|
||||
fileNameToGeneratedStrings["Tutorials"] = tutorialStrings.values.first()
|
||||
} else {
|
||||
fileNameToGeneratedStrings.putAll(GenerateStringsFromJSONs(modFolder.child("jsons")))
|
||||
@ -259,7 +259,7 @@ object TranslationFileWriter {
|
||||
|
||||
// used for unit test only
|
||||
fun getGeneratedStringsSize(): Int {
|
||||
return GenerateStringsFromJSONs(Gdx.files.local("jsons/Civ V - Vanilla")).values.sumOf {
|
||||
return GenerateStringsFromJSONs(UncivGame.Current.files.getLocalFile("jsons/Civ V - Vanilla")).values.sumOf {
|
||||
// exclude empty lines
|
||||
it.count { line: String -> !line.startsWith(specialNewLineCode) }
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class MusicController {
|
||||
private fun getFile(path: String) =
|
||||
if (musicLocation == FileType.External && Gdx.files.isExternalStorageAvailable)
|
||||
Gdx.files.external(path)
|
||||
else Gdx.files.local(path)
|
||||
else UncivGame.Current.files.getLocalFile(path)
|
||||
|
||||
// These are replaced when we _know_ we're attached to Gdx.audio.update
|
||||
private var needOwnTimer = true
|
||||
@ -62,9 +62,9 @@ class MusicController {
|
||||
}
|
||||
|
||||
init {
|
||||
val oldFallbackFile = Gdx.files.local(musicFallbackLocation.removePrefix("/"))
|
||||
val oldFallbackFile = UncivGame.Current.files.getLocalFile(musicFallbackLocation.removePrefix("/"))
|
||||
if (oldFallbackFile.exists()) {
|
||||
val newFallbackFile = Gdx.files.local(musicFallbackLocalName)
|
||||
val newFallbackFile = UncivGame.Current.files.getLocalFile(musicFallbackLocalName)
|
||||
if (!newFallbackFile.exists())
|
||||
oldFallbackFile.moveTo(newFallbackFile)
|
||||
}
|
||||
@ -82,7 +82,7 @@ class MusicController {
|
||||
else if (mod.isEmpty()) track else "$mod: $track"
|
||||
|
||||
companion object {
|
||||
/** Parse a path - must be relative to `Gdx.files.local` */
|
||||
/** Parse a path - must be relative to `UncivGame.Current.files.getLocalFile` */
|
||||
fun parse(fileName: String): MusicTrackInfo {
|
||||
if (fileName.isEmpty())
|
||||
return MusicTrackInfo("", "", "")
|
||||
|
@ -138,9 +138,9 @@ object SoundPlayer {
|
||||
private fun getFile(sound: UncivSound): FileHandle? {
|
||||
val fileName = sound.fileName
|
||||
for (modFolder in getFolders()) {
|
||||
for (extension in SupportedExtensions.values()) {
|
||||
for (extension in SupportedExtensions.entries) {
|
||||
val path = "${modFolder}sounds$separator$fileName.${extension.name}"
|
||||
val localFile = Gdx.files.local(path)
|
||||
val localFile = UncivGame.Current.files.getLocalFile(path)
|
||||
if (localFile.exists()) return localFile
|
||||
val internalFile = Gdx.files.internal(path)
|
||||
if (internalFile.exists()) return internalFile
|
||||
|
@ -76,7 +76,7 @@ object ImageGetter {
|
||||
// These are from the mods
|
||||
val visualMods = UncivGame.Current.settings.visualMods + ruleset.mods
|
||||
for (mod in visualMods) {
|
||||
loadModAtlases(mod, Gdx.files.local("mods/$mod"))
|
||||
loadModAtlases(mod, UncivGame.Current.files.getModFolder(mod))
|
||||
}
|
||||
|
||||
TileSetCache.assembleTileSetConfigs(ruleset.mods)
|
||||
@ -185,7 +185,7 @@ object ImageGetter {
|
||||
fun findExternalImage(name: String): FileHandle? {
|
||||
val folders = try { // For CI mod checker, we can't access "local" files
|
||||
// since Gdx files are not set up
|
||||
ruleset.mods.asSequence().map { Gdx.files.local("mods/$it/ExtraImages") } +
|
||||
ruleset.mods.asSequence().map { UncivGame.Current.files.getLocalFile("mods/$it/ExtraImages") } +
|
||||
sequenceOf(Gdx.files.internal("ExtraImages"))
|
||||
} catch (e: Exception) {
|
||||
debug("Error loading mods: $e")
|
||||
|
@ -168,7 +168,7 @@ class AdvancedTab(
|
||||
fonts.add(FontFamilyData.default)
|
||||
|
||||
// Add mods fonts
|
||||
val modsDir = Gdx.files.local("mods/")
|
||||
val modsDir = UncivGame.Current.files.getModsFolder()
|
||||
for (mod in modsDir.list()) {
|
||||
|
||||
// Not a dir, continue
|
||||
|
@ -40,7 +40,7 @@ class TutorialController(screen: BaseScreen) {
|
||||
val mods = UncivGame.Current.gameInfo?.ruleset?.mods
|
||||
?: return@sequence
|
||||
val files = mods.asSequence()
|
||||
.map { Gdx.files.local("mods/$it/jsons/Tutorials.json") }
|
||||
.map { UncivGame.Current.files.getLocalFile("mods/$it/jsons/Tutorials.json") }
|
||||
yieldAll(files.filter { it.exists() })
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.unciv.ui.screens.mapeditorscreen
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.logic.files.FileChooser
|
||||
@ -55,7 +55,7 @@ class MapEditorWesnothImporter(private val editorScreen: MapEditorScreen) : Disp
|
||||
json().fromJson(
|
||||
linkedMapOf<String,ArrayList<String>>()::class.java,
|
||||
arrayListOf<String>()::class.java, // else we get Gdx.Array despite the class above stating ArrayList
|
||||
Gdx.files.local("jsons/WesnothImportMappings.json")
|
||||
UncivGame.Current.files.getLocalFile("jsons/WesnothImportMappings.json")
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.github.Github
|
||||
import com.unciv.logic.github.GithubAPI
|
||||
import com.unciv.models.metadata.BaseRuleset
|
||||
@ -53,7 +54,7 @@ internal class ModInfoAndActionPane : Table() {
|
||||
fun update(mod: Ruleset) {
|
||||
val modName = mod.name
|
||||
val modOptions = mod.modOptions // The ModOptions as enriched by us with GitHub metadata when originally downloaded
|
||||
isBuiltin = modOptions.modUrl.isEmpty() && BaseRuleset.values().any { it.fullName == modName }
|
||||
isBuiltin = modOptions.modUrl.isEmpty() && BaseRuleset.entries.any { it.fullName == modName }
|
||||
enableVisualCheckBox = ModCompatibility.isAudioVisualMod(mod)
|
||||
update(
|
||||
modName, modOptions.modUrl, modOptions.defaultBranch,
|
||||
@ -159,7 +160,7 @@ internal class ModInfoAndActionPane : Table() {
|
||||
|
||||
private fun addLocalPreviewImage(modName: String) {
|
||||
// No concurrency, order of magnitude 20ms
|
||||
val modFolder = Gdx.files.local("mods/$modName")
|
||||
val modFolder = UncivGame.Current.files.getModFolder(modName)
|
||||
val previewFile = modFolder.child("preview.jpg").takeIf { it.exists() }
|
||||
?: modFolder.child("preview.png").takeIf { it.exists() }
|
||||
?: return
|
||||
|
@ -481,7 +481,7 @@ class ModManagementScreen private constructor(
|
||||
try {
|
||||
val modFolder = Github.downloadAndExtract(
|
||||
repo,
|
||||
Gdx.files.local("mods")
|
||||
UncivGame.Current.files.getModsFolder()
|
||||
)
|
||||
?: throw Exception("Exception during GitHub download") // downloadAndExtract returns null for 404 errors and the like -> display something!
|
||||
Github.rewriteModOptions(repo, modFolder)
|
||||
|
@ -7,6 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.SerializationException
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.MissingModsException
|
||||
import com.unciv.logic.UncivShowableException
|
||||
import com.unciv.logic.files.PlatformSaverLoader
|
||||
@ -176,7 +177,7 @@ class LoadGameScreen : LoadOrSaveScreen() {
|
||||
errorLabel.isVisible = false
|
||||
loadFromCustomLocationButton.setText(Constants.loading.tr())
|
||||
loadFromCustomLocationButton.disable()
|
||||
Concurrency.run(Companion.loadFromCustomLocation) {
|
||||
Concurrency.run(loadFromCustomLocation) {
|
||||
game.files.loadGameFromCustomLocation(
|
||||
{
|
||||
Concurrency.run { game.loadGame(it, callFromLoadScreen = true) }
|
||||
@ -265,7 +266,7 @@ class LoadGameScreen : LoadOrSaveScreen() {
|
||||
?: throw UncivShowableException("Could not find a mod named \"[$modName]\".")
|
||||
val modFolder = Github.downloadAndExtract(
|
||||
repo,
|
||||
Gdx.files.local("mods")
|
||||
UncivGame.Current.files.getModsFolder()
|
||||
)
|
||||
?: throw Exception("Unexpected 404 error") // downloadAndExtract returns null for 404 errors and the like -> display something!
|
||||
Github.rewriteModOptions(repo, modFolder)
|
||||
|
@ -8,4 +8,6 @@ interface PlatformSpecific {
|
||||
/** Install system audio hooks */
|
||||
fun installAudioHooks() {}
|
||||
|
||||
/** If not null, this is the path to the directory in which to store the local files - mods, saves, maps, etc */
|
||||
var customDataDirectory: String?
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.unciv.app.desktop
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.ui.components.fonts.FontFamilyData
|
||||
import com.unciv.ui.components.fonts.FontImplementation
|
||||
import com.unciv.ui.components.fonts.FontMetricsCommon
|
||||
@ -44,7 +44,7 @@ class DesktopFont : FontImplementation {
|
||||
try
|
||||
{
|
||||
// Try to create and register new font
|
||||
val fontFile = Gdx.files.local(path).file()
|
||||
val fontFile = UncivGame.Current.files.getLocalFile(path).file()
|
||||
val ge = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
font = Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(size.toFloat())
|
||||
ge.registerFont(font)
|
||||
|
@ -4,7 +4,7 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
|
||||
import com.unciv.UncivGame
|
||||
|
||||
class DesktopGame(config: Lwjgl3ApplicationConfiguration) : UncivGame() {
|
||||
class DesktopGame(config: Lwjgl3ApplicationConfiguration, override var customDataDirectory: String?) : UncivGame() {
|
||||
|
||||
private var discordUpdater = DiscordUpdater()
|
||||
private val windowListener = UncivWindowListener()
|
||||
@ -48,5 +48,4 @@ class DesktopGame(config: Lwjgl3ApplicationConfiguration) : UncivGame() {
|
||||
discordUpdater.stopUpdates()
|
||||
super.dispose()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ internal object DesktopLauncher {
|
||||
}
|
||||
|
||||
// HardenGdxAudio extends Lwjgl3Application, and the Lwjgl3Application constructor runs as long as the game runs
|
||||
HardenGdxAudio(DesktopGame(config), config)
|
||||
HardenGdxAudio(DesktopGame(config, null), config)
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.unciv.app.desktop
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.files.PlatformSaverLoader
|
||||
import java.awt.Component
|
||||
import java.awt.EventQueue
|
||||
@ -57,7 +57,7 @@ class DesktopSaverLoader : PlatformSaverLoader {
|
||||
try {
|
||||
val fileChooser = JFileChooser().apply fileChooser@{
|
||||
if (suggestedLocation == null) {
|
||||
currentDirectory = Gdx.files.local("").file()
|
||||
currentDirectory = UncivGame.Current.files.getDataFolder().file()
|
||||
} else {
|
||||
selectedFile = File(suggestedLocation)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Taken from https://github.com/TomGrill/gdx-testing
|
||||
package com.unciv.testing
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.BaseRuleset
|
||||
@ -40,7 +39,7 @@ class BasicTests {
|
||||
@Test
|
||||
fun gamePngExists() {
|
||||
Assert.assertTrue("This test will only pass when the game.png exists",
|
||||
Gdx.files.local("").list().any { it.name().endsWith(".png") })
|
||||
UncivGame.Current.files.getDataFolder().list().any { it.name().endsWith(".png") })
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -91,7 +90,7 @@ class BasicTests {
|
||||
|
||||
@Test
|
||||
fun baseRulesetHasNoBugs() {
|
||||
for (baseRuleset in BaseRuleset.values()) {
|
||||
for (baseRuleset in BaseRuleset.entries) {
|
||||
val ruleset = RulesetCache[baseRuleset.fullName]!!
|
||||
val modCheck = ruleset.checkModLinks()
|
||||
if (modCheck.isNotOK())
|
||||
@ -103,7 +102,7 @@ class BasicTests {
|
||||
@Test
|
||||
fun uniqueTypesHaveNoUnknownParameters() {
|
||||
var noUnknownParameters = true
|
||||
for (uniqueType in UniqueType.values()) {
|
||||
for (uniqueType in UniqueType.entries) {
|
||||
if (uniqueType.getDeprecationAnnotation()!=null) continue
|
||||
for (entry in uniqueType.parameterTypeMap.withIndex()) {
|
||||
for (paramType in entry.value) {
|
||||
@ -121,7 +120,7 @@ class BasicTests {
|
||||
@Test
|
||||
fun allUniqueTypesHaveAtLeastOneTarget() {
|
||||
var allOK = true
|
||||
for (uniqueType in UniqueType.values()) {
|
||||
for (uniqueType in UniqueType.entries) {
|
||||
if (uniqueType.targetTypes.isEmpty()) {
|
||||
debug("%s has no targets.", uniqueType.name)
|
||||
allOK = false
|
||||
@ -136,7 +135,7 @@ class BasicTests {
|
||||
var allOK = true
|
||||
for (unit in units) {
|
||||
for (unique in unit.uniques) {
|
||||
if (!UniqueType.values().any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
if (!UniqueType.entries.any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
debug("%s: %s", unit.name, unique)
|
||||
allOK = false
|
||||
}
|
||||
@ -151,7 +150,7 @@ class BasicTests {
|
||||
var allOK = true
|
||||
for (building in buildings) {
|
||||
for (unique in building.uniques) {
|
||||
if (!UniqueType.values().any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
if (!UniqueType.entries.any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
debug("%s: %s", building.name, unique)
|
||||
allOK = false
|
||||
}
|
||||
@ -166,7 +165,7 @@ class BasicTests {
|
||||
var allOK = true
|
||||
for (promotion in promotions) {
|
||||
for (unique in promotion.uniques) {
|
||||
if (!UniqueType.values().any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
if (!UniqueType.entries.any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
debug("%s: %s", promotion.name, unique)
|
||||
allOK = false
|
||||
}
|
||||
@ -181,7 +180,7 @@ class BasicTests {
|
||||
var allOK = true
|
||||
for (policy in policies) {
|
||||
for (unique in policy.uniques) {
|
||||
if (!UniqueType.values().any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
if (!UniqueType.entries.any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
println("${policy.name}: $unique")
|
||||
allOK = false
|
||||
}
|
||||
@ -197,7 +196,7 @@ class BasicTests {
|
||||
var allOK = true
|
||||
for (belief in beliefs) {
|
||||
for (unique in belief.uniques) {
|
||||
if (!UniqueType.values().any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
if (!UniqueType.entries.any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
println("${belief.name}: $unique")
|
||||
allOK = false
|
||||
}
|
||||
@ -212,7 +211,7 @@ class BasicTests {
|
||||
var allOK = true
|
||||
for (era in eras) {
|
||||
for (unique in era.uniques) {
|
||||
if (!UniqueType.values().any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
if (!UniqueType.entries.any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
println("${era.name}: $unique")
|
||||
allOK = false
|
||||
}
|
||||
@ -227,7 +226,7 @@ class BasicTests {
|
||||
var allOK = true
|
||||
for (reward in ruinRewards) {
|
||||
for (unique in reward.uniques) {
|
||||
if (!UniqueType.values().any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
if (!UniqueType.entries.any { it.placeholderText == unique.getPlaceholderText() }) {
|
||||
println("${reward.name}: $unique")
|
||||
allOK = false
|
||||
}
|
||||
@ -239,7 +238,7 @@ class BasicTests {
|
||||
@Test
|
||||
fun allDeprecatedUniqueTypesHaveReplacewithThatMatchesOtherType() {
|
||||
var allOK = true
|
||||
for (uniqueType in UniqueType.values()) {
|
||||
for (uniqueType in UniqueType.entries) {
|
||||
val deprecationAnnotation = uniqueType.getDeprecationAnnotation() ?: continue
|
||||
|
||||
val uniquesToCheck = deprecationAnnotation.replaceWith.expression.split("\", \"", Constants.uniqueOrDelimiter)
|
||||
@ -308,17 +307,17 @@ class BasicTests {
|
||||
|
||||
private fun statMathRunner(iterations: Int): Stats {
|
||||
val random = Random(42)
|
||||
val statCount = Stat.values().size
|
||||
val statCount = Stat.entries.size
|
||||
val stats = Stats()
|
||||
|
||||
repeat(iterations) {
|
||||
val value: Float = random.nextDouble(-10.0, 10.0).toFloat()
|
||||
stats.add( Stats(gold = value) )
|
||||
stats.forEach {
|
||||
val stat = Stat.values()[(it.key.ordinal + random.nextInt(1,statCount)).rem(statCount)]
|
||||
val stat = Stat.entries[(it.key.ordinal + random.nextInt(1,statCount)).rem(statCount)]
|
||||
stats.add(stat, -it.value)
|
||||
}
|
||||
val stat = Stat.values()[random.nextInt(statCount)]
|
||||
val stat = Stat.entries[random.nextInt(statCount)]
|
||||
stats.add(stat, stats.times(4)[stat])
|
||||
stats.timesInPlace(0.8f)
|
||||
if (abs(stats.values.maxOrNull()!!) > 1000000f)
|
||||
|
Loading…
x
Reference in New Issue
Block a user