mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-09-18 10:50:05 +00:00
Add functionality to get and set controller mappings in Android
This commit is contained in:
+30
-1
@@ -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
|
||||
|
||||
+24
@@ -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 }
|
||||
+16
@@ -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() }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2026 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -38,6 +39,30 @@ static NetPlay::NetPlayServer* GetServerPointer(JNIEnv* env, jobject obj)
|
||||
env->GetLongField(obj, IDCache::GetNetPlayServerPointer()));
|
||||
}
|
||||
|
||||
static jintArray PadMappingArrayToJIntArray(JNIEnv* env, const NetPlay::PadMappingArray& mapping)
|
||||
{
|
||||
const jsize size = static_cast<jsize>(mapping.size());
|
||||
jintArray jmapping = env->NewIntArray(size);
|
||||
std::array<jint, 4> values;
|
||||
for (size_t i = 0; i < mapping.size(); i++)
|
||||
values[i] = static_cast<jint>(mapping[i]);
|
||||
env->SetIntArrayRegion(jmapping, 0, size, values.data());
|
||||
return jmapping;
|
||||
}
|
||||
|
||||
static bool JIntArrayToPadMappingArray(JNIEnv* env, jintArray jmapping,
|
||||
NetPlay::PadMappingArray* mapping)
|
||||
{
|
||||
if (env->GetArrayLength(jmapping) != static_cast<jsize>(mapping->size()))
|
||||
return false;
|
||||
|
||||
std::array<jint, 4> values;
|
||||
env->GetIntArrayRegion(jmapping, 0, static_cast<jsize>(values.size()), values.data());
|
||||
for (size_t i = 0; i < mapping->size(); i++)
|
||||
(*mapping)[i] = static_cast<NetPlay::PlayerId>(values[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
@@ -224,6 +249,54 @@ Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeReconnectTr
|
||||
Common::g_TraversalClient->ReconnectToServer();
|
||||
}
|
||||
|
||||
JNIEXPORT jintArray JNICALL
|
||||
Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeGetPadMapping(JNIEnv* env,
|
||||
jobject obj)
|
||||
{
|
||||
auto* server = GetServerPointer(env, obj);
|
||||
if (!server)
|
||||
return env->NewIntArray(0);
|
||||
|
||||
return PadMappingArrayToJIntArray(env, server->GetPadMapping());
|
||||
}
|
||||
|
||||
JNIEXPORT jintArray JNICALL
|
||||
Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeGetWiimoteMapping(JNIEnv* env,
|
||||
jobject obj)
|
||||
{
|
||||
auto* server = GetServerPointer(env, obj);
|
||||
if (!server)
|
||||
return env->NewIntArray(0);
|
||||
|
||||
return PadMappingArrayToJIntArray(env, server->GetWiimoteMapping());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeSetPadMapping(
|
||||
JNIEnv* env, jobject obj, jintArray jmapping)
|
||||
{
|
||||
auto* server = GetServerPointer(env, obj);
|
||||
if (!server)
|
||||
return;
|
||||
|
||||
NetPlay::PadMappingArray mapping = server->GetPadMapping();
|
||||
if (JIntArrayToPadMappingArray(env, jmapping, &mapping))
|
||||
server->SetPadMapping(mapping);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeSetWiimoteMapping(
|
||||
JNIEnv* env, jobject obj, jintArray jmapping)
|
||||
{
|
||||
auto* server = GetServerPointer(env, obj);
|
||||
if (!server)
|
||||
return;
|
||||
|
||||
NetPlay::PadMappingArray mapping = server->GetWiimoteMapping();
|
||||
if (JIntArrayToPadMappingArray(env, jmapping, &mapping))
|
||||
server->SetWiimoteMapping(mapping);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeReleaseUICallbacks(
|
||||
JNIEnv*, jobject, jlong pointer)
|
||||
|
||||
Reference in New Issue
Block a user