diff --git a/src/index.ts b/src/index.ts index 2d97a70..a5f6b82 100644 --- a/src/index.ts +++ b/src/index.ts @@ -125,13 +125,13 @@ window.addEventListener('popstate', onHistoryChanged); window.history.pushState = patchHistoryMethod('pushState'); window.history.replaceState = patchHistoryMethod('replaceState'); +window.addEventListener(BxEvent.XCLOUD_SERVERS_UNAVAILABLE, e => { + STATES.supportedRegion = false; + window.setTimeout(watchHeader, 2000); +}); + window.addEventListener(BxEvent.XCLOUD_SERVERS_READY, e => { - // Start rendering UI - if (document.querySelector('div[class^=UnsupportedMarketPage]')) { - window.setTimeout(watchHeader, 2000); - } else { - watchHeader(); - } + watchHeader(); }); window.addEventListener(BxEvent.STREAM_LOADING, e => { diff --git a/src/modules/ui/global-settings.ts b/src/modules/ui/global-settings.ts index 20ab05d..bfaf662 100644 --- a/src/modules/ui/global-settings.ts +++ b/src/modules/ui/global-settings.ts @@ -15,6 +15,7 @@ const SETTINGS_UI = { 'Better xCloud': { items: [ PrefKey.BETTER_XCLOUD_LOCALE, + PrefKey.SERVER_BYPASS_RESTRICTION, PrefKey.REMOTE_PLAY_ENABLED, ], }, @@ -260,9 +261,9 @@ export function setupSettingsUi() { if (setting.experimental) { settingLabel = '🧪 ' + settingLabel; if (!settingNote) { - settingNote = t('experimental') + settingNote = t('experimental'); } else { - settingNote = `${t('experimental')}: ${settingNote}` + settingNote = `${t('experimental')}: ${settingNote}`; } } diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 1afe3a5..5f501a3 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -24,6 +24,8 @@ interface NavigatorBattery extends Navigator { } type BxStates = { + supportedRegion: boolean; + isPlaying: boolean; appContext: any | null; serverRegions: any; diff --git a/src/utils/bx-event.ts b/src/utils/bx-event.ts index 6b5cdad..97f7493 100644 --- a/src/utils/bx-event.ts +++ b/src/utils/bx-event.ts @@ -26,6 +26,7 @@ export enum BxEvent { REMOTE_PLAY_FAILED = 'bx-remote-play-failed', XCLOUD_SERVERS_READY = 'bx-servers-ready', + XCLOUD_SERVERS_UNAVAILABLE = 'bx-servers-unavailable', DATA_CHANNEL_CREATED = 'bx-data-channel-created', diff --git a/src/utils/global.ts b/src/utils/global.ts index 33df313..0a8da91 100644 --- a/src/utils/global.ts +++ b/src/utils/global.ts @@ -13,6 +13,8 @@ const browserHasTouchSupport = 'ontouchstart' in window || navigator.maxTouchPoi const userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport; export const STATES: BxStates = { + supportedRegion: true, + isPlaying: false, appContext: {}, serverRegions: {}, diff --git a/src/utils/preferences.ts b/src/utils/preferences.ts index c08a287..11ad723 100644 --- a/src/utils/preferences.ts +++ b/src/utils/preferences.ts @@ -1,5 +1,5 @@ import { CE } from "@utils/html"; -import { SUPPORTED_LANGUAGES, t } from "@utils/translation"; +import { SUPPORTED_LANGUAGES, t, ut } from "@utils/translation"; import { SettingElement, SettingElementType } from "@utils/settings"; import { UserAgent } from "@utils/user-agent"; import { StreamStat } from "@modules/stream/stream-stats"; @@ -17,6 +17,8 @@ export enum PrefKey { BETTER_XCLOUD_LOCALE = 'bx_locale', SERVER_REGION = 'server_region', + SERVER_BYPASS_RESTRICTION = 'server_bypass_restriction', + PREFER_IPV6_SERVER = 'prefer_ipv6_server', STREAM_TARGET_RESOLUTION = 'stream_target_resolution', STREAM_PREFERRED_LOCALE = 'stream_preferred_locale', @@ -122,6 +124,12 @@ export class Preferences { label: t('region'), default: 'default', }, + [PrefKey.SERVER_BYPASS_RESTRICTION]: { + label: ut('Bypass region restriction'), + note: ut('⚠️ Use this at your own risk'), + default: false, + }, + [PrefKey.STREAM_PREFERRED_LOCALE]: { label: t('preferred-game-language'), default: 'default', diff --git a/src/utils/xcloud-interceptor.ts b/src/utils/xcloud-interceptor.ts index ad8bd24..557769d 100644 --- a/src/utils/xcloud-interceptor.ts +++ b/src/utils/xcloud-interceptor.ts @@ -12,7 +12,17 @@ import { getPreferredServerRegion } from "./region"; export class XcloudInterceptor { static async #handleLogin(request: RequestInfo | URL, init?: RequestInit) { + if (getPref(PrefKey.SERVER_BYPASS_RESTRICTION)) { + (request as Request).headers.set('X-Forwarded-For', '9.9.9.9'); + } + const response = await NATIVE_FETCH(request, init); + if (response.status !== 200) { + // Unsupported region + BxEvent.dispatch(window, BxEvent.XCLOUD_SERVERS_UNAVAILABLE); + return response; + } + const obj = await response.clone().json(); // Preload Remote Play