First attempt at making Unciv Android-TV-compatible

This commit is contained in:
Yair Morgenstern 2020-12-01 23:26:01 +02:00
parent 07cee7e679
commit 0feb9bdefc
4 changed files with 123 additions and 107 deletions

View File

@ -6,12 +6,17 @@
<uses-sdk/> <uses-sdk/>
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- See https://developer.android.com/training/tv/start/start -->
<uses-feature android:name="android.software.leanback" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@drawable/uncivicon2" android:icon="@drawable/uncivicon2"
android:label="@string/app_name" android:label="@string/app_name"
android:isGame="true" android:isGame="true"
android:appCategory="game"
android:banner="@drawable/banner"
android:theme="@style/GdxTheme" > android:theme="@style/GdxTheme" >
<activity <activity
android:name="com.unciv.app.AndroidLauncher" android:name="com.unciv.app.AndroidLauncher"
@ -25,6 +30,19 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name="com.unciv.app.AndroidTvLauncher"
android:label="@string/app_name"
android:theme="@style/GdxTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".CopyToClipboardReceiver" android:exported="false" /> <receiver android:name=".CopyToClipboardReceiver" android:exported="false" />
</application> </application>

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -13,7 +13,7 @@ import com.unciv.logic.GameSaver
import com.unciv.ui.utils.ORIGINAL_FONT_SIZE import com.unciv.ui.utils.ORIGINAL_FONT_SIZE
import java.io.File import java.io.File
class AndroidLauncher : AndroidApplication() { open class AndroidLauncher : AndroidApplication() {
private var customSaveLocationHelper: CustomSaveLocationHelperAndroid? = null private var customSaveLocationHelper: CustomSaveLocationHelperAndroid? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -88,3 +88,5 @@ class AndroidLauncher : AndroidApplication() {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
} }
} }
class AndroidTvLauncher:AndroidLauncher()

View File

