From 1464fdfc2845817b52c204b719e16975e5182fe5 Mon Sep 17 00:00:00 2001 From: Tom Pratt Date: Wed, 6 May 2026 13:35:34 +0200 Subject: [PATCH] Add NetPlayClient join and stub NetPlayUICallbacks --- .../dolphinemu/features/netplay/Netplay.kt | 10 ++++ .../netplay/model/NetplaySetupViewModel.kt | 1 + Source/Android/jni/CMakeLists.txt | 2 + .../jni/NetPlay/NetPlayUICallbacks.cpp | 53 +++++++++++++++++ .../Android/jni/NetPlay/NetPlayUICallbacks.h | 57 +++++++++++++++++++ Source/Android/jni/NetPlay/Netplay.cpp | 25 ++++++++ 6 files changed, 148 insertions(+) create mode 100644 Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp create mode 100644 Source/Android/jni/NetPlay/NetPlayUICallbacks.h diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/Netplay.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/Netplay.kt index ace7277a9a..aaaca2b4fb 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/Netplay.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/Netplay.kt @@ -3,9 +3,13 @@ package org.dolphinemu.dolphinemu.features.netplay +import androidx.annotation.Keep import org.dolphinemu.dolphinemu.features.netplay.model.ConnectionType object Netplay { + @Keep + private var netPlayClientPointer: Long = 0 + @JvmStatic external fun getNickname(): String @@ -93,4 +97,10 @@ object Netplay { indexPassword: String, ) + fun join() { + netPlayClientPointer = Join() + } + + @JvmStatic + private external fun Join(): Long } 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 ecf0b2cff2..34cee1e5bf 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 @@ -62,5 +62,6 @@ class NetplaySetupViewModel : ViewModel() { hostCode = hostCode.value, connectPort = connectPort.value.toInt(), ) + Netplay.join() } } diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index a71668a758..a3a741a433 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -31,6 +31,8 @@ add_library(main SHARED Input/NumericSetting.cpp Input/NumericSetting.h NetPlay/Netplay.cpp + NetPlay/NetPlayUICallbacks.cpp + NetPlay/NetPlayUICallbacks.h MainAndroid.cpp RiivolutionPatches.cpp SkylanderConfig.cpp diff --git a/Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp b/Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp new file mode 100644 index 0000000000..ab56458eff --- /dev/null +++ b/Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp @@ -0,0 +1,53 @@ +// Copyright 2003 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "jni/NetPlay/NetPlayUICallbacks.h" + +namespace NetPlay { + +NetPlayUICallbacks::NetPlayUICallbacks() = default; +NetPlayUICallbacks::~NetPlayUICallbacks() = default; + +void NetPlayUICallbacks::BootGame(const std::string&, std::unique_ptr) {} +void NetPlayUICallbacks::StopGame() {} +bool NetPlayUICallbacks::IsHosting() const { return false; } +void NetPlayUICallbacks::Update() {} +void NetPlayUICallbacks::AppendChat(const std::string&) {} +void NetPlayUICallbacks::OnMsgChangeGame(const NetPlay::SyncIdentifier&, const std::string&) {} +void NetPlayUICallbacks::OnMsgChangeGBARom(int, const NetPlay::GBAConfig&) {} +void NetPlayUICallbacks::OnMsgStartGame() {} +void NetPlayUICallbacks::OnMsgStopGame() {} +void NetPlayUICallbacks::OnMsgPowerButton() {} +void NetPlayUICallbacks::OnPlayerConnect(const std::string&) {} +void NetPlayUICallbacks::OnPlayerDisconnect(const std::string&) {} +void NetPlayUICallbacks::OnPadBufferChanged(u32) {} +void NetPlayUICallbacks::OnHostInputAuthorityChanged(bool) {} +void NetPlayUICallbacks::OnDesync(u32, const std::string&) {} +void NetPlayUICallbacks::OnConnectionLost() {} +void NetPlayUICallbacks::OnConnectionError(const std::string&) {} +void NetPlayUICallbacks::OnTraversalError(Common::TraversalClient::FailureReason) {} +void NetPlayUICallbacks::OnTraversalStateChanged(Common::TraversalClient::State) {} +void NetPlayUICallbacks::OnGameStartAborted() {} +void NetPlayUICallbacks::OnGolferChanged(bool, const std::string&) {} +void NetPlayUICallbacks::OnTtlDetermined(u8) {} +void NetPlayUICallbacks::OnIndexAdded(bool, std::string) {} +void NetPlayUICallbacks::OnIndexRefreshFailed(std::string) {} +bool NetPlayUICallbacks::IsRecording() { return false; } + +std::shared_ptr +NetPlayUICallbacks::FindGameFile(const NetPlay::SyncIdentifier&, NetPlay::SyncIdentifierComparison*) +{ + return nullptr; +} + +std::string NetPlayUICallbacks::FindGBARomPath(const std::array&, std::string_view, int) { return {}; } +void NetPlayUICallbacks::ShowGameDigestDialog(const std::string&) {} +void NetPlayUICallbacks::SetGameDigestProgress(int, int) {} +void NetPlayUICallbacks::SetGameDigestResult(int, const std::string&) {} +void NetPlayUICallbacks::AbortGameDigest() {} +void NetPlayUICallbacks::ShowChunkedProgressDialog(const std::string&, u64, std::span) {} +void NetPlayUICallbacks::HideChunkedProgressDialog() {} +void NetPlayUICallbacks::SetChunkedProgress(int, u64) {} +void NetPlayUICallbacks::SetHostWiiSyncData(std::vector, std::string) {} + +} // namespace NetPlay diff --git a/Source/Android/jni/NetPlay/NetPlayUICallbacks.h b/Source/Android/jni/NetPlay/NetPlayUICallbacks.h new file mode 100644 index 0000000000..18fdf1df93 --- /dev/null +++ b/Source/Android/jni/NetPlay/NetPlayUICallbacks.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include "Core/NetPlayClient.h" + +namespace NetPlay { + +class NetPlayUICallbacks : public NetPlay::NetPlayUI { +public: + NetPlayUICallbacks(); + ~NetPlayUICallbacks() override; + + void BootGame(const std::string& filename, + std::unique_ptr boot_session_data) override; + void StopGame() override; + bool IsHosting() const override; + void Update() override; + void AppendChat(const std::string& msg) override; + void OnMsgChangeGame(const NetPlay::SyncIdentifier& sync_identifier, + const std::string& netplay_name) override; + void OnMsgChangeGBARom(int pad, const NetPlay::GBAConfig& config) override; + void OnMsgStartGame() override; + void OnMsgStopGame() override; + void OnMsgPowerButton() override; + void OnPlayerConnect(const std::string& player) override; + void OnPlayerDisconnect(const std::string& player) override; + void OnPadBufferChanged(u32 buffer) override; + void OnHostInputAuthorityChanged(bool enabled) override; + void OnDesync(u32 frame, const std::string& player) override; + void OnConnectionLost() override; + void OnConnectionError(const std::string& message) override; + void OnTraversalError(Common::TraversalClient::FailureReason error) override; + void OnTraversalStateChanged(Common::TraversalClient::State state) override; + void OnGameStartAborted() override; + void OnGolferChanged(bool is_golfer, const std::string& golfer_name) override; + void OnTtlDetermined(u8 ttl) override; + void OnIndexAdded(bool success, std::string error) override; + void OnIndexRefreshFailed(std::string error) override; + bool IsRecording() override; + std::shared_ptr + FindGameFile(const NetPlay::SyncIdentifier& sync_identifier, + NetPlay::SyncIdentifierComparison* found = nullptr) override; + std::string FindGBARomPath(const std::array& hash, std::string_view title, + int device_number) override; + void ShowGameDigestDialog(const std::string& title) override; + void SetGameDigestProgress(int pid, int progress) override; + void SetGameDigestResult(int pid, const std::string& result) override; + void AbortGameDigest() override; + void ShowChunkedProgressDialog(const std::string& title, u64 data_size, + std::span players) override; + void HideChunkedProgressDialog() override; + void SetChunkedProgress(int pid, u64 progress) override; + void SetHostWiiSyncData(std::vector titles, std::string redirect_folder) override; +}; + +} // namespace NetPlay diff --git a/Source/Android/jni/NetPlay/Netplay.cpp b/Source/Android/jni/NetPlay/Netplay.cpp index 245a24852c..42ed6483ce 100644 --- a/Source/Android/jni/NetPlay/Netplay.cpp +++ b/Source/Android/jni/NetPlay/Netplay.cpp @@ -1,14 +1,17 @@ // Copyright 2003 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include #include "Common/CommonTypes.h" #include "Core/Config/NetplaySettings.h" +#include "Core/NetPlayClient.h" #include "jni/AndroidCommon/AndroidCommon.h" +#include "jni/NetPlay/NetPlayUICallbacks.h" extern "C" { @@ -117,4 +120,26 @@ Java_org_dolphinemu_dolphinemu_features_netplay_Netplay_SaveSetup( Config::SetBaseOrCurrent(Config::NETPLAY_LISTEN_PORT, static_cast(listenPort)); } +JNIEXPORT jlong JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_Netplay_Join(JNIEnv*, jclass) +{ + const std::string traversal_choice = Config::Get(Config::NETPLAY_TRAVERSAL_CHOICE); + const bool is_traversal = traversal_choice == "traversal"; + + std::string host_ip; + host_ip = is_traversal ? Config::Get(Config::NETPLAY_HOST_CODE) : + Config::Get(Config::NETPLAY_ADDRESS); + + const u16 host_port = Config::Get(Config::NETPLAY_CONNECT_PORT); + const std::string traversal_host = Config::Get(Config::NETPLAY_TRAVERSAL_SERVER); + const u16 traversal_port = Config::Get(Config::NETPLAY_TRAVERSAL_PORT); + const std::string nickname = Config::Get(Config::NETPLAY_NICKNAME); + + auto* client = new NetPlay::NetPlayClient( + host_ip, host_port, new NetPlay::NetPlayUICallbacks(), nickname, + NetPlay::NetTraversalConfig{is_traversal, traversal_host, traversal_port}); + + return reinterpret_cast(client); +} + } // extern "C"