mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-07-06 14:21:43 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
b733d55e9e | |||
317ac9017b | |||
b8c62a1f4d | |||
7332528f72 | |||
d063500aae | |||
29ff1bc09c | |||
8998daf14c | |||
8bdad8b319 | |||
5dd3ebdea1 |
2
dist/better-xcloud.meta.js
vendored
2
dist/better-xcloud.meta.js
vendored
@ -1,5 +1,5 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud
|
// @name Better xCloud
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 6.4.5
|
// @version 6.4.7
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
51
dist/better-xcloud.pretty.user.js
vendored
51
dist/better-xcloud.pretty.user.js
vendored
@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud
|
// @name Better xCloud
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 6.4.5
|
// @version 6.4.7
|
||||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||||
// @author redphx
|
// @author redphx
|
||||||
// @license MIT
|
// @license MIT
|
||||||
@ -192,7 +192,7 @@ class UserAgent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var SCRIPT_VERSION = "6.4.5", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
var SCRIPT_VERSION = "6.4.7", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
||||||
UserAgent.init();
|
UserAgent.init();
|
||||||
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
||||||
supportedRegion: !0,
|
supportedRegion: !0,
|
||||||
@ -382,6 +382,7 @@ class GhPagesUtils {
|
|||||||
var SUPPORTED_LANGUAGES = {
|
var SUPPORTED_LANGUAGES = {
|
||||||
"en-US": "English (US)",
|
"en-US": "English (US)",
|
||||||
"ca-CA": "Català",
|
"ca-CA": "Català",
|
||||||
|
"cs-CZ": "čeština",
|
||||||
"da-DK": "dansk",
|
"da-DK": "dansk",
|
||||||
"de-DE": "Deutsch",
|
"de-DE": "Deutsch",
|
||||||
"en-ID": "Bahasa Indonesia",
|
"en-ID": "Bahasa Indonesia",
|
||||||
@ -571,6 +572,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
"new-version-available": [
|
"new-version-available": [
|
||||||
e => `Version ${e.version} available`,
|
e => `Version ${e.version} available`,
|
||||||
e => `Versió ${e.version} disponible`,
|
e => `Versió ${e.version} disponible`,
|
||||||
|
e => `Verze ${e.version} dostupná`,
|
||||||
,
|
,
|
||||||
e => `Version ${e.version} verfügbar`,
|
e => `Version ${e.version} verfügbar`,
|
||||||
e => `Versi ${e.version} tersedia`,
|
e => `Versi ${e.version} tersedia`,
|
||||||
@ -616,6 +618,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
"press-key-to-toggle-mkb": [
|
"press-key-to-toggle-mkb": [
|
||||||
e => `Press ${e.key} to toggle this feature`,
|
e => `Press ${e.key} to toggle this feature`,
|
||||||
e => `Premeu ${e.key} per alternar aquesta funció`,
|
e => `Premeu ${e.key} per alternar aquesta funció`,
|
||||||
|
e => `Zmáčknete ${e.key} pro přepnutí této funkce`,
|
||||||
e => `Tryk på ${e.key} for at slå denne funktion til`,
|
e => `Tryk på ${e.key} for at slå denne funktion til`,
|
||||||
e => `${e.key}: Funktion an-/ausschalten`,
|
e => `${e.key}: Funktion an-/ausschalten`,
|
||||||
e => `Tekan ${e.key} untuk mengaktifkan fitur ini`,
|
e => `Tekan ${e.key} untuk mengaktifkan fitur ini`,
|
||||||
@ -641,6 +644,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
e => `Recommended settings for ${e.device}`,
|
e => `Recommended settings for ${e.device}`,
|
||||||
e => `Configuració recomanada per a ${e.device}`,
|
e => `Configuració recomanada per a ${e.device}`,
|
||||||
,
|
,
|
||||||
|
,
|
||||||
e => `Empfohlene Einstellungen für ${e.device}`,
|
e => `Empfohlene Einstellungen für ${e.device}`,
|
||||||
e => `Rekomendasi pengaturan untuk ${e.device}`,
|
e => `Rekomendasi pengaturan untuk ${e.device}`,
|
||||||
e => `Ajustes recomendados para ${e.device}`,
|
e => `Ajustes recomendados para ${e.device}`,
|
||||||
@ -751,6 +755,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
"touch-control-layout-by": [
|
"touch-control-layout-by": [
|
||||||
e => `Touch control layout by ${e.name}`,
|
e => `Touch control layout by ${e.name}`,
|
||||||
e => `Format del control tàctil per ${e.name}`,
|
e => `Format del control tàctil per ${e.name}`,
|
||||||
|
e => `Rozložení dotykového ovládání ${e.name}`,
|
||||||
e => `Touch-kontrol layout af ${e.name}`,
|
e => `Touch-kontrol layout af ${e.name}`,
|
||||||
e => `Touch-Steuerungslayout von ${e.name}`,
|
e => `Touch-Steuerungslayout von ${e.name}`,
|
||||||
e => `Tata letak Sentuhan layar oleh ${e.name}`,
|
e => `Tata letak Sentuhan layar oleh ${e.name}`,
|
||||||
@ -2688,11 +2693,12 @@ function setPref(prefKey, value, origin) {
|
|||||||
}
|
}
|
||||||
function checkForUpdate() {
|
function checkForUpdate() {
|
||||||
if (SCRIPT_VERSION.includes("beta")) return;
|
if (SCRIPT_VERSION.includes("beta")) return;
|
||||||
|
fetch("https://api.github.com/repos/redphx/better-xcloud/releases/latest").then((response) => response.json()).then((json) => {
|
||||||
|
setGlobalPref("version.latest", json.tag_name.substring(1), "direct"), setGlobalPref("version.current", SCRIPT_VERSION, "direct");
|
||||||
|
});
|
||||||
let CHECK_INTERVAL_SECONDS = 7200, currentVersion = getGlobalPref("version.current"), lastCheck = getGlobalPref("version.lastCheck"), now = Math.round(+new Date / 1000);
|
let CHECK_INTERVAL_SECONDS = 7200, currentVersion = getGlobalPref("version.current"), lastCheck = getGlobalPref("version.lastCheck"), now = Math.round(+new Date / 1000);
|
||||||
if (currentVersion === SCRIPT_VERSION && now - lastCheck < CHECK_INTERVAL_SECONDS) return;
|
if (currentVersion === SCRIPT_VERSION && now - lastCheck < CHECK_INTERVAL_SECONDS) return;
|
||||||
setGlobalPref("version.lastCheck", now, "direct"), fetch("https://api.github.com/repos/redphx/better-xcloud/releases/latest").then((response) => response.json()).then((json) => {
|
setGlobalPref("version.lastCheck", now, "direct"), Translations.updateTranslations(currentVersion === SCRIPT_VERSION);
|
||||||
setGlobalPref("version.latest", json.tag_name.substring(1), "direct"), setGlobalPref("version.current", SCRIPT_VERSION, "direct");
|
|
||||||
}), Translations.updateTranslations(currentVersion === SCRIPT_VERSION);
|
|
||||||
}
|
}
|
||||||
function disablePwa() {
|
function disablePwa() {
|
||||||
if (!(window.navigator.orgUserAgent || window.navigator.userAgent || "").toLowerCase()) return;
|
if (!(window.navigator.orgUserAgent || window.navigator.userAgent || "").toLowerCase()) return;
|
||||||
@ -5017,6 +5023,9 @@ class TouchController {
|
|||||||
static getCustomList() {
|
static getCustomList() {
|
||||||
return TouchController.#customList;
|
return TouchController.#customList;
|
||||||
}
|
}
|
||||||
|
static hasCustomControl(productId) {
|
||||||
|
return TouchController.#customList?.includes(productId);
|
||||||
|
}
|
||||||
static setup() {
|
static setup() {
|
||||||
window.testTouchLayout = (layout) => {
|
window.testTouchLayout = (layout) => {
|
||||||
let { touchLayoutManager } = window.BX_EXPOSED;
|
let { touchLayoutManager } = window.BX_EXPOSED;
|
||||||
@ -5180,7 +5189,7 @@ remotePlayServerId: (window.BX_REMOTE_PLAY_CONFIG && window.BX_REMOTE_PLAY_CONFI
|
|||||||
remotePlayDisableAchievementToast(str) {
|
remotePlayDisableAchievementToast(str) {
|
||||||
let text = ".AchievementUnlock:{";
|
let text = ".AchievementUnlock:{";
|
||||||
if (!str.includes(text)) return !1;
|
if (!str.includes(text)) return !1;
|
||||||
let newCode = "if (!!window.BX_REMOTE_PLAY_CONFIG) return;";
|
let newCode = "if (window.location.pathname.includes('/consoles/launch/')) return;";
|
||||||
return str.replace(text, text + newCode);
|
return str.replace(text, text + newCode);
|
||||||
},
|
},
|
||||||
blockWebRtcStatsCollector(str) {
|
blockWebRtcStatsCollector(str) {
|
||||||
@ -5648,6 +5657,17 @@ ${subsVar} = subs;
|
|||||||
let index = str.indexOf("GuideAchievementDetail.useParams()");
|
let index = str.indexOf("GuideAchievementDetail.useParams()");
|
||||||
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const", index, 200)), index < 0) return !1;
|
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const", index, 200)), index < 0) return !1;
|
||||||
return PatcherUtils.injectUseEffect(str, index, "Script", "ui.guideAchievementDetail.rendered");
|
return PatcherUtils.injectUseEffect(str, index, "Script", "ui.guideAchievementDetail.rendered");
|
||||||
|
},
|
||||||
|
patchCustomInputIcon(str) {
|
||||||
|
let index = str.indexOf('.MouseAndKeyboard="MouseAndKeyboard"');
|
||||||
|
if (index < 0) return !1;
|
||||||
|
let productIdMatch = /const (\w+)=(\w+)=>{/.exec(str.substring(index, index + 200));
|
||||||
|
if (!productIdMatch) return !1;
|
||||||
|
str = str.replace(productIdMatch[0], productIdMatch[0] + `const productId = ${productIdMatch[2]};`);
|
||||||
|
let match = /(\w+)&&(\w+\.push\(\w+\.Touch\))/.exec(str);
|
||||||
|
if (!match) return !1;
|
||||||
|
if (str = str.replace(match[0], `(${match[1]} || window.BX_EXPOSED.hasCustomTouchControl(productId)) && ${match[2]}`), match = /(\w+)&&(\w+\.push\(\w+\.MouseAndKeyboard\))/.exec(str), match) str = str.replace(match[0], `(${match[1]} || window.BX_EXPOSED.hasCustomNativeMkb(productId)) && ${match[2]}`);
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
}, PATCH_ORDERS = PatcherUtils.filterPatches([
|
}, PATCH_ORDERS = PatcherUtils.filterPatches([
|
||||||
...AppInterface && getGlobalPref("nativeMkb.mode") === "on" ? [
|
...AppInterface && getGlobalPref("nativeMkb.mode") === "on" ? [
|
||||||
@ -5677,6 +5697,7 @@ ${subsVar} = subs;
|
|||||||
"guideAchievementsDefaultLocked",
|
"guideAchievementsDefaultLocked",
|
||||||
"injectHeaderUseEffect",
|
"injectHeaderUseEffect",
|
||||||
"homePageBeforeLoad",
|
"homePageBeforeLoad",
|
||||||
|
"patchCustomInputIcon",
|
||||||
"gameCardCustomIcons",
|
"gameCardCustomIcons",
|
||||||
"productDetailPageBeforeLoad",
|
"productDetailPageBeforeLoad",
|
||||||
"enableTvRoutes",
|
"enableTvRoutes",
|
||||||
@ -5731,7 +5752,6 @@ ${subsVar} = subs;
|
|||||||
getGlobalPref("touchController.opacity.default") !== 100 && "patchTouchControlDefaultOpacity",
|
getGlobalPref("touchController.opacity.default") !== 100 && "patchTouchControlDefaultOpacity",
|
||||||
getGlobalPref("touchController.mode") !== "off" && (getGlobalPref("mkb.enabled") || getGlobalPref("nativeMkb.mode") === "on") && "patchBabylonRendererClass"
|
getGlobalPref("touchController.mode") !== "off" && (getGlobalPref("mkb.enabled") || getGlobalPref("nativeMkb.mode") === "on") && "patchBabylonRendererClass"
|
||||||
] : [],
|
] : [],
|
||||||
BX_FLAGS.EnableXcloudLogging && "enableConsoleLogging",
|
|
||||||
"patchPollGamepads",
|
"patchPollGamepads",
|
||||||
getGlobalPref("stream.video.combineAudio") && "streamCombineSources",
|
getGlobalPref("stream.video.combineAudio") && "streamCombineSources",
|
||||||
...getGlobalPref("xhome.enabled") ? [
|
...getGlobalPref("xhome.enabled") ? [
|
||||||
@ -5821,11 +5841,12 @@ class PatcherCache {
|
|||||||
PATCH_ORDERS = this.cleanupPatches(PATCH_ORDERS), STREAM_PAGE_PATCH_ORDERS = this.cleanupPatches(STREAM_PAGE_PATCH_ORDERS), PRODUCT_DETAIL_PAGE_PATCH_ORDERS = this.cleanupPatches(PRODUCT_DETAIL_PAGE_PATCH_ORDERS), BxLogger.info(LOG_TAG2, "PATCH_ORDERS", PATCH_ORDERS.slice(0));
|
PATCH_ORDERS = this.cleanupPatches(PATCH_ORDERS), STREAM_PAGE_PATCH_ORDERS = this.cleanupPatches(STREAM_PAGE_PATCH_ORDERS), PRODUCT_DETAIL_PAGE_PATCH_ORDERS = this.cleanupPatches(PRODUCT_DETAIL_PAGE_PATCH_ORDERS), BxLogger.info(LOG_TAG2, "PATCH_ORDERS", PATCH_ORDERS.slice(0));
|
||||||
}
|
}
|
||||||
getSignature() {
|
getSignature() {
|
||||||
let scriptVersion = SCRIPT_VERSION, patches = JSON.stringify(ALL_PATCHES), webVersion = "", $link = document.querySelector('link[data-chunk="client"][href*="/client."]');
|
let scriptVersion = SCRIPT_VERSION, patches = JSON.stringify(ALL_PATCHES), webVersion = "", $link = document.querySelector('link[data-chunk="client"][as="script"][href*="/client."]');
|
||||||
if ($link) {
|
if ($link) {
|
||||||
let match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
let match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
||||||
match && (webVersion = match[1]);
|
match && (webVersion = match[1]);
|
||||||
} else webVersion = document.querySelector("meta[name=gamepass-app-version]")?.content ?? "";
|
}
|
||||||
|
if (!webVersion) webVersion = document.querySelector("meta[name=gamepass-app-version]")?.content ?? "";
|
||||||
return hashCode(scriptVersion + webVersion + patches);
|
return hashCode(scriptVersion + webVersion + patches);
|
||||||
}
|
}
|
||||||
clear() {
|
clear() {
|
||||||
@ -8275,6 +8296,10 @@ var BxExposed = {
|
|||||||
createReactLocalCoOpIcon: (attrs) => {
|
createReactLocalCoOpIcon: (attrs) => {
|
||||||
let reactCE = window.BX_EXPOSED.reactCreateElement;
|
let reactCE = window.BX_EXPOSED.reactCreateElement;
|
||||||
return reactCE("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 32 32", "fill-rule": "evenodd", "stroke-linecap": "round", "stroke-linejoin": "round", ...attrs }, reactCE("g", null, reactCE("path", { d: "M24.272 11.165h-3.294l-3.14 3.564c-.391.391-.922.611-1.476.611a2.1 2.1 0 0 1-2.087-2.088 2.09 2.09 0 0 1 .031-.362l1.22-6.274a3.89 3.89 0 0 1 3.81-3.206h6.57c1.834 0 3.439 1.573 3.833 3.295l1.205 6.185a2.09 2.09 0 0 1 .031.362 2.1 2.1 0 0 1-2.087 2.088c-.554 0-1.085-.22-1.476-.611l-3.14-3.564", fill: "none", stroke: "#fff", "stroke-width": "2" }), reactCE("circle", { cx: "22.625", cy: "5.874", r: ".879" }), reactCE("path", { d: "M11.022 24.415H7.728l-3.14 3.564c-.391.391-.922.611-1.476.611a2.1 2.1 0 0 1-2.087-2.088 2.09 2.09 0 0 1 .031-.362l1.22-6.274a3.89 3.89 0 0 1 3.81-3.206h6.57c1.834 0 3.439 1.573 3.833 3.295l1.205 6.185a2.09 2.09 0 0 1 .031.362 2.1 2.1 0 0 1-2.087 2.088c-.554 0-1.085-.22-1.476-.611l-3.14-3.564", fill: "none", stroke: "#fff", "stroke-width": "2" }), reactCE("circle", { cx: "9.375", cy: "19.124", r: ".879" })));
|
return reactCE("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 32 32", "fill-rule": "evenodd", "stroke-linecap": "round", "stroke-linejoin": "round", ...attrs }, reactCE("g", null, reactCE("path", { d: "M24.272 11.165h-3.294l-3.14 3.564c-.391.391-.922.611-1.476.611a2.1 2.1 0 0 1-2.087-2.088 2.09 2.09 0 0 1 .031-.362l1.22-6.274a3.89 3.89 0 0 1 3.81-3.206h6.57c1.834 0 3.439 1.573 3.833 3.295l1.205 6.185a2.09 2.09 0 0 1 .031.362 2.1 2.1 0 0 1-2.087 2.088c-.554 0-1.085-.22-1.476-.611l-3.14-3.564", fill: "none", stroke: "#fff", "stroke-width": "2" }), reactCE("circle", { cx: "22.625", cy: "5.874", r: ".879" }), reactCE("path", { d: "M11.022 24.415H7.728l-3.14 3.564c-.391.391-.922.611-1.476.611a2.1 2.1 0 0 1-2.087-2.088 2.09 2.09 0 0 1 .031-.362l1.22-6.274a3.89 3.89 0 0 1 3.81-3.206h6.57c1.834 0 3.439 1.573 3.833 3.295l1.205 6.185a2.09 2.09 0 0 1 .031.362 2.1 2.1 0 0 1-2.087 2.088c-.554 0-1.085-.22-1.476-.611l-3.14-3.564", fill: "none", stroke: "#fff", "stroke-width": "2" }), reactCE("circle", { cx: "9.375", cy: "19.124", r: ".879" })));
|
||||||
|
},
|
||||||
|
hasCustomTouchControl: TouchController.hasCustomControl,
|
||||||
|
hasCustomNativeMkb: (productId) => {
|
||||||
|
return BX_FLAGS.ForceNativeMkbTitles?.includes(productId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function localRedirect(path) {
|
function localRedirect(path) {
|
||||||
@ -8490,6 +8515,9 @@ class RemotePlayManager {
|
|||||||
Authorization: `Bearer ${this.XHOME_TOKEN}`
|
Authorization: `Bearer ${this.XHOME_TOKEN}`
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this.regions.sort((a, b) => {
|
||||||
|
return a.isDefault ? -1 : 0;
|
||||||
|
});
|
||||||
for (let region of this.regions)
|
for (let region of this.regions)
|
||||||
try {
|
try {
|
||||||
let request = new Request(`${region.baseUri}/v6/servers/home?mr=50`, options), json = await (await fetch(request)).json();
|
let request = new Request(`${region.baseUri}/v6/servers/home?mr=50`, options), json = await (await fetch(request)).json();
|
||||||
@ -9071,9 +9099,12 @@ function updateIceCandidates(candidates, options) {
|
|||||||
let pattern = new RegExp(/a=candidate:(?<foundation>\d+) (?<component>\d+) UDP (?<priority>\d+) (?<ip>[^\s]+) (?<port>\d+) (?<the_rest>.*)/), lst = [];
|
let pattern = new RegExp(/a=candidate:(?<foundation>\d+) (?<component>\d+) UDP (?<priority>\d+) (?<ip>[^\s]+) (?<port>\d+) (?<the_rest>.*)/), lst = [];
|
||||||
for (let item2 of candidates) {
|
for (let item2 of candidates) {
|
||||||
if (item2.candidate == "a=end-of-candidates") continue;
|
if (item2.candidate == "a=end-of-candidates") continue;
|
||||||
let groups = pattern.exec(item2.candidate).groups;
|
let match = pattern.exec(item2.candidate);
|
||||||
|
if (match && match.groups) {
|
||||||
|
let groups = match.groups;
|
||||||
lst.push(groups);
|
lst.push(groups);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (options.preferIpv6Server) lst.sort((a, b) => {
|
if (options.preferIpv6Server) lst.sort((a, b) => {
|
||||||
let firstIp = a.ip, secondIp = b.ip;
|
let firstIp = a.ip, secondIp = b.ip;
|
||||||
return !firstIp.includes(":") && secondIp.includes(":") ? 1 : -1;
|
return !firstIp.includes(":") && secondIp.includes(":") ? 1 : -1;
|
||||||
|
24
dist/better-xcloud.user.js
vendored
24
dist/better-xcloud.user.js
vendored
File diff suppressed because one or more lines are too long
@ -133,7 +133,7 @@ remotePlayServerId: (window.BX_REMOTE_PLAY_CONFIG && window.BX_REMOTE_PLAY_CONFI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCode = `if (!!window.BX_REMOTE_PLAY_CONFIG) return;`;
|
const newCode = `if (window.location.pathname.includes('/consoles/launch/')) return;`;
|
||||||
return str.replace(text, text + newCode);
|
return str.replace(text, text + newCode);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1169,6 +1169,36 @@ ${subsVar} = subs;
|
|||||||
return PatcherUtils.injectUseEffect(str, index, 'Script', 'ui.guideAchievementDetail.rendered');
|
return PatcherUtils.injectUseEffect(str, index, 'Script', 'ui.guideAchievementDetail.rendered');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
patchCustomInputIcon(str: string) {
|
||||||
|
let index = str.indexOf('.MouseAndKeyboard="MouseAndKeyboard"');
|
||||||
|
if (index < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get productId
|
||||||
|
const productIdMatch = /const (\w+)=(\w+)=>{/.exec(str.substring(index, index + 200));
|
||||||
|
if (!productIdMatch) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define productId variable
|
||||||
|
str = str.replace(productIdMatch[0], productIdMatch[0] + `const productId = ${productIdMatch[2]};`);
|
||||||
|
|
||||||
|
let match = /(\w+)&&(\w+\.push\(\w+\.Touch\))/.exec(str);
|
||||||
|
if (!match) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = str.replace(match[0], `(${match[1]} || window.BX_EXPOSED.hasCustomTouchControl(productId)) && ${match[2]}`);
|
||||||
|
|
||||||
|
match = /(\w+)&&(\w+\.push\(\w+\.MouseAndKeyboard\))/.exec(str);
|
||||||
|
if (match) {
|
||||||
|
str = str.replace(match[0], `(${match[1]} || window.BX_EXPOSED.hasCustomNativeMkb(productId)) && ${match[2]}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
patchBasicGameInfo(str: string) {
|
patchBasicGameInfo(str: string) {
|
||||||
let index = str.indexOf('.ChildXboxTitleIds,offerings');
|
let index = str.indexOf('.ChildXboxTitleIds,offerings');
|
||||||
@ -1240,6 +1270,8 @@ let PATCH_ORDERS = PatcherUtils.filterPatches([
|
|||||||
|
|
||||||
'homePageBeforeLoad',
|
'homePageBeforeLoad',
|
||||||
|
|
||||||
|
'patchCustomInputIcon',
|
||||||
|
|
||||||
'gameCardCustomIcons',
|
'gameCardCustomIcons',
|
||||||
// 'gameCardPassTitle',
|
// 'gameCardPassTitle',
|
||||||
|
|
||||||
@ -1329,8 +1361,6 @@ let STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
|
|||||||
(getGlobalPref(GlobalPref.TOUCH_CONTROLLER_MODE) !== TouchControllerMode.OFF && (getGlobalPref(GlobalPref.MKB_ENABLED) || getGlobalPref(GlobalPref.NATIVE_MKB_MODE) === NativeMkbMode.ON)) && 'patchBabylonRendererClass',
|
(getGlobalPref(GlobalPref.TOUCH_CONTROLLER_MODE) !== TouchControllerMode.OFF && (getGlobalPref(GlobalPref.MKB_ENABLED) || getGlobalPref(GlobalPref.NATIVE_MKB_MODE) === NativeMkbMode.ON)) && 'patchBabylonRendererClass',
|
||||||
] : []) as PatchArray,
|
] : []) as PatchArray,
|
||||||
|
|
||||||
BX_FLAGS.EnableXcloudLogging && 'enableConsoleLogging',
|
|
||||||
|
|
||||||
'patchPollGamepads',
|
'patchPollGamepads',
|
||||||
|
|
||||||
getGlobalPref(GlobalPref.STREAM_COMBINE_SOURCES) && 'streamCombineSources',
|
getGlobalPref(GlobalPref.STREAM_COMBINE_SOURCES) && 'streamCombineSources',
|
||||||
@ -1546,11 +1576,13 @@ export class PatcherCache {
|
|||||||
|
|
||||||
// Get client.js's hash
|
// Get client.js's hash
|
||||||
let webVersion = '';
|
let webVersion = '';
|
||||||
const $link = document.querySelector<HTMLLinkElement>('link[data-chunk="client"][href*="/client."]');
|
const $link = document.querySelector<HTMLLinkElement>('link[data-chunk="client"][as="script"][href*="/client."]');
|
||||||
if ($link) {
|
if ($link) {
|
||||||
const match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
const match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
||||||
match && (webVersion = match[1]);
|
match && (webVersion = match[1]);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (!webVersion) {
|
||||||
// Get version from <meta>
|
// Get version from <meta>
|
||||||
// Sometimes this value is missing
|
// Sometimes this value is missing
|
||||||
webVersion = (document.querySelector<HTMLMetaElement>('meta[name=gamepass-app-version]'))?.content ?? '';
|
webVersion = (document.querySelector<HTMLMetaElement>('meta[name=gamepass-app-version]'))?.content ?? '';
|
||||||
|
@ -156,6 +156,11 @@ export class RemotePlayManager {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Start with "isDefault" = true first
|
||||||
|
this.regions.sort((a: RemotePlayRegion, b: RemotePlayRegion) => {
|
||||||
|
return a.isDefault ? -1 : 0;
|
||||||
|
})
|
||||||
|
|
||||||
// Test servers one by one
|
// Test servers one by one
|
||||||
for (const region of this.regions) {
|
for (const region of this.regions) {
|
||||||
try {
|
try {
|
||||||
|
@ -267,6 +267,10 @@ export class TouchController {
|
|||||||
return TouchController.#customList;
|
return TouchController.#customList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hasCustomControl(productId: string): boolean {
|
||||||
|
return TouchController.#customList?.includes(productId);
|
||||||
|
}
|
||||||
|
|
||||||
static setup() {
|
static setup() {
|
||||||
// Function for testing touch control
|
// Function for testing touch control
|
||||||
window.testTouchLayout = (layout: any) => {
|
window.testTouchLayout = (layout: any) => {
|
||||||
|
@ -261,4 +261,9 @@ export const BxExposed = {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} : () => {},
|
} : () => {},
|
||||||
|
|
||||||
|
hasCustomTouchControl: TouchController.hasCustomControl,
|
||||||
|
hasCustomNativeMkb: (productId: string) => {
|
||||||
|
return BX_FLAGS.ForceNativeMkbTitles?.includes(productId);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -49,9 +49,12 @@ function updateIceCandidates(candidates: any, options: { preferIpv6Server: boole
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups: { [index: string]: string | number } = pattern.exec(item.candidate)!.groups!;
|
const match = pattern.exec(item.candidate);
|
||||||
|
if (match && match.groups) {
|
||||||
|
const groups: { [index: string]: string | number } = match.groups;
|
||||||
lst.push(groups);
|
lst.push(groups);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options.preferIpv6Server) {
|
if (options.preferIpv6Server) {
|
||||||
lst.sort((a, b) => {
|
lst.sort((a, b) => {
|
||||||
|
@ -7,6 +7,7 @@ export const SUPPORTED_LANGUAGES = {
|
|||||||
'en-US': 'English (US)',
|
'en-US': 'English (US)',
|
||||||
|
|
||||||
'ca-CA': 'Català',
|
'ca-CA': 'Català',
|
||||||
|
'cs-CZ': 'čeština',
|
||||||
'da-DK': 'dansk',
|
'da-DK': 'dansk',
|
||||||
'de-DE': 'Deutsch',
|
'de-DE': 'Deutsch',
|
||||||
'en-ID': 'Bahasa Indonesia',
|
'en-ID': 'Bahasa Indonesia',
|
||||||
@ -198,6 +199,7 @@ const Texts = {
|
|||||||
"new-version-available": [
|
"new-version-available": [
|
||||||
(e: any) => `Version ${e.version} available`,
|
(e: any) => `Version ${e.version} available`,
|
||||||
(e: any) => `Versió ${e.version} disponible`,
|
(e: any) => `Versió ${e.version} disponible`,
|
||||||
|
(e: any) => `Verze ${e.version} dostupná`,
|
||||||
,
|
,
|
||||||
(e: any) => `Version ${e.version} verfügbar`,
|
(e: any) => `Version ${e.version} verfügbar`,
|
||||||
(e: any) => `Versi ${e.version} tersedia`,
|
(e: any) => `Versi ${e.version} tersedia`,
|
||||||
@ -243,6 +245,7 @@ const Texts = {
|
|||||||
"press-key-to-toggle-mkb": [
|
"press-key-to-toggle-mkb": [
|
||||||
(e: any) => `Press ${e.key} to toggle this feature`,
|
(e: any) => `Press ${e.key} to toggle this feature`,
|
||||||
(e: any) => `Premeu ${e.key} per alternar aquesta funció`,
|
(e: any) => `Premeu ${e.key} per alternar aquesta funció`,
|
||||||
|
(e: any) => `Zmáčknete ${e.key} pro přepnutí této funkce`,
|
||||||
(e: any) => `Tryk på ${e.key} for at slå denne funktion til`,
|
(e: any) => `Tryk på ${e.key} for at slå denne funktion til`,
|
||||||
(e: any) => `${e.key}: Funktion an-/ausschalten`,
|
(e: any) => `${e.key}: Funktion an-/ausschalten`,
|
||||||
(e: any) => `Tekan ${e.key} untuk mengaktifkan fitur ini`,
|
(e: any) => `Tekan ${e.key} untuk mengaktifkan fitur ini`,
|
||||||
@ -268,6 +271,7 @@ const Texts = {
|
|||||||
(e: any) => `Recommended settings for ${e.device}`,
|
(e: any) => `Recommended settings for ${e.device}`,
|
||||||
(e: any) => `Configuració recomanada per a ${e.device}`,
|
(e: any) => `Configuració recomanada per a ${e.device}`,
|
||||||
,
|
,
|
||||||
|
,
|
||||||
(e: any) => `Empfohlene Einstellungen für ${e.device}`,
|
(e: any) => `Empfohlene Einstellungen für ${e.device}`,
|
||||||
(e: any) => `Rekomendasi pengaturan untuk ${e.device}`,
|
(e: any) => `Rekomendasi pengaturan untuk ${e.device}`,
|
||||||
(e: any) => `Ajustes recomendados para ${e.device}`,
|
(e: any) => `Ajustes recomendados para ${e.device}`,
|
||||||
@ -378,6 +382,7 @@ const Texts = {
|
|||||||
"touch-control-layout-by": [
|
"touch-control-layout-by": [
|
||||||
(e: any) => `Touch control layout by ${e.name}`,
|
(e: any) => `Touch control layout by ${e.name}`,
|
||||||
(e: any) => `Format del control tàctil per ${e.name}`,
|
(e: any) => `Format del control tàctil per ${e.name}`,
|
||||||
|
(e: any) => `Rozložení dotykového ovládání ${e.name}`,
|
||||||
(e: any) => `Touch-kontrol layout af ${e.name}`,
|
(e: any) => `Touch-kontrol layout af ${e.name}`,
|
||||||
(e: any) => `Touch-Steuerungslayout von ${e.name}`,
|
(e: any) => `Touch-Steuerungslayout von ${e.name}`,
|
||||||
(e: any) => `Tata letak Sentuhan layar oleh ${e.name}`,
|
(e: any) => `Tata letak Sentuhan layar oleh ${e.name}`,
|
||||||
|
@ -16,6 +16,15 @@ export function checkForUpdate() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always check for new version
|
||||||
|
fetch('https://api.github.com/repos/redphx/better-xcloud/releases/latest')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => {
|
||||||
|
// Store the latest version
|
||||||
|
setGlobalPref(GlobalPref.VERSION_LATEST, json.tag_name.substring(1), 'direct');
|
||||||
|
setGlobalPref(GlobalPref.VERSION_CURRENT, SCRIPT_VERSION, 'direct');
|
||||||
|
});
|
||||||
|
|
||||||
const CHECK_INTERVAL_SECONDS = 2 * 3600; // check every 2 hours
|
const CHECK_INTERVAL_SECONDS = 2 * 3600; // check every 2 hours
|
||||||
|
|
||||||
const currentVersion = getGlobalPref(GlobalPref.VERSION_CURRENT);
|
const currentVersion = getGlobalPref(GlobalPref.VERSION_CURRENT);
|
||||||
@ -28,13 +37,6 @@ export function checkForUpdate() {
|
|||||||
|
|
||||||
// Start checking
|
// Start checking
|
||||||
setGlobalPref(GlobalPref.VERSION_LAST_CHECK, now, 'direct');
|
setGlobalPref(GlobalPref.VERSION_LAST_CHECK, now, 'direct');
|
||||||
fetch('https://api.github.com/repos/redphx/better-xcloud/releases/latest')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(json => {
|
|
||||||
// Store the latest version
|
|
||||||
setGlobalPref(GlobalPref.VERSION_LATEST, json.tag_name.substring(1), 'direct');
|
|
||||||
setGlobalPref(GlobalPref.VERSION_CURRENT, SCRIPT_VERSION, 'direct');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update translations
|
// Update translations
|
||||||
Translations.updateTranslations(currentVersion === SCRIPT_VERSION);
|
Translations.updateTranslations(currentVersion === SCRIPT_VERSION);
|
||||||
|
Reference in New Issue
Block a user