Added multiplayer settings, now can direct connect to a room

This commit is contained in:
Timotej Leginus 2023-06-11 20:12:53 +02:00
parent c4a0dbfb20
commit 17693651b3
11 changed files with 266 additions and 1 deletions

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M0,720L0,667Q0,628.43 41.5,604.22Q83,580 150.38,580Q162.54,580 173.77,580.5Q185,581 196,582.65Q188,600 184,617.82Q180,635.63 180,655L180,720L0,720ZM240,720L240,655Q240,623 257.5,596.5Q275,570 307,550Q339,530 383.5,520Q428,510 480,510Q533,510 577.5,520Q622,530 654,550Q686,570 703,596.5Q720,623 720,655L720,720L240,720ZM780,720L780,655Q780,635.14 776.5,617.57Q773,600 765,582.73Q776,581 787.17,580.5Q798.34,580 810,580Q877.5,580 918.75,603.77Q960,627.54 960,667L960,720L780,720ZM300,660L660,660L660,654Q660,617 609.5,593.5Q559,570 480,570Q401,570 350.5,593.5Q300,617 300,655L300,660ZM149.57,550Q121,550 100.5,529.44Q80,508.88 80,480Q80,451 100.56,430.5Q121.13,410 150,410Q179,410 199.5,430.5Q220,451 220,480.43Q220,509 199.5,529.5Q179,550 149.57,550ZM809.57,550Q781,550 760.5,529.44Q740,508.88 740,480Q740,451 760.56,430.5Q781.13,410 810,410Q839,410 859.5,430.5Q880,451 880,480.43Q880,509 859.5,529.5Q839,550 809.57,550ZM480,480Q430,480 395,445Q360,410 360,360Q360,309 395,274.5Q430,240 480,240Q531,240 565.5,274.5Q600,309 600,360Q600,410 565.5,445Q531,480 480,480ZM480.35,420Q506,420 523,402.65Q540,385.3 540,359.65Q540,334 522.85,317Q505.7,300 480.35,300Q455,300 437.5,317.15Q420,334.3 420,359.65Q420,385 437.35,402.5Q454.7,420 480.35,420ZM480,660L480,660Q480,660 480,660Q480,660 480,660Q480,660 480,660Q480,660 480,660L480,660L480,660ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Z"/>
</vector>

View file

