diff options
| author | Tom Pratt <tom.pratt@outlook.com> | 2026-05-06 09:46:33 +0200 |
|---|---|---|
| committer | Tom Pratt <tompratt@squareup.com> | 2026-05-19 12:03:00 +0200 |
| commit | 76ae44569415c0ffb674d184312ea898aab92a18 (patch) | |
| tree | bb4fa81127339de90382aae45166b0e58a2fbc1d /Source/Android/app/src/main | |
| parent | 1c2806dfe9d6d644a1423ccced319d0ac7dea632 (diff) | |
Add network mode picker for host
Diffstat (limited to 'Source/Android/app/src/main')
7 files changed, 110 insertions, 1 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 c5795edf63..0ba5d409b0 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 @@ -162,6 +162,8 @@ class NetplaySession( nativeSendMessage(message) } + fun setHostInputAuthority(enable: Boolean) = nativeSetHostInputAuthority(enable) + fun adjustClientPadBufferSize(buffer: Int) = nativeAdjustClientPadBufferSize(buffer) fun adjustServerPadBufferSize(buffer: Int) = nativeAdjustServerPadBufferSize(buffer) @@ -243,6 +245,8 @@ class NetplaySession( private external fun nativeSendMessage(message: String) + private external fun nativeSetHostInputAuthority(enable: Boolean) + private external fun nativeAdjustClientPadBufferSize(buffer: Int) private external fun nativeAdjustServerPadBufferSize(buffer: Int) 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 ea8ac9dea5..9f9b422f4b 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 @@ -65,6 +65,11 @@ class NetplayViewModel( val hostInputAuthority = netplaySession.hostInputAuthorityEnabled .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), false) + private val _networkMode = MutableStateFlow( + NetworkMode.fromConfigValue(StringSetting.NETPLAY_NETWORK_MODE.string) + ) + val networkMode = _networkMode.asStateFlow() + private val _buffer = MutableStateFlow(IntSetting.NETPLAY_BUFFER_SIZE.int) val buffer = _buffer.asStateFlow() @@ -107,6 +112,12 @@ class NetplayViewModel( netplaySession.sendMessage(trimmedMessage) } + fun setNetworkMode(mode: NetworkMode) { + _networkMode.value = mode + StringSetting.NETPLAY_NETWORK_MODE.setString(NativeConfig.LAYER_BASE, mode.configValue) + netplaySession.setHostInputAuthority(mode.isHostInputAuthority) + } + fun setBuffer(value: Int) { _buffer.value = value IntSetting.NETPLAY_BUFFER_SIZE.setInt(NativeConfig.LAYER_BASE, value) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetworkMode.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetworkMode.kt new file mode 100644 index 0000000000..55d29f5f17 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetworkMode.kt @@ -0,0 +1,18 @@ +package org.dolphinemu.dolphinemu.features.netplay.model + +import androidx.annotation.StringRes +import org.dolphinemu.dolphinemu.R + +enum class NetworkMode(val configValue: String, @StringRes val labelId: Int) { + FAIR_INPUT_DELAY("fixeddelay", R.string.netplay_network_mode_fair_input_delay), + HOST_INPUT_AUTHORITY("hostinputauthority", R.string.netplay_network_mode_host_input_authority), + GOLF("golf", R.string.netplay_network_mode_golf); + + val isHostInputAuthority: Boolean + get() = this == HOST_INPUT_AUTHORITY || this == GOLF + + companion object { + fun fromConfigValue(value: String): NetworkMode = + entries.find { it.configValue == value } ?: FAIR_INPUT_DELAY + } +} 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 bae20aee46..fe38cfe067 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 @@ -60,6 +60,8 @@ class NetplayActivity : AppCompatActivity(), ThemeProvider { gameFiles = viewModel.gameFiles.collectAsState().value, players = viewModel.players.collectAsState().value, hostInputAuthorityEnabled = viewModel.hostInputAuthority.collectAsState().value, + networkMode = viewModel.networkMode.collectAsState().value, + onNetworkModeChanged = viewModel::setNetworkMode, buffer = viewModel.buffer.collectAsState().value, onBufferChanged = viewModel::setBuffer, clientBuffer = viewModel.clientBuffer.collectAsState().value, 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 e68e6ff7d2..3be5cb0618 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 @@ -95,6 +95,7 @@ import org.dolphinemu.dolphinemu.features.netplay.model.GameDigestProgress import org.dolphinemu.dolphinemu.features.netplay.model.JoinAddress import org.dolphinemu.dolphinemu.features.netplay.model.JoinInfoType import org.dolphinemu.dolphinemu.features.netplay.model.NetplayMessage +import org.dolphinemu.dolphinemu.features.netplay.model.NetworkMode import org.dolphinemu.dolphinemu.features.netplay.model.Player import org.dolphinemu.dolphinemu.features.netplay.model.SaveTransferProgress import org.dolphinemu.dolphinemu.features.netplay.model.TraversalState @@ -121,6 +122,8 @@ fun NetplayScreen( onGameSelected: (GameFile) -> Unit, gameFiles: List<GameFile>, hostInputAuthorityEnabled: Boolean, + networkMode: NetworkMode, + onNetworkModeChanged: (NetworkMode) -> Unit, buffer: Int, onBufferChanged: (Int) -> Unit, clientBuffer: Int, @@ -178,6 +181,8 @@ fun NetplayScreen( onShowGamePickerChanged = { showGamePicker = it }, players = players, hostInputAuthorityEnabled = hostInputAuthorityEnabled, + networkMode = networkMode, + onNetworkModeChanged = onNetworkModeChanged, buffer = buffer, onBufferChanged = onBufferChanged, clientBuffer = clientBuffer, @@ -201,6 +206,8 @@ fun NetplayScreen( onShowGamePickerChanged = { showGamePicker = it }, players = players, hostInputAuthorityEnabled = hostInputAuthorityEnabled, + networkMode = networkMode, + onNetworkModeChanged = onNetworkModeChanged, buffer = buffer, onBufferChanged = onBufferChanged, clientBuffer = clientBuffer, @@ -290,6 +297,8 @@ private fun PortraitContent( onShowGamePickerChanged: (Boolean) -> Unit, players: List<Player>, hostInputAuthorityEnabled: Boolean, + networkMode: NetworkMode, + onNetworkModeChanged: (NetworkMode) -> Unit, buffer: Int, onBufferChanged: (Int) -> Unit, clientBuffer: Int, @@ -324,6 +333,8 @@ private fun PortraitContent( onShowGamePickerChanged = onShowGamePickerChanged, players = players, hostInputAuthorityEnabled = hostInputAuthorityEnabled, + networkMode = networkMode, + onNetworkModeChanged = onNetworkModeChanged, buffer = buffer, onBufferChanged = onBufferChanged, clientBuffer = clientBuffer, @@ -356,6 +367,8 @@ private fun LandscapeContent( onShowGamePickerChanged: (Boolean) -> Unit, players: List<Player>, hostInputAuthorityEnabled: Boolean, + networkMode: NetworkMode, + onNetworkModeChanged: (NetworkMode) -> Unit, buffer: Int, onBufferChanged: (Int) -> Unit, clientBuffer: Int, @@ -394,6 +407,8 @@ private fun LandscapeContent( onShowGamePickerChanged = onShowGamePickerChanged, players = players, hostInputAuthorityEnabled = hostInputAuthorityEnabled, + networkMode = networkMode, + onNetworkModeChanged = onNetworkModeChanged, buffer = buffer, onBufferChanged = onBufferChanged, clientBuffer = clientBuffer, @@ -421,6 +436,8 @@ private fun PlayersAndSettings( onShowGamePickerChanged: (Boolean) -> Unit, players: List<Player>, hostInputAuthorityEnabled: Boolean, + networkMode: NetworkMode, + onNetworkModeChanged: (NetworkMode) -> Unit, buffer: Int, onBufferChanged: (Int) -> Unit, clientBuffer: Int, @@ -475,6 +492,15 @@ private fun PlayersAndSettings( ) } + if (isHosting) { + MenuSpacer() + + NetworkModeDropdown( + networkMode = networkMode, + onNetworkModeChanged = onNetworkModeChanged, + ) + } + if (isHosting && !hostInputAuthorityEnabled) { MenuSpacer() @@ -902,6 +928,47 @@ private fun PlayersTable( } } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun NetworkModeDropdown( + networkMode: NetworkMode, + onNetworkModeChanged: (NetworkMode) -> Unit, +) { + var expanded by remember { mutableStateOf(false) } + + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { expanded = it }, + ) { + OutlinedTextField( + value = stringResource(networkMode.labelId), + onValueChange = {}, + readOnly = true, + label = { Text(stringResource(R.string.netplay_network_mode_label)) }, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, + colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(), + modifier = Modifier + .menuAnchor(MenuAnchorType.PrimaryNotEditable) + .fillMaxWidth(), + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }, + ) { + // No golf mode for now since it requires in game UI. + listOf(NetworkMode.FAIR_INPUT_DELAY, NetworkMode.HOST_INPUT_AUTHORITY).forEach { mode -> + DropdownMenuItem( + text = { Text(stringResource(mode.labelId)) }, + onClick = { + onNetworkModeChanged(mode) + expanded = false + }, + ) + } + } + } +} + @Composable private fun BufferInput( value: Int, @@ -1214,6 +1281,8 @@ private fun PreviewNetplayScreen() { onGameSelected = {}, gameFiles = emptyList(), hostInputAuthorityEnabled = true, + networkMode = NetworkMode.HOST_INPUT_AUTHORITY, + onNetworkModeChanged = {}, buffer = 5, onBufferChanged = {}, clientBuffer = 10, diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt index 610f45b2a3..72877429af 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt @@ -116,7 +116,8 @@ enum class StringSetting( ), NETPLAY_ADDRESS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_NETPLAY, "Address", "127.0.0.1"), NETPLAY_NICKNAME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_NETPLAY, "Nickname", "Player"), - NETPLAY_GAME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_NETPLAY, "Game", ""); + NETPLAY_GAME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_NETPLAY, "Game", ""), + NETPLAY_NETWORK_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_NETPLAY, "NetworkMode", "fixeddelay"); override val isOverridden: Boolean get() = NativeConfig.isOverridden(file, section, key) diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 09abe850fb..6837e951fe 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -1008,6 +1008,10 @@ It can efficiently compress both junk data and encrypted Wii data. <string name="netplay_players_name">Name</string> <string name="netplay_players_ping">Ping</string> <string name="netplay_players_mapping">Mapping</string> + <string name="netplay_network_mode_label">Input mode</string> + <string name="netplay_network_mode_fair_input_delay">Fair Input Delay</string> + <string name="netplay_network_mode_host_input_authority">Host Input Authority</string> + <string name="netplay_network_mode_golf">Golf Mode</string> <string name="netplay_buffer">Buffer</string> <string name="netplay_client_buffer">Max buffer</string> <string name="netplay_connection_lost">Netplay connection lost</string> |
