Greasy Fork is available in English.

Xbox CLoud Gaming优化整合

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

2023-02-03 일자. 최신 버전을 확인하세요.

질문, 리뷰하거나, 이 스크립트를 신고하세요.
// ==UserScript==
// @name                 Xbox CLoud Gaming优化整合
// @name:zh-CN           Xbox CLoud Gaming优化整合
// @namespace            http://tampermonkey.net/xbox/nft
// @version              1.2.2
// @author               奈非天
// @match                https://www.xbox.com/*/play*
// @run-at               document-start
// @grant                unsafeWindow
// @grant                GM_getValue
// @grant                GM_setValue
// @grant                GM_unregisterMenuCommand
// @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=关 ★★//

    //免代理直连 默认美服 (影响到玩什么服,如果开加速器可以关闭,否则即使使用了日本线路的梯子或者加速器,免代理的IP是美服,那么玩的还是美服)
    let no_need_VPN_play=1;
    //选择语言
    let chooseLanguage=1;

    //【换区改下面的kr或者自己写ip】总开关是上一行的no_need_VPN_play
    let kr='168.126.63.1';//韩
    let us='4.2.2.2';//美
    let jp='210.131.113.123';//日

    let fakeIp=us;

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

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

    //使用默认触屏控制布局(默认关闭)
    let useDefaultTouchControls=0;

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

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

    //锁定云游戏服务器,注意此项并非是云游戏区域(默认关闭)
    let blockXcloudServer=0;
    //默认服务器 总开关是上一行的blockXcloudServer
    //AustraliaEast
    //AustraliaSouthEast
    //BrazilSouth
    //EastUS
    //EastUS2
    //JapanEast
    //KoreaCentral
    //NorthCentralUs
    //SouthCentralUS
    //UKSouth
    //WestEurope
    //WestUS
    //WestUS2
    let defaultXcloudServer='KoreaCentral';

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

    const originFetch = fetch;

    let languageMenuItemList = [];
    let xcloud_game_language;//
    let default_language_list=['zh-CN','zh-TW']
    let default_language_list_Chinese={'zh-CN':'简体','zh-TW':'繁体','Auto':'智能简繁'}
    let isSptGM=false;
    let BasicControlsCheck=false;

    try{
        GM_getValue('abcdegfhijklmn');
        isSptGM=true;
    }catch(e){}

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

    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)
                            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";
            if(no_pull_refresh==1){
                $('*').on('touchmove', false);
            }
            changeBasicBtnCss();

            if(chooseLanguage==1){
                return new Promise(async(resolve, reject) => {
                    console.log('语言开始')
                    let selectedLanguage=IfErrUsedefaultGameLanguage;
                    if(isSptGM){
                        selectedLanguage=xcloud_game_language;
                        console.log('配置项语言:'+selectedLanguage);
                    }
                    if(selectedLanguage=='Auto' || !isSptGM){
                        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 i=0;i<default_language_list.length;i++){
                                    if (default_language_list[i] in languageSupport) {
                                        selectedLanguage=default_language_list[i];
                                        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);
        }
    }

    //添加菜单
    if(isSptGM){
        function checkSelected(name){
            let selected = GM_getValue("xcloud_game_language");
            return name == selected;
        }

        //注册语言选项
        function registerSelectableMenuItem(name) {
            return GM_registerMenuCommand((checkSelected(name) ? "✅" : "🔲") + " " + default_language_list_Chinese[name] , function() {
                xcloud_game_language = name;
                GM_setValue("xcloud_game_language", xcloud_game_language);
                updateLanguageMenuItem();
            });
        }

        function updateLanguageMenuItem() {
            languageMenuItemList.forEach(command => {
                GM_unregisterMenuCommand(command);
            });
            languageMenuItemList = [];
            languageMenuItemList.push(registerSelectableMenuItem("Auto"));
            default_language_list.forEach((language) => {
                languageMenuItemList.push(registerSelectableMenuItem(language));
            });
        }

        if(chooseLanguage==1){
            xcloud_game_language = GM_getValue("xcloud_game_language",'Auto');
            GM_setValue("xcloud_game_language",xcloud_game_language);
            updateLanguageMenuItem();
        }

    }

    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);
        }
        HookProperty(windowCtx.navigator, "standalone", true);

    }catch(e){}

    function changeBasicBtnCss(){
        let btnCss = `
    .EditErgoMenu-module__basicControlsButtonColor___1sLIY{
        width:10px;
        min-width:10px;
        background-color:rgba(255,0,0,0)!important;
        overflow: hidden;
        color: white;
    }
    .GripHandle-module__container___3clUM{
        background:rgba(0, 0, 0, 0);
    }
    .Grip-module__container___2t3Ev{
        opacity:0.3;
    }
    .StreamHUD-module__buttonsContainer___9B1o3{
        background-color:rgba(255,0,0,0)
    }
`;
        var basicStyle = document.createElement('style');
        basicStyle.innerHTML = btnCss;
        var doc = document.head || document.documentElement;
        doc.appendChild(basicStyle);
    }

    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;
        }
    }
    $(document).on("click",'.Button-module__decoratedButton___t4Zaz',
                   function(){

        if($(this).attr('aria-checked')=='true'){
            BasicControlsCheck=true;
        }else{
            BasicControlsCheck=false;
        }
    });

    $(document).on("click",'.EditErgoMenu-module__topPanelBasicButton___tLdju.Button-module__typeBrand___1AMyM',
                   function(){
        if(BasicControlsCheck){
            $('.EditErgoMenu-module__basicControlsButtonColor___1sLIY').removeClass("Button-module__overlayModeAcrylic___19h3Y");
        }
    });

    if(no_pull_refresh==1){
        $(document).on("click",'.StreamHUD-module__button___4GEk2',
                       function(){
            let tdot=$(this).attr('aria-expanded');
            if(tdot!=null && tdot!=''){
                $('*').off('touchmove', false);
                $(".StreamMenu-module__container___2uc2J").on('click',function(){
                    setTimeout(function(){
                        let exitBtn=$('.ConfirmQuitScreen-module__quitButton___2EdfL');
                        if(exitBtn.length==0){
                            $('*').on('touchmove', false);
                        }else{
                            $(".PureInStreamConfirmationModal-module__buttonContainer___1Prkz").on('click',function(){
                                $('*').on('touchmove', false);
                            });

                            $(".PureInStreamConfirmationModal-module__closeButton___1SHZK").on('click',function(){
                                $('*').on('touchmove', false);
                            })
                        }

                    },1000)
                });
            }
        });

        $(window).on('popstate', function () {
            $('*').off('touchmove', false);
        });

        $(document).on("click",'.ConfirmQuitScreen-module__quitButton___2EdfL',
                       function(){
            document.documentElement.style.overflowY = "";
            $('*').off('touchmove', false);

        });
    }else{
        $(document).on("click",'.ConfirmQuitScreen-module__quitButton___2EdfL',
                       function(){
            document.documentElement.style.overflowY = "";
        });
    }
    let setLogoTitleTimeout=0;
    let setLogoTitleInterval=setInterval(function(){
        if(setLogoTitleTimeout<12){
            let logoText=$(".c-sgl-stk-uhfLogo");
            if(logoText.attr('href')!=null && logoText.attr('href')!=""){
                clearInterval(setLogoTitleInterval)
                logoText.css("color",'white');
                logoText.text("脚本加载成功");
            }
        }else{
            clearInterval(setLogoTitleInterval);
        }
        setLogoTitleTimeout=setLogoTitleTimeout+1;
    },5000);


})();