|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
// ==UserScript==
|
|
|
|
|
// @name Better xCloud
|
|
|
|
|
// @namespace https://github.com/redphx
|
|
|
|
|
// @version 2.0.3
|
|
|
|
|
// @version 2.0.4
|
|
|
|
|
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
|
|
|
|
// @author redphx
|
|
|
|
|
// @license MIT
|
|
|
|
@ -13,10 +13,11 @@
|
|
|
|
|
// ==/UserScript==
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
const SCRIPT_VERSION = '2.0.3';
|
|
|
|
|
const SCRIPT_VERSION = '2.0.4';
|
|
|
|
|
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
|
|
|
|
|
|
|
|
|
|
const ENABLE_MKB = false;
|
|
|
|
|
const ENABLE_XCLOUD_LOGGER = false;
|
|
|
|
|
|
|
|
|
|
console.log(`[Better xCloud] readyState: ${document.readyState}`);
|
|
|
|
|
|
|
|
|
@ -4304,30 +4305,21 @@ class Patcher {
|
|
|
|
|
return funcStr.replace(funcStr.substring(index - 9, index + 15), 'https://www.xbox.com/play');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Disable trackEvent() function
|
|
|
|
|
disableTrackEvent: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) {
|
|
|
|
|
const text = 'this.trackEvent=';
|
|
|
|
|
if (!funcStr.includes(text)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return funcStr.replace(text, 'this.trackEvent=e=>{},this.uwuwu=');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
remotePlayKeepAlive: PREFS.get(Preferences.REMOTE_PLAY_ENABLED) && function(funcStr) {
|
|
|
|
|
if (!funcStr.includes('onServerDisconnectMessage(e){')) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
funcStr = funcStr.replace('onServerDisconnectMessage(e){', `onServerDisconnectMessage (e) {
|
|
|
|
|
funcStr = funcStr.replace('onServerDisconnectMessage(e){', `onServerDisconnectMessage(e) {
|
|
|
|
|
const msg = JSON.parse(e);
|
|
|
|
|
if (msg.reason === 'WarningForBeingIdle') {
|
|
|
|
|
try {
|
|
|
|
|
this.sendKeepAlive();
|
|
|
|
|
return;
|
|
|
|
|
} catch (ex) {}
|
|
|
|
|
} catch (ex) { console.log(ex); }
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
return funcStr;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
@ -4341,6 +4333,16 @@ class Patcher {
|
|
|
|
|
return funcStr.replace(text, `connectMode:window.BX_REMOTE_PLAY_CONFIG?"xhome-connect":"cloud-connect",remotePlayServerId:(window.BX_REMOTE_PLAY_CONFIG&&window.BX_REMOTE_PLAY_CONFIG.serverId)||''`);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Disable trackEvent() function
|
|
|
|
|
disableTrackEvent: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) {
|
|
|
|
|
const text = 'this.trackEvent=';
|
|
|
|
|
if (!funcStr.includes(text)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return funcStr.replace(text, 'this.trackEvent=e=>{},this.uwuwu=');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Block WebRTC stats collector
|
|
|
|
|
blockWebRtcStatsCollector: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) {
|
|
|
|
|
const text = 'this.intervalMs=0,';
|
|
|
|
@ -4351,6 +4353,16 @@ class Patcher {
|
|
|
|
|
return funcStr.replace(text, 'false,' + text);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
enableXcloudLogger: ENABLE_XCLOUD_LOGGER && function(funcStr) {
|
|
|
|
|
const text = 'if(t!==Ke.LogLevel.Error&&t!==Ke.LogLevel.Warn)';
|
|
|
|
|
if (!funcStr.includes(text)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
funcStr = funcStr.replaceAll(text, 'console.log(arguments);' + text);
|
|
|
|
|
return funcStr;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Enable Mouse and Keyboard support
|
|
|
|
|
enableMouseAndKeyboard: PREFS.get(Preferences.MKB_ENABLED) && function(funcStr) {
|
|
|
|
|
if (!funcStr.includes('EnableMouseAndKeyboard:')) {
|
|
|
|
@ -4366,6 +4378,26 @@ class Patcher {
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static #PATCH_ORDERS = [
|
|
|
|
|
[
|
|
|
|
|
'disableAiTrack',
|
|
|
|
|
'disableTelemetry',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
['tvLayout'],
|
|
|
|
|
|
|
|
|
|
[
|
|
|
|
|
'enableMouseAndKeyboard',
|
|
|
|
|
'enableXcloudLogger',
|
|
|
|
|
'remotePlayDirectConnectUrl',
|
|
|
|
|
'disableTrackEvent',
|
|
|
|
|
'remotePlayKeepAlive',
|
|
|
|
|
'blockWebRtcStatsCollector',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
['remotePlayConnectMode'],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
static #patchFunctionBind() {
|
|
|
|
|
Function.prototype.nativeBind = Function.prototype.bind;
|
|
|
|
|
Function.prototype.bind = function() {
|
|
|
|
@ -4400,39 +4432,82 @@ class Patcher {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static length() { return Object.keys(Patcher.#PATCHES).length };
|
|
|
|
|
static length() { return Patcher.#PATCH_ORDERS.length; };
|
|
|
|
|
|
|
|
|
|
static patch(item) {
|
|
|
|
|
let patchName;
|
|
|
|
|
let appliedPatches;
|
|
|
|
|
|
|
|
|
|
for (let id in item[1]) {
|
|
|
|
|
if (Patcher.length() <= 0) {
|
|
|
|
|
if (Patcher.#PATCH_ORDERS.length <= 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
appliedPatches = [];
|
|
|
|
|
const func = item[1][id];
|
|
|
|
|
const funcStr = func.toString();
|
|
|
|
|
let funcStr = func.toString();
|
|
|
|
|
|
|
|
|
|
// Only check the first patch
|
|
|
|
|
if (!patchName) {
|
|
|
|
|
patchName = Object.keys(Patcher.#PATCHES)[0];
|
|
|
|
|
}
|
|
|
|
|
for (let groupIndex = 0; groupIndex < Patcher.#PATCH_ORDERS.length; groupIndex++) {
|
|
|
|
|
const group = Patcher.#PATCH_ORDERS[groupIndex];
|
|
|
|
|
let modified = false;
|
|
|
|
|
|
|
|
|
|
const patchedFuncStr = Patcher.#PATCHES[patchName].call(null, funcStr);
|
|
|
|
|
if (patchedFuncStr) {
|
|
|
|
|
console.log(`[Better xCloud] Applied "${patchName}" patch`);
|
|
|
|
|
for (let patchIndex = 0; patchIndex < group.length; patchIndex++) {
|
|
|
|
|
const patchName = group[patchIndex];
|
|
|
|
|
if (appliedPatches.indexOf(patchName) > -1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item[1][id] = eval(patchedFuncStr);
|
|
|
|
|
delete Patcher.#PATCHES[patchName];
|
|
|
|
|
patchName = null;
|
|
|
|
|
const patchedFuncStr = Patcher.#PATCHES[patchName].call(null, funcStr);
|
|
|
|
|
if (!patchedFuncStr) {
|
|
|
|
|
// Only stop if the first patch is failed
|
|
|
|
|
if (patchIndex === 0) {
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modified = true;
|
|
|
|
|
funcStr = patchedFuncStr;
|
|
|
|
|
|
|
|
|
|
console.log(`[Better xCloud] Applied "${patchName}" patch`);
|
|
|
|
|
appliedPatches.push(patchName);
|
|
|
|
|
|
|
|
|
|
// Remove patch from group
|
|
|
|
|
group.splice(patchIndex, 1);
|
|
|
|
|
patchIndex--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply patched functions
|
|
|
|
|
if (modified) {
|
|
|
|
|
item[1][id] = eval(funcStr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove empty group
|
|
|
|
|
if (!group.length) {
|
|
|
|
|
Patcher.#PATCH_ORDERS.splice(groupIndex, 1);
|
|
|
|
|
groupIndex--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static initialize() {
|
|
|
|
|
// Remove disabled patches
|
|
|
|
|
for (const patchName in Patcher.#PATCHES) {
|
|
|
|
|
if (!Patcher.#PATCHES[patchName]) {
|
|
|
|
|
delete Patcher.#PATCHES[patchName];
|
|
|
|
|
for (let groupIndex = Patcher.#PATCH_ORDERS.length - 1; groupIndex >= 0; groupIndex--) {
|
|
|
|
|
const group = Patcher.#PATCH_ORDERS[groupIndex];
|
|
|
|
|
|
|
|
|
|
for (let patchIndex = group.length - 1; patchIndex >= 0; patchIndex--) {
|
|
|
|
|
const patchName = group[patchIndex];
|
|
|
|
|
if (!Patcher.#PATCHES[patchName]) {
|
|
|
|
|
// Remove disabled patch
|
|
|
|
|
group.splice(patchIndex, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove empty group
|
|
|
|
|
if (!group.length) {
|
|
|
|
|
Patcher.#PATCH_ORDERS.splice(groupIndex, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|