diff --git a/dist/better-xcloud.user.js b/dist/better-xcloud.user.js
index f2529e7..5667033 100644
--- a/dist/better-xcloud.user.js
+++ b/dist/better-xcloud.user.js
@@ -84,42 +84,6 @@ try {
} catch (e) {
}
-// src/assets/svg/controller.svg
-var controller_default = "\n";
-
-// src/assets/svg/copy.svg
-var copy_default = "\n";
-
-// src/assets/svg/cursor-text.svg
-var cursor_text_default = "\n";
-
-// src/assets/svg/display.svg
-var display_default = "\n";
-
-// src/assets/svg/mouse-settings.svg
-var mouse_settings_default = "\n";
-
-// src/assets/svg/mouse.svg
-var mouse_default = "\n";
-
-// src/assets/svg/new.svg
-var new_default = "\n";
-
-// src/assets/svg/question.svg
-var question_default = "\n";
-
-// src/assets/svg/remote-play.svg
-var remote_play_default = "\n";
-
-// src/assets/svg/stream-settings.svg
-var stream_settings_default = "\n";
-
-// src/assets/svg/stream-stats.svg
-var stream_stats_default = "\n";
-
-// src/assets/svg/trash.svg
-var trash_default = "\n";
-
// src/utils/html.ts
var createElement = function(elmName, props = {}, ..._) {
let $elm;
@@ -153,21 +117,6 @@ var createElement = function(elmName, props = {}, ..._) {
};
var CE = createElement;
var svgParser = (svg) => new DOMParser().parseFromString(svg, "image/svg+xml").documentElement;
-var Icon;
-(function(Icon2) {
- Icon2[Icon2["STREAM_SETTINGS"] = stream_settings_default] = "STREAM_SETTINGS";
- Icon2[Icon2["STREAM_STATS"] = stream_stats_default] = "STREAM_STATS";
- Icon2[Icon2["CONTROLLER"] = controller_default] = "CONTROLLER";
- Icon2[Icon2["DISPLAY"] = display_default] = "DISPLAY";
- Icon2[Icon2["MOUSE"] = mouse_default] = "MOUSE";
- Icon2[Icon2["MOUSE_SETTINGS"] = mouse_settings_default] = "MOUSE_SETTINGS";
- Icon2[Icon2["NEW"] = new_default] = "NEW";
- Icon2[Icon2["COPY"] = copy_default] = "COPY";
- Icon2[Icon2["TRASH"] = trash_default] = "TRASH";
- Icon2[Icon2["CURSOR_TEXT"] = cursor_text_default] = "CURSOR_TEXT";
- Icon2[Icon2["QUESTION"] = question_default] = "QUESTION";
- Icon2[Icon2["REMOTE_PLAY"] = remote_play_default] = "REMOTE_PLAY";
-})(Icon || (Icon = {}));
var createSvgIcon = (icon) => {
return svgParser(icon.toString());
};
@@ -5014,6 +4963,58 @@ class LoadingScreen {
}
}
+// src/assets/svg/controller.svg
+var controller_default = "\n";
+
+// src/assets/svg/copy.svg
+var copy_default = "\n";
+
+// src/assets/svg/cursor-text.svg
+var cursor_text_default = "\n";
+
+// src/assets/svg/display.svg
+var display_default = "\n";
+
+// src/assets/svg/mouse-settings.svg
+var mouse_settings_default = "\n";
+
+// src/assets/svg/mouse.svg
+var mouse_default = "\n";
+
+// src/assets/svg/new.svg
+var new_default = "\n";
+
+// src/assets/svg/question.svg
+var question_default = "\n";
+
+// src/assets/svg/remote-play.svg
+var remote_play_default = "\n";
+
+// src/assets/svg/stream-settings.svg
+var stream_settings_default = "\n";
+
+// src/assets/svg/stream-stats.svg
+var stream_stats_default = "\n";
+
+// src/assets/svg/trash.svg
+var trash_default = "\n";
+
+// src/utils/bx-icon.ts
+var BxIcon = {
+ STREAM_SETTINGS: stream_settings_default,
+ STREAM_STATS: stream_stats_default,
+ CONTROLLER: controller_default,
+ DISPLAY: display_default,
+ MOUSE: mouse_default,
+ MOUSE_SETTINGS: mouse_settings_default,
+ NEW: new_default,
+ COPY: copy_default,
+ TRASH: trash_default,
+ CURSOR_TEXT: cursor_text_default,
+ QUESTION: question_default,
+ REMOTE_PLAY: remote_play_default
+};
+
// src/utils/toast.ts
class Toast {
static #$wrapper;
@@ -5180,16 +5181,18 @@ class Dialog {
onClose,
helpUrl
} = options;
- this.$overlay = document.querySelector(".bx-dialog-overlay");
- if (!this.$overlay) {
+ const $overlay = document.querySelector(".bx-dialog-overlay");
+ if (!$overlay) {
this.$overlay = CE("div", { class: "bx-dialog-overlay bx-gone" });
this.$overlay.addEventListener("contextmenu", (e) => e.preventDefault());
document.documentElement.appendChild(this.$overlay);
+ } else {
+ this.$overlay = $overlay;
}
let $close;
this.onClose = onClose;
this.$dialog = CE("div", { class: `bx-dialog ${className || ""} bx-gone` }, this.$title = CE("h2", {}, CE("b", {}, title), helpUrl && createButton({
- icon: Icon.QUESTION,
+ icon: BxIcon.QUESTION,
style: ButtonStyle.GHOST,
title: t("help"),
url: helpUrl
@@ -5511,7 +5514,7 @@ function injectStreamMenuButtons() {
return;
}
if (!$btnStreamSettings) {
- $btnStreamSettings = cloneStreamHudButton($orgButton, t("menu-stream-settings"), Icon.STREAM_SETTINGS);
+ $btnStreamSettings = cloneStreamHudButton($orgButton, t("menu-stream-settings"), BxIcon.STREAM_SETTINGS);
$btnStreamSettings.addEventListener("click", (e) => {
hideGripHandle();
e.preventDefault();
@@ -5522,7 +5525,7 @@ function injectStreamMenuButtons() {
});
}
if (!$btnStreamStats) {
- $btnStreamStats = cloneStreamHudButton($orgButton, t("menu-stream-stats"), Icon.STREAM_STATS);
+ $btnStreamStats = cloneStreamHudButton($orgButton, t("menu-stream-stats"), BxIcon.STREAM_STATS);
$btnStreamStats.addEventListener("click", (e) => {
hideGripHandle();
e.preventDefault();
@@ -5885,7 +5888,7 @@ class MkbHandler {
document.addEventListener("pointerlockchange", this.#onPointerLockChange);
document.addEventListener("pointerlockerror", this.#onPointerLockError);
this.#$message = CE("div", { class: "bx-mkb-pointer-lock-msg bx-gone" }, createButton({
- icon: Icon.MOUSE_SETTINGS,
+ icon: BxIcon.MOUSE_SETTINGS,
style: ButtonStyle.PRIMARY,
onClick: (e) => {
e.preventDefault();
@@ -6318,7 +6321,7 @@ class MkbRemapper {
};
const $header = CE("div", { class: "bx-mkb-preset-tools" }, this.#$.presetsSelect, createButton({
title: t("rename"),
- icon: Icon.CURSOR_TEXT,
+ icon: BxIcon.CURSOR_TEXT,
onClick: (e) => {
const preset = this.#getCurrentPreset();
let newName = promptNewName(preset.name);
@@ -6329,7 +6332,7 @@ class MkbRemapper {
LocalDb.INSTANCE.updatePreset(preset).then((id2) => this.#refresh());
}
}), createButton({
- icon: Icon.NEW,
+ icon: BxIcon.NEW,
title: t("new"),
onClick: (e) => {
let newName = promptNewName("");
@@ -6342,7 +6345,7 @@ class MkbRemapper {
});
}
}), createButton({
- icon: Icon.COPY,
+ icon: BxIcon.COPY,
title: t("copy"),
onClick: (e) => {
const preset = this.#getCurrentPreset();
@@ -6356,7 +6359,7 @@ class MkbRemapper {
});
}
}), createButton({
- icon: Icon.TRASH,
+ icon: BxIcon.TRASH,
style: ButtonStyle.DANGER,
title: t("delete"),
onClick: (e) => {
@@ -6904,7 +6907,7 @@ var setupQuickSettingsBar = function() {
const isSafari = UserAgent.isSafari();
const SETTINGS_UI = [
getPref(PrefKey.MKB_ENABLED) && {
- icon: Icon.MOUSE,
+ icon: BxIcon.MOUSE,
group: "mkb",
items: [
{
@@ -6916,7 +6919,7 @@ var setupQuickSettingsBar = function() {
]
},
{
- icon: Icon.DISPLAY,
+ icon: BxIcon.DISPLAY,
group: "stream",
items: [
{
@@ -6972,7 +6975,7 @@ var setupQuickSettingsBar = function() {
]
},
{
- icon: Icon.CONTROLLER,
+ icon: BxIcon.CONTROLLER,
group: "controller",
items: [
{
@@ -7045,7 +7048,7 @@ var setupQuickSettingsBar = function() {
]
},
{
- icon: Icon.STREAM_STATS,
+ icon: BxIcon.STREAM_STATS,
group: "stats",
items: [
{
@@ -7127,7 +7130,7 @@ var setupQuickSettingsBar = function() {
continue;
}
$group.appendChild(CE("h2", {}, CE("span", {}, settingGroup.label), settingGroup.help_url && createButton({
- icon: Icon.QUESTION,
+ icon: BxIcon.QUESTION,
style: ButtonStyle.GHOST,
url: settingGroup.help_url,
title: t("help")
@@ -7353,7 +7356,7 @@ class RemotePlay {
$fragment.appendChild($child);
}
$fragment.appendChild(createButton({
- icon: Icon.QUESTION,
+ icon: BxIcon.QUESTION,
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE,
url: "https://better-xcloud.github.io/remote-play",
label: t("help")
@@ -7468,8 +7471,8 @@ class RemotePlay {
return;
}
const $header = document.querySelector("#gamepass-root header");
- const group2 = $header.firstElementChild.getAttribute("data-group");
- RemotePlay.#$content.setAttribute("data-group", group2);
+ const group = $header.firstElementChild.getAttribute("data-group");
+ RemotePlay.#$content.setAttribute("data-group", group);
RemotePlay.#$content.classList.add("bx-remote-play-popup");
RemotePlay.#$content.classList.remove("bx-gone");
$header.insertAdjacentElement("afterend", RemotePlay.#$content);
@@ -7583,14 +7586,15 @@ function interceptHttpRequests() {
BLOCKED_URLS = BLOCKED_URLS.concat([
"https://arc.msn.com",
"https://browser.events.data.microsoft.com",
- "https://dc.services.visualstudio.com"
+ "https://dc.services.visualstudio.com",
+ "https://2c06dea3f26c40c69b8456d319791fd0@o427368.ingest.sentry.io"
]);
}
if (getPref(PrefKey.BLOCK_SOCIAL_FEATURES)) {
BLOCKED_URLS = BLOCKED_URLS.concat([
"https://peoplehub.xboxlive.com/users/me/people/social",
"https://peoplehub.xboxlive.com/users/me/people/recommendations",
- "https://notificationinbox.xboxlive.com"
+ "https://xblmessaging.xboxlive.com/network/xbox/users/me/inbox"
]);
}
const xhrPrototype = XMLHttpRequest.prototype;
@@ -7611,7 +7615,7 @@ function interceptHttpRequests() {
}
return nativeXhrSend.apply(this, arguments);
};
- window.fetch = async (request, init) => {
+ window.BX_FETCH = window.fetch = async (request, init) => {
let url = typeof request === "string" ? request : request.url;
for (let blocked of BLOCKED_URLS) {
if (!url.startsWith(blocked)) {
@@ -9160,7 +9164,7 @@ function setupSettingsUi() {
class: "bx-settings-title",
href: SCRIPT_HOME,
target: "_blank"
- }, "Better xCloud " + SCRIPT_VERSION), createButton({ icon: Icon.QUESTION, label: t("help"), url: "https://better-xcloud.github.io/features/" })));
+ }, "Better xCloud " + SCRIPT_VERSION), createButton({ icon: BxIcon.QUESTION, label: t("help"), url: "https://better-xcloud.github.io/features/" })));
$updateAvailable = CE("a", {
class: "bx-settings-update bx-gone",
href: "https://github.com/redphx/better-xcloud/releases",
@@ -9414,7 +9418,7 @@ var injectSettingsButton = function($parent) {
if (getPref(PrefKey.REMOTE_PLAY_ENABLED)) {
const $remotePlayBtn = createButton({
classes: ["bx-header-remote-play-button"],
- icon: Icon.REMOTE_PLAY,
+ icon: BxIcon.REMOTE_PLAY,
title: t("remote-play"),
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE,
onClick: (e) => {
@@ -9488,8 +9492,18 @@ function disablePwa() {
});
}
}
+function hashCode(str2) {
+ let hash = 0;
+ for (let i = 0, len = str2.length;i < len; i++) {
+ const chr = str2.charCodeAt(i);
+ hash = (hash << 5) - hash + chr;
+ hash |= 0;
+ }
+ return hash;
+}
// src/modules/patcher.ts
+var ENDING_CHUNKS_PATCH_NAME = "loadingEndingChunks";
var LOG_TAG4 = "Patcher";
var PATCHES = {
disableAiTrack(str2) {
@@ -9570,12 +9584,17 @@ var PATCHES = {
}
return str2.replace(text, `connectMode:window.BX_REMOTE_PLAY_CONFIG?"xhome-connect":"cloud-connect",remotePlayServerId:(window.BX_REMOTE_PLAY_CONFIG&&window.BX_REMOTE_PLAY_CONFIG.serverId)||''`);
},
- remotePlayGuideWorkaround(str2) {
- const text = "nexusButtonHandler:this.featureGates.EnableClientGuideInStream";
+ remotePlayDisableAchievementToast(str2) {
+ const text = ".AchievementUnlock:{";
if (!str2.includes(text)) {
return false;
}
- return str2.replace(text, `nexusButtonHandler: !window.BX_REMOTE_PLAY_CONFIG && this.featureGates.EnableClientGuideInStream`);
+ const newCode = `
+if (!!window.BX_REMOTE_PLAY_CONFIG) {
+ return;
+}
+`;
+ return str2.replace(text, text + newCode);
},
disableTrackEvent(str2) {
const text = "this.trackEvent=";
@@ -9668,13 +9687,12 @@ if (window.BX_VIBRATION_INTENSITY && window.BX_VIBRATION_INTENSITY < 1) {
return str2;
},
loadingEndingChunks(str2) {
- const text = 'Symbol("ChatSocketPlugin")';
+ const text = '"FamilySagaManager"';
if (!str2.includes(text)) {
return false;
}
BxLogger.info(LOG_TAG4, "Remaining patches:", PATCH_ORDERS);
PATCH_ORDERS = PATCH_ORDERS.concat(PLAYING_PATCH_ORDERS);
- Patcher.cleanupPatches();
return str2;
},
disableStreamGate(str2) {
@@ -9736,11 +9754,33 @@ if (match) {
if (!str2.includes(text)) {
return false;
}
- const newCode = `
-const titleInfo = window.BX_EXPOSED.getTitleInfo();
-if (!titleInfo.details.hasTouchSupport && !titleInfo.details.hasFakeTouchSupport) {
+ let remotePlayCode = "";
+ if (getPref(PrefKey.STREAM_TOUCH_CONTROLLER) !== "off" && getPref(PrefKey.STREAM_TOUCH_CONTROLLER_AUTO_OFF)) {
+ remotePlayCode = `
+const gamepads = window.navigator.getGamepads();
+let gamepadFound = false;
+
+for (let gamepad of gamepads) {
+ if (gamepad && gamepad.connected) {
+ gamepadFound = true;
+ break;
+ }
+}
+
+if (gamepadFound) {
return;
}
+`;
+ }
+ const newCode = `
+if (!!window.BX_REMOTE_PLAY_CONFIG) {
+ ${remotePlayCode}
+} else {
+ const titleInfo = window.BX_EXPOSED.getTitleInfo();
+ if (titleInfo && !titleInfo.details.hasTouchSupport && !titleInfo.details.hasFakeTouchSupport) {
+ return;
+ }
+}
`;
str2 = str2.replace(text, newCode + text);
return str2;
@@ -9813,50 +9853,47 @@ BxLogger.info('patchRemotePlayMkb', ${configsVar});
}
};
var PATCH_ORDERS = [
- getPref(PrefKey.BLOCK_TRACKING) && [
+ "disableStreamGate",
+ "overrideSettings",
+ "broadcastPollingMode",
+ getPref(PrefKey.UI_LAYOUT) === "tv" && "tvLayout",
+ getPref(PrefKey.LOCAL_CO_OP_ENABLED) && "supportLocalCoOp",
+ getPref(PrefKey.GAME_FORTNITE_FORCE_CONSOLE) && "forceFortniteConsole",
+ ...getPref(PrefKey.BLOCK_TRACKING) ? [
"disableAiTrack",
- "disableTelemetry"
- ],
- ["disableStreamGate"],
- ["broadcastPollingMode"],
- getPref(PrefKey.UI_LAYOUT) === "tv" && ["tvLayout"],
- BX_FLAGS.EnableXcloudLogging && [
- "enableConsoleLogging",
- "enableXcloudLogger"
- ],
- getPref(PrefKey.LOCAL_CO_OP_ENABLED) && ["supportLocalCoOp"],
- getPref(PrefKey.BLOCK_TRACKING) && [
+ "disableTelemetry",
"blockWebRtcStatsCollector",
- "disableIndexDbLogging"
- ],
- getPref(PrefKey.BLOCK_TRACKING) && [
+ "disableIndexDbLogging",
"disableTelemetryProvider",
"disableTrackEvent"
- ],
- getPref(PrefKey.REMOTE_PLAY_ENABLED) && ["remotePlayKeepAlive"],
- getPref(PrefKey.REMOTE_PLAY_ENABLED) && ["remotePlayDirectConnectUrl"],
- [
- "overrideSettings"
- ],
- getPref(PrefKey.REMOTE_PLAY_ENABLED) && STATES.hasTouchSupport && ["patchUpdateInputConfigurationAsync"],
- getPref(PrefKey.GAME_FORTNITE_FORCE_CONSOLE) && ["forceFortniteConsole"]
-];
+ ] : [],
+ ...getPref(PrefKey.REMOTE_PLAY_ENABLED) ? [
+ "remotePlayKeepAlive",
+ "remotePlayDirectConnectUrl",
+ "remotePlayDisableAchievementToast",
+ STATES.hasTouchSupport && "patchUpdateInputConfigurationAsync"
+ ] : [],
+ ...BX_FLAGS.EnableXcloudLogging ? [
+ "enableConsoleLogging",
+ "enableXcloudLogger"
+ ] : []
+].filter((item2) => !!item2);
var PLAYING_PATCH_ORDERS = [
- ["patchXcloudTitleInfo"],
- getPref(PrefKey.REMOTE_PLAY_ENABLED) && ["patchRemotePlayMkb"],
- getPref(PrefKey.REMOTE_PLAY_ENABLED) && ["remotePlayConnectMode"],
- getPref(PrefKey.REMOTE_PLAY_ENABLED) && ["remotePlayGuideWorkaround"],
- ["patchStreamHud"],
- ["playVibration"],
- STATES.hasTouchSupport && getPref(PrefKey.STREAM_TOUCH_CONTROLLER) === "all" && ["exposeTouchLayoutManager"],
- STATES.hasTouchSupport && (getPref(PrefKey.STREAM_TOUCH_CONTROLLER) === "off" || getPref(PrefKey.STREAM_TOUCH_CONTROLLER_AUTO_OFF)) && ["disableTakRenderer"],
- BX_FLAGS.EnableXcloudLogging && ["enableConsoleLogging"],
- getPref(PrefKey.BLOCK_TRACKING) && ["blockGamepadStatsCollector"],
- [
- "disableGamepadDisconnectedScreen"
- ],
- getPref(PrefKey.STREAM_COMBINE_SOURCES) && ["streamCombineSources"]
-];
+ "patchXcloudTitleInfo",
+ "disableGamepadDisconnectedScreen",
+ "patchStreamHud",
+ "playVibration",
+ STATES.hasTouchSupport && getPref(PrefKey.STREAM_TOUCH_CONTROLLER) === "all" && "exposeTouchLayoutManager",
+ STATES.hasTouchSupport && (getPref(PrefKey.STREAM_TOUCH_CONTROLLER) === "off" || getPref(PrefKey.STREAM_TOUCH_CONTROLLER_AUTO_OFF)) && "disableTakRenderer",
+ BX_FLAGS.EnableXcloudLogging && "enableConsoleLogging",
+ getPref(PrefKey.BLOCK_TRACKING) && "blockGamepadStatsCollector",
+ getPref(PrefKey.STREAM_COMBINE_SOURCES) && "streamCombineSources",
+ ...getPref(PrefKey.REMOTE_PLAY_ENABLED) ? [
+ "patchRemotePlayMkb",
+ "remotePlayConnectMode"
+ ] : []
+].filter((item2) => !!item2);
+var ALL_PATCHES = [...PATCH_ORDERS, ...PLAYING_PATCH_ORDERS];
class Patcher {
static #patchFunctionBind() {
@@ -9877,10 +9914,6 @@ class Patcher {
}
const orgFunc = this;
const newFunc = (a, item2) => {
- if (Patcher.length() === 0) {
- orgFunc(a, item2);
- return;
- }
Patcher.patch(item2);
orgFunc(a, item2);
};
@@ -9891,76 +9924,130 @@ class Patcher {
return PATCH_ORDERS.length;
}
static patch(item) {
+ let patchesToCheck;
let appliedPatches;
+ const caches = {};
for (let id in item[1]) {
- if (PATCH_ORDERS.length <= 0) {
- return;
+ const cachedPatches = PatcherCache.getPatches(id);
+ if (cachedPatches) {
+ patchesToCheck = cachedPatches;
+ patchesToCheck.push(...PATCH_ORDERS);
+ } else {
+ patchesToCheck = PATCH_ORDERS;
+ }
+ if (!patchesToCheck.length) {
+ continue;
}
appliedPatches = [];
const func = item[1][id];
let str = func.toString();
- for (let groupIndex = 0;groupIndex < PATCH_ORDERS.length; groupIndex++) {
- const group = PATCH_ORDERS[groupIndex];
+ for (let groupIndex = 0;groupIndex < patchesToCheck.length; groupIndex++) {
+ const patchName = patchesToCheck[groupIndex];
let modified = false;
- for (let patchIndex = 0;patchIndex < group.length; patchIndex++) {
- const patchName = group[patchIndex];
- if (appliedPatches.indexOf(patchName) > -1) {
- continue;
- }
- const patchedstr = PATCHES[patchName].call(null, str);
- if (!patchedstr) {
- if (patchIndex === 0) {
- break;
- } else {
- continue;
- }
- }
- modified = true;
- str = patchedstr;
- BxLogger.info(LOG_TAG4, `Applied "${patchName}" patch`);
- appliedPatches.push(patchName);
- group.splice(patchIndex, 1);
- patchIndex--;
+ if (appliedPatches.indexOf(patchName) > -1) {
+ continue;
}
+ const patchedStr = PATCHES[patchName].call(null, str);
+ if (!patchedStr) {
+ continue;
+ }
+ modified = true;
+ str = patchedStr;
+ BxLogger.info(LOG_TAG4, `Applied "${patchName}" patch`);
+ appliedPatches.push(patchName);
+ patchesToCheck.splice(groupIndex, 1);
+ groupIndex--;
+ PATCH_ORDERS = PATCH_ORDERS.filter((item2) => item2 != patchName);
if (modified) {
item[1][id] = eval(str);
}
- if (!group.length) {
- PATCH_ORDERS.splice(groupIndex, 1);
- groupIndex--;
- }
}
+ if (appliedPatches.length) {
+ caches[id] = appliedPatches;
+ }
+ }
+ if (Object.keys(caches).length) {
+ PatcherCache.saveToCache(caches);
}
}
- static cleanupPatches() {
- for (let groupIndex2 = PATCH_ORDERS.length - 1;groupIndex2 >= 0; groupIndex2--) {
- const group2 = PATCH_ORDERS[groupIndex2];
- if (group2 === false) {
- PATCH_ORDERS.splice(groupIndex2, 1);
- continue;
- }
- for (let patchIndex = group2.length - 1;patchIndex >= 0; patchIndex--) {
- const patchName = group2[patchIndex];
- if (!PATCHES[patchName]) {
- group2.splice(patchIndex, 1);
- }
- }
- if (!group2.length) {
- PATCH_ORDERS.splice(groupIndex2, 1);
- }
- }
- }
- static initialize() {
- if (window.location.pathname.includes("/play/")) {
- PATCH_ORDERS = PATCH_ORDERS.concat(PLAYING_PATCH_ORDERS);
- } else {
- PATCH_ORDERS.push(["loadingEndingChunks"]);
- }
- Patcher.cleanupPatches();
+ static init() {
Patcher.#patchFunctionBind();
}
}
+class PatcherCache {
+ static #KEY_CACHE = "better_xcloud_patches_cache";
+ static #KEY_SIGNATURE = "better_xcloud_patches_cache_signature";
+ static #CACHE;
+ static #getSignature() {
+ const scriptVersion = SCRIPT_VERSION;
+ const webVersion = document.querySelector("meta[name=gamepass-app-version]")?.content;
+ const patches = JSON.stringify(ALL_PATCHES);
+ const sig = hashCode(scriptVersion + webVersion + patches);
+ return sig;
+ }
+ static checkSignature() {
+ const storedSig = window.localStorage.getItem(PatcherCache.#KEY_SIGNATURE) || 0;
+ const currentSig = PatcherCache.#getSignature();
+ if (currentSig !== parseInt(storedSig)) {
+ BxLogger.warning(LOG_TAG4, "Signature changed");
+ window.localStorage.setItem(PatcherCache.#KEY_CACHE, "{}");
+ window.localStorage.setItem(PatcherCache.#KEY_SIGNATURE, currentSig.toString());
+ } else {
+ BxLogger.info(LOG_TAG4, "Signature unchanged");
+ }
+ }
+ static #cleanupPatches(patches) {
+ return patches.filter((item2) => {
+ for (const id2 in PatcherCache.#CACHE) {
+ const cached = PatcherCache.#CACHE[id2];
+ if (cached.includes(item2)) {
+ return false;
+ }
+ }
+ return true;
+ });
+ }
+ static getPatches(id2) {
+ return PatcherCache.#CACHE[id2];
+ }
+ static saveToCache(subCache) {
+ for (const id2 in subCache) {
+ const patchNames = subCache[id2];
+ let data = PatcherCache.#CACHE[id2];
+ if (!data) {
+ PatcherCache.#CACHE[id2] = patchNames;
+ } else {
+ for (const patchName2 of patchNames) {
+ if (!data.includes(patchName2)) {
+ data.push(patchName2);
+ }
+ }
+ }
+ }
+ window.localStorage.setItem(PatcherCache.#KEY_CACHE, JSON.stringify(PatcherCache.#CACHE));
+ }
+ static init() {
+ PatcherCache.#CACHE = JSON.parse(window.localStorage.getItem(PatcherCache.#KEY_CACHE) || "{}");
+ BxLogger.info(LOG_TAG4, PatcherCache.#CACHE);
+ if (window.location.pathname.includes("/play/")) {
+ PATCH_ORDERS.push(...PLAYING_PATCH_ORDERS);
+ } else {
+ PATCH_ORDERS.push(ENDING_CHUNKS_PATCH_NAME);
+ }
+ PATCH_ORDERS = PatcherCache.#cleanupPatches(PATCH_ORDERS);
+ PLAYING_PATCH_ORDERS = PatcherCache.#cleanupPatches(PLAYING_PATCH_ORDERS);
+ BxLogger.info(LOG_TAG4, PATCH_ORDERS.slice(0));
+ BxLogger.info(LOG_TAG4, PLAYING_PATCH_ORDERS.slice(0));
+ }
+}
+document.addEventListener("readystatechange", (e) => {
+ if (document.readyState === "interactive") {
+ PatcherCache.checkSignature();
+ }
+});
+PatcherCache.init();
+
// src/utils/history.ts
function patchHistoryMethod(type) {
const orig = window.history[type];
@@ -10143,7 +10230,7 @@ var main = function() {
StreamBadges.setupEvents();
StreamStats.setupEvents();
MkbHandler.setupEvents();
- Patcher.initialize();
+ Patcher.init();
disablePwa();
window.addEventListener("gamepadconnected", (e) => showGamepadToast(e.gamepad));
window.addEventListener("gamepaddisconnected", (e) => showGamepadToast(e.gamepad));