// Copyright 2003 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "UICommon/GameFile.h" #include "NetPlayUICallbacks.h" #include "Core/Boot/Boot.h" #include "Core/Core.h" #include "jni/AndroidCommon/AndroidCommon.h" #include "jni/AndroidCommon/IDCache.h" namespace NetPlay { NetPlayUICallbacks::NetPlayUICallbacks(std::vector> games) : m_games(std::move(games)) { m_state_changed_hook = Core::AddOnStateChangedCallback([this](Core::State state) { if ((state == Core::State::Uninitialized || state == Core::State::Stopping) && !m_got_stop_request) { JNIEnv* env = IDCache::GetEnvForThread(); auto* client = reinterpret_cast( env->GetStaticLongField(IDCache::GetNetplayClass(), IDCache::GetNetPlayClientPointer())); if (client) client->RequestStopGame(); } }); } NetPlayUICallbacks::~NetPlayUICallbacks() = default; void NetPlayUICallbacks::BootGame(const std::string& filename, std::unique_ptr boot_session_data) { m_got_stop_request = false; JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnBootGame(), ToJString(env, filename), reinterpret_cast(boot_session_data.release())); } void NetPlayUICallbacks::StopGame() { if (m_got_stop_request) return; m_got_stop_request = true; JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnStopGame()); } bool NetPlayUICallbacks::IsHosting() const { return false; } void NetPlayUICallbacks::Update() { JNIEnv* env = IDCache::GetEnvForThread(); auto* client = reinterpret_cast( env->GetStaticLongField(IDCache::GetNetplayClass(), IDCache::GetNetPlayClientPointer())); if (!client) return; const std::vector players = client->GetPlayers(); jobjectArray player_array = env->NewObjectArray(static_cast(players.size()), IDCache::GetNetplayPlayerClass(), nullptr); for (jsize i = 0; i < static_cast(players.size()); i++) { const NetPlay::Player* player = players[i]; const std::string mapping = NetPlay::GetPlayerMappingString( player->pid, client->GetPadMapping(), client->GetGBAConfig(), client->GetWiimoteMapping()); jobject player_obj = env->NewObject( IDCache::GetNetplayPlayerClass(), IDCache::GetNetplayPlayerConstructor(), static_cast(player->pid), ToJString(env, player->name), ToJString(env, player->revision), static_cast(player->ping), static_cast(player->IsHost()), ToJString(env, mapping)); env->SetObjectArrayElement(player_array, i, player_obj); env->DeleteLocalRef(player_obj); } env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayUpdate(), player_array); env->DeleteLocalRef(player_array); } void NetPlayUICallbacks::AppendChat(const std::string& message) { JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnChatMessageReceived(), ToJString(env, message)); } 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; JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnGameChanged(), ToJString(env, netplay_name)); } void NetPlayUICallbacks::OnMsgChangeGBARom(int, const NetPlay::GBAConfig&) {} void NetPlayUICallbacks::OnMsgStartGame() { JNIEnv* env = IDCache::GetEnvForThread(); auto* client = reinterpret_cast( 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&) {} void NetPlayUICallbacks::OnPlayerDisconnect(const std::string&) {} void NetPlayUICallbacks::OnPadBufferChanged(u32 buffer) { JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnPadBufferChanged(), static_cast(buffer)); } void NetPlayUICallbacks::OnHostInputAuthorityChanged(bool enabled) { JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnHostInputAuthorityChanged(), static_cast(enabled)); } void NetPlayUICallbacks::OnDesync(u32, const std::string&) {} void NetPlayUICallbacks::OnConnectionLost() { JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnConnectionLost()); } void NetPlayUICallbacks::OnConnectionError(const std::string& message) { JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnConnectionError(), ToJString(env, message)); } 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& sync_identifier, NetPlay::SyncIdentifierComparison* found) { NetPlay::SyncIdentifierComparison temp; if (!found) found = &temp; *found = NetPlay::SyncIdentifierComparison::DifferentGame; std::shared_ptr 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&, 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& title, u64 data_size, std::span players) { JNIEnv* env = IDCache::GetEnvForThread(); jintArray j_players = env->NewIntArray(static_cast(players.size())); env->SetIntArrayRegion(j_players, 0, static_cast(players.size()), players.data()); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnShowChunkedProgressDialog(), ToJString(env, title), static_cast(data_size), j_players); env->DeleteLocalRef(j_players); } void NetPlayUICallbacks::HideChunkedProgressDialog() { JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnHideChunkedProgressDialog()); } void NetPlayUICallbacks::SetChunkedProgress(int pid, u64 progress) { JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNetplayClass(), IDCache::GetNetplayOnSetChunkedProgress(), static_cast(pid), static_cast(progress)); } void NetPlayUICallbacks::SetHostWiiSyncData(std::vector, std::string) {} } // namespace NetPlay