@ -464,6 +464,17 @@ object NativeLibrary {
*/
external fun submitInlineKeyboardInput(key_code: Int)
/**
* Connects to a room (similar with desktop version's "direct connect")
*/
external fun connectToRoom(nickname: String, server_addr: String, server_port: Int, password: String)
/**
* Returns the state of the room member (client)
* @return The state as a string
*/
external fun getRoomMemberState(): String
/**
* Button type for use in onTouchEvent
*/

View file

@ -10,6 +10,7 @@ import android.content.Context
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.DocumentsTree
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
import org.yuzu.yuzu_emu.utils.MultiplayerHelper
import org.yuzu.yuzu_emu.utils.NetworkHelper
import java.io.File
@ -48,6 +49,7 @@ class YuzuApplication : Application() {
DirectoryInitialization.start(applicationContext)
GpuDriverHelper.initializeDriverParameters(applicationContext)
NetworkHelper.setRoutes(applicationContext)
MultiplayerHelper.initRoom(applicationContext)
NativeLibrary.logDeviceInfo()
createNotificationChannels();

View file

@ -109,6 +109,7 @@ class Settings {
const val SECTION_CPU = "Cpu"
const val SECTION_NETWORK = "Network"
const val SECTION_THEME = "Theme"
const val SECTION_MULTIPLAYER = "Multiplayer"
const val SECTION_DEBUG = "Debug"
const val PREF_OVERLAY_INIT = "OverlayInit"
@ -131,6 +132,12 @@ class Settings {
const val PREF_BUTTON_TOGGLE_13 = "buttonToggle13"
const val PREF_BUTTON_TOGGLE_14 = "buttonToggle14"
const val PREF_ROOM_ADDRESS = "MultiplayerRoom_ServerAddress"
const val PREF_ROOM_PORT = "MultiplayerRoom_ServerPort"
const val PREF_ROOM_NICKNAME = "MultiplayerRoom_Nickname"
const val PREF_ROOM_PASSWORD = "MultiplayerRoom_Password"
const val PREF_ROOM_CONNECT_ON_START = "MultiplayerRoom_ConnectOnStart"
const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics"

View file

@ -12,6 +12,7 @@ import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
@ -67,6 +68,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
Settings.SECTION_RENDERER -> addGraphicsSettings(sl)
Settings.SECTION_AUDIO -> addAudioSettings(sl)
Settings.SECTION_NETWORK -> addNetworkSettings(sl)
Settings.SECTION_MULTIPLAYER -> addMultiplayerSettings(sl)
Settings.SECTION_THEME -> addThemeSettings(sl)
Settings.SECTION_DEBUG -> addDebugSettings(sl)
else -> {
@ -460,6 +462,138 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
}
}
private fun addMultiplayerSettings(sl: ArrayList<SettingsItem>) {
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_multiplayer))
sl.apply {
val serverAddress: AbstractStringSetting = object : AbstractStringSetting {
override var string: String
get() = preferences.getString(Settings.PREF_ROOM_ADDRESS, "") ?: ""
set(value) {
preferences.edit()
.putString(Settings.PREF_ROOM_ADDRESS, value)
.apply()
}
override val key: String? = null
override val section: String? = null
override val isRuntimeEditable: Boolean = false
override val valueAsString: String
get() = preferences.getString(Settings.PREF_ROOM_ADDRESS, "") ?: ""
override val defaultValue: Any = -1
}
val serverPort: AbstractStringSetting = object : AbstractStringSetting {
override var string: String
get() = preferences.getString(Settings.PREF_ROOM_PORT, "24872") ?: "24872"
set(value) {
preferences.edit()
.putString(Settings.PREF_ROOM_PORT, value)
.apply()
}
override val key: String? = null
override val section: String? = null
override val isRuntimeEditable: Boolean = false
override val valueAsString: String
get() = preferences.getString(Settings.PREF_ROOM_PORT, "24872") ?: "24872"
override val defaultValue: Any = "24872"
}
val nickname: AbstractStringSetting = object : AbstractStringSetting {
override var string: String
get() = preferences.getString(Settings.PREF_ROOM_NICKNAME, "") ?: ""
set(value) {
preferences.edit()
.putString(Settings.PREF_ROOM_NICKNAME, value)
.apply()
}
override val key: String? = null
override val section: String? = null
override val isRuntimeEditable: Boolean = false
override val valueAsString: String
get() = preferences.getString(Settings.PREF_ROOM_NICKNAME, "") ?: ""
override val defaultValue: Any = -1
}
val password: AbstractStringSetting = object : AbstractStringSetting {
override var string: String
get() = preferences.getString(Settings.PREF_ROOM_PASSWORD, "") ?: ""
set(value) {
preferences.edit()
.putString(Settings.PREF_ROOM_PASSWORD, value)
.apply()
}
override val key: String? = null
override val section: String? = null
override val isRuntimeEditable: Boolean = false
override val valueAsString: String
get() = preferences.getString(Settings.PREF_ROOM_PASSWORD, "") ?: ""
override val defaultValue: Any = -1
}
val connectOnStart: AbstractBooleanSetting = object : AbstractBooleanSetting {
override var boolean: Boolean
get() = preferences.getBoolean(Settings.PREF_ROOM_CONNECT_ON_START, false)
set(value) {
preferences.edit()
.putBoolean(Settings.PREF_ROOM_CONNECT_ON_START, value)
.apply()
}
override val key: String? = null
override val section: String? = null
override val isRuntimeEditable: Boolean = false
override val valueAsString: String
get() = preferences.getBoolean(Settings.PREF_ROOM_CONNECT_ON_START, false).toString()
override val defaultValue: Any = -1
}
add(
TextSetting(
serverAddress,
R.string.multiplayer_room_server_address,
0,
"",
""
)
)
add(
TextSetting(
serverPort,
R.string.multiplayer_room_server_port,
0,
"",
""
)
)
add(
TextSetting(
nickname,
R.string.multiplayer_room_nickname,
0,
"",
""
)
)
add(
TextSetting(
password,
R.string.multiplayer_room_password,
0,
"",
""
)
)
add(
SwitchSetting(
connectOnStart,
R.string.multiplayer_room_connect_on_start,
0,
"",
false
)
)
}
}
private fun addDebugSettings(sl: ArrayList<SettingsItem>) {
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_debug))
sl.apply {

View file

@ -84,6 +84,11 @@ class HomeSettingsFragment : Fragment() {
R.string.theme_and_color_description,
R.drawable.ic_palette
) { SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") },
HomeSetting(
R.string.preferences_multiplayer,
R.string.multiplayer_description,
R.drawable.ic_multiplayer
) { SettingsActivity.launch(requireContext(), Settings.SECTION_MULTIPLAYER, "") },
HomeSetting(
R.string.install_gpu_driver,
R.string.install_gpu_driver_description,

View file

@ -0,0 +1,21 @@
package org.yuzu.yuzu_emu.utils
import android.content.Context
import androidx.preference.PreferenceManager
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.features.settings.model.Settings
object MultiplayerHelper {
fun initRoom(context: Context) {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
if(preferences.getBoolean(Settings.PREF_ROOM_CONNECT_ON_START, false)) {
val addr = preferences.getString(Settings.PREF_ROOM_ADDRESS, "") ?: ""
val port = preferences.getString(Settings.PREF_ROOM_PORT, "24872") ?: "24872"
val nickname = preferences.getString(Settings.PREF_ROOM_NICKNAME, "") ?: ""
val password = preferences.getString(Settings.PREF_ROOM_PASSWORD, "") ?: ""
NativeLibrary.connectToRoom(nickname, addr, port.toIntOrNull() ?: 0, password)
}
}
}

View file

@ -5,7 +5,6 @@ package org.yuzu.yuzu_emu.utils
import android.content.Context
import android.net.ConnectivityManager
import androidx.preference.PreferenceManager
object NetworkHelper {
fun setRoutes(context: Context) {

View file

@ -13,6 +13,8 @@
#include <android/api-level.h>
#include <android/native_window_jni.h>
#include <network/room_member.h>
#include <network/network.h>
#include "common/detached_tasks.h"
#include "common/dynamic_library.h"
@ -344,6 +346,29 @@ public:
return m_software_keyboard;
}
void DirectConnectToRoom(const std::string& nickname, const char* server_addr = "127.0.0.1",
u16 server_port = Network::DefaultRoomPort,
const std::string& password = "") {
auto room_network = m_system.GetRoomNetwork();
if (const auto member = room_network.GetRoomMember().lock()) {
// Prevent the user from trying to join a room while they are already joining.
if (member->GetState() == Network::RoomMember::State::Joining || member->IsConnected()) {
return;
} else {
member->Join(nickname, server_addr, server_port);
}
}
}
Network::RoomMember::State GetRoomMemberState() {
if (const auto member = m_system.GetRoomNetwork().GetRoomMember().lock()) {
return member->GetState();
} else {
return Network::RoomMember::State::Idle;
}
}
private:
struct RomMetadata {
std::string title;
@ -771,4 +796,45 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardInput(JNIEnv* env
EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardInput(j_key_code);
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_connectToRoom(JNIEnv* env, jclass clazz,
jstring nickname,
jstring server_addr,
jint server_port,
jstring password) {
EmulationSession::GetInstance().DirectConnectToRoom(
GetJString(env, nickname),
GetJString(env, server_addr).c_str(),
server_port,
GetJString(env, password)
);
}
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getRoomMemberState(JNIEnv* env, jclass clazz) {
auto state = EmulationSession::GetInstance().GetRoomMemberState();
std::string state_str{};
switch(state) {
using State = Network::RoomMember::State;
case State::Uninitialized:
state_str = "Uninitialized";
break;
case State::Idle:
state_str = "Idle";
break;
case State::Joining:
state_str = "Joining";
break;
case State::Joined:
state_str = "Joined";
break;
case State::Moderator:
state_str = "Moderator";
break;
}
return env->NewStringUTF(state_str.c_str());
}
} // extern "C"

View file

@ -84,6 +84,7 @@
<string name="open_user_folder">Open yuzu folder</string>
<string name="open_user_folder_description">Manage yuzu\'s internal files</string>
<string name="theme_and_color_description">Modify the look of the app</string>
<string name="multiplayer_description">Play with your friends!</string>
<string name="no_file_manager">No file manager found</string>
<string name="notification_no_directory_link">Could not open yuzu directory</string>
<string name="notification_no_directory_link_description">Please locate the user folder with the file manager\'s side panel manually.</string>
@ -155,6 +156,13 @@
<string name="network_route_desc">Sets the default network route</string>
<string name="set_network_route">Set network route</string>
<!-- Multiplayer settings strings -->
<string name="multiplayer_room_server_address">Server address</string>
<string name="multiplayer_room_server_port">Port</string>
<string name="multiplayer_room_nickname">Nickname</string>
<string name="multiplayer_room_password">Password</string>
<string name="multiplayer_room_connect_on_start">Connect on start</string>
<!-- Graphics settings strings -->
<string name="renderer_api">API</string>
<string name="renderer_accuracy">Accuracy level</string>
@ -211,6 +219,7 @@
<string name="preferences_graphics">Graphics</string>
<string name="preferences_audio">Audio</string>
<string name="preferences_theme">Theme and color</string>
<string name="preferences_multiplayer">Multiplayer</string>
<string name="preferences_debug">Debug</string>
<!-- ROM loading errors -->

View file

@ -81,6 +81,7 @@ void DirectConnectWindow::Connect() {
}
}
}
if (!ui->ip->hasAcceptableInput()) {
NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID);
return;