Compare commits

...

13 Commits
v2.0 ... v2.0.2

3 changed files with 145 additions and 68 deletions

View File

@ -67,7 +67,7 @@ Don't see your browser in the table? If it supports Tampermonkey/Userscript then
## Features
<img width="400" alt="Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/70b754fa-a638-4d02-bd05-0a3bdf5e1fcd">
<img width="400" alt="Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/ca38b3fa-1e89-4b37-937c-a6796c07cdf1">
<br>
<img width="400" alt="Remote Play dialog" src="https://github.com/redphx/better-xcloud/assets/96280/daf7f698-a228-4f9c-8f23-9669e061a64c">
<br>
@ -120,9 +120,7 @@ Don't see your browser in the table? If it supports Tampermonkey/Userscript then
> Hide the mouse cursor after 3 seconds of not moving.
### Controller
- Adjust controller polling rate
> Higher is better (reduce input latency).
- Enable controller shortcuts
- Enable controller shortcuts
> `Home` is the button which activates the Xbox sidebar menu (similar to the Xbox/Nexus button on the official controller).
> Not all controllers have this button. It's the `B16` button on the [Gamepad Tester site](https://hardwaretester.com/gamepad).
> More shortcuts will be added later.

View File

@ -1,5 +1,5 @@
// ==UserScript==
// @name Better xCloud
// @namespace https://github.com/redphx
// @version 2.0
// @version 2.0.2
// ==/UserScript==

View File

