// ==UserScript== // @name Xbox CLoud Gaming 优化(ios语言中文繁体选择+免代理+PC安卓振动+safari免桌面+免画质检测+隐藏滚动) // @namespace http://tampermonkey.net/xbox/nft // @version 0.3 // @description 整合和魔改现有脚本,感谢greasy的各位作者,支持ios,pc,安卓,优化项(ios语言中文繁体选择+免代理+PC安卓振动+safari免桌面+免画质检测+隐藏滚动条) xbox云游戏交流群531602832 // @author 奈非天 // @match https://www.xbox.com/*/play* // @run-at document-start // @grant unsafeWindow // @original-script https://greasyfork.org/zh-CN/scripts/455741-xbox-cloud-gaming-%E4%BC%98%E5%8C%96-ios%E8%AF%AD%E8%A8%80%E4%B8%AD%E6%96%87%E7%B9%81%E4%BD%93%E9%80%89%E6%8B%A9-%E5%85%8D%E4%BB%A3%E7%90%86-pc%E5%AE%89%E5%8D%93%E6%8C%AF%E5%8A%A8-safari%E5%85%8D%E6%A1%8C%E9%9D%A2-%E5%85%8D%E7%94%BB%E8%B4%A8%E6%A3%80%E6%B5%8B-%E9%9A%90%E8%97%8F%E6%BB%9A%E5%8A%A8 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // Your code here... const originFetch = fetch; let windowCtx = self.window; if (self.unsafeWindow) { console.log("使用unsafeWindow模式"); windowCtx = self.unsafeWindow; } else { console.log("使用原生模式"); } //Object.defineProperty(window.navigator, 'connection', {get: () => undefined}); //Object.defineProperty(window.navigator, 'standalone', {get: () => true}); 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){} windowCtx.fetch = (...arg) => { //fetch = (...arg) => { // console.log('fetch arg', ...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('xgpuweb.gssv-play-prod.xboxlive.com/v2/login/user') > -1){ console.log('xff欺骗开始'+url) return new Promise((resolve, reject) => { if (isRequest && arg0.method == "POST") { arg0.json().then(json => { let aaa=Math.floor(Math.random()*15+96) let bbb=Math.floor(Math.random()*255) let ccc=Math.floor(Math.random()*255) let body = JSON.stringify(json); arg[0].headers.set('x-forwarded-for','1.'+aaa+'.'+bbb+'.'+ccc) arg[0] = new Request(url, { method: arg0.method, headers: arg0.headers, body: body, }); originFetch(...arg).then(res => { console.log('xff欺骗结束') resolve(res); }).catch(err => { reject(err); }); }); } else { console.error("[ERROR] Not a request."); return originFetch(...arg); } }); }else if (url.indexOf('/v5/sessions/cloud/play') > -1) { console.log('语言开始') document.documentElement.style.overflowY = "hidden" // Start Configuration return new Promise((resolve, reject) => { if (isRequest && arg0.method == "POST") { arg0.json().then(json => { let selectedLanguage = "" var yuyan = confirm("确定是简体,取消是繁体"); if(yuyan){ selectedLanguage="zh-CN" }else{ selectedLanguage="zh-TW" } 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('语言结束') resolve(res); let cssChanged= setInterval(function(){ let basicBtn=$('.EditErgoMenu-module__basicControlsButtonColor___1sLIY'); if(basicBtn!=null){ if(basicBtn.css('color')!='black'){ $('.EditErgoMenu-module__basicControlsButtonColor___1sLIY').text('X') $('.EditErgoMenu-module__basicControlsButtonColor___1sLIY').css('background-color',' #dc353500') //$('.EditErgoMenu-module__basicControlsButtonColor___1sLIY').css('color',' black') $('.EditErgoMenu-module__basicControlsButtonColor___1sLIY').css('width',' 10px') $('.EditErgoMenu-module__basicControlsButtonColor___1sLIY').css('min-width',' 10px') } } },2000) }).catch(err => { reject(err); }); }); } else { console.error("[ERROR] Not a request."); return originFetch(...arg); } }); } else if (url.indexOf('/v2/login/user') > -1 && url.indexOf('xgpuweb.gssv-play-prod.xboxlive.com')<0) { console.log('允许修改区域开始') return new Promise((resolve, reject) => { originFetch(...arg).then(res => { res.json().then(json => { // console.error(json); json["offeringSettings"]["allowRegionSelection"] = true; let body = JSON.stringify(json); let newRes = new Response(body, { status: res.status, statusText: res.statusText, headers: res.headers }) console.log('允许修改区域结束') resolve(newRes); }).catch(err => { reject(err); }); }).catch(err => { reject(err); }); }); }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 { 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); } } zhengdong() function zhengdong(){ const useControllerVibration = true; const useMobileVibration = true; let haptic = null; let xinputMaxHaptic = 65535; RTCPeerConnection.prototype.createDataChannelOriginal = RTCPeerConnection.prototype.createDataChannel; RTCPeerConnection.prototype.createDataChannel = function (...params) { let dc = this.createDataChannelOriginal(...params) if (dc.label == "input") { dc.addEventListener("message", function (de) { if (typeof(de.data) == "object") { let dataBytes = new Uint8Array(de.data); if (dataBytes[0] == 128) { let leftM = dataBytes[3] / 255; let rightM = dataBytes[4] / 255; let leftT = dataBytes[5] / 255; let rightT = dataBytes[6] / 255; if (haptic) haptic.SetState(leftM * xinputMaxHaptic, rightM * xinputMaxHaptic); } } }); dc.addEventListener("close", function () { if (haptic) haptic.SetState(0, 0); }); } return dc; } // Compile with Webpack, disable UglifyJS class WebHaptic { constructor(t = !0, e = !0) { this.isRunning = !1, this.lms = 0, this.mp = 0, this.supportch = !1, this.enablech = !0, this.supportwvh = !1, this.enablewvh = !0, this.gamepads = [], this.enablewvh = t, this.enablewvh && (this.supportwvh = WebHaptic.IsSupportWebVibrateHaptic()), this.enablech = e, this.enablech && (this.supportch = WebHaptic.IsSupportControllerHaptic()), this.onGamepadConnected = (t => { console.log("A gamepad was connected:" + t.gamepad.id), this.UpdateGamepads() }), this.onGamepadDisonnected = (t => { console.log("A gamepad was disconnected:" + t.gamepad.id), this.UpdateGamepads() }), this.supportch && (window.addEventListener("gamepadconnected", this.onGamepadConnected), window.addEventListener("gamepaddisconnected", this.onGamepadDisonnected), this.UpdateGamepads()) } static IsSupportControllerHaptic() { var t, e; return !!(window.Gamepad && window.GamepadHapticActuator && (null === (e = null === (t = window.GamepadHapticActuator) || void 0 === t ? void 0 : t.prototype) || void 0 === e ? void 0 : e.hasOwnProperty("playEffect"))) } static IsSupportWebVibrateHaptic() { return !!window.navigator.vibrate } static IsSupport() { return WebHaptic.IsSupportControllerHaptic() || WebHaptic.IsSupportWebVibrateHaptic() } EnableControllerHaptic() { this.enablech = !0 } DisableControllerHaptic() { this.enablech = !1 } EnableWebVibrateHaptic() { this.enablewvh = !0 } DisableWebVibrateHaptic() { this.enablewvh = !1 } Dispose() { this.SetState(0, 0), this.supportch && (window.removeEventListener("gamepadconnected", this.onGamepadConnected), window.removeEventListener("gamepaddisconnected", this.onGamepadDisonnected)) } SetState(t, e) { this.updateTimeoutId && clearTimeout(this.updateTimeoutId), (this.enablewvh || 0 == t || 0 == e) && this.SetWebHapticState(t, e), (this.enablech || 0 == t || 0 == e) && this.SetControllerState(t, e) } SetWebHapticState(t, e) { if (this.supportwvh) { let i = .5, a = 65535, o = Math.max(t, e * i); o != this.lms && (this.lms = o, this.mp = o / a, o > 0 ? 0 == this.isRunning && (this.isRunning = !0, this.OnVibrateTick(this)) : (this.isRunning = !1, window.navigator.vibrate(0))) } } SetControllerState(t, e) { var i, a; if (this.supportch) { let o = 65535, r = 1e3, n = t / o, s = e / o; for (const [t, e] of Object.entries(this.gamepads)) null != e && (null === (a = null === (i = e) || void 0 === i ? void 0 : i.vibrationActuator) || void 0 === a || a.playEffect("dual-rumble", { duration: r, strongMagnitude: n, weakMagnitude: s })) } } UpdateGamepads() { this.gamepads = navigator.getGamepads() } OnVibrateTick(t) { t.lms > 0 && 1 == t.isRunning && (t.mp < .075 ? t.LowVibrate(t, t.mp) : this.mp < .88 ? t.MidVibrate(t, t.mp) : t.HighVibrate(t, t.mp)) } HighVibrate(t, e) { let i = 100 * e; window.navigator.vibrate(i), setTimeout(() => { t.OnVibrateTick(t) }, i) } MidVibrate(t, e) { let i = 50 * e; window.navigator.vibrate(i), setTimeout(() => { t.OnVibrateTick(t) }, i) } LowVibrate(t, e) { let i = 100 - e / .025 * 100; window.navigator.vibrate(2), setTimeout(() => { t.OnVibrateTick(t) }, i) } } if(WebHaptic.IsSupportWebVibrateHaptic){ haptic = new WebHaptic(useMobileVibration, useControllerVibration); } } })();