diff options
| author | JMC47 <JMC4789@gmail.com> | 2026-10-22 13:12:33 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-10-22 13:12:33 -0400 |
| commit | 2c805fee8f232d090c454381bb1b8422242345e1 (patch) | |
| tree | b564d1524b09695f3fda8730d3595f1f66a29beb /Source/Android/app/src | |
| parent | cf5cb7ef81c3e8e7af5c9d566334219ffda9f68b (diff) | |
| parent | 66657167e357597b99b0957a4ee27a0da8b36571 (diff) | |
Merge pull request #14734 from tom-pratt/trigger-game-digest-check
Android: Trigger netplay game digest check
Diffstat (limited to 'Source/Android/app/src')
7 files changed, 91 insertions, 15 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt index d44e70ba09..8e6ac314ff 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt @@ -186,6 +186,12 @@ class NetplaySession( fun startGame() = nativeStartGame() + fun computeGameDigest() = nativeComputeGameDigest() + + fun computeSDCardDigest() = nativeComputeSDCardDigest() + + fun abortGameDigest() = nativeAbortGameDigest() + fun getPort(): Int = nativeGetPort() fun getExternalIpAddress(): String? = nativeGetExternalIpAddress() @@ -284,6 +290,12 @@ class NetplaySession( private external fun nativeStartGame() + private external fun nativeComputeGameDigest() + + private external fun nativeComputeSDCardDigest() + + private external fun nativeAbortGameDigest() + private external fun nativeGetPort(): Int private external fun nativeGetExternalIpAddress(): String? @@ -410,7 +422,7 @@ class NetplaySession( result = null, ) } ?: emptyList(), - matches = null, + finished = false, ) } @@ -427,18 +439,12 @@ class NetplaySession( @Keep fun onSetGameDigestResult(playerId: Int, result: String) { val current = _gameDigestProgress.value ?: return - val updated = current.copy( + _gameDigestProgress.value = current.copy( playerProgresses = current.playerProgresses.map { if (it.playerId == playerId) it.copy(result = result) else it - } + }, + finished = true, ) - val finished = updated.playerProgresses.all { it.result != null } - _gameDigestProgress.value = if (finished) { - val results = updated.playerProgresses.map { it.result } - updated.copy(matches = results.distinct().size == 1) - } else { - updated - } } /** diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt index 923f03068a..861a5b99d2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt @@ -5,8 +5,14 @@ package org.dolphinemu.dolphinemu.features.netplay.model data class GameDigestProgress( val title: String, val playerProgresses: List<PlayerProgress>, - val matches: Boolean?, + val finished: Boolean, ) { + val matches: Boolean? + get() { + val results = playerProgresses.mapNotNull { it.result } + return if (results.size >= 2) results.distinct().size == 1 else null + } + data class PlayerProgress( val playerId: Int, val name: String, diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt index 1e3aea26a2..1dae14b6e2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt @@ -183,6 +183,12 @@ class NetplayViewModel( controllerMapping.value.withWiiRemote(remoteNumber, player) ) } + + fun computeGameDigest() = netplaySession.computeGameDigest() + + fun computeSDCardDigest() = netplaySession.computeSDCardDigest() + + fun abortGameDigest() = netplaySession.abortGameDigest() private fun getLocalIp(): JoinAddress { val localIp = networkHelper.getLocalIpString() diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt index ee1098956d..4916a6c7a1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt @@ -76,6 +76,9 @@ class NetplayActivity : AppCompatActivity(), ThemeProvider { controllerMapping = viewModel.controllerMapping.collectAsState().value, onGamecubePortChanged = viewModel::setGamecubePort, onWiiRemoteChanged = viewModel::setWiiRemote, + onComputeGameDigest = viewModel::computeGameDigest, + onComputeSDCardDigest = viewModel::computeSDCardDigest, + onAbortGameDigest = viewModel::abortGameDigest, ) } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt index aebac3f5bc..c3602facf4 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt @@ -42,11 +42,13 @@ import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Remove +import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.Share import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.Card import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExposedDropdownMenuAnchorType @@ -153,6 +155,9 @@ fun NetplayScreen( controllerMapping: ControllerMapping, onGamecubePortChanged: (port: Int, player: Player?) -> Unit, onWiiRemoteChanged: (port: Int, player: Player?) -> Unit, + onComputeGameDigest: () -> Unit, + onComputeSDCardDigest: () -> Unit, + onAbortGameDigest: () -> Unit, ) { val scrollState = rememberScrollState() @@ -168,6 +173,42 @@ fun NetplayScreen( ) } }, + actions = { + if (isHosting) { + var menuExpanded by remember { mutableStateOf(false) } + IconButton(onClick = { menuExpanded = true }) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = "More options", + ) + } + DropdownMenu( + expanded = menuExpanded, + onDismissRequest = { menuExpanded = false }, + ) { + Text( + text = stringResource(R.string.netplay_checksum), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + ) + DropdownMenuItem( + text = { Text(stringResource(R.string.netplay_checksum_current_game)) }, + onClick = { + menuExpanded = false + onComputeGameDigest() + }, + ) + DropdownMenuItem( + text = { Text(stringResource(R.string.netplay_checksum_sd_card)) }, + onClick = { + menuExpanded = false + onComputeSDCardDigest() + }, + ) + } + } + }, floatingActionButton = { if (isHosting) { ExtendedFloatingActionButton(onClick = onStartGame) { @@ -327,7 +368,10 @@ fun NetplayScreen( gameDigestProgress != null && !dismissGameDigestDialog -> { GameDigestProgressDialog( gameDigestProgress = gameDigestProgress, - onDismiss = { dismissGameDigestDialog = true }, + onDismiss = { + dismissGameDigestDialog = true + if (isHosting) onAbortGameDigest() + }, ) } @@ -1472,11 +1516,12 @@ private fun GameDigestProgressDialog( HorizontalDivider() } } - if (gameDigestProgress.matches != null) { + val matches = gameDigestProgress.matches + if (matches != null) { Spacer(modifier = Modifier.height(4.dp)) Text( text = stringResource( - if (gameDigestProgress.matches) { + if (matches) { R.string.netplay_game_digest_match } else { R.string.netplay_game_digest_mismatch @@ -1489,7 +1534,7 @@ private fun GameDigestProgressDialog( } }, confirmButton = { - if (gameDigestProgress.matches != null) { + if (gameDigestProgress.finished) { TextButton(onClick = onDismiss) { Text(stringResource(R.string.netplay_game_digest_close)) } @@ -1721,5 +1766,8 @@ private fun PreviewNetplayScreen() { // ), // ), // ), + onAbortGameDigest = {}, + onComputeGameDigest = {}, + onComputeSDCardDigest = {}, ) } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt index e3ab05f3ab..f3d0ac1fce 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -156,6 +157,7 @@ fun DolphinScaffold( title: @Composable () -> Unit, navigationIcon: @Composable () -> Unit, modifier: Modifier = Modifier, + actions: @Composable RowScope.() -> Unit = {}, floatingActionButton: @Composable () -> Unit = {}, content: @Composable (PaddingValues) -> Unit, ) { @@ -175,11 +177,13 @@ fun DolphinScaffold( TopAppBar( title = title, navigationIcon = navigationIcon, + actions = actions, ) } else { MediumTopAppBar( title = title, navigationIcon = navigationIcon, + actions = actions, scrollBehavior = topAppBarScrollBehavior, ) } diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index f8099fd652..69d8631e7e 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -1048,6 +1048,9 @@ It can efficiently compress both junk data and encrypted Wii data. <string name="netplay_game_digest_match">The hashes match</string> <string name="netplay_game_digest_mismatch">The hashes do not match</string> <string name="netplay_game_digest_close">Close</string> + <string name="netplay_checksum">Checksum</string> + <string name="netplay_checksum_current_game">Current game</string> + <string name="netplay_checksum_sd_card">SD Card</string> <string name="netplay_host_port_label">Port</string> <string name="netplay_use_upnp">Forward port (UPnP)</string> <string name="netplay_host_address_label">Join info</string> |