@ -1,7 +1,7 @@
// ==UserScript==
// @name Better xCloud
// @namespace https://github.com/redphx
// @version 2.0
// @version 2.0.2
// @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx
// @license MIT
@ -13,7 +13,7 @@
// ==/UserScript==
'use strict';
const SCRIPT_VERSION = '2.0';
const SCRIPT_VERSION = '2.0.2';
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
const ENABLE_MKB = false;
@ -311,6 +311,7 @@ const Translations = {
"can-stream-xbox-360-games": {
"de-DE": "Kann Xbox 360 Spiele streamen",
"en-US": "Can stream Xbox 360 games",
"es-ES": "Puede transmitir juegos de Xbox 360",
"it-IT": "Puoi riprodurre i giochi Xbox 360",
"ja-JP": "Xbox 360ゲームのストリーミング可能",
"pl-PL": "Można strumieniować gry Xbox 360",
@ -321,6 +322,7 @@ const Translations = {
"cant-stream-xbox-360-games": {
"de-DE": "Kann Xbox 360 Spiele nicht streamen",
"en-US": "Can't stream Xbox 360 games",
"es-ES": "No puede transmitir juegos de Xbox 360",
"it-IT": "Impossibile riprodurre i giochi Xbox 360",
"ja-JP": "Xbox 360ゲームのストリーミング不可",
"pl-PL": "Nie można strumieniować gier Xbox 360",
@ -406,6 +408,7 @@ const Translations = {
"console-connect": {
"de-DE": "Verbinden",
"en-US": "Connect",
"es-ES": "Conectar",
"it-IT": "Connetti",
"ja-JP": "本体に接続",
"pl-PL": "Połącz",
@ -432,6 +435,7 @@ const Translations = {
"controller": {
"de-DE": "Controller",
"en-US": "Controller",
"es-ES": "Joystick",
"it-IT": "Controller",
"ja-JP": "コントローラー",
"pl-PL": "Kontroler",
@ -441,8 +445,11 @@ const Translations = {
"zh-CN": "手柄",
},
"controller-polling-rate": {
"de-DE": "Controller-Abfragerate",
"en-US": "Controller polling rate",
"es-ES": "Tasa de sondeo del Joystick",
"ja-JP": "コントローラーポーリングレート",
"pl-PL": "Częstotliwości raportowania kontrolera",
"pt-BR": "Taxa de consulta do controle",
"tr-TR": "Oyun kumandası işlem hızı",
"vi-VN": "Tần suất cập nhật của bộ điều khiển",
@ -568,6 +575,7 @@ const Translations = {
"enable-controller-shortcuts": {
"de-DE": "Controller-Shortcuts aktivieren",
"en-US": "Enable controller shortcuts",
"es-ES": "Habilitar accesos directos del Joystick",
"it-IT": "Consenti scorciatoie da controller",
"ja-JP": "コントローラーショートカットを有効化",
"pl-PL": "Włącz skróty kontrolera",
@ -592,8 +600,12 @@ const Translations = {
"zh-CN": "游戏启动时打开麦克风",
},
"enable-mkb": {
"de-DE": "Maus- und Tastaturunterstützung aktivieren",
"en-US": "Enable Mouse & Keyboard support",
"es-ES": "Habilitar soporte para ratón y teclado",
"ja-JP": "マウス&キーボードのサポートを有効化",
"pl-PL": "Włącz obsługę myszy i klawiatury",
"pt-BR": "Habilitar suporte ao Mouse & Teclado",
"tr-TR": "Klavye ve fare desteğini aktive et",
"vi-VN": "Kích hoạt hỗ trợ Chuột & Bàn phím",
},
@ -612,6 +624,16 @@ const Translations = {
"vi-VN": "Bật chế độ \"Xem nhanh\"",
"zh-CN": "仅在打开设置时显示统计信息",
},
"enable-remote-play-feature": {
"de-DE": "\"Remote Play\" Funktion aktivieren",
"en-US": "Enable the \"Remote Play\" feature",
"es-ES": "Activar la función \"Reproducción remota\"",
"ja-JP": "リモートプレイ機能を有効化",
"pl-PL": "Włącz funkcję \"Gra zdalna\"",
"pt-BR": "Ativar o recurso \"Reprodução Remota\"",
"tr-TR": "\"Uzaktan Oynama\" özelliğini aktive et",
"vi-VN": "Bật tính năng \"Chơi từ xa\"",
},
"enable-volume-control": {
"de-DE": "Lautstärkeregelung aktivieren",
"en-US": "Enable volume control feature",
@ -627,14 +649,19 @@ const Translations = {
"zh-CN": "启用音量控制",
},
"fast": {
"de-DE": "Schnell",
"en-US": "Fast",
"es-ES": "Rápido",
"ja-JP": "高速",
"pl-PL": "Szybko",
"pt-BR": "Rápido",
"tr-TR": "Hızlı",
"vi-VN": "Nhanh",
},
"getting-consoles-list": {
"de-DE": "Rufe Liste der Konsolen ab...",
"en-US": "Getting the list of consoles...",
"es-ES": "Obteniendo la lista de consolas...",
"it-IT": "Ottenere la lista delle consoles...",
"ja-JP": "本体のリストを取得中...",
"pl-PL": "Pobieranie listy konsoli...",
@ -703,8 +730,11 @@ const Translations = {
"zh-CN": "大",
},
"layout": {
"de-DE": "Layout",
"en-US": "Layout",
"es-ES": "Diseño",
"ja-JP": "レイアウト",
"pl-PL": "Układ",
"pt-BR": "Layout",
"tr-TR": "Arayüz Görünümü",
"vi-VN": "Bố cục",
@ -725,14 +755,22 @@ const Translations = {
"zh-CN": "载入画面",
},
"max-bitrate": {
"de-DE": "Max. Bitrate",
"en-US": "Max bitrate",
"es-ES": "Tasa de bits máxima",
"ja-JP": "最大ビットレート",
"pl-PL": "Maksymalny bitrate",
"pt-BR": "Taxa máxima dos bits",
"tr-TR": "Maksimum bithızı",
"vi-VN": "Bitrate tối đa",
},
"may-not-work-properly": {
"de-DE": "Funktioniert evtl. nicht fehlerfrei!",
"en-US": "May not work properly!",
"es-ES": "¡Puede que no funcione correctamente!",
"ja-JP": "正常に動作しない場合があります!",
"pl-PL": "Może nie działać poprawnie!",
"pt-BR": "Pode não funcionar corretamente!",
"tr-TR": "Düzgün çalışmayabilir!",
"vi-VN": "Có thể không hoạt động!",
},
@ -769,6 +807,7 @@ const Translations = {
"microphone": {
"de-DE": "Mikrofon",
"en-US": "Microphone",
"es-ES": "Micrófono",
"it-IT": "Microfono",
"ja-JP": "マイク",
"pl-PL": "Mikrofon",
@ -778,14 +817,19 @@ const Translations = {
"zh-CN": "麦克风",
},
"mouse-and-keyboard": {
"de-DE": "Maus & Tastatur",
"en-US": "Mouse & Keyboard",
"es-ES": "Ratón y teclado",
"ja-JP": "マウス&キーボード",
"pl-PL": "Mysz i klawiatura",
"pt-BR": "Mouse e Teclado",
"tr-TR": "Klavye ve Fare",
"vi-VN": "Chuột và Bàn phím",
},
"muted": {
"de-DE": "Stumm",
"en-US": "Muted",
"es-ES": "Silenciado",
"it-IT": "Microfono disattivato",
"ja-JP": "ミュート",
"pl-PL": "Wyciszony",
@ -797,6 +841,7 @@ const Translations = {
"no-consoles-found": {
"de-DE": "Keine Konsolen gefunden",
"en-US": "No consoles found",
"es-ES": "No se encontraron consolas",
"it-IT": "Nessuna console trovata",
"ja-JP": "本体が見つかりません",
"pl-PL": "Nie znaleziono konsoli",
@ -838,6 +883,7 @@ const Translations = {
"on": {
"de-DE": "An",
"en-US": "On",
"es-ES": "Activado",
"it-IT": "Attivo",
"ja-JP": "オン",
"pl-PL": "Włącz",
@ -846,9 +892,13 @@ const Translations = {
"vi-VN": "Bật",
"zh-CN": "开启",
},
"only-support-some-games": {
"en-US": "Only support some games",
"only-supports-some-games": {
"de-DE": "Unterstützt nur einige Spiele",
"en-US": "Only supports some games",
"es-ES": "Sólo soporta algunos juegos",
"ja-JP": "一部のゲームのみサポート",
"pl-PL": "Wspiera tylko niektóre gry",
"pt-BR": "Suporta apenas alguns jogos",
"tr-TR": "Yalnızca belli oyunlar destekleniyor",
"vi-VN": "Chỉ hỗ trợ một vài game",
},
@ -900,8 +950,9 @@ const Translations = {
"powered-off": {
"de-DE": "Ausgeschaltet",
"en-US": "Powered off",
"es-ES": "Desactivado",
"it-IT": "Spento",
"ja-JP": "電源オフ",
"ja-JP": "本体オフ",
"pl-PL": "Zasilanie wyłączone",
"pt-BR": "Desligado",
"tr-TR": "Kapalı",
@ -911,8 +962,9 @@ const Translations = {
"powered-on": {
"de-DE": "Eingeschaltet",
"en-US": "Powered on",
"es-ES": "Activado",
"it-IT": "Acceso",
"ja-JP": "電源オン",
"ja-JP": "本体オン",
"pl-PL": "Zasilanie włączone",
"pt-BR": "Ligado",
"tr-TR": "Açık",
@ -997,6 +1049,7 @@ const Translations = {
"remote-play": {
"de-DE": "Remote Play",
"en-US": "Remote Play",
"es-ES": "Reproducción remota",
"it-IT": "Riproduzione Remota",
"ja-JP": "リモートプレイ",
"pl-PL": "Gra zdalna",
@ -1231,8 +1284,12 @@ const Translations = {
"zh-CN": "跳过 Xbox 启动动画",
},
"slow": {
"de-DE": "Langsam",
"en-US": "Slow",
"es-ES": "Lento",
"ja-JP": "低速",
"pl-PL": "Wolno",
"pt-BR": "Lento",
"tr-TR": "Yavaş",
"vi-VN": "Chậm",
},
@ -1252,8 +1309,11 @@ const Translations = {
"zh-CN": "小",
},
"smart-tv": {
"de-DE": "Smart TV",
"en-US": "Smart TV",
"es-ES": "Smart TV",
"ja-JP": "スマートTV",
"pl-PL": "Smart TV",
"pt-BR": "Smart TV",
"tr-TR": "Akıllı TV",
"vi-VN": "TV thông minh",
@ -1261,6 +1321,7 @@ const Translations = {
"sound": {
"de-DE": "Ton",
"en-US": "Sound",
"es-ES": "Sonido",
"it-IT": "Suoni",
"ja-JP": "サウンド",
"pl-PL": "Dźwięk",
@ -1272,6 +1333,7 @@ const Translations = {
"standby": {
"de-DE": "Standby",
"en-US": "Standby",
"es-ES": "Modo de espera",
"it-IT": "Sospendi",
"ja-JP": "スタンバイ",
"pl-PL": "Stan czuwania",
@ -1643,6 +1705,7 @@ const Translations = {
"unknown": {
"de-DE": "Unbekannt",
"en-US": "Unknown",
"es-ES": "Desconocido",
"it-IT": "Sconosciuto",
"ja-JP": "不明",
"pl-PL": "Nieznane",
@ -1652,14 +1715,19 @@ const Translations = {
"zh-CN": "未知",
},
"unlimited": {
"de-DE": "Unbegrenzt",
"en-US": "Unlimited",
"es-ES": "Ilimitado",
"ja-JP": "無制限",
"pl-PL": "Bez ograniczeń",
"pt-BR": "Ilimitado",
"tr-TR": "Limitsiz",
"vi-VN": "Không giới hạn",
},
"unmuted": {
"de-DE": "Ton an",
"en-US": "Unmuted",
"es-ES": "Activar sonido",
"it-IT": "Microfono attivato",
"ja-JP": "ミュート解除",
"pl-PL": "Wyciszenie wyłączone",
@ -1669,8 +1737,12 @@ const Translations = {
"zh-CN": "已取消静音",
},
"use-mouse-absolute-position": {
"de-DE": "Absolute Position der Maus verwenden",
"en-US": "Use mouse's absolute position",
"es-ES": "Usar la posición absoluta del ratón",
"ja-JP": "マウスの絶対座標を使用",
"pl-PL": "Użyj pozycji bezwzględnej myszy",
"pt-BR": "Usar posição absoluta do mouse",
"tr-TR": "Farenin mutlak pozisyonunu baz al",
"vi-VN": "Sử dụng vị trí tuyệt đối của chuột",
},
@ -2047,13 +2119,12 @@ class RemotePlay {
$connectButton = CE('button', {'class': 'bx-primary-button bx-no-margin'}, __('console-connect')),
);
REMOTE_PLAY_CONFIG = {
serverId: con.serverId,
};
$connectButton.addEventListener('click', e => {
const url = window.location.href.substring(0, 31) + '/launch/starfield/9NCJSXWZTP88#remote-play';
// const url = '/play';
REMOTE_PLAY_CONFIG = {
serverId: con.serverId,
};
const url = window.location.href.substring(0, 31) + '/launch/fortnite/BT5P2X999VH2#remote-play';
const $pageContent = document.getElementById('PageContent');
const $anchor = CE('a', {href: url, class: 'bx-hidden', style: 'position:absolute;top:-9990px;left:-9999px'}, '');
@ -2074,18 +2145,11 @@ class RemotePlay {
RemotePlay.#$content.parentElement.replaceChild($fragment, RemotePlay.#$content);
}
static #onLoad() {
const CE = createElement;
const $ui = CE('div', {'class': 'bx-container'},
CE('h2', {}, __('remote-play')),
CE('div', {'id': 'bxUi'}, __('getting-consoles-list')),
);
const $landingPageHeader = document.querySelector('h2[class*=LandingPage-module__header]');
$landingPageHeader.parentElement.insertBefore($ui, $landingPageHeader);
}
static detect() {
if (!PREFS.get(Preferences.REMOTE_PLAY_ENABLED)) {
return;
}
IS_REMOTE_PLAYING = window.location.pathname.includes('/launch/') && window.location.hash.startsWith('#remote-play');
if (IS_REMOTE_PLAYING) {
window.BX_REMOTE_PLAY_CONFIG = REMOTE_PLAY_CONFIG;
@ -3276,7 +3340,7 @@ class PreloadedState {
return this._state;
},
set: (state) => {
set: state => {
this._state = state;
APP_CONTEXT = structuredClone(state.appContext);
@ -3322,7 +3386,6 @@ class Preferences {
static get STREAM_DISABLE_FEEDBACK_DIALOG() { return 'stream_disable_feedback_dialog'; }
static get CONTROLLER_ENABLE_SHORTCUTS() { return 'controller_enable_shortcuts'; }
static get CONTROLLER_POLLING_RATE() { return 'controller_polling_rate'; }
static get MKB_ENABLED() { return 'mkb_enabled'; }
static get MKB_ABSOLUTE_MOUSE() { return 'mkb_absolute_mouse'; }
@ -3360,6 +3423,7 @@ class Preferences {
static get STATS_OPACITY() { return 'stats_opacity'; }
static get STATS_CONDITIONAL_FORMATTING() { return 'stats_conditional_formatting'; }
static get REMOTE_PLAY_ENABLED() { return 'xhome_enabled'; }
static get REMOTE_PLAY_RESOLUTION() { return 'xhome_resolution'; }
// Deprecated
@ -3553,15 +3617,6 @@ class Preferences {
[Preferences.CONTROLLER_ENABLE_SHORTCUTS]: {
'default': false,
},
[Preferences.CONTROLLER_POLLING_RATE]: {
'type': 'number',
'default': 50,
'options': {
16: '62.5 Hz (16ms)',
32: '31.25 Hz (32ms)',
50: `20 Hz (50ms - ${__('default')})`,
},
},
[Preferences.MKB_ENABLED]: {
'default': false,
@ -3707,6 +3762,10 @@ class Preferences {
'default': false,
},
[Preferences.REMOTE_PLAY_ENABLED]: {
'default': false,
},
[Preferences.REMOTE_PLAY_RESOLUTION]: {
'default': 1080,
'options': {
@ -4033,36 +4092,24 @@ const PREFS = new Preferences();
class Patcher {
static #PATCHES = {
// Modify controller polling rate
controllerPollingRate: (PREFS.get(Preferences.CONTROLLER_POLLING_RATE) !== 50) && function(funcStr) {
const text = '.startGamepadPolling=()';
const index = funcStr.indexOf(text);
if (index === -1) {
return false;
}
const patchedStr = funcStr.substring(index, index + 100).replace(/setInterval\((\w+),(\d+)\)/, `setInterval($1,${PREFS.get(Preferences.CONTROLLER_POLLING_RATE)})`);
return funcStr.substring(0, index) + patchedStr + funcStr.substring(index + 100);
},
// Enable Remote Play feature
connectMode: function(funcStr) {
remotePlayConnectMode: PREFS.get(Preferences.REMOTE_PLAY_ENABLED) && function(funcStr) {
const text = 'connectMode:"cloud-connect"';
if (!funcStr.includes(text)) {
return false;
}
return funcStr.replace(text, `connectMode:window.BX_REMOTE_PLAY_CONFIG?"xhome-connect":"cloud-connect",remotePlayServerId:window.BX_REMOTE_PLAY_CONFIG&&window.BX_REMOTE_PLAY_CONFIG.serverId||''`);
return funcStr.replace(text, `connectMode:window.BX_REMOTE_PLAY_CONFIG?"xhome-connect":"cloud-connect",remotePlayServerId:(window.BX_REMOTE_PLAY_CONFIG&&window.BX_REMOTE_PLAY_CONFIG.serverId)||''`);
},
// Replace "/direct-connect" with "/play"
directConnectUrl: function(funcStr) {
remotePlayDirectConnectUrl: PREFS.get(Preferences.REMOTE_PLAY_ENABLED) && function(funcStr) {
const index = funcStr.indexOf('/direct-connect');
if (index === -1) {
return false;
}
return funcStr.replace(funcStr.substring(index - 9, index + 15), '/play');
return funcStr.replace(funcStr.substring(index - 9, index + 15), 'https://www.xbox.com/play');
},
// Set disableTelemetry() to true
@ -4085,6 +4132,31 @@ class Patcher {
return funcStr.replace(text, 'this.trackEvent=e=>{},this.uwuwu=');
},
// Disable ApplicationInsights.track() function
disableAiTrack: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) {
const text = '.track=function(';
const index = funcStr.indexOf(text);
if (index === -1) {
return false;
}
if (funcStr.substring(0, index + 200).includes('"AppInsightsCore')) {
return false;
}
return funcStr.substring(0, index) + '.track=function(e){},!!function(' + funcStr.substring(index + text.length);
},
// Block WebRTC stats collector
blockWebRtcStatsCollector: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) {
const text = 'this.intervalMs=0,';
if (!funcStr.includes(text)) {
return false;
}
return funcStr.replace(text, 'false,' + text);
},
// Set TV layout
tvLayout: PREFS.get(Preferences.UI_LAYOUT) === 'tv' && function(funcStr) {
const text = '?"tv":"default"';
@ -4107,7 +4179,7 @@ class Patcher {
}
return funcStr;
}
},
};
static #patchFunctionBind() {
@ -5341,9 +5413,6 @@ function interceptHttpRequests() {
try {
const clone = request.clone();
const resp = (await (await orgFetch(...arg)).json());
RemotePlay.XCLOUD_TOKEN = resp.gsToken;
const obj = await clone.json();
obj.offeringId = 'xhome';
@ -5424,6 +5493,9 @@ function interceptHttpRequests() {
return promise.then(response => {
return response.clone().json().then(obj => {
// Store xCloud token
RemotePlay.XCLOUD_TOKEN = obj.gsToken;
// Get server list
if (!Object.keys(SERVER_REGIONS).length) {
for (let region of obj.offeringSettings.regions) {
@ -5620,6 +5692,7 @@ function injectSettingsButton($parent) {
const CE = createElement;
const PREF_PREFERRED_REGION = getPreferredServerRegion();
const PREF_LATEST_VERSION = PREFS.get(Preferences.LATEST_VERSION);
const PREF_REMOTE_PLAY_ENABLED = PREFS.get(Preferences.REMOTE_PLAY_ENABLED);
// Setup Settings button
const $button = CE('button', {'class': 'bx-settings-button'}, PREF_PREFERRED_REGION);
@ -5643,7 +5716,7 @@ function injectSettingsButton($parent) {
});
let $updateAvailable;
let $remotePlayLink;
let $remotePlayBtn;
const $wrapper = CE('div', {'class': 'bx-settings-wrapper'},
CE('div', {'class': 'bx-settings-title-wrapper'},
CE('a', {
@ -5651,7 +5724,7 @@ function injectSettingsButton($parent) {
'href': SCRIPT_HOME,
'target': '_blank',
}, 'Better xCloud ' + SCRIPT_VERSION),
$remotePlayLink = CE('button', {'class': 'bx-primary-button bx-no-margin'}, __('remote-play')),
$remotePlayBtn = CE('button', {'class': 'bx-primary-button bx-no-margin'}, __('remote-play')),
)
);
$updateAvailable = CE('a', {
@ -5660,12 +5733,17 @@ function injectSettingsButton($parent) {
'target': '_blank',
});
$remotePlayLink.addEventListener('click', e => {
RemotePlay.showDialog();
if (PREF_REMOTE_PLAY_ENABLED) {
$remotePlayBtn.addEventListener('click', e => {
RemotePlay.showDialog();
// Hide Settings
$container.classList.add('bx-gone');
});
} else {
$remotePlayBtn.classList.add('bx-gone');
}
// Hide Settings
$container.classList.add('bx-gone');
});
$wrapper.appendChild($updateAvailable);
// Show new version indicator
@ -5678,6 +5756,7 @@ function injectSettingsButton($parent) {
const SETTINGS_UI = {
'Better xCloud': {
[Preferences.BETTER_XCLOUD_LOCALE]: __('language'),
[Preferences.REMOTE_PLAY_ENABLED]: __('enable-remote-play-feature'),
},
[__('server')]: {
[Preferences.SERVER_REGION]: __('region'),
@ -5694,7 +5773,6 @@ function injectSettingsButton($parent) {
[Preferences.STREAM_DISABLE_FEEDBACK_DIALOG]: __('disable-post-stream-feedback-dialog'),
},
[__('controller')]: {
[Preferences.CONTROLLER_POLLING_RATE]: __('controller-polling-rate'),
[Preferences.CONTROLLER_ENABLE_SHORTCUTS]: __('enable-controller-shortcuts'),
},
[__('touch-controller')]: {
@ -5705,7 +5783,7 @@ function injectSettingsButton($parent) {
[__('mouse-and-keyboard')]: {
'_note': '⚠️ ' + __('may-not-work-properly'),
[Preferences.MKB_ENABLED]: [__('enable-mkb'), __('only-support-some-games')],
[Preferences.MKB_ENABLED]: [__('enable-mkb'), __('only-supports-some-games')],
[Preferences.MKB_ABSOLUTE_MOUSE]: __('use-mouse-absolute-position'),
},
@ -6623,4 +6701,5 @@ if (PREFS.get(Preferences.CONTROLLER_ENABLE_SHORTCUTS)) {
}
Patcher.initialize();
RemotePlay.detect();