diff --git a/dist/better-xcloud.pretty.user.js b/dist/better-xcloud.pretty.user.js index ffdc4b8..bb0e6ea 100644 --- a/dist/better-xcloud.pretty.user.js +++ b/dist/better-xcloud.pretty.user.js @@ -5160,7 +5160,7 @@ class PatcherUtils { let newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.${group}.emit('${eventName}', {}), [])${separator}`; return str = PatcherUtils.insertAt(str, index, newCode), str; } - static parseParams(str, index, maxRange) { + static findAndParseParams(str, index, maxRange) { let substr = str.substring(index, index + maxRange), startIndex = substr.indexOf("({"); if (startIndex < 0) return !1; startIndex += 1; @@ -5168,7 +5168,15 @@ class PatcherUtils { if (endIndex < 0) return !1; endIndex += 1; try { - let pairs = [...substr.substring(startIndex, endIndex).matchAll(/(\w+)\s*:\s*([a-zA-Z_$][\w$]*)/g)], result = {}; + let input = substr.substring(startIndex, endIndex); + return PatcherUtils.parseObjectVariables(input); + } catch { + return null; + } + } + static parseObjectVariables(input) { + try { + let pairs = [...input.matchAll(/(\w+)\s*:\s*([a-zA-Z_$][\w$]*)/g)], result = {}; for (let [_, key, value] of pairs) result[key] = value; return result; @@ -5362,7 +5370,7 @@ if (titleInfo && !titleInfo.details.hasTouchSupport && !titleInfo.details.hasFak let index = str.indexOf("({onCollapse:"); if (index < 0) return !1; try { - if (!PatcherUtils.parseParams(str, index, 1000)) return !1; + if (!PatcherUtils.findAndParseParams(str, index, 1000)) return !1; let canShowTakHUDVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "canShowTakHUD", index, 500, !0) + 1), guideUIVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "guideUI", index, 500, !0) + 1), onShowStreamMenuVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "onShowStreamMenu", index, 500, !0) + 1), offsetVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "offset", index, 500, !0) + 1), newCode = renderString(stream_hud_default, { guideUI: guideUIVar, onShowStreamMenu: onShowStreamMenuVar, @@ -5524,7 +5532,7 @@ true` + text; ignoreSiglSections(str) { let index = str.indexOf("SiglRow-module__heroCard___"); if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, "const[", index, 300)), index < 0) return !1; - let params = PatcherUtils.parseParams(str, index - 500, 500); + let params = PatcherUtils.findAndParseParams(str, index - 500, 500); if (!params || !params.id) return !1; let PREF_HIDE_SECTIONS = getGlobalPref("ui.hideSections"), siglIds = [], sections = { "native-mkb": "8fa264dd-124f-4af3-97e8-596fcdf4b486", @@ -5643,8 +5651,10 @@ ${subsVar} = subs; if (returnIndex < 0) return !1; let productIdIndex = PatcherUtils.lastIndexOf(str, ",productId:", initialIndex, 300); if (productIdIndex < 0) return !1; - let productIdVar = PatcherUtils.getVariableNameAfter(str, productIdIndex + 11), supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "supportedInputIcons:", initialIndex, 100, !0)); - if (!productIdVar || !supportedInputIconsVar) return !1; + let params = PatcherUtils.findAndParseParams(str, productIdIndex - 200, 400); + if (!params || !params.productId) return !1; + let productIdVar = params.productId, supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "supportedInputIcons:", initialIndex, 100, !0)); + if (!supportedInputIconsVar) return !1; let newCode = renderString(game_card_icons_default, { productId: productIdVar, supportedInputIcons: supportedInputIconsVar diff --git a/dist/better-xcloud.user.js b/dist/better-xcloud.user.js index 4753c98..2809aec 100755 --- a/dist/better-xcloud.user.js +++ b/dist/better-xcloud.user.js @@ -156,7 +156,7 @@ var remote_play_keep_alive_default = `try{if(JSON.parse(e).reason==="WarningForB var vibration_adjust_default = `if(e?.gamepad?.connected){let gamepadSettings=window.BX_STREAM_SETTINGS.controllers[e.gamepad.id];if(gamepadSettings?.customization){let intensity=gamepadSettings.customization.vibrationIntensity;if(intensity<=0){e.repeat=0;return}else if(intensity<1)e.leftMotorPercent*=intensity,e.rightMotorPercent*=intensity,e.leftTriggerMotorPercent*=intensity,e.rightTriggerMotorPercent*=intensity}}`; var stream_hud_default = `window.BX_EXPOSED.showStreamMenu=$onShowStreamMenu$;$guideUI$=null;window.BX_EXPOSED.reactUseEffect(()=>{window.BxEventBus.Stream.emit("ui.streamHud.rendered",{expanded:$offset$.x===0})});`; var create_portal_default = `var $dom=arguments[1];if($dom&&$dom instanceof HTMLElement&&$dom.id==="gamepass-dialog-root"){let showing=!1,$dialog=$dom.firstElementChild?.firstElementChild;if($dialog)showing=!$dialog.className.includes("pageChangeExit");window.BxEventBus.Script.emit(showing?"dialog.shown":"dialog.dismissed",{})}`; -class PatcherUtils {static indexOf(txt, searchString, startIndex, maxRange = 0, after = !1) {if (startIndex < 0) return -1;let index = txt.indexOf(searchString, startIndex);if (index < 0 || maxRange && index - startIndex > maxRange) return -1;return after ? index + searchString.length : index;}static lastIndexOf(txt, searchString, startIndex, maxRange = 0, after = !1) {if (startIndex < 0) return -1;let index = txt.lastIndexOf(searchString, startIndex);if (index < 0 || maxRange && startIndex - index > maxRange) return -1;return after ? index + searchString.length : index;}static insertAt(txt, index, insertString) {return txt.substring(0, index) + insertString + txt.substring(index);}static replaceWith(txt, index, fromString, toString) {return txt.substring(0, index) + toString + txt.substring(index + fromString.length);}static replaceAfterIndex(txt, search, replaceWith, index) {let before = txt.slice(0, index), after = txt.slice(index).replace(search, replaceWith);return before + after;}static filterPatches(patches) {return patches.filter((item2) => !!item2);}static patchBeforePageLoad(str, page) {let index = str.indexOf(`chunkName:()=>"${page}-page",`);if (index < 0) return !1;return str = PatcherUtils.replaceAfterIndex(str, "requireAsync(e){", `requireAsync(e){window.BX_EXPOSED.beforePageLoad("${page}");`, index), str = PatcherUtils.replaceAfterIndex(str, "requireSync(e){", `requireSync(e){window.BX_EXPOSED.beforePageLoad("${page}");`, index), str;}static isVarCharacter(char) {let code = char.charCodeAt(0), isUppercase = code >= 65 && code <= 90, isLowercase = code >= 97 && code <= 122, isDigit = code >= 48 && code <= 57;return isUppercase || isLowercase || isDigit || (char === "_" || char === "$");}static getVariableNameBefore(str, index) {if (index < 0) return null;let end = index, start = end - 1;while (PatcherUtils.isVarCharacter(str[start]))start -= 1;return str.substring(start + 1, end);}static getVariableNameAfter(str, index) {if (index < 0) return null;let start = index, end = start + 1;while (PatcherUtils.isVarCharacter(str[end]))end += 1;return str.substring(start, end);}static injectUseEffect(str, index, group, eventName, separator = ";") {let newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.${group}.emit('${eventName}', {}), [])${separator}`;return str = PatcherUtils.insertAt(str, index, newCode), str;}static parseParams(str, index, maxRange) {let substr = str.substring(index, index + maxRange), startIndex = substr.indexOf("({");if (startIndex < 0) return !1;startIndex += 1;let endIndex = substr.indexOf("})", startIndex);if (endIndex < 0) return !1;endIndex += 1;try {let pairs = [...substr.substring(startIndex, endIndex).matchAll(/(\w+)\s*:\s*([a-zA-Z_$][\w$]*)/g)], result = {};for (let [_, key, value] of pairs)result[key] = value;return result;} catch {return null;}}} +class PatcherUtils {static indexOf(txt, searchString, startIndex, maxRange = 0, after = !1) {if (startIndex < 0) return -1;let index = txt.indexOf(searchString, startIndex);if (index < 0 || maxRange && index - startIndex > maxRange) return -1;return after ? index + searchString.length : index;}static lastIndexOf(txt, searchString, startIndex, maxRange = 0, after = !1) {if (startIndex < 0) return -1;let index = txt.lastIndexOf(searchString, startIndex);if (index < 0 || maxRange && startIndex - index > maxRange) return -1;return after ? index + searchString.length : index;}static insertAt(txt, index, insertString) {return txt.substring(0, index) + insertString + txt.substring(index);}static replaceWith(txt, index, fromString, toString) {return txt.substring(0, index) + toString + txt.substring(index + fromString.length);}static replaceAfterIndex(txt, search, replaceWith, index) {let before = txt.slice(0, index), after = txt.slice(index).replace(search, replaceWith);return before + after;}static filterPatches(patches) {return patches.filter((item2) => !!item2);}static patchBeforePageLoad(str, page) {let index = str.indexOf(`chunkName:()=>"${page}-page",`);if (index < 0) return !1;return str = PatcherUtils.replaceAfterIndex(str, "requireAsync(e){", `requireAsync(e){window.BX_EXPOSED.beforePageLoad("${page}");`, index), str = PatcherUtils.replaceAfterIndex(str, "requireSync(e){", `requireSync(e){window.BX_EXPOSED.beforePageLoad("${page}");`, index), str;}static isVarCharacter(char) {let code = char.charCodeAt(0), isUppercase = code >= 65 && code <= 90, isLowercase = code >= 97 && code <= 122, isDigit = code >= 48 && code <= 57;return isUppercase || isLowercase || isDigit || (char === "_" || char === "$");}static getVariableNameBefore(str, index) {if (index < 0) return null;let end = index, start = end - 1;while (PatcherUtils.isVarCharacter(str[start]))start -= 1;return str.substring(start + 1, end);}static getVariableNameAfter(str, index) {if (index < 0) return null;let start = index, end = start + 1;while (PatcherUtils.isVarCharacter(str[end]))end += 1;return str.substring(start, end);}static injectUseEffect(str, index, group, eventName, separator = ";") {let newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.${group}.emit('${eventName}', {}), [])${separator}`;return str = PatcherUtils.insertAt(str, index, newCode), str;}static findAndParseParams(str, index, maxRange) {let substr = str.substring(index, index + maxRange), startIndex = substr.indexOf("({");if (startIndex < 0) return !1;startIndex += 1;let endIndex = substr.indexOf("})", startIndex);if (endIndex < 0) return !1;endIndex += 1;try {let input = substr.substring(startIndex, endIndex);return PatcherUtils.parseObjectVariables(input);} catch {return null;}}static parseObjectVariables(input) {try {let pairs = [...input.matchAll(/(\w+)\s*:\s*([a-zA-Z_$][\w$]*)/g)], result = {};for (let [_, key, value] of pairs)result[key] = value;return result;} catch {return null;}}} var LOG_TAG2 = "Patcher", PATCHES = {disableAiTrack(str) {let text = ".track=function(", index = str.indexOf(text);if (index < 0 || PatcherUtils.indexOf(str, '"AppInsightsCore', index, 200) < 0) return !1;return PatcherUtils.replaceWith(str, index, text, ".track=function(e){},!!function(");},disableTelemetryProvider(str) {let text = "this.enableLightweightTelemetry=!";if (!str.includes(text)) return !1;let newCode = ["this.trackEvent","this.trackPageView","this.trackHttpCompleted","this.trackHttpFailed","this.trackError","this.trackErrorLike","this.onTrackEvent","()=>{}"].join("=");return str.replace(text, newCode + ";" + text);},disableIndexDbLogging(str) {let text = ",this.logsDb=new";if (!str.includes(text)) return !1;let newCode = ",this.log=()=>{}";return str.replace(text, newCode + text);},websiteLayout(str) {let text = '?"tv":"default"';if (!str.includes(text)) return !1;let layout = getGlobalPref("ui.layout") === "tv" ? "tv" : "default";return str.replace(text, `?"${layout}":"${layout}"`);},remotePlayPostStreamRedirectUrl(str) {let text = ".RemotePlayRoot.getLink()):";if (!str.includes(text)) return !1;return str = str.replace(text, ".Home.getLink()):"), str;},remotePlayKeepAlive(str) {let text = "onServerDisconnectMessage(e){";if (!str.includes(text)) return !1;return str = str.replace(text, text + remote_play_keep_alive_default), str;},remotePlayDisableAchievementToast(str) {let text = ".AchievementUnlock:{";if (!str.includes(text)) return !1;let newCode = "if (window.location.pathname.includes('/play/consoles/launch/')) return;";return str.replace(text, text + newCode);},blockWebRtcStatsCollector(str) {let text = "this.shouldCollectStats=!0";if (!str.includes(text)) return !1;return str.replace(text, "this.shouldCollectStats=!1");},patchPollGamepads(str) {let index = str.indexOf("},this.pollGamepads=()=>{");if (index < 0) return !1;let setTimeoutIndex = str.indexOf("setTimeout(this.pollGamepads", index);if (setTimeoutIndex < 0) return !1;let codeBlock = str.substring(index, setTimeoutIndex), tmp = str.substring(setTimeoutIndex, setTimeoutIndex + 150), tmpPatched = tmp.replaceAll("Math.max(0,4-", "Math.max(0,window.BX_STREAM_SETTINGS.controllerPollingRate - ");if (str = PatcherUtils.replaceWith(str, setTimeoutIndex, tmp, tmpPatched), getGlobalPref("block.tracking")) codeBlock = codeBlock.replace("this.inputPollingIntervalStats.addValue", ""), codeBlock = codeBlock.replace("this.inputPollingDurationStats.addValue", "");let match = codeBlock.match(/this\.gamepadTimestamps\.set\(([A-Za-z0-9_$]+)\.index/);if (!match) return !1;let newCode = renderString(poll_gamepad_default, {gamepadVar: match[1]});if (codeBlock = codeBlock.replace("this.gamepadTimestamps.set", newCode + "this.gamepadTimestamps.set"), match = codeBlock.match(/let ([A-Za-z0-9_$]+)=this\.gamepadMappings\.find/), !match) return !1;let xCloudGamepadVar = match[1], inputFeedbackManager = PatcherUtils.indexOf(codeBlock, "this.inputFeedbackManager.onGamepadConnected(", 0, 1e4), backetIndex = PatcherUtils.indexOf(codeBlock, "}", inputFeedbackManager, 100);if (backetIndex < 0) return !1;let customizationCode = ";";return customizationCode += renderString(controller_customization_default, { xCloudGamepadVar }), codeBlock = PatcherUtils.insertAt(codeBlock, backetIndex, customizationCode), str = str.substring(0, index) + codeBlock + str.substring(setTimeoutIndex), str;},enableXcloudLogger(str) {let index = str.indexOf("this.telemetryProvider.trackErrorLike");if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "}log(", index, 1500)), index > -1 && (index = PatcherUtils.indexOf(str, "{", index, 30, !0)), index < 0) return !1;let newCode = ` const [logTag, logLevel, logMessage] = Array.from(arguments); const logFunc = [console.debug, console.log, console.warn, console.error][logLevel]; @@ -176,7 +176,7 @@ if (gamepadFound) {return;} ${autoOffCode} const titleInfo = window.BX_EXPOSED.getTitleInfo(); if (titleInfo && !titleInfo.details.hasTouchSupport && !titleInfo.details.hasFakeTouchSupport) {return;} -`;return str = str.replace(text, newCode + text), str;},streamCombineSources(str) {let text = "this.useCombinedAudioVideoStream=!!this.deviceInformation.isTizen";if (!str.includes(text)) return !1;return str = str.replace(text, "this.useCombinedAudioVideoStream=true"), str;},patchStreamHud(str) {let index = str.indexOf("({onCollapse:");if (index < 0) return !1;try {if (!PatcherUtils.parseParams(str, index, 1000)) return !1;let canShowTakHUDVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "canShowTakHUD", index, 500, !0) + 1), guideUIVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "guideUI", index, 500, !0) + 1), onShowStreamMenuVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "onShowStreamMenu", index, 500, !0) + 1), offsetVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "offset", index, 500, !0) + 1), newCode = renderString(stream_hud_default, {guideUI: guideUIVar,onShowStreamMenu: onShowStreamMenuVar,offset: offsetVar});if (getGlobalPref("touchController.mode") === "off") newCode += `${canShowTakHUDVar} = false;`;let bracketIndex = PatcherUtils.indexOf(str, "}){", index, 500, !0);return str = PatcherUtils.insertAt(str, bracketIndex, newCode), str;} catch (e) {return !1;}},broadcastPollingMode(str) {let text = ".setPollingMode=e=>{";if (!str.includes(text)) return !1;let newCode = ` +`;return str = str.replace(text, newCode + text), str;},streamCombineSources(str) {let text = "this.useCombinedAudioVideoStream=!!this.deviceInformation.isTizen";if (!str.includes(text)) return !1;return str = str.replace(text, "this.useCombinedAudioVideoStream=true"), str;},patchStreamHud(str) {let index = str.indexOf("({onCollapse:");if (index < 0) return !1;try {if (!PatcherUtils.findAndParseParams(str, index, 1000)) return !1;let canShowTakHUDVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "canShowTakHUD", index, 500, !0) + 1), guideUIVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "guideUI", index, 500, !0) + 1), onShowStreamMenuVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "onShowStreamMenu", index, 500, !0) + 1), offsetVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "offset", index, 500, !0) + 1), newCode = renderString(stream_hud_default, {guideUI: guideUIVar,onShowStreamMenu: onShowStreamMenuVar,offset: offsetVar});if (getGlobalPref("touchController.mode") === "off") newCode += `${canShowTakHUDVar} = false;`;let bracketIndex = PatcherUtils.indexOf(str, "}){", index, 500, !0);return str = PatcherUtils.insertAt(str, bracketIndex, newCode), str;} catch (e) {return !1;}},broadcastPollingMode(str) {let text = ".setPollingMode=e=>{";if (!str.includes(text)) return !1;let newCode = ` window.BX_STREAM_SETTINGS.xCloudPollingMode = e.toLowerCase(); BxEvent.dispatch(window, BxEvent.XCLOUD_POLLING_MODE_CHANGED); `;return str = str.replace(text, text + newCode), str;},patchGamepadPolling(str) {let index = str.indexOf(".shouldHandleGamepadInput)())return void");if (index < 0) return !1;return index = str.indexOf("{", index - 20) + 1, str = str.substring(0, index) + "if (window.BX_EXPOSED.disableGamepadPolling) return;" + str.substring(index), str;},patchXcloudTitleInfo(str) {let text = "async cloudConnect", index = str.indexOf(text);if (index < 0) return !1;let backetIndex = str.indexOf("{", index), params = str.substring(index, backetIndex).match(/\(([^)]+)\)/)[1];if (!params) return !1;let titleInfoVar = params.split(",")[0], newCode = ` @@ -187,14 +187,14 @@ Object.assign(${configsVar}.inputConfiguration, {enableMouseInput: false,enableK BxLogger.info('patchRemotePlayMkb', ${configsVar}); `;return str = str.substring(0, backetIndex + 1) + newCode + str.substring(backetIndex + 1), str;},patchAudioMediaStream(str) {let text = ".srcObject=this.audioMediaStream,";if (!str.includes(text)) return !1;let newCode = "window.BX_EXPOSED.setupGainNode(arguments[1], this.audioMediaStream),";return str = str.replace(text, text + newCode), str;},patchCombinedAudioVideoMediaStream(str) {let text = ".srcObject=this.combinedAudioVideoStream";if (!str.includes(text)) return !1;let newCode = ",window.BX_EXPOSED.setupGainNode(arguments[0], this.combinedAudioVideoStream)";return str = str.replace(text, text + newCode), str;},patchTouchControlDefaultOpacity(str) {let text = "opacityMultiplier:1";if (!str.includes(text)) return !1;let newCode = `opacityMultiplier: ${(getGlobalPref("touchController.opacity.default") / 100).toFixed(1)}`;return str = str.replace(text, newCode), str;},patchShowSensorControls(str) {let text = ",{shouldShowSensorControls:";if (!str.includes(text)) return !1;let newCode = ",{shouldShowSensorControls: (window.BX_EXPOSED && window.BX_EXPOSED.shouldShowSensorControls) ||";return str = str.replace(text, newCode), str;},exposeStreamSession(str) {let text = ",this._connectionType=";if (!str.includes(text)) return !1;let newCode = `; ${expose_stream_session_default} -true` + text;return str = str.replace(text, newCode), str;},skipFeedbackDialog(str) {let index = str.indexOf("}shouldTransitionToFeedback(");if (index >= 0 && (index = PatcherUtils.indexOf(str, "}){", index, 200, !0)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return !1;"), str;},enableNativeMkb(str) {let index = str.indexOf(".mouseSupported&&");if (index < 0) return !1;let varName = str.charAt(index - 1), text = `${varName}.mouseSupported&&${varName}.keyboardSupported&&${varName}.fullscreenSupported;`;if (!str.includes(text)) return !1;return str = str.replace(text, text + "return true;"), str;},patchMouseAndKeyboardEnabled(str) {let text = "get mouseAndKeyboardEnabled(){";if (!str.includes(text)) return !1;return str = str.replace(text, text + "return true;"), str;},exposeInputChannel(str) {let index = str.indexOf("this.flushData=");if (index < 0) return !1;let newCode = "window.BX_EXPOSED.inputChannel = this,";return str = PatcherUtils.insertAt(str, index, newCode), str;},disableNativeRequestPointerLock(str) {let text = "async requestPointerLock(){";if (!str.includes(text)) return !1;return str = str.replace(text, text + "return;"), str;},patchRequestInfoCrash(str) {let text = 'if(!e)throw new Error("RequestInfo.origin is falsy");';if (!str.includes(text)) return !1;return str = str.replace(text, 'if (!e) e = "https://www.xbox.com";'), str;},exposeDialogRoutes(str) {let text = "return{goBack:function(){";if (!str.includes(text)) return !1;return str = str.replace(text, "return window.BX_EXPOSED.dialogRoutes = {goBack:function(){"), str;},enableTvRoutes(str) {let index = str.indexOf(".LoginDeviceCode.path,");if (index < 0) return !1;let match = /render:.*?jsx\)\(([^,]+),/.exec(str.substring(index, index + 100));if (!match) return !1;let funcName = match[1];if (index = str.indexOf(`const ${funcName}=({children`), index > -1 && (index = PatcherUtils.indexOf(str, "return ", 300)), index > -1 && (index = PatcherUtils.indexOf(str, "?", 100)), index < 0) return !1;return str = str.substring(0, index) + "|| true" + str.substring(index), str;},ignoreNewsSection(str) {let index = str.indexOf('Logger("CarouselRow")');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const ", index, 200)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return null;"), str;},ignorePlayWithFriendsSection(str) {let index = str.indexOf('location:"PlayWithFriendsRow",');if (index < 0) return !1;if (index = PatcherUtils.lastIndexOf(str, "=>", index, 50), index < 0) return !1;return str = PatcherUtils.replaceWith(str, index, "=>", "=> true ? null :"), str;},ignoreAllGamesSection(str) {let index = str.indexOf('className:"AllGamesRow-module__allGamesRowContainer');if (index > -1 && (index = PatcherUtils.indexOf(str, "grid:!0,", index, 1500)), index > -1 && (index = PatcherUtils.lastIndexOf(str, "(0,", index, 70)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "true ? null :"), str;},ignoreByogSection(str) {let index = str.indexOf('"ByogRow-module__container');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 100)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return null;"), str;},ignorePlayWithTouchSection(str) {let index = str.indexOf('("Play_With_Touch"),');if (index < 0) return !1;if (index = PatcherUtils.lastIndexOf(str, "const ", index, 30), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return null;"), str;},ignoreSiglSections(str) {let index = str.indexOf("SiglRow-module__heroCard___");if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, "const[", index, 300)), index < 0) return !1;let params = PatcherUtils.parseParams(str, index - 500, 500);if (!params || !params.id) return !1;let PREF_HIDE_SECTIONS = getGlobalPref("ui.hideSections"), siglIds = [], sections = {"native-mkb": "8fa264dd-124f-4af3-97e8-596fcdf4b486","most-popular": "e7590b22-e299-44db-ae22-25c61405454c","leaving-soon": "393f05bf-e596-4ef6-9487-6d4fa0eab987","recently-added": "44a55037-770f-4bbf-bde5-a9fa27dba1da"};for (let section of PREF_HIDE_SECTIONS) {let galleryId = sections[section];galleryId && siglIds.push(galleryId);}let checkSyntax = siglIds.map((item2) => `${params.id} === "${item2}"`).join(" || "), newCode = `if (${params.id} && (${checkSyntax})) return null;`;return str = PatcherUtils.insertAt(str, index, newCode), str;},ignoreGenresSection(str) {let index = str.indexOf('="GenresRow"');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "{", index)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index + 1, "return null;"), str;},overrideStorageGetSettings(str) {let text = "}getSetting(e){";if (!str.includes(text)) return !1;let newCode = ` +true` + text;return str = str.replace(text, newCode), str;},skipFeedbackDialog(str) {let index = str.indexOf("}shouldTransitionToFeedback(");if (index >= 0 && (index = PatcherUtils.indexOf(str, "}){", index, 200, !0)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return !1;"), str;},enableNativeMkb(str) {let index = str.indexOf(".mouseSupported&&");if (index < 0) return !1;let varName = str.charAt(index - 1), text = `${varName}.mouseSupported&&${varName}.keyboardSupported&&${varName}.fullscreenSupported;`;if (!str.includes(text)) return !1;return str = str.replace(text, text + "return true;"), str;},patchMouseAndKeyboardEnabled(str) {let text = "get mouseAndKeyboardEnabled(){";if (!str.includes(text)) return !1;return str = str.replace(text, text + "return true;"), str;},exposeInputChannel(str) {let index = str.indexOf("this.flushData=");if (index < 0) return !1;let newCode = "window.BX_EXPOSED.inputChannel = this,";return str = PatcherUtils.insertAt(str, index, newCode), str;},disableNativeRequestPointerLock(str) {let text = "async requestPointerLock(){";if (!str.includes(text)) return !1;return str = str.replace(text, text + "return;"), str;},patchRequestInfoCrash(str) {let text = 'if(!e)throw new Error("RequestInfo.origin is falsy");';if (!str.includes(text)) return !1;return str = str.replace(text, 'if (!e) e = "https://www.xbox.com";'), str;},exposeDialogRoutes(str) {let text = "return{goBack:function(){";if (!str.includes(text)) return !1;return str = str.replace(text, "return window.BX_EXPOSED.dialogRoutes = {goBack:function(){"), str;},enableTvRoutes(str) {let index = str.indexOf(".LoginDeviceCode.path,");if (index < 0) return !1;let match = /render:.*?jsx\)\(([^,]+),/.exec(str.substring(index, index + 100));if (!match) return !1;let funcName = match[1];if (index = str.indexOf(`const ${funcName}=({children`), index > -1 && (index = PatcherUtils.indexOf(str, "return ", 300)), index > -1 && (index = PatcherUtils.indexOf(str, "?", 100)), index < 0) return !1;return str = str.substring(0, index) + "|| true" + str.substring(index), str;},ignoreNewsSection(str) {let index = str.indexOf('Logger("CarouselRow")');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const ", index, 200)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return null;"), str;},ignorePlayWithFriendsSection(str) {let index = str.indexOf('location:"PlayWithFriendsRow",');if (index < 0) return !1;if (index = PatcherUtils.lastIndexOf(str, "=>", index, 50), index < 0) return !1;return str = PatcherUtils.replaceWith(str, index, "=>", "=> true ? null :"), str;},ignoreAllGamesSection(str) {let index = str.indexOf('className:"AllGamesRow-module__allGamesRowContainer');if (index > -1 && (index = PatcherUtils.indexOf(str, "grid:!0,", index, 1500)), index > -1 && (index = PatcherUtils.lastIndexOf(str, "(0,", index, 70)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "true ? null :"), str;},ignoreByogSection(str) {let index = str.indexOf('"ByogRow-module__container');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 100)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return null;"), str;},ignorePlayWithTouchSection(str) {let index = str.indexOf('("Play_With_Touch"),');if (index < 0) return !1;if (index = PatcherUtils.lastIndexOf(str, "const ", index, 30), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "return null;"), str;},ignoreSiglSections(str) {let index = str.indexOf("SiglRow-module__heroCard___");if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, "const[", index, 300)), index < 0) return !1;let params = PatcherUtils.findAndParseParams(str, index - 500, 500);if (!params || !params.id) return !1;let PREF_HIDE_SECTIONS = getGlobalPref("ui.hideSections"), siglIds = [], sections = {"native-mkb": "8fa264dd-124f-4af3-97e8-596fcdf4b486","most-popular": "e7590b22-e299-44db-ae22-25c61405454c","leaving-soon": "393f05bf-e596-4ef6-9487-6d4fa0eab987","recently-added": "44a55037-770f-4bbf-bde5-a9fa27dba1da"};for (let section of PREF_HIDE_SECTIONS) {let galleryId = sections[section];galleryId && siglIds.push(galleryId);}let checkSyntax = siglIds.map((item2) => `${params.id} === "${item2}"`).join(" || "), newCode = `if (${params.id} && (${checkSyntax})) return null;`;return str = PatcherUtils.insertAt(str, index, newCode), str;},ignoreGenresSection(str) {let index = str.indexOf('="GenresRow"');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "{", index)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index + 1, "return null;"), str;},overrideStorageGetSettings(str) {let text = "}getSetting(e){";if (!str.includes(text)) return !1;let newCode = ` // console.log('setting', this.baseStorageKey, e); if (this.baseStorageKey in window.BX_EXPOSED.overrideSettings) {const settings = window.BX_EXPOSED.overrideSettings[this.baseStorageKey];if (e in settings) {return settings[e];}} `;return str = str.replace(text, text + newCode), str;},alwaysShowStreamHud(str) {let index = str.indexOf(",{onShowStreamMenu:");if (index < 0) return !1;if (index = str.indexOf("&&(0,", index - 100), index < 0) return !1;let commaIndex = str.indexOf(",", index - 10);return str = str.substring(0, commaIndex) + ",true" + str.substring(index), str;},patchSetCurrentFocus(str) {let index = str.indexOf(".setCurrentFocus=(");if (index < 0) return !1;return index = str.indexOf("{", index) + 1, str = PatcherUtils.insertAt(str, index, "e && BxEvent.dispatch(window, BxEvent.NAVIGATION_FOCUS_CHANGED, { element: e });"), str;},detectProductDetailPage(str) {let index = str.indexOf('{location:"ProductDetailPage",');if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;return str = str.substring(0, index) + 'BxEvent.dispatch(window, BxEvent.XCLOUD_RENDERING_COMPONENT, { component: "product-detail" });' + str.substring(index), str;},detectBrowserRouterReady(str) {let index = str.indexOf("{history:this.history,");if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, "return", index, 100)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, "window.BxEvent.dispatch(window, window.BxEvent.XCLOUD_ROUTER_HISTORY_READY, {history: this.history});"), str;},guideAchievementsDefaultLocked(str) {let index = str.indexOf("FilterButton-module__container");if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, '"All"', index, 150)), index < 0) return !1;if (str = PatcherUtils.replaceWith(str, index, '"All"', '"Locked"'), index = str.indexOf('"Guide_Achievements_Unlocked_Empty","Guide_Achievements_Locked_Empty"'), index >= 0 && (index = PatcherUtils.indexOf(str, '"All"', index, 250)), index < 0) return !1;return str = PatcherUtils.replaceWith(str, index, '"All"', '"Locked"'), str;},disableTouchContextMenu(str) {let index = str.indexOf('.addEventListener("touchstart",');if (index >= 0 && (index = PatcherUtils.indexOf(str, '.addEventListener("touchend"', index, 200)), index >= 0 && (index = PatcherUtils.lastIndexOf(str, "return ", index, 50)), index < 0) return !1;return str = PatcherUtils.replaceWith(str, index, "return", "return () => {};"), str;},modifyPreloadedState(str) {let text = "=window.__PRELOADED_STATE__;";if (!str.includes(text)) return !1;return str = str.replace(text, "=window.BX_EXPOSED.modifyPreloadedState(window.__PRELOADED_STATE__);"), str;},homePageBeforeLoad(str) {return PatcherUtils.patchBeforePageLoad(str, "home");},productDetailPageBeforeLoad(str) {return PatcherUtils.patchBeforePageLoad(str, "product-detail");},streamPageBeforeLoad(str) {return PatcherUtils.patchBeforePageLoad(str, "stream");},remotePlayStreamPageBeforeLoad(str) {return PatcherUtils.patchBeforePageLoad(str, "remote-play-stream");},disableAbsoluteMouse(str) {let text = "sendAbsoluteMouseCapableMessage(e){";if (!str.includes(text)) return !1;return str = str.replace(text, text + "return;"), str;},changeNotificationsSubscription(str) {let text = ";buildSubscriptionQueryParamsForNotifications(", index = str.indexOf(text);if (index < 0) return !1;index += text.length;let subsVar = str[index];index = str.indexOf("{", index) + 1;let blockFeatures = getGlobalPref("block.features"), filters = [];if (blockFeatures.includes("notifications-invites")) filters.push("GameInvite", "PartyInvite");if (blockFeatures.includes("friends")) filters.push("Follower");if (blockFeatures.includes("notifications-achievements")) filters.push("AchievementUnlock");let newCode = ` let subs = ${subsVar}; subs = subs.filter(val => !${JSON.stringify(filters)}.includes(val)); ${subsVar} = subs; -`;return str = PatcherUtils.insertAt(str, index, newCode), str;},exposeReactCreateComponent(str) {let index = str.indexOf(".prototype.isReactComponent={}");if (index > -1 && (index = PatcherUtils.indexOf(str, ".createElement=", index)), index < 0) return !1;if (str = PatcherUtils.insertAt(str, index - 1, "window.BX_EXPOSED.reactCreateElement="), index = PatcherUtils.indexOf(str, ".useEffect=", index), index < 0) return !1;return str = PatcherUtils.insertAt(str, index - 1, "window.BX_EXPOSED.reactUseEffect="), str;},gameCardCustomIcons(str) {let initialIndex = str.indexOf("const{supportedInputIcons:");if (initialIndex < 0) return !1;let returnIndex = PatcherUtils.lastIndexOf(str, "return ", str.indexOf("SupportedInputsBadge"));if (returnIndex < 0) return !1;let productIdIndex = PatcherUtils.lastIndexOf(str, ",productId:", initialIndex, 300);if (productIdIndex < 0) return !1;let productIdVar = PatcherUtils.getVariableNameAfter(str, productIdIndex + 11), supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "supportedInputIcons:", initialIndex, 100, !0));if (!productIdVar || !supportedInputIconsVar) return !1;let newCode = renderString(game_card_icons_default, {productId: productIdVar,supportedInputIcons: supportedInputIconsVar});return str = PatcherUtils.insertAt(str, returnIndex, newCode), str;},setImageQuality(str) {let index = str.indexOf("const{size:{width:");if (index > -1 && (index = PatcherUtils.indexOf(str, "=new URLSearchParams", index, 500)), index < 0) return !1;let paramVar = PatcherUtils.getVariableNameBefore(str, index);if (!paramVar) return !1;index = PatcherUtils.indexOf(str, "return", index, 200);let newCode = `${paramVar}.set('q', ${getGlobalPref("ui.imageQuality")});`;return str = PatcherUtils.insertAt(str, index, newCode), str;},setBackgroundImageQuality(str) {let index = str.indexOf("}?w=${");if (index > -1 && (index = PatcherUtils.indexOf(str, "}", index + 1, 10, !0)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, `&q=${getGlobalPref("ui.imageQuality")}`), str;},injectHeaderUseEffect(str) {let index = str.indexOf('className:"Header-module__header');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 300)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Script", "ui.header.rendered");},injectErrorPageUseEffect(str) {let index = str.indexOf('"PureErrorPage-module__container');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "})=>(0,", index, 200)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index + 4, "{return "), str = PatcherUtils.injectUseEffect(str, index + 5, "Script", "ui.error.rendered"), str += "}", str;},injectStreamMenuUseEffect(str) {let index = str.indexOf('"StreamMenu-module__container');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Stream", "ui.streamMenu.rendered");},injectGuideHomeUseEffect(str) {let index = str.indexOf('"HomeLandingPage-module__authenticatedContentContainer');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Script", "ui.guideHome.rendered");},injectCreatePortal(str) {let index = str.indexOf(".createPortal=function");if (index > -1 && (index = PatcherUtils.indexOf(str, "{", index, 50, !0)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, create_portal_default), str;},injectAchievementsProgressUseEffect(str) {let index = str.indexOf('"AchievementsButton-module__progressBarContainer');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Script", "ui.guideAchievementProgress.rendered");},injectAchievementsDetailUseEffect(str) {let index = str.indexOf("GuideAchievementDetail.useParams()");if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const", index, 200)), index < 0) return !1;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([...AppInterface && getGlobalPref("nativeMkb.mode") === "on" ? ["enableNativeMkb","disableAbsoluteMouse"] : [],"exposeReactCreateComponent","injectCreatePortal","broadcastPollingMode",getGlobalPref("ui.gameCard.waitTime.show") && "patchSetCurrentFocus","patchGamepadPolling","modifyPreloadedState","detectBrowserRouterReady","exposeStreamSession","supportLocalCoOp","disableStreamGate","exposeDialogRoutes",...getGlobalPref("ui.imageQuality") < 90 ? ["setImageQuality"] : [],"patchRequestInfoCrash","injectErrorPageUseEffect","streamPageBeforeLoad","remotePlayStreamPageBeforeLoad","injectGuideHomeUseEffect","injectAchievementsProgressUseEffect","injectAchievementsDetailUseEffect","guideAchievementsDefaultLocked","injectHeaderUseEffect","homePageBeforeLoad","patchCustomInputIcon","gameCardCustomIcons","productDetailPageBeforeLoad","enableTvRoutes","overrideStorageGetSettings",getGlobalPref("ui.layout") !== "default" && "websiteLayout",getGlobalPref("game.fortnite.forceConsole") && "forceFortniteConsole",...STATES.userAgent.capabilities.touch ? ["disableTouchContextMenu"] : [],...getGlobalPref("block.tracking") ? ["disableAiTrack","blockWebRtcStatsCollector","disableIndexDbLogging","disableTelemetryProvider"] : [],...!getGlobalPref("block.features").includes("remote-play") ? ["remotePlayKeepAlive","remotePlayDisableAchievementToast",STATES.userAgent.capabilities.touch && "patchUpdateInputConfigurationAsync"] : [],...BX_FLAGS.EnableXcloudLogging ? ["enableConsoleLogging","enableXcloudLogger"] : [] +`;return str = PatcherUtils.insertAt(str, index, newCode), str;},exposeReactCreateComponent(str) {let index = str.indexOf(".prototype.isReactComponent={}");if (index > -1 && (index = PatcherUtils.indexOf(str, ".createElement=", index)), index < 0) return !1;if (str = PatcherUtils.insertAt(str, index - 1, "window.BX_EXPOSED.reactCreateElement="), index = PatcherUtils.indexOf(str, ".useEffect=", index), index < 0) return !1;return str = PatcherUtils.insertAt(str, index - 1, "window.BX_EXPOSED.reactUseEffect="), str;},gameCardCustomIcons(str) {let initialIndex = str.indexOf("const{supportedInputIcons:");if (initialIndex < 0) return !1;let returnIndex = PatcherUtils.lastIndexOf(str, "return ", str.indexOf("SupportedInputsBadge"));if (returnIndex < 0) return !1;let productIdIndex = PatcherUtils.lastIndexOf(str, ",productId:", initialIndex, 300);if (productIdIndex < 0) return !1;let params = PatcherUtils.findAndParseParams(str, productIdIndex - 200, 400);if (!params || !params.productId) return !1;let productIdVar = params.productId, supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "supportedInputIcons:", initialIndex, 100, !0));if (!supportedInputIconsVar) return !1;let newCode = renderString(game_card_icons_default, {productId: productIdVar,supportedInputIcons: supportedInputIconsVar});return str = PatcherUtils.insertAt(str, returnIndex, newCode), str;},setImageQuality(str) {let index = str.indexOf("const{size:{width:");if (index > -1 && (index = PatcherUtils.indexOf(str, "=new URLSearchParams", index, 500)), index < 0) return !1;let paramVar = PatcherUtils.getVariableNameBefore(str, index);if (!paramVar) return !1;index = PatcherUtils.indexOf(str, "return", index, 200);let newCode = `${paramVar}.set('q', ${getGlobalPref("ui.imageQuality")});`;return str = PatcherUtils.insertAt(str, index, newCode), str;},setBackgroundImageQuality(str) {let index = str.indexOf("}?w=${");if (index > -1 && (index = PatcherUtils.indexOf(str, "}", index + 1, 10, !0)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, `&q=${getGlobalPref("ui.imageQuality")}`), str;},injectHeaderUseEffect(str) {let index = str.indexOf('className:"Header-module__header');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 300)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Script", "ui.header.rendered");},injectErrorPageUseEffect(str) {let index = str.indexOf('"PureErrorPage-module__container');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "})=>(0,", index, 200)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index + 4, "{return "), str = PatcherUtils.injectUseEffect(str, index + 5, "Script", "ui.error.rendered"), str += "}", str;},injectStreamMenuUseEffect(str) {let index = str.indexOf('"StreamMenu-module__container');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Stream", "ui.streamMenu.rendered");},injectGuideHomeUseEffect(str) {let index = str.indexOf('"HomeLandingPage-module__authenticatedContentContainer');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Script", "ui.guideHome.rendered");},injectCreatePortal(str) {let index = str.indexOf(".createPortal=function");if (index > -1 && (index = PatcherUtils.indexOf(str, "{", index, 50, !0)), index < 0) return !1;return str = PatcherUtils.insertAt(str, index, create_portal_default), str;},injectAchievementsProgressUseEffect(str) {let index = str.indexOf('"AchievementsButton-module__progressBarContainer');if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;return PatcherUtils.injectUseEffect(str, index, "Script", "ui.guideAchievementProgress.rendered");},injectAchievementsDetailUseEffect(str) {let index = str.indexOf("GuideAchievementDetail.useParams()");if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const", index, 200)), index < 0) return !1;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([...AppInterface && getGlobalPref("nativeMkb.mode") === "on" ? ["enableNativeMkb","disableAbsoluteMouse"] : [],"exposeReactCreateComponent","injectCreatePortal","broadcastPollingMode",getGlobalPref("ui.gameCard.waitTime.show") && "patchSetCurrentFocus","patchGamepadPolling","modifyPreloadedState","detectBrowserRouterReady","exposeStreamSession","supportLocalCoOp","disableStreamGate","exposeDialogRoutes",...getGlobalPref("ui.imageQuality") < 90 ? ["setImageQuality"] : [],"patchRequestInfoCrash","injectErrorPageUseEffect","streamPageBeforeLoad","remotePlayStreamPageBeforeLoad","injectGuideHomeUseEffect","injectAchievementsProgressUseEffect","injectAchievementsDetailUseEffect","guideAchievementsDefaultLocked","injectHeaderUseEffect","homePageBeforeLoad","patchCustomInputIcon","gameCardCustomIcons","productDetailPageBeforeLoad","enableTvRoutes","overrideStorageGetSettings",getGlobalPref("ui.layout") !== "default" && "websiteLayout",getGlobalPref("game.fortnite.forceConsole") && "forceFortniteConsole",...STATES.userAgent.capabilities.touch ? ["disableTouchContextMenu"] : [],...getGlobalPref("block.tracking") ? ["disableAiTrack","blockWebRtcStatsCollector","disableIndexDbLogging","disableTelemetryProvider"] : [],...!getGlobalPref("block.features").includes("remote-play") ? ["remotePlayKeepAlive","remotePlayDisableAchievementToast",STATES.userAgent.capabilities.touch && "patchUpdateInputConfigurationAsync"] : [],...BX_FLAGS.EnableXcloudLogging ? ["enableConsoleLogging","enableXcloudLogger"] : [] ]), hideSections = getGlobalPref("ui.hideSections"), HOME_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([hideSections.includes("genres") && "ignoreGenresSection",!getGlobalPref("block.features").includes("byog") && hideSections.includes("byog") && "ignoreByogSection",STATES.browser.capabilities.touch && hideSections.includes("touch") && "ignorePlayWithTouchSection",getGlobalPref("ui.imageQuality") < 90 && "setBackgroundImageQuality",hideSections.some((value) => ["native-mkb", "most-popular"].includes(value)) && "ignoreSiglSections",hideSections.includes("news") && "ignoreNewsSection",(getGlobalPref("block.features").includes("friends") || hideSections.includes("friends")) && "ignorePlayWithFriendsSection",hideSections.includes("all-games") && "ignoreAllGamesSection",...blockSomeNotifications() ? ["changeNotificationsSubscription"] : [] ]), STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches(["exposeInputChannel","patchXcloudTitleInfo","disableGamepadDisconnectedScreen","patchStreamHud","playVibration","alwaysShowStreamHud","injectStreamMenuUseEffect",getGlobalPref("audio.volume.booster.enabled") && !getGlobalPref("stream.video.combineAudio") && "patchAudioMediaStream",getGlobalPref("audio.volume.booster.enabled") && getGlobalPref("stream.video.combineAudio") && "patchCombinedAudioVideoMediaStream",getGlobalPref("ui.feedbackDialog.disabled") && "skipFeedbackDialog",...STATES.userAgent.capabilities.touch ? [getGlobalPref("touchController.mode") === "all" && "patchShowSensorControls",getGlobalPref("touchController.mode") === "all" && "exposeTouchLayoutManager",(getGlobalPref("touchController.mode") === "off" || getGlobalPref("touchController.autoOff")) && "disableTakRenderer",getGlobalPref("touchController.opacity.default") !== 100 && "patchTouchControlDefaultOpacity",getGlobalPref("touchController.mode") !== "off" && (getGlobalPref("mkb.enabled") || getGlobalPref("nativeMkb.mode") === "on") && "patchBabylonRendererClass"] : [],"patchPollGamepads",getGlobalPref("stream.video.combineAudio") && "streamCombineSources",...!getGlobalPref("block.features").includes("remote-play") ? ["remotePlayPostStreamRedirectUrl","patchRemotePlayMkb"] : [],...AppInterface && getGlobalPref("nativeMkb.mode") === "on" ? ["patchMouseAndKeyboardEnabled","disableNativeRequestPointerLock"] : [] ]), PRODUCT_DETAIL_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches(["detectProductDetailPage" diff --git a/src/modules/patcher/patcher-utils.ts b/src/modules/patcher/patcher-utils.ts index d729b7f..a25845d 100644 --- a/src/modules/patcher/patcher-utils.ts +++ b/src/modules/patcher/patcher-utils.ts @@ -111,7 +111,7 @@ export class PatcherUtils { return str; } - static parseParams(str: string, index: number, maxRange: number) { + static findAndParseParams(str: string, index: number, maxRange: number) { const substr = str.substring(index, index + maxRange); let startIndex = substr.indexOf('({'); if (startIndex < 0) { @@ -127,6 +127,14 @@ export class PatcherUtils { try { const input = substr.substring(startIndex, endIndex); + return PatcherUtils.parseObjectVariables(input); + } catch { + return null; + } + } + + static parseObjectVariables(input: string) { + try { const pairs = [...input.matchAll(/(\w+)\s*:\s*([a-zA-Z_$][\w$]*)/g)]; const result: Record = {}; diff --git a/src/modules/patcher/patcher.ts b/src/modules/patcher/patcher.ts index d7d957d..49d0aa3 100755 --- a/src/modules/patcher/patcher.ts +++ b/src/modules/patcher/patcher.ts @@ -399,7 +399,7 @@ if (titleInfo && !titleInfo.details.hasTouchSupport && !titleInfo.details.hasFak } try { - const params = PatcherUtils.parseParams(str, index, 1000); + const params = PatcherUtils.findAndParseParams(str, index, 1000); if (!params) { return false; } @@ -778,7 +778,7 @@ true` + text; return false; } - const params = PatcherUtils.parseParams(str, index - 500, 500); + const params = PatcherUtils.findAndParseParams(str, index - 500, 500); if (!params || !params.id) { return false; } @@ -1030,12 +1030,16 @@ ${subsVar} = subs; return false; } - const productIdVar = PatcherUtils.getVariableNameAfter(str, productIdIndex + 11); + const params = PatcherUtils.findAndParseParams(str, productIdIndex - 200, 400); + if (!params || !params.productId) { + return false; + } + + const productIdVar = params.productId; // Find supportedInputIcons and title var names const supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, 'supportedInputIcons:', initialIndex, 100, true)); - - if (!productIdVar || !supportedInputIconsVar) { + if (!supportedInputIconsVar) { return false; }