Compare commits

...

6 Commits

Author SHA1 Message Date
b4149e718b Bump version to 2.0.4 2023-12-06 20:06:41 +07:00
7c22685e95 Update README.md 2023-12-05 14:50:32 +07:00
ad98eb60e1 Only call eval() once per patch group 2023-12-05 06:38:35 +07:00
049e65429a Fix not applying patches correctly 2023-12-03 16:36:02 +07:00
a5b77ae8c0 Improve Patcher class 2023-12-03 10:38:10 +07:00
49550eed0a Add "enableXcloudLogger" patch 2023-12-02 17:31:51 +07:00
3 changed files with 107 additions and 32 deletions

View File

@ -1,5 +1,5 @@
# Better xCloud # Better xCloud
Improve [Xbox Cloud Gaming (xCloud)](https://www.xbox.com/play/) experience on web browser. Improve Xbox Cloud Gaming (xCloud) experience on [xbox.com/play](https://www.xbox.com/play).
The main target of this script is mobile users, but it should work great on desktop too. The main target of this script is mobile users, but it should work great on desktop too.
Supported platforms: Supported platforms:

View File

@ -1,5 +1,5 @@
// ==UserScript== // ==UserScript==
// @name Better xCloud // @name Better xCloud
// @namespace https://github.com/redphx // @namespace https://github.com/redphx
// @version 2.0.3 // @version 2.0.4
// ==/UserScript== // ==/UserScript==

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name Better xCloud // @name Better xCloud
// @namespace https://github.com/redphx // @namespace https://github.com/redphx
// @version 2.0.3 // @version 2.0.4
// @description Improve Xbox Cloud Gaming (xCloud) experience // @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx // @author redphx
// @license MIT // @license MIT
@ -13,10 +13,11 @@
// ==/UserScript== // ==/UserScript==
'use strict'; 'use strict';
const SCRIPT_VERSION = '2.0.3'; const SCRIPT_VERSION = '2.0.4';
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud'; const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
const ENABLE_MKB = false; const ENABLE_MKB = false;
const ENABLE_XCLOUD_LOGGER = false;
console.log(`[Better xCloud] readyState: ${document.readyState}`); 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'); 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) { remotePlayKeepAlive: PREFS.get(Preferences.REMOTE_PLAY_ENABLED) && function(funcStr) {
if (!funcStr.includes('onServerDisconnectMessage(e){')) { if (!funcStr.includes('onServerDisconnectMessage(e){')) {
return false; return false;
} }
funcStr = funcStr.replace('onServerDisconnectMessage(e){', `onServerDisconnectMessage (e) { funcStr = funcStr.replace('onServerDisconnectMessage(e){', `onServerDisconnectMessage(e) {
const msg = JSON.parse(e); const msg = JSON.parse(e);
if (msg.reason === 'WarningForBeingIdle') { if (msg.reason === 'WarningForBeingIdle') {
try { try {
this.sendKeepAlive(); this.sendKeepAlive();
return; return;
} catch (ex) {} } catch (ex) { console.log(ex); }
} }
`); `);
return funcStr; 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)||''`); 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 // Block WebRTC stats collector
blockWebRtcStatsCollector: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) { blockWebRtcStatsCollector: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) {
const text = 'this.intervalMs=0,'; const text = 'this.intervalMs=0,';
@ -4351,6 +4353,16 @@ class Patcher {
return funcStr.replace(text, 'false,' + text); 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 // Enable Mouse and Keyboard support
enableMouseAndKeyboard: PREFS.get(Preferences.MKB_ENABLED) && function(funcStr) { enableMouseAndKeyboard: PREFS.get(Preferences.MKB_ENABLED) && function(funcStr) {
if (!funcStr.includes('EnableMouseAndKeyboard:')) { 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() { static #patchFunctionBind() {
Function.prototype.nativeBind = Function.prototype.bind; Function.prototype.nativeBind = Function.prototype.bind;
Function.prototype.bind = function() { 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) { static patch(item) {
let patchName; let patchName;
let appliedPatches;
for (let id in item[1]) { for (let id in item[1]) {
if (Patcher.length() <= 0) { if (Patcher.#PATCH_ORDERS.length <= 0) {
return; return;
} }
appliedPatches = [];
const func = item[1][id]; const func = item[1][id];
const funcStr = func.toString(); let funcStr = func.toString();
// Only check the first patch for (let groupIndex = 0; groupIndex < Patcher.#PATCH_ORDERS.length; groupIndex++) {
if (!patchName) { const group = Patcher.#PATCH_ORDERS[groupIndex];
patchName = Object.keys(Patcher.#PATCHES)[0]; let modified = false;
}
const patchedFuncStr = Patcher.#PATCHES[patchName].call(null, funcStr); for (let patchIndex = 0; patchIndex < group.length; patchIndex++) {
if (patchedFuncStr) { const patchName = group[patchIndex];
console.log(`[Better xCloud] Applied "${patchName}" patch`); if (appliedPatches.indexOf(patchName) > -1) {
continue;
}
item[1][id] = eval(patchedFuncStr); const patchedFuncStr = Patcher.#PATCHES[patchName].call(null, funcStr);
delete Patcher.#PATCHES[patchName]; if (!patchedFuncStr) {
patchName = null; // 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() { static initialize() {
// Remove disabled patches // Remove disabled patches
for (const patchName in Patcher.#PATCHES) { for (let groupIndex = Patcher.#PATCH_ORDERS.length - 1; groupIndex >= 0; groupIndex--) {
if (!Patcher.#PATCHES[patchName]) { const group = Patcher.#PATCH_ORDERS[groupIndex];
delete Patcher.#PATCHES[patchName];
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);
} }
} }