@ -61,15 +61,14 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
private val diplomacyButtonHolder = Table() private val diplomacyButtonHolder = Table()
private val fogOfWarButton = createFogOfWarButton() private val fogOfWarButton = createFogOfWarButton()
private val nextTurnButton = createNextTurnButton() private val nextTurnButton = createNextTurnButton()
private var nextTurnAction:()->Unit= {} private var nextTurnAction: () -> Unit = {}
private val tutorialTaskTable = Table().apply { background=ImageGetter.getBackground(ImageGetter.getBlue().lerp(Color.BLACK, 0.5f)) } private val tutorialTaskTable = Table().apply { background = ImageGetter.getBackground(ImageGetter.getBlue().lerp(Color.BLACK, 0.5f)) }
private val notificationsScroll: NotificationsScroll private val notificationsScroll: NotificationsScroll
var shouldUpdate = false var shouldUpdate = false
private var backButtonListener : InputListener private var backButtonListener: InputListener
init { init {
@ -78,13 +77,13 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
notificationsScroll = NotificationsScroll(this) notificationsScroll = NotificationsScroll(this)
// notifications are right-aligned, they take up only as much space as necessary. // notifications are right-aligned, they take up only as much space as necessary.
notificationsScroll.width = stage.width/2 notificationsScroll.width = stage.width / 2
minimapWrapper.x = stage.width - minimapWrapper.width minimapWrapper.x = stage.width - minimapWrapper.width
mapHolder.addTiles() mapHolder.addTiles()
techButtonHolder.touchable=Touchable.enabled techButtonHolder.touchable = Touchable.enabled
techButtonHolder.onClick(UncivSound.Paper) { techButtonHolder.onClick(UncivSound.Paper) {
game.setScreen(TechPickerScreen(viewingCiv)) game.setScreen(TechPickerScreen(viewingCiv))
} }
@ -94,7 +93,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
fogOfWarButton.setPosition(10f, topBar.y - fogOfWarButton.height - 10f) fogOfWarButton.setPosition(10f, topBar.y - fogOfWarButton.height - 10f)
// Don't show policies until they become relevant // Don't show policies until they become relevant
if(viewingCiv.policies.adoptedPolicies.isNotEmpty() || viewingCiv.policies.canAdoptPolicy()) { if (viewingCiv.policies.adoptedPolicies.isNotEmpty() || viewingCiv.policies.canAdoptPolicy()) {
val policyScreenButton = Button(skin) val policyScreenButton = Button(skin)
policyScreenButton.add(ImageGetter.getImage("PolicyIcons/Constitution")).size(30f).pad(15f) policyScreenButton.add(ImageGetter.getImage("PolicyIcons/Constitution")).size(30f).pad(15f)
policyScreenButton.onClick { game.setScreen(PolicyPickerScreen(this)) } policyScreenButton.onClick { game.setScreen(PolicyPickerScreen(this)) }
@ -116,8 +115,8 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
stage.addActor(diplomacyButtonHolder) stage.addActor(diplomacyButtonHolder)
stage.addActor(bottomUnitTable) stage.addActor(bottomUnitTable)
stage.addActor(bottomTileInfoTable) stage.addActor(bottomTileInfoTable)
battleTable.width = stage.width/3 battleTable.width = stage.width / 3
battleTable.x = stage.width/3 battleTable.x = stage.width / 3
stage.addActor(battleTable) stage.addActor(battleTable)
stage.addActor(unitActionsTable) stage.addActor(unitActionsTable)
@ -133,28 +132,28 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
// Don't select unit and change selectedCiv when centering as spectator // Don't select unit and change selectedCiv when centering as spectator
if (viewingCiv.isSpectator()) if (viewingCiv.isSpectator())
mapHolder.setCenterPosition(tileToCenterOn,true, false) mapHolder.setCenterPosition(tileToCenterOn, true, false)
else else
mapHolder.setCenterPosition(tileToCenterOn,true, true) mapHolder.setCenterPosition(tileToCenterOn, true, true)
if(gameInfo.gameParameters.isOnlineMultiplayer && !gameInfo.isUpToDate) if (gameInfo.gameParameters.isOnlineMultiplayer && !gameInfo.isUpToDate)
isPlayersTurn = false // until we're up to date, don't let the player do anything isPlayersTurn = false // until we're up to date, don't let the player do anything
if(gameInfo.gameParameters.isOnlineMultiplayer && !isPlayersTurn) { if (gameInfo.gameParameters.isOnlineMultiplayer && !isPlayersTurn) {
// restart the timer // restart the timer
stopMultiPlayerRefresher() stopMultiPlayerRefresher()
// isDaemon = true, in order to not block the app closing // isDaemon = true, in order to not block the app closing
multiPlayerRefresher = Timer("multiPlayerRefresh", true).apply { multiPlayerRefresher = Timer("multiPlayerRefresh", true).apply {
schedule(object : TimerTask() { //todo maybe not use timer for web request, from timer docs "Timer tasks should complete quickly." schedule(object : TimerTask() { //todo maybe not use timer for web request, from timer docs "Timer tasks should complete quickly."
override fun run() { loadLatestMultiplayerState() } override fun run() {
loadLatestMultiplayerState()
}
}, 0, 10000) // 10 seconds }, 0, 10000) // 10 seconds
} }
} }
tutorialController.allTutorialsShowedCallback = { tutorialController.allTutorialsShowedCallback = { shouldUpdate = true }
shouldUpdate = true
}
backButtonListener = onBackButtonClicked { backButtonAndESCHandler() } backButtonListener = onBackButtonClicked { backButtonAndESCHandler() }
@ -173,63 +172,63 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
} }
private fun cleanupKeyDispatcher() { private fun cleanupKeyDispatcher() {
val delKeys = keyPressDispatcher.keys.filter { it!=' ' && it!='n' } val delKeys = keyPressDispatcher.keys.filter { it != ' ' && it != 'n' }
delKeys.forEach { keyPressDispatcher.remove(it) } delKeys.forEach { keyPressDispatcher.remove(it) }
} }
private fun addKeyboardListener() { private fun addKeyboardListener() {
stage.addListener( stage.addListener(
object : InputListener() { object : InputListener() {
private val pressedKeys = mutableSetOf<Int>() private val pressedKeys = mutableSetOf<Int>()
private var infiniteAction : RepeatAction? = null private var infiniteAction: RepeatAction? = null
private val amountToMove = 30 / mapHolder.scaleX private val amountToMove = 30 / mapHolder.scaleX
private val ALLOWED_KEYS = setOf(Input.Keys.W,Input.Keys.S,Input.Keys.A,Input.Keys.D, private val ALLOWED_KEYS = setOf(Input.Keys.W, Input.Keys.S, Input.Keys.A, Input.Keys.D,
Input.Keys.UP, Input.Keys.DOWN, Input.Keys.LEFT, Input.Keys.RIGHT ) Input.Keys.UP, Input.Keys.DOWN, Input.Keys.LEFT, Input.Keys.RIGHT)
override fun keyDown(event: InputEvent?, keycode: Int): Boolean { override fun keyDown(event: InputEvent?, keycode: Int): Boolean {
if (keycode !in ALLOWED_KEYS) return false if (keycode !in ALLOWED_KEYS) return false
pressedKeys.add(keycode) pressedKeys.add(keycode)
if (infiniteAction == null) { if (infiniteAction == null) {
// create a copy of the action, because removeAction() will destroy this instance // create a copy of the action, because removeAction() will destroy this instance
infiniteAction = Actions.forever(Actions.delay(0.05f, Actions.run { whileKeyPressedLoop() })) infiniteAction = Actions.forever(Actions.delay(0.05f, Actions.run { whileKeyPressedLoop() }))
mapHolder.addAction(infiniteAction) mapHolder.addAction(infiniteAction)
}
return true
}
fun whileKeyPressedLoop() {
for (keycode in pressedKeys) {
when (keycode) {
Input.Keys.W, Input.Keys.UP -> mapHolder.scrollY -= amountToMove
Input.Keys.S, Input.Keys.DOWN -> mapHolder.scrollY += amountToMove
Input.Keys.A, Input.Keys.LEFT -> mapHolder.scrollX -= amountToMove
Input.Keys.D, Input.Keys.RIGHT -> mapHolder.scrollX += amountToMove
} }
return true
} }
mapHolder.updateVisualScroll()
}
override fun keyUp(event: InputEvent?, keycode: Int): Boolean { fun whileKeyPressedLoop() {
if (keycode !in ALLOWED_KEYS) return false for (keycode in pressedKeys) {
when (keycode) {
pressedKeys.remove(keycode) Input.Keys.W, Input.Keys.UP -> mapHolder.scrollY -= amountToMove
if (infiniteAction != null && pressedKeys.isEmpty()) { Input.Keys.S, Input.Keys.DOWN -> mapHolder.scrollY += amountToMove
// stop the loop otherwise it keeps going even after removal Input.Keys.A, Input.Keys.LEFT -> mapHolder.scrollX -= amountToMove
infiniteAction?.finish() Input.Keys.D, Input.Keys.RIGHT -> mapHolder.scrollX += amountToMove
// remove and nil the action }
mapHolder.removeAction(infiniteAction) }
infiniteAction = null mapHolder.updateVisualScroll()
}
override fun keyUp(event: InputEvent?, keycode: Int): Boolean {
if (keycode !in ALLOWED_KEYS) return false
pressedKeys.remove(keycode)
if (infiniteAction != null && pressedKeys.isEmpty()) {
// stop the loop otherwise it keeps going even after removal
infiniteAction?.finish()
// remove and nil the action
mapHolder.removeAction(infiniteAction)
infiniteAction = null
}
return true
} }
return true
} }
}
) )
} }
private fun loadLatestMultiplayerState(){ private fun loadLatestMultiplayerState() {
// Since we're on a background thread, all the UI calls in this func need to run from the // Since we're on a background thread, all the UI calls in this func need to run from the
// main thread which has a GL context // main thread which has a GL context
@ -243,14 +242,13 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
val latestGame = OnlineMultiplayer().tryDownloadGame(gameInfo.gameId) val latestGame = OnlineMultiplayer().tryDownloadGame(gameInfo.gameId)
// if we find it still isn't player's turn...nothing changed // if we find it still isn't player's turn...nothing changed
if(gameInfo.isUpToDate && gameInfo.currentPlayer==latestGame.currentPlayer) { if (gameInfo.isUpToDate && gameInfo.currentPlayer == latestGame.currentPlayer) {
Gdx.app.postRunnable { loadingGamePopup.close() } Gdx.app.postRunnable { loadingGamePopup.close() }
return return
} } else { //else we found it is the player's turn again, turn off polling and load turn
else{ //else we found it is the player's turn again, turn off polling and load turn
stopMultiPlayerRefresher() stopMultiPlayerRefresher()
latestGame.isUpToDate=true latestGame.isUpToDate = true
Gdx.app.postRunnable { game.loadGame(latestGame) } Gdx.app.postRunnable { game.loadGame(latestGame) }
} }
@ -328,50 +326,50 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
} }
updateNextTurnButton(hasOpenPopups()) // This must be before the notifications update, since its position is based on it updateNextTurnButton(hasOpenPopups()) // This must be before the notifications update, since its position is based on it
notificationsScroll.update(viewingCiv.notifications) notificationsScroll.update(viewingCiv.notifications)
notificationsScroll.setPosition(stage.width - notificationsScroll.width*0.5f - 10f, notificationsScroll.setPosition(stage.width - notificationsScroll.width * 0.5f - 10f,
nextTurnButton.y - notificationsScroll.height*0.5f - 5f) nextTurnButton.y - notificationsScroll.height * 0.5f - 5f)
} }
private fun getCurrentTutorialTask(): String { private fun getCurrentTutorialTask(): String {
val completedTasks = game.settings.tutorialTasksCompleted val completedTasks = game.settings.tutorialTasksCompleted
if(!completedTasks.contains("Move unit")) if (!completedTasks.contains("Move unit"))
return "Move a unit!\nClick on a unit > Click on a destination > Click the arrow popup" return "Move a unit!\nClick on a unit > Click on a destination > Click the arrow popup"
if(!completedTasks.contains("Found city")) if (!completedTasks.contains("Found city"))
return "Found a city!\nSelect the Settler (flag unit) > Click on 'Found city' (bottom-left corner)" return "Found a city!\nSelect the Settler (flag unit) > Click on 'Found city' (bottom-left corner)"
if(!completedTasks.contains("Enter city screen")) if (!completedTasks.contains("Enter city screen"))
return "Enter the city screen!\nClick the city button twice" return "Enter the city screen!\nClick the city button twice"
if(!completedTasks.contains("Pick technology")) if (!completedTasks.contains("Pick technology"))
return "Pick a technology to research!\nClick on the tech button (greenish, top left) > " + return "Pick a technology to research!\nClick on the tech button (greenish, top left) > " +
"\n select technology > click 'Research' (bottom right)" "\n select technology > click 'Research' (bottom right)"
if(!completedTasks.contains("Pick construction")) if (!completedTasks.contains("Pick construction"))
return "Pick a construction!\nEnter city screen > Click on a unit or building (bottom left side) >" + return "Pick a construction!\nEnter city screen > Click on a unit or building (bottom left side) >" +
" \n click 'add to queue'" " \n click 'add to queue'"
if(!completedTasks.contains("Pass a turn")) if (!completedTasks.contains("Pass a turn"))
return "Pass a turn!\nCycle through units with 'Next unit' > Click 'Next turn'" return "Pass a turn!\nCycle through units with 'Next unit' > Click 'Next turn'"
if(!completedTasks.contains("Reassign worked tiles")) if (!completedTasks.contains("Reassign worked tiles"))
return "Reassign worked tiles!\nEnter city screen > click the assigned (green) tile to unassign > " + return "Reassign worked tiles!\nEnter city screen > click the assigned (green) tile to unassign > " +
"\n click an unassigned tile to assign population" "\n click an unassigned tile to assign population"
if(!completedTasks.contains("Meet another civilization")) if (!completedTasks.contains("Meet another civilization"))
return "Meet another civilization!\nExplore the map until you encounter another civilization!" return "Meet another civilization!\nExplore the map until you encounter another civilization!"
if(!completedTasks.contains("Open the options table")) if (!completedTasks.contains("Open the options table"))
return "Open the options table!\nClick the menu button (top left) > click 'Options'" return "Open the options table!\nClick the menu button (top left) > click 'Options'"
if(!completedTasks.contains("Construct an improvement")) if (!completedTasks.contains("Construct an improvement"))
return "Construct an improvement!\nConstruct a Worker unit > Move to a Plains or Grassland tile > " + return "Construct an improvement!\nConstruct a Worker unit > Move to a Plains or Grassland tile > " +
"\n Click 'Create improvement' (above the unit table, bottom left)" + "\n Click 'Create improvement' (above the unit table, bottom left)" +
"\n > Choose the farm > \n Leave the worker there until it's finished" "\n > Choose the farm > \n Leave the worker there until it's finished"
if(!completedTasks.contains("Create a trade route") if (!completedTasks.contains("Create a trade route")
&& viewingCiv.citiesConnectedToCapitalToMediums.any { it.key.civInfo==viewingCiv }) && viewingCiv.citiesConnectedToCapitalToMediums.any { it.key.civInfo == viewingCiv })
game.settings.addCompletedTutorialTask("Create a trade route") game.settings.addCompletedTutorialTask("Create a trade route")
if(viewingCiv.cities.size>1 && !completedTasks.contains("Create a trade route")) if (viewingCiv.cities.size > 1 && !completedTasks.contains("Create a trade route"))
return "Create a trade route!\nConstruct roads between your capital and another city" + return "Create a trade route!\nConstruct roads between your capital and another city" +
"\nOr, automate your worker and let him get to that eventually" "\nOr, automate your worker and let him get to that eventually"
if(viewingCiv.isAtWar() && !completedTasks.contains("Conquer a city")) if (viewingCiv.isAtWar() && !completedTasks.contains("Conquer a city"))
return "Conquer a city!\nBring an enemy city down to low health > " + return "Conquer a city!\nBring an enemy city down to low health > " +
"\nEnter the city with a melee unit" "\nEnter the city with a melee unit"
if(viewingCiv.getCivUnits().any { it.type.isAirUnit() } && !completedTasks.contains("Move an air unit")) if (viewingCiv.getCivUnits().any { it.type.isAirUnit() } && !completedTasks.contains("Move an air unit"))
return "Move an air unit!\nSelect an air unit > select another city within range > " + return "Move an air unit!\nSelect an air unit > select another city within range > " +
"\nMove the unit to the other city" "\nMove the unit to the other city"
if(!completedTasks.contains("See your stats breakdown")) if (!completedTasks.contains("See your stats breakdown"))
return "See your stats breakdown!\nEnter the Overview screen (top right corner) >" + return "See your stats breakdown!\nEnter the Overview screen (top right corner) >" +
"\nClick on 'Stats'" "\nClick on 'Stats'"
@ -398,9 +396,9 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
// ... all tiles around those in range of an average melee unit // ... all tiles around those in range of an average melee unit
// -> and now we look for a unit that could do the conquering because it's ours // -> and now we look for a unit that could do the conquering because it's ours
// no matter whether civilian, air or ranged, tell user he needs melee // no matter whether civilian, air or ranged, tell user he needs melee
.any { it.getUnits().any { unit -> unit.civInfo == viewingCiv} } .any { it.getUnits().any { unit -> unit.civInfo == viewingCiv } }
} }
displayTutorial(Tutorial.AfterConquering) { viewingCiv.cities.any{it.hasJustBeenConquered} } displayTutorial(Tutorial.AfterConquering) { viewingCiv.cities.any { it.hasJustBeenConquered } }
displayTutorial(Tutorial.InjuredUnits) { gameInfo.getCurrentPlayerCivilization().getCivUnits().any { it.health < 100 } } displayTutorial(Tutorial.InjuredUnits) { gameInfo.getCurrentPlayerCivilization().getCivUnits().any { it.health < 100 } }
@ -409,8 +407,8 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
private fun updateDiplomacyButton(civInfo: CivilizationInfo) { private fun updateDiplomacyButton(civInfo: CivilizationInfo) {
diplomacyButtonHolder.clear() diplomacyButtonHolder.clear()
if(!civInfo.isDefeated() && !civInfo.isSpectator() && civInfo.getKnownCivs() if (!civInfo.isDefeated() && !civInfo.isSpectator() && civInfo.getKnownCivs()
.filterNot { it==viewingCiv || it.isBarbarian() } .filterNot { it == viewingCiv || it.isBarbarian() }
.any()) { .any()) {
displayTutorial(Tutorial.OtherCivEncountered) displayTutorial(Tutorial.OtherCivEncountered)
val btn = "Diplomacy".toTextButton() val btn = "Diplomacy".toTextButton()
@ -439,7 +437,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
val buttonPic = Table() val buttonPic = Table()
buttonPic.background = ImageGetter.getRoundedEdgeTableBackground(colorFromRGB(7, 46, 43)) buttonPic.background = ImageGetter.getRoundedEdgeTableBackground(colorFromRGB(7, 46, 43))
buttonPic.defaults().pad(20f) buttonPic.defaults().pad(20f)
val text = if(viewingCiv.tech.canResearchTech()) "{Pick a tech}!" else "Technologies" val text = if (viewingCiv.tech.canResearchTech()) "{Pick a tech}!" else "Technologies"
buttonPic.add(text.toLabel(Color.WHITE, 30)) buttonPic.add(text.toLabel(Color.WHITE, 30))
techButtonHolder.add(buttonPic) techButtonHolder.add(buttonPic)
} }
@ -474,7 +472,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
nextTurnButton.label.setFontSize(30) nextTurnButton.label.setFontSize(30)
nextTurnButton.labelCell.pad(10f) nextTurnButton.labelCell.pad(10f)
val nextTurnActionWrapped = { nextTurnAction() } val nextTurnActionWrapped = { nextTurnAction() }
nextTurnButton.onClick (nextTurnActionWrapped) nextTurnButton.onClick(nextTurnActionWrapped)
keyPressDispatcher[' '] = nextTurnActionWrapped keyPressDispatcher[' '] = nextTurnActionWrapped
keyPressDispatcher['n'] = nextTurnActionWrapped keyPressDispatcher['n'] = nextTurnActionWrapped
@ -486,13 +484,13 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
shouldUpdate = true shouldUpdate = true
thread(name="NextTurn") { // on a separate thread so the user can explore their world while we're passing the turn thread(name = "NextTurn") { // on a separate thread so the user can explore their world while we're passing the turn
val gameInfoClone = gameInfo.clone() val gameInfoClone = gameInfo.clone()
gameInfoClone.setTransients() gameInfoClone.setTransients()
try { try {
gameInfoClone.nextTurn() gameInfoClone.nextTurn()
if(gameInfo.gameParameters.isOnlineMultiplayer) { if (gameInfo.gameParameters.isOnlineMultiplayer) {
try { try {
OnlineMultiplayer().tryUploadGame(gameInfoClone) OnlineMultiplayer().tryUploadGame(gameInfoClone)
} catch (ex: Exception) { } catch (ex: Exception) {
@ -520,7 +518,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
// do this on main thread - it's the only one that has a GL context to create images from // do this on main thread - it's the only one that has a GL context to create images from
Gdx.app.postRunnable { Gdx.app.postRunnable {
fun createNewWorldScreen(){ fun createNewWorldScreen() {
val newWorldScreen = WorldScreen(gameInfoClone.getPlayerToViewAs()) val newWorldScreen = WorldScreen(gameInfoClone.getPlayerToViewAs())
newWorldScreen.mapHolder.scrollX = mapHolder.scrollX newWorldScreen.mapHolder.scrollX = mapHolder.scrollX
newWorldScreen.mapHolder.scrollY = mapHolder.scrollY newWorldScreen.mapHolder.scrollY = mapHolder.scrollY
@ -542,7 +540,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
createNewWorldScreen() createNewWorldScreen()
} }
if(shouldAutoSave) { if (shouldAutoSave) {
val newWorldScreen = game.worldScreen val newWorldScreen = game.worldScreen
newWorldScreen.waitingForAutosave = true newWorldScreen.waitingForAutosave = true
newWorldScreen.shouldUpdate = true newWorldScreen.shouldUpdate = true
@ -556,10 +554,10 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
} }
} }
private class NextTurnAction(val text:String, val color:Color, val action:()->Unit) private class NextTurnAction(val text: String, val color: Color, val action: () -> Unit)
private fun updateNextTurnButton(isSomethingOpen: Boolean) { private fun updateNextTurnButton(isSomethingOpen: Boolean) {
val action:NextTurnAction = getNextTurnAction() val action: NextTurnAction = getNextTurnAction()
nextTurnAction = action.action nextTurnAction = action.action
nextTurnButton.setText(action.text.tr()) nextTurnButton.setText(action.text.tr())
@ -568,6 +566,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
nextTurnButton.isEnabled = !isSomethingOpen && isPlayersTurn && !waitingForAutosave nextTurnButton.isEnabled = !isSomethingOpen && isPlayersTurn && !waitingForAutosave
nextTurnButton.setPosition(stage.width - nextTurnButton.width - 10f, topBar.y - nextTurnButton.height - 10f) nextTurnButton.setPosition(stage.width - nextTurnButton.width - 10f, topBar.y - nextTurnButton.height - 10f)
} }
fun enableNextTurnButtonAfterOptions() { fun enableNextTurnButtonAfterOptions() {
nextTurnButton.isEnabled = isPlayersTurn && !waitingForAutosave nextTurnButton.isEnabled = isPlayersTurn && !waitingForAutosave
} }
@ -598,7 +597,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
game.setScreen(TechPickerScreen(viewingCiv.tech.freeTechs != 0, viewingCiv)) game.setScreen(TechPickerScreen(viewingCiv.tech.freeTechs != 0, viewingCiv))
} }
viewingCiv.policies.shouldOpenPolicyPicker || (viewingCiv.policies.freePolicies > 0 && viewingCiv.policies.canAdoptPolicy()) -> viewingCiv.policies.shouldOpenPolicyPicker || (viewingCiv.policies.freePolicies > 0 && viewingCiv.policies.canAdoptPolicy()) ->
NextTurnAction("Pick a policy", Color.VIOLET) { NextTurnAction("Pick a policy", Color.VIOLET) {
game.setScreen(PolicyPickerScreen(this)) game.setScreen(PolicyPickerScreen(this))
viewingCiv.policies.shouldOpenPolicyPicker = false viewingCiv.policies.shouldOpenPolicyPicker = false
@ -634,10 +633,10 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
super.render(delta) super.render(delta)
} }
private fun showTutorialsOnNextTurn(){ private fun showTutorialsOnNextTurn() {
if (!game.settings.showTutorials) return if (!game.settings.showTutorials) return
displayTutorial(Tutorial.SlowStart) displayTutorial(Tutorial.SlowStart)
displayTutorial(Tutorial.CityExpansion){ viewingCiv.cities.any { it.expansion.tilesClaimed()>0 } } displayTutorial(Tutorial.CityExpansion) { viewingCiv.cities.any { it.expansion.tilesClaimed() > 0 } }
displayTutorial(Tutorial.BarbarianEncountered) { viewingCiv.viewableTiles.any { it.getUnits().any { unit -> unit.civInfo.isBarbarian() } } } displayTutorial(Tutorial.BarbarianEncountered) { viewingCiv.viewableTiles.any { it.getUnits().any { unit -> unit.civInfo.isBarbarian() } } }
displayTutorial(Tutorial.RoadsAndRailroads) { viewingCiv.cities.size > 2 } displayTutorial(Tutorial.RoadsAndRailroads) { viewingCiv.cities.size > 2 }
displayTutorial(Tutorial.Happiness) { viewingCiv.getHappiness() < 5 } displayTutorial(Tutorial.Happiness) { viewingCiv.getHappiness() < 5 }
@ -646,11 +645,11 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
displayTutorial(Tutorial.IdleUnits) { gameInfo.turns >= 50 && game.settings.checkForDueUnits } displayTutorial(Tutorial.IdleUnits) { gameInfo.turns >= 50 && game.settings.checkForDueUnits }
displayTutorial(Tutorial.ContactMe) { gameInfo.turns >= 100 } displayTutorial(Tutorial.ContactMe) { gameInfo.turns >= 100 }
val resources = viewingCiv.detailedCivResources.asSequence().filter { it.origin == "All" } // Avoid full list copy val resources = viewingCiv.detailedCivResources.asSequence().filter { it.origin == "All" } // Avoid full list copy
displayTutorial(Tutorial.LuxuryResource) { resources.any { it.resource.resourceType==ResourceType.Luxury } } displayTutorial(Tutorial.LuxuryResource) { resources.any { it.resource.resourceType == ResourceType.Luxury } }
displayTutorial(Tutorial.StrategicResource) { resources.any { it.resource.resourceType==ResourceType.Strategic} } displayTutorial(Tutorial.StrategicResource) { resources.any { it.resource.resourceType == ResourceType.Strategic } }
displayTutorial(Tutorial.EnemyCity) { displayTutorial(Tutorial.EnemyCity) {
viewingCiv.getKnownCivs().asSequence().filter { viewingCiv.isAtWarWith(it) } viewingCiv.getKnownCivs().asSequence().filter { viewingCiv.isAtWarWith(it) }
.flatMap { it.cities.asSequence() }.any { viewingCiv.exploredTiles.contains(it.location) } .flatMap { it.cities.asSequence() }.any { viewingCiv.exploredTiles.contains(it.location) }
} }
displayTutorial(Tutorial.ApolloProgram) { viewingCiv.hasUnique("Enables construction of Spaceship parts") } displayTutorial(Tutorial.ApolloProgram) { viewingCiv.hasUnique("Enables construction of Spaceship parts") }
displayTutorial(Tutorial.SiegeUnits) { viewingCiv.getCivUnits().any { it.type == UnitType.Siege } } displayTutorial(Tutorial.SiegeUnits) { viewingCiv.getCivUnits().any { it.type == UnitType.Siege } }
@ -693,17 +692,14 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
promptWindow.addGoodSizedLabel("Do you want to exit the game?".tr()) promptWindow.addGoodSizedLabel("Do you want to exit the game?".tr())
promptWindow.row() promptWindow.row()
promptWindow.addButton("Yes") { Gdx.app.exit() } promptWindow.addButton("Yes") { Gdx.app.exit() }
promptWindow.addButton("No") { promptWindow.addButton("No") { promptWindow.close() }
promptWindow.close()
}
// show the dialog // show the dialog
promptWindow.open (true) // true = always on top promptWindow.open(true) // true = always on top
} }
companion object { companion object {
// this object must not be created multiple times // this object must not be created multiple times
private var multiPlayerRefresher : Timer? = null private var multiPlayerRefresher: Timer? = null
} }
} }