Xbox CLoud Gaming优化整合

整合和修改现有脚本,优化项详见脚本说明。【若你有好的想法或者BUG可以进xbox云游戏交流群531602832反馈】

As of 26/02/2023. See the latest version.

// ==UserScript==
// @name                 Xbox CLoud Gaming优化整合
// @name:zh-CN           Xbox CLoud Gaming优化整合
// @namespace            http://tampermonkey.net/xbox/nft
// @version              2.0.9
// @author               奈非天
// @match                https://www.xbox.com/*/play*
// @run-at               document-start
// @grant                unsafeWindow
// @grant                GM_registerMenuCommand
// @require              https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.2.1/jquery.min.js
// @original-script      https://greasyfork.org/zh-CN/scripts/455741-xbox-cloud-gaming%E4%BC%98%E5%8C%96%E6%95%B4%E5%90%88
// @description:zh-cn    整合和修改现有脚本,优化项详见脚本说明。【若你有好的想法或者BUG可以进xbox云游戏交流群531602832反馈】
// @description          整合和修改现有脚本,优化项详见脚本说明。【若你有好的想法或者BUG可以进xbox云游戏交流群531602832反馈】
// ==/UserScript==
(function() {


    'use strict';
    // Your code here...

    //========↓↓↓↓↓是各个功能的总开关↓↓↓↓↓========//
    //★★ 1=开   0=关 ★★//

    //免代理直连
    let no_need_VPN_play=1;

    let regionsList={'韩':'168.126.63.1'
                     ,'美':'4.2.2.2'
                     ,'日':'210.131.113.123'
                    }

    //欺骗IP
    let fakeIp=regionsList['美'];

    //选择语言
    let chooseLanguage=1;
    //智能语言报错时默认使用的语言,简体zh-CN,繁体zh-TW,总开关是上一行的chooseLanguage
    let IfErrUsedefaultGameLanguage='zh-CN';

    //高码率,禁用后最高8M码率720P画质
    let high_bitrate=1;

    //使用触屏经典手柄布局(默认关闭)
    let useDefaultTouchControls=0;

    //禁止检测网络状况
    let disableCheckNetwork=1;

    //禁用游戏界面下拉刷新
    let no_pull_refresh=1;

    //自动全屏
    let autoFullScreen=0;

    //锁定云游戏服务器,注意此项并非是云游戏区域(默认关闭)
    let blockXcloudServer=0;
    //默认服务器 总开关是上一行的blockXcloudServer

    let blockXcloudServerList=['AustraliaEast','AustraliaSouthEast','BrazilSouth','EastUS','EastUS2','JapanEast','KoreaCentral','NorthCentralUs','SouthCentralUS','UKSouth','WestEurope','WestUS','WestUS2'];
    let defaultXcloudServer='KoreaCentral';

    //========↑↑↑↑↑是各个功能的总开关↑↑↑↑↑========//

    const originFetch = fetch;
    let regionsMenuItemList = [];
    let languageMenuItemList = [];
    let default_language_list={'智能简繁':'Auto','简体':'zh-CN','繁体':'zh-TW'}
    let xcloud_game_language=default_language_list['简体'];//
    let useCustomfakeIp=0;
    let customfakeIp='';
    let BasicControlsCheck=false;

    let windowCtx = self.window;
    if (self.unsafeWindow) {
        console.log("使用unsafeWindow模式");
        windowCtx = self.unsafeWindow;
    } else {
        console.log("使用原生模式");
    }

    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') {
                return localStorage.setItem(key, JSON.stringify(value));
            }
            return localStorage.setItem(key, value);
        },
        isValidIP(ip) {
            var 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);
        }
    }

    no_need_VPN_play=naifeitian.getValue("no_need_VPN_playGM")==null?no_need_VPN_play:naifeitian.getValue("no_need_VPN_playGM");
    naifeitian.setValue("no_need_VPN_playGM",no_need_VPN_play);

    chooseLanguage=naifeitian.getValue("chooseLanguageGM")==null?chooseLanguage:naifeitian.getValue("chooseLanguageGM");
    naifeitian.setValue("chooseLanguageGM",chooseLanguage);

    IfErrUsedefaultGameLanguage=naifeitian.getValue("IfErrUsedefaultGameLanguageGM")==null?IfErrUsedefaultGameLanguage:naifeitian.getValue("IfErrUsedefaultGameLanguageGM");
    naifeitian.setValue("IfErrUsedefaultGameLanguageGM",IfErrUsedefaultGameLanguage);

    fakeIp=naifeitian.getValue("fakeIpGM")==null?fakeIp:naifeitian.getValue("fakeIpGM");
    naifeitian.setValue("fakeIpGM",fakeIp);

    high_bitrate=naifeitian.getValue("high_bitrateGM")==null?high_bitrate:naifeitian.getValue("high_bitrateGM");
    naifeitian.setValue("high_bitrateGM",high_bitrate);

    useDefaultTouchControls=naifeitian.getValue("useDefaultTouchControlsGM")==null?useDefaultTouchControls:naifeitian.getValue("useDefaultTouchControlsGM");
    naifeitian.setValue("useDefaultTouchControlsGM",useDefaultTouchControls);

    disableCheckNetwork=naifeitian.getValue("disableCheckNetworkGM")==null?disableCheckNetwork:naifeitian.getValue("disableCheckNetworkGM");
    naifeitian.setValue("disableCheckNetworkGM",disableCheckNetwork);

    no_pull_refresh=naifeitian.getValue("no_pull_refreshGM")==null?no_pull_refresh:naifeitian.getValue("no_pull_refreshGM");
    naifeitian.setValue("no_pull_refreshGM",no_pull_refresh);

    blockXcloudServer=naifeitian.getValue("blockXcloudServerGM")==null?blockXcloudServer:naifeitian.getValue("blockXcloudServerGM");
    naifeitian.setValue("blockXcloudServerGM",blockXcloudServer);

    defaultXcloudServer=naifeitian.getValue("defaultXcloudServerGM")==null?defaultXcloudServer:naifeitian.getValue("defaultXcloudServerGM");
    naifeitian.setValue("defaultXcloudServerGM",defaultXcloudServer);

    xcloud_game_language=naifeitian.getValue("xcloud_game_languageGM")==null?xcloud_game_language:naifeitian.getValue("xcloud_game_languageGM");
    naifeitian.setValue("xcloud_game_languageGM",xcloud_game_language);

    useCustomfakeIp=naifeitian.getValue("useCustomfakeIpGM")==null?useCustomfakeIp:naifeitian.getValue("useCustomfakeIpGM");
    naifeitian.setValue("useCustomfakeIpGM",useCustomfakeIp);

    customfakeIp=naifeitian.getValue("customfakeIpGM")==null?customfakeIp:naifeitian.getValue("customfakeIpGM");
    naifeitian.setValue("customfakeIpGM",customfakeIp);

    autoFullScreen=naifeitian.getValue("autoFullScreenGM")==null?autoFullScreen:naifeitian.getValue("autoFullScreenGM");
    naifeitian.setValue("autoFullScreenGM",autoFullScreen);


    if(no_pull_refresh==1){
        $('*').on('touchmove', false);
    }

    if(useDefaultTouchControls==1){
        windowCtx.RTCPeerConnection.prototype.originalCreateDataChannelGTC = windowCtx.RTCPeerConnection.prototype.createDataChannel;
        windowCtx.RTCPeerConnection.prototype.createDataChannel = function (...params) {
            let dc = this.originalCreateDataChannelGTC(...params);
            let paddingMsgTimeoutId = 0;
            if (dc.label == "message") {
                dc.addEventListener("message", function (de) {
                    if (typeof(de.data) == "string") {
                        // console.debug(de.data);
                        let msgdata = JSON.parse(de.data);
                        if (msgdata.target == "/streaming/touchcontrols/showlayoutv2") {
                            clearTimeout(paddingMsgTimeoutId);
                        } else if (msgdata.target == "/streaming/touchcontrols/showtitledefault") {
                            if (msgdata.pluginHookMessage !== true) {
                                clearTimeout(paddingMsgTimeoutId);
                                paddingMsgTimeoutId = setTimeout(() => {
                                    dc.dispatchEvent(new MessageEvent('message', {
                                        data : '{"content":"{\\"layoutId\\":\\"\\"}","target":"/streaming/touchcontrols/showlayoutv2","type":"Message","pluginHookMessage":true}'
                                    }));
                                }, 1000);
                            }
                        }
                    }
                });
            }
            return dc;
        }
    }

    if(autoFullScreen==1){
        document.addEventListener('fullscreenchange', () => {
            screen?.orientation?.lock("landscape");
        });
        window.addEventListener("touchend", () => {
            const element = document.documentElement;
            let requestFullScreen = element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullScreen || element.msRequestFullscreen;
            if (!document.fullscreenElement) {
                requestFullScreen?.call(element, { "navigationUI": "hide" }).then(() => {
                    screen?.orientation?.lock("landscape");
                }).catch((error) => {
                    console.error(error);
                });
            }
            screen?.orientation?.lock("landscape");
        });
    }

    function HookProperty(object, property, value)
    {
        Object.defineProperty(object, property, {
            value: value
        });
    }

    let fakeuad = {
        "brands": [
            {
                "brand": "Microsoft Edge",
                "version": "999"
            },
            {
                "brand": "Chromium",
                "version": "999"
            },
            {
                "brand": "Not=A?Brand",
                "version": "24"
            }
        ],
        "mobile": false,
        "platform": "Windows"
    };
    try{
        if(high_bitrate==1){
            HookProperty(windowCtx.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(windowCtx.navigator, "appVersion", "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(windowCtx.navigator, "platform", "Win32");
            HookProperty(windowCtx.navigator, "appName", "Netscape");
            HookProperty(windowCtx.navigator, "appCodeName", "Mozilla");
            HookProperty(windowCtx.navigator, "product", "Gecko");
            HookProperty(windowCtx.navigator, "vendor", "Google Inc.");
            HookProperty(windowCtx.navigator, "vendorSub", "");
            HookProperty(windowCtx.navigator, "maxTouchPoints", undefined);
            HookProperty(windowCtx.navigator, "userAgentData", fakeuad);
        }
        if(disableCheckNetwork==1){
            //HookProperty(windowCtx.navigator, "connection", undefined);
            Object.defineProperty(windowCtx.navigator, 'connection', {
                get: function () {
                    return {
                        onchange: null,
                        effectiveType: '4g',
                        rtt: 0,
                        downlink: 10,
                        saveData: false,
                        addEventListener: function() {},
                        removeEventListener: function() {},
                    }; // Official check: rtt >= 100 || downlink <= 10 || saveData || effectiveType is ["slow-2g","2g","3g"]
                }
            });
        }
        HookProperty(windowCtx.navigator, "standalone", true);

    }catch(e){}

    //悬浮确认按钮
    let confirmBtn='.EditErgoMenu-module__topPanelBasicButton___tLdju.Button-module__typeBrand___1AMyM';
    //悬浮x按钮
    let basic_X_Btn='.EditErgoMenu-module__basicControlsButtonColor___1sLIY';
    //basic不需要的Class
    let basicFukClass='Button-module__overlayModeAcrylic___19h3Y';
    //悬浮···
    let threeDotBtn='.StreamHUD-module__button___4GEk2';
    //悬浮···后全屏
    let threeDotClickedScreen='.StreamMenu-module__container___2uc2J';
    //退出游戏确认按钮区域
    let quitGameArea='.PureInStreamConfirmationModal-module__buttonContainer___1Prkz';
    //退出游戏区域X和never mind按钮
    let quitGame_X_nm_btn='.Button-module__typeSecondary___2OJbk';
    //退出游戏确认按钮
    let quitGameConfirmBtn='.PureInStreamConfirmationModal-module__destructiveButton___3aGxP';
    //开启basic的开关
    let basicCheckBtn='.Button-module__decoratedButton___t4Zaz';
    //微软logo
    let mslogo=".c-sgl-stk-uhfLogo";
    //悬浮窗6个点Box
    let floatingSixDotBox='.GripHandle-module__container___3clUM';
    //悬浮窗6个点
    let floatingSixDot='.Grip-module__container___2t3Ev';
    //悬浮窗6个点left
    let floatingSixDotLeft='.StreamHUD-module__buttonsContainer___9B1o3';
    //选游页左上角
    let cloudGameBeta='.CloudGamingButton-module__text___i-aRJ';

    windowCtx.fetch = (...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 (url.indexOf('/v2/login/user') > -1){//xgpuweb.gssv-play-prod.xboxlive.com
            return new Promise((resolve, reject) => {
                if (isRequest && arg0.method == "POST") {
                    arg0.json().then(json => {
                        let body = JSON.stringify(json);
                        if(no_need_VPN_play==1){
                            console.log('xff欺骗开始'+url)
                            if(useCustomfakeIp==1 && naifeitian.isValidIP(customfakeIp)){
                                arg[0].headers.set('x-forwarded-for',customfakeIp);
                                console.log('自定义IP:'+customfakeIp);
                            }else{
                                arg[0].headers.set('x-forwarded-for',fakeIp);
                            }
                        }

                        arg[0] = new Request(url, {
                            method: arg0.method,
                            headers: arg0.headers,
                            body: body,

                        });
                        originFetch(...arg).then(res => {
                            console.log('xff欺骗结束');
                            res.json().then(json => {
                                json["offeringSettings"]["allowRegionSelection"] = true;
                                if(blockXcloudServer==1){
                                    console.log('修改服务器开始');
                                    let newServerList = [];
                                    let currentAutoServer;
                                    json["offeringSettings"]["regions"].forEach((region) => {
                                        newServerList.push(region["name"]);
                                        if (region["isDefault"] === true) {
                                            currentAutoServer = region["name"];
                                        }
                                    });

                                    let selectedServer=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('修改服务器结束');
                                }
                                let body = JSON.stringify(json);
                                let newRes = new Response(body, {
                                    status: res.status,
                                    statusText: res.statusText,
                                    headers: res.headers
                                })
                                resolve(newRes);
                            }).catch(err => {
                                reject(err);
                            });
                        }).catch(err => {
                            reject(err);
                        });
                    });

                } else {
                    console.error("[ERROR] Not a request.");
                    return originFetch(...arg);
                }
            });
        }else if (url.indexOf('/v5/sessions/cloud/play') > -1) {

            document.documentElement.style.overflowY = "hidden";

            changeBasicBtnCss();
            if(chooseLanguage==1){
                return new Promise(async(resolve, reject) => {
                    console.log('语言开始');
                    let selectedLanguage=xcloud_game_language;
                    console.log('语言选择:'+selectedLanguage);
                    if(selectedLanguage=='Auto'){
                        const regex = /\/([a-zA-Z0-9]+)\/?/gm;
                        let matches;
                        let latestMatch;
                        while ((matches = regex.exec(document.location.pathname)) !== null) {
                            if (matches.index === regex.lastIndex) {
                                regex.lastIndex++;
                            }
                            matches.forEach((match, groupIndex) => {
                                // console.log(`Found match, group ${groupIndex}: ${match}`);
                                latestMatch = match;
                            });
                        }
                        if (latestMatch) {
                            let pid = latestMatch;
                            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 languageSupport = jsonObj["Products"][pid]["LanguageSupport"]


                                for(let language of Object.keys(default_language_list)) {
                                    if (default_language_list[language] in languageSupport) {
                                        selectedLanguage=default_language_list[language];
                                        break;
                                    }
                                }

                                if(selectedLanguage=='Auto'){
                                    //防止接口没有返回支持语言
                                    selectedLanguage=IfErrUsedefaultGameLanguage;
                                }

                            }catch(e){}
                        }
                    }

                    if (isRequest && arg0.method == "POST") {
                        arg0.json().then(json => {
                            json["settings"]["locale"] = selectedLanguage;
                            let body = JSON.stringify(json);
                            arg[0] = new Request(url, {
                                method: arg0.method,
                                headers: arg0.headers,
                                body: body,
                                mode: arg0.mode,
                                credentials: arg0.credentials,
                                cache: arg0.cache,
                                redirect: arg0.redirect,
                                referrer: arg0.referrer,
                                integrity: arg0.integrity
                            });
                            originFetch(...arg).then(res => {
                                console.log(`语言结束, 选择语言: ${selectedLanguage}.`)
                                resolve(res);

                            }).catch(err => {
                                reject(err);
                            });
                        });
                    } else {
                        console.error("[ERROR] Not a request.");
                        return originFetch(...arg);
                    }
                });
            }else {
                return originFetch(...arg);
            }
        } else if (url.indexOf('/v2/titles') > -1) { // /v2/titles or /v2/titles/mru
            // Enable CustomTouchOverlay
            console.log('修改触摸开始')
            return new Promise((resolve, reject) => {
                originFetch(...arg).then(res => {
                    res.json().then(json => {
                        // console.error(json);
                        try {
                            //e.controller = "Controller",
                            //  e.mouseAndKeyboard = "MKB",
                            //  e.customTouchOverlay = "CustomTouchOverlay",
                            //   e.genericTouch = "GenericTouch",
                            //    e.nativeTouch = "NativeTouch",
                            //    e.nativeSensor = "NativeSensor"
                            json["results"].forEach(result => {
                                if (result["details"]["supportedInputTypes"].includes("CustomTouchOverlay") === false) {
                                    result["details"]["supportedInputTypes"].push("CustomTouchOverlay");
                                    // console.log("[Xbox Cloud Gaming Global Touch Controll] Hook " + result["titleId"]);
                                }
                                if (result["details"]["supportedInputTypes"].includes("MKB") === false) {
                                    result["details"]["supportedInputTypes"].push("MKB");
                                    // console.log("[Xbox Cloud Gaming Global Touch Controll] Hook " + result["titleId"]);
                                }
                                if (result["details"]["supportedInputTypes"].includes("GenericTouch") === false) {
                                    result["details"]["supportedInputTypes"].push("GenericTouch");
                                    // console.log("[Xbox Cloud Gaming Global Touch Controll] Hook " + result["titleId"]);
                                }
                                if (result["details"]["supportedInputTypes"].includes("NativeTouch") === false) {
                                    result["details"]["supportedInputTypes"].push("NativeTouch");
                                    // console.log("[Xbox Cloud Gaming Global Touch Controll] Hook " + result["titleId"]);
                                }
                            });
                        } catch (err) {}
                        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 changeBasicBtnCss(){
        let btnCss =
            basic_X_Btn+`{
        width:10px;
        min-width:10px;
        background-color:rgba(255,0,0,0)!important;
        overflow: hidden;
        color: white;
    }
    `+floatingSixDotBox+`{
        background:rgba(0, 0, 0, 0);
    }
    `+floatingSixDot+`{
        opacity:0.3;
    }
    `+floatingSixDotLeft+`{
        background-color:rgba(255,0,0,0)
    }  

    .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: 0px;
				top: 5%;
				background: #0000;
				width: 100%;
				height: 100%;
                overflow: scroll;
			}
			.settingsBox{
				position: relative;
				background: wheat;
				width: fit-content;
                height: fit-content;
				border-radius: 5px;
				margin: 5% auto;
                padding: 20px;
                font-family: '微软雅黑';
			}
           .settingsBoxInputRadio{
                background-color: initial;
                cursor: default;
                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;
            }

`;
        var basicStyle = document.createElement('style');
        basicStyle.innerHTML = btnCss;
        var doc = document.head || document.documentElement;
        doc.appendChild(basicStyle);
    }


    changeBasicBtnCss();
    $(document).on("click",basicCheckBtn,
                   function(){

        if($(this).attr('aria-checked')=='true'){
            BasicControlsCheck=true;
        }else{
            BasicControlsCheck=false;
        }
    });
    $(document).on("click",confirmBtn,
                   function(){
        if(BasicControlsCheck){
            $(basic_X_Btn).removeClass(basicFukClass);
        }
    });


    $(document).on("click",quitGameConfirmBtn,
                   function(){
        document.documentElement.style.overflowY = "";
    });

    let needrefresh=0;
    function initSettingBox() {

        let dom = '';
        dom += `<label  style="display: block;text-align:left;"><div   style="display: inline;">选择语言:</div>`;
        dom += `<input type="radio" class="chooseLanguageListener settingsBoxInputRadio" style="outline:none;" name='chooseLanguage' id="chooseLanguageOn" value="1" ${naifeitian.getValue('chooseLanguageGM') == 1 ? 'checked' : ''}><label for="chooseLanguageOn" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class="chooseLanguageListener settingsBoxInputRadio" style="outline:none;" name='chooseLanguage' id="chooseLanguageOff" value="0" ${naifeitian.getValue('chooseLanguageGM') == 0 ? 'checked' : ''}><label for="chooseLanguageOff" style="padding-right: 25px;">关</label>`;

        dom += `<label class=" chooseLanguageBlock" style="text-align:left;display:`+(naifeitian.getValue('chooseLanguageGM')==1?'block':'none')+`"><div   style="display: inline;">语言:</div>`;

        Object.keys(default_language_list).forEach(languageChinese => {
            dom += `<input type="radio" class="languageSingleListener settingsBoxInputRadio" style="outline:none;" name='selectLanguage' id="${default_language_list[languageChinese]}" value="${default_language_list[languageChinese]}" ${naifeitian.getValue('xcloud_game_languageGM') == default_language_list[languageChinese] ? 'checked' : ''}><label for="${default_language_list[languageChinese]}" style="padding-right: 15px;">${languageChinese}</label>`;
        });
        dom += `</label>`;

        dom += `</label>`;

        dom += `<label class=" IfErrUsedefaultGameLanguageBlock" style="display:`+ (naifeitian.getValue('xcloud_game_languageGM')=='Auto'?'block':'none')+`;text-align:left;"><div   style="display: inline;">智能错误时使用:</div>`;
        dom += `<input type="radio" style="outline:none;" name='IfErrUsedefaultGameLanguage' class="IfErrUsedefaultGameLanguageListener settingsBoxInputRadio" id="IfErrUsedefaultGameLanguageCN" value="zh-CN" ${naifeitian.getValue('IfErrUsedefaultGameLanguageGM') == 'zh-CN' ? 'checked' : ''}><label for="IfErrUsedefaultGameLanguageCN" style="padding-right: 15px;">简体</label>`;
        dom += `<input type="radio" style="outline:none;" name='IfErrUsedefaultGameLanguage' class="IfErrUsedefaultGameLanguageListener settingsBoxInputRadio" id="IfErrUsedefaultGameLanguageTW" value="zh-TW" ${naifeitian.getValue('IfErrUsedefaultGameLanguageGM') == 'zh-TW' ? 'checked' : ''}><label for="IfErrUsedefaultGameLanguageTW" style="padding-right: 15px;">繁体</label>`;
        dom += `</label><hr style="background-color: black;width:95%" />`;

        dom += `<label class="" style="display: block;text-align:left;"><div   style="display: inline;">免代理直连:</div>`;
        dom += `<input type="radio" class='noNeedVpnListener settingsBoxInputRadio' style="outline:none;" name='noNeedVpn' id="noNeedVpnOpen" value="1" ${naifeitian.getValue('no_need_VPN_playGM') == 1 ? 'checked' : ''}><label for="noNeedVpnOpen" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class='noNeedVpnListener settingsBoxInputRadio' style="outline:none;" name='noNeedVpn' id="noNeedVpnOff" value="0" ${naifeitian.getValue('no_need_VPN_playGM') == 0 ? 'checked' : ''}><label for="noNeedVpnOff" style="padding-right: 15px;">关</label>`;
        dom += `</label>`;


        dom += `<label class=" chooseRegionsBlock" style="text-align:left;display:`+(naifeitian.getValue('no_need_VPN_playGM')==1?'block':'none')+`"><div   style="display: inline;">欺骗IP:</div>`;


        Object.keys(regionsList).forEach(region => {
            dom += `<input type="radio" class="regionSingleListener settingsBoxInputRadio" style="outline:none;" name='selectRegion' id="${region}" value="${regionsList[region]}" ${naifeitian.getValue('fakeIpGM') == regionsList[region] ? 'checked' : ''}><label for="${region}" style="padding-right: 15px;">${region}</label>`;
        });
        dom += `<div style="display:block">`
        dom += `<input type="radio" class="regionSingleListener settingsBoxInputRadio" style="outline:none;" name='selectRegion' id="customfakeIp" value="customfakeIp" ${naifeitian.getValue('useCustomfakeIpGM') == 1 ? 'checked' : ''}><label for="customfakeIp" style="padding-right: 15px;">自定义IP:</label>`;

        dom += `<input type='text' style="display: `+(naifeitian.getValue('useCustomfakeIpGM')==1?'inline':'none')+`;outline: none;width: 125px;" id="customfakeIpInput" class="customfakeIpListener" value="${naifeitian.getValue('customfakeIpGM')}" placeholder="请输入IP"/>`
        dom += `</div>`
        dom+=`</label><hr style="background-color: black;width:95%" />`;

        dom += `<label class="" style="display: block;text-align:left;"><div   style="display: inline;">高码率:</div>`;
        dom += `<input type="radio" class="high_bitrateListener settingsBoxInputRadio" style="outline:none;" name='highBitrate' id="high_bitrateOn" value="1" ${naifeitian.getValue('high_bitrateGM') == 1 ? 'checked' : ''}><label for="high_bitrateOn" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class="high_bitrateListener settingsBoxInputRadio" style="outline:none;" name='highBitrate' id="high_bitrateOff" value="0" ${naifeitian.getValue('high_bitrateGM') == 0 ? 'checked' : ''}><label for="high_bitrateOff" style="padding-right: 25px;">关</label>`;
        dom+=`</label><hr style="background-color: black;width:95%" />`;

        dom += `<label class="" style="display: block;text-align:left;"><div   style="display: inline;">禁止检测网络状况:</div>`;
        dom += `<input type="radio" class="disableCheckNetworkListener settingsBoxInputRadio" style="outline:none;" name='disableCheckNetwork' id="disableCheckNetworkOn" value="1" ${naifeitian.getValue('disableCheckNetworkGM') == 1 ? 'checked' : ''}><label for="disableCheckNetworkOn" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class="disableCheckNetworkListener settingsBoxInputRadio" style="outline:none;" name='disableCheckNetwork' id="disableCheckNetworkOff" value="0" ${naifeitian.getValue('disableCheckNetworkGM') == 0 ? 'checked' : ''}><label for="disableCheckNetworkOff" style="padding-right: 25px;">关</label>`;
        dom+=`</label><hr style="background-color: black;width:95%" />`;

        dom += `<label class="" style="display: block;text-align:left;"><div   style="display: inline;">自动打开经典触控:</div>`;
        dom += `<input type="radio" class="useDefaultTouchControlsListener settingsBoxInputRadio" style="outline:none;" name='useDefaultTouchControls' id="useDefaultTouchControlsOn" value="1" ${naifeitian.getValue('useDefaultTouchControlsGM') == 1 ? 'checked' : ''}><label for="useDefaultTouchControlsOn" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class="useDefaultTouchControlsListener settingsBoxInputRadio" style="outline:none;" name='useDefaultTouchControls' id="useDefaultTouchControlsOff" value="0" ${naifeitian.getValue('useDefaultTouchControlsGM') == 0 ? 'checked' : ''}><label for="useDefaultTouchControlsOff" style="padding-right: 25px;">关</label>`;
        dom+=`</label><hr style="background-color: black;width:95%" />`;

        dom += `<label class="" style="display: block;text-align:left;"><div   style="display: inline;">禁用游戏内下拉刷新:</div>`;
        dom += `<input type="radio" class="no_pull_refreshListener settingsBoxInputRadio" style="outline:none;" name='no_pull_refresh' id="no_pull_refreshOn" value="1" ${naifeitian.getValue('no_pull_refreshGM') == 1 ? 'checked' : ''}><label for="no_pull_refreshOn" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class="no_pull_refreshListener settingsBoxInputRadio" style="outline:none;" name='no_pull_refresh' id="no_pull_refreshOff" value="0" ${naifeitian.getValue('no_pull_refreshGM') == 0 ? 'checked' : ''}><label for="no_pull_refreshOff" style="padding-right: 25px;">关</label>`;
        dom+=`</label><hr style="background-color: black;width:95%" />`;

        dom += `<label class="" style="display: block;text-align:left;"><div   style="display: inline;">自动全屏:</div>`;
        dom += `<input type="radio" class="autoFullScreenListener settingsBoxInputRadio" style="outline:none;" name='autoFullScreen' id="autoFullScreenOn" value="1" ${naifeitian.getValue('autoFullScreenGM') == 1 ? 'checked' : ''}><label for="autoFullScreenOn" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class="autoFullScreenListener settingsBoxInputRadio" style="outline:none;" name='autoFullScreen' id="autoFullScreenOff" value="0" ${naifeitian.getValue('autoFullScreenGM') == 0 ? 'checked' : ''}><label for="autoFullScreenOff" style="padding-right: 25px;">关</label>`;
        dom+=`</label><hr style="background-color: black;width:95%" />`;


        dom += `<label class="" style="display: block;text-align:left;"><div   style="display: inline;">锁定物理服务器:</div>`;
        dom += `<input type="radio" class="blockXcloudServerListener settingsBoxInputRadio" style="outline:none;" name='blockXcloudServer' id="blockXcloudServerOn" value="1" ${naifeitian.getValue('blockXcloudServerGM') == 1 ? 'checked' : ''}><label for="blockXcloudServerOn" style="padding-right: 15px;">开</label>`;
        dom += `<input type="radio" class="blockXcloudServerListener settingsBoxInputRadio" style="outline:none;" name='blockXcloudServer' id="blockXcloudServerOff" value="0" ${naifeitian.getValue('blockXcloudServerGM') == 0 ? 'checked' : ''}><label for="blockXcloudServerOff" style="padding-right: 25px;">关</label>`;

        dom += `<select class="blockServerBlock" style="outline: none;display:`+(naifeitian.getValue('blockXcloudServerGM')==1?'block':'none')+`">`;
        blockXcloudServerList.forEach(serverName => {
            dom += `<option value="${serverName}" ${naifeitian.getValue('defaultXcloudServerGM') == serverName ? 'selected' : ''}>${serverName}</option>`;
        });
        dom += `</select>`;
        dom+=`</label><hr style="background-color: black;width:95%" />`;
        dom+=`<button class="closeSetting1 closeSetting2" style="outline: none;">关闭</button>`

        dom+=`<div style="text-align: right;margin-top: 8px;font-size: 16px;"><lable>捐赠:</lable><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>`
        dom = '<div style="padding: 20px;color: black;display:none;" class="settingsBackgroud" id=\'settingsBackgroud\'>' +`<div class="settingsBox">`+dom+`</div>`+ '</div>';

        $('body').append(dom);

        $(document).on('click', '#header-right',function(){
            $('#settingsBackgroud').css('display','none');
        });

        $(document).on('click', '.closeSetting1',function(){

            $('#settingsBackgroud').css('display','none');
            if(needrefresh==1){
                history.go(0);
            }
        });

        $(document).on('click', '.chooseLanguageListener',function(){
            if($(this).val()==0){
                $('.chooseLanguageBlock').hide();
                $('.IfErrUsedefaultGameLanguageBlock').hide();
            }else{
                $('.chooseLanguageBlock').css('display','block');

                if(naifeitian.getValue('xcloud_game_languageGM')=='Auto'){
                    $('.IfErrUsedefaultGameLanguageBlock').css('display','block');
                }
            }
            naifeitian.setValue('chooseLanguageGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });


        $(document).on('click', '.languageSingleListener',function(){
            if($(this).val()!='Auto'){
                $('.IfErrUsedefaultGameLanguageBlock').hide();
            }else{
                $('.IfErrUsedefaultGameLanguageBlock').css('display','block');
            }
            naifeitian.setValue('xcloud_game_languageGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.IfErrUsedefaultGameLanguageListener',function(){
            naifeitian.setValue('IfErrUsedefaultGameLanguageGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.noNeedVpnListener',function(){
            if($(this).val()==0){
                $('.chooseRegionsBlock').hide();
            }else{
                $('.chooseRegionsBlock').css('display','block');
            }
            naifeitian.setValue('no_need_VPN_playGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.regionSingleListener',function(){
            if($(this).val()=='customfakeIp'){
                naifeitian.setValue('useCustomfakeIpGM',1);
                $('#customfakeIpInput').css('display','inline');
            }else{
                naifeitian.setValue('fakeIpGM',$(this).val());
                naifeitian.setValue('useCustomfakeIpGM',0);
                $('#customfakeIpInput').css('display','none');
            }

            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('blur', '.customfakeIpListener',function(){
            if(naifeitian.isValidIP($(this).val())){
                naifeitian.setValue('customfakeIpGM',$(this).val());
            }else{
                $(this).val("");
                naifeitian.setValue('customfakeIpGM','');
                alert('IP格式错误!');
            }
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });


        $(document).on('click', '.high_bitrateListener',function(){

            naifeitian.setValue('high_bitrateGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.autoFullScreenListener',function(){
            naifeitian.setValue('autoFullScreenGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.disableCheckNetworkListener',function(){
            naifeitian.setValue('disableCheckNetworkGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.useDefaultTouchControlsListener',function(){
            naifeitian.setValue('useDefaultTouchControlsGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.no_pull_refreshListener',function(){
            naifeitian.setValue('no_pull_refreshGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('click', '.blockXcloudServerListener',function(){
            if($(this).val()==0){
                $('.blockServerBlock').hide();
            }else{
                $('.blockServerBlock').css('display','block');
            }
            naifeitian.setValue('blockXcloudServerGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });

        $(document).on('change', '.blockServerBlock',function(){
            naifeitian.setValue('defaultXcloudServerGM',$(this).val());
            needrefresh=1;
            $('.closeSetting1').text('确定');
        });
    }

    $(document).on('click', cloudGameBeta,function(){
        $('#settingsBackgroud').css('display','');
        $(this).text("⚙️ 设置");
        $(this).next().remove();
    });

    $(document).ready(function(){
        setTimeout(function(){
            initSettingBox();
            let logoText=$(mslogo);
            if(logoText.attr('href')!=null && logoText.attr('href')!=""){
                logoText.removeAttr('href');
                logoText.css("color",'white');
                logoText.text("⚙️ 设置");
            }
        },2000);

    });
    $(document).on('click', mslogo,function(){
        $('#settingsBackgroud').css('display','');
    });
    try{
        GM_registerMenuCommand('⚙️ 设置', () => {
            $('#settingsBackgroud').css('display','');
        });}catch(e){}
    console.log("all done");
})();