diff options
| author | Tom Pratt <tom.pratt@outlook.com> | 2026-07-23 19:47:07 +0200 |
|---|---|---|
| committer | Tom Pratt <tom.pratt@outlook.com> | 2026-08-24 19:36:00 +0200 |
| commit | 3236c634d9dfb9d382d1f27c2e380c341cb56ab7 (patch) | |
| tree | 81178c1de2874cc69d3c45e1e4a4066c0236ab1a /Source/Android/app/src/main/java/org | |
| parent | 123d32248e455ec242866e3a75fea70dcecfd567 (diff) | |
Add functionality to get and set controller mappings in Android
Diffstat (limited to 'Source/Android/app/src/main/java/org')
3 files changed, 70 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 56676c4d3f..d44e70ba09 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 @@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.runningFold import kotlinx.coroutines.isActive import kotlinx.coroutines.withContext +import org.dolphinemu.dolphinemu.features.netplay.model.ControllerMapping import org.dolphinemu.dolphinemu.features.netplay.model.GameDigestProgress import org.dolphinemu.dolphinemu.features.netplay.model.NetplayMessage import org.dolphinemu.dolphinemu.features.netplay.model.Player @@ -87,6 +88,12 @@ class NetplaySession( ) val players = _players.asSharedFlow().distinctUntilChanged() + private val _controllerMapping = MutableSharedFlow<ControllerMapping>( + replay = 1, + onBufferOverflow = BufferOverflow.DROP_OLDEST + ) + val controllerMapping = _controllerMapping.asSharedFlow().distinctUntilChanged() + private val _chatMessages = MutableSharedFlow<String>( extraBufferCapacity = 32, onBufferOverflow = BufferOverflow.DROP_OLDEST @@ -185,6 +192,11 @@ class NetplaySession( fun reconnectTraversal() = nativeReconnectTraversal() + fun setControllerMapping(mapping: ControllerMapping) { + nativeSetPadMapping(mapping.gamecubePorts.map { it?.pid ?: 0 }.toIntArray()) + nativeSetWiimoteMapping(mapping.wiiRemotes.map { it?.pid ?: 0 }.toIntArray()) + } + fun consumeBootSessionData(): Long { return bootSessionDataPointer.also { bootSessionDataPointer = 0 @@ -278,6 +290,14 @@ class NetplaySession( private external fun nativeReconnectTraversal() + private external fun nativeGetPadMapping(): IntArray + + private external fun nativeGetWiimoteMapping(): IntArray + + private external fun nativeSetPadMapping(mapping: IntArray) + + private external fun nativeSetWiimoteMapping(mapping: IntArray) + // NetPlayUI callbacks @Keep @@ -304,7 +324,16 @@ class NetplaySession( @Keep fun onUpdate(players: Array<Player>) { - _players.tryEmit(players.toList()) + val playersList = players.toList() + _players.tryEmit(playersList) + + fun findPlayer(playerId: Int) = playersList.find { it.pid == playerId } + _controllerMapping.tryEmit( + ControllerMapping( + gamecubePorts = nativeGetPadMapping().map(::findPlayer).toList(), + wiiRemotes = nativeGetWiimoteMapping().map(::findPlayer).toList(), + ) + ) } @Keep diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/ControllerMapping.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/ControllerMapping.kt new file mode 100644 index 0000000000..d7cfae0ab3 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/ControllerMapping.kt @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.netplay.model + +data class ControllerMapping( + val gamecubePorts: List<Player?>, + val wiiRemotes: List<Player?>, +) { + fun withGamecubePort(port: Int, player: Player?) = + copy(gamecubePorts = gamecubePorts.replace(port, player)) + + fun withWiiRemote(port: Int, player: Player?) = + copy(wiiRemotes = wiiRemotes.replace(port, player)) + + companion object { + fun emptyControllerMapping(): ControllerMapping = ControllerMapping( + gamecubePorts = emptyList(), + wiiRemotes = emptyList(), + ) + } +} + +private fun <T> List<T>.replace(index: Int, value: T) = + toMutableList().also { it[index] = value } 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 0764448824..1e3aea26a2 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 @@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import org.dolphinemu.dolphinemu.features.netplay.NetplaySession +import org.dolphinemu.dolphinemu.features.netplay.model.ControllerMapping.Companion.emptyControllerMapping import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting import org.dolphinemu.dolphinemu.features.settings.model.IntSetting import org.dolphinemu.dolphinemu.features.settings.model.NativeConfig @@ -59,6 +60,9 @@ class NetplayViewModel( val players = netplaySession.players .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList()) + val controllerMapping = netplaySession.controllerMapping + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyControllerMapping()) + val messages = netplaySession.messages .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList()) @@ -168,6 +172,18 @@ class NetplayViewModel( netplaySession.changeGame(gameFile) } + fun setGamecubePort(portNumber: Int, player: Player?) { + netplaySession.setControllerMapping( + controllerMapping.value.withGamecubePort(portNumber, player) + ) + } + + fun setWiiRemote(remoteNumber: Int, player: Player?) { + netplaySession.setControllerMapping( + controllerMapping.value.withWiiRemote(remoteNumber, player) + ) + } + private fun getLocalIp(): JoinAddress { val localIp = networkHelper.getLocalIpString() ?: return JoinAddress.Unknown { _joinAddresses.value += JoinInfoType.LOCAL to getLocalIp() } |
