From 4c19347a897f7c31bd677214bd440eac2e140709 Mon Sep 17 00:00:00 2001 From: Colin Vanden Heuvel Date: Mon, 25 Oct 2021 11:09:03 -0500 Subject: [PATCH] Provide more information to waiting players in multiplayer (#5508) * Add some very small Quality-of-Life improvements for multiplayer games - GameInfo.kt - Add timestamp for the start of the last turn to save info, hopefully this will enable a multiplayer turn timer in the near future - MultiplayerScreen.kt - Current turn indicator for multiplayer games now shows for how long it has been the current player's turn. - WorldScreen.kt - Next Turn Action will display which player we are waiting for rather than the generic "Waiting for other players..." * Update text for translations and add better elapsed times template.properties - Add translation templates for waiting turn information German.properties - Provide German translation for waiting turn info Japanese.properties - Provide Japanese translation for waiting turn info MultiplayerScreen.kt - Add translation brackets for waiting turn info - Add a function which determines whether to represent elapsed time in Minutes, Hours, or Days (and does so) WorldScreen.kt - Add translation brackets for waiting turn info * Fix line translated endings as per request MultiplayerScreen.kt - Translation for the "Last refresh:/Current Turn:" display no longer includes line endings - "Last refresh:/Current Turn:" display now uses LF line endings only * Show generic "Waiting for" message in single player WorldScreen.kt - Place an additional condition for getNextTurnAction which selects the generic "Waiting for" message in single player and the civ-specific one in multiplayer Co-authored-by: Colin S. Vanden Heuvel --- .gitignore | 3 +++ .../jsons/translations/German.properties | 6 ++++++ .../jsons/translations/Japanese.properties | 6 ++++++ .../jsons/translations/template.properties | 6 ++++++ core/src/com/unciv/logic/GameInfo.kt | 3 +++ .../unciv/ui/multiplayer/MultiplayerScreen.kt | 20 ++++++++++++++----- .../com/unciv/ui/worldscreen/WorldScreen.kt | 3 ++- 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 28807ac488..32bf49eb39 100644 --- a/.gitignore +++ b/.gitignore @@ -139,3 +139,6 @@ android/assets/SaveFiles/ android/assets/scenarios/ android/assets/MultiplayerGames/ android/assets/music/ + +# Visual Studio Code +.vscode/ diff --git a/android/assets/jsons/translations/German.properties b/android/assets/jsons/translations/German.properties index de22ca4c0b..e6821b7545 100644 --- a/android/assets/jsons/translations/German.properties +++ b/android/assets/jsons/translations/German.properties @@ -443,6 +443,11 @@ Resign = Aufgeben Are you sure you want to resign? = Willst du wirklich aufgeben? You can only resign if it's your turn = Du kannst nur aufgeben, wenn du am Zug bist [civName] resigned and is now controlled by AI = [civName] hat aufgegeben und wird nun von der KI gespielt +Last refresh: [time] [timeUnit] ago = Letzte Aktualisierung: Vor [time] [timeUnit] +Current Turn: [civName] since [time] [timeUnit] ago = Aktuelle Runde: [civName] seit [time] [timeUnit] +Minutes = Minuten +Hours = Stunden +Days = Tage # Save game menu @@ -642,6 +647,7 @@ A Great Person joins you! = Eine Große Persönlichkeit schließt sich dir an! Working... = Bitte warten... Waiting for other players... = Warte auf andere Spieler... +Waiting for [civName]... = Warte auf [civName]... in = in Next turn = Nächste Runde [currentPlayerCiv] ready? = [currentPlayerCiv] bereit? diff --git a/android/assets/jsons/translations/Japanese.properties b/android/assets/jsons/translations/Japanese.properties index f8629131e1..933015d7a1 100644 --- a/android/assets/jsons/translations/Japanese.properties +++ b/android/assets/jsons/translations/Japanese.properties @@ -514,6 +514,11 @@ Resign = やめる Are you sure you want to resign? = ほんとにやめますか? You can only resign if it's your turn = やめることができるのは自分のターンの時のみです [civName] resigned and is now controlled by AI = [civName]がやめました。代わりにAIがコントロールしています。 +Last refresh: [time] [timeUnit] ago = 最終進行:[time][timeUnit]前 +Current Turn: [civName] since [time] [timeUnit] ago = 現在のターン:[civName]、[time][timeUnit]前から +Minutes = 数分 +Hours = 時間 +Days = 数日 # Save game menu @@ -756,6 +761,7 @@ A Great Person joins you! = Working... = ロード中… Waiting for other players... = 他のプレイヤーを待っています… +Waiting for [civName]... = [civName]を待っています… in = 建設 Next turn = 次のターン [currentPlayerCiv] ready? = [currentPlayerCiv] レディー? diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 906dfadc89..47df073581 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -445,6 +445,11 @@ Resign = Are you sure you want to resign? = You can only resign if it's your turn = [civName] resigned and is now controlled by AI = +Last refresh: [time] [timeUnit] ago = +Current Turn: [civName] since [time] [timeUnit] ago = +Minutes = +Hours = +Days = # Save game menu @@ -645,6 +650,7 @@ A Great Person joins you! = Working... = Waiting for other players... = +Waiting for [civName]... = in = Next turn = [currentPlayerCiv] ready? = diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index ea23ad8d75..ed779b2e4d 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -34,6 +34,7 @@ class GameInfo { var turns = 0 var oneMoreTurnMode = false var currentPlayer = "" + var currentTurnStartTime = 0L var gameId = UUID.randomUUID().toString() // random string // Maps a civ to the civ they voted for @@ -88,6 +89,7 @@ class GameInfo { toReturn.barbarians = barbarians.clone() toReturn.religions.putAll(religions.map { Pair(it.key, it.value.clone()) }) toReturn.currentPlayer = currentPlayer + toReturn.currentTurnStartTime = currentTurnStartTime toReturn.turns = turns toReturn.difficulty = difficulty toReturn.gameParameters = gameParameters @@ -240,6 +242,7 @@ class GameInfo { switchTurn() } + currentTurnStartTime = System.currentTimeMillis() currentPlayer = thisPlayer.civName currentPlayerCiv = getCivilization(currentPlayer) if (currentPlayerCiv.isSpectator()) currentPlayerCiv.popupAlerts.clear() // no popups for spectators diff --git a/core/src/com/unciv/ui/multiplayer/MultiplayerScreen.kt b/core/src/com/unciv/ui/multiplayer/MultiplayerScreen.kt index 1d05a39549..22dc9a3ef9 100644 --- a/core/src/com/unciv/ui/multiplayer/MultiplayerScreen.kt +++ b/core/src/com/unciv/ui/multiplayer/MultiplayerScreen.kt @@ -210,6 +210,7 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen() val gameTable = Table() val turnIndicator = Table() var currentTurnUser = "" + var lastTurnMillis = 0L try { turnIndicator.add(ImageGetter.getImage("EmojiIcons/Turn")) @@ -218,6 +219,17 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen() val lastModifiedMillis = gameSaveFile.lastModified() val gameButton = gameSaveFile.name().toTextButton() + + //TODO: replace this with nice formatting using kotlin.time.DurationUnit (once it is no longer experimental) + fun formattedElapsedTime(lastMillis: Long): String { + val elapsedMinutes = (System.currentTimeMillis() - lastMillis) / 60000 + return when { + elapsedMinutes < 120 -> "[$elapsedMinutes] [Minutes]" + elapsedMinutes < 2880 -> "[${elapsedMinutes / 60}] [Hours]" + else -> "[${elapsedMinutes / 1440}] [Days]" + } + } + gameButton.onClick { selectedGameFile = gameSaveFile if (multiplayerGames[gameSaveFile] != null) { @@ -228,11 +240,8 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen() editButton.enable() rightSideButton.enable() - - //get Minutes since last modified - val lastSavedMinutesAgo = (System.currentTimeMillis() - lastModifiedMillis) / 60000 - var descriptionText = "Last refresh: [$lastSavedMinutesAgo] minutes ago".tr() + "\r\n" - descriptionText += "Current Turn:".tr() + " ${currentTurnUser}\r\n" + var descriptionText = "Last refresh: ${formattedElapsedTime(lastModifiedMillis)} ago".tr() + "\n" + descriptionText += "Current Turn: [$currentTurnUser] since ${formattedElapsedTime(lastTurnMillis)} ago".tr() + "\n" descriptionLabel.setText(descriptionText) } @@ -260,6 +269,7 @@ class MultiplayerScreen(previousScreen: CameraStageBaseScreen) : PickerScreen() } //set variable so it can be displayed when gameButton.onClick gets called currentTurnUser = game.currentPlayer + lastTurnMillis = game.currentTurnStartTime } } catch (usx: UncivShowableException) { //Gets thrown when mods are not installed diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index adfead82b7..9c0b559e29 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -683,7 +683,8 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Cam private fun getNextTurnAction(): NextTurnAction { return when { - !isPlayersTurn -> NextTurnAction("Waiting for other players...", Color.GRAY) {} + !isPlayersTurn && gameInfo.gameParameters.isOnlineMultiplayer -> NextTurnAction("Waiting for [${gameInfo.currentPlayerCiv}]...", Color.GRAY) {} + !isPlayersTurn && !gameInfo.gameParameters.isOnlineMultiplayer -> NextTurnAction("Waiting for other players...", Color.GRAY) {} viewingCiv.shouldGoToDueUnit() -> NextTurnAction("Next unit", Color.LIGHT_GRAY) {