mirror of
https://github.com/yairm210/Unciv.git
synced 2025-10-04 09:26:16 -04:00
Fix TileSet mods can lock user out (#9023)
This commit is contained in:
parent
13f4dd0756
commit
be69f8b52d
@ -189,7 +189,9 @@ open class UncivGame(val isConsoleMode: Boolean = false) : Game(), PlatformSpeci
|
|||||||
|
|
||||||
ImageGetter.resetAtlases()
|
ImageGetter.resetAtlases()
|
||||||
ImageGetter.setNewRuleset(ImageGetter.ruleset) // This needs to come after the settings, since we may have default visual mods
|
ImageGetter.setNewRuleset(ImageGetter.ruleset) // This needs to come after the settings, since we may have default visual mods
|
||||||
if (settings.tileSet !in ImageGetter.getAvailableTilesets()) { // If one of the tilesets is no longer available, default back
|
val availableTileSets = ImageGetter.getAvailableTilesets().toSet()
|
||||||
|
.intersect(TileSetCache.getAvailableTilesets().toSet())
|
||||||
|
if (settings.tileSet !in availableTileSets) { // If the configured tileset is no longer available, default back
|
||||||
settings.tileSet = Constants.defaultTileset
|
settings.tileSet = Constants.defaultTileset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,4 +80,20 @@ object TileSetCache : HashMap<String, TileSet>() {
|
|||||||
set(name, tileset)
|
set(name, tileset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Determines potentially available TileSets - by scanning for TileSet jsons.
|
||||||
|
*
|
||||||
|
* Available before initialization finishes.
|
||||||
|
* To get more reliable info, either wait until `this` is fully initialized,
|
||||||
|
* or intersect with [ImageGetter.getAvailableTilesets]
|
||||||
|
*/
|
||||||
|
fun getAvailableTilesets() = sequence<FileHandle> {
|
||||||
|
yieldAll(FileHandle("jsons/TileSets").list().asIterable())
|
||||||
|
for (modFolder in FileHandle("mods").list()) {
|
||||||
|
if (!modFolder.isDirectory || modFolder.name().startsWith('.'))
|
||||||
|
continue
|
||||||
|
yieldAll(modFolder.child("jsons/TileSets").list().asIterable())
|
||||||
|
}
|
||||||
|
}.filter { it.exists() }
|
||||||
|
.map { it.nameWithoutExtension().removeSuffix("Config") }
|
||||||
}
|
}
|
||||||
|
@ -448,8 +448,16 @@ object ImageGetter {
|
|||||||
|
|
||||||
fun getAvailableSkins() = ninePatchDrawables.keys.asSequence().map { it.split("/")[1] }.distinct()
|
fun getAvailableSkins() = ninePatchDrawables.keys.asSequence().map { it.split("/")[1] }.distinct()
|
||||||
|
|
||||||
fun getAvailableTilesets() = textureRegionDrawables.keys.asSequence().filter { it.startsWith("TileSets") && !it.contains("/Units/") }
|
/** Determines available TileSets from the currently loaded Texture paths.
|
||||||
.map { it.split("/")[1] }.distinct()
|
*
|
||||||
|
* Note [TileSetCache] will not necessarily load all of them, e.g. if a Mod fails
|
||||||
|
* to provide a config json for a graphic with a Tileset path.
|
||||||
|
*
|
||||||
|
* Intersect with [TileSetCache.getAvailableTilesets] for a more reliable answer
|
||||||
|
*/
|
||||||
|
fun getAvailableTilesets() = textureRegionDrawables.keys.asSequence()
|
||||||
|
.filter { it.startsWith("TileSets") && !it.contains("/Units/") }
|
||||||
|
.map { it.split("/")[1] }.distinct()
|
||||||
|
|
||||||
fun getAvailableUnitsets() = textureRegionDrawables.keys.asSequence().filter { it.contains("/Units/") }
|
fun getAvailableUnitsets() = textureRegionDrawables.keys.asSequence().filter { it.contains("/Units/") }
|
||||||
.map { it.split("/")[1] }.distinct()
|
.map { it.split("/")[1] }.distinct()
|
||||||
|
@ -21,6 +21,7 @@ import com.unciv.models.metadata.BaseRuleset
|
|||||||
import com.unciv.models.metadata.GameSetupInfo
|
import com.unciv.models.metadata.GameSetupInfo
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
|
import com.unciv.models.tilesets.TileSetCache
|
||||||
import com.unciv.ui.components.AutoScrollPane
|
import com.unciv.ui.components.AutoScrollPane
|
||||||
import com.unciv.ui.components.KeyCharAndCode
|
import com.unciv.ui.components.KeyCharAndCode
|
||||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||||
@ -51,6 +52,7 @@ import com.unciv.ui.screens.worldscreen.WorldScreen
|
|||||||
import com.unciv.ui.screens.worldscreen.mainmenu.WorldScreenMenuPopup
|
import com.unciv.ui.screens.worldscreen.mainmenu.WorldScreenMenuPopup
|
||||||
import com.unciv.utils.concurrency.Concurrency
|
import com.unciv.utils.concurrency.Concurrency
|
||||||
import com.unciv.utils.concurrency.launchOnGLThread
|
import com.unciv.utils.concurrency.launchOnGLThread
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
||||||
@ -104,51 +106,14 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize {
|
|||||||
// will not exist unless we reset the ruleset and images
|
// will not exist unless we reset the ruleset and images
|
||||||
ImageGetter.ruleset = RulesetCache.getVanillaRuleset()
|
ImageGetter.ruleset = RulesetCache.getVanillaRuleset()
|
||||||
|
|
||||||
Concurrency.run("ShowMapBackground") {
|
// This is an extreme safeguard - should an invalid settings.tileSet ever make it past the
|
||||||
var scale = 1f
|
// guard in UncivGame.create, simply omit the background so the user can at least get to options
|
||||||
var mapWidth = stage.width / TileGroupMap.groupHorizontalAdvance
|
// (let him crash when loading a game but avoid locking him out entirely)
|
||||||
var mapHeight = stage.height / TileGroupMap.groupSize
|
if (game.settings.tileSet in TileSetCache)
|
||||||
if (mapWidth * mapHeight > 3000f) { // 3000 as max estimated number of tiles is arbitrary (we had typically 721 before)
|
Concurrency.run("ShowMapBackground") {
|
||||||
scale = mapWidth * mapHeight / 3000f
|
showMapBackground()
|
||||||
mapWidth /= scale
|
|
||||||
mapHeight /= scale
|
|
||||||
scale = min(scale, 20f)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val baseRuleset = RulesetCache.getVanillaRuleset()
|
|
||||||
easterEggRuleset = EasterEggRulesets.getTodayEasterEggRuleset()?.let {
|
|
||||||
RulesetCache.getComplexRuleset(baseRuleset, listOf(it))
|
|
||||||
}
|
|
||||||
val mapRuleset = if (game.settings.enableEasterEggs) easterEggRuleset ?: baseRuleset else baseRuleset
|
|
||||||
|
|
||||||
val newMap = MapGenerator(mapRuleset)
|
|
||||||
.generateMap(MapParameters().apply {
|
|
||||||
shape = MapShape.rectangular
|
|
||||||
mapSize = MapSizeNew(MapSize.Small)
|
|
||||||
type = MapType.pangaea
|
|
||||||
temperatureExtremeness = .7f
|
|
||||||
waterThreshold = -0.1f // mainly land, gets about 30% water
|
|
||||||
modifyForEasterEgg()
|
|
||||||
})
|
|
||||||
|
|
||||||
launchOnGLThread { // for GL context
|
|
||||||
ImageGetter.setNewRuleset(mapRuleset)
|
|
||||||
val mapHolder = EditorMapHolder(
|
|
||||||
this@MainMenuScreen,
|
|
||||||
newMap
|
|
||||||
) {}
|
|
||||||
mapHolder.setScale(scale)
|
|
||||||
backgroundTable.addAction(Actions.sequence(
|
|
||||||
Actions.fadeOut(0f),
|
|
||||||
Actions.run {
|
|
||||||
backgroundTable.addActor(mapHolder)
|
|
||||||
mapHolder.center(backgroundTable)
|
|
||||||
},
|
|
||||||
Actions.fadeIn(0.3f)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val column1 = Table().apply { defaults().pad(10f).fillX() }
|
val column1 = Table().apply { defaults().pad(10f).fillX() }
|
||||||
val column2 = if (singleColumn) column1 else Table().apply { defaults().pad(10f).fillX() }
|
val column2 = if (singleColumn) column1 else Table().apply { defaults().pad(10f).fillX() }
|
||||||
|
|
||||||
@ -220,6 +185,50 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize {
|
|||||||
stage.addActor(helpButton)
|
stage.addActor(helpButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CoroutineScope.showMapBackground() {
|
||||||
|
var scale = 1f
|
||||||
|
var mapWidth = stage.width / TileGroupMap.groupHorizontalAdvance
|
||||||
|
var mapHeight = stage.height / TileGroupMap.groupSize
|
||||||
|
if (mapWidth * mapHeight > 3000f) { // 3000 as max estimated number of tiles is arbitrary (we had typically 721 before)
|
||||||
|
scale = mapWidth * mapHeight / 3000f
|
||||||
|
mapWidth /= scale
|
||||||
|
mapHeight /= scale
|
||||||
|
scale = min(scale, 20f)
|
||||||
|
}
|
||||||
|
|
||||||
|
val baseRuleset = RulesetCache.getVanillaRuleset()
|
||||||
|
easterEggRuleset = EasterEggRulesets.getTodayEasterEggRuleset()?.let {
|
||||||
|
RulesetCache.getComplexRuleset(baseRuleset, listOf(it))
|
||||||
|
}
|
||||||
|
val mapRuleset = if (game.settings.enableEasterEggs) easterEggRuleset ?: baseRuleset else baseRuleset
|
||||||
|
|
||||||
|
val newMap = MapGenerator(mapRuleset)
|
||||||
|
.generateMap(MapParameters().apply {
|
||||||
|
shape = MapShape.rectangular
|
||||||
|
mapSize = MapSizeNew(MapSize.Small)
|
||||||
|
type = MapType.pangaea
|
||||||
|
temperatureExtremeness = 0.7f
|
||||||
|
waterThreshold = -0.1f // mainly land, gets about 30% water
|
||||||
|
modifyForEasterEgg()
|
||||||
|
})
|
||||||
|
|
||||||
|
launchOnGLThread { // for GL context
|
||||||
|
ImageGetter.setNewRuleset(mapRuleset)
|
||||||
|
val mapHolder = EditorMapHolder(
|
||||||
|
this@MainMenuScreen,
|
||||||
|
newMap
|
||||||
|
) {}
|
||||||
|
mapHolder.setScale(scale)
|
||||||
|
backgroundTable.addAction(Actions.sequence(
|
||||||
|
Actions.fadeOut(0f),
|
||||||
|
Actions.run {
|
||||||
|
backgroundTable.addActor(mapHolder)
|
||||||
|
mapHolder.center(backgroundTable)
|
||||||
|
},
|
||||||
|
Actions.fadeIn(0.3f)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun resumeGame() {
|
private fun resumeGame() {
|
||||||
if (GUI.isWorldLoaded()) {
|
if (GUI.isWorldLoaded()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user