mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-07-08 07:11:43 +02:00
Compare commits
1 Commits
v3.1
...
feature/mk
Author | SHA1 | Date | |
---|---|---|---|
1d018cc0a3 |
@ -1,5 +1,5 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud
|
// @name Better xCloud
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 3.1
|
// @version 3.0.5
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud
|
// @name Better xCloud
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 3.1
|
// @version 3.0.5
|
||||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||||
// @author redphx
|
// @author redphx
|
||||||
// @license MIT
|
// @license MIT
|
||||||
@ -13,15 +13,14 @@
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const SCRIPT_VERSION = '3.1';
|
const SCRIPT_VERSION = '3.0.5';
|
||||||
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
|
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
|
||||||
|
|
||||||
const ENABLE_XCLOUD_LOGGER = false;
|
const ENABLE_XCLOUD_LOGGER = false;
|
||||||
const ENABLE_PRELOAD_BX_UI = false;
|
const ENABLE_PRELOAD_BX_UI = false;
|
||||||
const USE_DEV_TOUCH_LAYOUT = false;
|
|
||||||
|
|
||||||
const ENABLE_NATIVE_MKB_BETA = false;
|
|
||||||
window.NATIVE_MKB_TITLES = [
|
window.NATIVE_MKB_TITLES = [
|
||||||
|
'BT5P2X999VH2',
|
||||||
// Not working anymore
|
// Not working anymore
|
||||||
// '9PMQDM08SNK9', // MS Flight Simulator
|
// '9PMQDM08SNK9', // MS Flight Simulator
|
||||||
// '9NP1P1WFS0LB', // Halo Infinite
|
// '9NP1P1WFS0LB', // Halo Infinite
|
||||||
@ -38,6 +37,16 @@ window.NATIVE_MKB_TITLES = [
|
|||||||
// '9P731Z4BBCT3', // Atomic Heart
|
// '9P731Z4BBCT3', // Atomic Heart
|
||||||
];
|
];
|
||||||
|
|
||||||
|
window.REMOTE_PLAY_NATIVE_MKB_TITLES = [
|
||||||
|
// DOOM 64
|
||||||
|
'DOOM64',
|
||||||
|
'BT5P2X999VH2',
|
||||||
|
|
||||||
|
// Cyperpunk 2077
|
||||||
|
'222473492',
|
||||||
|
'BX3M8L83BBRW',
|
||||||
|
];
|
||||||
|
|
||||||
console.log(`[Better xCloud] readyState: ${document.readyState}`);
|
console.log(`[Better xCloud] readyState: ${document.readyState}`);
|
||||||
|
|
||||||
const BxEvent = {
|
const BxEvent = {
|
||||||
@ -707,7 +716,6 @@ const Translations = {
|
|||||||
"en-US": "Deadzone counterweight",
|
"en-US": "Deadzone counterweight",
|
||||||
"es-ES": "Contrapeso de la zona muerta",
|
"es-ES": "Contrapeso de la zona muerta",
|
||||||
"ja-JP": "デッドゾーンのカウンターウエイト",
|
"ja-JP": "デッドゾーンのカウンターウエイト",
|
||||||
"pl-PL": "Przeciwwaga martwej strefy",
|
|
||||||
"pt-BR": "Contador da Zona Morta",
|
"pt-BR": "Contador da Zona Morta",
|
||||||
"ru-RU": "Противодействие мертвой зоне игры",
|
"ru-RU": "Противодействие мертвой зоне игры",
|
||||||
"tr-TR": "Ölü alan denge ağırlığı",
|
"tr-TR": "Ölü alan denge ağırlığı",
|
||||||
@ -1282,17 +1290,6 @@ const Translations = {
|
|||||||
"vi-VN": "Nhấn vào để kích hoạt",
|
"vi-VN": "Nhấn vào để kích hoạt",
|
||||||
"zh-CN": "单击以启用",
|
"zh-CN": "单击以启用",
|
||||||
},
|
},
|
||||||
"mkb-disclaimer": {
|
|
||||||
"de-DE": "Das Nutzen dieser Funktion beim Online-Spielen könnte als Betrug angesehen werden",
|
|
||||||
"en-US": "Using this feature when playing online could be viewed as cheating",
|
|
||||||
"es-ES": "Usar esta función al jugar en línea podría ser visto como trampas",
|
|
||||||
"ja-JP": "オンラインプレイでこの機能を使用すると不正行為と判定される可能性があります",
|
|
||||||
"pl-PL": "Używanie tej funkcji podczas grania online może być postrzegane jako oszukiwanie",
|
|
||||||
"pt-BR": "Usar esta função em jogos online pode ser considerado como uma forma de trapaça",
|
|
||||||
"ru-RU": "Использование этой функции при игре онлайн может рассматриваться как читерство",
|
|
||||||
"uk-UA": "Використання цієї функції під час гри онлайн може розглядатися як шахрайство",
|
|
||||||
"vi-VN": "Sử dụng chức năng này khi chơi trực tuyến có thể bị xem là gian lận",
|
|
||||||
},
|
|
||||||
"mouse-and-keyboard": {
|
"mouse-and-keyboard": {
|
||||||
"de-DE": "Maus & Tastatur",
|
"de-DE": "Maus & Tastatur",
|
||||||
"en-US": "Mouse & Keyboard",
|
"en-US": "Mouse & Keyboard",
|
||||||
@ -2174,7 +2171,6 @@ const Translations = {
|
|||||||
"en-US": "Stick decay minimum",
|
"en-US": "Stick decay minimum",
|
||||||
"es-ES": "Disminuir mínimamente el analógico",
|
"es-ES": "Disminuir mínimamente el analógico",
|
||||||
"ja-JP": "スティックの減衰の最小値",
|
"ja-JP": "スティックの減衰の最小値",
|
||||||
"pl-PL": "Minimalne opóźnienie drążka",
|
|
||||||
"pt-BR": "Mínimo decaimento do analógico",
|
"pt-BR": "Mínimo decaimento do analógico",
|
||||||
"ru-RU": "Минимальная перезарядка стика",
|
"ru-RU": "Минимальная перезарядка стика",
|
||||||
"tr-TR": "Çubuğun ortalanma süresi minimumu",
|
"tr-TR": "Çubuğun ortalanma süresi minimumu",
|
||||||
@ -2187,7 +2183,6 @@ const Translations = {
|
|||||||
"en-US": "Stick decay strength",
|
"en-US": "Stick decay strength",
|
||||||
"es-ES": "Intensidad de decaimiento del analógico",
|
"es-ES": "Intensidad de decaimiento del analógico",
|
||||||
"ja-JP": "スティックの減衰の強さ",
|
"ja-JP": "スティックの減衰の強さ",
|
||||||
"pl-PL": "Siła opóźnienia drążka",
|
|
||||||
"pt-BR": "Força de decaimento do analógico",
|
"pt-BR": "Força de decaimento do analógico",
|
||||||
"ru-RU": "Скорость перезарядки стика",
|
"ru-RU": "Скорость перезарядки стика",
|
||||||
"tr-TR": "Çubuğun ortalanma gücü",
|
"tr-TR": "Çubuğun ortalanma gücü",
|
||||||
@ -2232,7 +2227,6 @@ const Translations = {
|
|||||||
"en-US": "Support Better xCloud",
|
"en-US": "Support Better xCloud",
|
||||||
"es-ES": "Apoyar a Better xCloud",
|
"es-ES": "Apoyar a Better xCloud",
|
||||||
"ja-JP": "Better xCloudをサポート",
|
"ja-JP": "Better xCloudをサポート",
|
||||||
"pl-PL": "Wesprzyj Better xCloud",
|
|
||||||
"pt-BR": "Suporte ao Melhor xCloud",
|
"pt-BR": "Suporte ao Melhor xCloud",
|
||||||
"ru-RU": "Поддержать Better xCloud",
|
"ru-RU": "Поддержать Better xCloud",
|
||||||
"tr-TR": "Better xCloud'a destek ver",
|
"tr-TR": "Better xCloud'a destek ver",
|
||||||
@ -2760,7 +2754,6 @@ window.addEventListener('load', e => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const NATIVE_FETCH = window.fetch;
|
|
||||||
const SERVER_REGIONS = {};
|
const SERVER_REGIONS = {};
|
||||||
var IS_PLAYING = false;
|
var IS_PLAYING = false;
|
||||||
var STREAM_WEBRTC;
|
var STREAM_WEBRTC;
|
||||||
@ -2769,12 +2762,9 @@ var STREAM_AUDIO_GAIN_NODE;
|
|||||||
var $STREAM_VIDEO;
|
var $STREAM_VIDEO;
|
||||||
var $SCREENSHOT_CANVAS;
|
var $SCREENSHOT_CANVAS;
|
||||||
var GAME_TITLE_ID;
|
var GAME_TITLE_ID;
|
||||||
var GAME_XBOX_TITLE_ID;
|
|
||||||
var GAME_PRODUCT_ID;
|
var GAME_PRODUCT_ID;
|
||||||
var APP_CONTEXT;
|
var APP_CONTEXT;
|
||||||
|
|
||||||
window.BX_EXPOSED = {};
|
|
||||||
|
|
||||||
let IS_REMOTE_PLAYING;
|
let IS_REMOTE_PLAYING;
|
||||||
let REMOTE_PLAY_CONFIG;
|
let REMOTE_PLAY_CONFIG;
|
||||||
|
|
||||||
@ -3123,7 +3113,6 @@ class TitlesInfo {
|
|||||||
const details = titleInfo.details;
|
const details = titleInfo.details;
|
||||||
TitlesInfo.update(details.productId, {
|
TitlesInfo.update(details.productId, {
|
||||||
titleId: titleInfo.titleId,
|
titleId: titleInfo.titleId,
|
||||||
xboxTitleId: details.xboxTitleId,
|
|
||||||
// Has more than one input type -> must have touch support
|
// Has more than one input type -> must have touch support
|
||||||
hasTouchSupport: (details.supportedInputTypes.length > 1),
|
hasTouchSupport: (details.supportedInputTypes.length > 1),
|
||||||
});
|
});
|
||||||
@ -3340,7 +3329,7 @@ class LoadingScreen {
|
|||||||
|
|
||||||
|
|
||||||
class TouchController {
|
class TouchController {
|
||||||
static get #EVENT_SHOW_DEFAULT_CONTROLLER() {
|
static get #EVENT_SHOW_CONTROLLER() {
|
||||||
return new MessageEvent('message', {
|
return new MessageEvent('message', {
|
||||||
data: '{"content":"{\\"layoutId\\":\\"\\"}","target":"/streaming/touchcontrols/showlayoutv2","type":"Message"}',
|
data: '{"content":"{\\"layoutId\\":\\"\\"}","target":"/streaming/touchcontrols/showlayoutv2","type":"Message"}',
|
||||||
origin: 'better-xcloud',
|
origin: 'better-xcloud',
|
||||||
@ -3361,8 +3350,6 @@ class TouchController {
|
|||||||
static #showing = false;
|
static #showing = false;
|
||||||
static #dataChannel;
|
static #dataChannel;
|
||||||
|
|
||||||
static #customLayouts = {};
|
|
||||||
|
|
||||||
static enable() {
|
static enable() {
|
||||||
TouchController.#enable = true;
|
TouchController.#enable = true;
|
||||||
}
|
}
|
||||||
@ -3375,17 +3362,8 @@ class TouchController {
|
|||||||
return TouchController.#enable;
|
return TouchController.#enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static #showDefault() {
|
|
||||||
TouchController.#dispatchMessage(TouchController.#EVENT_SHOW_DEFAULT_CONTROLLER);
|
|
||||||
TouchController.#showing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static #show() {
|
static #show() {
|
||||||
if (GAME_XBOX_TITLE_ID && GAME_XBOX_TITLE_ID in TouchController.#customLayouts) {
|
TouchController.#dispatchMessage(TouchController.#EVENT_SHOW_CONTROLLER);
|
||||||
TouchController.loadCustomLayout(GAME_XBOX_TITLE_ID);
|
|
||||||
} else {
|
|
||||||
TouchController.#showDefault();
|
|
||||||
}
|
|
||||||
TouchController.#showing = true;
|
TouchController.#showing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3421,55 +3399,6 @@ class TouchController {
|
|||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static #getCustomLayout(xboxTitleId, callback) {
|
|
||||||
xboxTitleId = '' + xboxTitleId;
|
|
||||||
if (xboxTitleId in TouchController.#customLayouts) {
|
|
||||||
callback(TouchController.#customLayouts[xboxTitleId]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url;
|
|
||||||
if (USE_DEV_TOUCH_LAYOUT) {
|
|
||||||
url = `https://raw.githubusercontent.com/redphx/better-xcloud/gh-pages/touch-layouts/dev/${xboxTitleId}.json`;
|
|
||||||
} else {
|
|
||||||
url = `https://raw.githubusercontent.com/redphx/better-xcloud/gh-pages/touch-layouts/${xboxTitleId}.json`;
|
|
||||||
}
|
|
||||||
window.BX_EXPOSED.touch_layout_manager && NATIVE_FETCH(url)
|
|
||||||
.then(resp => resp.json())
|
|
||||||
.then(json => {
|
|
||||||
TouchController.#customLayouts[xboxTitleId] = json;
|
|
||||||
callback(json);
|
|
||||||
})
|
|
||||||
.reject(() => {
|
|
||||||
TouchController.#customLayouts[xboxTitleId] = null;
|
|
||||||
callback(null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static loadCustomLayout(xboxTitleId) {
|
|
||||||
if (!window.BX_EXPOSED.touch_layout_manager) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
xboxTitleId = '' + xboxTitleId;
|
|
||||||
TouchController.#getCustomLayout(xboxTitleId, json => {
|
|
||||||
json && setTimeout(() => {
|
|
||||||
window.BX_EXPOSED.touch_layout_manager.changeLayoutForScope({
|
|
||||||
type: 'showLayout',
|
|
||||||
scope: '' + xboxTitleId,
|
|
||||||
subscope: 'base',
|
|
||||||
layout: {
|
|
||||||
id: 'System.Standard',
|
|
||||||
displayName: 'System',
|
|
||||||
layoutFile: {
|
|
||||||
content: json.layout,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static setup() {
|
static setup() {
|
||||||
const $style = document.createElement('style');
|
const $style = document.createElement('style');
|
||||||
document.documentElement.appendChild($style);
|
document.documentElement.appendChild($style);
|
||||||
@ -3534,26 +3463,9 @@ class TouchController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load custom touch layout
|
|
||||||
let showCustom = false;
|
|
||||||
try {
|
|
||||||
if (msg.data.includes('/titleinfo')) {
|
|
||||||
const json = JSON.parse(JSON.parse(msg.data).content);
|
|
||||||
if (json.focused) {
|
|
||||||
const xboxTitleId = parseInt(json.titleid, 16);
|
|
||||||
GAME_XBOX_TITLE_ID = xboxTitleId;
|
|
||||||
TouchController.loadCustomLayout(xboxTitleId);
|
|
||||||
showCustom = true;
|
|
||||||
} else {
|
|
||||||
GAME_XBOX_TITLE_ID = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) { console.log(e) }
|
|
||||||
|
|
||||||
|
|
||||||
// Dispatch a message to display generic touch controller
|
// Dispatch a message to display generic touch controller
|
||||||
if (!showCustom && msg.data.includes('touchcontrols/showtitledefault')) {
|
if (msg.data.includes('touchcontrols/showtitledefault')) {
|
||||||
TouchController.#showDefault();
|
TouchController.#show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6307,8 +6219,7 @@ class Preferences {
|
|||||||
'ready': () => {
|
'ready': () => {
|
||||||
const options = Preferences.SETTINGS[Preferences.STREAM_CODEC_PROFILE].options;
|
const options = Preferences.SETTINGS[Preferences.STREAM_CODEC_PROFILE].options;
|
||||||
if (Object.keys(options).length <= 1) {
|
if (Object.keys(options).length <= 1) {
|
||||||
Preferences.SETTINGS[Preferences.STREAM_CODEC_PROFILE].unsupported = true;
|
Preferences.SETTINGS[Preferences.STREAM_CODEC_PROFILE].unsupported = __('browser-unsupported-feature');
|
||||||
Preferences.SETTINGS[Preferences.STREAM_CODEC_PROFILE].note = '⚠️ ' + __('browser-unsupported-feature');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -6336,7 +6247,7 @@ class Preferences {
|
|||||||
'all': __('tc-all-games'),
|
'all': __('tc-all-games'),
|
||||||
'off': __('off'),
|
'off': __('off'),
|
||||||
},
|
},
|
||||||
'unsupported': !HAS_TOUCH_SUPPORT,
|
'unsupported': !HAS_TOUCH_SUPPORT ? __('device-unsupported-touch') : false,
|
||||||
},
|
},
|
||||||
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_STANDARD]: {
|
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_STANDARD]: {
|
||||||
'default': 'default',
|
'default': 'default',
|
||||||
@ -6345,7 +6256,7 @@ class Preferences {
|
|||||||
'white': __('tc-all-white'),
|
'white': __('tc-all-white'),
|
||||||
'muted': __('tc-muted-colors'),
|
'muted': __('tc-muted-colors'),
|
||||||
},
|
},
|
||||||
'unsupported': !HAS_TOUCH_SUPPORT,
|
'unsupported': !HAS_TOUCH_SUPPORT ? __('device-unsupported-touch') : false,
|
||||||
},
|
},
|
||||||
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_CUSTOM]: {
|
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_CUSTOM]: {
|
||||||
'default': 'default',
|
'default': 'default',
|
||||||
@ -6353,7 +6264,7 @@ class Preferences {
|
|||||||
'default': __('default'),
|
'default': __('default'),
|
||||||
'muted': __('tc-muted-colors'),
|
'muted': __('tc-muted-colors'),
|
||||||
},
|
},
|
||||||
'unsupported': !HAS_TOUCH_SUPPORT,
|
'unsupported': !HAS_TOUCH_SUPPORT ? __('device-unsupported-touch') : false,
|
||||||
},
|
},
|
||||||
[Preferences.STREAM_SIMPLIFY_MENU]: {
|
[Preferences.STREAM_SIMPLIFY_MENU]: {
|
||||||
'default': false,
|
'default': false,
|
||||||
@ -6400,11 +6311,6 @@ class Preferences {
|
|||||||
const userAgent = (window.navigator.orgUserAgent || window.navigator.userAgent || '').toLowerCase();
|
const userAgent = (window.navigator.orgUserAgent || window.navigator.userAgent || '').toLowerCase();
|
||||||
return userAgent.match(/(android|iphone|ipad)/) ? __('browser-unsupported-feature') : false;
|
return userAgent.match(/(android|iphone|ipad)/) ? __('browser-unsupported-feature') : false;
|
||||||
})(),
|
})(),
|
||||||
'ready': () => {
|
|
||||||
const pref = Preferences.SETTINGS[Preferences.MKB_ENABLED];
|
|
||||||
const note = __(pref.unsupported ? 'browser-unsupported-feature' : 'mkb-disclaimer');
|
|
||||||
Preferences.SETTINGS[Preferences.MKB_ENABLED].note = '⚠️ ' + note;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[Preferences.MKB_DEFAULT_PRESET_ID]: {
|
[Preferences.MKB_DEFAULT_PRESET_ID]: {
|
||||||
@ -6811,7 +6717,7 @@ class Patcher {
|
|||||||
|
|
||||||
funcStr = funcStr.replace('onServerDisconnectMessage(e){', `onServerDisconnectMessage(e) {
|
funcStr = funcStr.replace('onServerDisconnectMessage(e){', `onServerDisconnectMessage(e) {
|
||||||
const msg = JSON.parse(e);
|
const msg = JSON.parse(e);
|
||||||
if (msg.reason === 'WarningForBeingIdle' && !window.location.pathname.includes('/launch/')) {
|
if (msg.reason === 'WarningForBeingIdle') {
|
||||||
try {
|
try {
|
||||||
this.sendKeepAlive();
|
this.sendKeepAlive();
|
||||||
return;
|
return;
|
||||||
@ -6824,12 +6730,32 @@ class Patcher {
|
|||||||
|
|
||||||
// Enable Remote Play feature
|
// Enable Remote Play feature
|
||||||
remotePlayConnectMode: function(funcStr) {
|
remotePlayConnectMode: function(funcStr) {
|
||||||
const text = 'connectMode:"cloud-connect"';
|
const text = 'connectMode:"cloud-connect",';
|
||||||
if (!funcStr.includes(text)) {
|
if (!funcStr.includes(text)) {
|
||||||
return false;
|
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)||''`);
|
const newCode = `
|
||||||
|
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, newCode);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remote Play MKB support
|
||||||
|
remotePlayMkb: function(funcStr) {
|
||||||
|
const text = 'handleRemotePlayTitleInputConfig(e){';
|
||||||
|
if (!funcStr.includes(text)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newCode = `
|
||||||
|
const supportMkb = window.REMOTE_PLAY_NATIVE_MKB_TITLES.includes(e.titleId);
|
||||||
|
this.gameStream.session.updateInputConfigurationAsync({ enableMouseAndKeyboard: supportMkb });
|
||||||
|
`;
|
||||||
|
|
||||||
|
return funcStr.replace(text, text + newCode);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Disable trackEvent() function
|
// Disable trackEvent() function
|
||||||
@ -6912,13 +6838,11 @@ if (window.BX_VIBRATION_INTENSITY && window.BX_VIBRATION_INTENSITY < 1) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Enable native Mouse and Keyboard support
|
// Enable native Mouse and Keyboard support
|
||||||
if (ENABLE_NATIVE_MKB_BETA) {
|
newSettings.push('EnableMouseAndKeyboard: true');
|
||||||
newSettings.push('EnableMouseAndKeyboard: true');
|
newSettings.push('ShowMouseKeyboardSetting: true');
|
||||||
newSettings.push('ShowMouseKeyboardSetting: true');
|
|
||||||
|
|
||||||
if (getPref(Preferences.MKB_ABSOLUTE_MOUSE)) {
|
if (getPref(Preferences.MKB_ABSOLUTE_MOUSE)) {
|
||||||
newSettings.push('EnableAbsoluteMouse: true');
|
newSettings.push('EnableAbsoluteMouse: true');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCode = newSettings.join(',');
|
const newCode = newSettings.join(',');
|
||||||
@ -6928,12 +6852,12 @@ if (window.BX_VIBRATION_INTENSITY && window.BX_VIBRATION_INTENSITY < 1) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
mkbIsMouseAndKeyboardTitle: function(funcStr) {
|
mkbIsMouseAndKeyboardTitle: function(funcStr) {
|
||||||
const text = 'isMouseAndKeyboardTitle:()=>yn';
|
const text = 'isMouseAndKeyboardTitle:()=>';
|
||||||
if (!funcStr.includes(text)) {
|
if (!funcStr.includes(text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return funcStr.replace(text, `isMouseAndKeyboardTitle:()=>(function(e) { return e && e.details ? window.NATIVE_MKB_TITLES.includes(e.details.productId) : true; })`);
|
return funcStr.replace(text, text + `(function(e) { return e && e.details ? (window.BX_REMOTE_PLAY_CONFIG ? window.REMOTE_PLAY_NATIVE_MKB_TITLES : window.NATIVE_MKB_TITLES).includes(e.details.productId) : true; }),uwuwu:()=>`);
|
||||||
},
|
},
|
||||||
|
|
||||||
mkbMouseAndKeyboardEnabled: function(funcStr) {
|
mkbMouseAndKeyboardEnabled: function(funcStr) {
|
||||||
@ -6992,16 +6916,6 @@ if (window.BX_VIBRATION_INTENSITY && window.BX_VIBRATION_INTENSITY < 1) {
|
|||||||
funcStr = funcStr.substring(0, bracketIndex) + 'return 0;' + funcStr.substring(bracketIndex);
|
funcStr = funcStr.substring(0, bracketIndex) + 'return 0;' + funcStr.substring(bracketIndex);
|
||||||
return funcStr;
|
return funcStr;
|
||||||
},
|
},
|
||||||
|
|
||||||
exposeTouchLayoutManager: function(funcStr) {
|
|
||||||
const text = 'this._perScopeLayoutsStream=new';
|
|
||||||
if (!funcStr.includes(text)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
funcStr = funcStr.replace(text, 'window.BX_EXPOSED["touch_layout_manager"] = this,' + text);
|
|
||||||
return funcStr;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static #PATCH_ORDERS = [
|
static #PATCH_ORDERS = [
|
||||||
@ -7031,7 +6945,7 @@ if (window.BX_VIBRATION_INTENSITY && window.BX_VIBRATION_INTENSITY < 1) {
|
|||||||
|
|
||||||
[
|
[
|
||||||
'overrideSettings',
|
'overrideSettings',
|
||||||
ENABLE_NATIVE_MKB_BETA && 'mkbIsMouseAndKeyboardTitle',
|
'mkbIsMouseAndKeyboardTitle',
|
||||||
HAS_TOUCH_SUPPORT && 'patchUpdateInputConfigurationAsync',
|
HAS_TOUCH_SUPPORT && 'patchUpdateInputConfigurationAsync',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
@ -7041,13 +6955,14 @@ if (window.BX_VIBRATION_INTENSITY && window.BX_VIBRATION_INTENSITY < 1) {
|
|||||||
getPref(Preferences.REMOTE_PLAY_ENABLED) && ['remotePlayConnectMode'],
|
getPref(Preferences.REMOTE_PLAY_ENABLED) && ['remotePlayConnectMode'],
|
||||||
|
|
||||||
['playVibration'],
|
['playVibration'],
|
||||||
getPref(Preferences.STREAM_TOUCH_CONTROLLER) === 'all' && ['exposeTouchLayoutManager'],
|
|
||||||
|
|
||||||
ENABLE_XCLOUD_LOGGER && ['enableConsoleLogging'],
|
ENABLE_XCLOUD_LOGGER && ['enableConsoleLogging'],
|
||||||
|
|
||||||
|
getPref(Preferences.REMOTE_PLAY_ENABLED) && ['remotePlayMkb'],
|
||||||
|
|
||||||
[
|
[
|
||||||
'disableGamepadDisconnectedScreen',
|
'disableGamepadDisconnectedScreen',
|
||||||
ENABLE_NATIVE_MKB_BETA && 'mkbMouseAndKeyboardEnabled',
|
'mkbMouseAndKeyboardEnabled',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -8718,6 +8633,8 @@ function interceptHttpRequests() {
|
|||||||
const PREF_STREAM_TOUCH_CONTROLLER = getPref(Preferences.STREAM_TOUCH_CONTROLLER);
|
const PREF_STREAM_TOUCH_CONTROLLER = getPref(Preferences.STREAM_TOUCH_CONTROLLER);
|
||||||
const PREF_AUDIO_MIC_ON_PLAYING = getPref(Preferences.AUDIO_MIC_ON_PLAYING);
|
const PREF_AUDIO_MIC_ON_PLAYING = getPref(Preferences.AUDIO_MIC_ON_PLAYING);
|
||||||
|
|
||||||
|
const orgFetch = window.fetch;
|
||||||
|
|
||||||
const consoleAddrs = {};
|
const consoleAddrs = {};
|
||||||
|
|
||||||
const patchIceCandidates = function(...arg) {
|
const patchIceCandidates = function(...arg) {
|
||||||
@ -8726,7 +8643,7 @@ function interceptHttpRequests() {
|
|||||||
const url = (typeof request === 'string') ? request : request.url;
|
const url = (typeof request === 'string') ? request : request.url;
|
||||||
|
|
||||||
if (url && url.endsWith('/ice') && url.includes('/sessions/') && request.method === 'GET') {
|
if (url && url.endsWith('/ice') && url.includes('/sessions/') && request.method === 'GET') {
|
||||||
const promise = NATIVE_FETCH(...arg);
|
const promise = orgFetch(...arg);
|
||||||
|
|
||||||
return promise.then(response => {
|
return promise.then(response => {
|
||||||
return response.clone().text().then(text => {
|
return response.clone().text().then(text => {
|
||||||
@ -8801,7 +8718,7 @@ function interceptHttpRequests() {
|
|||||||
|
|
||||||
// Get console IP
|
// Get console IP
|
||||||
if (url.includes('/configuration')) {
|
if (url.includes('/configuration')) {
|
||||||
const promise = NATIVE_FETCH(...arg);
|
const promise = orgFetch(...arg);
|
||||||
|
|
||||||
return promise.then(response => {
|
return promise.then(response => {
|
||||||
return response.clone().json().then(obj => {
|
return response.clone().json().then(obj => {
|
||||||
@ -8824,7 +8741,7 @@ function interceptHttpRequests() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return patchIceCandidates(...arg) || NATIVE_FETCH(...arg);
|
return patchIceCandidates(...arg) || orgFetch(...arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_REMOTE_PLAYING && url.includes('/login/user')) {
|
if (IS_REMOTE_PLAYING && url.includes('/login/user')) {
|
||||||
@ -8848,7 +8765,7 @@ function interceptHttpRequests() {
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NATIVE_FETCH(...arg);
|
return orgFetch(...arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_REMOTE_PLAYING && url.includes('/titles')) {
|
if (IS_REMOTE_PLAYING && url.includes('/titles')) {
|
||||||
@ -8868,7 +8785,7 @@ function interceptHttpRequests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
arg[0] = request;
|
arg[0] = request;
|
||||||
return NATIVE_FETCH(...arg);
|
return orgFetch(...arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ICE server candidates
|
// ICE server candidates
|
||||||
@ -8879,7 +8796,7 @@ function interceptHttpRequests() {
|
|||||||
|
|
||||||
// Server list
|
// Server list
|
||||||
if (!url.includes('xhome.') && url.endsWith('/v2/login/user')) {
|
if (!url.includes('xhome.') && url.endsWith('/v2/login/user')) {
|
||||||
const promise = NATIVE_FETCH(...arg);
|
const promise = orgFetch(...arg);
|
||||||
|
|
||||||
return promise.then(response => {
|
return promise.then(response => {
|
||||||
return response.clone().json().then(obj => {
|
return response.clone().json().then(obj => {
|
||||||
@ -8954,12 +8871,12 @@ function interceptHttpRequests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
arg[0] = newRequest;
|
arg[0] = newRequest;
|
||||||
return NATIVE_FETCH(...arg);
|
return orgFetch(...arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get wait time
|
// Get wait time
|
||||||
if (PREF_UI_LOADING_SCREEN_WAIT_TIME && url.includes('xboxlive.com') && url.includes('/waittime/')) {
|
if (PREF_UI_LOADING_SCREEN_WAIT_TIME && url.includes('xboxlive.com') && url.includes('/waittime/')) {
|
||||||
const promise = NATIVE_FETCH(...arg);
|
const promise = orgFetch(...arg);
|
||||||
return promise.then(response => {
|
return promise.then(response => {
|
||||||
return response.clone().json().then(json => {
|
return response.clone().json().then(json => {
|
||||||
if (json.estimatedAllocationTimeInSeconds > 0) {
|
if (json.estimatedAllocationTimeInSeconds > 0) {
|
||||||
@ -8975,7 +8892,7 @@ function interceptHttpRequests() {
|
|||||||
if (url.endsWith('/configuration') && url.includes('/sessions/cloud/') && request.method === 'GET') {
|
if (url.endsWith('/configuration') && url.includes('/sessions/cloud/') && request.method === 'GET') {
|
||||||
PREF_UI_LOADING_SCREEN_GAME_ART && LoadingScreen.hide();
|
PREF_UI_LOADING_SCREEN_GAME_ART && LoadingScreen.hide();
|
||||||
|
|
||||||
const promise = NATIVE_FETCH(...arg);
|
const promise = orgFetch(...arg);
|
||||||
|
|
||||||
// Touch controller for all games
|
// Touch controller for all games
|
||||||
if (PREF_STREAM_TOUCH_CONTROLLER === 'all') {
|
if (PREF_STREAM_TOUCH_CONTROLLER === 'all') {
|
||||||
@ -9002,9 +8919,7 @@ function interceptHttpRequests() {
|
|||||||
|
|
||||||
overrides.inputConfiguration = overrides.inputConfiguration || {};
|
overrides.inputConfiguration = overrides.inputConfiguration || {};
|
||||||
overrides.inputConfiguration.enableVibration = true;
|
overrides.inputConfiguration.enableVibration = true;
|
||||||
if (ENABLE_NATIVE_MKB_BETA) {
|
overrides.inputConfiguration.enableMouseAndKeyboard = true;
|
||||||
overrides.inputConfiguration.enableMouseAndKeyboard = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable touch controller
|
// Enable touch controller
|
||||||
if (TouchController.isEnabled()) {
|
if (TouchController.isEnabled()) {
|
||||||
@ -9030,7 +8945,7 @@ function interceptHttpRequests() {
|
|||||||
|
|
||||||
// catalog.gamepass
|
// catalog.gamepass
|
||||||
if (url.startsWith('https://catalog.gamepass.com') && url.includes('/products')) {
|
if (url.startsWith('https://catalog.gamepass.com') && url.includes('/products')) {
|
||||||
const promise = NATIVE_FETCH(...arg);
|
const promise = orgFetch(...arg);
|
||||||
return promise.then(response => {
|
return promise.then(response => {
|
||||||
return response.clone().json().then(json => {
|
return response.clone().json().then(json => {
|
||||||
for (let productId in json.Products) {
|
for (let productId in json.Products) {
|
||||||
@ -9043,7 +8958,7 @@ function interceptHttpRequests() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PREF_STREAM_TOUCH_CONTROLLER === 'all' && (url.endsWith('/titles') || url.endsWith('/mru'))) {
|
if (PREF_STREAM_TOUCH_CONTROLLER === 'all' && (url.endsWith('/titles') || url.endsWith('/mru'))) {
|
||||||
const promise = NATIVE_FETCH(...arg);
|
const promise = orgFetch(...arg);
|
||||||
return promise.then(response => {
|
return promise.then(response => {
|
||||||
return response.clone().json().then(json => {
|
return response.clone().json().then(json => {
|
||||||
for (let game of json.results) {
|
for (let game of json.results) {
|
||||||
@ -9066,7 +8981,7 @@ function interceptHttpRequests() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return NATIVE_FETCH(...arg);
|
return orgFetch(...arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9182,7 +9097,6 @@ function injectSettingsButton($parent) {
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
[__('touch-controller')]: {
|
[__('touch-controller')]: {
|
||||||
_note: !HAS_TOUCH_SUPPORT ? '⚠️ ' + __('device-unsupported-touch') : null,
|
|
||||||
[Preferences.STREAM_TOUCH_CONTROLLER]: __('tc-availability'),
|
[Preferences.STREAM_TOUCH_CONTROLLER]: __('tc-availability'),
|
||||||
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_STANDARD]: __('tc-standard-layout-style'),
|
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_STANDARD]: __('tc-standard-layout-style'),
|
||||||
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_CUSTOM]: __('tc-custom-layout-style'),
|
[Preferences.STREAM_TOUCH_CONTROLLER_STYLE_CUSTOM]: __('tc-custom-layout-style'),
|
||||||
@ -9228,8 +9142,14 @@ function injectSettingsButton($parent) {
|
|||||||
|
|
||||||
const setting = Preferences.SETTINGS[settingId];
|
const setting = Preferences.SETTINGS[settingId];
|
||||||
|
|
||||||
const settingLabel = SETTINGS_UI[groupLabel][settingId];
|
let settingLabel;
|
||||||
const settingNote = setting.note;
|
let settingNote;
|
||||||
|
|
||||||
|
if (Array.isArray(SETTINGS_UI[groupLabel][settingId])) {
|
||||||
|
[settingLabel, settingNote] = SETTINGS_UI[groupLabel][settingId];
|
||||||
|
} else {
|
||||||
|
settingLabel = SETTINGS_UI[groupLabel][settingId];
|
||||||
|
}
|
||||||
|
|
||||||
let $control, $inpCustomUserAgent;
|
let $control, $inpCustomUserAgent;
|
||||||
let labelAttrs = {};
|
let labelAttrs = {};
|
||||||
@ -9300,8 +9220,11 @@ function injectSettingsButton($parent) {
|
|||||||
// Disable unsupported settings
|
// Disable unsupported settings
|
||||||
if (setting.unsupported) {
|
if (setting.unsupported) {
|
||||||
$control.disabled = true;
|
$control.disabled = true;
|
||||||
|
$control.title = setting.unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$control.disabled && ($control.style.cursor = 'help');
|
||||||
|
|
||||||
const $label = CE('label', labelAttrs, settingLabel);
|
const $label = CE('label', labelAttrs, settingLabel);
|
||||||
if (settingNote) {
|
if (settingNote) {
|
||||||
$label.appendChild(CE('b', {}, settingNote));
|
$label.appendChild(CE('b', {}, settingNote));
|
||||||
@ -10207,11 +10130,10 @@ function onStreamStarted($video) {
|
|||||||
GAME_PRODUCT_ID = matches.groups.product_id;
|
GAME_PRODUCT_ID = matches.groups.product_id;
|
||||||
} else {
|
} else {
|
||||||
GAME_TITLE_ID = 'remote-play';
|
GAME_TITLE_ID = 'remote-play';
|
||||||
GAME_PRODUCT_ID = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable MKB
|
// Enable MKB
|
||||||
if (getPref(Preferences.MKB_ENABLED) && (!ENABLE_NATIVE_MKB_BETA || !window.NATIVE_MKB_TITLES.includes(GAME_PRODUCT_ID))) {
|
if (getPref(Preferences.MKB_ENABLED) && (!window.NATIVE_MKB_TITLES.includes(GAME_PRODUCT_ID))) {
|
||||||
console.log('Emulate MKB');
|
console.log('Emulate MKB');
|
||||||
MkbHandler.INSTANCE.init();
|
MkbHandler.INSTANCE.init();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user