From 77f08364db41de05e06d02128c3107c2d45df105 Mon Sep 17 00:00:00 2001 From: Tom Pratt Date: Tue, 12 May 2026 11:20:46 -0700 Subject: Create NetPlayServer and start game --- .../dolphinemu/features/netplay/NetplaySession.kt | 31 ++++++++++++++++++++++ .../netplay/model/NetplaySetupViewModel.kt | 13 +++++---- .../features/netplay/model/NetplayViewModel.kt | 6 +++++ .../features/netplay/ui/NetplayActivity.kt | 4 +-- 4 files changed, 47 insertions(+), 7 deletions(-) (limited to 'Source/Android/app/src/main/java') 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 e0531a6477..1ec663a1a5 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 @@ -37,6 +37,8 @@ class NetplaySession( private var netPlayClientPointer: Long = 0 + private var netPlayServerPointer: Long = 0 + private var bootSessionDataPointer: Long = 0 private val sessionScope = CoroutineScope(SupervisorJob()) @@ -44,6 +46,9 @@ class NetplaySession( @Volatile var isClosed = false private set + + val isHosting: Boolean + get() = netPlayServerPointer != 0L val isLaunching: Boolean get() = bootSessionDataPointer != 0L @@ -126,10 +131,24 @@ class NetplaySession( true } + suspend fun host(): Boolean = withContext(Dispatchers.IO) { + if (isClosed) throw IllegalStateException("Cannot host a closed session") + + netPlayServerPointer = nativeHost() + if (netPlayServerPointer == 0L || !isActive) { + closeBlocking() + return@withContext false + } + + join() + } + fun sendMessage(message: String) = nativeSendMessage(message) fun adjustPadBufferSize(buffer: Int) = nativeAdjustPadBufferSize(buffer) + fun startGame() = nativeStartGame() + fun consumeBootSessionData(): Long { return bootSessionDataPointer.also { bootSessionDataPointer = 0 @@ -174,6 +193,12 @@ class NetplaySession( nativeReleaseClient(currentNetPlayClientPointer) } + val currentNetPlayServerPointer = netPlayServerPointer + if (currentNetPlayServerPointer != 0L) { + netPlayServerPointer = 0 + nativeReleaseServer(currentNetPlayServerPointer) + } + val currentNetPlayUICallbacksPointer = netPlayUICallbacksPointer if (currentNetPlayUICallbacksPointer != 0L) { netPlayUICallbacksPointer = 0 @@ -187,6 +212,8 @@ class NetplaySession( private external fun nativeJoin(): Long + private external fun nativeHost(): Long + private external fun nativeSendMessage(message: String) private external fun nativeAdjustPadBufferSize(buffer: Int) @@ -195,8 +222,12 @@ class NetplaySession( private external fun nativeReleaseClient(pointer: Long) + private external fun nativeReleaseServer(pointer: Long) + private external fun nativeReleaseBootSessionData(pointer: Long) + private external fun nativeStartGame() + // NetPlayUI callbacks @Keep diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplaySetupViewModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplaySetupViewModel.kt index d51ae477ac..9c667245e5 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplaySetupViewModel.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplaySetupViewModel.kt @@ -119,11 +119,9 @@ class NetplaySetupViewModel( BooleanSetting.NETPLAY_USE_UPNP.setBoolean(NativeConfig.LAYER_BASE, useUpnp) } - fun host() { + fun host() = connect(host = true) - } - - fun connect() { + fun connect(host: Boolean = false) { if (_connecting.value) return _connecting.value = true @@ -139,7 +137,12 @@ class NetplaySetupViewModel( .onEach { _errors.emit(it) } .launchIn(this) - if (session.join()) { + val success = if (host) { + session.host() + } else { + session.join() + } + if (success) { _showNetplayScreen.trySend(Unit) } } finally { 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 d0f86ed3f6..e7518bdf43 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 @@ -22,6 +22,8 @@ class NetplayViewModel( val launchGame = netplaySession.launchGame + val isHosting = netplaySession.isHosting + val connectionLost = netplaySession.connectionLost val players = netplaySession.players @@ -43,6 +45,10 @@ class NetplayViewModel( val gameDigestProgress = netplaySession.gameDigestProgress + fun startGame() { + netplaySession.startGame() + } + fun sendMessage(message: String) { val trimmedMessage = message.trim() if (trimmedMessage.isEmpty()) { 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 c01ec2a76c..ce1f7dec19 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 @@ -51,8 +51,8 @@ class NetplayActivity : AppCompatActivity(), ThemeProvider { messages = viewModel.messages.collectAsState().value, onSendMessage = viewModel::sendMessage, game = viewModel.game.collectAsState().value, - isHosting = false, - onStartGame = {}, + isHosting = viewModel.isHosting, + onStartGame = viewModel::startGame, players = viewModel.players.collectAsState().value, hostInputAuthorityEnabled = viewModel.hostInputAuthority.collectAsState().value, maxBuffer = viewModel.maxBuffer.collectAsState().value, -- cgit v1.2.3