// ==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://gf.qytechs.cn/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);
})();