check for internet before starting a mp game to avoid freeze (#6679)

* Fixed issue #6649 by checking for internet connection before starting the game if "online multiplayer" is selected
Many thanks to SomeTroglodyte for most of the code and for explanations

* check for internet before starting a mp game to avoid freeze

Fixed issue #6649 by checking for internet connection before starting the game if "online multiplayer" is selected.

Many thanks to SomeTroglodyte for most of the code and for explanations. A slight modification has been done to the code to catch an error caused by InetAddress

* Revert "Merge remote-tracking branch 'origin/master-noInternet' into master-noInternet"

This reverts commit bd6474b50d, reversing
changes made to f52ad60b51.
This commit is contained in:
alexban011 2022-05-03 00:41:08 +03:00 committed by GitHub
parent 031cb4fc14
commit 898b1ca056
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 25 deletions

View File

@ -35,15 +35,15 @@ open class AndroidLauncher : AndroidApplication() {
val fontFamily = settings.fontFamily
// Manage orientation lock
val limitOrientationsHelper = LimitOrientationsHelperAndroid(this)
limitOrientationsHelper.allowPortrait(settings.allowAndroidPortrait)
val platformSpecificHelper = PlatformSpecificHelpersAndroid(this)
platformSpecificHelper.allowPortrait(settings.allowAndroidPortrait)
val androidParameters = UncivGameParameters(
version = BuildConfig.VERSION_NAME,
crashReportSysInfo = CrashReportSysInfoAndroid,
fontImplementation = NativeFontAndroid(Fonts.ORIGINAL_FONT_SIZE.toInt(), fontFamily),
customSaveLocationHelper = customSaveLocationHelper,
limitOrientationsHelper = limitOrientationsHelper
platformSpecificHelper = platformSpecificHelper
)
game = UncivGame(androidParameters)

View File

@ -1,15 +1,19 @@
package com.unciv.app
import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import com.unciv.ui.utils.LimitOrientationsHelper
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import com.unciv.ui.utils.GeneralPlatformSpecificHelpers
/** See also interface [LimitOrientationsHelper].
/** See also interface [GeneralPlatformSpecificHelpers].
*
* The Android implementation (currently the only one) effectively ends up doing
* [Activity.setRequestedOrientation]
*/
class LimitOrientationsHelperAndroid(private val activity: Activity) : LimitOrientationsHelper {
class PlatformSpecificHelpersAndroid(private val activity: Activity) : GeneralPlatformSpecificHelpers {
/*
Sources for Info about current orientation in case need:
val windowManager = (activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager)
@ -28,4 +32,15 @@ Sources for Info about current orientation in case need:
// Comparison ensures ActivityTaskManager.getService().setRequestedOrientation isn't called unless necessary
if (activity.requestedOrientation != orientation) activity.requestedOrientation = orientation
}
override fun isInternetConnected(): Boolean {
val connectivityManager = activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
for (network in connectivityManager.allNetworks) {
val networkCapabilities = connectivityManager.getNetworkCapabilities(network) ?: continue
val isInternet = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
val info = connectivityManager.getNetworkInfo(network) ?: continue
if (isInternet && info.isConnected) return true
}
return false
}
}

View File

@ -36,7 +36,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
val fontImplementation = parameters.fontImplementation
val consoleMode = parameters.consoleMode
val customSaveLocationHelper = parameters.customSaveLocationHelper
val limitOrientationsHelper = parameters.limitOrientationsHelper
val platformSpecificHelper = parameters.platformSpecificHelper
private val audioExceptionHelper = parameters.audioExceptionHelper
var deepLinkedMultiplayerGame: String? = null
@ -167,7 +167,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
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()
}
fun tryLoadDeepLinkedGame() {
if (deepLinkedMultiplayerGame != null) {
try {
@ -205,7 +205,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
override fun dispose() {
Gdx.input.inputProcessor = null // don't allow ANRs when shutting down, that's silly
cancelDiscordEvent?.invoke()
Sounds.clearCache()
if (::musicController.isInitialized) musicController.gracefulShutdown() // Do allow fade-out
@ -214,7 +214,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
val numThreads = Thread.activeCount()
val threadList = Array(numThreads) { _ -> Thread() }
Thread.enumerate(threadList)
if (isGameInfoInitialized()) {
val autoSaveThread = threadList.firstOrNull { it.name == "Autosave" }
if (autoSaveThread != null && autoSaveThread.isAlive) {

View File

@ -3,7 +3,7 @@ package com.unciv
import com.unciv.logic.CustomSaveLocationHelper
import com.unciv.ui.crashhandling.CrashReportSysInfo
import com.unciv.ui.utils.AudioExceptionHelper
import com.unciv.ui.utils.LimitOrientationsHelper
import com.unciv.ui.utils.GeneralPlatformSpecificHelpers
import com.unciv.ui.utils.NativeFontImplementation
class UncivGameParameters(val version: String,
@ -12,6 +12,6 @@ class UncivGameParameters(val version: String,
val fontImplementation: NativeFontImplementation? = null,
val consoleMode: Boolean = false,
val customSaveLocationHelper: CustomSaveLocationHelper? = null,
val limitOrientationsHelper: LimitOrientationsHelper? = null,
val platformSpecificHelper: GeneralPlatformSpecificHelpers? = null,
val audioExceptionHelper: AudioExceptionHelper? = null
)

View File

@ -71,6 +71,13 @@ class NewGameScreen(
rightSideButton.setText("Start game!".tr())
rightSideButton.onClick {
if (gameSetupInfo.gameParameters.isOnlineMultiplayer) {
if (UncivGame.Current.platformSpecificHelper?.isInternetConnected() != true) {
val noInternetConnectionPopup = Popup(this)
noInternetConnectionPopup.addGoodSizedLabel("No internet connection!".tr()).row()
noInternetConnectionPopup.addCloseButton()
noInternetConnectionPopup.open()
return@onClick
}
for (player in gameSetupInfo.gameParameters.players.filter { it.playerType == PlayerType.Human }) {
try {
UUID.fromString(IdChecker.checkAndReturnPlayerUuid(player.playerId))

View File

@ -2,15 +2,16 @@ package com.unciv.ui.utils
import com.unciv.models.metadata.GameSettings
/** Interface to support managing orientations
*
* You can turn a mobile device on its side or upside down, and a mobile OS may or may not allow the
* position changes to automatically result in App orientation changes. This is about limiting that feature.
*/
interface LimitOrientationsHelper {
/** Interface to support various platform-specific tools */
interface GeneralPlatformSpecificHelpers {
/** Pass a Boolean setting as used in [allowAndroidPortrait][GameSettings.allowAndroidPortrait] to the OS.
*
* You can turn a mobile device on its side or upside down, and a mobile OS may or may not allow the
* position changes to automatically result in App orientation changes. This is about limiting that feature.
* @param allow `true`: allow all orientations (follows sensor as limited by OS settings)
* `false`: allow only landscape orientations (both if supported, otherwise default landscape only)
*/
fun allowPortrait(allow: Boolean)
fun isInternetConnected(): Boolean
}

View File

@ -108,7 +108,7 @@ class OptionsPopup(val previousScreen: BaseScreen) : Popup(previousScreen) {
addCloseButton {
previousScreen.game.musicController.onChange(null)
previousScreen.game.limitOrientationsHelper?.allowPortrait(settings.allowAndroidPortrait)
previousScreen.game.platformSpecificHelper?.allowPortrait(settings.allowAndroidPortrait)
if (previousScreen is WorldScreen)
previousScreen.enableNextTurnButtonAfterOptions()
}.padBottom(10f)
@ -270,17 +270,17 @@ class OptionsPopup(val previousScreen: BaseScreen) : Popup(previousScreen) {
val connectionToServerButton = "Check connection to server".toTextButton()
val textToShowForMultiplayerAddress =
val textToShowForMultiplayerAddress =
if (settings.multiplayerServer != Constants.dropboxMultiplayerServer) settings.multiplayerServer
else "https://..."
val multiplayerServerTextField = TextField(textToShowForMultiplayerAddress, BaseScreen.skin)
multiplayerServerTextField.programmaticChangeEvents = true
val serverIpTable = Table()
serverIpTable.add("Server address".toLabel().onClick {
serverIpTable.add("Server address".toLabel().onClick {
multiplayerServerTextField.text = Gdx.app.clipboard.contents
}).row()
multiplayerServerTextField.onChange {
multiplayerServerTextField.onChange {
settings.multiplayerServer = multiplayerServerTextField.text
settings.save()
connectionToServerButton.isEnabled = multiplayerServerTextField.text != Constants.dropboxMultiplayerServer
@ -318,11 +318,11 @@ class OptionsPopup(val previousScreen: BaseScreen) : Popup(previousScreen) {
addMaxZoomSlider()
if (previousScreen.game.limitOrientationsHelper != null) {
if (previousScreen.game.platformSpecificHelper != null) {
addCheckbox("Enable portrait orientation", settings.allowAndroidPortrait) {
settings.allowAndroidPortrait = it
// Note the following might close the options screen indirectly and delayed
previousScreen.game.limitOrientationsHelper.allowPortrait(it)
previousScreen.game.platformSpecificHelper.allowPortrait(it)
}
}

View File

@ -95,4 +95,4 @@ class CustomSaveLocationHelperDesktop : CustomSaveLocationHelper {
}
loadCompleteCallback(gameInfo, exception)
}
}
}

View File

@ -52,6 +52,7 @@ internal object DesktopLauncher {
fontImplementation = NativeFontDesktop(Fonts.ORIGINAL_FONT_SIZE.toInt(), settings.fontFamily),
customSaveLocationHelper = CustomSaveLocationHelperDesktop(),
crashReportSysInfo = CrashReportSysInfoDesktop(),
platformSpecificHelper = PlatformSpecificHelpersDesktop(),
audioExceptionHelper = HardenGdxAudio()
)

View File

@ -0,0 +1,18 @@
package com.unciv.app.desktop
import com.unciv.ui.utils.GeneralPlatformSpecificHelpers
import java.net.InetAddress
class PlatformSpecificHelpersDesktop : GeneralPlatformSpecificHelpers {
override fun allowPortrait(allow: Boolean) {
// No need to do anything
}
override fun isInternetConnected(): Boolean {
return try {
InetAddress.getByName("8.8.8.8").isReachable(500) // Parameter timeout in milliseconds
} catch (ex: Throwable) {
false
}
}
}