返回首頁 

Xbox CLoud Gaming优化整合

脚本免费!谨防上当受骗!整合和修改现有脚本,优化项详见脚本说明。【若你有好的想法或者BUG可以进xbox云游戏QQ交流1群531602832,2群313340764,3群826510890,4群82737876反馈】


Install this script?
Author's suggested script

You may also like Xbox Cloud Gaming Vibration.


Install this script
// ==UserScript==// @name                 Xbox CLoud Gaming优化整合// @name:zh-CN           Xbox CLoud Gaming优化整合// @namespace            http://tampermonkey.net/xbox/nft// @version              3.10.3.3// @author               奈非天// @license              MIT// @match                https://www.xbox.com/*/*play*// @run-at               document-start// @grant                none// @require              https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.4.1/jquery.min.js// @description:zh-cn    脚本免费!谨防上当受骗!整合和修改现有脚本,优化项详见脚本说明。【若你有好的想法或者BUG可以进xbox云游戏QQ交流1群531602832,2群313340764,3群826510890,4群82737876反馈】// @description          脚本免费!谨防上当受骗!整合和修改现有脚本,优化项详见脚本说明。【若你有好的想法或者BUG可以进xbox云游戏QQ交流1群531602832,2群313340764,3群826510890,4群82737876反馈】// ==/UserScript==(function () {'use strict';// Your code here...//★★★★★★★★★★★★★★★★★★★★Reference Project License Agreement Begin 参考项目许可协议开始★★★★★★★★★★★★★★★★★★★★///*  better-xcloud MIT LicenseCopyright (c) 2023 redphxPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE.*///★★★★★★★★★★★★★★★★★★★★Reference Project License Agreement End 参考项目许可协议结束★★★★★★★★★★★★★★★★★★★★//let nftxboxversion = 'v3.10.3.3';let naifeitian = {isType(obj) {return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();},getValue(key) {try {return JSON.parse(localStorage.getItem(key));} catch (e) {return localStorage.getItem(key);}},setValue(key, value) {if (this.isType(value) === 'object' || this.isType(value) === 'array' || this.isType(value) === 'boolean') {return localStorage.setItem(key, JSON.stringify(value));}return localStorage.setItem(key, value);},isValidIP(ip) {let reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/return reg.test(ip);},isNumber(val) {return !isNaN(parseFloat(val)) && isFinite(val);},toElement(key, onChange) {const CE = createElement;const setting = key;const currentValue = key['default'] == undefined ? key : key['default'];let $control;if (setting['options'] != undefined) {$control = CE('select', { id: 'xcloud_setting_' + key['name'] });for (let value in setting.options) {const label = setting.options[value];const $option = CE('option', { value: value }, label);$control.appendChild($option);}$control.value = currentValue;$control.addEventListener('change', e => {key['default'] = e.target.value;this.setValue(key['name'], key);onChange && onChange(e);});} else if (typeof setting.default === 'number') {$control = CE('input', { 'type': 'number', 'min': setting.min, 'max': setting.max });$control.value = currentValue;$control.addEventListener('change', e => {let value = Math.max(setting.min, Math.min(setting.max, parseInt(e.target.value)));e.target.value = value;key['default'] = e.target.valuethis.setValue(key['name'], key);onChange && onChange(e);});} else {if (key.fps == undefined) {$control = CE('input', { 'type': 'checkbox' });$control.checked = currentValue;$control.addEventListener('change', e => {key['default'] = e.target.checked;NFTconfig[key['name'].slice(0, -2)]['default'] = e.target.checked;this.setValue(key['name'], key);if (key['name'] == 'STATS_SLIDE_OPENGM' && e.target.checked) {if (this.getValue('STATS_SHOW_WHEN_PLAYINGGM')['default']) {$('#xcloud_setting_STATS_SHOW_WHEN_PLAYINGGM').click();}} else if (key['name'] == 'STATS_SHOW_WHEN_PLAYINGGM' && e.target.checked) {if (this.getValue('STATS_SLIDE_OPENGM')['default']) {$('#xcloud_setting_STATS_SLIDE_OPENGM').click();}}onChange && onChange(e);});} else {let stats_info_sortedEntries = Object.entries(NFTconfig['stats_info']).sort((a, b) => a[1][1] - b[1][1]);//流统计信息$control = CE('div', { 'class': 'stats-container' });stats_info_sortedEntries.forEach(entry => {//entry[1][0]     是否选中//entry[1][1]     顺序//entry[1][2]     名字let divElement = document.createElement('div');divElement.className = `drag-handle ${entry[1][0] === true ? 'stats-selected' : 'stats-delete'}`;divElement.draggable = "true";divElement.dataset.name = entry[0];divElement.dataset.index = entry[1][1];divElement.textContent = entry[1][2];let dragIndicator = document.createElement('div');dragIndicator.className = "drag-indicator";divElement.appendChild(dragIndicator);$control.appendChild(divElement);});let placeholder = document.createElement('div');placeholder.className = "placeholder drag-handle";$control.appendChild(placeholder);}}$control.id = `xcloud_setting_${key.name}`;return $control;},isSafari() {let userAgent = userAgentOriginal.toLowerCase();if (userAgent.indexOf('safari') !== -1 && userAgent.indexOf('chrome') === -1) {return true;} else {return false;}},getGM(defaultValue, n) {let newval = this.getValue(n) == null ? defaultValue : this.getValue(n);if (newval?.options != undefined) {newval.options = defaultValue.options;}naifeitian.setValue(n, newval);return newval;},showSetting() {$('#settingsBackgroud').css('display', '');$('body').css('overflow', 'hidden');},hideSetting() {$('#settingsBackgroud').css('display', 'none');$('body').css('overflow', 'visible');},patchFunctionBind() {const nativeBind = Function.prototype.bind;Function.prototype.bind = function () {let valid = false;if (this.name.length <= 2 && arguments.length === 2 && arguments[0] === null) {if (arguments[1] === 0 || (typeof arguments[1] === 'function')) {valid = true;}}if (!valid) {return nativeBind.apply(this, arguments);}if (typeof arguments[1] === 'function') {console.log('还原 Function.prototype.bind()');Function.prototype.bind = nativeBind;}const orgFunc = this;const newFunc = (a, item) => {if (NFTconfig['PATCH_ORDERS'].length === 0) {orgFunc(a, item);return;}naifeitian.patch(item);orgFunc(a, item);}return nativeBind.apply(newFunc, arguments);};},patch(item) {// console.log('patch', '-----');let patchName;let appliedPatches;for (let id in item[1]) {if (NFTconfig['PATCH_ORDERS'].length <= 0) {return;}appliedPatches = [];const func = item[1][id];let funcStr = func.toString();for (let groupIndex = 0; groupIndex < NFTconfig['PATCH_ORDERS'].length; groupIndex++) {const group = NFTconfig['PATCH_ORDERS'][groupIndex];let modified = false;for (let patchIndex = 0; patchIndex < group.length; patchIndex++) {const patchName = group[patchIndex];if (appliedPatches.indexOf(patchName) > -1) {continue;}const patchedFuncStr = naifeitian.handle_remote_patch(patchName, funcStr);if (!patchedFuncStr) {// Only stop if the first patch is failedif (patchIndex === 0) {break;} else {continue;}}modified = true;funcStr = patchedFuncStr;console.log(`应用 "${patchName}" 修补`);appliedPatches.push(patchName);// Remove patch from groupgroup.splice(patchIndex, 1);patchIndex--;}// Apply patched functionsif (modified) {item[1][id] = eval(funcStr);}// Remove empty groupif (!group.length) {NFTconfig['PATCH_ORDERS'].splice(groupIndex, 1);groupIndex--;}}}},handle_remote_patch(name, funcStr) {//根据不同的字符串执行不同的方法if (name == 'remotePlayConnectMode') {const text = 'connectMode:"cloud-connect"';if (!funcStr.includes(text)) {return false;}return funcStr.replace(text, `connectMode:window.BX_REMOTE_PLAY_CONFIG?"xhome-connect":"cloud-connect",remotePlayServerId:(window.BX_REMOTE_PLAY_CONFIG&&window.BX_REMOTE_PLAY_CONFIG.serverId)||''`);} else if (name == 'remotePlayDirectConnectUrl') {const index = funcStr.indexOf('/direct-connect');if (index === -1) {return false;}return funcStr.replace(funcStr.substring(index - 9, index + 15), 'https://www.xbox.com/play');} else if (name == 'remotePlayKeepAlive') {if (!funcStr.includes('onServerDisconnectMessage(e){')) {return false;}funcStr = funcStr.replace('onServerDisconnectMessage(e){', `onServerDisconnectMessage (e) {const msg = JSON.parse(e);if (msg.reason === 'WarningForBeingIdle') {try {this.sendKeepAlive();return;} catch (ex) {}}`);return funcStr;} else if (name == 'EnableStreamGate') {const index = funcStr.indexOf(',EnableStreamGate:');if (index === -1) {return false;}// Find the next "},"const endIndex = funcStr.indexOf('},', index);const newCode = `EnableStreamGate: false,PwaPrompt: false,`;funcStr = funcStr.substring(0, endIndex) + ',' + newCode + funcStr.substring(endIndex);return funcStr;} else if (name == 'remotePlayGuideWorkaround') {const text = 'nexusButtonHandler:this.featureGates.EnableClientGuideInStream';if (!funcStr.includes(text)) {return false;}return funcStr.replace(text, `nexusButtonHandler: !window.BX_REMOTE_PLAY_CONFIG && this.featureGates.EnableClientGuideInStream`);} else if (name == 'patchStreamHud') {const text = 'let{onCollapse';if (!funcStr.includes(text)) {return false;}// 恢复悬浮窗 "..." 按钮funcStr = funcStr.replace(text, 'e.guideUI = null;' + text);return funcStr;} else if (name == "loadingEndingChunks") {// Add patches that are only needed when start playingconst text = 'Symbol("ChatSocketPlugin")';if (!funcStr.includes(text)) {return false;}NFTconfig['PATCH_ORDERS'] = NFTconfig['PATCH_ORDERS'].concat(NFTconfig['PLAYING_PATCH_ORDERS']);return funcStr;}},isDivTopOrBottomOutOfBounds(divElement) {const $div = $(divElement);$div.css("height","")// 获取div的边界信息const divRect = $div[0].getBoundingClientRect();const divTop = divRect.top;const divBottom = divRect.bottom;const viewportHeight = window.innerHeight || document.documentElement.clientHeight;return (divBottom > viewportHeight ||divTop < 0);}}//★★ 1=开   0=关 ★★//let default_language_list = { '智能简繁': 'Auto', '简体': 'zh-CN', '繁体': 'zh-TW' }let NFTconfig ={enableRemotePlay: 0,PATCH_ORDERS: [],PLAYING_PATCH_ORDERS: [],no_need_###_play: 1,regionBlock: {blockIp: '美服',options: {'韩服': '168.126.63.1','美服': '4.2.2.2','日服': '210.131.113.123'}},chooseLanguage: 1,IfErrUsedefaultGameLanguage: 'zh-CN',high_bitrate: 1,disableCheckNetwork: 1,IPv6: 0,autoFullScreen: 0,blockXcloudServer: 0,blockXcloudServerList: ['AustraliaEast', 'AustraliaSouthEast', 'BrazilSouth', 'EastUS', 'EastUS2', 'JapanEast', 'KoreaCentral', 'NorthCentralUs', 'SouthCentralUS', 'UKSouth', 'WestEurope', 'WestUS', 'WestUS2'],defaultXcloudServer: 'KoreaCentral',video_stretch: {default: 'none',options: {none: '无',fill: '填充',setting: '微调'},name: 'video_stretchGM'},rtcCodecPreferences: {default: '自动',options: ['默认','自动']},video_stretch_x_y: {x: 0,y: 0,name: 'video_stretch_x_yGM'},noPopSetting: 0,disableTouchControls: 0,autoOpenOC: 1,autoShowTouch: true,STATS_SHOW_WHEN_PLAYING: {default: false,name: 'STATS_SHOW_WHEN_PLAYINGGM'},STATS_POSITION: {default: 'top-left',options: {'top-left': '上左','top-center': '上中','top-right': '上右'},name: 'STATS_POSITIONGM'},STATS_TRANSPARENT: {default: false,name: 'STATS_TRANSPARENTGM'},STATS_OPACITY: {default: 80,min: 10,max: 100,name: 'STATS_OPACITYGM'},STATS_TEXT_SIZE: {default: '0.9rem',options: {'0.9rem': '小','1.0rem': '中','1.1rem': '大'},name: 'STATS_TEXT_SIZEGM'},STATS_CONDITIONAL_FORMATTING: {default: false,name: 'STATS_CONDITIONAL_FORMATTINGGM'},STATS_SLIDE_OPEN: {default: false,name: 'STATS_SLIDE_OPENGM'},VIDEO_CLARITY: {default: 0,min: 0,max: 3,name: 'VIDEO_CLARITYGM'},VIDEO_CONTRAST: {default: 100,min: 0,max: 150,name: 'VIDEO_CONTRASTGM'},VIDEO_SATURATION: {default: 100,min: 0,max: 150,name: 'VIDEO_SATURATIONGM'},VIDEO_BRIGHTNESS: {default: 100,min: 0,max: 150,name: 'VIDEO_BRIGHTNESSGM'},antiKick: 0,useCustomfakeIp: 0,customfakeIp: '',xcloud_game_language: default_language_list['简体'],REMOTE_PLAY_RESOLUTION: {'default': '1080p','options': {'1080p': '1080p','720p': '720p',},'name': 'REMOTE_PLAY_RESOLUTIONGM'},REMOTE_SERVER_LIST: ['eau', 'seau', 'brs', 'eus', 'eus2', 'ejp', 'ckr', 'mxc', 'ncus', 'scus', 'uks', 'weu', 'wus', 'wus2'],stats_info: {fps: [true, 1, "帧率"],rtt: [true, 2, "延迟"],dt: [true, 3, "解码"],br: [true, 4, "码率"],pl: [true, 5, "丢包"],fl: [true, 6, "丢帧"],}}const integratekeys = Object.keys(NFTconfig);integratekeys.forEach(key => {NFTconfig[key] = naifeitian.getGM(NFTconfig[key], key + 'GM');});NFTconfig['PATCH_ORDERS'] = [NFTconfig['enableRemotePlay'] == 1 && ['remotePlayKeepAlive'],NFTconfig['enableRemotePlay'] == 1 && ['remotePlayDirectConnectUrl'],];NFTconfig['PATCH_ORDERS'] = [NFTconfig['enableRemotePlay'] == 1 && ['remotePlayConnectMode'],NFTconfig['enableRemotePlay'] == 1 && ['remotePlayGuideWorkaround'],['patchStreamHud'],['EnableStreamGate']]let regionsMenuItemList = [];let languageMenuItemList = [];let crturl = "";let canShowOC = null;let letmeOb = true;let checkIpsuc = false;let STREAM_WEBRTC;const ICON_VIDEO_SETTINGS = '<path d="M16 9.144A6.89 6.89 0 0 0 9.144 16 6.89 6.89 0 0 0 16 22.856 6.89 6.89 0 0 0 22.856 16 6.9 6.9 0 0 0 16 9.144zm0 11.427c-2.507 0-4.571-2.064-4.571-4.571s2.064-4.571 4.571-4.571 4.571 2.064 4.571 4.571-2.064 4.571-4.571 4.571zm15.704-7.541c-.065-.326-.267-.607-.556-.771l-4.26-2.428-.017-4.802c-.001-.335-.15-.652-.405-.868-1.546-1.307-3.325-2.309-5.245-2.953-.306-.103-.641-.073-.923.085L16 3.694l-4.302-2.407c-.282-.158-.618-.189-.924-.086a16.02 16.02 0 0 0-5.239 2.964 1.14 1.14 0 0 0-.403.867L5.109 9.84.848 12.268a1.14 1.14 0 0 0-.555.771 15.22 15.22 0 0 0 0 5.936c.064.326.267.607.555.771l4.261 2.428.017 4.802c.001.335.149.652.403.868 1.546 1.307 3.326 2.309 5.245 2.953.306.103.641.073.923-.085L16 28.306l4.302 2.407a1.13 1.13 0 0 0 .558.143 1.18 1.18 0 0 0 .367-.059c1.917-.648 3.695-1.652 5.239-2.962.255-.216.402-.532.405-.866l.021-4.807 4.261-2.428a1.14 1.14 0 0 0 .555-.771 15.21 15.21 0 0 0-.003-5.931zm-2.143 4.987l-4.082 2.321a1.15 1.15 0 0 0-.429.429l-.258.438a1.13 1.13 0 0 0-.174.601l-.022 4.606a13.71 13.71 0 0 1-3.623 2.043l-4.117-2.295a1.15 1.15 0 0 0-.559-.143h-.546c-.205-.005-.407.045-.586.143l-4.119 2.3a13.74 13.74 0 0 1-3.634-2.033l-.016-4.599a1.14 1.14 0 0 0-.174-.603l-.257-.437c-.102-.182-.249-.333-.429-.437l-4.085-2.328a12.92 12.92 0 0 1 0-4.036l4.074-2.325a1.15 1.15 0 0 0 .429-.429l.258-.438a1.14 1.14 0 0 0 .175-.601l.021-4.606a13.7 13.7 0 0 1 3.625-2.043l4.11 2.295a1.14 1.14 0 0 0 .585.143h.52c.205.005.407-.045.586-.143l4.119-2.3a13.74 13.74 0 0 1 3.634 2.033l.016 4.599a1.14 1.14 0 0 0 .174.603l.257.437c.102.182.249.333.429.438l4.085 2.327a12.88 12.88 0 0 1 .007 4.041h.007z" fill-rule="nonzero"/>';//视频调整const ICON_HD_VIDEO_SETTINGS = '<g transform="matrix(.142357 0 0 .142357 -2.22021 -2.22164)" fill="none" stroke="#fff" stroke-width="16"><circle cx="128" cy="128" r="40"/><path d="M130.05 206.11h-4L94 224c-12.477-4.197-24.049-10.711-34.11-19.2l-.12-36c-.71-1.12-1.38-2.25-2-3.41L25.9 147.24a99.16 99.16 0 0 1 0-38.46l31.84-18.1c.65-1.15 1.32-2.29 2-3.41l.16-36C69.951 42.757 81.521 36.218 94 32l32 17.89h4L162 32c12.477 4.197 24.049 10.711 34.11 19.2l.12 36c.71 1.12 1.38 2.25 2 3.41l31.85 18.14a99.16 99.16 0 0 1 0 38.46l-31.84 18.1c-.65 1.15-1.32 2.29-2 3.41l-.16 36A104.59 104.59 0 0 1 162 224l-31.95-17.89z"/></g>';//流监控const ICON_HD_STREAM_STATS = '<g transform="scale(2)" class="ICON_HD_STREAM_STATS_OFF" style="display:block"><path d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7 7 0 0 0-2.79.588l.77.771A6 6 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13 13 0 0 1 14.828 8q-.086.13-.195.288c-.335.48-.83 1.12-1.465 1.755q-.247.248-.517.486z"></path><path d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829"></path><path d="M3.35 5.47q-.27.24-.518.487A13 13 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7 7 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709zm10.296 8.884-12-12 .708-.708 12 12z"></path></g><g transform="scale(2)" class="ICON_HD_STREAM_STATS_ON" style="display:none"><path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8M1.173 8a13 13 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5s3.879 1.168 5.168 2.457A13 13 0 0 1 14.828 8q-.086.13-.195.288c-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5s-3.879-1.168-5.168-2.457A13 13 0 0 1 1.172 8z"/><path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5M4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0"/></g>';// Quickly create a tree of elements without having to use innerHTMLfunction createElement(elmName, props = {}) {let $elm;const hasNs = 'xmlns' in props;if (hasNs) {$elm = document.createElementNS(props.xmlns, elmName);} else {$elm = document.createElement(elmName);}for (let key in props) {if (key === 'xmlns') {continue;}if (!props.hasOwnProperty(key) || $elm.hasOwnProperty(key)) {continue;}if (hasNs) {$elm.setAttributeNS(null, key, props[key]);} else {$elm.setAttribute(key, props[key]);}}for (let i = 2, size = arguments.length; i < size; i++) {const arg = arguments[i];const argType = typeof arg;if (argType === 'string' || argType === 'number') {$elm.textContent = arg;} else if (arg) {$elm.appendChild(arg);}}return $elm;}function setMachineFullScreen() {try {let element = document.documentElement;if (element.requestFullscreen) {element.requestFullscreen();} else if (element.mozRequestFullScreen) {element.mozRequestFullScreen();} else if (element.msRequestFullscreen) {element.msRequestFullscreen();} else if (element.webkitRequestFullscreen) {element.webkitRequestFullScreen();}screen?.orientation?.lock("landscape");} catch (e) {}}function exitMachineFullscreen() {try {screen?.orientation?.unlock();if (document.exitFullScreen) {document.exitFullScreen();} else if (document.mozCancelFullScreen) {document.mozCancelFullScreen();} else if (document.webkitExitFullscreen) {document.webkitExitFullscreen();} else if (element.msExitFullscreen) {element.msExitFullscreen();}} catch (e) {}}function exitGame() {canShowOC = null;setTimeout(RemotePlay.detect, 10);document.documentElement.style.overflowY = "";StreamStats.hideSettingsUi();letmeOb = true;StreamStats.stop();bindmslogoevent();$('.better-xcloud-quick-settings-bar').css("display", "none");if (NFTconfig['autoFullScreen'] == 1) {exitMachineFullscreen();}if (NFTconfig['noPopSetting'] == 0) {$('#popSetting').css('display', 'block');}}function inGame() {if (!IS_REMOTE_PLAYING) {let path = window.location.pathname;history.pushState({}, null, window.location.pathname.substr(0, window.location.pathname.indexOf("/launch/")));history.pushState({}, null, path);}document.documentElement.style.overflowY = "hidden";document.body.style.top = '0px';if (NFTconfig['autoFullScreen'] == 1) {setMachineFullScreen();}if (NFTconfig['noPopSetting'] == 0) {$('#popSetting').css('display', 'none');}}class StreamBadges {static get BADGE_PLAYTIME() { return '游玩时间'; };static get BADGE_BATTERY() { return '电量'; };static get BADGE_IN() { return '下载'; };static get BADGE_OUT() { return '上传'; };static get BADGE_SERVER() { return '服务器'; };static get BADGE_VIDEO() { return '编解码器'; };static get BADGE_AUDIO() { return '音频'; };static get BADGE_BREAK() { return 'break'; };static ipv6 = false;static resolution = null;static video = null;static audio = null;static fps = 0;static region = '';static startBatteryLevel = 100;static startTimestamp = 0;static #cachedDoms = {};static #interval;static get #REFRESH_INTERVAL() { return 3000; };static #renderBadge(name, value, color) {const CE = createElement;if (name === StreamBadges.BADGE_BREAK) {return CE('div', { 'style': 'display: block' });}let $badge;if (StreamBadges.#cachedDoms[name]) {$badge = StreamBadges.#cachedDoms[name];$badge.lastElementChild.textContent = value;return $badge;}$badge = CE('div', { 'class': 'better-xcloud-badge' },CE('span', { 'class': 'better-xcloud-badge-name' }, name),CE('span', { 'class': 'better-xcloud-badge-value', 'style': `background-color: ${color}` }, value));if (name === StreamBadges.BADGE_BATTERY) {$badge.classList.add('better-xcloud-badge-battery');}StreamBadges.#cachedDoms[name] = $badge;return $badge;}static async #updateBadges(forceUpdate) {if (!forceUpdate && !document.querySelector('.better-xcloud-badges')) {StreamBadges.#stop();return;}// 游玩时间let now = +new Date;const diffSeconds = Math.ceil((now - StreamBadges.startTimestamp) / 1000);const playtime = StreamBadges.#secondsToHm(diffSeconds);// 电量let batteryLevel = '100%';let batteryLevelInt = 100;let isCharging = false;if (navigator.getBattery) {try {const bm = await navigator.getBattery();isCharging = bm.charging;batteryLevelInt = Math.round(bm.level * 100);batteryLevel = `${batteryLevelInt}%`;if (batteryLevelInt != StreamBadges.startBatteryLevel) {const diffLevel = Math.round(batteryLevelInt - StreamBadges.startBatteryLevel);const sign = diffLevel > 0 ? '+' : '';batteryLevel += ` (${sign}${diffLevel}%)`;}} catch (e) { }}const stats = await STREAM_WEBRTC.getStats();let totalIn = 0;let totalOut = 0;stats.forEach(stat => {if (stat.type === 'candidate-pair' && stat.state == 'succeeded') {totalIn += stat.bytesReceived;totalOut += stat.bytesSent;}});const badges = {[StreamBadges.BADGE_IN]: totalIn ? StreamBadges.#humanFileSize(totalIn) : null,[StreamBadges.BADGE_OUT]: totalOut ? StreamBadges.#humanFileSize(totalOut) : null,[StreamBadges.BADGE_PLAYTIME]: playtime,[StreamBadges.BADGE_BATTERY]: batteryLevel,};for (let name in badges) {const value = badges[name];if (value === null) {continue;}const $elm = StreamBadges.#cachedDoms[name];$elm && ($elm.lastElementChild.textContent = value);if (name === StreamBadges.BADGE_BATTERY) {// Show charging status$elm.setAttribute('data-charging', isCharging);if (StreamBadges.startBatteryLevel === 100 && batteryLevelInt === 100) {$elm.style.display = 'none';} else {$elm.style = '';}}}}static #stop() {StreamBadges.#interval && clearInterval(StreamBadges.#interval);StreamBadges.#interval = null;}static #secondsToHm(seconds) {const h = Math.floor(seconds / 3600);const m = Math.floor(seconds % 3600 / 60) + 1;const hDisplay = h > 0 ? `${h}小时` : '';const mDisplay = m > 0 ? `${m}分钟` : '';return hDisplay + mDisplay;}// https://stackoverflow.com/a/20732091static #humanFileSize(size) {let i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(####));return (size / Math.pow(####, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];}static async render() {// Videolet video = '';if (StreamBadges.resolution) {video = `${StreamBadges.resolution.height}p`;}if (StreamBadges.video) {video && (video += '/');video += StreamBadges.video.codec;if (StreamBadges.video.profile) {let profile = StreamBadges.video.profile;profile = profile.startsWith('4d') ? '高' : (profile.startsWith('42e') ? '中' : '低');video += ` (${profile})`;}}// 音频let audio;if (StreamBadges.audio) {audio = StreamBadges.audio.codec;const bitrate = StreamBadges.audio.bitrate / 1000;audio += ` (${bitrate} kHz)`;}// 电量let batteryLevel = '';if (navigator.getBattery) {batteryLevel = '100%';}// Server + Regionlet server = StreamBadges.region;server += '@' + (StreamBadges.ipv6 ? 'IPv6' : 'IPv4');const BADGES = [[StreamBadges.BADGE_PLAYTIME, '1m', '#ff004d'],[StreamBadges.BADGE_BATTERY, batteryLevel, '#00b543'],[StreamBadges.BADGE_IN, StreamBadges.#humanFileSize(0), '#29adff'],[StreamBadges.BADGE_OUT, StreamBadges.#humanFileSize(0), '#ff77a8'],[StreamBadges.BADGE_BREAK],[StreamBadges.BADGE_SERVER, server, '#ff6c24'],video ? [StreamBadges.BADGE_VIDEO, video, '#742f29'] : null,audio ? [StreamBadges.BADGE_AUDIO, audio, '#5f574f'] : null,];const $wrapper = createElement('div', { 'class': 'better-xcloud-badges' });BADGES.forEach(item => item && $wrapper.appendChild(StreamBadges.#renderBadge(...item)));await StreamBadges.#updateBadges(true);StreamBadges.#stop();StreamBadges.#interval = setInterval(StreamBadges.#updateBadges, StreamBadges.#REFRESH_INTERVAL);return $wrapper;}}class StreamStats {static #interval;static #updateInterval = 1000;static #$container;static #$fps;static #$rtt;static #$dt;static #$pl;static #$fl;static #$br;static #$settings;static #lastStat;static status() {return StreamStats.#interval != null;}static start() {clearInterval(StreamStats.#interval);StreamStats.#$container.classList.remove('better-xcloud-gone');StreamStats.#interval = setInterval(StreamStats.update, StreamStats.#updateInterval);$('#xcloud_setting_STATS_BUTTON').text("关闭监控");$('.ICON_HD_STREAM_STATS_ON').css("display", 'block');$('.ICON_HD_STREAM_STATS_OFF').css("display", 'none');}static stop() {clearInterval(StreamStats.#interval);StreamStats.#$container.classList.add('better-xcloud-gone');StreamStats.#interval = null;StreamStats.#lastStat = null;$('#xcloud_setting_STATS_BUTTON').text("启动监控");$('.ICON_HD_STREAM_STATS_ON').css("display", 'none');$('.ICON_HD_STREAM_STATS_OFF').css("display", 'block');}static toggle() {StreamStats.#isHidden() ? StreamStats.start() : StreamStats.stop();screenClicktohide();if (naifeitian.isDivTopOrBottomOutOfBounds(".better-xcloud-stats-settings")) {$(".better-xcloud-stats-settings").css("height", "90%");} else {$(".better-xcloud-stats-settings").css("height", "");}}static #isHidden = () => StreamStats.#$container.classList.contains('better-xcloud-gone');static update() {if (StreamStats.#isHidden() || !STREAM_WEBRTC) {StreamStats.stop();return;}try {STREAM_WEBRTC.getStats().then(stats => {stats.forEach(stat => {let grade = '';if (stat.type === 'inbound-rtp' && stat.kind === 'video') {// FPS$(".stats_fps span").text(stat.framesPerSecond || 0);// Packets Lostconst packetsLost = stat.packetsLost;if (packetsLost != undefined) {const packetsReceived = stat.packetsReceived;const packetsLostPercentage = (packetsLost * 100 / ((packetsLost + packetsReceived) || 1)).toFixed(2);$(".stats_pl span").text(`${packetsLost} (${packetsLostPercentage}%)`);} else {$(".stats_pl span").text(`-1 (-1%)`);}// Frames Droppedconst framesDropped = stat.framesDropped;if (framesDropped != undefined) {const framesReceived = stat.framesReceived;const framesDroppedPercentage = (framesDropped * 100 / ((framesDropped + framesReceived) || 1)).toFixed(2);$(".stats_fl span").text(`${framesDropped} (${framesDroppedPercentage}%)`);} else {$(".stats_fl span").text(`-1 (-1%)`);}if (StreamStats.#lastStat) {const lastStat = StreamStats.#lastStat;// Bitrateconst timeDiff = stat.timestamp - lastStat.timestamp;const bitrate = 8 * (stat.bytesReceived - lastStat.bytesReceived) / timeDiff / 1000;$(".stats_br span").text(`${bitrate.toFixed(2)} Mbps`);// Decode timeconst totalDecodeTimeDiff = stat.totalDecodeTime - lastStat.totalDecodeTime;const framesDecodedDiff = stat.framesDecoded - lastStat.framesDecoded;const currentDecodeTime = totalDecodeTimeDiff / framesDecodedDiff * 1000;$(".stats_dt span").text(`${currentDecodeTime.toFixed(2)}ms`);if (NFTconfig['STATS_CONDITIONAL_FORMATTING']['default']) {grade = (currentDecodeTime > 12) ? 'bad' : (currentDecodeTime > 9) ? 'ok' : (currentDecodeTime > 6) ? 'good' : '';}$(".stats_dt span").attr('data-grade', grade);}StreamStats.#lastStat = stat;} else if (stat.type === 'candidate-pair' && stat.state === 'succeeded') {// Round Trip Timeconst roundTripTime = typeof stat.currentRoundTripTime !== 'undefined' ? stat.currentRoundTripTime * 1000 : '???';$(".stats_rtt span").text(`${roundTripTime}ms`);if (NFTconfig['STATS_CONDITIONAL_FORMATTING']['default']) {grade = (roundTripTime > 100) ? 'bad' : (roundTripTime > 75) ? 'ok' : (roundTripTime > 40) ? 'good' : '';}$(".stats_rtt span").attr('data-grade', grade);}});});} catch (e) { }}static #refreshStyles() {const PREF_POSITION = NFTconfig['STATS_POSITION']['default'];const PREF_TRANSPARENT = NFTconfig['STATS_TRANSPARENT']['default'];const PREF_OPACITY = NFTconfig['STATS_OPACITY']['default'];const PREF_TEXT_SIZE = NFTconfig['STATS_TEXT_SIZE']['default'];StreamStats.#$container.setAttribute('data-position', PREF_POSITION);StreamStats.#$container.setAttribute('data-transparent', PREF_TRANSPARENT);StreamStats.#$container.style.opacity = PREF_OPACITY + '%';StreamStats.#$container.style.fontSize = PREF_TEXT_SIZE;}static hideSettingsUi() {StreamStats.#$settings.style.display = 'none';}static toggleSettingsUi() {const display = StreamStats.#$settings.style.display;StreamStats.#$settings.style.display = display === 'block' ? 'none' : 'block';screenClicktohide();if (naifeitian.isDivTopOrBottomOutOfBounds(".better-xcloud-stats-settings")) {$(".better-xcloud-stats-settings").css("height", "90%");} else {$(".better-xcloud-stats-settings").css("height", "");}}static render() {if (StreamStats.#$container) {return;}const CE = createElement;StreamStats.#$container = CE('div', { 'class': 'better-xcloud-stats-bar better-xcloud-gone' },CE('div', { 'class': 'stats_fps' }, CE('label', {}, '帧率'),StreamStats.#$fps = CE('span', {}, 0)),CE('div', { 'class': 'stats_rtt' }, CE('label', {}, '延迟'),StreamStats.#$rtt = CE('span', {}, '0ms')),CE('div', { 'class': 'stats_dt' }, CE('label', {}, '解码'),StreamStats.#$dt = CE('span', {}, '0ms')),CE('div', { 'class': 'stats_br' }, CE('label', {}, '码率'),StreamStats.#$br = CE('span', {}, '0ms')),CE('div', { 'class': 'stats_pl' }, CE('label', {}, '丢包'),StreamStats.#$pl = CE('span', {}, '0ms')),CE('div', { 'class': 'stats_fl' }, CE('label', {}, '丢帧'),StreamStats.#$fl = CE('span', {}, '0ms')));let clicked_count = 0;StreamStats.#$container.addEventListener('ontouchstart' in document ? 'touchstart' : 'mousedown', function (e) {clicked_count++;setTimeout(function () {clicked_count = 0;}, 500);if (clicked_count > 1) {//双击StreamStats.toggleSettingsUi();clicked_count = 0;}}, false);document.documentElement.appendChild(StreamStats.#$container);const refreshFunc = e => {StreamStats.#refreshStyles()};const $position = naifeitian.toElement(NFTconfig['STATS_POSITION'], refreshFunc);let $open_button;const $showStartup = naifeitian.toElement(NFTconfig['STATS_SHOW_WHEN_PLAYING'], refreshFunc);const $transparent = naifeitian.toElement(NFTconfig['STATS_TRANSPARENT'], refreshFunc);const $formatting = naifeitian.toElement(NFTconfig['STATS_CONDITIONAL_FORMATTING'], refreshFunc);const $opacity = naifeitian.toElement(NFTconfig['STATS_OPACITY'], refreshFunc);const $textSize = naifeitian.toElement(NFTconfig['STATS_TEXT_SIZE'], refreshFunc);const $slideopen = naifeitian.toElement(NFTconfig['STATS_SLIDE_OPEN'], refreshFunc);const $stats_info = naifeitian.toElement(NFTconfig['stats_info'], refreshFunc);StreamStats.#$settings = CE('div', { 'class': 'better-xcloud-stats-settings' },CE('b', {}, '流监控设置'),CE('div', {},CE('label', { 'for': `xcloud_setting_NFTconfig['STATS_SHOW_WHEN_PLAYING']` }, '自启动'),$showStartup),CE('div', {},CE('label', {}, '位置'),$position),CE('div', {},CE('label', {}, '统计信息'),$stats_info),CE('div', {},CE('label', {}, '字体大小'),$textSize),CE('div', {},CE('label', { 'for': `xcloud_setting_STATS_OPACITY` }, '透明度 (10-100%)'),$opacity),CE('div', {},CE('label', { 'for': `xcloud_setting_STATS_TRANSPARENT` }, '背景透明'),$transparent),CE('div', {},CE('label', { 'for': `xcloud_setting_STATS_CONDITIONAL_FORMATTING` }, '数值颜色'),$formatting),CE('div', {},CE('label', { 'for': `xcloud_setting_STATS_SLIDE_OPEN` }, '仅悬浮窗展开时打开'),$slideopen),$open_button = CE('button', { 'id': 'xcloud_setting_STATS_BUTTON' }, '启动监控'));$open_button.addEventListener('click', () => {if (StreamStats.status()) {//需关闭StreamStats.stop();} else {//需启动StreamStats.start();}});document.documentElement.appendChild(StreamStats.#$settings);let stats_info_sortedEntries = Object.entries(NFTconfig['stats_info']).sort((a, b) => a[1][1] - b[1][1]);let infos = [];stats_info_sortedEntries.forEach(entry => {//entry[1][0]     是否选中//entry[1][1]     顺序//entry[1][2]     名字let tempDom = $(".stats_" + entry[0]).clone();if (entry[1][0]) {tempDom.css("display", "block");} else {tempDom.css("display", "none");}tempDom.css("border-right", "2px solid #fff");infos.push(tempDom);$(".stats_" + entry[0]).remove();});infos.forEach(function (item, index, array) {$(".better-xcloud-stats-bar").append(item);});$('.better-xcloud-stats-bar > *').filter(function () {return $(this).css('display') === 'block';}).last().css("border-right", '0px');//流统计信息事件let draggedItemIndex = -1;let draggedItem;let draggedItemClone; // 声明一个变量来存储被拖拽元素的副本let isClick = false;let isTouchstart = false;let touchTimeout;// 当拖拽开始时,添加拖拽中的样式,并设置拖拽数据$('.drag-handle').on('dragstart', function (event) {draggedItem = $(this);draggedItemIndex = draggedItem.index();});// 当拖拽对象在可放置区域上方移动时触发$('.drag-handle').on('dra###er', function (event) {event.preventDefault();$('.drag-handle').removeClass('drag-over');$(this).addClass('drag-over');var placeholder = $('.placeholder');var target = $(this);if (event.originalEvent.clientY < target.offset().top + target.outerHeight() / 2) {placeholder.insertBefore(target);} else {placeholder.insertAfter(target);}if (!placeholder.prev().hasClass("dragging") && !placeholder.next().hasClass("dragging")) {placeholder.show();}});// 当拖拽对象离开可放置区域时触发$('.drag-handle').on('dragleave', function (event) {$(this).removeClass('drag-over');});// 当拖拽对象被松开触发$('.drag-handle').on('dragend', function (event) {var droppedIndex = $('.placeholder').index();var draggedItem = $('.drag-handle').eq(draggedItemIndex);draggedItem.insertBefore($('.placeholder'));draggedItem.removeClass('dragging').hide().fadeIn();$('.drag-handle').removeClass('drag-over');$('.drag-handle').removeClass('dragging');$('.placeholder').hide();draggedItemClone?.remove(); // 移除被拖拽元素的副本let drag_index = 0;let infos = [];$('.drag-handle').each(function (index, d) {let name = $(d).attr("data-name");if (name != undefined) {drag_index = drag_index + 1;NFTconfig['stats_info'][name][1] = drag_index;$(this).attr("data-index", drag_index);let tempDom = $(".stats_" + name).clone();if (!NFTconfig['stats_info'][name][0]) {//隐藏tempDom.css("display", "none");} else {tempDom.css("display", "block");}tempDom.css("border-right", "2px solid #fff");infos.push(tempDom);$(".stats_" + name).remove();}});naifeitian.setValue("stats_infoGM", NFTconfig['stats_info']);infos.forEach(function (item, index, array) {$(".better-xcloud-stats-bar").append(item);});$('.better-xcloud-stats-bar > *').filter(function () {return $(this).css('display') === 'block';}).last().css("border-right", '0px');});// 添加触摸事件$('.drag-handle').on('touchstart', function (event) {isTouchstart = true;draggedItem = $(this);draggedItemIndex = $(this).index();touchTimeout = setTimeout(function () {isClick = false;if ($(".dragged-copy-item").length == 0) {// 创建被拖拽元素的副本draggedItemClone = draggedItem.clone().addClass('stats-container dragged-copy-item');$('.better-xcloud-stats-settings').after(draggedItemClone);} else {draggedItemClone = $(".dragged-copy-item");}}, 200);isClick = true;});$('.stats-container').on('touchmove', function (event) {event.preventDefault();if (isClick) { return; }draggedItem.addClass("dragging");$(".dragged-copy-item").css("display", "block");const touch = event.originalEvent.touches[0] || event.originalEvent.changedTouches[0];var previousElement = $(".better-xcloud-stats-settings");// 计算右边界位置var rightEdgeOfPrevious = previousElement.offset().left + previousElement.outerWidth() - 100;// 更新被拖拽元素的副本位置draggedItemClone.css({top: touch.clientY - draggedItemClone.outerHeight() / 2 + 'px',left: rightEdgeOfPrevious + 'px'});$('.drag-handle').each(function () {if ($(this).hasClass("dragged-copy-item")) { return }const itemOffset = $(this).offset().top;const itemHeight = $(this).outerHeight();if (draggedItem.is($(this))) return true;let placeholder = $('.placeholder');if (touch.clientY > itemOffset && touch.clientY < itemOffset + itemHeight) {$(this).addClass('drag-over');if (touch.clientY < itemOffset + itemHeight / 4) {placeholder.insertBefore($(this));} else {placeholder.insertAfter($(this));}if (!placeholder.prev().hasClass("dragging") && !placeholder.next().hasClass("dragging")) {placeholder.css("display", "block");}return false;} else {$(this).removeClass("drag-over");}});});$('.stats-container').on('touchend', function (event) {isTouchstart = false;if (isClick) { return; }var droppedIndex = $('.placeholder').index();var draggedItem = $('.drag-handle').eq(draggedItemIndex);draggedItem.insertBefore($('.placeholder'));draggedItem.removeClass('dragging').hide().fadeIn();$('.drag-handle').removeClass('drag-over');$('.drag-handle').removeClass('dragging');$('.placeholder').hide();draggedItemClone.remove();let drag_index = 0;let infos = [];$('.drag-handle').each(function (index, d) {let name = $(d).attr("data-name");if (name != undefined) {drag_index = drag_index + 1;NFTconfig['stats_info'][name][1] = drag_index;$(this).attr("data-index", drag_index);let tempDom = $(".stats_" + name).clone();if (!NFTconfig['stats_info'][name][0]) {//隐藏tempDom.css("display", "none");} else {tempDom.css("display", "block");}tempDom.css("border-right", "2px solid #fff");infos.push(tempDom);$(".stats_" + name).remove();}});naifeitian.setValue("stats_infoGM", NFTconfig['stats_info']);infos.forEach(function (item, index, array) {$(".better-xcloud-stats-bar").append(item);});$('.better-xcloud-stats-bar > *').filter(function () {return $(this).css('display') === 'block';}).last().css("border-right", '0px');});// 点击事件,选中/取消选中按钮$('.drag-handle').on('click', function (event) {if (!isClick) {if (isTouchstart) {return;}}if ($(this).hasClass('stats-selected')) {//取消$(this).removeClass('stats-selected');$(this).addClass('stats-delete');NFTconfig['stats_info'][$(this).attr("data-name")][0] = false;} else {//启用$(this).addClass('stats-selected');$(this).removeClass('stats-delete');NFTconfig['stats_info'][$(this).attr("data-name")][0] = true;}naifeitian.setValue("stats_infoGM", NFTconfig['stats_info']);let stats_info_sortedEntries = Object.entries(NFTconfig['stats_info']).sort((a, b) => a[1][1] - b[1][1]);stats_info_sortedEntries.forEach(entry => {//entry[1][0]     是否选中//entry[1][1]     顺序//entry[1][2]     名字if (entry[1][0]) {$(".stats_" + entry[0]).css("display", "block");} else {$(".stats_" + entry[0]).css("display", "none");}$(".stats_" + entry[0]).css("border-right", "2px solid #fff");})$('.better-xcloud-stats-bar > *').filter(function () {return $(this).css('display') === 'block';}).last().css("border-right", '0px');});StreamStats.#refreshStyles();}}function numberPicker(key, suffix = '', disabled = false, range = true) {const setting = key.name;let value = key.default;let $text, $decBtn, $incBtn, $range;const MIN = key.min;const MAX = key.max;const CE = createElement;const $wrapper = CE('div', {},$decBtn = CE('button', { 'data-type': 'dec' }, '-'),$text = CE('span', {}, value + suffix),$incBtn = CE('button', { 'data-type': 'inc' }, '+'),);if (range) {$range = CE('input', { 'type': 'range', 'style': "width:100px", 'min': 0, 'max': 150, 'value': value });$range.addEventListener('input', e => {value = parseInt(e.target.value);$text.textContent = value + "%";key['default'] = value;naifeitian.setValue(key['name'], key);updateVideoPlayerCss();});$wrapper.appendChild($range);}if (disabled) {$incBtn.disabled = true;$incBtn.classList.add('better-xcloud-hidden');$decBtn.disabled = true;$decBtn.classList.add('better-xcloud-hidden');return $wrapper;}let interval;let isHolding = false;const onClick = e => {if (isHolding) {e.preventDefault();isHolding = false;return;}const btnType = e.target.getAttribute('data-type');if (btnType === 'dec') {value = (value <= MIN) ? MIN : value - 1;} else {value = (value >= MAX) ? MAX : value + 1;}$($range).val(value);$text.textContent = value + suffix;key['default'] = value;naifeitian.setValue(key['name'], key);updateVideoPlayerCss();isHolding = false;}const onMouseDown = e => {isHolding = true;const args = arguments;interval = setInterval(() => {const event = new Event('click');event.arguments = args;e.target.dispatchEvent(event);}, 200);};const onMouseUp = e => {clearInterval(interval);isHolding = false;};$decBtn.addEventListener('click', onClick);$decBtn.addEventListener('mousedown', onMouseDown);$decBtn.addEventListener('mouseup', onMouseUp);$decBtn.addEventListener('touchstart', onMouseDown);$decBtn.addEventListener('touchend', onMouseUp);$incBtn.addEventListener('click', onClick);$incBtn.addEventListener('mousedown', onMouseDown);$incBtn.addEventListener('mouseup', onMouseUp);$incBtn.addEventListener('touchstart', onMouseDown);$incBtn.addEventListener('touchend', onMouseUp);return $wrapper;}function setupVideoSettingsBar() {const CE = createElement;let $stretchInp;const refreshFunc = e => {updateVideoPlayerCss();};const $stretch = naifeitian.toElement(NFTconfig['video_stretch'], refreshFunc);const $wrapper = CE('div', { 'class': 'better-xcloud-quick-settings-bar' },CE('div', {},CE('label', { 'for': 'better-xcloud-quick-setting-stretch' }, '去黑边'),$stretch),CE('div', {},CE('label', {}, '清晰'),numberPicker(NFTconfig['VIDEO_CLARITY'], '', naifeitian.isSafari(), false)),CE('div', {},CE('label', {}, '饱和'),numberPicker(NFTconfig['VIDEO_SATURATION'], '%')),CE('div', {},CE('label', {}, '对比'),numberPicker(NFTconfig['VIDEO_CONTRAST'], '%')),CE('div', {},CE('label', {}, '亮度'),numberPicker(NFTconfig['VIDEO_BRIGHTNESS'], '%')));$stretch.addEventListener('change', e => {if (e.target.value == 'setting') {$('#video_stretch_x_y').css('display', 'block');} else {$('#video_stretch_x_y').css('display', 'none');}NFTconfig['video_stretch'].default = e.target.value;naifeitian.setValue('video_stretchGM', NFTconfig['video_stretch']);updateVideoPlayerCss();});document.documentElement.appendChild($wrapper);if ($stretch.id == 'xcloud_setting_video_stretchGM') {let dom = $('#xcloud_setting_video_stretchGM');dom.after(`<div id="video_stretch_x_y" style="display: ${NFTconfig['video_stretch'].default == 'setting' ? 'block' : 'none'}"><lable>左右<input type=\'text\'class="video_stretch_x_y_Listener" id="video_stretch_x" style="width:35px" value="${NFTconfig['video_stretch_x_y']['x']}"/></lable><br/><lable>上下<input type=\'text\'class="video_stretch_x_y_Listener" id="video_stretch_y" style="width:35px" value="${NFTconfig['video_stretch_x_y']['y']}"/></lable></div>`);$(document).on('blur', '.video_stretch_x_y_Listener', function () {let newval = $(this).val();if (naifeitian.isNumber($(this).val())) {if ($(this).attr('id') == 'video_stretch_x') {NFTconfig['video_stretch_x_y']['x'] = newval;naifeitian.setValue('video_stretch_x_yGM', NFTconfig['video_stretch_x_y']);} else {NFTconfig['video_stretch_x_y']['y'] = newval;naifeitian.setValue('video_stretch_x_yGM', NFTconfig['video_stretch_x_y']);}} else {$(this).val("0");NFTconfig['video_stretch_x_y']['x'] = 0;NFTconfig['video_stretch_x_y']['y'] = 0;naifeitian.setValue('video_stretch_x_yGM', NFTconfig['video_stretch_x_y']);}updateVideoPlayerCss();});}}function cloneStreamHudButton($orgButton, class_, label, svg_icon) {const $container = $orgButton.cloneNode(true);if (class_ != "") {$($container).addClass(class_);}const $button = $container.querySelector('button');$button.setAttribute('title', label);const $svg = $button.querySelector('svg');$svg.innerHTML = svg_icon;const attrs = {'fill-rule': 'evenodd','stroke-linecap': 'round','stroke-linejoin': 'round','stroke-width': 2,'viewBox': '0 0 32 32'};for (const attr in attrs) {$svg.setAttribute(attr, attrs[attr]);}return $container;}function cloneStreamMenuButton($orgButton, label, svg_icon) {const $button = $orgButton.cloneNode(true);$button.setAttribute('aria-label', label);$button.querySelector('div[class*=label]').textContent = label;const $svg = $button.querySelector('svg');$svg.innerHTML = svg_icon;$svg.setAttribute('viewBox', '0 0 32 32');return $button;}function HookProperty(object, property, value) {Object.defineProperty(object, property, {value: value});}let userAgentOriginal = window.navigator.userAgent;try {HookProperty(window.navigator, "userAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/999.0.0.0 Safari/537.36 Edg/999.0.0.0");HookProperty(window.navigator, "maxTouchPoints", 10);if (NFTconfig['disableCheckNetwork'] == 1) {Object.defineProperty(window.navigator, 'connection', {get: () => undefined,});}HookProperty(window.navigator, "standalone", true);} catch (e) { }let consoleIp;let consolePort;const patchIceCandidates = function (...arg) {// ICE server candidatesconst request = arg[0];const url = (typeof request === 'string') ? request : request.url;if (url && url.endsWith('/ice') && url.includes('/sessions/') && request.method === 'GET') {const promise = originFetch(...arg);return promise.then(response => {return response.clone().text().then(text => {if (!text.length) {return response;}const options = {preferIpv6Server: NFTconfig['IPv6'] == 1,consoleIp: consoleIp,};const obj = JSON.parse(text);let exchangeResponse = JSON.parse(obj.exchangeResponse);exchangeResponse = updateIceCandidates(exchangeResponse, options)obj.exchangeResponse = JSON.stringify(exchangeResponse);response.json = () => Promise.resolve(obj);response.text = () => Promise.resolve(JSON.stringify(obj));return response;});});}return null;}const originFetch = window.fetch;window.fetch = async (...arg) => {let arg0 = arg[0];let url = "";let isRequest = false;switch (typeof arg0) {case "object":url = arg0.url;isRequest = true;break;case "string":url = arg0;break;default:break;}// 串流if (IS_REMOTE_PLAYING && url.includes('/sessions/home') || url.includes('inputconfigs')) {canShowOC = true;const clone = arg0.clone();const headers = {};for (const pair of clone.headers.entries()) {headers[pair[0]] = pair[1];}headers['authorization'] = `Bearer ${RemotePlay.XHOME_TOKEN}`;const deviceInfo = RemotePlay.BASE_DEVICE_INFO;if (NFTconfig['REMOTE_PLAY_RESOLUTION']['default'] == '720p') {deviceInfo.dev.os.name = 'android';}headers['x-ms-device-info'] = JSON.stringify(deviceInfo);const opts = {method: clone.method,headers: headers,};if (clone.method === 'POST') {opts.body = await clone.text();}const index = arg0.url.indexOf('.xboxlive.com');let newUrl = `https://${REMOTE_PLAY_SERVER}.core.gssv-play-prodxhome` + arg0.url.substring(index);arg0 = new Request(newUrl, opts);arg[0] = arg0;url = (typeof request === 'string') ? arg0 : arg0.url;// Get console IPif (url.includes('/configuration')) {const promise = originFetch(...arg);return promise.then(response => {return response.clone().json().then(obj => {console.log(obj);consoleIp = obj.serverDetails.ipAddress;consolePort = obj.serverDetails.port;response.json = () => Promise.resolve(obj);return response;});});}if (url.includes('/sessions/home/play')) {inGame();document.title = document.title.replace('Fortnite', '串流');}return patchIceCandidates(...arg) || originFetch(...arg);}if (IS_REMOTE_PLAYING && url.includes('/login/user')) {try {const clone = arg0.clone();const obj = await clone.json();obj.offeringId = 'xhome';arg0 = new Request('https://xhome.core.gssv-play-prod.xboxlive.com/v2/login/user', {method: 'POST',body: JSON.stringify(obj),headers: {'Content-Type': 'application/json',},});arg[0] = arg0;} catch (e) {alert(e);console.log(e);}return originFetch(...arg);}// ICE server candidatesconst patchedIpv6 = patchIceCandidates(...arg);if (patchedIpv6) {return patchedIpv6;}if (!url.includes('xhome.') && url.indexOf('/v2/login/user') > -1) {//xgpuweb.gssv-play-prod.xboxlive.comcheckIpsuc = true;let json = await arg0.json();let body = JSON.stringify(json);// 处理免代理逻辑if (NFTconfig['no_need_###_play'] == 1) {if (NFTconfig['useCustomfakeIp'] == 1 && naifeitian.isValidIP(NFTconfig['customfakeIp'])) {arg0.headers.set('x-forwarded-for', NFTconfig['customfakeIp']);} else {arg0.headers.set('x-forwarded-for', NFTconfig['regionBlock']['options'][NFTconfig['regionBlock']['blockIp']]);}}arg[0] = new Request(url, {method: arg0.method,headers: arg0.headers,body: body,});const promise = originFetch(...arg);if (NFTconfig['useCustomfakeIp'] == 1 && naifeitian.isValidIP(NFTconfig['customfakeIp'])) {console.log('免代理成功,已设置为自定义IP【' + NFTconfig['customfakeIp'] + "】");} else {console.log('免代理成功,已设置为【' + NFTconfig['regionBlock']['blockIp'] + "】");}RemotePlay.preload();return promise.then(response => {return response.clone().json().then(json => {//获取服务器列表let newServerList = [];let currentAutoServer;let REMOTE_SERVER_LIST = [];json["offeringSettings"]["regions"].forEach((region) => {REMOTE_SERVER_LIST.push(region.networkTestHostname.split(".")[0]);newServerList.push(region["name"]);if (region["isDefault"] === true) {currentAutoServer = region["name"];}});NFTconfig['REMOTE_SERVER_LIST'] = REMOTE_SERVER_LIST;naifeitian.setValue("REMOTE_SERVER_LISTGM", REMOTE_SERVER_LIST);naifeitian.setValue("blockXcloudServerListGM", newServerList);NFTconfig['blockXcloudServerList'] = newServerList;if (NFTconfig['blockXcloudServerList'].indexOf(NFTconfig['defaultXcloudServer']) == -1) {naifeitian.setValue("defaultXcloudServerGM", "");NFTconfig['defaultXcloudServer'] = "";NFTconfig['blockXcloudServer'] = 0;naifeitian.setValue("blockXcloudServerGM", 0);}if (NFTconfig['blockXcloudServer'] == 1) {console.log('修改服务器开始');json["offeringSettings"]["allowRegionSelection"] = true;let selectedServer = NFTconfig['defaultXcloudServer'];if (selectedServer !== "Auto" && newServerList.includes(selectedServer)) {json["offeringSettings"]["regions"].forEach((region) => {if (region["name"] === selectedServer) {region["isDefault"] = true;} else {region["isDefault"] = false;}});}console.log('修改服务器结束');}try {json["offeringSettings"]["regions"].forEach((region) => {if (region.isDefault) {StreamBadges.region = region.name;throw new Error();}});} catch (e) { }response.json = () => Promise.resolve(json);return response;});});} else if (url.indexOf('/cloud/play') > -1) {inGame();const clone = arg0.clone();const body = await clone.json();if (NFTconfig['chooseLanguage'] == 1) {let selectedLanguage = NFTconfig['xcloud_game_language'];if (selectedLanguage == 'Auto') {let parts = window.location.pathname.split('/');let pid = parts[parts.length - 1];try {let res = await fetch("https://catalog.gamepass.com/products?market=US&language=en-US&hydration=PCInline", {"headers": {"content-type": "application/json;charset=UTF-8",},"body": "{\"Products\":[\"" + pid + "\"]}","method": "POST","mode": "cors","credentials": "omit"});let jsonObj = await res.json();let languag###pport = jsonObj["Products"][pid]["Languag###pport"]for (let language of Object.keys(default_language_list)) {if (default_language_list[language] in languag###pport) {selectedLanguage = default_language_list[language];break;}}if (selectedLanguage == 'Auto') {//防止接口没有返回支持语言selectedLanguage = NFTconfig['IfErrUsedefaultGameLanguage'];console.log("使用次选语言");}} catch (e) {}}console.log('语言已设置:【' + selectedLanguage + '】');body.settings.locale = selectedLanguage;}body.settings.osName = NFTconfig['high_bitrate'] == 1 ? 'windows' : 'android';const newRequest = new Request(arg0, {body: JSON.stringify(body),});arg[0] = newRequest;return originFetch(...arg);} else if (url.endsWith('/configuration') && url.includes('/sessions/cloud/') && NFTconfig['autoOpenOC'] == 1 && NFTconfig['disableTouchControls'] == 0) {// Enable CustomTouchOverlayreturn new Promise((resolve, reject) => {originFetch(...arg).then(res => {res.json().then(json => {// console.error(json);let inputOverrides = JSON.parse(json.clientStreamingConfi###errides || '{}') || {};inputOverrides.inputConfiguration = {enableTouchInput: true,maxTouchPoints: 10,enableVibration: true};json.clientStreamingConfi###errides = JSON.stringify(inputOverrides);let cdom = $('#BabylonCanvasContainer-main').children();if (cdom.length > 0) {canShowOC = false;} else {canShowOC = true;}let body = JSON.stringify(json);let newRes = new Response(body, {status: res.status,statusText: res.statusText,headers: res.headers})resolve(newRes);console.log('修改触摸成功')}).catch(err => {reject(err);});}).catch(err => {reject(err);});});} else {return originFetch(...arg);}}function updateIceCandidates(candidates, options) {const pattern = new RegExp(/a=candidate:(?<foundation>\d+) (?<component>\d+) UDP (?<priority>\d+) (?<ip>[^\s]+) (?<the_rest>.*)/);const lst = [];for (let item of candidates) {if (item.candidate == 'a=end-of-candidates') {continue;}const groups = pattern.exec(item.candidate).groups;lst.push(groups);}if (options.preferIpv6Server) {lst.sort((a, b) => (!a.ip.includes(':') && b.ip.includes(':')) ? 1 : -1);}const newCandidates = [];let foundation = 1;lst.forEach(item => {item.foundation = foundation;item.priority = (foundation == 1) ? 10000 : 1;newCandidates.push({'candidate': `a=candidate:${item.foundation} 1 UDP ${item.priority} ${item.ip} ${item.the_rest}`,'messageType': 'iceCandidate','sdpMLineIndex': '0','sdpMid': '0',});++foundation;});if (options.consoleIp) {newCandidates.push({'candidate': `a=candidate:${newCandidates.length + 1} 1 UDP 1 ${options.consoleIp} 9002 typ host`,'messageType': 'iceCandidate','sdpMLineIndex': '0','sdpMid': '0',});}newCandidates.push({'candidate': 'a=end-of-candidates','messageType': 'iceCandidate','sdpMLineIndex': '0','sdpMid': '0',});return newCandidates;}function checkCodec() {let rtcCodecPreferences = naifeitian.getValue('rtcCodecPreferencesGM');let codecs = RTCRtpReceiver.getCapabilities('video').codecs;let codesOptions = ['默认', '自动'];const codecProfileMap = { "高": "4d", "中": "42e", "低": "420" };codecs.forEach((codec, index) => {if (codec.mimeType === 'video/H264') {for (let key in codecProfileMap) {if (codec.sdpFmtpLine.includes(codecProfileMap[key])) {codesOptions.push(codec.mimeType.substring(6) + key);break;}}} else {codesOptions.push(codec.mimeType.substring(6));}});codesOptions = [...new Set(codesOptions)];let sortOrder = ['默认', '自动', 'AV1', 'VP9', 'H265', 'VP8', 'H264高', 'H264中', 'H264低', 'flexfec-03', 'ulpfec', 'rtx', 'red'];const customSort = (a, b) => {const indexOfA = sortOrder.indexOf(a);const indexOfB = sortOrder.indexOf(b);if (indexOfA === -1) {return 1;}if (indexOfB === -1) {return -1;}return indexOfA - indexOfB;};codesOptions.sort(customSort);rtcCodecPreferences['options'] = codesOptions;if (!rtcCodecPreferences['options'].includes(rtcCodecPreferences['default'])) {rtcCodecPreferences['default'] = "默认";}NFTconfig['rtcCodecPreferences'] = rtcCodecPreferences;naifeitian.setValue('rtcCodecPreferencesGM', rtcCodecPreferences);}checkCodec();if (NFTconfig['autoOpenOC'] == 1 && NFTconfig['disableTouchControls'] == 0 && NFTconfig['autoShowTouch']) {window.RTCPeerConnection.prototype.originalCreateDataChannelGTC = window.RTCPeerConnection.prototype.createDataChannel;window.RTCPeerConnection.prototype.createDataChannel = function (...params) {const dc = this.originalCreateDataChannelGTC.apply(this, arguments);if (dc.label == "message") {dc.addEventListener('open', e => {setTimeout(() => {if (canShowOC) {dc.dispatchEvent(new MessageEvent('message', {data: '{"content":"{\\"layoutId\\":\\"\\"}","target":"/streaming/touchcontrols/showlayoutv2","type":"Message"}'}));}}, 1000);});dc.addEventListener("message", function (de) {if (typeof (de.data) != "string") { return; }let msgdata = JSON.parse(de.data);if (msgdata.target == "/streaming/touchcontrols/showtitledefault") {let chkItv = setInterval(() => {if (canShowOC == null) { return; }clearInterval(chkItv);if (canShowOC) {dc.dispatchEvent(new MessageEvent('message', {data: '{"content":"{\\"layoutId\\":\\"\\"}","target":"/streaming/touchcontrols/showlayoutv2","type":"Message"}'}));}}, 1000);}});}return dc;}}// 配置对象,定义每个设置项的信息const settingsConfig = [{label: '选择语言:',type: 'radio',name: 'chooseLanguage',display: 'block',options: [{ value: 1, text: '开', id: 'chooseLanguageOn' },{ value: 0, text: '关', id: 'chooseLanguageOff' }],checkedValue: NFTconfig['chooseLanguage'],needHr: false},{label: '首选语言:',type: 'radio',name: 'selectLanguage',display: NFTconfig['chooseLanguage'] === 1 ? 'block' : 'none',options: Object.keys(default_language_list).map(languageChinese => {return {value: default_language_list[languageChinese],text: languageChinese,id: default_language_list[languageChinese]};}),checkedValue: NFTconfig['xcloud_game_language'],needHr: false},{label: '次选语言:',type: 'radio',name: 'IfErrUsedefaultGameLanguage',display: NFTconfig['xcloud_game_language'] === 'Auto' ? 'block' : 'none',options: Object.keys(default_language_list).map(languageChinese => {if (languageChinese == '智能简繁') { return; }return {value: default_language_list[languageChinese],text: languageChinese,id: default_language_list[languageChinese] + 'ifErr'};}),checkedValue: NFTconfig['IfErrUsedefaultGameLanguage'],needHr: true},{label: '免代理直连:',type: 'radio',name: 'noNeed###',display: 'block',options: [{ value: 1, text: '开', id: 'noNeed###On' },{ value: 0, text: '关', id: 'noNeed###Off' },],checkedValue: NFTconfig['no_need_###_play'],needHr: false},{label: '选服:',type: 'radio',name: 'selectRegion',display: NFTconfig['no_need_###_play'] === 1 ? 'block' : 'none',options: Object.keys(NFTconfig['regionBlock']['options']).map(region => {return {value: NFTconfig['regionBlock']['options'][region],text: region,id: NFTconfig['regionBlock']['options'][region]};}),checkedValue: NFTconfig['regionBlock']['options'][NFTconfig['regionBlock']['blockIp']],needHr: false},{label: '自定义IP:',type: 'radio',name: 'customfakeIpInput',display: NFTconfig['no_need_###_play'] === 1 ? 'block' : 'none',value: NFTconfig['useCustomfakeIp'],needHr: true,moreDom: `<input type="radio" class="selectRegionListener settingsBoxInputRadio" style="outline:none;"name='selectRegion' id="customfakeIp" value="customfakeIp" ${NFTconfig['useCustomfakeIp'] == 1 ? 'checked' : ''}><label for="customfakeIp" style="padding-right: 7px;">自定义IP:</label><input type='text' style="display: ` + (NFTconfig['useCustomfakeIp'] == 1 ? 'inline' : 'none')+ `;outline: none;width: 125px;" id="customfakeIpInput" class="customfakeIpListener" value="${NFTconfig['customfakeIp']}" placeholder="请输入IP"/>`},{label: '分辨率:',type: 'radio',name: 'highBitrate',display: 'block',options: [{ value: 1, text: '1080P', id: 'high_bitrateOn' },{ value: 0, text: '720P', id: 'high_bitrateOff' }],checkedValue: NFTconfig['high_bitrate'],needHr: true},{label: '浏览器编解码偏好:',showLable: true,type: 'dropdown',name: 'rtcCodecPreferences',display: "block",options: NFTconfig['rtcCodecPreferences']['options'],selectedValue: NFTconfig['rtcCodecPreferences']['default'],needHr: true},{label: '禁止检测网络状况:',type: 'radio',name: 'disableCheckNetwork',display: 'block',options: [{ value: 1, text: '开', id: 'disableCheckNetworkOn' },{ value: 0, text: '关', id: 'disableCheckNetworkOff' }],checkedValue: NFTconfig['disableCheckNetwork'],needHr: true},{label: '强制触控:',type: 'radio',name: 'autoOpenOC',display: 'block',options: [{ value: 1, text: '开', id: 'autoOpenOCOn' },{ value: 0, text: '关', id: 'autoOpenOCOff' }],checkedValue: NFTconfig['autoOpenOC'],needHr: true,moreDom: `<div id="autoShowTouchDom" style="padding-right: 0px;display: ${NFTconfig['autoOpenOC'] == 1 ? 'inline' : 'none'}"><input type="checkbox" class="autoShowTouchListener settingsBoxInputRadio" style="outline:none;cursor: pointer;" name='autoShowTouch'id="autoShowTouch" ${NFTconfig['autoShowTouch'] == true ? 'checked' : ''}><label for="autoShowTouch" style="cursor: pointer;">自动弹出</label></div>`},{label: '屏蔽触控:',type: 'radio',name: 'disableTouchControls',display: 'block',options: [{ value: 1, text: '开', id: 'disableTouchControlsOn' },{ value: 0, text: '关', id: 'disableTouchControlsOff' },],checkedValue: NFTconfig['disableTouchControls'],needHr: true},{label: '自动全屏:',type: 'radio',name: 'autoFullScreen',display: 'block',options: [{ value: 1, text: '开', id: 'autoFullScreenOn' },{ value: 0, text: '关', id: 'autoFullScreenOff' }],checkedValue: NFTconfig['autoFullScreen'],needHr: true},{label: '优先IPv6:',type: 'radio',name: 'IPv6server',display: 'block',options: [{ value: 1, text: '开', id: 'IPv6On' },{ value: 0, text: '关', id: 'IPv6Off' }],checkedValue: NFTconfig['IPv6'],needHr: true},{label: '物理服务器:',type: 'radio',name: 'blockXcloudServer',display: 'block',options: [{ value: 1, text: '开', id: 'blockXcloudServerOn' },{ value: 0, text: '关', id: 'blockXcloudServerOff' }],checkedValue: NFTconfig['blockXcloudServer'],needHr: false},{label: '选择服务器:',type: 'dropdown',name: 'defaultXcloudServer',display: NFTconfig['blockXcloudServer'] === 1 ? "block" : "none",options: NFTconfig['blockXcloudServerList'],selectedValue: NFTconfig['defaultXcloudServer'],needHr: true},{label: '挂机防踢:',type: 'radio',name: 'antiKick',display: 'block',options: [{ value: 1, text: '开', id: 'antiKickOn' },{ value: 0, text: '关', id: 'antiKickOff' }],checkedValue: NFTconfig['antiKick'],needHr: true},{label: '设置悬浮窗:',type: 'radio',name: 'noPopSetting',display: 'block',options: [{ value: 0, text: '显示', id: 'noPopSettingOff' },{ value: 1, text: '隐藏', id: 'noPopSettingOn' }],checkedValue: NFTconfig['noPopSetting'],needHr: true},{label: '开启串流功能:',type: 'radio',name: 'enableRemotePlay',display: 'block',options: [{ value: 1, text: '开', id: 'enableRemotePlayOn' },{ value: 0, text: '关', id: 'enableRemotePlayOff' }],checkedValue: NFTconfig['enableRemotePlay'],needHr: true}];// 函数用于生成单个设置项的HTMLfunction generateSettingElement(setting) {let settingHTML = `<lable style="display:${setting.display};white-space: nowrap;margin-bottom:0.375rem;" class="${setting.name + 'Dom'}">`;if (setting.type === 'radio') {if (setting.options != undefined) {settingHTML += `<label style="display:block;text-align:left;"><div style="display: inline;">${setting.label}</div>`;setting.options.forEach(option => {if (option == null) { return; }settingHTML += `<label style="cursor: pointer;"><input type="radio" class="${setting.name + 'Listener'} settingsBoxInputRadio" style="outline:none;" name="${setting.name}"id="${option.id}" value="${option.value}" ${option.value === setting.checkedValue ? 'checked' : ''}>${option.text}</label>`;});}if (setting.moreDom != undefined) {settingHTML += setting.moreDom;}settingHTML += '</label>';} else if (setting.type === 'text') {settingHTML += `<label style="display: block;text-align:left;"><div style="display: inline;">${setting.label}</div>`;settingHTML += `<input type="text" style="display: inline;outline: none;width: 125px;" id="${setting.name}" class="${setting.name}Listener" value="${setting.value}" placeholder="请输入${setting.label}"/>`;settingHTML += `</label>`;} else if (setting.type === 'dropdown') {if (setting.showLable == true) {settingHTML += `<label style="display: block;text-align:left;${setting.css}"><div style="display: inline;">${setting.label}</div>`;}if (setting.options.length == undefined) {setting.options = Object.keys(setting.options);}settingHTML += `<select style="outline: none;margin-bottom:5px;" class="${setting.name + 'Listener'}">${setting.options.map(option => `<option value="${option}" ${option === setting.selectedValue ? 'selected' : ''}>${option}</option>`).join('')}</select>`;if (setting.moreDom != undefined) {settingHTML += setting.moreDom;}}settingHTML += `</lable>`;if (setting.needHr) {settingHTML += `<hr style="background-color: black;width:95%" />`}return settingHTML;}function generateSettingsPage() {let settingsHTML = `<div style="padding: 10px;color: black;display:none;" class="settingsBackgroud" id="settingsBackgroud"><div class="settingsBox"><span class="blink-text" onclick="window.location.href='https://greasyfork.org/zh-CN/scripts/455741';">更新咯~</span>`;settingsConfig.forEach(setting => {settingsHTML += generateSettingElement(setting);});settingsHTML += `<button class="closeSetting1 closeSetting2" style="outline: none;">关闭</button><div style="text-align: right;margin-top: 8px;font-size: 16px;"><label>捐赠:</label><a style="margin-right:15px;outline: none;color: #107c10;text-decoration: underline;" href="https://greasyfork.org/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBMVNFQVE9PSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--14c278e3f72d104cff50bf130d4039229fc25a6b/wx.png?locale=zh-CN">微信</a><a style="outline: none;color: #107c10;text-decoration: underline;" href="https://greasyfork.org/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBMU9FQVE9PSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--5fc08aaa8407cc6099654d65455b7966bf2c60ee/alipay.png?locale=zh-CN">支付宝</a></div></div></div>`;return settingsHTML;}let needrefresh = 0;function initSettingBox() {$('body').append(generateSettingsPage());//确定$(document).on('click', '.closeSetting1', function () {naifeitian.hideSetting();if (needrefresh == 1) {history.go(0);}});//开启串流$(document).on('click', '.enableRemotePlayListener', function () {needrefresh = 1;naifeitian.setValue('enableRemotePlayGM', $(this).val());$('.closeSetting1').text('确定');});//设置悬浮窗$(document).on('click', '.noPopSettingListener', function () {naifeitian.setValue('noPopSettingGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//挂机防踢$(document).on('click', '.antiKickListener', function () {needrefresh = 1;naifeitian.setValue('antiKickGM', $(this).val());$('.closeSetting1').text('确定');});//ipv6$(document).on('click', '.IPv6serverListener', function () {naifeitian.setValue('IPv6GM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//选择服务器change$(document).on('change', '.defaultXcloudServerListener', function () {naifeitian.setValue('defaultXcloudServerGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//物理服务器$(document).on('click', '.blockXcloudServerListener', function () {if ($(this).val() == 0) {$('.defaultXcloudServerDom').css('display', 'none');} else {$('.defaultXcloudServerDom').css('display', 'block');}naifeitian.setValue('blockXcloudServerGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//自动全屏$(document).on('click', '.autoFullScreenListener', function () {naifeitian.setValue('autoFullScreenGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//屏蔽触控$(document).on('click', '.disableTouchControlsListener', function () {if ($(this).val() == 1) {if (!confirm("确定要屏蔽触控吗?")) {$('#disableTouchControlsOff').click();return;}$('#autoOpenOCOff').click();}needrefresh = 1;naifeitian.setValue('disableTouchControlsGM', $(this).val());$('.closeSetting1').text('确定');});//自动弹出$(document).on('change', '.autoShowTouchListener', function () {let newVal = $(this).attr('checked') == 'checked';if (newVal) {$(this).removeAttr('checked');} else {$(this).attr('checked');}naifeitian.setValue('autoShowTouchGM', !newVal);needrefresh = 1;$('.closeSetting1').text('确定');});//强制触控$(document).on('click', '.autoOpenOCListener', function () {if ($(this).val() == 0) {$('#autoShowTouchDom').css('display', 'none');} else {$('#autoShowTouchDom').css('display', 'inline');$('#disableTouchControlsOff').click();}naifeitian.setValue('autoOpenOCGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//禁止检测网络$(document).on('click', '.disableCheckNetworkListener', function () {naifeitian.setValue('disableCheckNetworkGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//浏览器编解码偏好$(document).on('change', '.rtcCodecPreferencesListener', function () {NFTconfig['rtcCodecPreferences']['default'] = $(this).val();naifeitian.setValue('rtcCodecPreferencesGM', NFTconfig['rtcCodecPreferences']);needrefresh = 1;$('.closeSetting1').text('确定');});//分辨率$(document).on('click', '.highBitrateListener', function () {naifeitian.setValue('high_bitrateGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//自定义ip输入框$(document).on('blur', '.customfakeIpListener', function () {if (naifeitian.isValidIP($(this).val())) {naifeitian.setValue('customfakeIpGM', $(this).val());} else {$(this).val("");naifeitian.setValue('customfakeIpGM', '');alert('IP格式错误!');return;}needrefresh = 1;$('.closeSetting1').text('确定');});//选服$(document).on('click', '.selectRegionListener', function () {if ($(this).val() == 'customfakeIp') {naifeitian.setValue('useCustomfakeIpGM', 1);$('#customfakeIpInput').css('display', 'inline');} else {NFTconfig['regionBlock']['blockIp'] = Object.keys(NFTconfig['regionBlock']['options']).find(key => NFTconfig['regionBlock']['options'][key] === $(this).val());naifeitian.setValue('regionBlockGM', NFTconfig['regionBlock']);naifeitian.setValue('useCustomfakeIpGM', 0);$('#customfakeIpInput').css('display', 'none');}needrefresh = 1;$('.closeSetting1').text('确定');});//免代理直连$(document).on('click', '.noNeed###Listener', function () {if ($(this).val() == 0) {$('.selectRegionDom').css('display', 'none');;$('.customfakeIpInputDom').css('display', 'none');} else {$('.selectRegionDom').css('display', 'block');$('.customfakeIpInputDom').css('display', 'block');}naifeitian.setValue('no_need_###_playGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//智能简繁错误$(document).on('click', '.IfErrUsedefaultGameLanguageListener', function () {naifeitian.setValue('IfErrUsedefaultGameLanguageGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//语言$(document).on('click', '.selectLanguageListener', function () {if ($(this).val() != 'Auto') {$('.IfErrUsedefaultGameLanguageDom').css('display', 'none');} else {$('.IfErrUsedefaultGameLanguageDom').css('display', 'block');}naifeitian.setValue('xcloud_game_languageGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});//选择语言$(document).on('click', '.chooseLanguageListener', function () {if ($(this).val() == 0) {$('.selectLanguageDom').css('display', 'none');$('.IfErrUsedefaultGameLanguageDom').css('display', 'none');} else {$('.selectLanguageDom').css('display', 'block');if (naifeitian.getValue('xcloud_game_languageGM') == 'Auto') {$('.IfErrUsedefaultGameLanguageDom').css('display', 'block');}}naifeitian.setValue('chooseLanguageGM', $(this).val());needrefresh = 1;$('.closeSetting1').text('确定');});}//手势显隐触控function initSlideHide() {var gestureArea = $("<div></div>");gestureArea.attr("id", "touchControllerEventArea");$(document.documentElement).append(gestureArea);gestureArea = $("#touchControllerEventArea");let startX, startY, endX, endY;let threshold = 60; // 手势滑动的阈值gestureArea.on("touchstart", function (e) {startX = e.originalEvent.touches[0].clientX;startY = e.originalEvent.touches[0].clientY;});gestureArea.on("touchmove", function (e) {endX = e.originalEvent.touches[0].clientX;endY = e.originalEvent.touches[0].clientY;});gestureArea.on("touchend", function (e) {if (startX !== undefined && startY !== undefined && endX !== undefined && endY !== undefined) {const deltaX = endX - startX;const deltaY = endY - startY;if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > threshold) {if (deltaX < 0) {// 左滑$('#BabylonCanvasContainer-main').css('display', 'none');$('#MultiTouchSurface').css('display', 'none');e.preventDefault();} else {// 右滑$('#BabylonCanvasContainer-main').css('display', 'block');$('#MultiTouchSurface').css('display', 'block');e.preventDefault();}}}});}async function checkUPD() {try {const response = await fetch("https://greasyfork.org/zh-CN/scripts/455741-xbox-cloud-gaming%E4%BC%98%E5%8C%96%E6%95%B4%E5%90%88/versions");const data = await response.text();let historyVersion = $(data).find('.history_versions')[0];let hli = $($(historyVersion).find('li .version-number > a')[0]);let version = hli.text();if (nftxboxversion != version) {$('head').append('<style>.blink-text{ display:block!important }</style>');}} catch (error) {//console.error('Fetch error:', error);}}$(document).ready(function () {//检测Thank you for your interestlet checkTYFYIInterval = setInterval(() => {if (checkIpsuc) {clearInterval(checkTYFYIInterval);return;}var title = $("[class*='UnsupportedMarketPage-module__title']");if (title.length > 0) {console.log("脚本检测到免代理没有成功,自动刷新中");title.text("脚本检测到免代理没有成功,自动刷新中");history.go(0);clearInterval(checkTYFYIInterval);}}, 5000);setTimeout(function () {if (NFTconfig['noPopSetting'] == 0) {$('body').append(`<div id="popSetting" style="display:block">⚙️ 设置</div>`);$(document).on('click', '#popSetting', function () {naifeitian.showSetting();});}checkUPD();initSettingBox();updateVideoPlayerCss();StreamStats.render();setupVideoSettingsBar();initSlideHide();}, 2000);});let timer;let mousehidding = false;$(document).mousemove(function () {if (mousehidding) {mousehidding = false;return;}if (timer) {clearTimeout(timer);timer = 0;}$('html').css({cursor: ''});timer = setTimeout(function () {mousehidding = true;$('html').css({cursor: 'none'});}, 2000);});let _pushState = window.history.pushState;window.history.pushState = function () {setTimeout(RemotePlay.detect, 10);if (NFTconfig['noPopSetting'] == 0) {if (arguments[2].substring(arguments[2].length, arguments[2].length - 5) == '/play') {exitGame();} else {$('#popSetting').css('display', 'none');}}if (arguments[2].indexOf("/play/games/") > -1) {let timeout = 0;let checkPlayInterval = setInterval(() => {var playButtons = $("[class*='PlayButton-module__playButton'][disabled]");if (playButtons.length > 0) {playButtons.text("该游戏无法在" + [NFTconfig['regionBlock']['blockIp']] + "游玩,请使用脚本切换其他服尝试");clearInterval(checkPlayInterval);}if (timeout == 10) {clearInterval(checkPlayInterval);}timeout++;}, 1333);}if ((!arguments[2].includes("/play/launch/") && !arguments[2].includes('/remote-play'))) {exitGame();}if(arguments[2].includes("/play/launch/")){$($("div[class^='StreamGateDialog-module__scrollable']")[0]).css("display","none");}if (arguments[2].includes("/https")) {if (window.location.href.includes("/remote-play")) {exitGame();}setTimeout(() => { history.go(-1) }, 10);return;}if (arguments[2].includes("/dev-tools/direct-connect")) {exitGame();setTimeout(() => { history.go(-1) }, 10);return}return _pushState.apply(this, arguments);}function getVideoPlayerFilterStyle() {const filters = [];const clarity = NFTconfig['VIDEO_CLARITY']['default'];if (clarity != 0) {const level = 7 - (clarity - 1); // 5,6,7const matrix = `0 -1 0 -1 ${level} -1 0 -1 0`;document.getElementById('better-xcloud-filter-clarity-matrix').setAttributeNS(null, 'kernelMatrix', matrix);filters.push(`url(#better-xcloud-filter-clarity)`);}const saturation = NFTconfig['VIDEO_SATURATION']['default'];if (saturation != 100) {filters.push(`saturate(${saturation}%)`);}const contrast = NFTconfig['VIDEO_CONTRAST']['default'];if (contrast != 100) {filters.push(`contrast(${contrast}%)`);}const brightness = NFTconfig['VIDEO_BRIGHTNESS']['default'];if (brightness != 100) {filters.push(`brightness(${brightness}%)`);}return filters.join(' ');}function updateVideoPlayerCss() {let $elm = document.getElementById('better-xcloud-video-css');if (!$elm) {const CE = createElement;$elm = CE('style', { id: 'better-xcloud-video-css' });document.documentElement.appendChild($elm);// Setup SVG filtersconst $svg = CE('svg', {'id': 'better-xcloud-video-filters','xmlns': 'http://www.w3.org/2000/svg','class': 'better-xcloud-gone',}, CE('defs', { 'xmlns': 'http://www.w3.org/2000/svg' },CE('filter', { 'id': 'better-xcloud-filter-clarity', 'xmlns': 'http://www.w3.org/2000/svg' },CE('feConvolveMatrix', { 'id': 'better-xcloud-filter-clarity-matrix', 'order': '3', 'xmlns': 'http://www.w3.org/2000/svg' }))));document.documentElement.appendChild($svg);}let filters = getVideoPlayerFilterStyle();let css = '';if (filters) {css += `filter: ${filters} !important;`;}if (NFTconfig['video_stretch'].default == 'fill') {css += 'object-fit: fill !important;';}if (NFTconfig['video_stretch'].default == 'setting') {css += `transform: scaleX(` + (NFTconfig['video_stretch_x_y'].x * 1 + 1) + `) scaleY(` + (NFTconfig['video_stretch_x_y'].y * 1 + 1) + `) !important;`;}if (css) {css = `#game-stream video {${css}}`;}$elm.textContent = css;}function screenClicktohide() {const $screen = document.querySelector('#PageContent section[class*=PureScreens]');const $quickBar = document.querySelector('.better-xcloud-quick-settings-bar');const $parent = $screen.parentElement;const hideQuickBarFunc = e => {e.stopPropagation();if (e.target != $parent && e.target.id !== 'MultiTouchSurface' && !e.target.querySelector('#BabylonCanvasContainer-main')) {return;}// Hide Quick settings bar$quickBar.style.display = 'none';$('.better-xcloud-stats-settings').css("display", "none");$parent.removeEventListener('click', hideQuickBarFunc);$parent.removeEventListener('touchstart', hideQuickBarFunc);if (e.target.id === 'MultiTouchSurface') {e.target.removeEventListener('touchstart', hideQuickBarFunc);}}$parent.addEventListener('click', hideQuickBarFunc);$parent.addEventListener('touchstart', hideQuickBarFunc);}//插入按钮function injectVideoSettingsButton() {const $screen = document.querySelector('#PageContent section[class*=PureScreens]');if (!$screen) {return;}if ($screen.xObserving) {return;}$screen.xObserving = true;const $parent = $screen.parentElement;const $quickBar = document.querySelector('.better-xcloud-quick-settings-bar');screenClicktohide();let $btnStreamStats;let $btnVideoSettings_HD;const observer = new MutationObserver(mutationList => {mutationList.forEach(item => {if (item.type !== 'childList') {return;}item.addedNodes.forEach(async node => {if (IS_REMOTE_PLAYING) {try {let btn = $(node).find('button[class*=PopupScreen-module__button][data-auto-focus=false]');if ($(btn).length > 0) {$(btn).click();throw new Error("巴啦啦能量-呼#拉-魔仙变身!");}} catch (e) { }}if (!node.className || !node.className.startsWith('StreamMenu')) {return;}const $orgButton = node.querySelector('div > div > button');if (!$orgButton) {return;}// 创建视频调整const $btnVideoSettings = cloneStreamMenuButton($orgButton, '视频调整', ICON_VIDEO_SETTINGS);$btnVideoSettings.addEventListener('click', e => {e.preventDefault();e.stopPropagation();// Show Quick settings bar$quickBar.style.display = 'flex';$parent.addEventListener('click', screenClicktohide());$parent.addEventListener('touchstart', screenClicktohide());const $touchSurface = document.getElementById('MultiTouchSurface');$touchSurface && $touchSurface.style.display != 'none' && $touchSurface.addEventListener('touchstart', screenClicktohide());});// Add button at the beginning$orgButton.parentElement.insertBefore($btnVideoSettings, $orgButton.parentElement.firstChild);// Hide Quick bar when closing HUDconst $btnCloseHud = document.querySelector('button[class*=StreamMenu-module__backButton]');$btnCloseHud.addEventListener('click', e => {$quickBar.style.display = 'none';});// 创建流监控const $btnStreamStats = cloneStreamMenuButton($orgButton, '流监控', ICON_HD_STREAM_STATS);$btnStreamStats.addEventListener('click', e => {e.preventDefault();e.stopPropagation();// Toggle Stream StatsStreamStats.toggle();});// Insert after Video Settings button$orgButton.parentElement.insertBefore($btnStreamStats, $btnVideoSettings);//menu图标样式if (StreamStats.status()) {$('.ICON_HD_STREAM_STATS_ON').css("display", 'block');$('.ICON_HD_STREAM_STATS_OFF').css("display", 'none');} else {$('.ICON_HD_STREAM_STATS_ON').css("display", 'none');$('.ICON_HD_STREAM_STATS_OFF').css("display", 'block');}//桥const $menu = document.querySelector('div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module]');//const streamBadgesElement = await StreamBadges.render();$menu.appendChild(await StreamBadges.render());//$menu.insertAdjacentElement('afterend', streamBadgesElement);});});mutationList.forEach(item => {if (item.type !== 'childList') {return;}item.removedNodes.forEach($node => {if (!$node || !$node.className || !$node.className.startsWith) {return;}});item.addedNodes.forEach(async $node => {if (!$node || !$node.className) {return;}if ($node.className.startsWith('Overlay-module_') || $node.className.startsWith('InProgressScreen')) {$node = $node.querySelector('#StreamHud');}if (!$node || ($node.id || '') !== 'StreamHud') {return;}$(document).on('transitionend', '#StreamHud', function () {if ($('#StreamHud').css('left') == '0px') {$('.hd-stream-setting').removeClass("hd-stream-setting-hide");} else {$('.hd-stream-setting').addClass("hd-stream-setting-hide");}if (!NFTconfig['STATS_SLIDE_OPEN']['default']) { return; }if ($('#StreamHud').css('left') == '0px') {if (!StreamStats.status()) {StreamStats.start();}} else {StreamStats.stop();}});// Get the second last buttonconst $orgButton = $node.querySelector('div[class^=HUDButton]');if (!$orgButton) {return;}// 流监控设置if (!$btnStreamStats) {$btnStreamStats = cloneStreamHudButton($orgButton, "hd-stream-setting", "流监控设置", ICON_HD_STREAM_STATS);$btnStreamStats.addEventListener('click', e => {e.preventDefault();StreamStats.toggleSettingsUi();});}// 视频调整if (!$btnVideoSettings_HD) {$btnVideoSettings_HD = cloneStreamHudButton($orgButton, "hd-stream-setting", '视频调整', ICON_HD_VIDEO_SETTINGS);$btnVideoSettings_HD.addEventListener('click', e => {e.preventDefault();e.stopPropagation();// Show Quick settings bar$quickBar.style.display = 'flex';$parent.addEventListener('click', screenClicktohide());$parent.addEventListener('touchstart', screenClicktohide());const $touchSurface = document.getElementById('MultiTouchSurface');$touchSurface && $touchSurface.style.display != 'none' && $touchSurface.addEventListener('touchstart', screenClicktohide());});}// Insert buttons after Stream Settings button$orgButton.parentElement.insertBefore($btnStreamStats, $orgButton.parentElement.lastElementChild);$orgButton.parentElement.insertBefore($btnVideoSettings_HD, $btnStreamStats);if ($('#StreamHud').css('left') == '0px' && NFTconfig['STATS_SLIDE_OPEN']['default']) {StreamStats.start();}if (StreamStats.status()) {$('.ICON_HD_STREAM_STATS_ON').css("display", 'block');$('.ICON_HD_STREAM_STATS_OFF').css("display", 'none');} else {$('.ICON_HD_STREAM_STATS_ON').css("display", 'none');$('.ICON_HD_STREAM_STATS_OFF').css("display", 'block');}// Move the Dots button to the beginningconst $dotsButton = $orgButton.parentElement.lastElementChild;$dotsButton.parentElement.insertBefore($dotsButton, $dotsButton.parentElement.firstElementChild);});});});observer.observe($screen, { subtree: true, childList: true });}function patchVideoApi() {// Show video player when it's readylet showFunc;showFunc = function () {this.removeEventListener('playing', showFunc);if (!this.videoWidth) {return;}onStreamStarted(this);STREAM_WEBRTC?.getStats().then(stats => {if (NFTconfig['STATS_SHOW_WHEN_PLAYING']['default']) {StreamStats.start();}});}HTMLMediaElement.prototype.orgPlay = HTMLMediaElement.prototype.play;HTMLMediaElement.prototype.play = function () {if (letmeOb && NFTconfig['antiKick'] == 1) {const divElement = $('div[data-testid="ui-container"]')[0];const observer = new MutationObserver(function (mutations) {try {mutations.forEach(function (mutation) {if (mutation.type === 'childList') {mutation.addedNodes.forEach(function (addedNode) {let btn = $(addedNode).find('button[data-auto-focus="true"]');if ($(btn).length > 0 && btn.parent().children().length == 1) {$(btn).click();throw new Error("巴啦啦能量-呼#拉-魔仙变身!");}});}});} catch (e) { }});setTimeout(() => {observer.observe(divElement, { childList: true, subtree: true });console.log('antiKick已部署');}, 1000 * 20);letmeOb = false;}if (this.className && this.className.startsWith('XboxSplashVideo')) {this.volume = 0;this.style.display = 'none';this.dispatchEvent(new Event('ended'));return {catch: () => { },};return nativePlay.apply(this);}this.addEventListener('playing', showFunc);injectVideoSettingsButton();return this.orgPlay.apply(this);};}function onStreamStarted($video) {StreamBadges.resolution = { width: $video.videoWidth, height: $video.videoHeight };StreamBadges.startTimestamp = +new Date;// Get battery leveltry {navigator.getBattery && navigator.getBattery().then(bm => {StreamBadges.startBatteryLevel = Math.round(bm.level * 100);});STREAM_WEBRTC.getStats().then(stats => {const allVideoCodecs = {};let videoCodecId;const allAudioCodecs = {};let audioCodecId;const allCandidates = {};let candidateId;stats.forEach(stat => {if (stat.type == 'codec') {const mimeType = stat.mimeType.split('/');if (mimeType[0] === 'video') {// Store all video statsallVideoCodecs[stat.id] = stat;} else if (mimeType[0] === 'audio') {// Store all audio statsallAudioCodecs[stat.id] = stat;}} else if (stat.type === 'inbound-rtp' && stat.packetsReceived > 0) {// Get the codecId of the video/audio track currently being usedif (stat.kind === 'video') {videoCodecId = stat.codecId;} else if (stat.kind === 'audio') {audioCodecId = stat.codecId;}} else if (stat.type === 'candidate-pair' && stat.packetsReceived > 0 && stat.state === 'succeeded') {candidateId = stat.remoteCandidateId;} else if (stat.type === 'remote-candidate') {allCandidates[stat.id] = stat.address;}});// Get video codec from codecIdif (videoCodecId) {const videoStat = allVideoCodecs[videoCodecId];const video = {codec: videoStat.mimeType.substring(6),};if (video.codec === 'H264') {const match = /profile-level-id=([0-9a-f]{6})/.exec(videoStat.sdpFmtpLine);video.profile = match ? match[1] : null;}StreamBadges.video = video;}// Get audio codec from codecIdif (audioCodecId) {const audioStat = allAudioCodecs[audioCodecId];StreamBadges.audio = {codec: audioStat.mimeType.substring(6),bitrate: audioStat.clockRate,}}// Get server typeif (candidateId) {//console.log(candidateId, allCandidates);StreamBadges.ipv6 = allCandidates[candidateId].includes(':');}});} catch (e) { }}function moveCodecToIndex(array, currentIndex, targetIndex, element) {array.splice(currentIndex, 1);array.splice(targetIndex, 0, element);}function customizeRtcCodecs() {const customCodecProfile = NFTconfig['rtcCodecPreferences']['default'];if (customCodecProfile === '默认') {console.log("customizeRtcCodecs:默认");return;}if (typeof RTCRtpTransceiver === 'undefined' || !('setCodecPreferences' in RTCRtpTransceiver.prototype)) {return false;}let codecProfilePrefix = "";let codecProfileLevelId = "";let codecMimeType = "";const codecProfileMap = { "264": { "高": "4d", "中": "42e", "低": "420" } };if (customCodecProfile.includes("264")) {const codecLevel = Object.keys(codecProfileMap["264"]).find(level => customCodecProfile.includes(level));if (codecLevel) {codecProfilePrefix = codecProfileMap["264"][codecLevel];codecProfileLevelId = `profile-level-id=${codecProfilePrefix}`;}} else {codecMimeType = "video/" + customCodecProfile;}RTCRtpTransceiver.prototype.originalSetCodecPreferences = RTCRtpTransceiver.prototype.setCodecPreferences;RTCRtpTransceiver.prototype.setCodecPreferences = function (codecs) {let customizedCodecs = null;if (customCodecProfile === '自动') {let a = [];let b = [];let c = [];let d = [];codecs.slice().forEach((item) => {if (item.mimeType == 'video/H264') {if (item.sdpFmtpLine.indexOf('id=4d') > -1) {a.push(item);} else if (item.sdpFmtpLine.indexOf('id=42e') > -1) {b.push(item);} else if (item.sdpFmtpLine.indexOf('id=420') > -1) {c.push(item);} else {d.push(item);}} else {d.push(item);}});customizedCodecs = a.concat(b, c, d);} else {customizedCodecs = codecs.slice();let insertionIndex = 0;customizedCodecs.forEach((codec, index) => {if (codecProfileLevelId !== '' && codec.sdpFmtpLine && codec.sdpFmtpLine.includes(codecProfileLevelId)) {moveCodecToIndex(customizedCodecs, index, insertionIndex, codec);insertionIndex++;} else if (codec.mimeType === codecMimeType) {moveCodecToIndex(customizedCodecs, index, insertionIndex, codec);insertionIndex++;}});}try {this.originalSetCodecPreferences.apply(this, [customizedCodecs]);console.log("编解码偏好配置成功");} catch (error) {console.log("无法修改编解码配置,将使用默认设置");this.originalSetCodecPreferences.apply(this, [codecs]);}}}customizeRtcCodecs();patchVideoApi();let mslogotimeOut = 0;function mslogoClickevent(mslogoInterval, s) {let mslogodom = $($('header>div>div>button')[1]);if (mslogodom.length > 0) {clearInterval(mslogoInterval);mslogodom = mslogodom.next();if (mslogodom.text() == ("⚙️ 设置" + nftxboxversion)) { return; }mslogodom.removeAttr('href');mslogodom.css("color", 'white');mslogodom.text("⚙️ 设置" + nftxboxversion);mslogodom.click(() => {naifeitian.showSetting();});setTimeout(() => { mslogoClickevent(mslogoInterval) }, 5000);}mslogotimeOut = mslogotimeOut + 1;if (mslogotimeOut > 10) {mslogotimeOut = 0;clearInterval(mslogoInterval);}}let mslogoInterval = setInterval(() => {mslogoClickevent(mslogoInterval, 3000);}, 1000);class Dialog {constructor(title, className, $content, onClose) {const CE = createElement;// Create dialog overlaythis.$overlay = document.querySelector('.bx-dialog-overlay');if (!this.$overlay) {this.$overlay = CE('div', { 'class': 'bx-dialog-overlay bx-gone' });document.documentElement.appendChild(this.$overlay);}let $close;this.onClose = onClose;this.$dialog = CE('div', { 'class': `bx-dialog ${className} bx-gone` },CE('b', {}, title),CE('div', { 'class': 'bx-dialog-content' }, $content),$close = CE('button', {}, "关闭"));$close.addEventListener('click', e => {this.hide(e);});document.documentElement.appendChild(this.$dialog);}show() {this.$dialog.classList.remove('bx-gone');this.$overlay.classList.remove('bx-gone');}hide(e) {this.$dialog.classList.add('bx-gone');this.$overlay.classList.add('bx-gone');this.onClose && this.onClose(e);}toggle() {this.$dialog.classList.toggle('bx-gone');this.$overlay.classList.toggle('bx-gone');}preload() {this.$dialog.classList.add('bx-gone');this.$overlay.classList.add('bx-gone');}}let REMOTE_PLAY_CONFIG;let IS_REMOTE_PLAYING;let REMOTE_PLAY_SERVER;class RemotePlay {static XCLOUD_TOKEN;static XHOME_TOKEN;static #CONSOLES;static #STATE_LABELS = {'On': "已开机",'Off': "已关机",'ConnectedStandby': "待机中",'Unknown': "未知",};static get BASE_DEVICE_INFO() {return {appInfo: {env: {clientAppId: window.location.host,clientAppType: 'browser',clientAppVersion: '21.1.98',clientSdkVersion: '8.5.3',httpEnvironment: 'prod',sdkInstallId: '',},},dev: {displayInfo: {dimensions: {widthInPixels: 1920,heightInPixels: 1080,},pixelDensity: {dpiX: 1,dpiY: 1,},},hw: {make: 'Microsoft',model: 'unknown',sdktype: 'web',},os: {name: 'windows',ver: '22631.2715',platform: 'desktop',},browser: {browserName: 'chrome',browserVersion: '119.0',},},};}static #dialog;static #$content;static #$consoles;static #initialize() {if (RemotePlay.#$content) {return;}const CE = createElement;RemotePlay.#$content = CE('div', {}, "获取控制台列表");RemotePlay.#dialog = new Dialog(("串流"), '', RemotePlay.#$content);RemotePlay.#getXhomeToken(() => {RemotePlay.#getConsolesList(() => {console.log(RemotePlay.#CONSOLES);RemotePlay.#renderConsoles();});});}static #renderConsoles() {const CE = createElement;const $fragment = document.createDocumentFragment();if (!RemotePlay.#CONSOLES || RemotePlay.#CONSOLES.length === 0) {$fragment.appendChild(CE('span', {}, "未找到主机"));} else {const $settingNote = CE('p', {});const resolutions = [1080, 720];const currentResolution = NFTconfig['REMOTE_PLAY_RESOLUTION']['default'];const $resolutionSelect = CE('select', {});for (const resolution of resolutions) {const value = `${resolution}p`;const $option = CE('option', { 'value': value }, value);if (currentResolution === value) {$option.selected = true;}$resolutionSelect.appendChild($option);}$resolutionSelect.addEventListener('change', e => {const value = $resolutionSelect.value;$settingNote.textContent = value === '1080p' ? '✅ ' + "可串流xbox360游戏" : '❌ ' + "不可串流xbox360游戏";NFTconfig['REMOTE_PLAY_RESOLUTION']['default'] = value;naifeitian.setValue(NFTconfig['REMOTE_PLAY_RESOLUTION']['name'], NFTconfig['REMOTE_PLAY_RESOLUTION']);});$resolutionSelect.dispatchEvent(new Event('change'));const $qualitySettings = CE('div', { 'class': 'bx-remote-play-settings' },CE('div', {},CE('label', {}, "目标分辨率", $settingNote),$resolutionSelect,));$fragment.appendChild($qualitySettings);}for (let con of RemotePlay.#CONSOLES) {let $connectButton;const $child = CE('div', { 'class': 'bx-remote-play-device-wrapper' },CE('div', { 'class': 'bx-remote-play-device-info' },CE('div', {},CE('span', { 'class': 'bx-remote-play-device-name' }, con.deviceName),CE('span', { 'class': 'bx-remote-play-console-type' }, con.consoleType)),CE('div', { 'class': 'bx-remote-play-power-state' }, RemotePlay.#STATE_LABELS[con.powerState]),),$connectButton = CE('button', { 'class': 'bx-primary-button bx-no-margin' }, "连接"),);$connectButton.addEventListener('click', e => {REMOTE_PLAY_CONFIG = {serverId: con.serverId,};window.BX_REMOTE_PLAY_CONFIG = REMOTE_PLAY_CONFIG;const url = window.location.href.substring(0, 31) + '/launch/fortnite/BT5P2X999VH2#remote-play';const $pageContent = document.getElementById('PageContent');const $anchor = CE('a', { href: url, class: 'bx-hidden', style: 'position:absolute;top:-9990px;left:-9999px' }, '');$anchor.addEventListener('click', e => {setTimeout(() => {$pageContent.removeChild($anchor);}, 1000);});$pageContent.appendChild($anchor);$anchor.click();RemotePlay.#dialog.hide();});$fragment.appendChild($child);}RemotePlay.#$content.parentElement.replaceChild($fragment, RemotePlay.#$content);}static detect() {IS_REMOTE_PLAYING = window.location.pathname.includes('/remote-play') || window.location.hash.startsWith('#remote-play');if (IS_REMOTE_PLAYING) {window.BX_REMOTE_PLAY_CONFIG = REMOTE_PLAY_CONFIG;// 移除 /launch/...window.history.replaceState({}, '', 'https://www.xbox.com/' + location.pathname.substring(1, 6) + '/remote-play');} else {window.BX_REMOTE_PLAY_CONFIG = null;}}static #getXhomeToken(callback) {if (RemotePlay.XHOME_TOKEN) {callback();return;}let GSSV_TOKEN;try {const xboxUserInfo = JSON.parse(localStorage.getItem('xboxcom_xbl_user_info'));GSSV_TOKEN = xboxUserInfo.tokens['http://gssv.xboxlive.com/'].token;} catch (e) {for (let i = 0; i < localStorage.length; i++) {const key = localStorage.key(i);if (key.startsWith('Auth.User.')) {const json = JSON.parse(localStorage.getItem(key));GSSV_TOKEN = json.tokens.find(token => token.relyingParty.includes('gssv.xboxlive.com'))?.tokenData.token;if (GSSV_TOKEN) {break;}}}}fetch('https://xhome.gssv-play-prod.xboxlive.com/v2/login/user', {method: 'POST',body: JSON.stringify({offeringId: 'xhome',token: GSSV_TOKEN,}),headers: {'Content-Type': 'application/json; charset=utf-8',},}).then(resp => resp.json()).then(json => {RemotePlay.XHOME_TOKEN = json.gsToken;callback();});}//获取xbox列表static async #getConsolesList(callback) {if (RemotePlay.#CONSOLES) {callback();return;}let servers;if (!REMOTE_PLAY_SERVER) {if (NFTconfig['REMOTE_SERVER_LIST'].length == 0) {servers = ['wus2', 'eus', 'uks', 'ejp'];} else {servers = NFTconfig['REMOTE_SERVER_LIST'];}} else {servers = REMOTE_PLAY_SERVER;}const options = {method: 'GET',headers: {'Authorization': `Bearer ${RemotePlay.XHOME_TOKEN}`,},};const controller = new AbortController();const signal = controller.signal;let foundResponse = false;const promises = NFTconfig['REMOTE_SERVER_LIST'].map(async (server) => {const url = `https://${server}.core.gssv-play-prodxhome.xboxlive.com/v6/servers/home?mr=50`;try {const response = await fetch(url, { ...options, signal });const json = await response.json();if (json.r###lts && !foundResponse) {foundResponse = true;RemotePlay.#CONSOLES = json.r###lts;REMOTE_PLAY_SERVER = server;// 取消剩余请求controller.abort();return 'Found response';}} catch (error) {console.log(`请求至服务器 ${server} 时遇到错误,已忽略:`, error);}});// 等待所有请求完成const r###lts=await Promise.allSettled(promises);// 检查是否有请求成功const successfulR###lt = r###lts.find(r###lt => r###lt.status === 'fulfilled' && r###lt.value === 'Found response');if (successfulR###lt) {callback();} else {RemotePlay.#CONSOLES = [];}}static preload() {RemotePlay.#initialize();RemotePlay.#dialog.preload();}static showDialog() {RemotePlay.#initialize();RemotePlay.#dialog.show();}}function bindmslogoevent() {let divElement = $('#gamepass-root > div > div');if (divElement.length == 0) {setTimeout(() => {bindmslogoevent();}, 2333);return;}divElement = divElement.get(0);let mslogodom = $(divElement).children('header').find('a[href]');if (mslogodom.length == 0) {setTimeout(() => {bindmslogoevent();}, 2333);return;}if (mslogodom.length > 0) { mslogodom = $(mslogodom.get(0)); }let linkElement = $("a:contains('⚙️ 设置" + nftxboxversion + "')");for (let i = 0; i < linkElement.length; i++) {let ele = linkElement.get(i);if ($(ele).attr('class').indexOf('button') > -1) {return;}}mslogodom.removeAttr('href');mslogodom.css("color", 'white');mslogodom.text("⚙️ 设置" + nftxboxversion);mslogodom.click(() => {naifeitian.showSetting();});if (NFTconfig['enableRemotePlay'] == 1) {let remotePlayBtn = $('.bx-remote-play-button');if (remotePlayBtn.length > 0) { return; }//添加串流按钮var targetElement = $("[title*='Account Settings']");var newButton = $(`<button class="bx-remote-play-button" title="远程串流"><svg fill="none" stroke="#fff" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" viewBox="0 0 32 32"><g transform="matrix(.492308 0 0 .581818 -14.7692 -11.6364)"><clipPath id="A"><path d="M30 20h65v55H30z"></path></clipPath><g clip-path="url(#A)"><g transform="matrix(.395211 0 0 .334409 11.913 7.01124)"><g transform="matrix(.555556 0 0 .555556 57.8889 -20.2417)" fill="none" stroke="#fff" stroke-width="13.88"><path d="M200 140.564c-42.045-33.285-101.955-33.285-144 0M168 165c-23.783-17.3-56.217-17.3-80 0"></path></g><g transform="matrix(-.555556 0 0 -.555556 200.111 262.393)"><g transform="matrix(1 0 0 1 0 11.5642)"><path d="M200 129c-17.342-13.728-37.723-21.795-58.636-24.198C111.574 101.378 80.703 109.444 56 129" fill="none" stroke="#fff" stroke-width="13.88"></path></g><path d="M168 165c-23.783-17.3-56.217-17.3-80 0" fill="none" stroke="#fff" stroke-width="13.88"></path></g><g transform="matrix(.75 0 0 .75 32 32)"><path d="M24 72h208v93.881H24z" fill="none" stroke="#fff" stroke-linejoin="miter" stroke-width="9.485"></path><circle cx="188" cy="128" r="12" stroke-width="10" transform="matrix(.708333 0 0 .708333 71.8333 12.8333)"></circle><path d="M24.358 103.5h110" fill="none" stroke="#fff" stroke-linecap="butt" stroke-width="10.282"></path></g></g></g></g></svg></button>`);newButton.on("click", function () {RemotePlay.showDialog();});newButton.insertBefore(targetElement);}setTimeout(() => { bindmslogoevent() }, 5000);}bindmslogoevent();if (window.location.pathname.includes('/play/')) {NFTconfig['PATCH_ORDERS'] = NFTconfig['PATCH_ORDERS'].concat(NFTconfig['PLAYING_PATCH_ORDERS']);} else {NFTconfig['PATCH_ORDERS'].push(['loadingEndingChunks']);}naifeitian.patchFunctionBind();RemotePlay.detect();if (window.location.pathname.toLocaleLowerCase() == '/zh-cn/play') {window.location.href = "https://www.xbox.com/en-us/play";}if (window.location.href.endsWith('consoles/remote-play') || window.location.href.endsWith('/remote-play')) {//https://www.xbox.com/en-US/consoles/remote-playlet jurl = window.location.href.replace('/consoles', '');jurl = window.location.href.replace('/remote-play', '/play');window.location.href = jurl;}if (window.location.href.endsWith('play/dev-tools')) {window.location.href="/play"}RTCPeerConnection.prototype.orgAddIceCandidate = RTCPeerConnection.prototype.addIceCandidate;RTCPeerConnection.prototype.addIceCandidate = function (...args) {STREAM_WEBRTC = this;return this.orgAddIceCandidate(...args);};function addCss() {let popCss = `#popSetting {width: 76px;height: 33px;background: #fff;position: absolute;top: 30%;cursor: pointer;box-sizing: border-box;background-size: 100% 100%;overflow: hidden;font-family: Arial;font-size: 18px;line-height: 30px;font-weight: bold;color: #000000bf;border: 2px solid;border-radius: 10px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none ;}.better-xcloud-hidden {visibility: hidden !important;}.hd-stream-setting-hide{pointer-events: none !important;}div[class^=HUDButton-module__hiddenContainer] ~ div:not([class^=HUDButton-module__hiddenContainer]) {opacity: 0;position: absolute;top: -9999px;left: -9999px;}.bx-remote-play-button {height: auto;margin-right: 8px !important;position: relative;background-color: transparent;border:0px;border-radius: 50%;}.bx-remote-play-button svg {width: 28px;height: 46px;}.bx-remote-play-button:hover {background-color: #515863;}.better-xcloud-stats-bar {display: block;user-select: none;position: fixed;top: 0;background-color: #000;color: #fff;font-family: Consolas, "Courier New", Courier, monospace;font-size: 0.9rem;padding-left: 8px;z-index: 1000;text-wrap: nowrap;}.better-xcloud-stats-bar[data-position=top-left] {left: 20px;}.better-xcloud-stats-bar[data-position=top-right] {right: 0;}.better-xcloud-stats-bar[data-position=top-center] {transform: translate(-50%, 0);left: 50%;}.better-xcloud-stats-bar[data-transparent=true] {background: none;filter: drop-shadow(1px 0 0 #000) drop-shadow(-1px 0 0 #000) drop-shadow(0 1px 0 #000) drop-shadow(0 -1px 0 #000);}.better-xcloud-stats-bar label {margin: 0 8px 0 0;font-family: Bahnschrift, Arial, Helvetica, sans-serif;font-size: inherit;font-weight: bold;vertical-align: middle;}.better-xcloud-stats-bar span {min-width: 60px;display: inline-block;text-align: right;padding-right: 8px;margin-right: 8px;border-right: 2px solid #fff;vertical-align: middle;}.better-xcloud-stats-bar div {min-width: 60px;display: inline-block;text-align: right;padding-right: 8px;margin-right: 8px;border-right: 2px solid #fff;vertical-align: middle;float:left}.better-xcloud-stats-bar span[data-grade=good] {color: #6bffff;}.better-xcloud-stats-bar span[data-grade=ok] {color: #fff16b;}.better-xcloud-stats-bar span[data-grade=bad] {color: #ff5f5f;}.better-xcloud-stats-bar span:first-of-type {min-width: 30px;}.better-xcloud-stats-bar span:last-of-type {border: 0;margin-right: 0;}.better-xcloud-stats-bar div:last-of-type {border: 0;margin-right: 0;}.better-xcloud-stats-settings {display: none;position: fixed;top: 50%;left: 50%;margin-right: -50%;transform: translate(-50%, -50%);width: 420px;padding: 20px;border-radius: 8px;z-index: 500;background: #1a1b1e;color: #fff;font-weight: 400;font-size: 16px;font-family: "Segoe UI", Arial, Helvetica, sans-serif;box-shadow: 0 0 6px #000;user-select: none;overflow-y: auto;}.better-xcloud-stats-settings *:focus {outline: none !important;}.better-xcloud-stats-settings > b {color: #fff;display: block;font-family: Bahnschrift, Arial, Helvetica, sans-serif;font-size: 26px;font-weight: 400;line-height: 32px;margin-bottom: 12px;}.better-xcloud-stats-settings > div {display: flex;margin-bottom: 8px;padding: 2px 4px;}.better-xcloud-stats-settings label {flex: 1;margin-bottom: 0;align-self: center;}.better-xcloud-stats-settings button {padding: 8px 32px;margin: 20px auto 0;border: none;border-radius: 4px;display: block;background-color: #2d3036;text-align: center;color: white;text-transform: uppercase;font-family: Bahnschrift, Arial, Helvetica, sans-serif;font-weight: 400;line-height: 18px;font-size: 14px;}@media (hover: hover) {.better-xcloud-stats-settings button:hover {background-color: #515863;}}.better-xcloud-stats-settings button:focus {background-color: #515863;}.better-xcloud-gone {display: none !important;}.better-xcloud-quick-settings-bar {display: none;user-select: none;-webkit-user-select: none;position: fixed;bottom: 10%;left: 50%;transform: translate(-50%, 0);z-index: 9999;padding: 16px;width: 600px;background: #1a1b1e;color: #fff;border-radius: 8px 8px 0 0;font-weight: 400;font-size: 14px;font-family: Bahnschrift, Arial, Helvetica, sans-serif;text-align: center;box-shadow: 0px 0px 6px #000;opacity: 0.95;}.better-xcloud-quick-settings-bar *:focus {outline: none !important;}.better-xcloud-quick-settings-bar > div {flex: 1;}.better-xcloud-quick-settings-bar label {font-size: 16px;display: block;margin-bottom: 8px;}.better-xcloud-quick-settings-bar input {width: 22px;height: 22px;}.better-xcloud-quick-settings-bar button {border: none;width: 22px;height: 22px;margin: 0 4px;line-height: 22px;background-color: #515151;color: #fff;border-radius: 4px;}@media (hover: hover) {.better-xcloud-quick-settings-bar button:hover {background-color: #414141;color: white;}}.better-xcloud-quick-settings-bar button:active {background-color: #414141;color: white;}.better-xcloud-quick-settings-bar span {display: inline-block;width: 40px;font-weight: bold;font-family: Consolas, "Courier New", Courier, monospace;}.closeSetting1 {color: #0099CC;background: transparent;border: 2px solid #0099CC;border-radius: 6px;border: none;color: white;padding: 3px 13px;text-align: center;display: inline-block;font-size: 16px;margin: 4px 2px;-webkit-transition-duration: 0.4s; /* Safari */transition-duration: 0.4s;cursor: pointer;text-decoration: none;text-transform: uppercase;}.closeSetting2 {background-color: white;color: black;border: 2px solid #008CBA;display: block;margin: 0 auto;margin-top: 5px;}.closeSetting2:hover {background-color: #008CBA;color: white;}.settingsBackgroud{position: fixed;left: 0;top: 0;background: #0000;width: 100%;height: 90vh;overflow: scroll;z-index:8888;}.settingsBox{position: relative;background: wheat;width: fit-content;height: fit-content;border-radius: 5px;margin: 5% auto;padding: 10px;font-family: '微软雅黑';line-height: 22px;top:5%;z-index:8889;}.settingsBoxInputRadio{background-color: initial;cursor: pointer;appearance: auto;box-sizing: border-box;margin: 3px 3px 0px 5px;padding: initial;padding-top: initial;padding-right: initial;padding-bottom: initial;padding-left: initial;border: initial;-webkit-appearance: checkbox;accent-color: dodgerblue;}#StreamHud >div{background-color:rgba(255,0,0,0)!important;}#StreamHud >button{background-color:rgba(0,0,0,0)!important;}#StreamHud >button > div{opacity:0.3!important;}#touchControllerEventArea {pointer-events: auto;position: fixed;bottom: 0;right: 0;width: 33%;height: 6vh;z-index: 5678;background-color: rgba(0, 0, 0, 0);}.better-xcloud-badges {position: absolute;margin-left: 0px;user-select: none;-webkit-user-select: none;bottom: 0px;display: none;}/* 横屏 */@media screen and (orientation: landscape) {.better-xcloud-badges {display: block; /* 显示 */}}/* 竖屏 */@media screen and (orientation: portrait) {.better-xcloud-badges {display: none; /* 隐藏 */}}button[class*=BaseItem-module__container] {height:fit-content;}div[class*=Menu-module__scrollable] {height:225px;}.better-xcloud-badge {border: none;display: inline-block;line-height: 24px;color: #fff;font-family: Bahnschrift Semibold, Arial, Helvetica, sans-serif;font-size: 14px;font-weight: 400;margin: 0 8px 8px 0;box-shadow: 0px 0px 6px #000;border-radius: 4px;}.better-xcloud-badge-name {background-color: #2d3036;display: inline-block;padding: 2px 8px;border-radius: 4px 0 0 4px;text-transform: uppercase;}.better-xcloud-badge-value {background-color: grey;display: inline-block;padding: 2px 8px;border-radius: 0 4px 4px 0;}.better-xcloud-badge-battery[data-charging=true] span:first-of-type::after {content: ' ⚡️';}div[class*=NotFocusedDialog-module__container] {display:none}@keyframes blink {20% {color: blueviolet; }50% { color: blue; }100% { color: green; }}.blink-text {font-size: 15px;font-weight: bold;animation: blink 3s infinite;float: right;cursor: pointer;display:none}.remote-play-button {background-color: transparent;border: none;color: white;font-weight: bold;line-height: 30px;border-radius: 4px;padding: 8px;}.remote-play-button:hover, .remote-play-button:focus {background-color: #515863;}.bx-dialog-overlay {position: fixed;inset: 0;z-index: var(--bx-dialog-overlay-z-index);background: black;opacity: 50%;}.bx-dialog {display: flex;flex-flow: column;max-height: 90vh;position: fixed;top: 50%;left: 50%;margin-right: -50%;transform: translate(-50%, -50%);max-width: 410px;width:95%;padding: 20px;border-radius: 8px;z-index: var(--bx-dialog-z-index);background: #1a1b1e;color: #fff;font-weight: 400;font-size: 16px;font-family: var(--bx-normal-font);box-shadow: 0 0 6px #000;user-select: none;-webkit-user-select: none;}.bx-dialog *:focus {outline: none !important;}.bx-dialog > b {color: #fff;display: block;font-family: var(--bx-title-font);font-size: 26px;font-weight: 400;line-height: 32px;margin-bottom: 12px;}.bx-dialog > div {overflow: auto;padding: 2px 0;}.bx-dialog > button {padding: 8px 32px;margin: 20px auto 0;border: none;border-radius: 4px;display: block;background-color: #2d3036;text-align: center;color: white;text-transform: uppercase;font-family: var(--bx-title-font);font-weight: 400;line-height: 18px;font-size: 14px;}.bx-gone {display: none !important;}.bx-remote-play-settings {margin-bottom: 12px;padding-bottom: 12px;border-bottom: 1px solid #2d2d2d;}.bx-remote-play-settings > div {display: flex;}.bx-remote-play-settings label {flex: 1;}.bx-remote-play-settings label p {margin: 4px 0 0;padding: 0;color: #888;font-size: 12px;}.bx-remote-play-settings input {display: block;margin: 0 auto;}.bx-remote-play-settings span {font-weight: bold;font-size: 18px;display: block;margin-bottom: 8px;text-align: center;}.bx-remote-play-device-name {font-size: 20px;font-weight: bold;display: inline-block;vertical-align: middle;}.bx-remote-play-console-type {font-size: 12px;background: #888;color: #fff;display: inline-block;border-radius: 14px;padding: 2px 10px;margin-left: 8px;vertical-align: middle;}.bx-remote-play-power-state {color: #888;font-size: 14px;}.bx-remote-play-power-state {color: #888;font-size: 14px;}.bx-primary-button {padding: 8px 32px;margin: 10px auto 0;border: none;border-radius: 4px;display: block;background-color: #044e2a;text-align: center;color: white;text-transform: uppercase;font-family: var(--bx-title-font);font-weight: 400;font-size: 14px;line-height: 24px;}@media (hover: hover) {.bx-primary-button:hover {background-color: #00753c;}}.bx-primary-button:focus {background-color: #00753c;}.bx-primary-button:active {background-color: #00753c;}.bx-primary-button[disabled] {background: #393939;color: #a2a2a2;}.bx-no-margin {margin: 0 !important;}.bx-remote-play-device-info {flex: 1;padding: 4px 0;}.bx-remote-play-device-wrapper {display: flex;margin-bottom: 8px;}.bx-remote-play-device-wrapper:not(:last-child) {margin-bottom: 14px;}#xcloud_setting_STATS_BUTTON{background-color: cadetblue;width:100%;}.stats-container {width: 30%;border:1px solid white;}.drag-handle {cursor: pointer;margin: 5px;padding: 6px;border: 1px solid #ccc;border-radius: 5px;background-color: #f9f9f9;transition: background-color 0.2s ease;position: relative;color:black;height: 30px;}.drag-handle::after {content: "≡";position: absolute;right: 5px;top: 50%;transform: translateY(-50%);color: #999;}.drag-handle.drag-over {background-color: #e0f0ff;}.drag-handle.dragging {opacity: 0.5;}.drag-handle.stats-selected {background-color: #cbffcd;}.drag-handle.stats-delete {text-decoration: line-through;}.placeholder {border: 1px dashed #ccc;border-radius: 5px;margin: 5px;height: 30px;display: none;background-color:#c5c5c5!important;}/* 新增样式,用于被拖拽元素的副本 */.dragged-copy-item {position: absolute;z-index: 1000;pointer-events: none;/* 防止被拖拽元素副本干扰其他事件 */display: none;width:100px}`;if (NFTconfig['disableTouchControls'] == 1) {popCss += `#MultiTouchSurface, #BabylonCanvasContainer-main {display: none !important;}`};let xfbasicStyle = document.createElement('style');xfbasicStyle.innerHTML = popCss;let docxf = document.head || document.documentElement;docxf.appendChild(xfbasicStyle);}addCss();crturl = window.location.href;console.log("all done");})();