Greasy Fork

Greasy Fork is available in English.

Xbox CLoud Gaming优化整合

整合和修改现有脚本,感谢@TGSAN,@刘翠两位大佬,该脚本支持ios(使用Userscripts),pc,安卓,优化项:游戏语言简体繁体选择+免代理直连(默认韩服)+safari免添加桌面+高码率+禁用低画质+裸连网络中强制开启触屏控制(开加速器失效)+美化悬浮按钮的样式+锁定默认服务器(默认关闭)。 【若你有好的想法或者有BUG可以进xbox云游戏交流群531602832反馈】

当前为 2023-01-25 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                 Xbox CLoud Gaming优化整合
// @name:zh-CN           Xbox CLoud Gaming优化整合
// @namespace            http://tampermonkey.net/xbox/nft
// @version              1.1.7
// @description:zh-cn    整合和修改现有脚本,感谢@TGSAN,@刘翠两位大佬,该脚本支持ios(使用Userscripts),pc,安卓,优化项:游戏语言简体繁体选择+免代理直连(默认韩服)+safari免添加桌面+高码率+禁用低画质+裸连网络中强制开启触屏控制(开加速器失效)+美化悬浮按钮的样式+锁定默认服务器(默认关闭)。 【若你有好的想法或者有BUG可以进xbox云游戏交流群531602832反馈】
// @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
// @original-script      http://greasyfork.icu/zh-CN/scripts/455741-xbox-cloud-gaming%E4%BC%98%E5%8C%96%E6%95%B4%E5%90%88
// @description 整合和修改现有脚本,感谢@TGSAN,@刘翠两位大佬,该脚本支持ios(使用Userscripts),pc,安卓,优化项:游戏语言简体繁体选择+免代理直连(默认韩服)+safari免添加桌面+高码率+禁用低画质+裸连网络中强制开启触屏控制(开加速器失效)+美化悬浮按钮的样式+锁定默认服务器(默认关闭)。 【若你有好的想法或者有BUG可以进xbox云游戏交流群531602832反馈】
// ==/UserScript==
(function() {
    'use strict';
    // Your code here...

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

    //★★ 1=开   0=关 ★★//

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

    let kr='168.126.63.1';//韩
    let us='4.2.2.2';//美
    let jp='210.131.113.123';//日

    //【换区改下面的kr或者自己写ip】总开关是上一行的no_need_VPN_play
    let fakeIp=kr;

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

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

    //锁定云游戏服务器,注意此项并非是云游戏区域(默认关闭)
    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).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',
                           function(){
                if(BasicControlsCheck){
                    $('.EditErgoMenu-module__basicControlsButtonColor___1sLIY').removeClass("Button-module__overlayModeAcrylic___19h3Y");
                }
            });

            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{

        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);
        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;
        }
    }

})();