diff options
Diffstat (limited to 'Source/Android/jni/NetPlay/Netplay.cpp')
| -rw-r--r-- | Source/Android/jni/NetPlay/Netplay.cpp | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/Source/Android/jni/NetPlay/Netplay.cpp b/Source/Android/jni/NetPlay/Netplay.cpp new file mode 100644 index 0000000000..d6e24d250b --- /dev/null +++ b/Source/Android/jni/NetPlay/Netplay.cpp @@ -0,0 +1,255 @@ +// Copyright 2026 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <memory> +#include <string> +#include <vector> + +#include <jni.h> + +#include "Common/CommonTypes.h" +#include "Common/TraversalClient.h" +#include "Core/Boot/Boot.h" +#include "Core/Config/NetplaySettings.h" +#include "Core/NetPlayClient.h" +#include "Core/NetPlayCommon.h" +#include "Core/NetPlayServer.h" +#include "UICommon/GameFile.h" + +#include "jni/AndroidCommon/AndroidCommon.h" +#include "jni/AndroidCommon/IDCache.h" +#include "jni/NetPlay/NetPlayUICallbacks.h" + +static NetPlay::NetPlayUICallbacks* GetUICallbacksPointer(JNIEnv* env, jobject obj) +{ + return reinterpret_cast<NetPlay::NetPlayUICallbacks*>( + env->GetLongField(obj, IDCache::GetNetPlayUICallbacksPointer())); +} + +static NetPlay::NetPlayClient* GetClientPointer(JNIEnv* env, jobject obj) +{ + return reinterpret_cast<NetPlay::NetPlayClient*>( + env->GetLongField(obj, IDCache::GetNetPlayClientPointer())); +} + +static NetPlay::NetPlayServer* GetServerPointer(JNIEnv* env, jobject obj) +{ + return reinterpret_cast<NetPlay::NetPlayServer*>( + env->GetLongField(obj, IDCache::GetNetPlayServerPointer())); +} + +extern "C" { + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeSendMessage(JNIEnv* env, + jobject obj, + jstring jmessage) +{ + if (auto* client = GetClientPointer(env, obj)) + client->SendChatMessage(GetJString(env, jmessage)); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeSetHostInputAuthority( + JNIEnv* env, jobject obj, jboolean enable) +{ + if (auto* server = GetServerPointer(env, obj)) + server->SetHostInputAuthority(static_cast<bool>(enable)); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeAdjustClientPadBufferSize( + JNIEnv* env, jobject obj, jint buffer) +{ + if (auto* client = GetClientPointer(env, obj)) + client->AdjustPadBufferSize(static_cast<u32>(buffer)); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeAdjustServerPadBufferSize( + JNIEnv* env, jobject obj, jint buffer) +{ + if (auto* server = GetServerPointer(env, obj)) + server->AdjustPadBufferSize(static_cast<u32>(buffer)); +} + +JNIEXPORT jlong JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeCreateUICallbacks( + JNIEnv* env, jobject obj, jobjectArray jgame_files) +{ + std::vector<std::shared_ptr<const UICommon::GameFile>> games; + const jsize count = env->GetArrayLength(jgame_files); + games.reserve(count); + for (jsize i = 0; i < count; i++) + { + jobject jgame_file = env->GetObjectArrayElement(jgame_files, i); + auto* game_ptr = reinterpret_cast<std::shared_ptr<const UICommon::GameFile>*>( + env->GetLongField(jgame_file, IDCache::GetGameFilePointer())); + if (game_ptr) + games.push_back(*game_ptr); + env->DeleteLocalRef(jgame_file); + } + + return reinterpret_cast<jlong>(new NetPlay::NetPlayUICallbacks(obj, std::move(games))); +} + +JNIEXPORT jlong JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeJoin(JNIEnv* env, jobject obj) +{ + auto* ui = GetUICallbacksPointer(env, obj); + + 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); + + std::string host_ip; + u16 host_port; + bool is_traversal; + + // When hosting, join our own server on localhost + if (auto* server = GetServerPointer(env, obj)) + { + host_ip = "127.0.0.1"; + host_port = server->GetPort(); + is_traversal = false; + } + else + { + const std::string traversal_choice = Config::Get(Config::NETPLAY_TRAVERSAL_CHOICE); + is_traversal = traversal_choice == "traversal"; + host_ip = is_traversal ? Config::Get(Config::NETPLAY_HOST_CODE) : + Config::Get(Config::NETPLAY_ADDRESS); + host_port = Config::Get(Config::NETPLAY_CONNECT_PORT); + } + + auto client = std::make_unique<NetPlay::NetPlayClient>( + host_ip, host_port, ui, nickname, + NetPlay::NetTraversalConfig{is_traversal, traversal_host, traversal_port}); + + if (!client->IsConnected()) + return 0; + + return reinterpret_cast<jlong>(client.release()); +} + +JNIEXPORT jlong JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeHost(JNIEnv* env, jobject obj) +{ + auto* ui = GetUICallbacksPointer(env, obj); + + const std::string traversal_choice = Config::Get(Config::NETPLAY_TRAVERSAL_CHOICE); + const bool is_traversal = traversal_choice == "traversal"; + const bool use_upnp = Config::Get(Config::NETPLAY_USE_UPNP); + const std::string traversal_host = Config::Get(Config::NETPLAY_TRAVERSAL_SERVER); + const u16 traversal_port = Config::Get(Config::NETPLAY_TRAVERSAL_PORT); + const u16 traversal_port_alt = Config::Get(Config::NETPLAY_TRAVERSAL_PORT_ALT); + + const u16 host_port = is_traversal ? Config::Get(Config::NETPLAY_LISTEN_PORT) : + Config::Get(Config::NETPLAY_HOST_PORT); + + auto server = std::make_unique<NetPlay::NetPlayServer>( + host_port, use_upnp, ui, + NetPlay::NetTraversalConfig{is_traversal, traversal_host, traversal_port, + traversal_port_alt}); + + if (!server->is_connected) + return 0; + + const std::string network_mode = Config::Get(Config::NETPLAY_NETWORK_MODE); + const bool host_input_authority = network_mode == "hostinputauthority" || network_mode == "golf"; + server->SetHostInputAuthority(host_input_authority); + server->AdjustPadBufferSize(Config::Get(Config::NETPLAY_BUFFER_SIZE)); + + return reinterpret_cast<jlong>(server.release()); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeChangeGame(JNIEnv* env, + jobject obj, + jobject jgame_file) +{ + auto* server = GetServerPointer(env, obj); + if (!server) + return; + + const auto& game_file = *reinterpret_cast<std::shared_ptr<const UICommon::GameFile>*>( + env->GetLongField(jgame_file, IDCache::GetGameFilePointer())); + + server->ChangeGame(game_file->GetSyncIdentifier(), game_file->GetLongName()); +} + +JNIEXPORT jboolean JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeDoAllPlayersHaveGame( + JNIEnv* env, jobject obj) +{ + if (auto* client = GetClientPointer(env, obj)) + return static_cast<jboolean>(client->DoAllPlayersHaveGame()); + return JNI_TRUE; +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeStartGame(JNIEnv* env, + jobject obj) +{ + auto* server = GetServerPointer(env, obj); + if (!server) + return; + + server->RequestStartGame(); +} + +JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeGetPort( + JNIEnv* env, jobject obj) +{ + if (auto* server = GetServerPointer(env, obj)) + return static_cast<jint>(server->GetPort()); + return 0; +} + +JNIEXPORT jstring JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeGetExternalIpAddress( + JNIEnv* env, jobject) +{ + std::string ip = NetPlay::GetExternalIPAddress(); + if (ip.empty()) + return nullptr; + return ToJString(env, ip); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeReconnectTraversal(JNIEnv*, + jobject) +{ + if (Common::g_TraversalClient) + Common::g_TraversalClient->ReconnectToServer(); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeReleaseUICallbacks( + JNIEnv*, jobject, jlong pointer) +{ + delete reinterpret_cast<NetPlay::NetPlayUICallbacks*>(pointer); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeReleaseBootSessionData( + JNIEnv*, jobject, jlong pointer) +{ + delete reinterpret_cast<BootSessionData*>(pointer); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeReleaseClient(JNIEnv*, jobject, + jlong pointer) +{ + delete reinterpret_cast<NetPlay::NetPlayClient*>(pointer); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_netplay_NetplaySession_nativeReleaseServer(JNIEnv*, jobject, + jlong pointer) +{ + delete reinterpret_cast<NetPlay::NetPlayServer*>(pointer); +} + +} // extern "C" |
