From b090d325ae2581dc20379d1ab393fe7b70f88fa4 Mon Sep 17 00:00:00 2001 From: redphx <96280+redphx@users.noreply.github.com> Date: Fri, 1 Nov 2024 07:22:21 +0700 Subject: [PATCH] Migrate PatcherCache to singleton class --- dist/better-xcloud.user.js | 58 ++++++++++---------- src/modules/patcher.ts | 70 +++++++++++++----------- src/modules/ui/dialog/settings-dialog.ts | 2 +- 3 files changed, 68 insertions(+), 62 deletions(-) diff --git a/dist/better-xcloud.user.js b/dist/better-xcloud.user.js index 1e87bd7..01c56d1 100644 --- a/dist/better-xcloud.user.js +++ b/dist/better-xcloud.user.js @@ -4489,7 +4489,7 @@ class Patcher { if (arguments[1] === 0 || typeof arguments[1] === "function") valid = !0; } if (!valid) return nativeBind.apply(this, arguments); - if (PatcherCache.init(), typeof arguments[1] === "function") BxLogger.info(LOG_TAG2, "Restored Function.prototype.bind()"), Function.prototype.bind = nativeBind; + if (PatcherCache.getInstance().init(), typeof arguments[1] === "function") BxLogger.info(LOG_TAG2, "Restored Function.prototype.bind()"), Function.prototype.bind = nativeBind; let orgFunc = this, newFunc = (a, item2) => { Patcher.patch(item2), orgFunc(a, item2); }; @@ -4497,10 +4497,10 @@ class Patcher { }; } static patch(item) { - let patchesToCheck, appliedPatches, patchesMap = {}; + let patchesToCheck, appliedPatches, patchesMap = {}, patcherCache = PatcherCache.getInstance(); for (let id in item[1]) { appliedPatches = []; - let cachedPatches = PatcherCache.getPatches(id); + let cachedPatches = patcherCache.getPatches(id); if (cachedPatches) patchesToCheck = cachedPatches.slice(0), patchesToCheck.push(...PATCH_ORDERS); else patchesToCheck = PATCH_ORDERS.slice(0); if (!patchesToCheck.length) continue; @@ -4520,18 +4520,20 @@ class Patcher { } if (appliedPatches.length) patchesMap[id] = appliedPatches; } - if (Object.keys(patchesMap).length) PatcherCache.saveToCache(patchesMap); + if (Object.keys(patchesMap).length) patcherCache.saveToCache(patchesMap); } static init() { Patcher.#patchFunctionBind(); } } class PatcherCache { - static KEY_CACHE = "better_xcloud_patches_cache"; - static KEY_SIGNATURE = "better_xcloud_patches_cache_signature"; - static CACHE; - static isInitialized = !1; - static getSignature() { + static instance; + static getInstance = () => PatcherCache.instance ?? (PatcherCache.instance = new PatcherCache); + KEY_CACHE = "better_xcloud_patches_cache"; + KEY_SIGNATURE = "better_xcloud_patches_cache_signature"; + CACHE; + isInitialized = !1; + getSignature() { let scriptVersion = SCRIPT_VERSION, patches = JSON.stringify(ALL_PATCHES), webVersion = "", $link = document.querySelector('link[data-chunk="client"][href*="/client."]'); if ($link) { let match = /\/client\.([^\.]+)\.js/.exec($link.href); @@ -4539,38 +4541,38 @@ class PatcherCache { } else webVersion = document.querySelector("meta[name=gamepass-app-version]")?.content ?? ""; return hashCode(scriptVersion + webVersion + patches); } - static clear() { - window.localStorage.removeItem(PatcherCache.KEY_CACHE), PatcherCache.CACHE = {}; + clear() { + window.localStorage.removeItem(this.KEY_CACHE), this.CACHE = {}; } - static checkSignature() { - let storedSig = window.localStorage.getItem(PatcherCache.KEY_SIGNATURE) || 0, currentSig = PatcherCache.getSignature(); - if (currentSig !== parseInt(storedSig)) BxLogger.warning(LOG_TAG2, "Signature changed"), window.localStorage.setItem(PatcherCache.KEY_SIGNATURE, currentSig.toString()), PatcherCache.clear(); + checkSignature() { + let storedSig = window.localStorage.getItem(this.KEY_SIGNATURE) || 0, currentSig = this.getSignature(); + if (currentSig !== parseInt(storedSig)) BxLogger.warning(LOG_TAG2, "Signature changed"), window.localStorage.setItem(this.KEY_SIGNATURE, currentSig.toString()), this.clear(); else BxLogger.info(LOG_TAG2, "Signature unchanged"); } - static cleanupPatches(patches) { + cleanupPatches(patches) { return patches.filter((item2) => { - for (let id2 in PatcherCache.CACHE) - if (PatcherCache.CACHE[id2].includes(item2)) return !1; + for (let id2 in this.CACHE) + if (this.CACHE[id2].includes(item2)) return !1; return !0; }); } - static getPatches(id2) { - return PatcherCache.CACHE[id2]; + getPatches(id2) { + return this.CACHE[id2]; } - static saveToCache(subCache) { + saveToCache(subCache) { for (let id2 in subCache) { - let patchNames = subCache[id2], data = PatcherCache.CACHE[id2]; - if (!data) PatcherCache.CACHE[id2] = patchNames; + let patchNames = subCache[id2], data = this.CACHE[id2]; + if (!data) this.CACHE[id2] = patchNames; else for (let patchName of patchNames) if (!data.includes(patchName)) data.push(patchName); } - window.localStorage.setItem(PatcherCache.KEY_CACHE, JSON.stringify(PatcherCache.CACHE)); + window.localStorage.setItem(this.KEY_CACHE, JSON.stringify(this.CACHE)); } - static init() { - if (PatcherCache.isInitialized) return; - if (PatcherCache.isInitialized = !0, PatcherCache.checkSignature(), PatcherCache.CACHE = JSON.parse(window.localStorage.getItem(PatcherCache.KEY_CACHE) || "{}"), BxLogger.info(LOG_TAG2, PatcherCache.CACHE), window.location.pathname.includes("/play/")) PATCH_ORDERS.push(...PLAYING_PATCH_ORDERS); + init() { + if (this.isInitialized) return; + if (this.isInitialized = !0, this.checkSignature(), this.CACHE = JSON.parse(window.localStorage.getItem(this.KEY_CACHE) || "{}"), BxLogger.info(LOG_TAG2, this.CACHE), 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_TAG2, PATCH_ORDERS.slice(0)), BxLogger.info(LOG_TAG2, PLAYING_PATCH_ORDERS.slice(0)); + PATCH_ORDERS = this.cleanupPatches(PATCH_ORDERS), PLAYING_PATCH_ORDERS = this.cleanupPatches(PLAYING_PATCH_ORDERS), BxLogger.info(LOG_TAG2, PATCH_ORDERS.slice(0)), BxLogger.info(LOG_TAG2, PLAYING_PATCH_ORDERS.slice(0)); } } class FullscreenText { @@ -5254,7 +5256,7 @@ class SettingsNavigationDialog extends NavigationDialog { return $svg.dataset.group = settingTab.group, $svg.tabIndex = 0, settingTab.lazyContent && ($svg.dataset.lazy = settingTab.lazyContent.toString()), $svg.addEventListener("click", this.onTabClicked.bind(this)), $svg; } onGlobalSettingChanged(e) { - PatcherCache.clear(), this.$btnReload.classList.add("bx-danger"), this.$noteGlobalReload.classList.add("bx-gone"), this.$btnGlobalReload.classList.remove("bx-gone"), this.$btnGlobalReload.classList.add("bx-danger"); + PatcherCache.getInstance().clear(), this.$btnReload.classList.add("bx-danger"), this.$noteGlobalReload.classList.add("bx-gone"), this.$btnGlobalReload.classList.remove("bx-gone"), this.$btnGlobalReload.classList.add("bx-danger"); } renderServerSetting(setting) { let selectedValue = getPref("server_region"), continents = { diff --git a/src/modules/patcher.ts b/src/modules/patcher.ts index 763a417..2bdb650 100644 --- a/src/modules/patcher.ts +++ b/src/modules/patcher.ts @@ -1116,7 +1116,7 @@ export class Patcher { return nativeBind.apply(this, arguments); } - PatcherCache.init(); + PatcherCache.getInstance().init(); if (typeof arguments[1] === 'function') { BxLogger.info(LOG_TAG, 'Restored Function.prototype.bind()'); @@ -1141,11 +1141,12 @@ export class Patcher { let appliedPatches: PatchArray; const patchesMap: Record = {}; + const patcherCache = PatcherCache.getInstance(); for (let id in item[1]) { appliedPatches = []; - const cachedPatches = PatcherCache.getPatches(id); + const cachedPatches = patcherCache.getPatches(id); if (cachedPatches) { patchesToCheck = cachedPatches.slice(0); patchesToCheck.push(...PATCH_ORDERS); @@ -1212,7 +1213,7 @@ export class Patcher { } if (Object.keys(patchesMap).length) { - PatcherCache.saveToCache(patchesMap); + patcherCache.saveToCache(patchesMap); } } @@ -1222,17 +1223,20 @@ export class Patcher { } export class PatcherCache { - private static readonly KEY_CACHE = 'better_xcloud_patches_cache'; - private static readonly KEY_SIGNATURE = 'better_xcloud_patches_cache_signature'; + private static instance: PatcherCache; + public static getInstance = () => PatcherCache.instance ?? (PatcherCache.instance = new PatcherCache()); - private static CACHE: any; + private readonly KEY_CACHE = 'better_xcloud_patches_cache'; + private readonly KEY_SIGNATURE = 'better_xcloud_patches_cache_signature'; - private static isInitialized = false; + private CACHE: any; + + private isInitialized = false; /** * Get patch's signature */ - private static getSignature(): number { + private getSignature(): number { const scriptVersion = SCRIPT_VERSION; const patches = JSON.stringify(ALL_PATCHES); @@ -1253,31 +1257,31 @@ export class PatcherCache { return sig; } - static clear() { + clear() { // Clear cache - window.localStorage.removeItem(PatcherCache.KEY_CACHE); - PatcherCache.CACHE = {}; + window.localStorage.removeItem(this.KEY_CACHE); + this.CACHE = {}; } - static checkSignature() { - const storedSig = window.localStorage.getItem(PatcherCache.KEY_SIGNATURE) || 0; - const currentSig = PatcherCache.getSignature(); + private checkSignature() { + const storedSig = window.localStorage.getItem(this.KEY_SIGNATURE) || 0; + const currentSig = this.getSignature(); if (currentSig !== parseInt(storedSig as string)) { // Save new signature BxLogger.warning(LOG_TAG, 'Signature changed'); - window.localStorage.setItem(PatcherCache.KEY_SIGNATURE, currentSig.toString()); + window.localStorage.setItem(this.KEY_SIGNATURE, currentSig.toString()); - PatcherCache.clear(); + this.clear(); } else { BxLogger.info(LOG_TAG, 'Signature unchanged'); } } - private static cleanupPatches(patches: PatchArray): PatchArray { + private cleanupPatches(patches: PatchArray): PatchArray { return patches.filter(item => { - for (const id in PatcherCache.CACHE) { - const cached = PatcherCache.CACHE[id]; + for (const id in this.CACHE) { + const cached = this.CACHE[id]; if (cached.includes(item)) { return false; @@ -1288,17 +1292,17 @@ export class PatcherCache { }); } - static getPatches(id: string): PatchArray { - return PatcherCache.CACHE[id]; + getPatches(id: string): PatchArray { + return this.CACHE[id]; } - static saveToCache(subCache: Record) { + saveToCache(subCache: Record) { for (const id in subCache) { const patchNames = subCache[id]; - let data = PatcherCache.CACHE[id]; + let data = this.CACHE[id]; if (!data) { - PatcherCache.CACHE[id] = patchNames; + this.CACHE[id] = patchNames; } else { for (const patchName of patchNames) { if (!data.includes(patchName)) { @@ -1309,20 +1313,20 @@ export class PatcherCache { } // Save to storage - window.localStorage.setItem(PatcherCache.KEY_CACHE, JSON.stringify(PatcherCache.CACHE)); + window.localStorage.setItem(this.KEY_CACHE, JSON.stringify(this.CACHE)); } - static init() { - if (PatcherCache.isInitialized) { + init() { + if (this.isInitialized) { return; } - PatcherCache.isInitialized = true; + this.isInitialized = true; - PatcherCache.checkSignature(); + this.checkSignature(); // Read cache from storage - PatcherCache.CACHE = JSON.parse(window.localStorage.getItem(PatcherCache.KEY_CACHE) || '{}'); - BxLogger.info(LOG_TAG, PatcherCache.CACHE); + this.CACHE = JSON.parse(window.localStorage.getItem(this.KEY_CACHE) || '{}'); + BxLogger.info(LOG_TAG, this.CACHE); if (window.location.pathname.includes('/play/')) { PATCH_ORDERS.push(...PLAYING_PATCH_ORDERS); @@ -1331,8 +1335,8 @@ export class PatcherCache { } // Remove cached patches from PATCH_ORDERS & PLAYING_PATCH_ORDERS - PATCH_ORDERS = PatcherCache.cleanupPatches(PATCH_ORDERS); - PLAYING_PATCH_ORDERS = PatcherCache.cleanupPatches(PLAYING_PATCH_ORDERS); + PATCH_ORDERS = this.cleanupPatches(PATCH_ORDERS); + PLAYING_PATCH_ORDERS = this.cleanupPatches(PLAYING_PATCH_ORDERS); BxLogger.info(LOG_TAG, PATCH_ORDERS.slice(0)); BxLogger.info(LOG_TAG, PLAYING_PATCH_ORDERS.slice(0)); diff --git a/src/modules/ui/dialog/settings-dialog.ts b/src/modules/ui/dialog/settings-dialog.ts index f9473ce..0f365d5 100644 --- a/src/modules/ui/dialog/settings-dialog.ts +++ b/src/modules/ui/dialog/settings-dialog.ts @@ -1034,7 +1034,7 @@ export class SettingsNavigationDialog extends NavigationDialog { private onGlobalSettingChanged(e: Event) { // Clear PatcherCache; - isFullVersion() && PatcherCache.clear(); + isFullVersion() && PatcherCache.getInstance().clear(); this.$btnReload.classList.add('bx-danger');