Pass game list to NetPlayUICallbacks and implement OnMsgChangeGame, OnMsgStartGame, FindGameFile

This commit is contained in:
Tom Pratt 2026-05-06 13:44:53 +02:00
parent 2839a5d11b
commit 01c8c4aee2
6 changed files with 131 additions and 8 deletions

View File

@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.dolphinemu.dolphinemu.features.netplay.Netplay
import org.dolphinemu.dolphinemu.services.GameFileCacheManager
class NetplaySetupViewModel : ViewModel() {
private val _connectionRole = MutableStateFlow<ConnectionRole>(ConnectionRole.Connect)
@ -26,6 +27,10 @@ class NetplaySetupViewModel : ViewModel() {
private val _connectPort = MutableStateFlow(Netplay.getConnectPort().toString())
val connectPort = _connectPort.asStateFlow()
init {
GameFileCacheManager.startLoad()
}
fun setConnectionRole(connectionRole: ConnectionRole) {
_connectionRole.value = connectionRole
}
@ -55,6 +60,10 @@ class NetplaySetupViewModel : ViewModel() {
}
fun connect() {
if (GameFileCacheManager.isLoading().value == true) {
return
}
Netplay.saveSetup(
nickname = nickname.value,
connectionType = connectionType.value,

View File

@ -25,6 +25,13 @@ static jmethodID s_game_file_constructor;
static jclass s_game_file_cache_class;
static jfieldID s_game_file_cache_pointer;
static jclass s_game_file_cache_manager_class;
static jfieldID s_game_file_cache_manager_instance;
static jclass s_netplay_class;
static jfieldID s_net_play_client_pointer;
static jmethodID s_netplay_on_msg_start_game;
static jclass s_analytics_class;
static jmethodID s_get_analytics_value;
@ -220,6 +227,26 @@ jfieldID GetGameFileCachePointer()
return s_game_file_cache_pointer;
}
jclass GetGameFileCacheManagerClass()
{
return s_game_file_cache_manager_class;
}
jfieldID GetGameFileCacheManagerInstance()
{
return s_game_file_cache_manager_instance;
}
jclass GetNetplayClass()
{
return s_netplay_class;
}
jfieldID GetNetPlayClientPointer()
{
return s_net_play_client_pointer;
}
jclass GetPairClass()
{
return s_pair_class;
@ -615,6 +642,21 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
s_game_file_cache_pointer = env->GetFieldID(game_file_cache_class, "pointer", "J");
env->DeleteLocalRef(game_file_cache_class);
const jclass game_file_cache_manager_class =
env->FindClass("org/dolphinemu/dolphinemu/services/GameFileCacheManager");
s_game_file_cache_manager_class =
reinterpret_cast<jclass>(env->NewGlobalRef(game_file_cache_manager_class));
s_game_file_cache_manager_instance = env->GetStaticFieldID(
game_file_cache_manager_class, "gameFileCache",
"Lorg/dolphinemu/dolphinemu/model/GameFileCache;");
env->DeleteLocalRef(game_file_cache_manager_class);
const jclass netplay_class =
env->FindClass("org/dolphinemu/dolphinemu/features/netplay/Netplay");
s_netplay_class = reinterpret_cast<jclass>(env->NewGlobalRef(netplay_class));
s_net_play_client_pointer = env->GetStaticFieldID(netplay_class, "netPlayClientPointer", "J");
env->DeleteLocalRef(netplay_class);
const jclass analytics_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Analytics");
s_analytics_class = reinterpret_cast<jclass>(env->NewGlobalRef(analytics_class));
s_get_analytics_value = env->GetStaticMethodID(s_analytics_class, "getValue",
@ -828,6 +870,8 @@ JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
env->DeleteGlobalRef(s_native_library_class);
env->DeleteGlobalRef(s_game_file_class);
env->DeleteGlobalRef(s_game_file_cache_class);
env->DeleteGlobalRef(s_game_file_cache_manager_class);
env->DeleteGlobalRef(s_netplay_class);
env->DeleteGlobalRef(s_analytics_class);
env->DeleteGlobalRef(s_pair_class);
env->DeleteGlobalRef(s_hash_map_class);

View File

@ -28,6 +28,12 @@ jmethodID GetGameFileConstructor();
jclass GetGameFileCacheClass();
jfieldID GetGameFileCachePointer();
jclass GetGameFileCacheManagerClass();
jfieldID GetGameFileCacheManagerInstance();
jclass GetNetplayClass();
jfieldID GetNetPlayClientPointer();
jclass GetPairClass();
jmethodID GetPairConstructor();

View File

@ -3,9 +3,15 @@
#include "jni/NetPlay/NetPlayUICallbacks.h"
#include "jni/AndroidCommon/IDCache.h"
namespace NetPlay {
NetPlayUICallbacks::NetPlayUICallbacks() = default;
NetPlayUICallbacks::NetPlayUICallbacks(std::vector<std::shared_ptr<const UICommon::GameFile>> games)
: m_games(std::move(games))
{
}
NetPlayUICallbacks::~NetPlayUICallbacks() = default;
void NetPlayUICallbacks::BootGame(const std::string&, std::unique_ptr<BootSessionData>) {}
@ -13,9 +19,28 @@ 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::OnMsgChangeGame(const NetPlay::SyncIdentifier& sync_identifier,
const std::string& netplay_name)
{
m_current_game_identifier = sync_identifier;
m_current_game_name = netplay_name;
}
void NetPlayUICallbacks::OnMsgChangeGBARom(int, const NetPlay::GBAConfig&) {}
void NetPlayUICallbacks::OnMsgStartGame() {}
void NetPlayUICallbacks::OnMsgStartGame()
{
JNIEnv* env = IDCache::GetEnvForThread();
auto* client = reinterpret_cast<NetPlay::NetPlayClient*>(
env->GetStaticLongField(IDCache::GetNetplayClass(), IDCache::GetNetPlayClientPointer()));
if (client)
{
if (const auto game = FindGameFile(m_current_game_identifier))
client->StartGame(game->GetFilePath());
}
}
void NetPlayUICallbacks::OnMsgStopGame() {}
void NetPlayUICallbacks::OnMsgPowerButton() {}
void NetPlayUICallbacks::OnPlayerConnect(const std::string&) {}
@ -35,9 +60,26 @@ void NetPlayUICallbacks::OnIndexRefreshFailed(std::string) {}
bool NetPlayUICallbacks::IsRecording() { return false; }
std::shared_ptr<const UICommon::GameFile>
NetPlayUICallbacks::FindGameFile(const NetPlay::SyncIdentifier&, NetPlay::SyncIdentifierComparison*)
NetPlayUICallbacks::FindGameFile(const NetPlay::SyncIdentifier& sync_identifier,
NetPlay::SyncIdentifierComparison* found)
{
return nullptr;
NetPlay::SyncIdentifierComparison temp;
if (!found)
found = &temp;
*found = NetPlay::SyncIdentifierComparison::DifferentGame;
std::shared_ptr<const UICommon::GameFile> result;
for (const auto& game : m_games)
{
const auto cmp = game->CompareSyncIdentifier(sync_identifier);
if (cmp < *found)
{
*found = cmp;
result = game;
}
}
return result;
}
std::string NetPlayUICallbacks::FindGBARomPath(const std::array<u8, 20>&, std::string_view, int) { return {}; }

View File

@ -1,14 +1,18 @@
#pragma once
#include <memory>
#include <span>
#include <string>
#include <vector>
#include "Core/NetPlayClient.h"
#include "UICommon/GameFile.h"
namespace NetPlay {
class NetPlayUICallbacks : public NetPlay::NetPlayUI {
public:
NetPlayUICallbacks();
NetPlayUICallbacks(std::vector<std::shared_ptr<const UICommon::GameFile>> games);
~NetPlayUICallbacks() override;
void BootGame(const std::string& filename,
@ -52,6 +56,11 @@ public:
void HideChunkedProgressDialog() override;
void SetChunkedProgress(int pid, u64 progress) override;
void SetHostWiiSyncData(std::vector<u64> titles, std::string redirect_folder) override;
private:
std::vector<std::shared_ptr<const UICommon::GameFile>> m_games;
NetPlay::SyncIdentifier m_current_game_identifier;
std::string m_current_game_name;
};
} // namespace NetPlay

View File

@ -3,14 +3,18 @@
#include <memory>
#include <string>
#include <vector>
#include <jni.h>
#include "Common/CommonTypes.h"
#include "Core/Config/NetplaySettings.h"
#include "Core/NetPlayClient.h"
#include "UICommon/GameFile.h"
#include "UICommon/GameFileCache.h"
#include "jni/AndroidCommon/AndroidCommon.h"
#include "jni/AndroidCommon/IDCache.h"
#include "jni/NetPlay/NetPlayUICallbacks.h"
extern "C" {
@ -121,7 +125,7 @@ Java_org_dolphinemu_dolphinemu_features_netplay_Netplay_SaveSetup(
}
JNIEXPORT jlong JNICALL
Java_org_dolphinemu_dolphinemu_features_netplay_Netplay_Join(JNIEnv*, jclass)
Java_org_dolphinemu_dolphinemu_features_netplay_Netplay_Join(JNIEnv* env, jclass)
{
const std::string traversal_choice = Config::Get(Config::NETPLAY_TRAVERSAL_CHOICE);
const bool is_traversal = traversal_choice == "traversal";
@ -135,8 +139,17 @@ Java_org_dolphinemu_dolphinemu_features_netplay_Netplay_Join(JNIEnv*, jclass)
const u16 traversal_port = Config::Get(Config::NETPLAY_TRAVERSAL_PORT);
const std::string nickname = Config::Get(Config::NETPLAY_NICKNAME);
jobject jgame_file_cache = env->GetStaticObjectField(
IDCache::GetGameFileCacheManagerClass(), IDCache::GetGameFileCacheManagerInstance());
auto* game_file_cache = reinterpret_cast<UICommon::GameFileCache*>(
env->GetLongField(jgame_file_cache, IDCache::GetGameFileCachePointer()));
std::vector<std::shared_ptr<const UICommon::GameFile>> games;
game_file_cache->ForEach(
[&games](const std::shared_ptr<const UICommon::GameFile>& game) { games.push_back(game); });
auto* client = new NetPlay::NetPlayClient(
host_ip, host_port, new NetPlay::NetPlayUICallbacks(), nickname,
host_ip, host_port, new NetPlay::NetPlayUICallbacks(std::move(games)), nickname,
NetPlay::NetTraversalConfig{is_traversal, traversal_host, traversal_port});
return reinterpret_cast<jlong>(client);