mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 14:24:43 -04:00
Refactor: Change UncivGame.worldScreen and UncivGame.gameInfo to be of nullable type (#7114)
* Refactor: Make Popups work on Stages instead of BaseScreens * Refactor: Change UncivGame.worldScreen and UncivGame.gameInfo to be of nullable type * Fix "Resume" game loading not fully handling exceptions * Fix one missed refactoring * Refactor: remove useless postRunnable
This commit is contained in:
parent
72b197fdc3
commit
9008d242a3
@ -70,13 +70,13 @@ open class AndroidLauncher : AndroidApplication() {
|
||||
|
||||
override fun onPause() {
|
||||
if (UncivGame.isCurrentInitialized()
|
||||
&& UncivGame.Current.isGameInfoInitialized()
|
||||
&& UncivGame.Current.gameInfo != null
|
||||
&& UncivGame.Current.settings.multiplayer.turnCheckerEnabled
|
||||
&& UncivGame.Current.gameSaver.getMultiplayerSaves().any()
|
||||
) {
|
||||
MultiplayerTurnCheckWorker.startTurnChecker(
|
||||
applicationContext, UncivGame.Current.gameSaver,
|
||||
UncivGame.Current.gameInfo, UncivGame.Current.settings.multiplayer
|
||||
UncivGame.Current.gameInfo!!, UncivGame.Current.settings.multiplayer
|
||||
)
|
||||
}
|
||||
super.onPause()
|
||||
|
@ -198,7 +198,7 @@ class MainMenuScreen: BaseScreen() {
|
||||
|
||||
|
||||
private fun resumeGame() {
|
||||
val curWorldScreen = game.getWorldScreenOrNull()
|
||||
val curWorldScreen = game.worldScreen
|
||||
if (curWorldScreen != null) {
|
||||
game.resetToWorldScreen()
|
||||
curWorldScreen.popups.filterIsInstance(WorldScreenMenuPopup::class.java).forEach(Popup::close)
|
||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.Application
|
||||
import com.badlogic.gdx.Game
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.logic.GameInfo
|
||||
@ -22,13 +23,13 @@ import com.unciv.ui.audio.SoundPlayer
|
||||
import com.unciv.ui.crashhandling.closeExecutors
|
||||
import com.unciv.ui.crashhandling.launchCrashHandling
|
||||
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
|
||||
import com.unciv.ui.crashhandling.wrapCrashHandlingUnit
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.multiplayer.LoadDeepLinkScreen
|
||||
import com.unciv.ui.multiplayer.MultiplayerHelpers
|
||||
import com.unciv.ui.popup.Popup
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.extensions.center
|
||||
import com.unciv.ui.crashhandling.wrapCrashHandlingUnit
|
||||
import com.unciv.ui.worldscreen.PlayerReadyScreen
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
import com.unciv.utils.debug
|
||||
@ -49,8 +50,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
private val audioExceptionHelper = parameters.audioExceptionHelper
|
||||
|
||||
var deepLinkedMultiplayerGame: String? = null
|
||||
lateinit var gameInfo: GameInfo
|
||||
fun isGameInfoInitialized() = this::gameInfo.isInitialized
|
||||
var gameInfo: GameInfo? = null
|
||||
lateinit var settings: GameSettings
|
||||
lateinit var musicController: MusicController
|
||||
lateinit var onlineMultiplayer: OnlineMultiplayer
|
||||
@ -70,9 +70,8 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
*/
|
||||
var simulateUntilTurnForDebug: Int = 0
|
||||
|
||||
lateinit var worldScreen: WorldScreen
|
||||
var worldScreen: WorldScreen? = null
|
||||
private set
|
||||
fun getWorldScreenOrNull() = if (this::worldScreen.isInitialized) worldScreen else null
|
||||
|
||||
var isInitialized = false
|
||||
|
||||
@ -105,7 +104,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
* - Font (hence Fonts.resetFont() inside setSkin())
|
||||
*/
|
||||
settings = gameSaver.getGeneralSettings() // needed for the screen
|
||||
screen = LoadingScreen() // NOT dependent on any atlas or skin
|
||||
setScreen(LoadingScreen()) // NOT dependent on any atlas or skin
|
||||
GameSounds.init()
|
||||
musicController = MusicController() // early, but at this point does only copy volume from settings
|
||||
audioExceptionHelper?.installHooks(
|
||||
@ -152,49 +151,66 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
}
|
||||
}
|
||||
|
||||
fun loadGame(gameInfo: GameInfo) {
|
||||
fun loadGame(gameInfo: GameInfo): WorldScreen {
|
||||
this.gameInfo = gameInfo
|
||||
ImageGetter.setNewRuleset(gameInfo.ruleSet)
|
||||
// Clone the mod list and add the base ruleset to it
|
||||
val fullModList = gameInfo.gameParameters.getModsAndBaseRuleset()
|
||||
musicController.setModList(fullModList)
|
||||
Gdx.input.inputProcessor = null // Since we will set the world screen when we're ready,
|
||||
if (gameInfo.civilizations.count { it.playerType == PlayerType.Human } > 1 && !gameInfo.gameParameters.isOnlineMultiplayer)
|
||||
setScreen(PlayerReadyScreen(gameInfo, gameInfo.getPlayerToViewAs()))
|
||||
val worldScreen = WorldScreen(gameInfo, gameInfo.getPlayerToViewAs())
|
||||
val newScreen = if (gameInfo.civilizations.count { it.playerType == PlayerType.Human } > 1 && !gameInfo.gameParameters.isOnlineMultiplayer)
|
||||
PlayerReadyScreen(worldScreen)
|
||||
else {
|
||||
resetToWorldScreen(WorldScreen(gameInfo, gameInfo.getPlayerToViewAs()))
|
||||
worldScreen
|
||||
}
|
||||
}
|
||||
|
||||
fun setScreen(screen: BaseScreen) {
|
||||
val oldScreen = getScreen()
|
||||
Gdx.input.inputProcessor = screen.stage
|
||||
super.setScreen(screen)
|
||||
if (oldScreen != getWorldScreenOrNull()) oldScreen.dispose()
|
||||
setScreen(newScreen)
|
||||
return worldScreen
|
||||
}
|
||||
|
||||
/**
|
||||
* If called with null [newWorldScreen], disposes of the current screen and sets it to the current stored world screen.
|
||||
* If the current screen is already the world screen, the only thing that happens is that the world screen updates.
|
||||
* Sets the screen of the game and automatically disposes the old screen as long as it isn't the world screen.
|
||||
*
|
||||
* @param screen must be a subclass of [BaseScreen].
|
||||
*/
|
||||
fun resetToWorldScreen(newWorldScreen: WorldScreen? = null) {
|
||||
if (newWorldScreen != null) {
|
||||
debug("Reset to new WorldScreen, gameId: %s, turn: %s, curCiv: %s",
|
||||
newWorldScreen.gameInfo.gameId, newWorldScreen.gameInfo.turns, newWorldScreen.gameInfo.currentPlayer)
|
||||
val oldWorldScreen = getWorldScreenOrNull()
|
||||
worldScreen = newWorldScreen
|
||||
// setScreen disposes the current screen, but the old world screen is not the current screen, so need to dispose here
|
||||
if (screen != oldWorldScreen) {
|
||||
oldWorldScreen?.dispose()
|
||||
}
|
||||
override fun setScreen(screen: Screen) {
|
||||
if (screen !is BaseScreen) throw IllegalArgumentException("Call to setScreen with screen that does not inherit BaseScreen: " + screen.javaClass.simpleName)
|
||||
setScreen(screen)
|
||||
}
|
||||
|
||||
override fun getScreen(): BaseScreen? {
|
||||
val curScreen = super.getScreen()
|
||||
return if (curScreen == null) { null } else { curScreen as BaseScreen }
|
||||
}
|
||||
|
||||
/** Sets the screen of the game and automatically [disposes][Screen.dispose] the old screen as long as it isn't the world screen. */
|
||||
fun setScreen(newScreen: BaseScreen) {
|
||||
if (newScreen is WorldScreen) {
|
||||
debug(
|
||||
"Setting new world screen: gameId: %s, turn: %s, curCiv: %s",
|
||||
newScreen.gameInfo.gameId, newScreen.gameInfo.turns, newScreen.gameInfo.currentPlayer
|
||||
)
|
||||
if (newScreen != worldScreen) worldScreen?.dispose()
|
||||
worldScreen = newScreen
|
||||
newScreen.shouldUpdate = true
|
||||
Gdx.graphics.requestRendering()
|
||||
} else {
|
||||
val oldWorldScreen = getWorldScreenOrNull()!!
|
||||
debug("Reset to old WorldScreen, gameId: %s, turn: %s, curCiv: %s",
|
||||
oldWorldScreen.gameInfo.gameId, oldWorldScreen.gameInfo.turns, oldWorldScreen.gameInfo.currentPlayer)
|
||||
debug("Setting new screen: %s", newScreen)
|
||||
}
|
||||
setScreen(worldScreen)
|
||||
worldScreen.shouldUpdate = true // This can set the screen to the policy picker or tech picker screen, so the input processor must come before
|
||||
Gdx.graphics.requestRendering()
|
||||
|
||||
val oldScreen = screen
|
||||
Gdx.input.inputProcessor = newScreen.stage
|
||||
super.setScreen(newScreen) // This can set the screen to the policy picker or tech picker screen, so the input processor must be set before
|
||||
if (oldScreen !is WorldScreen) { // we want to keep the world screen around, because it's expensive to re-create it
|
||||
oldScreen?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the game to the stored world screen and automatically [disposes][Screen.dispose] the old screen.
|
||||
*/
|
||||
fun resetToWorldScreen() {
|
||||
setScreen(worldScreen!!)
|
||||
}
|
||||
|
||||
private fun tryLoadDeepLinkedGame() = launchCrashHandling("LoadDeepLinkedGame") {
|
||||
@ -233,7 +249,8 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
if (isGameInfoInitialized()) gameSaver.autoSave(this.gameInfo)
|
||||
val curGameInfo = gameInfo
|
||||
if (curGameInfo != null) gameSaver.autoSave(curGameInfo)
|
||||
musicController.pause()
|
||||
super.pause()
|
||||
}
|
||||
@ -252,14 +269,15 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
if (::musicController.isInitialized) musicController.gracefulShutdown() // Do allow fade-out
|
||||
closeExecutors()
|
||||
|
||||
if (isGameInfoInitialized()) {
|
||||
val curGameInfo = gameInfo
|
||||
if (curGameInfo != null) {
|
||||
val autoSaveJob = gameSaver.autoSaveJob
|
||||
if (autoSaveJob != null && autoSaveJob.isActive) {
|
||||
// auto save is already in progress (e.g. started by onPause() event)
|
||||
// let's allow it to finish and do not try to autosave second time
|
||||
autoSaveJob.join()
|
||||
} else {
|
||||
gameSaver.autoSaveSingleThreaded(gameInfo) // NO new thread
|
||||
gameSaver.autoSaveSingleThreaded(curGameInfo) // NO new thread
|
||||
}
|
||||
}
|
||||
settings.save()
|
||||
@ -277,10 +295,15 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the [worldScreen] if it is the currently active screen of the game */
|
||||
fun getWorldScreenIfActive(): WorldScreen? {
|
||||
return if (screen == worldScreen) worldScreen else null
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var Current: UncivGame
|
||||
fun isCurrentInitialized() = this::Current.isInitialized
|
||||
fun isCurrentGame(gameId: String): Boolean = isCurrentInitialized() && Current.isGameInfoInitialized() && Current.gameInfo.gameId == gameId
|
||||
fun isCurrentGame(gameId: String): Boolean = isCurrentInitialized() && Current.gameInfo != null && Current.gameInfo!!.gameId == gameId
|
||||
fun isDeepLinkedGameLoading() = isCurrentInitialized() && Current.deepLinkedMultiplayerGame != null
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ object Battle {
|
||||
|
||||
// CS friendship from killing barbarians
|
||||
if (defeatedUnit.matchesCategory("Barbarian") && defeatedUnit.matchesCategory("Military") && civUnit.getCivInfo().isMajorCiv()) {
|
||||
for (cityState in UncivGame.Current.gameInfo.getAliveCityStates()) {
|
||||
for (cityState in UncivGame.Current.gameInfo!!.getAliveCityStates()) {
|
||||
if (civUnit.getCivInfo().knows(cityState) && defeatedUnit.unit.threatensCiv(cityState)) {
|
||||
cityState.cityStateFunctions.threateningBarbarianKilledBy(civUnit.getCivInfo())
|
||||
}
|
||||
@ -216,7 +216,7 @@ object Battle {
|
||||
}
|
||||
|
||||
// CS war with major pseudo-quest
|
||||
for (cityState in UncivGame.Current.gameInfo.getAliveCityStates()) {
|
||||
for (cityState in UncivGame.Current.gameInfo!!.getAliveCityStates()) {
|
||||
cityState.questManager.militaryUnitKilledBy(civUnit.getCivInfo(), defeatedUnit.getCivInfo())
|
||||
}
|
||||
}
|
||||
|
@ -663,8 +663,8 @@ class CityConstructions {
|
||||
cityInfo.cityStats.update()
|
||||
cityInfo.civInfo.updateDetailedCivResources()
|
||||
// If bought the worldscreen will not have been marked to update, and the new improvement won't show until later...
|
||||
if (UncivGame.isCurrentInitialized())
|
||||
UncivGame.Current.worldScreen.shouldUpdate = true
|
||||
if (UncivGame.isCurrentInitialized() && UncivGame.Current.worldScreen != null)
|
||||
UncivGame.Current.worldScreen!!.shouldUpdate = true
|
||||
}
|
||||
|
||||
/** Support for [UniqueType.CreatesOneImprovement]:
|
||||
|
@ -155,8 +155,10 @@ class CityInfoConquestFunctions(val city: CityInfo){
|
||||
city.isPuppet = false
|
||||
city.cityConstructions.inProgressConstructions.clear() // undo all progress of the previous civ on units etc.
|
||||
city.cityStats.update()
|
||||
if (!UncivGame.Current.consoleMode)
|
||||
UncivGame.Current.worldScreen.shouldUpdate = true
|
||||
val worldScreen = UncivGame.Current.worldScreen
|
||||
if (!UncivGame.Current.consoleMode && worldScreen != null) {
|
||||
worldScreen.shouldUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun diplomaticRepercussionsForConqueringCity(oldCiv: CivilizationInfo, conqueringCiv: CivilizationInfo) {
|
||||
|
@ -62,8 +62,11 @@ class CivilizationInfo {
|
||||
/** Returns an instance of WorkerAutomation valid for the duration of the current turn
|
||||
* This instance carries cached data common for all Workers of this civ */
|
||||
fun getWorkerAutomation(): WorkerAutomation {
|
||||
val currentTurn = if (UncivGame.Current.isInitialized && UncivGame.Current.isGameInfoInitialized())
|
||||
UncivGame.Current.gameInfo.turns else 0
|
||||
val currentTurn = if (UncivGame.Current.isInitialized && UncivGame.Current.gameInfo != null) {
|
||||
UncivGame.Current.gameInfo!!.turns
|
||||
} else {
|
||||
0
|
||||
}
|
||||
if (workerAutomationCache == null || workerAutomationCache!!.cachedForTurn != currentTurn)
|
||||
workerAutomationCache = WorkerAutomation(this, currentTurn)
|
||||
return workerAutomationCache!!
|
||||
|
@ -56,7 +56,7 @@ interface NotificationAction {
|
||||
}
|
||||
|
||||
/** A notification action that cycles through tiles.
|
||||
*
|
||||
*
|
||||
* Constructors accept any kind of [Vector2] collection, including [Iterable], [Sequence], `vararg`.
|
||||
* `varargs` allows nulls which are ignored, a resulting empty list is allowed and equivalent to no [NotificationAction].
|
||||
*/
|
||||
|
@ -919,11 +919,11 @@ class AssignedQuest(val questName: String = "",
|
||||
when (questName) {
|
||||
QuestName.ClearBarbarianCamp.value -> {
|
||||
game.resetToWorldScreen()
|
||||
game.worldScreen.mapHolder.setCenterPosition(Vector2(data1.toFloat(), data2.toFloat()), selectUnit = false)
|
||||
game.worldScreen!!.mapHolder.setCenterPosition(Vector2(data1.toFloat(), data2.toFloat()), selectUnit = false)
|
||||
}
|
||||
QuestName.Route.value -> {
|
||||
game.resetToWorldScreen()
|
||||
game.worldScreen.mapHolder.setCenterPosition(gameInfo.getCivilization(assigner).getCapital()!!.location, selectUnit = false)
|
||||
game.worldScreen!!.mapHolder.setCenterPosition(gameInfo.getCivilization(assigner).getCapital()!!.location, selectUnit = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,8 +67,9 @@ class OnlineMultiplayer {
|
||||
}
|
||||
|
||||
private fun getCurrentGame(): OnlineMultiplayerGame? {
|
||||
if (UncivGame.isCurrentInitialized() && UncivGame.Current.isGameInfoInitialized()) {
|
||||
return getGameByGameId(UncivGame.Current.gameInfo.gameId)
|
||||
val gameInfo = UncivGame.Current.gameInfo
|
||||
if (gameInfo != null) {
|
||||
return getGameByGameId(gameInfo.gameId)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ import com.unciv.logic.trade.TradeType.TradeTypeNumberType
|
||||
data class TradeOffer(val name: String, val type: TradeType, var amount: Int = 1, var duration: Int) {
|
||||
|
||||
constructor(
|
||||
name: String,
|
||||
type: TradeType,
|
||||
amount: Int = 1,
|
||||
gameSpeed: GameSpeed = UncivGame.Current.gameInfo.gameParameters.gameSpeed
|
||||
name: String,
|
||||
type: TradeType,
|
||||
amount: Int = 1,
|
||||
gameSpeed: GameSpeed = UncivGame.Current.gameInfo!!.gameParameters.gameSpeed
|
||||
) : this(name, type, amount, duration = -1) {
|
||||
duration = when {
|
||||
type.isImmediate -> -1 // -1 for offers that are immediate (e.g. gold transfer)
|
||||
@ -22,7 +22,7 @@ data class TradeOffer(val name: String, val type: TradeType, var amount: Int = 1
|
||||
else -> (30 * gameSpeed.modifier).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
constructor() : this("", TradeType.Gold, duration = -1) // so that the json deserializer can work
|
||||
|
||||
@Suppress("CovariantEquals") // This is an overload, not an override of the built-in equals(Any?)
|
||||
@ -36,13 +36,13 @@ data class TradeOffer(val name: String, val type: TradeType, var amount: Int = 1
|
||||
var offerText = when(type){
|
||||
TradeType.WarDeclaration -> "Declare war on [$name]"
|
||||
TradeType.Introduction -> "Introduction to [$name]"
|
||||
TradeType.City -> UncivGame.Current.gameInfo.getCities().firstOrNull{ it.id == name }?.name ?: "Non-existent city"
|
||||
TradeType.City -> UncivGame.Current.gameInfo!!.getCities().firstOrNull{ it.id == name }?.name ?: "Non-existent city"
|
||||
else -> name
|
||||
}.tr()
|
||||
|
||||
if (type.numberType == TradeTypeNumberType.Simple || name == Constants.researchAgreement) offerText += " ($amount)"
|
||||
else if (type.numberType == TradeTypeNumberType.Gold) offerText += " ($amount)"
|
||||
|
||||
|
||||
if (duration > 0) offerText += "\n" + duration + Fonts.turn
|
||||
|
||||
if (untradable == 1) {
|
||||
|
@ -47,8 +47,9 @@ class Belief() : RulesetObject() {
|
||||
// private but potentially reusable, therefore not folded into getCivilopediaTextMatching
|
||||
private fun getBeliefsMatching(name: String, ruleset: Ruleset): Sequence<Belief> {
|
||||
if (!UncivGame.isCurrentInitialized()) return sequenceOf()
|
||||
if (!UncivGame.Current.isGameInfoInitialized()) return sequenceOf()
|
||||
if (!UncivGame.Current.gameInfo.isReligionEnabled()) return sequenceOf()
|
||||
val gameInfo = UncivGame.Current.gameInfo
|
||||
if (gameInfo == null) return sequenceOf()
|
||||
if (!gameInfo.isReligionEnabled()) return sequenceOf()
|
||||
return ruleset.beliefs.asSequence().map { it.value }
|
||||
.filter { belief -> belief.uniqueObjects.any { unique -> unique.params.any { it == name } }
|
||||
}
|
||||
|
@ -137,10 +137,11 @@ class Nation : RulesetObject() {
|
||||
|
||||
textList += FormattedLine("{Type}: {$cityStateType}", header = 4, color = cityStateType!!.color)
|
||||
|
||||
val era = if (UncivGame.isCurrentInitialized() && UncivGame.Current.isGameInfoInitialized())
|
||||
UncivGame.Current.gameInfo.currentPlayerCiv.getEra()
|
||||
else
|
||||
val era = if (UncivGame.isCurrentInitialized() && UncivGame.Current.gameInfo != null) {
|
||||
UncivGame.Current.gameInfo!!.currentPlayerCiv.getEra()
|
||||
} else {
|
||||
ruleset.eras.values.first()
|
||||
}
|
||||
var showResources = false
|
||||
|
||||
val friendBonus = era.friendBonus[cityStateType!!.name]
|
||||
@ -185,7 +186,7 @@ class Nation : RulesetObject() {
|
||||
when {
|
||||
building.uniqueTo != name -> continue
|
||||
building.hasUnique(UniqueType.HiddenFromCivilopedia) -> continue
|
||||
UncivGame.Current.isGameInfoInitialized() && !UncivGame.Current.gameInfo.isReligionEnabled() && building.hasUnique(UniqueType.HiddenWithoutReligion) -> continue // This seems consistent with existing behaviour of CivilopediaScreen's init.<locals>.shouldBeDisplayed(), and Technology().getEnabledUnits(). Otherwise there are broken links in the Civilopedia (E.G. to "Pyramid" and "Shrine", from "The Maya").
|
||||
UncivGame.Current.gameInfo != null && !UncivGame.Current.gameInfo!!.isReligionEnabled() && building.hasUnique(UniqueType.HiddenWithoutReligion) -> continue // This seems consistent with existing behaviour of CivilopediaScreen's init.<locals>.shouldBeDisplayed(), and Technology().getEnabledUnits(). Otherwise there are broken links in the Civilopedia (E.G. to "Pyramid" and "Shrine", from "The Maya").
|
||||
}
|
||||
yield(FormattedLine("{${building.name}} -", link=building.makeLink()))
|
||||
if (building.replaces != null && ruleset.buildings.containsKey(building.replaces!!)) {
|
||||
|
@ -51,7 +51,7 @@ class Technology: RulesetObject() {
|
||||
}
|
||||
}
|
||||
|
||||
val viewingCiv = UncivGame.Current.worldScreen.viewingCiv
|
||||
val viewingCiv = UncivGame.Current.worldScreen!!.viewingCiv
|
||||
val enabledUnits = getEnabledUnits(ruleset, viewingCiv)
|
||||
if (enabledUnits.any()) {
|
||||
lineList += "{Units enabled}: "
|
||||
@ -158,11 +158,11 @@ class Technology: RulesetObject() {
|
||||
ruleset.tileImprovements.values
|
||||
.asSequence()
|
||||
.filter { improvement ->
|
||||
improvement.uniqueObjects.any {
|
||||
unique -> unique.conditionals.any {
|
||||
(it.isOfType(UniqueType.ConditionalTech) || it.isOfType(UniqueType.ConditionalNoTech))
|
||||
&& it.params[0] == name
|
||||
}
|
||||
improvement.uniqueObjects.any {
|
||||
unique -> unique.conditionals.any {
|
||||
(it.isOfType(UniqueType.ConditionalTech) || it.isOfType(UniqueType.ConditionalNoTech))
|
||||
&& it.params[0] == name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ class Technology: RulesetObject() {
|
||||
}
|
||||
}
|
||||
|
||||
val viewingCiv = UncivGame.Current.getWorldScreenOrNull()?.viewingCiv
|
||||
val viewingCiv = UncivGame.Current.worldScreen?.viewingCiv
|
||||
val enabledUnits = getEnabledUnits(ruleset, viewingCiv)
|
||||
if (enabledUnits.any()) {
|
||||
lineList += FormattedLine()
|
||||
|
@ -176,9 +176,9 @@ class TileImprovement : RulesetStatsObject() {
|
||||
if (isAncientRuinsEquivalent() && ruleset.ruinRewards.isNotEmpty()) {
|
||||
val difficulty: String
|
||||
val religionEnabled: Boolean
|
||||
if (UncivGame.isCurrentInitialized() && UncivGame.Current.isGameInfoInitialized()) {
|
||||
difficulty = UncivGame.Current.gameInfo.gameParameters.difficulty
|
||||
religionEnabled = UncivGame.Current.gameInfo.isReligionEnabled()
|
||||
if (UncivGame.isCurrentInitialized() && UncivGame.Current.gameInfo != null) {
|
||||
difficulty = UncivGame.Current.gameInfo!!.gameParameters.difficulty
|
||||
religionEnabled = UncivGame.Current.gameInfo!!.isReligionEnabled()
|
||||
} else {
|
||||
difficulty = "Prince" // most factors == 1
|
||||
religionEnabled = true
|
||||
|
@ -38,7 +38,7 @@ class Simulation(
|
||||
for (civ in civilizations) {
|
||||
this.winRate[civ] = MutableInt(0)
|
||||
winRateByVictory[civ] = mutableMapOf()
|
||||
for (victory in UncivGame.Current.gameInfo.ruleSet.victories.keys)
|
||||
for (victory in UncivGame.Current.gameInfo!!.ruleSet.victories.keys)
|
||||
winRateByVictory[civ]!![victory] = MutableInt(0)
|
||||
}
|
||||
}
|
||||
@ -121,7 +121,7 @@ class Simulation(
|
||||
outString += "\n$civ:\n"
|
||||
val wins = winRate[civ]!!.value * 100 / max(steps.size, 1)
|
||||
outString += "$wins% total win rate \n"
|
||||
for (victory in UncivGame.Current.gameInfo.ruleSet.victories.keys) {
|
||||
for (victory in UncivGame.Current.gameInfo!!.ruleSet.victories.keys) {
|
||||
val winsVictory = winRateByVictory[civ]!![victory]!!.value * 100 / max(winRate[civ]!!.value, 1)
|
||||
outString += "$victory: $winsVictory% "
|
||||
}
|
||||
|
@ -250,22 +250,28 @@ object TranslationActiveModsCache {
|
||||
}
|
||||
private set
|
||||
|
||||
private fun getCurrentHash() = UncivGame.Current.run {
|
||||
if (isGameInfoInitialized())
|
||||
gameInfo.gameParameters.mods.hashCode() + gameInfo.gameParameters.baseRuleset.hashCode() * 31
|
||||
else translations.translationActiveMods.hashCode() * 31 * 31
|
||||
private fun getCurrentHash(): Int {
|
||||
val gameInfo = UncivGame.Current.gameInfo
|
||||
return if (gameInfo != null) {
|
||||
gameInfo.gameParameters.mods.hashCode() + gameInfo.gameParameters.baseRuleset.hashCode() * 31
|
||||
} else {
|
||||
UncivGame.Current.translations.translationActiveMods.hashCode() * 31 * 31
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCurrentSet() = UncivGame.Current.run {
|
||||
if (isGameInfoInitialized()) {
|
||||
val par = gameInfo.gameParameters
|
||||
// This is equivalent to (par.mods + par.baseRuleset) without the cast down to `Set`
|
||||
LinkedHashSet<String>(par.mods.size + 1).apply {
|
||||
addAll(par.mods)
|
||||
add(par.baseRuleset)
|
||||
}
|
||||
} else translations.translationActiveMods
|
||||
private fun getCurrentSet(): LinkedHashSet<String> {
|
||||
val gameInfo = UncivGame.Current.gameInfo
|
||||
return if (gameInfo != null) {
|
||||
val par = gameInfo.gameParameters
|
||||
// This is equivalent to (par.mods + par.baseRuleset) without the cast down to `Set`
|
||||
LinkedHashSet<String>(par.mods.size + 1).apply {
|
||||
addAll(par.mods)
|
||||
add(par.baseRuleset)
|
||||
}
|
||||
} else {
|
||||
UncivGame.Current.translations.translationActiveMods
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,6 +49,5 @@ class LanguagePickerScreen : PickerScreen() {
|
||||
|
||||
game.translations.tryReadTranslationForCurrentLanguage()
|
||||
game.setScreen(MainMenuScreen())
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ object SoundPlayer {
|
||||
val game = UncivGame.Current
|
||||
|
||||
// Get a hash covering all mods - quickly, so don't map, cast or copy the Set types
|
||||
val hash1 = if (game.isGameInfoInitialized()) game.gameInfo.ruleSet.mods.hashCode() else 0
|
||||
val gameInfo = game.gameInfo
|
||||
val hash1 = if (gameInfo != null) gameInfo.ruleSet.mods.hashCode() else 0
|
||||
val newHash = hash1.xor(game.settings.visualMods.hashCode())
|
||||
|
||||
// If hash the same, leave the cache as is
|
||||
@ -91,8 +92,10 @@ object SoundPlayer {
|
||||
// audiovisual mods after game mods but before built-in sounds
|
||||
// (these can already be available when game.gameInfo is not)
|
||||
val modList: MutableSet<String> = mutableSetOf()
|
||||
if (game.isGameInfoInitialized())
|
||||
modList.addAll(game.gameInfo.ruleSet.mods) // Sounds from game mods
|
||||
val gameInfo = game.gameInfo
|
||||
if (gameInfo != null) {
|
||||
modList.addAll(gameInfo.ruleSet.mods) // Sounds from game mods
|
||||
}
|
||||
modList.addAll(game.settings.visualMods)
|
||||
|
||||
// Translate the basic mod list into relative folder names so only sounds/name.ext needs
|
||||
|
@ -516,10 +516,9 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
||||
"Would you like to purchase [${construction.name}] for [$constructionBuyCost] [${stat.character}]?".tr()
|
||||
YesNoPopup(
|
||||
purchasePrompt,
|
||||
action = { purchaseConstruction(construction, stat, tile) },
|
||||
screen = cityScreen,
|
||||
restoreDefault = { cityScreen.update() }
|
||||
).open()
|
||||
) { purchaseConstruction(construction, stat, tile) }.open()
|
||||
}
|
||||
|
||||
/** This tests whether the buy button should be _shown_ */
|
||||
|
@ -138,17 +138,17 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(BaseScreen.skin)
|
||||
cityScreen.closeAllPopups()
|
||||
|
||||
YesNoPopup("Are you sure you want to sell this [${building.name}]?".tr(),
|
||||
{
|
||||
cityScreen.city.sellBuilding(building.name)
|
||||
cityScreen, {
|
||||
cityScreen.update()
|
||||
}, cityScreen,
|
||||
{
|
||||
cityScreen.update()
|
||||
}).open()
|
||||
}
|
||||
) {
|
||||
cityScreen.city.sellBuilding(building.name)
|
||||
cityScreen.update()
|
||||
}.open()
|
||||
}
|
||||
if (cityScreen.city.hasSoldBuildingThisTurn && !cityScreen.city.civInfo.gameInfo.gameParameters.godMode
|
||||
|| cityScreen.city.isPuppet
|
||||
|| !UncivGame.Current.worldScreen.isPlayersTurn || !cityScreen.canChangeState)
|
||||
|| !UncivGame.Current.worldScreen!!.isPlayersTurn || !cityScreen.canChangeState)
|
||||
sellBuildingButton.disable()
|
||||
}
|
||||
it.addSeparator()
|
||||
|
@ -81,7 +81,7 @@ class CityReligionInfoTable(
|
||||
icon.onClick {
|
||||
val newScreen = if (religion == iconName)
|
||||
EmpireOverviewScreen(civInfo, EmpireOverviewCategories.Religion.name, religion)
|
||||
else CivilopediaScreen(gameInfo.ruleSet, UncivGame.Current.screen as BaseScreen, CivilopediaCategories.Belief, religion )
|
||||
else CivilopediaScreen(gameInfo.ruleSet, UncivGame.Current.screen!!, CivilopediaCategories.Belief, religion )
|
||||
UncivGame.Current.setScreen(newScreen)
|
||||
}
|
||||
return icon
|
||||
|
@ -41,7 +41,7 @@ class CityScreen(
|
||||
}
|
||||
|
||||
/** Toggles or adds/removes all state changing buttons */
|
||||
val canChangeState = UncivGame.Current.worldScreen.canChangeState
|
||||
val canChangeState = UncivGame.Current.worldScreen!!.canChangeState
|
||||
|
||||
/** Toggle between Constructions and cityInfo (buildings, specialists etc. */
|
||||
var showConstructionsTable = true
|
||||
@ -402,8 +402,8 @@ class CityScreen(
|
||||
|
||||
fun exit() {
|
||||
game.resetToWorldScreen()
|
||||
game.worldScreen.mapHolder.setCenterPosition(city.location)
|
||||
game.worldScreen.bottomUnitTable.selectUnit()
|
||||
game.worldScreen!!.mapHolder.setCenterPosition(city.location)
|
||||
game.worldScreen!!.bottomUnitTable.selectUnit()
|
||||
}
|
||||
|
||||
fun page(delta: Int) {
|
||||
|
@ -112,15 +112,14 @@ class CityScreenTileTable(private val cityScreen: CityScreen): Table() {
|
||||
"Would you like to purchase [Tile] for [$goldCostOfTile] [${Stat.Gold.character}]?".tr()
|
||||
YesNoPopup(
|
||||
purchasePrompt,
|
||||
action = {
|
||||
SoundPlayer.play(UncivSound.Coin)
|
||||
city.expansion.buyTile(selectedTile)
|
||||
// preselect the next tile on city screen rebuild so bulk buying can go faster
|
||||
UncivGame.Current.setScreen(CityScreen(city, initSelectedTile = city.expansion.chooseNewTileToOwn()))
|
||||
},
|
||||
screen = cityScreen,
|
||||
restoreDefault = { cityScreen.update() }
|
||||
).open()
|
||||
) {
|
||||
SoundPlayer.play(UncivSound.Coin)
|
||||
city.expansion.buyTile(selectedTile)
|
||||
// preselect the next tile on city screen rebuild so bulk buying can go faster
|
||||
UncivGame.Current.setScreen(CityScreen(city, initSelectedTile = city.expansion.chooseNewTileToOwn()))
|
||||
}.open()
|
||||
}
|
||||
|
||||
/** This tests whether the buy button should be _shown_ */
|
||||
|
@ -81,7 +81,7 @@ class SpecialistAllocationTable(val cityScreen: CityScreen) : Table(BaseScreen.s
|
||||
cityInfo.cityStats.update()
|
||||
cityScreen.update()
|
||||
}
|
||||
if (cityInfo.population.getFreePopulation() == 0 || !UncivGame.Current.worldScreen.isPlayersTurn)
|
||||
if (cityInfo.population.getFreePopulation() == 0 || !UncivGame.Current.worldScreen!!.isPlayersTurn)
|
||||
assignButton.clear()
|
||||
return assignButton
|
||||
}
|
||||
@ -98,7 +98,7 @@ class SpecialistAllocationTable(val cityScreen: CityScreen) : Table(BaseScreen.s
|
||||
}
|
||||
|
||||
if (assignedSpecialists <= 0 || cityInfo.isPuppet) unassignButton.isVisible = false
|
||||
if (!UncivGame.Current.worldScreen.isPlayersTurn) unassignButton.clear()
|
||||
if (!UncivGame.Current.worldScreen!!.isPlayersTurn) unassignButton.clear()
|
||||
return unassignButton
|
||||
}
|
||||
|
||||
|
@ -183,10 +183,9 @@ class CivilopediaScreen(
|
||||
val imageSize = 50f
|
||||
onBackButtonClicked { game.setScreen(previousScreen) }
|
||||
|
||||
val religionEnabled = if (game.isGameInfoInitialized()) game.gameInfo.isReligionEnabled()
|
||||
else ruleset.beliefs.isNotEmpty()
|
||||
val victoryTypes = if (game.isGameInfoInitialized()) game.gameInfo.gameParameters.victoryTypes
|
||||
else listOf()
|
||||
val curGameInfo = game.gameInfo
|
||||
val religionEnabled = if (curGameInfo != null) curGameInfo.isReligionEnabled() else ruleset.beliefs.isNotEmpty()
|
||||
val victoryTypes = if (curGameInfo != null) curGameInfo.gameParameters.victoryTypes else emptyList()
|
||||
|
||||
fun shouldBeDisplayed(obj: IHasUniques): Boolean {
|
||||
return when {
|
||||
@ -254,7 +253,6 @@ class CivilopediaScreen(
|
||||
val goToGameButton = Constants.close.toTextButton()
|
||||
goToGameButton.onClick {
|
||||
game.setScreen(previousScreen)
|
||||
dispose()
|
||||
}
|
||||
|
||||
val topTable = Table()
|
||||
|
@ -164,10 +164,13 @@ class FormattedLine (
|
||||
}
|
||||
return ""
|
||||
}
|
||||
private fun getCurrentRuleset() = when {
|
||||
!UncivGame.isCurrentInitialized() -> Ruleset()
|
||||
!UncivGame.Current.isGameInfoInitialized() -> RulesetCache[BaseRuleset.Civ_V_Vanilla.fullName]!!
|
||||
else -> UncivGame.Current.gameInfo.ruleSet
|
||||
private fun getCurrentRuleset(): Ruleset {
|
||||
val gameInfo = UncivGame.Current.gameInfo
|
||||
return when {
|
||||
!UncivGame.isCurrentInitialized() -> Ruleset()
|
||||
gameInfo == null -> RulesetCache[BaseRuleset.Civ_V_Vanilla.fullName]!!
|
||||
else -> gameInfo.ruleSet
|
||||
}
|
||||
}
|
||||
private fun initNamesCategoryMap(ruleSet: Ruleset): HashMap<String, CivilopediaCategories> {
|
||||
//val startTime = System.nanoTime()
|
||||
|
@ -47,7 +47,7 @@ class CrashScreen(val exception: Throwable): BaseScreen() {
|
||||
|
||||
/** Qualified class name of the game screen that was active at the construction of this instance, or an error note. */
|
||||
private val lastScreenType = try {
|
||||
UncivGame.Current.screen::class.qualifiedName.toString()
|
||||
UncivGame.Current.screen!!::class.qualifiedName.toString()
|
||||
} catch (e: Throwable) {
|
||||
"Could not get screen type: $e"
|
||||
}
|
||||
@ -58,11 +58,11 @@ class CrashScreen(val exception: Throwable): BaseScreen() {
|
||||
|
||||
/** @return The last active save game serialized as a compressed string if any, or an informational note otherwise. */
|
||||
private fun tryGetSaveGame(): String {
|
||||
if (!UncivGame.isCurrentInitialized() || !UncivGame.Current.isGameInfoInitialized())
|
||||
if (!UncivGame.isCurrentInitialized() || UncivGame.Current.gameInfo == null)
|
||||
return ""
|
||||
return "\n**Save Data:**\n<details><summary>Show Saved Game</summary>\n\n```\n" +
|
||||
try {
|
||||
GameSaver.gameInfoToString(UncivGame.Current.gameInfo, forceZip = true)
|
||||
GameSaver.gameInfoToString(UncivGame.Current.gameInfo!!, forceZip = true)
|
||||
} catch (e: Throwable) {
|
||||
"No save data: $e" // In theory .toString() could still error here.
|
||||
} + "\n```\n</details>\n"
|
||||
@ -70,11 +70,11 @@ class CrashScreen(val exception: Throwable): BaseScreen() {
|
||||
|
||||
/** @return Mods from the last active save game if any, or an informational note otherwise. */
|
||||
private fun tryGetSaveMods(): String {
|
||||
if (!UncivGame.isCurrentInitialized() || !UncivGame.Current.isGameInfoInitialized())
|
||||
if (!UncivGame.isCurrentInitialized() || UncivGame.Current.gameInfo == null)
|
||||
return ""
|
||||
return "\n**Save Mods:**\n```\n" +
|
||||
try { // Also from old CrashController().buildReport(), also could still error at .toString().
|
||||
LinkedHashSet(UncivGame.Current.gameInfo.gameParameters.getModsAndBaseRuleset()).toString()
|
||||
LinkedHashSet(UncivGame.Current.gameInfo!!.gameParameters.getModsAndBaseRuleset()).toString()
|
||||
} catch (e: Throwable) {
|
||||
"No mod data: $e"
|
||||
} + "\n```\n"
|
||||
|
@ -62,10 +62,10 @@ class MapEditorLoadTab(
|
||||
|
||||
private fun deleteHandler() {
|
||||
if (chosenMap == null) return
|
||||
YesNoPopup("Are you sure you want to delete this map?", {
|
||||
YesNoPopup("Are you sure you want to delete this map?", editorScreen) {
|
||||
chosenMap!!.delete()
|
||||
mapFiles.update()
|
||||
}, editorScreen).open()
|
||||
}.open()
|
||||
}
|
||||
|
||||
override fun activated(index: Int, caption: String, pager: TabbedPager) {
|
||||
|
@ -131,7 +131,7 @@ class MapEditorModsTab(
|
||||
add(inc.toLabel()).row()
|
||||
}
|
||||
add(ScrollPane(incompatibilityTable)).colspan(2)
|
||||
.maxHeight(screen.stage.height * 0.8f).row()
|
||||
.maxHeight(stage.height * 0.8f).row()
|
||||
addGoodSizedLabel("Change map to fit selected ruleset?", 24).colspan(2).row()
|
||||
addButtonInRow(Constants.yes, 'y') {
|
||||
onOK()
|
||||
|
@ -78,10 +78,10 @@ class MapEditorSaveTab(
|
||||
|
||||
private fun deleteHandler() {
|
||||
if (chosenMap == null) return
|
||||
YesNoPopup("Are you sure you want to delete this map?", {
|
||||
YesNoPopup("Are you sure you want to delete this map?", editorScreen) {
|
||||
chosenMap!!.delete()
|
||||
mapFiles.update()
|
||||
}, editorScreen).open()
|
||||
}.open()
|
||||
}
|
||||
|
||||
override fun activated(index: Int, caption: String, pager: TabbedPager) {
|
||||
|
@ -191,9 +191,9 @@ class MapEditorScreen(map: TileMap? = null): BaseScreen() {
|
||||
|
||||
fun askIfDirty(question: String, action: ()->Unit) {
|
||||
if (!isDirty) return action()
|
||||
YesNoPopup(question, action, screen = this, restoreDefault = {
|
||||
YesNoPopup(question, screen = this, restoreDefault = {
|
||||
keyPressDispatcher[KeyCharAndCode.BACK] = this::closeEditor
|
||||
}).open()
|
||||
}, action).open()
|
||||
}
|
||||
|
||||
fun hideSelection() {
|
||||
|
@ -40,11 +40,11 @@ class EditFriendScreen(selectedFriend: FriendList.Friend, backScreen: ViewFriend
|
||||
topTable.add(gameIDTable).padBottom(30f).row()
|
||||
|
||||
deleteFriendButton.onClick {
|
||||
val askPopup = YesNoPopup("Are you sure you want to delete this friend?", {
|
||||
val askPopup = YesNoPopup("Are you sure you want to delete this friend?", this) {
|
||||
friendlist.delete(selectedFriend)
|
||||
backScreen.game.setScreen(backScreen)
|
||||
backScreen.refreshFriendsList()
|
||||
}, this)
|
||||
}
|
||||
askPopup.open()
|
||||
}.apply { color = Color.RED }
|
||||
topTable.add(deleteFriendButton)
|
||||
|
@ -27,22 +27,22 @@ class EditMultiplayerGameInfoScreen(val multiplayerGame: OnlineMultiplayerGame,
|
||||
|
||||
val deleteButton = "Delete save".toTextButton()
|
||||
deleteButton.onClick {
|
||||
val askPopup = YesNoPopup("Are you sure you want to delete this map?", {
|
||||
val askPopup = YesNoPopup("Are you sure you want to delete this map?", this) {
|
||||
try {
|
||||
game.onlineMultiplayer.deleteGame(multiplayerGame)
|
||||
game.setScreen(backScreen)
|
||||
} catch (ex: Exception) {
|
||||
ToastPopup("Could not delete game!", this)
|
||||
}
|
||||
}, this)
|
||||
}
|
||||
askPopup.open()
|
||||
}.apply { color = Color.RED }
|
||||
|
||||
val giveUpButton = "Resign".toTextButton()
|
||||
giveUpButton.onClick {
|
||||
val askPopup = YesNoPopup("Are you sure you want to resign?", {
|
||||
val askPopup = YesNoPopup("Are you sure you want to resign?", this) {
|
||||
resign(multiplayerGame, backScreen)
|
||||
}, this)
|
||||
}
|
||||
askPopup.open()
|
||||
}
|
||||
giveUpButton.apply { color = Color.RED }
|
||||
|
@ -36,6 +36,7 @@ import com.unciv.ui.utils.extensions.onClick
|
||||
import com.unciv.ui.utils.extensions.pad
|
||||
import com.unciv.ui.utils.extensions.toLabel
|
||||
import com.unciv.ui.utils.extensions.toTextButton
|
||||
import com.unciv.utils.Log
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
|
||||
@ -74,9 +75,9 @@ class NewGameScreen(
|
||||
val resetToDefaultsButton = "Reset to defaults".toTextButton()
|
||||
rightSideGroup.addActorAt(0, resetToDefaultsButton)
|
||||
resetToDefaultsButton.onClick {
|
||||
YesNoPopup("Are you sure you want to reset all game options to defaults?", {
|
||||
YesNoPopup("Are you sure you want to reset all game options to defaults?", this) {
|
||||
game.setScreen(NewGameScreen(previousScreen, GameSetupInfo()))
|
||||
}, this).open(true)
|
||||
}.open(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +156,7 @@ class NewGameScreen(
|
||||
val message = mapSize.fixUndesiredSizes(gameSetupInfo.mapParameters.worldWrap)
|
||||
if (message != null) {
|
||||
postCrashHandlingRunnable {
|
||||
ToastPopup( message, UncivGame.Current.screen as BaseScreen, 4000 )
|
||||
ToastPopup( message, UncivGame.Current.screen!!, 4000 )
|
||||
with (mapOptionsTable.generatedMapOptionsTable) {
|
||||
customMapSizeRadius.text = mapSize.radius.toString()
|
||||
customMapWidth.text = mapSize.width.toString()
|
||||
@ -275,6 +276,7 @@ class NewGameScreen(
|
||||
rightSideButton.setText("Start game!".tr())
|
||||
return
|
||||
} catch (ex: Exception) {
|
||||
Log.error("Error while creating game", ex)
|
||||
postCrashHandlingRunnable {
|
||||
popup.reuseWith("Could not upload game!", true)
|
||||
}
|
||||
@ -286,13 +288,12 @@ class NewGameScreen(
|
||||
}
|
||||
|
||||
postCrashHandlingRunnable {
|
||||
game.loadGame(newGame)
|
||||
previousScreen.dispose()
|
||||
val worldScreen = game.loadGame(newGame)
|
||||
if (newGame.gameParameters.isOnlineMultiplayer) {
|
||||
// Save gameId to clipboard because you have to do it anyway.
|
||||
Gdx.app.clipboard.contents = newGame.gameId
|
||||
// Popup to notify the User that the gameID got copied to the clipboard
|
||||
ToastPopup("Game ID copied to clipboard!".tr(), game.worldScreen, 2500)
|
||||
ToastPopup("Game ID copied to clipboard!".tr(), worldScreen, 2500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ private class NationPickerPopup(
|
||||
private val ruleset = previousScreen.ruleset
|
||||
// This Popup's body has two halves of same size, either side by side or arranged vertically
|
||||
// depending on screen proportions - determine height for one of those
|
||||
private val partHeight = screen.stage.height * (if (screen.isNarrowerThan4to3()) 0.45f else 0.8f)
|
||||
private val partHeight = stage.height * (if (stage.isNarrowerThan4to3()) 0.45f else 0.8f)
|
||||
private val civBlocksWidth = playerPicker.civBlocksWidth
|
||||
private val nationListTable = Table()
|
||||
private val nationListScroll = ScrollPane(nationListTable)
|
||||
@ -356,7 +356,7 @@ private class NationPickerPopup(
|
||||
nationListScroll.setOverscroll(false, false)
|
||||
add(nationListScroll).size( civBlocksWidth + 10f, partHeight )
|
||||
// +10, because the nation table has a 5f pad, for a total of +10f
|
||||
if (screen.isNarrowerThan4to3()) row()
|
||||
if (stage.isNarrowerThan4to3()) row()
|
||||
nationDetailsScroll.setOverscroll(false, false)
|
||||
add(nationDetailsScroll).size(civBlocksWidth + 10f, partHeight) // Same here, see above
|
||||
|
||||
|
@ -9,6 +9,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Array
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.models.translations.TranslationFileWriter
|
||||
import com.unciv.models.translations.tr
|
||||
@ -48,12 +49,12 @@ fun advancedTab(
|
||||
|
||||
addMaxZoomSlider(this, settings)
|
||||
|
||||
val screen = optionsPopup.screen
|
||||
if (screen.game.platformSpecificHelper != null && Gdx.app.type == Application.ApplicationType.Android) {
|
||||
val helper = UncivGame.Current.platformSpecificHelper
|
||||
if (helper != null && Gdx.app.type == Application.ApplicationType.Android) {
|
||||
optionsPopup.addCheckbox(this, "Enable portrait orientation", settings.allowAndroidPortrait) {
|
||||
settings.allowAndroidPortrait = it
|
||||
// Note the following might close the options screen indirectly and delayed
|
||||
screen.game.platformSpecificHelper.allowPortrait(it)
|
||||
helper.allowPortrait(it)
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +62,7 @@ fun advancedTab(
|
||||
|
||||
addTranslationGeneration(this, optionsPopup)
|
||||
|
||||
addSetUserId(this, settings, screen)
|
||||
addSetUserId(this, settings)
|
||||
}
|
||||
|
||||
private fun addAutosaveTurnsSelectBox(table: Table, settings: GameSettings) {
|
||||
@ -161,22 +162,18 @@ private fun addTranslationGeneration(table: Table, optionsPopup: OptionsPopup) {
|
||||
table.add(generateTranslationsButton).colspan(2).row()
|
||||
}
|
||||
|
||||
private fun addSetUserId(table: Table, settings: GameSettings, screen: BaseScreen) {
|
||||
private fun addSetUserId(table: Table, settings: GameSettings) {
|
||||
val idSetLabel = "".toLabel()
|
||||
val takeUserIdFromClipboardButton = "Take user ID from clipboard".toTextButton()
|
||||
.onClick {
|
||||
try {
|
||||
val clipboardContents = Gdx.app.clipboard.contents.trim()
|
||||
UUID.fromString(clipboardContents)
|
||||
YesNoPopup(
|
||||
"Doing this will reset your current user ID to the clipboard contents - are you sure?",
|
||||
{
|
||||
settings.multiplayer.userId = clipboardContents
|
||||
settings.save()
|
||||
idSetLabel.setFontColor(Color.WHITE).setText("ID successfully set!".tr())
|
||||
},
|
||||
screen
|
||||
).open(true)
|
||||
YesNoPopup("Doing this will reset your current user ID to the clipboard contents - are you sure?",table.stage) {
|
||||
settings.multiplayer.userId = clipboardContents
|
||||
settings.save()
|
||||
idSetLabel.setFontColor(Color.WHITE).setText("ID successfully set!".tr())
|
||||
}.open(true)
|
||||
idSetLabel.isVisible = true
|
||||
} catch (ex: Exception) {
|
||||
idSetLabel.isVisible = true
|
||||
|
@ -19,22 +19,25 @@ fun debugTab() = Table(BaseScreen.skin).apply {
|
||||
defaults().pad(5f)
|
||||
val game = UncivGame.Current
|
||||
|
||||
val simulateButton = "Simulate until turn:".toTextButton()
|
||||
val simulateTextField = TextField(game.simulateUntilTurnForDebug.toString(), BaseScreen.skin)
|
||||
val invalidInputLabel = "This is not a valid integer!".toLabel().also { it.isVisible = false }
|
||||
simulateButton.onClick {
|
||||
val simulateUntilTurns = simulateTextField.text.toIntOrNull()
|
||||
if (simulateUntilTurns == null) {
|
||||
invalidInputLabel.isVisible = true
|
||||
return@onClick
|
||||
val worldScreen = game.worldScreen
|
||||
if (worldScreen != null) {
|
||||
val simulateButton = "Simulate until turn:".toTextButton()
|
||||
val simulateTextField = TextField(game.simulateUntilTurnForDebug.toString(), BaseScreen.skin)
|
||||
val invalidInputLabel = "This is not a valid integer!".toLabel().also { it.isVisible = false }
|
||||
simulateButton.onClick {
|
||||
val simulateUntilTurns = simulateTextField.text.toIntOrNull()
|
||||
if (simulateUntilTurns == null) {
|
||||
invalidInputLabel.isVisible = true
|
||||
return@onClick
|
||||
}
|
||||
game.simulateUntilTurnForDebug = simulateUntilTurns
|
||||
invalidInputLabel.isVisible = false
|
||||
worldScreen.nextTurn()
|
||||
}
|
||||
game.simulateUntilTurnForDebug = simulateUntilTurns
|
||||
invalidInputLabel.isVisible = false
|
||||
game.worldScreen.nextTurn()
|
||||
add(simulateButton)
|
||||
add(simulateTextField).row()
|
||||
add(invalidInputLabel).colspan(2).row()
|
||||
}
|
||||
add(simulateButton)
|
||||
add(simulateTextField).row()
|
||||
add(invalidInputLabel).colspan(2).row()
|
||||
|
||||
add("Supercharged".toCheckBox(game.superchargedForDebug) {
|
||||
game.superchargedForDebug = it
|
||||
@ -42,9 +45,10 @@ fun debugTab() = Table(BaseScreen.skin).apply {
|
||||
add("View entire map".toCheckBox(game.viewEntireMapForDebug) {
|
||||
game.viewEntireMapForDebug = it
|
||||
}).colspan(2).row()
|
||||
if (game.isGameInfoInitialized()) {
|
||||
add("God mode (current game)".toCheckBox(game.gameInfo.gameParameters.godMode) {
|
||||
game.gameInfo.gameParameters.godMode = it
|
||||
val curGameInfo = game.gameInfo
|
||||
if (curGameInfo != null) {
|
||||
add("God mode (current game)".toCheckBox(curGameInfo.gameParameters.godMode) {
|
||||
curGameInfo.gameParameters.godMode = it
|
||||
}).colspan(2).row()
|
||||
}
|
||||
add("Save games compressed".toCheckBox(GameSaver.saveZipped) {
|
||||
@ -73,25 +77,25 @@ fun debugTab() = Table(BaseScreen.skin).apply {
|
||||
|
||||
val unlockTechsButton = "Unlock all techs".toTextButton()
|
||||
unlockTechsButton.onClick {
|
||||
if (!game.isGameInfoInitialized())
|
||||
if (curGameInfo == null)
|
||||
return@onClick
|
||||
for (tech in game.gameInfo.ruleSet.technologies.keys) {
|
||||
if (tech !in game.gameInfo.getCurrentPlayerCivilization().tech.techsResearched) {
|
||||
game.gameInfo.getCurrentPlayerCivilization().tech.addTechnology(tech)
|
||||
game.gameInfo.getCurrentPlayerCivilization().popupAlerts.removeLastOrNull()
|
||||
for (tech in curGameInfo.ruleSet.technologies.keys) {
|
||||
if (tech !in curGameInfo.getCurrentPlayerCivilization().tech.techsResearched) {
|
||||
curGameInfo.getCurrentPlayerCivilization().tech.addTechnology(tech)
|
||||
curGameInfo.getCurrentPlayerCivilization().popupAlerts.removeLastOrNull()
|
||||
}
|
||||
}
|
||||
game.gameInfo.getCurrentPlayerCivilization().updateSightAndResources()
|
||||
game.worldScreen.shouldUpdate = true
|
||||
curGameInfo.getCurrentPlayerCivilization().updateSightAndResources()
|
||||
if (worldScreen != null) worldScreen.shouldUpdate = true
|
||||
}
|
||||
add(unlockTechsButton).colspan(2).row()
|
||||
|
||||
val giveResourcesButton = "Get all strategic resources".toTextButton()
|
||||
giveResourcesButton.onClick {
|
||||
if (!game.isGameInfoInitialized())
|
||||
if (curGameInfo == null)
|
||||
return@onClick
|
||||
val ownedTiles = game.gameInfo.tileMap.values.asSequence().filter { it.getOwner() == game.gameInfo.getCurrentPlayerCivilization() }
|
||||
val resourceTypes = game.gameInfo.ruleSet.tileResources.values.asSequence().filter { it.resourceType == ResourceType.Strategic }
|
||||
val ownedTiles = curGameInfo.tileMap.values.asSequence().filter { it.getOwner() == curGameInfo.getCurrentPlayerCivilization() }
|
||||
val resourceTypes = curGameInfo.ruleSet.tileResources.values.asSequence().filter { it.resourceType == ResourceType.Strategic }
|
||||
for ((tile, resource) in ownedTiles zip resourceTypes) {
|
||||
tile.resource = resource.name
|
||||
tile.resourceAmount = 999
|
||||
@ -99,8 +103,8 @@ fun debugTab() = Table(BaseScreen.skin).apply {
|
||||
// If this becomes a problem, check if such an improvement exists and otherwise plop down a great improvement or so
|
||||
tile.improvement = resource.getImprovements().first()
|
||||
}
|
||||
game.gameInfo.getCurrentPlayerCivilization().updateSightAndResources()
|
||||
game.worldScreen.shouldUpdate = true
|
||||
curGameInfo.getCurrentPlayerCivilization().updateSightAndResources()
|
||||
if (worldScreen != null) worldScreen.shouldUpdate = true
|
||||
}
|
||||
add(giveResourcesButton).colspan(2).row()
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Array
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.models.tilesets.TileSetCache
|
||||
import com.unciv.models.translations.tr
|
||||
@ -41,7 +42,7 @@ fun displayTab(
|
||||
optionsPopup.addCheckbox(this, "Experimental Demographics scoreboard", settings.useDemographics, true) { settings.useDemographics = it }
|
||||
optionsPopup.addCheckbox(this, "Show zoom buttons in world screen", settings.showZoomButtons, true) { settings.showZoomButtons = it }
|
||||
|
||||
addMinimapSizeSlider(this, settings, optionsPopup.screen, optionsPopup.selectBoxMinWidth)
|
||||
addMinimapSizeSlider(this, settings, optionsPopup.selectBoxMinWidth)
|
||||
|
||||
addResolutionSelectBox(this, settings, optionsPopup.selectBoxMinWidth, onResolutionChange)
|
||||
|
||||
@ -62,7 +63,7 @@ fun displayTab(
|
||||
|
||||
}
|
||||
|
||||
private fun addMinimapSizeSlider(table: Table, settings: GameSettings, screen: BaseScreen, selectBoxMinWidth: Float) {
|
||||
private fun addMinimapSizeSlider(table: Table, settings: GameSettings, selectBoxMinWidth: Float) {
|
||||
table.add("Show minimap".toLabel()).left().fillX()
|
||||
|
||||
// The meaning of the values needs a formula to be synchronized between here and
|
||||
@ -88,8 +89,9 @@ private fun addMinimapSizeSlider(table: Table, settings: GameSettings, screen: B
|
||||
settings.minimapSize = size
|
||||
}
|
||||
settings.save()
|
||||
if (screen is WorldScreen)
|
||||
screen.shouldUpdate = true
|
||||
val worldScreen = UncivGame.Current.getWorldScreenIfActive()
|
||||
if (worldScreen != null)
|
||||
worldScreen.shouldUpdate = true
|
||||
}
|
||||
table.add(minimapSlider).minWidth(selectBoxMinWidth).pad(10f).row()
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.unciv.ui.options
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.PlayerType
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
@ -12,16 +13,16 @@ fun gameplayTab(
|
||||
defaults().pad(5f)
|
||||
|
||||
val settings = optionsPopup.settings
|
||||
val screen = optionsPopup.screen
|
||||
|
||||
optionsPopup.addCheckbox(this, "Check for idle units", settings.checkForDueUnits, true) { settings.checkForDueUnits = it }
|
||||
optionsPopup.addCheckbox(this, "Move units with a single tap", settings.singleTapMove) { settings.singleTapMove = it }
|
||||
optionsPopup.addCheckbox(this, "Auto-assign city production", settings.autoAssignCityProduction, true) {
|
||||
settings.autoAssignCityProduction = it
|
||||
if (it && screen is WorldScreen &&
|
||||
screen.viewingCiv.isCurrentPlayer() && screen.viewingCiv.playerType == PlayerType.Human
|
||||
optionsPopup.addCheckbox(this, "Auto-assign city production", settings.autoAssignCityProduction, true) { shouldAutoAssignCityProduction ->
|
||||
settings.autoAssignCityProduction = shouldAutoAssignCityProduction
|
||||
val worldScreen = UncivGame.Current.getWorldScreenIfActive()
|
||||
if (shouldAutoAssignCityProduction && worldScreen != null &&
|
||||
worldScreen.viewingCiv.isCurrentPlayer() && worldScreen.viewingCiv.playerType == PlayerType.Human
|
||||
) {
|
||||
screen.gameInfo.currentPlayerCiv.cities.forEach { city ->
|
||||
worldScreen.gameInfo.currentPlayerCiv.cities.forEach { city ->
|
||||
city.cityConstructions.chooseNextConstruction()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.unciv.ui.options
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.LanguageTable.Companion.addLanguageTables
|
||||
import com.unciv.ui.utils.extensions.onClick
|
||||
@ -17,7 +18,7 @@ fun languageTab(
|
||||
fun selectLanguage() {
|
||||
settings.language = chosenLanguage
|
||||
settings.updateLocaleFromLanguage()
|
||||
optionsPopup.screen.game.translations.tryReadTranslationForCurrentLanguage()
|
||||
UncivGame.Current.translations.tryReadTranslationForCurrentLanguage()
|
||||
onLanguageSelected()
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ import com.unciv.models.metadata.GameSetting
|
||||
import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.crashhandling.launchCrashHandling
|
||||
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
|
||||
import com.unciv.ui.popup.Popup
|
||||
@ -145,8 +144,7 @@ private fun addMultiplayerServerOptions(
|
||||
settings.save()
|
||||
}
|
||||
|
||||
val screen = optionsPopup.screen
|
||||
serverIpTable.add(multiplayerServerTextField).minWidth(screen.stage.width / 2).growX()
|
||||
serverIpTable.add(multiplayerServerTextField).minWidth(optionsPopup.stageToShowOn.width / 2).growX()
|
||||
tab.add(serverIpTable).colspan(2).fillX().row()
|
||||
|
||||
tab.add("Reset to Dropbox".toTextButton().onClick {
|
||||
@ -156,7 +154,7 @@ private fun addMultiplayerServerOptions(
|
||||
}).colspan(2).row()
|
||||
|
||||
tab.add(connectionToServerButton.onClick {
|
||||
val popup = Popup(screen).apply {
|
||||
val popup = Popup(optionsPopup.stage).apply {
|
||||
addGoodSizedLabel("Awaiting response...").row()
|
||||
}
|
||||
popup.open(true)
|
||||
|
@ -8,6 +8,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
||||
import com.badlogic.gdx.utils.Array
|
||||
import com.unciv.MainMenuScreen
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.event.EventBus
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.metadata.BaseRuleset
|
||||
@ -133,20 +134,20 @@ class OptionsPopup(
|
||||
/** Reload this Popup after major changes (resolution, tileset, language, font) */
|
||||
private fun reloadWorldAndOptions() {
|
||||
settings.save()
|
||||
if (screen is WorldScreen) {
|
||||
screen.game.resetToWorldScreen(WorldScreen(screen.gameInfo, screen.viewingCiv))
|
||||
} else if (screen is MainMenuScreen) {
|
||||
screen.game.setScreen(MainMenuScreen())
|
||||
val worldScreen = UncivGame.Current.getWorldScreenIfActive()
|
||||
if (worldScreen != null) {
|
||||
val newWorldScreen = WorldScreen(worldScreen.gameInfo, worldScreen.viewingCiv)
|
||||
worldScreen.game.setScreen(newWorldScreen)
|
||||
newWorldScreen.openOptionsPopup(tabs.activePage)
|
||||
}
|
||||
(screen.game.screen as BaseScreen).openOptionsPopup(tabs.activePage)
|
||||
}
|
||||
|
||||
fun addCheckbox(table: Table, text: String, initialState: Boolean, updateWorld: Boolean = false, action: ((Boolean) -> Unit)) {
|
||||
val checkbox = text.toCheckBox(initialState) {
|
||||
action(it)
|
||||
settings.save()
|
||||
if (updateWorld && screen is WorldScreen)
|
||||
screen.shouldUpdate = true
|
||||
val worldScreen = UncivGame.Current.getWorldScreenIfActive()
|
||||
if (updateWorld && worldScreen != null) worldScreen.shouldUpdate = true
|
||||
}
|
||||
table.add(checkbox).colspan(2).left().row()
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ package com.unciv.ui.options
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.audio.MusicController
|
||||
import com.unciv.ui.audio.MusicTrackChooserFlags
|
||||
import com.unciv.ui.crashhandling.launchCrashHandling
|
||||
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
|
||||
@ -24,17 +26,17 @@ fun soundTab(
|
||||
defaults().pad(5f)
|
||||
|
||||
val settings = optionsPopup.settings
|
||||
val screen = optionsPopup.screen
|
||||
val music = UncivGame.Current.musicController
|
||||
|
||||
addSoundEffectsVolumeSlider(this, settings)
|
||||
|
||||
if (screen.game.musicController.isMusicAvailable()) {
|
||||
addMusicVolumeSlider(this, settings, screen)
|
||||
addMusicPauseSlider(this, settings, screen)
|
||||
addMusicCurrentlyPlaying(this, screen)
|
||||
if (UncivGame.Current.musicController.isMusicAvailable()) {
|
||||
addMusicVolumeSlider(this, settings, music)
|
||||
addMusicPauseSlider(this, settings, music)
|
||||
addMusicCurrentlyPlaying(this, music)
|
||||
}
|
||||
|
||||
if (!screen.game.musicController.isDefaultFileAvailable())
|
||||
if (!UncivGame.Current.musicController.isDefaultFileAvailable())
|
||||
addDownloadMusic(this, optionsPopup)
|
||||
}
|
||||
|
||||
@ -52,11 +54,10 @@ private fun addDownloadMusic(table: Table, optionsPopup: OptionsPopup) {
|
||||
// So the whole game doesn't get stuck while downloading the file
|
||||
launchCrashHandling("MusicDownload") {
|
||||
try {
|
||||
val screen = optionsPopup.screen
|
||||
screen.game.musicController.downloadDefaultFile()
|
||||
UncivGame.Current.musicController.downloadDefaultFile()
|
||||
postCrashHandlingRunnable {
|
||||
optionsPopup.tabs.replacePage("Sound", soundTab(optionsPopup))
|
||||
screen.game.musicController.chooseTrack(flags = MusicTrackChooserFlags.setPlayDefault)
|
||||
UncivGame.Current.musicController.chooseTrack(flags = MusicTrackChooserFlags.setPlayDefault)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
postCrashHandlingRunnable {
|
||||
@ -83,7 +84,7 @@ private fun addSoundEffectsVolumeSlider(table: Table, settings: GameSettings) {
|
||||
table.add(soundEffectsVolumeSlider).pad(5f).row()
|
||||
}
|
||||
|
||||
private fun addMusicVolumeSlider(table: Table, settings: GameSettings, screen: BaseScreen) {
|
||||
private fun addMusicVolumeSlider(table: Table, settings: GameSettings, music: MusicController) {
|
||||
table.add("Music volume".tr()).left().fillX()
|
||||
|
||||
val musicVolumeSlider = UncivSlider(
|
||||
@ -95,7 +96,6 @@ private fun addMusicVolumeSlider(table: Table, settings: GameSettings, screen: B
|
||||
settings.musicVolume = it
|
||||
settings.save()
|
||||
|
||||
val music = screen.game.musicController
|
||||
music.setVolume(it)
|
||||
if (!music.isPlaying())
|
||||
music.chooseTrack(flags = MusicTrackChooserFlags.setPlayDefault)
|
||||
@ -103,9 +103,7 @@ private fun addMusicVolumeSlider(table: Table, settings: GameSettings, screen: B
|
||||
table.add(musicVolumeSlider).pad(5f).row()
|
||||
}
|
||||
|
||||
private fun addMusicPauseSlider(table: Table, settings: GameSettings, screen: BaseScreen) {
|
||||
val music = screen.game.musicController
|
||||
|
||||
private fun addMusicPauseSlider(table: Table, settings: GameSettings, music: MusicController) {
|
||||
// map to/from 0-1-2..10-12-14..30-35-40..60-75-90-105-120
|
||||
fun posToLength(pos: Float): Float = when (pos) {
|
||||
in 0f..10f -> pos
|
||||
@ -141,16 +139,16 @@ private fun addMusicPauseSlider(table: Table, settings: GameSettings, screen: Ba
|
||||
table.add(pauseLengthSlider).pad(5f).row()
|
||||
}
|
||||
|
||||
private fun addMusicCurrentlyPlaying(table: Table, screen: BaseScreen) {
|
||||
private fun addMusicCurrentlyPlaying(table: Table, music: MusicController) {
|
||||
val label = WrappableLabel("", table.width - 10f, Color(-0x2f5001), 16)
|
||||
label.wrap = true
|
||||
table.add(label).padTop(20f).colspan(2).fillX().row()
|
||||
screen.game.musicController.onChange {
|
||||
music.onChange {
|
||||
postCrashHandlingRunnable {
|
||||
label.setText("Currently playing: [$it]".tr())
|
||||
}
|
||||
}
|
||||
label.onClick(UncivSound.Silent) {
|
||||
screen.game.musicController.chooseTrack(flags = MusicTrackChooserFlags.none)
|
||||
music.chooseTrack(flags = MusicTrackChooserFlags.none)
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,6 @@ class DiplomacyOverviewTab (
|
||||
table.touchable = Touchable.enabled
|
||||
table.onClick {
|
||||
if (civInfo.isDefeated() || viewingPlayer.isSpectator() || civInfo == viewingPlayer) return@onClick
|
||||
overviewScreen.dispose()
|
||||
UncivGame.Current.setScreen(DiplomacyScreen(viewingPlayer, civInfo))
|
||||
}
|
||||
return table
|
||||
|
@ -138,7 +138,7 @@ class StatsOverviewTab(
|
||||
for (city in viewingPlayer.cities) { city.cityStats.update() }
|
||||
update()
|
||||
}
|
||||
slider.isDisabled = !UncivGame.Current.worldScreen.canChangeState
|
||||
slider.isDisabled = !UncivGame.Current.worldScreen!!.canChangeState
|
||||
|
||||
sliderTable.add(slider).padTop(15f)
|
||||
add(sliderTable).colspan(2)
|
||||
|
@ -78,7 +78,7 @@ class UnitOverviewTab(
|
||||
private fun showWorldScreenAt(position: Vector2, unit: MapUnit?) {
|
||||
val game = overviewScreen.game
|
||||
game.resetToWorldScreen()
|
||||
game.worldScreen.mapHolder.setCenterPosition(position, forceSelectUnit = unit)
|
||||
game.worldScreen!!.mapHolder.setCenterPosition(position, forceSelectUnit = unit)
|
||||
}
|
||||
private fun showWorldScreenAt(unit: MapUnit) = showWorldScreenAt(unit.currentTile.position, unit)
|
||||
private fun showWorldScreenAt(tile: TileInfo) = showWorldScreenAt(tile.position, null)
|
||||
@ -190,7 +190,7 @@ class UnitOverviewTab(
|
||||
if (unit.promotions.canBePromoted())
|
||||
promotionsTable.add(
|
||||
ImageGetter.getImage("OtherIcons/Star").apply {
|
||||
color = if (game.worldScreen.canChangeState && unit.currentMovement > 0f && unit.attacksThisTurn == 0)
|
||||
color = if (game.worldScreen!!.canChangeState && unit.currentMovement > 0f && unit.attacksThisTurn == 0)
|
||||
Color.GOLDENROD
|
||||
else Color.GOLDENROD.darken(0.25f)
|
||||
}
|
||||
@ -198,7 +198,6 @@ class UnitOverviewTab(
|
||||
promotionsTable.onClick {
|
||||
if (unit.promotions.canBePromoted() || unit.promotions.promotions.isNotEmpty()) {
|
||||
game.setScreen(PromotionPickerScreen(unit))
|
||||
overviewScreen.dispose()
|
||||
}
|
||||
}
|
||||
add(promotionsTable)
|
||||
|
@ -238,8 +238,11 @@ class WonderOverviewTab(
|
||||
val locationLabel = locationText.toLabel()
|
||||
if (wonder.location != null)
|
||||
locationLabel.onClick{
|
||||
UncivGame.Current.resetToWorldScreen()
|
||||
UncivGame.Current.worldScreen.mapHolder.setCenterPosition(wonder.location.position)
|
||||
val worldScreen = UncivGame.Current.worldScreen
|
||||
if (worldScreen != null) {
|
||||
UncivGame.Current.resetToWorldScreen()
|
||||
worldScreen.mapHolder.setCenterPosition(wonder.location.position)
|
||||
}
|
||||
}
|
||||
add(locationLabel).fillY()
|
||||
}
|
||||
|
@ -59,7 +59,6 @@ class ImprovementPickerScreen(
|
||||
onAccept()
|
||||
}
|
||||
game.resetToWorldScreen()
|
||||
dispose()
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -87,7 +87,6 @@ class ModManagementScreen(
|
||||
game.settings.tileSet = tileSets.first()
|
||||
}
|
||||
game.setScreen(MainMenuScreen())
|
||||
dispose()
|
||||
}
|
||||
closeButton.onClick(closeAction)
|
||||
onBackButtonClicked(closeAction)
|
||||
@ -581,7 +580,6 @@ class ModManagementScreen(
|
||||
override fun resize(width: Int, height: Int) {
|
||||
if (stage.viewport.screenWidth != width || stage.viewport.screenHeight != height) {
|
||||
game.setScreen(ModManagementScreen(installedModInfo, onlineModInfo))
|
||||
dispose() // interrupt background loader - sorry, the resized new screen won't continue
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ class PickerPane(
|
||||
|
||||
/** Sets the text of the [rightSideButton] and enables it if it's the player's turn */
|
||||
fun pick(rightButtonText: String) {
|
||||
if (UncivGame.Current.worldScreen.isPlayersTurn) rightSideButton.enable()
|
||||
if (UncivGame.Current.worldScreen!!.isPlayersTurn) rightSideButton.enable()
|
||||
rightSideButton.setText(rightButtonText)
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,6 @@ open class PickerScreen(disableScroll: Boolean = false) : BaseScreen() {
|
||||
val closeAction = {
|
||||
if (previousScreen != null) game.setScreen(previousScreen)
|
||||
else game.resetToWorldScreen()
|
||||
dispose()
|
||||
}
|
||||
pickerPane.closeButton.onClick(closeAction)
|
||||
onBackButtonClicked(closeAction)
|
||||
|
@ -58,7 +58,6 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
// If we've moved to another screen in the meantime (great person pick, victory screen) ignore this
|
||||
if (game.screen !is PolicyPickerScreen || !policies.canAdoptPolicy()) {
|
||||
game.resetToWorldScreen()
|
||||
dispose()
|
||||
} else {
|
||||
val policyScreen = PolicyPickerScreen(worldScreen)
|
||||
policyScreen.scrollPane.scrollPercentX = scrollPane.scrollPercentX
|
||||
|
@ -30,8 +30,6 @@ class PromotionPickerScreen(val unit: MapUnit) : PickerScreen() {
|
||||
game.setScreen(PromotionPickerScreen(unit).setScrollY(scrollPane.scrollY))
|
||||
else
|
||||
game.resetToWorldScreen()
|
||||
dispose()
|
||||
game.worldScreen.shouldUpdate = true
|
||||
}
|
||||
|
||||
init {
|
||||
@ -43,7 +41,7 @@ class PromotionPickerScreen(val unit: MapUnit) : PickerScreen() {
|
||||
acceptPromotion(selectedPromotion)
|
||||
}
|
||||
val canBePromoted = unit.promotions.canBePromoted()
|
||||
val canChangeState = game.worldScreen.canChangeState
|
||||
val canChangeState = game.worldScreen!!.canChangeState
|
||||
val canPromoteNow = canBePromoted && canChangeState
|
||||
&& unit.currentMovement > 0 && unit.attacksThisTurn == 0
|
||||
rightSideButton.isEnabled = canPromoteNow
|
||||
|
@ -67,7 +67,6 @@ abstract class ReligionPickerScreenCommon(
|
||||
rightSideButton.onClick(UncivSound.Choir) {
|
||||
choosingCiv.religionManager.action()
|
||||
UncivGame.Current.resetToWorldScreen()
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,6 @@ class TechPickerScreen(
|
||||
game.settings.addCompletedTutorialTask("Pick technology")
|
||||
|
||||
game.resetToWorldScreen()
|
||||
game.worldScreen.shouldUpdate = true
|
||||
dispose()
|
||||
}
|
||||
|
||||
// per default show current/recent technology,
|
||||
@ -265,7 +263,7 @@ class TechPickerScreen(
|
||||
return
|
||||
}
|
||||
|
||||
if (!UncivGame.Current.worldScreen.canChangeState) {
|
||||
if (!UncivGame.Current.worldScreen!!.canChangeState) {
|
||||
rightSideButton.disable()
|
||||
return
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.unciv.ui.popup
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||
@ -27,7 +28,12 @@ import com.unciv.ui.utils.extensions.toTextButton
|
||||
* Base class for all Popups, i.e. Tables that get rendered in the middle of a screen and on top of everything else
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
open class Popup(val screen: BaseScreen): Table(BaseScreen.skin) {
|
||||
open class Popup(
|
||||
val stageToShowOn: Stage
|
||||
): Table(BaseScreen.skin) {
|
||||
|
||||
constructor(screen: BaseScreen) : this(screen.stage)
|
||||
|
||||
// This exists to differentiate the actual popup (the inner table)
|
||||
// from the 'screen blocking' part of the popup (which covers the entire screen)
|
||||
val innerTable = Table(BaseScreen.skin)
|
||||
@ -38,11 +44,15 @@ open class Popup(val screen: BaseScreen): Table(BaseScreen.skin) {
|
||||
*/
|
||||
val keyPressDispatcher = KeyPressDispatcher(this.javaClass.simpleName)
|
||||
|
||||
val closeListeners = mutableListOf<() -> Unit>()
|
||||
|
||||
val scrollPane: AutoScrollPane
|
||||
|
||||
init {
|
||||
// Set actor name for debugging
|
||||
name = javaClass.simpleName
|
||||
|
||||
val scrollPane = AutoScrollPane(innerTable, BaseScreen.skin)
|
||||
scrollPane = AutoScrollPane(innerTable, BaseScreen.skin)
|
||||
|
||||
background = ImageGetter.getBackground(Color.GRAY.cpy().apply { a=.5f })
|
||||
innerTable.background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f))
|
||||
@ -61,11 +71,11 @@ open class Popup(val screen: BaseScreen): Table(BaseScreen.skin) {
|
||||
* closed. Use [force] = true if you want to open this popup above the other one anyway.
|
||||
*/
|
||||
fun open(force: Boolean = false) {
|
||||
screen.stage.addActor(this)
|
||||
stageToShowOn.addActor(this)
|
||||
innerTable.pack()
|
||||
pack()
|
||||
center(screen.stage)
|
||||
if (force || !screen.hasOpenPopups()) {
|
||||
center(stageToShowOn)
|
||||
if (force || !stageToShowOn.hasOpenPopups()) {
|
||||
show()
|
||||
}
|
||||
}
|
||||
@ -73,18 +83,19 @@ open class Popup(val screen: BaseScreen): Table(BaseScreen.skin) {
|
||||
/** Subroutine for [open] handles only visibility and [keyPressDispatcher] */
|
||||
private fun show() {
|
||||
this.isVisible = true
|
||||
val currentCount = screen.countOpenPopups()
|
||||
val currentCount = stageToShowOn.countOpenPopups()
|
||||
// the lambda is for stacked key dispatcher precedence:
|
||||
keyPressDispatcher.install(screen.stage) { screen.countOpenPopups() > currentCount }
|
||||
keyPressDispatcher.install(stageToShowOn) { stageToShowOn.countOpenPopups() > currentCount }
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this popup and - if any other popups are pending - display the next one.
|
||||
*/
|
||||
open fun close() {
|
||||
for (listener in closeListeners) listener()
|
||||
keyPressDispatcher.uninstall()
|
||||
remove()
|
||||
val nextPopup = screen.stage.actors.firstOrNull { it is Popup }
|
||||
val nextPopup = stageToShowOn.actors.firstOrNull { it is Popup }
|
||||
if (nextPopup != null) (nextPopup as Popup).show()
|
||||
}
|
||||
|
||||
@ -104,7 +115,7 @@ open class Popup(val screen: BaseScreen): Table(BaseScreen.skin) {
|
||||
val label = text.toLabel(fontSize = size)
|
||||
label.wrap = true
|
||||
label.setAlignment(Align.center)
|
||||
return add(label).width(screen.stage.width / 2)
|
||||
return add(label).width(stageToShowOn.width / 2)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,9 +230,9 @@ open class Popup(val screen: BaseScreen): Table(BaseScreen.skin) {
|
||||
* [FocusListener][com.badlogic.gdx.scenes.scene2d.utils.FocusListener] cancels the event.
|
||||
*/
|
||||
var keyboardFocus: Actor?
|
||||
get() = screen.stage.keyboardFocus
|
||||
get() = stageToShowOn.keyboardFocus
|
||||
set(value) {
|
||||
if (screen.stage.setKeyboardFocus(value))
|
||||
if (stageToShowOn.setKeyboardFocus(value))
|
||||
(value as? TextField)?.selectAll()
|
||||
}
|
||||
}
|
||||
@ -230,25 +241,22 @@ open class Popup(val screen: BaseScreen): Table(BaseScreen.skin) {
|
||||
* Checks if there are visible [Popup]s.
|
||||
* @return `true` if any were found.
|
||||
*/
|
||||
fun BaseScreen.hasOpenPopups(): Boolean = stage.actors.any { it is Popup && it.isVisible }
|
||||
fun BaseScreen.hasOpenPopups(): Boolean = stage.hasOpenPopups()
|
||||
private fun Stage.hasOpenPopups(): Boolean = actors.any { it is Popup && it.isVisible }
|
||||
|
||||
/**
|
||||
* Counts number of visible[Popup]s.
|
||||
*
|
||||
* Used for key dispatcher precedence.
|
||||
*/
|
||||
fun BaseScreen.countOpenPopups() = stage.actors.count { it is Popup && it.isVisible }
|
||||
private fun Stage.countOpenPopups() = actors.count { it is Popup && it.isVisible }
|
||||
|
||||
/** Closes all [Popup]s. */
|
||||
fun BaseScreen.closeAllPopups() = popups.forEach { it.close() }
|
||||
|
||||
/**
|
||||
* Closes the topmost visible [Popup].
|
||||
* @return The [name][Popup.name] of the closed [Popup] if any popup was closed and if it had a name.
|
||||
*/
|
||||
fun BaseScreen.closeOneVisiblePopup() = popups.lastOrNull { it.isVisible }?.apply { close() }?.name
|
||||
fun BaseScreen.closeAllPopups() = stage.popups.forEach { it.close() }
|
||||
|
||||
/** @return A [List] of currently active or pending [Popup] screens. */
|
||||
val BaseScreen.popups: List<Popup>
|
||||
get() = stage.actors.filterIsInstance<Popup>()
|
||||
val BaseScreen.popups
|
||||
get() = stage.popups
|
||||
private val Stage.popups: List<Popup>
|
||||
get() = actors.filterIsInstance<Popup>()
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.unciv.ui.popup
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||
import com.unciv.ui.crashhandling.launchCrashHandling
|
||||
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
@ -10,7 +11,10 @@ import kotlinx.coroutines.delay
|
||||
* This is an unobtrusive popup which will close itself after a given amount of time.
|
||||
* Default time is two seconds (in milliseconds)
|
||||
*/
|
||||
class ToastPopup (message: String, screen: BaseScreen, val time: Long = 2000) : Popup(screen){
|
||||
class ToastPopup (message: String, stage: Stage, val time: Long = 2000) : Popup(stage){
|
||||
|
||||
constructor(message: String, screen: BaseScreen, time: Long = 2000) : this(message, screen.stage, time)
|
||||
|
||||
init {
|
||||
//Make this popup unobtrusive
|
||||
setFillParent(false)
|
||||
@ -20,7 +24,7 @@ class ToastPopup (message: String, screen: BaseScreen, val time: Long = 2000) :
|
||||
open()
|
||||
//move it to the top so its not in the middle of the screen
|
||||
//have to be done after open() because open() centers the popup
|
||||
y = screen.stage.height - (height + 20f)
|
||||
y = stage.height - (height + 20f)
|
||||
}
|
||||
|
||||
private fun startTimer(){
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.unciv.ui.popup
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
@ -14,12 +15,19 @@ import com.unciv.ui.utils.extensions.toLabel
|
||||
* @param screen The parent screen - see [Popup.screen]. Optional, defaults to the current [WorldScreen][com.unciv.ui.worldscreen.WorldScreen]
|
||||
* @param restoreDefault A lambda to execute when "No" is chosen
|
||||
*/
|
||||
open class YesNoPopup (
|
||||
open class YesNoPopup(
|
||||
question: String,
|
||||
action: ()->Unit,
|
||||
screen: BaseScreen = UncivGame.Current.worldScreen,
|
||||
restoreDefault: ()->Unit = {}
|
||||
) : Popup(screen) {
|
||||
stage: Stage,
|
||||
restoreDefault: () -> Unit = {},
|
||||
action: () -> Unit
|
||||
) : Popup(stage) {
|
||||
|
||||
constructor(
|
||||
question: String,
|
||||
screen: BaseScreen,
|
||||
restoreDefault: () -> Unit = {},
|
||||
action: () -> Unit
|
||||
) : this(question, screen.stage, restoreDefault, action)
|
||||
|
||||
/** The [Label][com.badlogic.gdx.scenes.scene2d.ui.Label] created for parameter `question` for optional layout tweaking */
|
||||
private val promptLabel = question.toLabel()
|
||||
@ -34,13 +42,12 @@ open class YesNoPopup (
|
||||
}
|
||||
|
||||
/** Shortcut to open a [YesNoPopup] with the exit game question */
|
||||
class ExitGamePopup(screen: BaseScreen, force: Boolean = false)
|
||||
: YesNoPopup(
|
||||
question = "Do you want to exit the game?",
|
||||
action = { Gdx.app.exit() },
|
||||
screen = screen,
|
||||
restoreDefault = { screen.game.musicController.resume() }
|
||||
) {
|
||||
class ExitGamePopup(screen: BaseScreen, force: Boolean = false) : YesNoPopup(
|
||||
question = "Do you want to exit the game?",
|
||||
screen = screen,
|
||||
restoreDefault = { screen.game.musicController.resume() },
|
||||
action = { Gdx.app.exit() }
|
||||
) {
|
||||
init {
|
||||
screen.game.musicController.pause()
|
||||
open(force)
|
||||
|
@ -6,9 +6,11 @@ import com.unciv.UncivGame
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.ui.crashhandling.launchCrashHandling
|
||||
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
|
||||
import com.unciv.ui.multiplayer.MultiplayerHelpers
|
||||
import com.unciv.ui.popup.Popup
|
||||
import com.unciv.ui.popup.ToastPopup
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
import com.unciv.utils.Log
|
||||
|
||||
|
||||
//todo reduce code duplication
|
||||
@ -70,6 +72,7 @@ object QuickSave {
|
||||
outOfMemory()
|
||||
return@launchCrashHandling
|
||||
} catch (ex: Exception) {
|
||||
Log.error("Could not autoload game", ex)
|
||||
postCrashHandlingRunnable {
|
||||
loadingPopup.close()
|
||||
ToastPopup("Cannot resume game!", screen)
|
||||
@ -82,6 +85,13 @@ object QuickSave {
|
||||
screen.game.onlineMultiplayer.loadGame(savedGame)
|
||||
} catch (oom: OutOfMemoryError) {
|
||||
outOfMemory()
|
||||
} catch (ex: Exception) {
|
||||
val message = MultiplayerHelpers.getLoadExceptionMessage(ex)
|
||||
Log.error("Could not autoload game", ex)
|
||||
postCrashHandlingRunnable {
|
||||
loadingPopup.close()
|
||||
ToastPopup(message, screen)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
postCrashHandlingRunnable { /// ... and load it into the screen on main thread for GL context
|
||||
@ -89,6 +99,10 @@ object QuickSave {
|
||||
screen.game.loadGame(savedGame)
|
||||
} catch (oom: OutOfMemoryError) {
|
||||
outOfMemory()
|
||||
} catch (ex: Exception) {
|
||||
Log.error("Could not autoload game", ex)
|
||||
loadingPopup.close()
|
||||
ToastPopup("Cannot resume game!", screen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : LoadOrSaveScreen("Current saves")
|
||||
rightSideButton.setText("Save game".tr())
|
||||
val saveAction = {
|
||||
if (game.gameSaver.getSave(gameNameTextField.text).exists())
|
||||
YesNoPopup("Overwrite existing file?", { saveGame() }, this).open()
|
||||
YesNoPopup("Overwrite existing file?", this) { saveGame() }.open()
|
||||
else saveGame()
|
||||
}
|
||||
rightSideButton.onClick(saveAction)
|
||||
|
@ -172,7 +172,7 @@ class TileGroupIcons(val tileGroup: TileGroup) {
|
||||
val shouldDisplayResource =
|
||||
if (tileGroup.showEntireMap) showResourcesAndImprovements
|
||||
else showResourcesAndImprovements
|
||||
&& tileGroup.tileInfo.hasViewableResource(UncivGame.Current.worldScreen.viewingCiv)
|
||||
&& tileGroup.tileInfo.hasViewableResource(UncivGame.Current.worldScreen!!.viewingCiv)
|
||||
tileGroup.resourceImage!!.isVisible = shouldDisplayResource
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ class DiplomacyScreen(
|
||||
private val rightSideTable = Table()
|
||||
private val closeButton = Constants.close.toTextButton()
|
||||
|
||||
private fun isNotPlayersTurn() = !UncivGame.Current.worldScreen.canChangeState
|
||||
private fun isNotPlayersTurn() = !UncivGame.Current.worldScreen!!.canChangeState
|
||||
|
||||
init {
|
||||
onBackButtonClicked { UncivGame.Current.resetToWorldScreen() }
|
||||
@ -205,7 +205,7 @@ class DiplomacyScreen(
|
||||
wrapper.addTooltip(name, 18f)
|
||||
wrapper.onClick {
|
||||
val pedia = CivilopediaScreen(
|
||||
UncivGame.Current.gameInfo.ruleSet,
|
||||
UncivGame.Current.gameInfo!!.ruleSet,
|
||||
this,
|
||||
link = "Resource/$name"
|
||||
)
|
||||
@ -389,11 +389,11 @@ class DiplomacyScreen(
|
||||
private fun getRevokeProtectionButton(otherCiv: CivilizationInfo): TextButton {
|
||||
val revokeProtectionButton = "Revoke Protection".toTextButton()
|
||||
revokeProtectionButton.onClick {
|
||||
YesNoPopup("Revoke protection for [${otherCiv.civName}]?", {
|
||||
YesNoPopup("Revoke protection for [${otherCiv.civName}]?", this) {
|
||||
otherCiv.removeProtectorCiv(viewingCiv)
|
||||
updateLeftSideTable(otherCiv)
|
||||
updateRightSide(otherCiv)
|
||||
}, this).open()
|
||||
}.open()
|
||||
}
|
||||
if (isNotPlayersTurn() || !otherCiv.otherCivCanWithdrawProtection(viewingCiv)) revokeProtectionButton.disable()
|
||||
return revokeProtectionButton
|
||||
@ -402,11 +402,11 @@ class DiplomacyScreen(
|
||||
private fun getPledgeToProtectButton(otherCiv: CivilizationInfo): TextButton {
|
||||
val protectionButton = "Pledge to protect".toTextButton()
|
||||
protectionButton.onClick {
|
||||
YesNoPopup("Declare Protection of [${otherCiv.civName}]?", {
|
||||
YesNoPopup("Declare Protection of [${otherCiv.civName}]?", this) {
|
||||
otherCiv.addProtectorCiv(viewingCiv)
|
||||
updateLeftSideTable(otherCiv)
|
||||
updateRightSide(otherCiv)
|
||||
}, this).open()
|
||||
}.open()
|
||||
}
|
||||
if (isNotPlayersTurn() || !otherCiv.otherCivCanPledgeProtection(viewingCiv)) protectionButton.disable()
|
||||
return protectionButton
|
||||
@ -418,7 +418,7 @@ class DiplomacyScreen(
|
||||
): TextButton {
|
||||
val peaceButton = "Negotiate Peace".toTextButton()
|
||||
peaceButton.onClick {
|
||||
YesNoPopup("Peace with [${otherCiv.civName}]?", {
|
||||
YesNoPopup("Peace with [${otherCiv.civName}]?", this) {
|
||||
val tradeLogic = TradeLogic(viewingCiv, otherCiv)
|
||||
tradeLogic.currentTrade.ourOffers.add(
|
||||
TradeOffer(
|
||||
@ -435,7 +435,7 @@ class DiplomacyScreen(
|
||||
tradeLogic.acceptTrade()
|
||||
updateLeftSideTable(otherCiv)
|
||||
updateRightSide(otherCiv)
|
||||
}, this).open()
|
||||
}.open()
|
||||
}
|
||||
val cityStatesAlly = otherCiv.getAllyCiv()
|
||||
val atWarWithItsAlly = viewingCiv.getKnownCivs()
|
||||
@ -761,11 +761,11 @@ class DiplomacyScreen(
|
||||
): TextButton {
|
||||
val denounceButton = "Denounce ([30] turns)".toTextButton()
|
||||
denounceButton.onClick {
|
||||
YesNoPopup("Denounce [${otherCiv.civName}]?", {
|
||||
YesNoPopup("Denounce [${otherCiv.civName}]?", this) {
|
||||
diplomacyManager.denounce()
|
||||
updateLeftSideTable(otherCiv)
|
||||
setRightSideFlavorText(otherCiv, "We will remember this.", "Very well.")
|
||||
}, this).open()
|
||||
}.open()
|
||||
}
|
||||
if (isNotPlayersTurn()) denounceButton.disable()
|
||||
return denounceButton
|
||||
@ -956,12 +956,12 @@ class DiplomacyScreen(
|
||||
declareWarButton.setText(declareWarButton.text.toString() + " ($turnsToPeaceTreaty${Fonts.turn})")
|
||||
}
|
||||
declareWarButton.onClick {
|
||||
YesNoPopup("Declare war on [${otherCiv.civName}]?", {
|
||||
YesNoPopup("Declare war on [${otherCiv.civName}]?", this) {
|
||||
diplomacyManager.declareWar()
|
||||
setRightSideFlavorText(otherCiv, otherCiv.nation.attacked, "Very well.")
|
||||
updateLeftSideTable(otherCiv)
|
||||
UncivGame.Current.musicController.chooseTrack(otherCiv.civName, MusicMood.War, MusicTrackChooserFlags.setSpecific)
|
||||
}, this).open()
|
||||
}.open()
|
||||
}
|
||||
if (isNotPlayersTurn()) declareWarButton.disable()
|
||||
return declareWarButton
|
||||
@ -996,8 +996,11 @@ class DiplomacyScreen(
|
||||
private fun getGoToOnMapButton(civilization: CivilizationInfo): TextButton {
|
||||
val goToOnMapButton = "Go to on map".toTextButton()
|
||||
goToOnMapButton.onClick {
|
||||
UncivGame.Current.resetToWorldScreen()
|
||||
UncivGame.Current.worldScreen.mapHolder.setCenterPosition(civilization.getCapital()!!.location, selectUnit = false)
|
||||
val worldScreen = UncivGame.Current.worldScreen
|
||||
if (worldScreen != null) {
|
||||
UncivGame.Current.resetToWorldScreen()
|
||||
worldScreen.mapHolder.setCenterPosition(civilization.getCapital()!!.location, selectUnit = false)
|
||||
}
|
||||
}
|
||||
return goToOnMapButton
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class OffersListScroll(
|
||||
Luxury_Resource, Strategic_Resource ->
|
||||
ImageGetter.getResourceImage(offer.name, 30f)
|
||||
WarDeclaration ->
|
||||
ImageGetter.getNationIndicator(UncivGame.Current.gameInfo.ruleSet.nations[offer.name]!!, 30f)
|
||||
ImageGetter.getNationIndicator(UncivGame.Current.gameInfo!!.ruleSet.nations[offer.name]!!, 30f)
|
||||
else -> null
|
||||
}
|
||||
val tradeButton = IconTextButton(tradeLabel, tradeIcon).apply {
|
||||
|
@ -7,16 +7,22 @@ import com.badlogic.gdx.graphics.GL20
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.Drawable
|
||||
import com.badlogic.gdx.utils.viewport.ExtendViewport
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.Tutorial
|
||||
import com.unciv.ui.UncivStage
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.options.OptionsPopup
|
||||
import com.unciv.ui.popup.hasOpenPopups
|
||||
import com.unciv.ui.tutorials.TutorialController
|
||||
import com.unciv.ui.options.OptionsPopup
|
||||
import com.unciv.ui.utils.extensions.isNarrowerThan4to3
|
||||
|
||||
abstract class BaseScreen : Screen {
|
||||
|
||||
@ -122,7 +128,7 @@ abstract class BaseScreen : Screen {
|
||||
fun isCrampedPortrait() = isPortrait() &&
|
||||
game.settings.resolution.split("x").map { it.toInt() }.last() <= 700
|
||||
/** @return `true` if the screen is narrower than 4:3 landscape */
|
||||
fun isNarrowerThan4to3() = stage.viewport.screenHeight * 4 > stage.viewport.screenWidth * 3
|
||||
fun isNarrowerThan4to3() = stage.isNarrowerThan4to3()
|
||||
|
||||
fun openOptionsPopup(startingPage: Int = OptionsPopup.defaultPage, onClose: () -> Unit = {}) {
|
||||
OptionsPopup(this, startingPage, onClose).open(force = true)
|
||||
|
@ -289,7 +289,7 @@ open class TabbedPager(
|
||||
//region Initialization
|
||||
|
||||
init {
|
||||
val screen = (if (UncivGame.isCurrentInitialized()) UncivGame.Current.screen else null) as? BaseScreen
|
||||
val screen = (if (UncivGame.isCurrentInitialized()) UncivGame.Current.screen else null)
|
||||
val (screenWidth, screenHeight) = (screen?.stage?.run { width to height }) ?: (Float.MAX_VALUE to Float.MAX_VALUE)
|
||||
dimW = DimensionMeasurement.from(minimumWidth, maximumWidth, screenWidth)
|
||||
dimH = DimensionMeasurement.from(minimumHeight, maximumHeight, screenHeight)
|
||||
@ -601,7 +601,7 @@ open class TabbedPager(
|
||||
if (!UncivGame.isCurrentInitialized() || askPasswordLock || deferredSecretPages.isEmpty()) return
|
||||
askPasswordLock = true // race condition: Popup closes _first_, then deferredSecretPages is emptied -> parent shows and calls us again
|
||||
|
||||
PassPopup(UncivGame.Current.screen as BaseScreen, {
|
||||
PassPopup(UncivGame.Current.screen!!, {
|
||||
addDeferredSecrets()
|
||||
}, {
|
||||
deferredSecretPages.clear()
|
||||
|
@ -229,3 +229,6 @@ fun WidgetGroup.packIfNeeded(): WidgetGroup {
|
||||
if (needsLayout()) pack()
|
||||
return this
|
||||
}
|
||||
|
||||
/** @return `true` if the screen is narrower than 4:3 landscape */
|
||||
fun Stage.isNarrowerThan4to3() = viewport.screenHeight * 4 > viewport.screenWidth * 3
|
||||
|
@ -3,25 +3,24 @@ package com.unciv.ui.worldscreen
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.extensions.onClick
|
||||
import com.unciv.ui.utils.extensions.toLabel
|
||||
|
||||
class PlayerReadyScreen(gameInfo: GameInfo, currentPlayerCiv: CivilizationInfo) : BaseScreen(){
|
||||
class PlayerReadyScreen(worldScreen: WorldScreen) : BaseScreen() {
|
||||
init {
|
||||
val table= Table()
|
||||
table.touchable= Touchable.enabled
|
||||
table.background= ImageGetter.getBackground(currentPlayerCiv.nation.getOuterColor())
|
||||
val table = Table()
|
||||
table.touchable = Touchable.enabled
|
||||
val curCiv = worldScreen.viewingCiv
|
||||
table.background = ImageGetter.getBackground(curCiv.nation.getOuterColor())
|
||||
|
||||
table.add("[$currentPlayerCiv] ready?".toLabel(currentPlayerCiv.nation.getInnerColor(), Constants.headingFontSize))
|
||||
table.add("[$curCiv] ready?".toLabel(curCiv.nation.getInnerColor(), Constants.headingFontSize))
|
||||
|
||||
table.onClick {
|
||||
postCrashHandlingRunnable { // To avoid ANRs on Android when the creation of the worldscreen takes more than 500ms
|
||||
game.resetToWorldScreen(WorldScreen(gameInfo, currentPlayerCiv))
|
||||
game.setScreen(worldScreen)
|
||||
}
|
||||
}
|
||||
table.setFillParent(true)
|
||||
|
@ -216,7 +216,7 @@ class WorldMapHolder(
|
||||
}
|
||||
|
||||
private fun onTileRightClicked(unit: MapUnit, tile: TileInfo) {
|
||||
if (UncivGame.Current.gameInfo.currentPlayerCiv.isSpectator()) {
|
||||
if (UncivGame.Current.gameInfo!!.currentPlayerCiv.isSpectator()) {
|
||||
return
|
||||
}
|
||||
removeUnitActionOverlay()
|
||||
|
@ -336,7 +336,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
|
||||
try {
|
||||
debug("loadLatestMultiplayerState current game: gameId: %s, turn: %s, curCiv: %s",
|
||||
game.worldScreen.gameInfo.gameId, game.worldScreen.gameInfo.turns, game.worldScreen.gameInfo.currentPlayer)
|
||||
gameInfo.gameId, gameInfo.turns, gameInfo.currentPlayer)
|
||||
val latestGame = game.onlineMultiplayer.downloadGame(gameInfo.gameId)
|
||||
debug("loadLatestMultiplayerState downloaded game: gameId: %s, turn: %s, curCiv: %s",
|
||||
latestGame.gameId, latestGame.turns, latestGame.currentPlayer)
|
||||
@ -345,8 +345,8 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
}
|
||||
postCrashHandlingRunnable {
|
||||
loadingGamePopup.close()
|
||||
if (game.gameInfo.gameId == gameInfo.gameId) { // game could've been changed during download
|
||||
createNewWorldScreen(latestGame)
|
||||
if (game.gameInfo!!.gameId == gameInfo.gameId) { // game could've been changed during download
|
||||
game.setScreen(createNewWorldScreen(latestGame))
|
||||
}
|
||||
}
|
||||
} catch (ex: Throwable) {
|
||||
@ -602,7 +602,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
|
||||
}
|
||||
|
||||
private fun createNewWorldScreen(gameInfo: GameInfo, resize:Boolean=false) {
|
||||
private fun createNewWorldScreen(gameInfo: GameInfo, resize:Boolean=false): WorldScreen {
|
||||
|
||||
game.gameInfo = gameInfo
|
||||
val newWorldScreen = WorldScreen(gameInfo, gameInfo.getPlayerToViewAs())
|
||||
@ -621,7 +621,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
newWorldScreen.selectedCiv = gameInfo.getCivilization(selectedCiv.civName)
|
||||
newWorldScreen.fogOfWar = fogOfWar
|
||||
|
||||
game.resetToWorldScreen(newWorldScreen)
|
||||
return newWorldScreen
|
||||
}
|
||||
|
||||
fun nextTurn() {
|
||||
@ -669,16 +669,15 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
// create a new WorldScreen to show the new stuff we've changed, and switch out the current screen.
|
||||
// do this on main thread - it's the only one that has a GL context to create images from
|
||||
postCrashHandlingRunnable {
|
||||
|
||||
val newWorldScreen = createNewWorldScreen(gameInfoClone)
|
||||
if (gameInfoClone.currentPlayerCiv.civName != viewingCiv.civName
|
||||
&& !gameInfoClone.gameParameters.isOnlineMultiplayer)
|
||||
game.setScreen(PlayerReadyScreen(gameInfoClone, gameInfoClone.getCurrentPlayerCivilization()))
|
||||
else {
|
||||
createNewWorldScreen(gameInfoClone)
|
||||
&& !gameInfoClone.gameParameters.isOnlineMultiplayer) {
|
||||
game.setScreen(PlayerReadyScreen(newWorldScreen))
|
||||
} else {
|
||||
game.setScreen(newWorldScreen)
|
||||
}
|
||||
|
||||
if (shouldAutoSave) {
|
||||
val newWorldScreen = this@WorldScreen.game.worldScreen
|
||||
newWorldScreen.waitingForAutosave = true
|
||||
newWorldScreen.shouldUpdate = true
|
||||
game.gameSaver.autoSave(gameInfoClone) {
|
||||
@ -821,7 +820,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
nextTurn()
|
||||
}
|
||||
if (game.settings.confirmNextTurn) {
|
||||
YesNoPopup("Confirm next turn", action, this).open()
|
||||
YesNoPopup("Confirm next turn", this, action = action).open()
|
||||
} else {
|
||||
action()
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class TileInfoTable(private val viewingCiv :CivilizationInfo) : Table(BaseScreen
|
||||
if (tile != null && (UncivGame.Current.viewEntireMapForDebug || viewingCiv.exploredTiles.contains(tile.position)) ) {
|
||||
add(getStatsTable(tile))
|
||||
add( MarkupRenderer.render(tile.toMarkup(viewingCiv), padding = 0f, iconDisplay = IconDisplay.None) {
|
||||
UncivGame.Current.setScreen(CivilopediaScreen(viewingCiv.gameInfo.ruleSet, UncivGame.Current.worldScreen, link = it))
|
||||
UncivGame.Current.setScreen(CivilopediaScreen(viewingCiv.gameInfo.ruleSet, UncivGame.Current.worldScreen!!, link = it))
|
||||
} ).pad(5f).row()
|
||||
if (UncivGame.Current.viewEntireMapForDebug)
|
||||
add(tile.position.run { "(${x.toInt()},${y.toInt()})" }.toLabel()).colspan(2).pad(5f)
|
||||
|
@ -42,7 +42,7 @@ class MapOverlayToggleButton(
|
||||
/** Toggle overlay. Called on click. */
|
||||
fun toggle() {
|
||||
setter(!getter())
|
||||
UncivGame.Current.worldScreen.shouldUpdate = true
|
||||
UncivGame.Current.worldScreen!!.shouldUpdate = true
|
||||
// Setting worldScreen.shouldUpdate implicitly causes this.update() to be called by the WorldScreen on the next update.
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ object UnitActions {
|
||||
val disbandText = if (unit.currentTile.getOwner() == unit.civInfo)
|
||||
"Disband this unit for [${unit.baseUnit.getDisbandGold(unit.civInfo)}] gold?".tr()
|
||||
else "Do you really want to disband this unit?".tr()
|
||||
YesNoPopup(disbandText, { unit.disband(); worldScreen.shouldUpdate = true }).open()
|
||||
YesNoPopup(disbandText, UncivGame.Current.worldScreen!!) { unit.disband(); worldScreen.shouldUpdate = true }.open()
|
||||
}
|
||||
}.takeIf { unit.currentMovement > 0 })
|
||||
}
|
||||
@ -187,7 +187,7 @@ object UnitActions {
|
||||
if (tile.ruleset.tileImprovements.containsKey("City center"))
|
||||
tile.improvement = "City center"
|
||||
unit.destroy()
|
||||
UncivGame.Current.worldScreen.shouldUpdate = true
|
||||
UncivGame.Current.worldScreen!!.shouldUpdate = true
|
||||
}
|
||||
|
||||
if (unit.civInfo.playerType == PlayerType.AI)
|
||||
@ -204,7 +204,7 @@ object UnitActions {
|
||||
else {
|
||||
// ask if we would be breaking a promise
|
||||
val text = "Do you want to break your promise to [$leaders]?"
|
||||
YesNoPopup(text, foundAction, UncivGame.Current.worldScreen).open(force = true)
|
||||
YesNoPopup(text, UncivGame.Current.worldScreen!!, action = foundAction).open(force = true)
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -275,7 +275,7 @@ object UnitActions {
|
||||
else actionList += UnitAction(type = UnitActionType.Pillage) {
|
||||
if (!worldScreen.hasOpenPopups()) {
|
||||
val pillageText = "Are you sure you want to pillage this [${unit.currentTile.improvement}]?"
|
||||
YesNoPopup(pillageText, { (pillageAction.action)(); worldScreen.shouldUpdate = true }).open()
|
||||
YesNoPopup(pillageText, UncivGame.Current.worldScreen!!) { (pillageAction.action)(); worldScreen.shouldUpdate = true }.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -853,7 +853,7 @@ object UnitActions {
|
||||
unit.destroy() // City states dont get GPs
|
||||
else
|
||||
unit.gift(recipient)
|
||||
UncivGame.Current.worldScreen.shouldUpdate = true
|
||||
UncivGame.Current.worldScreen!!.shouldUpdate = true
|
||||
}
|
||||
|
||||
return UnitAction(UnitActionType.GiftUnit, action = giftAction)
|
||||
|
@ -39,7 +39,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
||||
actionButton.pack()
|
||||
val action = {
|
||||
unitAction.action?.invoke()
|
||||
UncivGame.Current.worldScreen.shouldUpdate = true
|
||||
UncivGame.Current.worldScreen!!.shouldUpdate = true
|
||||
}
|
||||
if (unitAction.action == null) actionButton.disable()
|
||||
else {
|
||||
|
@ -87,6 +87,7 @@ internal object DesktopLauncher {
|
||||
try {
|
||||
updateRpc(game)
|
||||
} catch (ex: Exception) {
|
||||
debug("Exception while updating Discord Rich Presence", ex)
|
||||
}
|
||||
}
|
||||
} catch (ex: Throwable) {
|
||||
@ -98,10 +99,15 @@ internal object DesktopLauncher {
|
||||
private fun updateRpc(game: UncivGame) {
|
||||
if (!game.isInitialized) return
|
||||
val presence = DiscordRichPresence()
|
||||
val currentPlayerCiv = game.gameInfo.getCurrentPlayerCivilization()
|
||||
presence.details = "${currentPlayerCiv.nation.leaderName} of ${currentPlayerCiv.nation.name}"
|
||||
presence.largeImageKey = "logo" // The actual image is uploaded to the discord app / applications webpage
|
||||
presence.largeImageText = "Turn" + " " + currentPlayerCiv.gameInfo.turns
|
||||
|
||||
val gameInfo = game.gameInfo
|
||||
if (gameInfo != null) {
|
||||
val currentPlayerCiv = gameInfo.getCurrentPlayerCivilization()
|
||||
presence.details = "${currentPlayerCiv.nation.leaderName} of ${currentPlayerCiv.nation.name}"
|
||||
presence.largeImageText = "Turn" + " " + currentPlayerCiv.gameInfo.turns
|
||||
}
|
||||
|
||||
DiscordRPC.INSTANCE.Discord_UpdatePresence(presence)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user