mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-07-02 04:11:44 +02:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
f7f01fd27e | |||
67c2fb125f | |||
fad91d14a6 | |||
3a3fc77e83 | |||
4bf3bd3bb4 | |||
cc33e27bd6 | |||
9112853dfc | |||
368164b567 | |||
ce71c3043e | |||
3bb138cd05 | |||
3d6688e1db | |||
fc354e680c | |||
be51199279 | |||
e276d9a2b9 | |||
c2f9f129d0 | |||
aa50261726 | |||
bb32d97ae8 | |||
3d2abf6b12 | |||
4c8a49a43a | |||
256f28695e | |||
9e851fbd15 | |||
c829f74dcc | |||
62cf045f05 | |||
fdb4e58b5d | |||
b1407c2447 | |||
b5ba6e9600 | |||
a3094d2c9f | |||
3290a36886 |
25
.github/workflows/stale.yaml
vendored
Normal file
25
.github/workflows/stale.yaml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
name: 'Mark stale bug issues'
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # Runs daily at midnight UTC
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
stale-issue-message: |
|
||||||
|
This issue has been marked `stale` due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days.
|
||||||
|
close-issue-message: |
|
||||||
|
This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details.
|
||||||
|
days-before-stale: 60
|
||||||
|
days-before-close: 30
|
||||||
|
stale-issue-label: 'stale'
|
||||||
|
only-issues: true
|
||||||
|
only-labels: 'bug'
|
20
bun.lock
20
bun.lock
@ -3,11 +3,11 @@
|
|||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.2.9",
|
"@types/bun": "^1.2.10",
|
||||||
"@types/node": "^22.14.1",
|
"@types/node": "^22.14.1",
|
||||||
"@types/stylus": "^0.48.43",
|
"@types/stylus": "^0.48.43",
|
||||||
"@webgpu/types": "^0.1.60",
|
"@webgpu/types": "^0.1.60",
|
||||||
"eslint": "^9.24.0",
|
"eslint": "^9.25.0",
|
||||||
"eslint-plugin-compat": "^6.0.2",
|
"eslint-plugin-compat": "^6.0.2",
|
||||||
"stylus": "^0.64.0",
|
"stylus": "^0.64.0",
|
||||||
},
|
},
|
||||||
@ -27,15 +27,15 @@
|
|||||||
|
|
||||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.2.1", "", {}, "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw=="],
|
"@eslint/config-helpers": ["@eslint/config-helpers@0.2.1", "", {}, "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw=="],
|
||||||
|
|
||||||
"@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="],
|
"@eslint/core": ["@eslint/core@0.14.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg=="],
|
||||||
|
|
||||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
|
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
|
||||||
|
|
||||||
"@eslint/js": ["@eslint/js@9.25.0", "", {}, "sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w=="],
|
"@eslint/js": ["@eslint/js@9.27.0", "", {}, "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA=="],
|
||||||
|
|
||||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
||||||
|
|
||||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.8", "", { "dependencies": { "@eslint/core": "^0.13.0", "levn": "^0.4.1" } }, "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA=="],
|
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.1", "", { "dependencies": { "@eslint/core": "^0.14.0", "levn": "^0.4.1" } }, "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w=="],
|
||||||
|
|
||||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||||
|
|
||||||
@ -51,17 +51,17 @@
|
|||||||
|
|
||||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.2.10", "", { "dependencies": { "bun-types": "1.2.10" } }, "sha512-eilv6WFM3M0c9ztJt7/g80BDusK98z/FrFwseZgT4bXCq2vPhXD4z8R3oddmAn+R/Nmz9vBn4kweJKmGTZj+lg=="],
|
"@types/bun": ["@types/bun@1.2.15", "", { "dependencies": { "bun-types": "1.2.15" } }, "sha512-U1ljPdBEphF0nw1MIk0hI7kPg7dFdPyM7EenHsp6W5loNHl7zqy6JQf/RKCgnUn2KDzUpkBwHPnEJEjII594bA=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
|
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
|
||||||
|
|
||||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@22.14.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw=="],
|
"@types/node": ["@types/node@22.15.24", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng=="],
|
||||||
|
|
||||||
"@types/stylus": ["@types/stylus@0.48.43", "", { "dependencies": { "@types/node": "*" } }, "sha512-72dv/zdhuyXWVHUXG2VTPEQdOG+oen95/DNFx2aMFFaY6LoITI6PwEqf5x31JF49kp2w9hvUzkNfTGBIeg61LQ=="],
|
"@types/stylus": ["@types/stylus@0.48.43", "", { "dependencies": { "@types/node": "*" } }, "sha512-72dv/zdhuyXWVHUXG2VTPEQdOG+oen95/DNFx2aMFFaY6LoITI6PwEqf5x31JF49kp2w9hvUzkNfTGBIeg61LQ=="],
|
||||||
|
|
||||||
"@webgpu/types": ["@webgpu/types@0.1.60", "", {}, "sha512-8B/tdfRFKdrnejqmvq95ogp8tf52oZ51p3f4QD5m5Paey/qlX4Rhhy5Y8tgFMi7Ms70HzcMMw3EQjH/jdhTwlA=="],
|
"@webgpu/types": ["@webgpu/types@0.1.61", "", {}, "sha512-w2HbBvH+qO19SB5pJOJFKs533CdZqxl3fcGonqL321VHkW7W/iBo6H8bjDy6pr/+pbMwIu5dnuaAxH7NxBqUrQ=="],
|
||||||
|
|
||||||
"acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
"acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||||
|
|
||||||
@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
"browserslist": ["browserslist@4.24.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA=="],
|
"browserslist": ["browserslist@4.24.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.2.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-b5ITZMnVdf3m1gMvJHG+gIfeJHiQPJak0f7925Hxu6ZN5VKA8AGy4GZ4lM+Xkn6jtWxg5S3ldWvfmXdvnkp3GQ=="],
|
"bun-types": ["bun-types@1.2.15", "", { "dependencies": { "@types/node": "*" } }, "sha512-NarRIaS+iOaQU1JPfyKhZm4AsUOrwUOqRNHY0XxI8GI8jYxiLXLcdjYMG9UKS+fwWasc1uw1htV9AX24dD+p4w=="],
|
||||||
|
|
||||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||||
|
|
||||||
@ -113,7 +113,7 @@
|
|||||||
|
|
||||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||||
|
|
||||||
"eslint": ["eslint@9.25.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.25.0", "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-MsBdObhM4cEwkzCiraDv7A6txFXEqtNXOb877TsSp2FCkBNl8JfVQrmiuDqC1IkejT6JLPzYBXx/xAiYhyzgGA=="],
|
"eslint": ["eslint@9.27.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.27.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q=="],
|
||||||
|
|
||||||
"eslint-plugin-compat": ["eslint-plugin-compat@6.0.2", "", { "dependencies": { "@mdn/browser-compat-data": "^5.5.35", "ast-metadata-inferer": "^0.8.1", "browserslist": "^4.24.2", "caniuse-lite": "^1.0.30001687", "find-up": "^5.0.0", "globals": "^15.7.0", "lodash.memoize": "^4.1.2", "semver": "^7.6.2" }, "peerDependencies": { "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA=="],
|
"eslint-plugin-compat": ["eslint-plugin-compat@6.0.2", "", { "dependencies": { "@mdn/browser-compat-data": "^5.5.35", "ast-metadata-inferer": "^0.8.1", "browserslist": "^4.24.2", "caniuse-lite": "^1.0.30001687", "find-up": "^5.0.0", "globals": "^15.7.0", "lodash.memoize": "^4.1.2", "semver": "^7.6.2" }, "peerDependencies": { "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA=="],
|
||||||
|
|
||||||
|
2
dist/better-xcloud.meta.js
vendored
2
dist/better-xcloud.meta.js
vendored
@ -1,5 +1,5 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud
|
// @name Better xCloud
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 6.5.0
|
// @version 6.6.2
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
161
dist/better-xcloud.pretty.user.js
vendored
161
dist/better-xcloud.pretty.user.js
vendored
@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Better xCloud
|
// @name Better xCloud
|
||||||
// @namespace https://github.com/redphx
|
// @namespace https://github.com/redphx
|
||||||
// @version 6.5.0
|
// @version 6.6.2
|
||||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||||
// @author redphx
|
// @author redphx
|
||||||
// @license MIT
|
// @license MIT
|
||||||
@ -120,6 +120,7 @@ var ALL_PREFS = {
|
|||||||
"video.position",
|
"video.position",
|
||||||
"video.player.powerPreference",
|
"video.player.powerPreference",
|
||||||
"video.processing",
|
"video.processing",
|
||||||
|
"video.processing.mode",
|
||||||
"video.ratio",
|
"video.ratio",
|
||||||
"video.saturation",
|
"video.saturation",
|
||||||
"video.processing.sharpness"
|
"video.processing.sharpness"
|
||||||
@ -192,7 +193,7 @@ class UserAgent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var SCRIPT_VERSION = "6.5.0", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
var SCRIPT_VERSION = "6.6.2", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
||||||
UserAgent.init();
|
UserAgent.init();
|
||||||
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
||||||
supportedRegion: !0,
|
supportedRegion: !0,
|
||||||
@ -438,6 +439,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
center: "Center",
|
center: "Center",
|
||||||
chat: "Chat",
|
chat: "Chat",
|
||||||
"clarity-boost": "Clarity boost",
|
"clarity-boost": "Clarity boost",
|
||||||
|
"clarity-boost-mode": "Clarity boost mode",
|
||||||
"clarity-boost-warning": "These settings don't work when the Clarity Boost mode is ON",
|
"clarity-boost-warning": "These settings don't work when the Clarity Boost mode is ON",
|
||||||
clear: "Clear",
|
clear: "Clear",
|
||||||
"clear-data": "Clear data",
|
"clear-data": "Clear data",
|
||||||
@ -600,6 +602,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
"only-supports-some-games": "Only supports some games",
|
"only-supports-some-games": "Only supports some games",
|
||||||
opacity: "Opacity",
|
opacity: "Opacity",
|
||||||
other: "Other",
|
other: "Other",
|
||||||
|
performance: "Performance",
|
||||||
playing: "Playing",
|
playing: "Playing",
|
||||||
playtime: "Playtime",
|
playtime: "Playtime",
|
||||||
poland: "Poland",
|
poland: "Poland",
|
||||||
@ -637,6 +640,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
],
|
],
|
||||||
"press-to-bind": "Press a key or do a mouse click to bind...",
|
"press-to-bind": "Press a key or do a mouse click to bind...",
|
||||||
"prompt-preset-name": "Preset's name:",
|
"prompt-preset-name": "Preset's name:",
|
||||||
|
quality: "Quality",
|
||||||
recommended: "Recommended",
|
recommended: "Recommended",
|
||||||
"recommended-settings-for-device": [
|
"recommended-settings-for-device": [
|
||||||
e => `Recommended settings for ${e.device}`,
|
e => `Recommended settings for ${e.device}`,
|
||||||
@ -692,6 +696,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
"separate-touch-controller": "Separate Touch controller & Controller #1",
|
"separate-touch-controller": "Separate Touch controller & Controller #1",
|
||||||
"separate-touch-controller-note": "Touch controller is Player 1, Controller #1 is Player 2",
|
"separate-touch-controller-note": "Touch controller is Player 1, Controller #1 is Player 2",
|
||||||
server: "Server",
|
server: "Server",
|
||||||
|
"server-list-error": "Can't get the server list",
|
||||||
"server-locations": "Server locations",
|
"server-locations": "Server locations",
|
||||||
settings: "Settings",
|
settings: "Settings",
|
||||||
"settings-for": "Settings for",
|
"settings-for": "Settings for",
|
||||||
@ -741,6 +746,7 @@ var SUPPORTED_LANGUAGES = {
|
|||||||
"tc-custom-layout-style": "Custom layout's button style",
|
"tc-custom-layout-style": "Custom layout's button style",
|
||||||
"tc-muted-colors": "Muted colors",
|
"tc-muted-colors": "Muted colors",
|
||||||
"tc-standard-layout-style": "Standard layout's button style",
|
"tc-standard-layout-style": "Standard layout's button style",
|
||||||
|
"test-controller": "Test controller",
|
||||||
"text-size": "Text size",
|
"text-size": "Text size",
|
||||||
theme: "Theme",
|
theme: "Theme",
|
||||||
toggle: "Toggle",
|
toggle: "Toggle",
|
||||||
@ -2395,6 +2401,18 @@ class StreamSettingsStorage extends BaseSettingsStorage {
|
|||||||
highest: "cas"
|
highest: "cas"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"video.processing.mode": {
|
||||||
|
label: t("clarity-boost-mode"),
|
||||||
|
default: "performance",
|
||||||
|
options: {
|
||||||
|
performance: t("performance"),
|
||||||
|
quality: t("quality")
|
||||||
|
},
|
||||||
|
suggest: {
|
||||||
|
lowest: "performance",
|
||||||
|
highest: "quality"
|
||||||
|
}
|
||||||
|
},
|
||||||
"video.player.powerPreference": {
|
"video.player.powerPreference": {
|
||||||
label: t("renderer-configuration"),
|
label: t("renderer-configuration"),
|
||||||
default: "default",
|
default: "default",
|
||||||
@ -4415,6 +4433,10 @@ class SettingsManager {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"video.processing": {
|
"video.processing": {
|
||||||
|
onChange: updateVideoPlayer,
|
||||||
|
onChangeUi: onChangeVideoPlayerType
|
||||||
|
},
|
||||||
|
"video.processing.mode": {
|
||||||
onChange: updateVideoPlayer
|
onChange: updateVideoPlayer
|
||||||
},
|
},
|
||||||
"video.processing.sharpness": {
|
"video.processing.sharpness": {
|
||||||
@ -4565,13 +4587,13 @@ class SettingsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onChangeVideoPlayerType() {
|
function onChangeVideoPlayerType() {
|
||||||
let playerType = getStreamPref("video.player.type"), settingsManager = SettingsManager.getInstance();
|
let playerType = getStreamPref("video.player.type"), processing = getStreamPref("video.processing"), settingsManager = SettingsManager.getInstance();
|
||||||
if (!settingsManager.hasElement("video.processing")) return;
|
if (!settingsManager.hasElement("video.processing")) return;
|
||||||
let isDisabled = !1, $videoProcessing = settingsManager.getElement("video.processing"), $videoSharpness = settingsManager.getElement("video.processing.sharpness"), $videoPowerPreference = settingsManager.getElement("video.player.powerPreference"), $videoMaxFps = settingsManager.getElement("video.maxFps"), $optCas = $videoProcessing.querySelector(`option[value=${"cas"}]`);
|
let isDisabled = !1, $videoProcessing = settingsManager.getElement("video.processing"), $videoProcessingMode = settingsManager.getElement("video.processing.mode"), $videoSharpness = settingsManager.getElement("video.processing.sharpness"), $videoPowerPreference = settingsManager.getElement("video.player.powerPreference"), $videoMaxFps = settingsManager.getElement("video.maxFps"), $optCas = $videoProcessing.querySelector(`option[value=${"cas"}]`);
|
||||||
if (playerType === "default") {
|
if (playerType === "default") {
|
||||||
if ($videoProcessing.value = "usm", setStreamPref("video.processing", "usm", "direct"), $optCas && ($optCas.disabled = !0), UserAgent.isSafari()) isDisabled = !0;
|
if ($videoProcessing.value = "usm", setStreamPref("video.processing", "usm", "direct"), $optCas && ($optCas.disabled = !0), UserAgent.isSafari()) isDisabled = !0;
|
||||||
} else $optCas && ($optCas.disabled = !1);
|
} else $optCas && ($optCas.disabled = !1);
|
||||||
$videoProcessing.disabled = isDisabled, $videoSharpness.dataset.disabled = isDisabled.toString(), $videoPowerPreference.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType === "default");
|
$videoProcessing.disabled = isDisabled, $videoSharpness.dataset.disabled = isDisabled.toString(), $videoProcessingMode.closest(".bx-settings-row").classList.toggle("bx-gone", !(playerType === "webgl2" && processing === "cas")), $videoPowerPreference.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType === "default");
|
||||||
}
|
}
|
||||||
function limitVideoPlayerFps(targetFps) {
|
function limitVideoPlayerFps(targetFps) {
|
||||||
STATES.currentStream.streamPlayerManager?.getCanvasPlayer()?.setTargetFps(targetFps);
|
STATES.currentStream.streamPlayerManager?.getCanvasPlayer()?.setTargetFps(targetFps);
|
||||||
@ -4581,6 +4603,7 @@ function updateVideoPlayer() {
|
|||||||
if (!streamPlayerManager) return;
|
if (!streamPlayerManager) return;
|
||||||
let options = {
|
let options = {
|
||||||
processing: getStreamPref("video.processing"),
|
processing: getStreamPref("video.processing"),
|
||||||
|
processingMode: getStreamPref("video.processing.mode"),
|
||||||
sharpness: getStreamPref("video.processing.sharpness"),
|
sharpness: getStreamPref("video.processing.sharpness"),
|
||||||
saturation: getStreamPref("video.saturation"),
|
saturation: getStreamPref("video.saturation"),
|
||||||
contrast: getStreamPref("video.contrast"),
|
contrast: getStreamPref("video.contrast"),
|
||||||
@ -5078,11 +5101,11 @@ class TouchController {
|
|||||||
var controller_customization_default = "var shareButtonPressed=currentGamepad.buttons[17]?.pressed,shareButtonHandled=!1,xCloudGamepad=$xCloudGamepadVar$;if(currentGamepad.id in window.BX_STREAM_SETTINGS.controllers){let controller=window.BX_STREAM_SETTINGS.controllers[currentGamepad.id];if(controller?.customization){let{mapping,ranges}=controller.customization,pressedButtons={},releasedButtons={},isModified=!1;if(ranges.LeftTrigger){let[from,to]=ranges.LeftTrigger;xCloudGamepad.LeftTrigger=xCloudGamepad.LeftTrigger>to?1:xCloudGamepad.LeftTrigger,xCloudGamepad.LeftTrigger=xCloudGamepad.LeftTrigger<from?0:xCloudGamepad.LeftTrigger}if(ranges.RightTrigger){let[from,to]=ranges.RightTrigger;xCloudGamepad.RightTrigger=xCloudGamepad.RightTrigger>to?1:xCloudGamepad.RightTrigger,xCloudGamepad.RightTrigger=xCloudGamepad.RightTrigger<from?0:xCloudGamepad.RightTrigger}if(ranges.LeftThumb){let[from,to]=ranges.LeftThumb,xAxis=xCloudGamepad.LeftThumbXAxis,yAxis=xCloudGamepad.LeftThumbYAxis,range=Math.abs(Math.sqrt(xAxis*xAxis+yAxis*yAxis)),newRange=range>to?1:range;if(newRange=newRange<from?0:newRange,newRange!==range)xCloudGamepad.LeftThumbXAxis=xAxis*(newRange/range),xCloudGamepad.LeftThumbYAxis=yAxis*(newRange/range)}if(ranges.RightThumb){let[from,to]=ranges.RightThumb,xAxis=xCloudGamepad.RightThumbXAxis,yAxis=xCloudGamepad.RightThumbYAxis,range=Math.abs(Math.sqrt(xAxis*xAxis+yAxis*yAxis)),newRange=range>to?1:range;if(newRange=newRange<from?0:newRange,newRange!==range)xCloudGamepad.RightThumbXAxis=xAxis*(newRange/range),xCloudGamepad.RightThumbYAxis=yAxis*(newRange/range)}if(shareButtonPressed&&\"Share\"in mapping){let targetButton=mapping.Share;if(typeof targetButton===\"string\")pressedButtons[targetButton]=1;shareButtonHandled=!0,delete mapping.Share}let key;for(key in mapping){let mappedKey=mapping[key];if(key===\"LeftStickAxes\"||key===\"RightStickAxes\"){let sourceX,sourceY,targetX,targetY;if(key===\"LeftStickAxes\")sourceX=\"LeftThumbXAxis\",sourceY=\"LeftThumbYAxis\",targetX=\"RightThumbXAxis\",targetY=\"RightThumbYAxis\";else sourceX=\"RightThumbXAxis\",sourceY=\"RightThumbYAxis\",targetX=\"LeftThumbXAxis\",targetY=\"LeftThumbYAxis\";if(typeof mappedKey===\"string\"){let rangeX=xCloudGamepad[sourceX],rangeY=xCloudGamepad[sourceY];if(Math.abs(Math.sqrt(rangeX*rangeX+rangeY*rangeY))>=0.1)pressedButtons[targetX]=rangeX,pressedButtons[targetY]=rangeY}releasedButtons[sourceX]=0,releasedButtons[sourceY]=0,isModified=!0}else if(typeof mappedKey===\"string\"){let pressed=!1,value=0;if(key===\"LeftTrigger\"||key===\"RightTrigger\"){let currentRange=xCloudGamepad[key];if(mappedKey===\"LeftTrigger\"||mappedKey===\"RightTrigger\")pressed=currentRange>=0.1,value=currentRange;else pressed=!0,value=currentRange>=0.9?1:0}else if(xCloudGamepad[key])pressed=!0,value=xCloudGamepad[key];if(pressed)pressedButtons[mappedKey]=value,releasedButtons[key]=0,isModified=!0}else if(mappedKey===!1)pressedButtons[key]=0,isModified=!0}isModified&&Object.assign(xCloudGamepad,releasedButtons,pressedButtons)}}if(shareButtonPressed&&!shareButtonHandled)window.dispatchEvent(new Event(BxEvent.CAPTURE_SCREENSHOT));\n";
|
var controller_customization_default = "var shareButtonPressed=currentGamepad.buttons[17]?.pressed,shareButtonHandled=!1,xCloudGamepad=$xCloudGamepadVar$;if(currentGamepad.id in window.BX_STREAM_SETTINGS.controllers){let controller=window.BX_STREAM_SETTINGS.controllers[currentGamepad.id];if(controller?.customization){let{mapping,ranges}=controller.customization,pressedButtons={},releasedButtons={},isModified=!1;if(ranges.LeftTrigger){let[from,to]=ranges.LeftTrigger;xCloudGamepad.LeftTrigger=xCloudGamepad.LeftTrigger>to?1:xCloudGamepad.LeftTrigger,xCloudGamepad.LeftTrigger=xCloudGamepad.LeftTrigger<from?0:xCloudGamepad.LeftTrigger}if(ranges.RightTrigger){let[from,to]=ranges.RightTrigger;xCloudGamepad.RightTrigger=xCloudGamepad.RightTrigger>to?1:xCloudGamepad.RightTrigger,xCloudGamepad.RightTrigger=xCloudGamepad.RightTrigger<from?0:xCloudGamepad.RightTrigger}if(ranges.LeftThumb){let[from,to]=ranges.LeftThumb,xAxis=xCloudGamepad.LeftThumbXAxis,yAxis=xCloudGamepad.LeftThumbYAxis,range=Math.abs(Math.sqrt(xAxis*xAxis+yAxis*yAxis)),newRange=range>to?1:range;if(newRange=newRange<from?0:newRange,newRange!==range)xCloudGamepad.LeftThumbXAxis=xAxis*(newRange/range),xCloudGamepad.LeftThumbYAxis=yAxis*(newRange/range)}if(ranges.RightThumb){let[from,to]=ranges.RightThumb,xAxis=xCloudGamepad.RightThumbXAxis,yAxis=xCloudGamepad.RightThumbYAxis,range=Math.abs(Math.sqrt(xAxis*xAxis+yAxis*yAxis)),newRange=range>to?1:range;if(newRange=newRange<from?0:newRange,newRange!==range)xCloudGamepad.RightThumbXAxis=xAxis*(newRange/range),xCloudGamepad.RightThumbYAxis=yAxis*(newRange/range)}if(shareButtonPressed&&\"Share\"in mapping){let targetButton=mapping.Share;if(typeof targetButton===\"string\")pressedButtons[targetButton]=1;shareButtonHandled=!0,delete mapping.Share}let key;for(key in mapping){let mappedKey=mapping[key];if(key===\"LeftStickAxes\"||key===\"RightStickAxes\"){let sourceX,sourceY,targetX,targetY;if(key===\"LeftStickAxes\")sourceX=\"LeftThumbXAxis\",sourceY=\"LeftThumbYAxis\",targetX=\"RightThumbXAxis\",targetY=\"RightThumbYAxis\";else sourceX=\"RightThumbXAxis\",sourceY=\"RightThumbYAxis\",targetX=\"LeftThumbXAxis\",targetY=\"LeftThumbYAxis\";if(typeof mappedKey===\"string\"){let rangeX=xCloudGamepad[sourceX],rangeY=xCloudGamepad[sourceY];if(Math.abs(Math.sqrt(rangeX*rangeX+rangeY*rangeY))>=0.1)pressedButtons[targetX]=rangeX,pressedButtons[targetY]=rangeY}releasedButtons[sourceX]=0,releasedButtons[sourceY]=0,isModified=!0}else if(typeof mappedKey===\"string\"){let pressed=!1,value=0;if(key===\"LeftTrigger\"||key===\"RightTrigger\"){let currentRange=xCloudGamepad[key];if(mappedKey===\"LeftTrigger\"||mappedKey===\"RightTrigger\")pressed=currentRange>=0.1,value=currentRange;else pressed=!0,value=currentRange>=0.9?1:0}else if(xCloudGamepad[key])pressed=!0,value=xCloudGamepad[key];if(pressed)pressedButtons[mappedKey]=value,releasedButtons[key]=0,isModified=!0}else if(mappedKey===!1)pressedButtons[key]=0,isModified=!0}isModified&&Object.assign(xCloudGamepad,releasedButtons,pressedButtons)}}if(shareButtonPressed&&!shareButtonHandled)window.dispatchEvent(new Event(BxEvent.CAPTURE_SCREENSHOT));\n";
|
||||||
var poll_gamepad_default = "var self=this;if(window.BX_EXPOSED.disableGamepadPolling){self.inputConfiguration.useIntervalWorkerThreadForInput&&self.intervalWorker?self.intervalWorker.scheduleTimer(50):self.pollGamepadssetTimeoutTimerID=window.setTimeout(self.pollGamepads,50);return}var currentGamepad=$gamepadVar$,btnHome=currentGamepad.buttons[16];if(btnHome){if(!self.bxHomeStates)self.bxHomeStates={};let intervalMs=0,hijack=!1;if(btnHome.pressed)if(hijack=!0,intervalMs=16,self.gamepadIsIdle.set(currentGamepad.index,!1),self.bxHomeStates[currentGamepad.index]){let lastTimestamp=self.bxHomeStates[currentGamepad.index].timestamp;if(currentGamepad.timestamp!==lastTimestamp){if(self.bxHomeStates[currentGamepad.index].timestamp=currentGamepad.timestamp,window.BX_EXPOSED.handleControllerShortcut(currentGamepad))self.bxHomeStates[currentGamepad.index].shortcutPressed+=1}}else window.BX_EXPOSED.resetControllerShortcut(currentGamepad.index),self.bxHomeStates[currentGamepad.index]={shortcutPressed:0,timestamp:currentGamepad.timestamp};else if(self.bxHomeStates[currentGamepad.index]){hijack=!0;let info=structuredClone(self.bxHomeStates[currentGamepad.index]);if(self.bxHomeStates[currentGamepad.index]=null,info.shortcutPressed===0){let fakeGamepadMappings=[{GamepadIndex:currentGamepad.index,A:0,B:0,X:0,Y:0,LeftShoulder:0,RightShoulder:0,LeftTrigger:0,RightTrigger:0,View:0,Menu:0,LeftThumb:0,RightThumb:0,DPadUp:0,DPadDown:0,DPadLeft:0,DPadRight:0,Nexus:1,LeftThumbXAxis:0,LeftThumbYAxis:0,RightThumbXAxis:0,RightThumbYAxis:0,PhysicalPhysicality:0,VirtualPhysicality:0,Dirty:!0,Virtual:!1}];intervalMs=currentGamepad.timestamp-info.timestamp>=500?500:100,self.inputSink.onGamepadInput(performance.now()-intervalMs,fakeGamepadMappings)}else intervalMs=window.BX_STREAM_SETTINGS.controllerPollingRate}if(hijack&&intervalMs){self.inputConfiguration.useIntervalWorkerThreadForInput&&self.intervalWorker?self.intervalWorker.scheduleTimer(intervalMs):self.pollGamepadssetTimeoutTimerID=setTimeout(self.pollGamepads,intervalMs);return}}\n";
|
var poll_gamepad_default = "var self=this;if(window.BX_EXPOSED.disableGamepadPolling){self.inputConfiguration.useIntervalWorkerThreadForInput&&self.intervalWorker?self.intervalWorker.scheduleTimer(50):self.pollGamepadssetTimeoutTimerID=window.setTimeout(self.pollGamepads,50);return}var currentGamepad=$gamepadVar$,btnHome=currentGamepad.buttons[16];if(btnHome){if(!self.bxHomeStates)self.bxHomeStates={};let intervalMs=0,hijack=!1;if(btnHome.pressed)if(hijack=!0,intervalMs=16,self.gamepadIsIdle.set(currentGamepad.index,!1),self.bxHomeStates[currentGamepad.index]){let lastTimestamp=self.bxHomeStates[currentGamepad.index].timestamp;if(currentGamepad.timestamp!==lastTimestamp){if(self.bxHomeStates[currentGamepad.index].timestamp=currentGamepad.timestamp,window.BX_EXPOSED.handleControllerShortcut(currentGamepad))self.bxHomeStates[currentGamepad.index].shortcutPressed+=1}}else window.BX_EXPOSED.resetControllerShortcut(currentGamepad.index),self.bxHomeStates[currentGamepad.index]={shortcutPressed:0,timestamp:currentGamepad.timestamp};else if(self.bxHomeStates[currentGamepad.index]){hijack=!0;let info=structuredClone(self.bxHomeStates[currentGamepad.index]);if(self.bxHomeStates[currentGamepad.index]=null,info.shortcutPressed===0){let fakeGamepadMappings=[{GamepadIndex:currentGamepad.index,A:0,B:0,X:0,Y:0,LeftShoulder:0,RightShoulder:0,LeftTrigger:0,RightTrigger:0,View:0,Menu:0,LeftThumb:0,RightThumb:0,DPadUp:0,DPadDown:0,DPadLeft:0,DPadRight:0,Nexus:1,LeftThumbXAxis:0,LeftThumbYAxis:0,RightThumbXAxis:0,RightThumbYAxis:0,PhysicalPhysicality:0,VirtualPhysicality:0,Dirty:!0,Virtual:!1}];intervalMs=currentGamepad.timestamp-info.timestamp>=500?500:100,self.inputSink.onGamepadInput(performance.now()-intervalMs,fakeGamepadMappings)}else intervalMs=window.BX_STREAM_SETTINGS.controllerPollingRate}if(hijack&&intervalMs){self.inputConfiguration.useIntervalWorkerThreadForInput&&self.intervalWorker?self.intervalWorker.scheduleTimer(intervalMs):self.pollGamepadssetTimeoutTimerID=setTimeout(self.pollGamepads,intervalMs);return}}\n";
|
||||||
var expose_stream_session_default = 'var self=this;window.BX_EXPOSED.streamSession=self;var orgSetMicrophoneState=self.setMicrophoneState.bind(self);self.setMicrophoneState=(state)=>{orgSetMicrophoneState(state),window.BxEventBus.Stream.emit("microphone.state.changed",{state})};window.dispatchEvent(new Event(BxEvent.STREAM_SESSION_READY));var updateDimensionsStr=self.updateDimensions.toString();if(updateDimensionsStr.startsWith("function "))updateDimensionsStr=updateDimensionsStr.substring(9);var renderTargetVar=updateDimensionsStr.match(/if\\((\\w+)\\){/)[1];updateDimensionsStr=updateDimensionsStr.replaceAll(renderTargetVar+".scroll","scroll");updateDimensionsStr=updateDimensionsStr.replace(`if(${renderTargetVar}){`,`\nif (${renderTargetVar}) {\nconst scrollWidth = ${renderTargetVar}.dataset.width ? parseInt(${renderTargetVar}.dataset.width) : ${renderTargetVar}.scrollWidth;\nconst scrollHeight = ${renderTargetVar}.dataset.height ? parseInt(${renderTargetVar}.dataset.height) : ${renderTargetVar}.scrollHeight;\n`);eval(`this.updateDimensions = function ${updateDimensionsStr}`);\n';
|
var expose_stream_session_default = 'var self=this;window.BX_EXPOSED.streamSession=self;var orgSetMicrophoneState=self.setMicrophoneState.bind(self);self.setMicrophoneState=(state)=>{orgSetMicrophoneState(state),window.BxEventBus.Stream.emit("microphone.state.changed",{state})};window.dispatchEvent(new Event(BxEvent.STREAM_SESSION_READY));var updateDimensionsStr=self.updateDimensions.toString();if(updateDimensionsStr.startsWith("function "))updateDimensionsStr=updateDimensionsStr.substring(9);var renderTargetVar=updateDimensionsStr.match(/if\\((\\w+)\\){/)[1];updateDimensionsStr=updateDimensionsStr.replaceAll(renderTargetVar+".scroll","scroll");updateDimensionsStr=updateDimensionsStr.replace(`if(${renderTargetVar}){`,`\nif (${renderTargetVar}) {\nconst scrollWidth = ${renderTargetVar}.dataset.width ? parseInt(${renderTargetVar}.dataset.width) : ${renderTargetVar}.scrollWidth;\nconst scrollHeight = ${renderTargetVar}.dataset.height ? parseInt(${renderTargetVar}.dataset.height) : ${renderTargetVar}.scrollHeight;\n`);eval(`this.updateDimensions = function ${updateDimensionsStr}`);\n';
|
||||||
var game_card_icons_default = `var supportedInputIcons=$supportedInputIcons$,{productId}=$param$;supportedInputIcons.shift();if(window.BX_EXPOSED.localCoOpManager.isSupported(productId))supportedInputIcons.push(window.BX_EXPOSED.createReactLocalCoOpIcon);`;
|
var game_card_icons_default = `var supportedInputIcons=$supportedInputIcons$,productId=$productId$;supportedInputIcons.shift();if(window.BX_EXPOSED.localCoOpManager.isSupported(productId))supportedInputIcons.push(window.BX_EXPOSED.createReactLocalCoOpIcon);`;
|
||||||
var local_co_op_enable_default = 'this.orgOnGamepadChanged=this.onGamepadChanged;this.orgOnGamepadInput=this.onGamepadInput;var match,onGamepadChangedStr=this.onGamepadChanged.toString();if(onGamepadChangedStr.startsWith("function "))onGamepadChangedStr=onGamepadChangedStr.substring(9);onGamepadChangedStr=onGamepadChangedStr.replaceAll("0","arguments[1]");eval(`this.patchedOnGamepadChanged = function ${onGamepadChangedStr}`);var onGamepadInputStr=this.onGamepadInput.toString();if(onGamepadInputStr.startsWith("function "))onGamepadInputStr=onGamepadInputStr.substring(9);match=onGamepadInputStr.match(/(\\w+\\.GamepadIndex)/);if(match){let gamepadIndexVar=match[0];onGamepadInputStr=onGamepadInputStr.replace("this.gamepadStates.get(",`this.gamepadStates.get(${gamepadIndexVar},`),eval(`this.patchedOnGamepadInput = function ${onGamepadInputStr}`),BxLogger.info("supportLocalCoOp","✅ Successfully patched local co-op support")}else BxLogger.error("supportLocalCoOp","❌ Unable to patch local co-op support");this.toggleLocalCoOp=(enable)=>{BxLogger.info("toggleLocalCoOp",enable?"Enabled":"Disabled"),this.onGamepadChanged=enable?this.patchedOnGamepadChanged:this.orgOnGamepadChanged,this.onGamepadInput=enable?this.patchedOnGamepadInput:this.orgOnGamepadInput;let gamepads=window.navigator.getGamepads();for(let gamepad of gamepads){if(!gamepad?.connected)continue;if(gamepad.id.includes("Better xCloud"))continue;gamepad._noToast=!0,window.dispatchEvent(new GamepadEvent("gamepaddisconnected",{gamepad})),window.dispatchEvent(new GamepadEvent("gamepadconnected",{gamepad}))}};window.BX_EXPOSED.toggleLocalCoOp=this.toggleLocalCoOp.bind(null);\n';
|
var local_co_op_enable_default = 'this.orgOnGamepadChanged=this.onGamepadChanged;this.orgOnGamepadInput=this.onGamepadInput;var match,onGamepadChangedStr=this.onGamepadChanged.toString();if(onGamepadChangedStr.startsWith("function "))onGamepadChangedStr=onGamepadChangedStr.substring(9);onGamepadChangedStr=onGamepadChangedStr.replaceAll("0","arguments[1]");eval(`this.patchedOnGamepadChanged = function ${onGamepadChangedStr}`);var onGamepadInputStr=this.onGamepadInput.toString();if(onGamepadInputStr.startsWith("function "))onGamepadInputStr=onGamepadInputStr.substring(9);match=onGamepadInputStr.match(/(\\w+\\.GamepadIndex)/);if(match){let gamepadIndexVar=match[0];onGamepadInputStr=onGamepadInputStr.replace("this.gamepadStates.get(",`this.gamepadStates.get(${gamepadIndexVar},`),eval(`this.patchedOnGamepadInput = function ${onGamepadInputStr}`),BxLogger.info("supportLocalCoOp","✅ Successfully patched local co-op support")}else BxLogger.error("supportLocalCoOp","❌ Unable to patch local co-op support");this.toggleLocalCoOp=(enable)=>{BxLogger.info("toggleLocalCoOp",enable?"Enabled":"Disabled"),this.onGamepadChanged=enable?this.patchedOnGamepadChanged:this.orgOnGamepadChanged,this.onGamepadInput=enable?this.patchedOnGamepadInput:this.orgOnGamepadInput;let gamepads=window.navigator.getGamepads();for(let gamepad of gamepads){if(!gamepad?.connected)continue;if(gamepad.id.includes("Better xCloud"))continue;gamepad._noToast=!0,window.dispatchEvent(new GamepadEvent("gamepaddisconnected",{gamepad})),window.dispatchEvent(new GamepadEvent("gamepadconnected",{gamepad}))}};window.BX_EXPOSED.toggleLocalCoOp=this.toggleLocalCoOp.bind(null);\n';
|
||||||
var remote_play_keep_alive_default = `try{if(JSON.parse(e).reason==="WarningForBeingIdle"&&window.location.pathname.includes("/play/consoles/launch/")){this.sendKeepAlive();return}}catch(ex){console.log(ex)}`;
|
var remote_play_keep_alive_default = `try{if(JSON.parse(e).reason==="WarningForBeingIdle"&&window.location.pathname.includes("/play/consoles/launch/")){this.sendKeepAlive();return}}catch(ex){console.log(ex)}`;
|
||||||
var vibration_adjust_default = `if(e?.gamepad?.connected){let gamepadSettings=window.BX_STREAM_SETTINGS.controllers[e.gamepad.id];if(gamepadSettings?.customization){let intensity=gamepadSettings.customization.vibrationIntensity;if(intensity<=0){e.repeat=0;return}else if(intensity<1)e.leftMotorPercent*=intensity,e.rightMotorPercent*=intensity,e.leftTriggerMotorPercent*=intensity,e.rightTriggerMotorPercent*=intensity}}`;
|
var vibration_adjust_default = `if(e?.gamepad?.connected){let gamepadSettings=window.BX_STREAM_SETTINGS.controllers[e.gamepad.id];if(gamepadSettings?.customization){let intensity=gamepadSettings.customization.vibrationIntensity;if(intensity<=0){e.repeat=0;return}else if(intensity<1)e.leftMotorPercent*=intensity,e.rightMotorPercent*=intensity,e.leftTriggerMotorPercent*=intensity,e.rightTriggerMotorPercent*=intensity}}`;
|
||||||
var stream_hud_default = `var options=arguments[0];window.BX_EXPOSED.showStreamMenu=options.onShowStreamMenu;options.guideUI=null;window.BX_EXPOSED.reactUseEffect(()=>{window.BxEventBus.Stream.emit("ui.streamHud.rendered",{expanded:options.offset.x===0})});`;
|
var stream_hud_default = `window.BX_EXPOSED.showStreamMenu=$onShowStreamMenu$;$guideUI$=null;window.BX_EXPOSED.reactUseEffect(()=>{window.BxEventBus.Stream.emit("ui.streamHud.rendered",{expanded:$offset$.x===0})});`;
|
||||||
var create_portal_default = `var $dom=arguments[1];if($dom&&$dom instanceof HTMLElement&&$dom.id==="gamepass-dialog-root"){let showing=!1,$dialog=$dom.firstElementChild?.firstElementChild;if($dialog)showing=!$dialog.className.includes("pageChangeExit");window.BxEventBus.Script.emit(showing?"dialog.shown":"dialog.dismissed",{})}`;
|
var create_portal_default = `var $dom=arguments[1];if($dom&&$dom instanceof HTMLElement&&$dom.id==="gamepass-dialog-root"){let showing=!1,$dialog=$dom.firstElementChild?.firstElementChild;if($dialog)showing=!$dialog.className.includes("pageChangeExit");window.BxEventBus.Script.emit(showing?"dialog.shown":"dialog.dismissed",{})}`;
|
||||||
class PatcherUtils {
|
class PatcherUtils {
|
||||||
static indexOf(txt, searchString, startIndex, maxRange = 0, after = !1) {
|
static indexOf(txt, searchString, startIndex, maxRange = 0, after = !1) {
|
||||||
@ -5133,10 +5156,34 @@ class PatcherUtils {
|
|||||||
end += 1;
|
end += 1;
|
||||||
return str.substring(start, end);
|
return str.substring(start, end);
|
||||||
}
|
}
|
||||||
static injectUseEffect(str, index, group, eventName) {
|
static injectUseEffect(str, index, group, eventName, separator = ";") {
|
||||||
let newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.${group}.emit('${eventName}', {}), []);`;
|
let newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.${group}.emit('${eventName}', {}), [])${separator}`;
|
||||||
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
||||||
}
|
}
|
||||||
|
static findAndParseParams(str, index, maxRange) {
|
||||||
|
let substr = str.substring(index, index + maxRange), startIndex = substr.indexOf("({");
|
||||||
|
if (startIndex < 0) return !1;
|
||||||
|
startIndex += 1;
|
||||||
|
let endIndex = substr.indexOf("})", startIndex);
|
||||||
|
if (endIndex < 0) return !1;
|
||||||
|
endIndex += 1;
|
||||||
|
try {
|
||||||
|
let input = substr.substring(startIndex, endIndex);
|
||||||
|
return PatcherUtils.parseObjectVariables(input);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static parseObjectVariables(input) {
|
||||||
|
try {
|
||||||
|
let pairs = [...input.matchAll(/(\w+)\s*:\s*([a-zA-Z_$][\w$]*)/g)], result = {};
|
||||||
|
for (let [_, key, value] of pairs)
|
||||||
|
result[key] = value;
|
||||||
|
return result;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var LOG_TAG2 = "Patcher", PATCHES = {
|
var LOG_TAG2 = "Patcher", PATCHES = {
|
||||||
disableAiTrack(str) {
|
disableAiTrack(str) {
|
||||||
@ -5193,7 +5240,7 @@ var LOG_TAG2 = "Patcher", PATCHES = {
|
|||||||
return str.replace(text, "this.shouldCollectStats=!1");
|
return str.replace(text, "this.shouldCollectStats=!1");
|
||||||
},
|
},
|
||||||
patchPollGamepads(str) {
|
patchPollGamepads(str) {
|
||||||
let index = str.indexOf("},this.pollGamepads=()=>{");
|
let index = str.indexOf('()(this,"pollGamepads",');
|
||||||
if (index < 0) return !1;
|
if (index < 0) return !1;
|
||||||
let setTimeoutIndex = str.indexOf("setTimeout(this.pollGamepads", index);
|
let setTimeoutIndex = str.indexOf("setTimeout(this.pollGamepads", index);
|
||||||
if (setTimeoutIndex < 0) return !1;
|
if (setTimeoutIndex < 0) return !1;
|
||||||
@ -5233,8 +5280,9 @@ logFunc(logTag, '//', logMessage);
|
|||||||
disableGamepadDisconnectedScreen(str) {
|
disableGamepadDisconnectedScreen(str) {
|
||||||
let index = str.indexOf('"GamepadDisconnected_Title",');
|
let index = str.indexOf('"GamepadDisconnected_Title",');
|
||||||
if (index < 0) return !1;
|
if (index < 0) return !1;
|
||||||
let constIndex = str.indexOf("const", index - 30);
|
let constIndex = PatcherUtils.lastIndexOf(str, "const[", index, 100);
|
||||||
return str = str.substring(0, constIndex) + "e.onClose();return null;" + str.substring(constIndex), str;
|
if (constIndex < 0) return !1;
|
||||||
|
return str = PatcherUtils.insertAt(str, constIndex, "e();return null;"), str;
|
||||||
},
|
},
|
||||||
patchUpdateInputConfigurationAsync(str) {
|
patchUpdateInputConfigurationAsync(str) {
|
||||||
let text = "async updateInputConfigurationAsync(e){";
|
let text = "async updateInputConfigurationAsync(e){";
|
||||||
@ -5319,11 +5367,21 @@ if (titleInfo && !titleInfo.details.hasTouchSupport && !titleInfo.details.hasFak
|
|||||||
return str = str.replace(text, "this.useCombinedAudioVideoStream=true"), str;
|
return str = str.replace(text, "this.useCombinedAudioVideoStream=true"), str;
|
||||||
},
|
},
|
||||||
patchStreamHud(str) {
|
patchStreamHud(str) {
|
||||||
let index = str.indexOf("let{onCollapse");
|
let index = str.indexOf("({onCollapse:");
|
||||||
if (index < 0) return !1;
|
if (index < 0) return !1;
|
||||||
let newCode = stream_hud_default;
|
try {
|
||||||
if (getGlobalPref("touchController.mode") === "off") newCode += "options.canShowTakHUD = false;";
|
if (!PatcherUtils.findAndParseParams(str, index, 1000)) return !1;
|
||||||
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
let canShowTakHUDVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "canShowTakHUD", index, 500, !0) + 1), guideUIVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "guideUI", index, 500, !0) + 1), onShowStreamMenuVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "onShowStreamMenu", index, 500, !0) + 1), offsetVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "offset", index, 500, !0) + 1), newCode = renderString(stream_hud_default, {
|
||||||
|
guideUI: guideUIVar,
|
||||||
|
onShowStreamMenu: onShowStreamMenuVar,
|
||||||
|
offset: offsetVar
|
||||||
|
});
|
||||||
|
if (getGlobalPref("touchController.mode") === "off") newCode += `${canShowTakHUDVar} = false;`;
|
||||||
|
let bracketIndex = PatcherUtils.indexOf(str, "}){", index, 500, !0);
|
||||||
|
return str = PatcherUtils.insertAt(str, bracketIndex, newCode), str;
|
||||||
|
} catch (e) {
|
||||||
|
return !1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
broadcastPollingMode(str) {
|
broadcastPollingMode(str) {
|
||||||
let text = ".setPollingMode=e=>{";
|
let text = ".setPollingMode=e=>{";
|
||||||
@ -5398,9 +5456,9 @@ true` + text;
|
|||||||
return str = str.replace(text, newCode), str;
|
return str = str.replace(text, newCode), str;
|
||||||
},
|
},
|
||||||
skipFeedbackDialog(str) {
|
skipFeedbackDialog(str) {
|
||||||
let text = "shouldTransitionToFeedback(e){";
|
let index = str.indexOf("}shouldTransitionToFeedback(");
|
||||||
if (!str.includes(text)) return !1;
|
if (index >= 0 && (index = PatcherUtils.indexOf(str, "}){", index, 200, !0)), index < 0) return !1;
|
||||||
return str = str.replace(text, text + "return !1;"), str;
|
return str = PatcherUtils.insertAt(str, index, "return !1;"), str;
|
||||||
},
|
},
|
||||||
enableNativeMkb(str) {
|
enableNativeMkb(str) {
|
||||||
let index = str.indexOf(".mouseSupported&&");
|
let index = str.indexOf(".mouseSupported&&");
|
||||||
@ -5415,10 +5473,9 @@ true` + text;
|
|||||||
return str = str.replace(text, text + "return true;"), str;
|
return str = str.replace(text, text + "return true;"), str;
|
||||||
},
|
},
|
||||||
exposeInputChannel(str) {
|
exposeInputChannel(str) {
|
||||||
let index = str.indexOf("this.flushData=");
|
let text = '()(this,"flushData",(';
|
||||||
if (index < 0) return !1;
|
if (!str.includes(text)) return !1;
|
||||||
let newCode = "window.BX_EXPOSED.inputChannel = this,";
|
return str = str.replace(text, '()(window.BX_EXPOSED.inputChannel = this, "flushData", ('), str;
|
||||||
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
|
||||||
},
|
},
|
||||||
disableNativeRequestPointerLock(str) {
|
disableNativeRequestPointerLock(str) {
|
||||||
let text = "async requestPointerLock(){";
|
let text = "async requestPointerLock(){";
|
||||||
@ -5441,19 +5498,19 @@ true` + text;
|
|||||||
let match = /render:.*?jsx\)\(([^,]+),/.exec(str.substring(index, index + 100));
|
let match = /render:.*?jsx\)\(([^,]+),/.exec(str.substring(index, index + 100));
|
||||||
if (!match) return !1;
|
if (!match) return !1;
|
||||||
let funcName = match[1];
|
let funcName = match[1];
|
||||||
if (index = str.indexOf(`const ${funcName}=e=>{`), index > -1 && (index = str.indexOf("return ", index)), index > -1 && (index = str.indexOf("?", index)), index < 0) return !1;
|
if (index = str.indexOf(`const ${funcName}=({children`), index > -1 && (index = PatcherUtils.indexOf(str, "return ", 300)), index > -1 && (index = PatcherUtils.indexOf(str, "?", 100)), index < 0) return !1;
|
||||||
return str = str.substring(0, index) + "|| true" + str.substring(index), str;
|
return str = str.substring(0, index) + "|| true" + str.substring(index), str;
|
||||||
},
|
},
|
||||||
ignoreNewsSection(str) {
|
ignoreNewsSection(str) {
|
||||||
let index = str.indexOf('Logger("CarouselRow")');
|
let index = str.indexOf('("CarouselRow"))');
|
||||||
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const ", index, 200)), index < 0) return !1;
|
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "const ", index, 200)), index < 0) return !1;
|
||||||
return str = PatcherUtils.insertAt(str, index, "return null;"), str;
|
return str = PatcherUtils.insertAt(str, index, "return null;"), str;
|
||||||
},
|
},
|
||||||
ignorePlayWithFriendsSection(str) {
|
ignorePlayWithFriendsSection(str) {
|
||||||
let index = str.indexOf('location:"PlayWithFriendsRow",');
|
let index = str.indexOf('location:"PlayWithFriendsRow",');
|
||||||
if (index < 0) return !1;
|
if (index < 0) return !1;
|
||||||
if (index = PatcherUtils.lastIndexOf(str, "return", index, 50), index < 0) return !1;
|
if (index = PatcherUtils.lastIndexOf(str, "=>", index, 50), index < 0) return !1;
|
||||||
return str = PatcherUtils.replaceWith(str, index, "return", "return null;"), str;
|
return str = PatcherUtils.replaceWith(str, index, "=>", "=> true ? null :"), str;
|
||||||
},
|
},
|
||||||
ignoreAllGamesSection(str) {
|
ignoreAllGamesSection(str) {
|
||||||
let index = str.indexOf('className:"AllGamesRow-module__allGamesRowContainer');
|
let index = str.indexOf('className:"AllGamesRow-module__allGamesRowContainer');
|
||||||
@ -5473,8 +5530,9 @@ true` + text;
|
|||||||
},
|
},
|
||||||
ignoreSiglSections(str) {
|
ignoreSiglSections(str) {
|
||||||
let index = str.indexOf("SiglRow-module__heroCard___");
|
let index = str.indexOf("SiglRow-module__heroCard___");
|
||||||
if (index < 0) return !1;
|
if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, "const[", index, 300)), index < 0) return !1;
|
||||||
if (index = PatcherUtils.lastIndexOf(str, "const[", index, 300), index < 0) return !1;
|
let params = PatcherUtils.findAndParseParams(str, index - 500, 500);
|
||||||
|
if (!params || !params.id) return !1;
|
||||||
let PREF_HIDE_SECTIONS = getGlobalPref("ui.hideSections"), siglIds = [], sections = {
|
let PREF_HIDE_SECTIONS = getGlobalPref("ui.hideSections"), siglIds = [], sections = {
|
||||||
"native-mkb": "8fa264dd-124f-4af3-97e8-596fcdf4b486",
|
"native-mkb": "8fa264dd-124f-4af3-97e8-596fcdf4b486",
|
||||||
"most-popular": "e7590b22-e299-44db-ae22-25c61405454c",
|
"most-popular": "e7590b22-e299-44db-ae22-25c61405454c",
|
||||||
@ -5485,14 +5543,7 @@ true` + text;
|
|||||||
let galleryId = sections[section];
|
let galleryId = sections[section];
|
||||||
galleryId && siglIds.push(galleryId);
|
galleryId && siglIds.push(galleryId);
|
||||||
}
|
}
|
||||||
let newCode = `
|
let checkSyntax = siglIds.map((item2) => `${params.id} === "${item2}"`).join(" || "), newCode = `if (${params.id} && (${checkSyntax})) return null;`;
|
||||||
if (e && e.id) {
|
|
||||||
const siglId = e.id;
|
|
||||||
if (${siglIds.map((item2) => `siglId === "${item2}"`).join(" || ")}) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
||||||
},
|
},
|
||||||
ignoreGenresSection(str) {
|
ignoreGenresSection(str) {
|
||||||
@ -5543,8 +5594,8 @@ if (this.baseStorageKey in window.BX_EXPOSED.overrideSettings) {
|
|||||||
return str = PatcherUtils.replaceWith(str, index, '"All"', '"Locked"'), str;
|
return str = PatcherUtils.replaceWith(str, index, '"All"', '"Locked"'), str;
|
||||||
},
|
},
|
||||||
disableTouchContextMenu(str) {
|
disableTouchContextMenu(str) {
|
||||||
let index = str.indexOf("arguments.length>2&&void 0!==arguments[2]?arguments[2]:500;");
|
let index = str.indexOf('.addEventListener("touchstart",');
|
||||||
if (index >= 0 && (index = str.indexOf('addEventListener("touchstart"', index)), index >= 0 && (index = PatcherUtils.lastIndexOf(str, "return ", index, 50)), index < 0) return !1;
|
if (index >= 0 && (index = PatcherUtils.indexOf(str, '.addEventListener("touchend"', index, 200)), index >= 0 && (index = PatcherUtils.lastIndexOf(str, "return ", index, 50)), index < 0) return !1;
|
||||||
return str = PatcherUtils.replaceWith(str, index, "return", "return () => {};"), str;
|
return str = PatcherUtils.replaceWith(str, index, "return", "return () => {};"), str;
|
||||||
},
|
},
|
||||||
modifyPreloadedState(str) {
|
modifyPreloadedState(str) {
|
||||||
@ -5597,12 +5648,14 @@ ${subsVar} = subs;
|
|||||||
if (initialIndex < 0) return !1;
|
if (initialIndex < 0) return !1;
|
||||||
let returnIndex = PatcherUtils.lastIndexOf(str, "return ", str.indexOf("SupportedInputsBadge"));
|
let returnIndex = PatcherUtils.lastIndexOf(str, "return ", str.indexOf("SupportedInputsBadge"));
|
||||||
if (returnIndex < 0) return !1;
|
if (returnIndex < 0) return !1;
|
||||||
let arrowIndex = PatcherUtils.lastIndexOf(str, "=>{", initialIndex, 300);
|
let productIdIndex = PatcherUtils.lastIndexOf(str, ",productId:", initialIndex, 300);
|
||||||
if (arrowIndex < 0) return !1;
|
if (productIdIndex < 0) return !1;
|
||||||
let paramVar = PatcherUtils.getVariableNameBefore(str, arrowIndex), supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "supportedInputIcons:", initialIndex, 100, !0));
|
let params = PatcherUtils.findAndParseParams(str, productIdIndex - 200, 400);
|
||||||
if (!paramVar || !supportedInputIconsVar) return !1;
|
if (!params || !params.productId) return !1;
|
||||||
|
let productIdVar = params.productId, supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, "supportedInputIcons:", initialIndex, 100, !0));
|
||||||
|
if (!supportedInputIconsVar) return !1;
|
||||||
let newCode = renderString(game_card_icons_default, {
|
let newCode = renderString(game_card_icons_default, {
|
||||||
param: paramVar,
|
productId: productIdVar,
|
||||||
supportedInputIcons: supportedInputIconsVar
|
supportedInputIcons: supportedInputIconsVar
|
||||||
});
|
});
|
||||||
return str = PatcherUtils.insertAt(str, returnIndex, newCode), str;
|
return str = PatcherUtils.insertAt(str, returnIndex, newCode), str;
|
||||||
@ -5628,8 +5681,8 @@ ${subsVar} = subs;
|
|||||||
},
|
},
|
||||||
injectErrorPageUseEffect(str) {
|
injectErrorPageUseEffect(str) {
|
||||||
let index = str.indexOf('"PureErrorPage-module__container');
|
let index = str.indexOf('"PureErrorPage-module__container');
|
||||||
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;
|
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "})=>(0,", index, 200)), index < 0) return !1;
|
||||||
return PatcherUtils.injectUseEffect(str, index, "Script", "ui.error.rendered");
|
return str = PatcherUtils.insertAt(str, index + 4, "{return "), str = PatcherUtils.injectUseEffect(str, index + 5, "Script", "ui.error.rendered"), str += "}", str;
|
||||||
},
|
},
|
||||||
injectStreamMenuUseEffect(str) {
|
injectStreamMenuUseEffect(str) {
|
||||||
let index = str.indexOf('"StreamMenu-module__container');
|
let index = str.indexOf('"StreamMenu-module__container');
|
||||||
@ -5841,20 +5894,20 @@ class PatcherCache {
|
|||||||
PATCH_ORDERS = this.cleanupPatches(PATCH_ORDERS), STREAM_PAGE_PATCH_ORDERS = this.cleanupPatches(STREAM_PAGE_PATCH_ORDERS), PRODUCT_DETAIL_PAGE_PATCH_ORDERS = this.cleanupPatches(PRODUCT_DETAIL_PAGE_PATCH_ORDERS), BxLogger.info(LOG_TAG2, "PATCH_ORDERS", PATCH_ORDERS.slice(0));
|
PATCH_ORDERS = this.cleanupPatches(PATCH_ORDERS), STREAM_PAGE_PATCH_ORDERS = this.cleanupPatches(STREAM_PAGE_PATCH_ORDERS), PRODUCT_DETAIL_PAGE_PATCH_ORDERS = this.cleanupPatches(PRODUCT_DETAIL_PAGE_PATCH_ORDERS), BxLogger.info(LOG_TAG2, "PATCH_ORDERS", PATCH_ORDERS.slice(0));
|
||||||
}
|
}
|
||||||
getSignature() {
|
getSignature() {
|
||||||
let scriptVersion = SCRIPT_VERSION, patches = JSON.stringify(ALL_PATCHES), webVersion = "", $link = document.querySelector('link[data-chunk="client"][as="script"][href*="/client."]');
|
let scriptVersion = SCRIPT_VERSION, patches = JSON.stringify(ALL_PATCHES), clientHash = "", $link = document.querySelector('link[data-chunk="client"][as="script"][href*="/client."]');
|
||||||
if ($link) {
|
if ($link) {
|
||||||
let match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
let match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
||||||
match && (webVersion = match[1]);
|
match && (clientHash = match[1]);
|
||||||
}
|
}
|
||||||
if (!webVersion) webVersion = document.querySelector("meta[name=gamepass-app-version]")?.content ?? "";
|
let webVersion = document.querySelector("meta[name=gamepass-app-version]")?.content ?? "", webVersionDate = document.querySelector("meta[name=gamepass-app-date]")?.content ?? "";
|
||||||
return hashCode(scriptVersion + webVersion + patches);
|
return `${scriptVersion}:${clientHash}:${webVersion}:${webVersionDate}:${hashCode(patches)}`;
|
||||||
}
|
}
|
||||||
clear() {
|
clear() {
|
||||||
window.localStorage.removeItem(this.KEY_CACHE), this.CACHE = {};
|
window.localStorage.removeItem(this.KEY_CACHE), this.CACHE = {};
|
||||||
}
|
}
|
||||||
checkSignature() {
|
checkSignature() {
|
||||||
let storedSig = window.localStorage.getItem(this.KEY_SIGNATURE) || 0, currentSig = this.getSignature();
|
let storedSig = window.localStorage.getItem(this.KEY_SIGNATURE) || 0, currentSig = this.getSignature();
|
||||||
if (currentSig !== parseInt(storedSig)) BxLogger.warning(LOG_TAG2, "Signature changed"), window.localStorage.setItem(this.KEY_SIGNATURE, currentSig.toString()), this.clear();
|
if (currentSig !== storedSig) BxLogger.warning(LOG_TAG2, "Signature changed"), window.localStorage.setItem(this.KEY_SIGNATURE, currentSig.toString()), this.clear();
|
||||||
else BxLogger.info(LOG_TAG2, "Signature unchanged");
|
else BxLogger.info(LOG_TAG2, "Signature unchanged");
|
||||||
}
|
}
|
||||||
cleanupPatches(patches) {
|
cleanupPatches(patches) {
|
||||||
@ -7393,6 +7446,7 @@ class SettingsDialog extends NavigationDialog {
|
|||||||
"video.maxFps",
|
"video.maxFps",
|
||||||
"video.player.powerPreference",
|
"video.player.powerPreference",
|
||||||
"video.processing",
|
"video.processing",
|
||||||
|
"video.processing.mode",
|
||||||
"video.ratio",
|
"video.ratio",
|
||||||
"video.position",
|
"video.position",
|
||||||
"video.processing.sharpness",
|
"video.processing.sharpness",
|
||||||
@ -9382,7 +9436,7 @@ class WebGL2Player extends BaseCanvasPlayer {
|
|||||||
updateCanvas() {
|
updateCanvas() {
|
||||||
console.log("updateCanvas", this.options);
|
console.log("updateCanvas", this.options);
|
||||||
let gl = this.gl, program = this.program, filterId = this.toFilterId(this.options.processing);
|
let gl = this.gl, program = this.program, filterId = this.toFilterId(this.options.processing);
|
||||||
gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), filterId), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpness), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness / 100), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast / 100), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation / 100);
|
gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), filterId), gl.uniform1i(gl.getUniformLocation(program, "qualityMode"), this.options.processingMode === "quality" ? 1 : 0), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpness / (this.options.processingMode === "quality" ? 1 : 1.2)), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness / 100), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast / 100), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation / 100);
|
||||||
}
|
}
|
||||||
updateFrame() {
|
updateFrame() {
|
||||||
let gl = this.gl;
|
let gl = this.gl;
|
||||||
@ -9404,7 +9458,7 @@ class WebGL2Player extends BaseCanvasPlayer {
|
|||||||
in vec4 position;void main() {gl_Position = position;}`), gl.compileShader(vShader);
|
in vec4 position;void main() {gl_Position = position;}`), gl.compileShader(vShader);
|
||||||
let fShader = gl.createShader(gl.FRAGMENT_SHADER);
|
let fShader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||||
gl.shaderSource(fShader, `#version 300 es
|
gl.shaderSource(fShader, `#version 300 es
|
||||||
precision mediump float;uniform sampler2D data;uniform vec2 iResolution;const int FILTER_UNSHARP_MASKING = 1;const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;const vec3 LUMINOSITY_FACTOR = vec3(0.299, 0.587, 0.114);uniform int filterId;uniform float sharpenFactor;uniform float brightness;uniform float contrast;uniform float saturation;out vec4 fragColor;vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {vec2 texelSize = 1.0 / iResolution.xy;vec3 a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;vec3 b = texture(tex, coord + texelSize * vec2(0, 1)).rgb;vec3 c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;vec3 d = texture(tex, coord + texelSize * vec2(-1, 0)).rgb;vec3 f = texture(tex, coord + texelSize * vec2(1, 0)).rgb;vec3 g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;vec3 h = texture(tex, coord + texelSize * vec2(0, -1)).rgb;vec3 i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;if (filterId == FILTER_UNSHARP_MASKING) {vec3 gaussianBlur = (a + c + g + i) * 1.0 + (b + d + f + h) * 2.0 + e * 4.0;gaussianBlur /= 16.0;return e + (e - gaussianBlur) * sharpenFactor / 3.0;}vec3 minRgb = min(min(min(d, e), min(f, b)), h);minRgb += min(min(a, c), min(g, i));vec3 maxRgb = max(max(max(d, e), max(f, b)), h);maxRgb += max(max(a, c), max(g, i));vec3 reciprocalMaxRgb = 1.0 / maxRgb;vec3 amplifyRgb = clamp(min(minRgb, 2.0 - maxRgb) * reciprocalMaxRgb, 0.0, 1.0);amplifyRgb = inversesqrt(amplifyRgb);vec3 weightRgb = -(1.0 / (amplifyRgb * CAS_CONTRAST_PEAK));vec3 reciprocalWeightRgb = 1.0 / (4.0 * weightRgb + 1.0);vec3 window = b + d + f + h;vec3 outColor = clamp((window * weightRgb + e) * reciprocalWeightRgb, 0.0, 1.0);return mix(e, outColor, sharpenFactor / 2.0);}void main() {vec2 uv = gl_FragCoord.xy / iResolution.xy;vec3 color = texture(data, uv).rgb;color = sharpenFactor > 0.0 ? clarityBoost(data, uv, color) : color;color = saturation != 1.0 ? mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation) : color;color = contrast * (color - 0.5) + 0.5;color = brightness * color;fragColor = vec4(color, 1.0);}`), gl.compileShader(fShader);
|
precision mediump float;uniform sampler2D data;uniform vec2 iResolution;const int FILTER_UNSHARP_MASKING = 1;const int FILTER_CAS = 2;const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;const vec3 LUMINOSITY_FACTOR = vec3(0.299, 0.587, 0.114);uniform int filterId;uniform bool qualityMode;uniform float sharpenFactor;uniform float brightness;uniform float contrast;uniform float saturation;out vec4 fragColor;vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {vec2 texelSize = 1.0 / iResolution.xy;vec3 b = texture(tex, coord + texelSize * vec2(0, 1)).rgb;vec3 d = texture(tex, coord + texelSize * vec2(-1, 0)).rgb;vec3 f = texture(tex, coord + texelSize * vec2(1, 0)).rgb;vec3 h = texture(tex, coord + texelSize * vec2(0, -1)).rgb;vec3 a;vec3 c;vec3 g;vec3 i;if (filterId == FILTER_UNSHARP_MASKING || qualityMode) {a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;}if (filterId == FILTER_UNSHARP_MASKING) {vec3 gaussianBlur = (a + c + g + i) * 1.0 + (b + d + f + h) * 2.0 + e * 4.0;gaussianBlur /= 16.0;return e + (e - gaussianBlur) * sharpenFactor / 3.0;}vec3 minRgb = min(min(min(d, e), min(f, b)), h);vec3 maxRgb = max(max(max(d, e), max(f, b)), h);if (qualityMode) {minRgb += min(min(a, c), min(g, i));maxRgb += max(max(a, c), max(g, i));}vec3 reciprocalMaxRgb = 1.0 / maxRgb;vec3 amplifyRgb = clamp(min(minRgb, 2.0 - maxRgb) * reciprocalMaxRgb, 0.0, 1.0);amplifyRgb = inversesqrt(amplifyRgb);vec3 weightRgb = -(1.0 / (amplifyRgb * CAS_CONTRAST_PEAK));vec3 reciprocalWeightRgb = 1.0 / (4.0 * weightRgb + 1.0);vec3 window = b + d + f + h;vec3 outColor = clamp((window * weightRgb + e) * reciprocalWeightRgb, 0.0, 1.0);return mix(e, outColor, sharpenFactor / 2.0);}void main() {vec2 uv = gl_FragCoord.xy / iResolution.xy;vec3 color = texture(data, uv).rgb;if (sharpenFactor > 0.0) {color = clarityBoost(data, uv, color);}color = mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation);color = contrast * (color - 0.5) + 0.5;color = brightness * color;fragColor = vec4(color, 1.0);}`), gl.compileShader(fShader);
|
||||||
let program = gl.createProgram();
|
let program = gl.createProgram();
|
||||||
if (this.program = program, gl.attachShader(program, vShader), gl.attachShader(program, fShader), gl.linkProgram(program), gl.useProgram(program), !gl.getProgramParameter(program, gl.LINK_STATUS)) console.error(`Link failed: ${gl.getProgramInfoLog(program)}`), console.error(`vs info-log: ${gl.getShaderInfoLog(vShader)}`), console.error(`fs info-log: ${gl.getShaderInfoLog(fShader)}`);
|
if (this.program = program, gl.attachShader(program, vShader), gl.attachShader(program, fShader), gl.linkProgram(program), gl.useProgram(program), !gl.getProgramParameter(program, gl.LINK_STATUS)) console.error(`Link failed: ${gl.getProgramInfoLog(program)}`), console.error(`vs info-log: ${gl.getShaderInfoLog(vShader)}`), console.error(`fs info-log: ${gl.getShaderInfoLog(fShader)}`);
|
||||||
this.updateCanvas();
|
this.updateCanvas();
|
||||||
@ -9567,6 +9621,7 @@ function patchVideoApi() {
|
|||||||
if (this.style.visibility = "visible", !this.videoWidth) return;
|
if (this.style.visibility = "visible", !this.videoWidth) return;
|
||||||
let playerOptions = {
|
let playerOptions = {
|
||||||
processing: getStreamPref("video.processing"),
|
processing: getStreamPref("video.processing"),
|
||||||
|
processingMode: getStreamPref("video.processing.mode"),
|
||||||
sharpness: getStreamPref("video.processing.sharpness"),
|
sharpness: getStreamPref("video.processing.sharpness"),
|
||||||
saturation: getStreamPref("video.saturation"),
|
saturation: getStreamPref("video.saturation"),
|
||||||
contrast: getStreamPref("video.contrast"),
|
contrast: getStreamPref("video.contrast"),
|
||||||
|
46
dist/better-xcloud.user.js
vendored
46
dist/better-xcloud.user.js
vendored
File diff suppressed because one or more lines are too long
@ -10,11 +10,11 @@
|
|||||||
"build": "build.ts"
|
"build": "build.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.2.10",
|
"@types/bun": "^1.2.15",
|
||||||
"@types/node": "^22.14.1",
|
"@types/node": "^22.15.24",
|
||||||
"@types/stylus": "^0.48.43",
|
"@types/stylus": "^0.48.43",
|
||||||
"@webgpu/types": "^0.1.60",
|
"@webgpu/types": "^0.1.61",
|
||||||
"eslint": "^9.25.0",
|
"eslint": "^9.27.0",
|
||||||
"eslint-plugin-compat": "^6.0.2",
|
"eslint-plugin-compat": "^6.0.2",
|
||||||
"stylus": "^0.64.0"
|
"stylus": "^0.64.0"
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { BaseSettingsStorage } from "@/utils/settings-storages/base-settings-storage";
|
import type { BaseSettingsStorage } from "@/utils/settings-storages/base-settings-storage";
|
||||||
import type { BlockFeature, CodecProfile, DeviceVibrationMode, GameBarPosition, LoadingScreenRocket, NativeMkbMode, StreamPlayerType, StreamResolution, StreamStat, StreamStatPosition, StreamVideoProcessing, TouchControllerMode, TouchControllerStyleCustom, TouchControllerStyleStandard, UiLayout, UiSection, UiTheme, VideoPosition, VideoPowerPreference, VideoRatio } from "./pref-values"
|
import type { BlockFeature, CodecProfile, DeviceVibrationMode, GameBarPosition, LoadingScreenRocket, NativeMkbMode, StreamPlayerType, StreamResolution, StreamStat, StreamStatPosition, StreamVideoProcessing, StreamVideoProcessingMode, TouchControllerMode, TouchControllerStyleCustom, TouchControllerStyleStandard, UiLayout, UiSection, UiTheme, VideoPosition, VideoPowerPreference, VideoRatio } from "./pref-values"
|
||||||
|
|
||||||
export const enum StorageKey {
|
export const enum StorageKey {
|
||||||
GLOBAL = 'BetterXcloud',
|
GLOBAL = 'BetterXcloud',
|
||||||
@ -156,6 +156,7 @@ export const enum StreamPref {
|
|||||||
VIDEO_PLAYER_TYPE = 'video.player.type',
|
VIDEO_PLAYER_TYPE = 'video.player.type',
|
||||||
VIDEO_POWER_PREFERENCE = 'video.player.powerPreference',
|
VIDEO_POWER_PREFERENCE = 'video.player.powerPreference',
|
||||||
VIDEO_PROCESSING = 'video.processing',
|
VIDEO_PROCESSING = 'video.processing',
|
||||||
|
VIDEO_PROCESSING_MODE = 'video.processing.mode',
|
||||||
VIDEO_SHARPNESS = 'video.processing.sharpness',
|
VIDEO_SHARPNESS = 'video.processing.sharpness',
|
||||||
VIDEO_MAX_FPS = 'video.maxFps',
|
VIDEO_MAX_FPS = 'video.maxFps',
|
||||||
VIDEO_RATIO = 'video.ratio',
|
VIDEO_RATIO = 'video.ratio',
|
||||||
@ -205,6 +206,7 @@ export type StreamPrefTypeMap = {
|
|||||||
[StreamPref.VIDEO_POSITION]: VideoPosition;
|
[StreamPref.VIDEO_POSITION]: VideoPosition;
|
||||||
[StreamPref.VIDEO_POWER_PREFERENCE]: VideoPowerPreference;
|
[StreamPref.VIDEO_POWER_PREFERENCE]: VideoPowerPreference;
|
||||||
[StreamPref.VIDEO_PROCESSING]: StreamVideoProcessing;
|
[StreamPref.VIDEO_PROCESSING]: StreamVideoProcessing;
|
||||||
|
[StreamPref.VIDEO_PROCESSING_MODE]: StreamVideoProcessingMode;
|
||||||
[StreamPref.VIDEO_RATIO]: VideoRatio;
|
[StreamPref.VIDEO_RATIO]: VideoRatio;
|
||||||
[StreamPref.VIDEO_SATURATION]: number;
|
[StreamPref.VIDEO_SATURATION]: number;
|
||||||
[StreamPref.VIDEO_SHARPNESS]: number;
|
[StreamPref.VIDEO_SHARPNESS]: number;
|
||||||
@ -294,6 +296,7 @@ export const ALL_PREFS: {
|
|||||||
StreamPref.VIDEO_POSITION,
|
StreamPref.VIDEO_POSITION,
|
||||||
StreamPref.VIDEO_POWER_PREFERENCE,
|
StreamPref.VIDEO_POWER_PREFERENCE,
|
||||||
StreamPref.VIDEO_PROCESSING,
|
StreamPref.VIDEO_PROCESSING,
|
||||||
|
StreamPref.VIDEO_PROCESSING_MODE,
|
||||||
StreamPref.VIDEO_RATIO,
|
StreamPref.VIDEO_RATIO,
|
||||||
StreamPref.VIDEO_SATURATION,
|
StreamPref.VIDEO_SATURATION,
|
||||||
StreamPref.VIDEO_SHARPNESS,
|
StreamPref.VIDEO_SHARPNESS,
|
||||||
|
@ -130,6 +130,11 @@ export const enum StreamVideoProcessing {
|
|||||||
CAS = 'cas',
|
CAS = 'cas',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const enum StreamVideoProcessingMode {
|
||||||
|
QUALITY = 'quality',
|
||||||
|
PERFORMANCE = 'performance',
|
||||||
|
}
|
||||||
|
|
||||||
export const enum BlockFeature {
|
export const enum BlockFeature {
|
||||||
CHAT = 'chat',
|
CHAT = 'chat',
|
||||||
FRIENDS = 'friends',
|
FRIENDS = 'friends',
|
||||||
|
@ -104,10 +104,47 @@ export class PatcherUtils {
|
|||||||
return str.substring(start, end);
|
return str.substring(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static injectUseEffect<T extends 'Stream' | 'Script'>(str: string, index: number, group: T, eventName: T extends 'Stream' ? keyof StreamEvents : keyof ScriptEvents) {
|
static injectUseEffect<T extends 'Stream' | 'Script'>(str: string, index: number, group: T, eventName: T extends 'Stream' ? keyof StreamEvents : keyof ScriptEvents, separator: string = ';') {
|
||||||
const newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.${group}.emit('${eventName}', {}), []);`;
|
const newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.${group}.emit('${eventName}', {}), [])${separator}`;
|
||||||
str = PatcherUtils.insertAt(str, index, newCode);
|
str = PatcherUtils.insertAt(str, index, newCode);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static findAndParseParams(str: string, index: number, maxRange: number) {
|
||||||
|
const substr = str.substring(index, index + maxRange);
|
||||||
|
let startIndex = substr.indexOf('({');
|
||||||
|
if (startIndex < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
startIndex += 1;
|
||||||
|
|
||||||
|
let endIndex = substr.indexOf('})', startIndex);
|
||||||
|
if (endIndex < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
endIndex += 1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const input = substr.substring(startIndex, endIndex);
|
||||||
|
return PatcherUtils.parseObjectVariables(input);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static parseObjectVariables(input: string) {
|
||||||
|
try {
|
||||||
|
const pairs = [...input.matchAll(/(\w+)\s*:\s*([a-zA-Z_$][\w$]*)/g)];
|
||||||
|
|
||||||
|
const result: Record<string, string> = {};
|
||||||
|
for (const [_, key, value] of pairs) {
|
||||||
|
result[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ const PATCHES = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
patchPollGamepads(str: string) {
|
patchPollGamepads(str: string) {
|
||||||
const index = str.indexOf('},this.pollGamepads=()=>{');
|
const index = str.indexOf('()(this,"pollGamepads",');
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -237,8 +237,12 @@ logFunc(logTag, '//', logMessage);
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const constIndex = str.indexOf('const', index - 30);
|
const constIndex = PatcherUtils.lastIndexOf(str, 'const[', index, 100);
|
||||||
str = str.substring(0, constIndex) + 'e.onClose();return null;' + str.substring(constIndex);
|
if (constIndex < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = PatcherUtils.insertAt(str, constIndex, 'e();return null;');
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -389,20 +393,40 @@ if (titleInfo && !titleInfo.details.hasTouchSupport && !titleInfo.details.hasFak
|
|||||||
},
|
},
|
||||||
|
|
||||||
patchStreamHud(str: string) {
|
patchStreamHud(str: string) {
|
||||||
let index = str.indexOf('let{onCollapse');
|
let index = str.indexOf('({onCollapse:');
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let newCode = codeStreamHud;
|
try {
|
||||||
|
const params = PatcherUtils.findAndParseParams(str, index, 1000);
|
||||||
|
if (!params) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the TAK Edit button when the touch controller is disabled
|
const canShowTakHUDVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, 'canShowTakHUD', index, 500, true) + 1);
|
||||||
if (getGlobalPref(GlobalPref.TOUCH_CONTROLLER_MODE) === TouchControllerMode.OFF) {
|
const guideUIVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, 'guideUI', index, 500, true) + 1);
|
||||||
newCode += 'options.canShowTakHUD = false;';
|
const onShowStreamMenuVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, 'onShowStreamMenu', index, 500, true) + 1);
|
||||||
|
const offsetVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, 'offset', index, 500, true) + 1);
|
||||||
|
|
||||||
|
let newCode = renderString(codeStreamHud, {
|
||||||
|
guideUI: guideUIVar,
|
||||||
|
onShowStreamMenu: onShowStreamMenuVar,
|
||||||
|
offset: offsetVar,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove the TAK Edit button when the touch controller is disabled
|
||||||
|
if (getGlobalPref(GlobalPref.TOUCH_CONTROLLER_MODE) === TouchControllerMode.OFF) {
|
||||||
|
newCode += `${canShowTakHUDVar} = false;`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bracketIndex = PatcherUtils.indexOf(str, '}){', index, 500, true);
|
||||||
|
str = PatcherUtils.insertAt(str, bracketIndex, newCode);
|
||||||
|
return str;
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = PatcherUtils.insertAt(str, index, newCode);
|
|
||||||
return str;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
broadcastPollingMode(str: string) {
|
broadcastPollingMode(str: string) {
|
||||||
@ -568,12 +592,13 @@ true` + text;
|
|||||||
},
|
},
|
||||||
|
|
||||||
skipFeedbackDialog(str: string) {
|
skipFeedbackDialog(str: string) {
|
||||||
let text = 'shouldTransitionToFeedback(e){';
|
let index = str.indexOf('}shouldTransitionToFeedback(');
|
||||||
if (!str.includes(text)) {
|
index >= 0 && (index = PatcherUtils.indexOf(str, '}){', index, 200, true));
|
||||||
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = str.replace(text, text + 'return !1;');
|
str = PatcherUtils.insertAt(str, index, 'return !1;');
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -607,13 +632,12 @@ true` + text;
|
|||||||
},
|
},
|
||||||
|
|
||||||
exposeInputChannel(str: string) {
|
exposeInputChannel(str: string) {
|
||||||
let index = str.indexOf('this.flushData=');
|
let text = '()(this,"flushData",(';
|
||||||
if (index < 0) {
|
if (!str.includes(text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCode = 'window.BX_EXPOSED.inputChannel = this,';
|
str = str.replace(text, '()(window.BX_EXPOSED.inputChannel = this, "flushData", (');
|
||||||
str = PatcherUtils.insertAt(str, index, newCode);
|
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -664,9 +688,9 @@ true` + text;
|
|||||||
|
|
||||||
// Replace *qe*'s return value
|
// Replace *qe*'s return value
|
||||||
// `return a && r ?` => `return a && r || true ?`
|
// `return a && r ?` => `return a && r || true ?`
|
||||||
index = str.indexOf(`const ${funcName}=e=>{`);
|
index = str.indexOf(`const ${funcName}=({children`);
|
||||||
index > -1 && (index = str.indexOf('return ', index));
|
index > -1 && (index = PatcherUtils.indexOf(str, 'return ', 300));
|
||||||
index > -1 && (index = str.indexOf('?', index));
|
index > -1 && (index = PatcherUtils.indexOf(str, '?', 100));
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -678,7 +702,7 @@ true` + text;
|
|||||||
|
|
||||||
// Don't render News section
|
// Don't render News section
|
||||||
ignoreNewsSection(str: string) {
|
ignoreNewsSection(str: string) {
|
||||||
let index = str.indexOf('Logger("CarouselRow")');
|
let index = str.indexOf('("CarouselRow"))');
|
||||||
index > -1 && (index = PatcherUtils.lastIndexOf(str, 'const ', index, 200));
|
index > -1 && (index = PatcherUtils.lastIndexOf(str, 'const ', index, 200));
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -695,12 +719,12 @@ true` + text;
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = PatcherUtils.lastIndexOf(str, 'return', index, 50);
|
index = PatcherUtils.lastIndexOf(str, '=>', index, 50);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = PatcherUtils.replaceWith(str, index, 'return', 'return null;');
|
str = PatcherUtils.replaceWith(str, index, '=>', '=> true ? null :');
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -748,12 +772,13 @@ true` + text;
|
|||||||
// home-page.js
|
// home-page.js
|
||||||
ignoreSiglSections(str: string) {
|
ignoreSiglSections(str: string) {
|
||||||
let index = str.indexOf('SiglRow-module__heroCard___');
|
let index = str.indexOf('SiglRow-module__heroCard___');
|
||||||
|
index >= 0 && (index = PatcherUtils.lastIndexOf(str, 'const[', index, 300));
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = PatcherUtils.lastIndexOf(str, 'const[', index, 300);
|
const params = PatcherUtils.findAndParseParams(str, index - 500, 500);
|
||||||
if (index < 0) {
|
if (!params || !params.id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,16 +797,9 @@ true` + text;
|
|||||||
galleryId && siglIds.push(galleryId);
|
galleryId && siglIds.push(galleryId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkSyntax = siglIds.map(item => `siglId === "${item}"`).join(' || ');
|
const checkSyntax = siglIds.map(item => `${params.id} === "${item}"`).join(' || ');
|
||||||
|
const newCode = `if (${params.id} && (${checkSyntax})) return null;`;
|
||||||
|
|
||||||
const newCode = `
|
|
||||||
if (e && e.id) {
|
|
||||||
const siglId = e.id;
|
|
||||||
if (${checkSyntax}) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
str = PatcherUtils.insertAt(str, index, newCode);
|
str = PatcherUtils.insertAt(str, index, newCode);
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
@ -891,8 +909,8 @@ if (this.baseStorageKey in window.BX_EXPOSED.overrideSettings) {
|
|||||||
|
|
||||||
// Disable long touch activating context menu
|
// Disable long touch activating context menu
|
||||||
disableTouchContextMenu(str: string) {
|
disableTouchContextMenu(str: string) {
|
||||||
let index = str.indexOf('arguments.length>2&&void 0!==arguments[2]?arguments[2]:500;');
|
let index = str.indexOf('.addEventListener("touchstart",');
|
||||||
index >= 0 && (index = str.indexOf('addEventListener("touchstart"', index));
|
index >= 0 && (index = PatcherUtils.indexOf(str, '.addEventListener("touchend"', index, 200));
|
||||||
index >= 0 && (index = PatcherUtils.lastIndexOf(str, 'return ', index, 50));
|
index >= 0 && (index = PatcherUtils.lastIndexOf(str, 'return ', index, 50));
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -1006,22 +1024,26 @@ ${subsVar} = subs;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find function's parameter
|
// Find function's parameter
|
||||||
const arrowIndex = PatcherUtils.lastIndexOf(str, '=>{', initialIndex, 300);
|
const productIdIndex = PatcherUtils.lastIndexOf(str, ',productId:', initialIndex, 300);
|
||||||
if (arrowIndex < 0) {
|
if (productIdIndex < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const paramVar = PatcherUtils.getVariableNameBefore(str, arrowIndex);
|
const params = PatcherUtils.findAndParseParams(str, productIdIndex - 200, 400);
|
||||||
|
if (!params || !params.productId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const productIdVar = params.productId;
|
||||||
|
|
||||||
// Find supportedInputIcons and title var names
|
// Find supportedInputIcons and title var names
|
||||||
const supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, 'supportedInputIcons:', initialIndex, 100, true));
|
const supportedInputIconsVar = PatcherUtils.getVariableNameAfter(str, PatcherUtils.indexOf(str, 'supportedInputIcons:', initialIndex, 100, true));
|
||||||
|
if (!supportedInputIconsVar) {
|
||||||
if (!paramVar || !supportedInputIconsVar) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCode = renderString(codeGameCardIcons, {
|
const newCode = renderString(codeGameCardIcons, {
|
||||||
param: paramVar,
|
productId: productIdVar,
|
||||||
supportedInputIcons: supportedInputIconsVar,
|
supportedInputIcons: supportedInputIconsVar,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1102,12 +1124,15 @@ ${subsVar} = subs;
|
|||||||
|
|
||||||
injectErrorPageUseEffect(str: string) {
|
injectErrorPageUseEffect(str: string) {
|
||||||
let index = str.indexOf('"PureErrorPage-module__container');
|
let index = str.indexOf('"PureErrorPage-module__container');
|
||||||
index > -1 && (index = PatcherUtils.lastIndexOf(str, 'return', index, 200));
|
index > -1 && (index = PatcherUtils.lastIndexOf(str, '})=>(0,', index, 200));
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PatcherUtils.injectUseEffect(str, index, 'Script', 'ui.error.rendered');
|
str = PatcherUtils.insertAt(str, index + 4, '{return ');
|
||||||
|
str = PatcherUtils.injectUseEffect(str, index + 5, 'Script', 'ui.error.rendered');
|
||||||
|
str += '}';
|
||||||
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
injectStreamMenuUseEffect(str: string) {
|
injectStreamMenuUseEffect(str: string) {
|
||||||
@ -1565,26 +1590,25 @@ export class PatcherCache {
|
|||||||
/**
|
/**
|
||||||
* Get patch's signature
|
* Get patch's signature
|
||||||
*/
|
*/
|
||||||
private getSignature(): number {
|
private getSignature(): string {
|
||||||
const scriptVersion = SCRIPT_VERSION;
|
const scriptVersion = SCRIPT_VERSION;
|
||||||
const patches = JSON.stringify(ALL_PATCHES);
|
const patches = JSON.stringify(ALL_PATCHES);
|
||||||
|
|
||||||
// Get client.js's hash
|
// Get client.js's hash
|
||||||
let webVersion = '';
|
let clientHash = '';
|
||||||
const $link = document.querySelector<HTMLLinkElement>('link[data-chunk="client"][as="script"][href*="/client."]');
|
const $link = document.querySelector<HTMLLinkElement>('link[data-chunk="client"][as="script"][href*="/client."]');
|
||||||
if ($link) {
|
if ($link) {
|
||||||
const match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
const match = /\/client\.([^\.]+)\.js/.exec($link.href);
|
||||||
match && (webVersion = match[1]);
|
match && (clientHash = match[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!webVersion) {
|
// Get version from <meta>
|
||||||
// Get version from <meta>
|
// Sometimes this value is missing
|
||||||
// Sometimes this value is missing
|
const webVersion = (document.querySelector<HTMLMetaElement>('meta[name=gamepass-app-version]'))?.content ?? '';
|
||||||
webVersion = (document.querySelector<HTMLMetaElement>('meta[name=gamepass-app-version]'))?.content ?? '';
|
const webVersionDate = (document.querySelector<HTMLMetaElement>('meta[name=gamepass-app-date]'))?.content ?? '';
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate signature
|
// Calculate signature
|
||||||
const sig = hashCode(scriptVersion + webVersion + patches)
|
const sig = `${scriptVersion}:${clientHash}:${webVersion}:${webVersionDate}:${hashCode(patches)}`;
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1598,7 +1622,7 @@ export class PatcherCache {
|
|||||||
const storedSig = window.localStorage.getItem(this.KEY_SIGNATURE) || 0;
|
const storedSig = window.localStorage.getItem(this.KEY_SIGNATURE) || 0;
|
||||||
const currentSig = this.getSignature();
|
const currentSig = this.getSignature();
|
||||||
|
|
||||||
if (currentSig !== parseInt(storedSig as string)) {
|
if (currentSig !== storedSig) {
|
||||||
// Save new signature
|
// Save new signature
|
||||||
BxLogger.warning(LOG_TAG, 'Signature changed');
|
BxLogger.warning(LOG_TAG, 'Signature changed');
|
||||||
window.localStorage.setItem(this.KEY_SIGNATURE, currentSig.toString());
|
window.localStorage.setItem(this.KEY_SIGNATURE, currentSig.toString());
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
declare const $supportedInputIcons$: Array<any>;
|
declare const $supportedInputIcons$: Array<any>;
|
||||||
declare const $param$: { productId: string };
|
declare const $productId$: string;
|
||||||
|
|
||||||
const supportedInputIcons = $supportedInputIcons$;
|
const supportedInputIcons = $supportedInputIcons$;
|
||||||
const { productId } = $param$;
|
const productId = $productId$;
|
||||||
|
|
||||||
// Remove controller icon
|
// Remove controller icon
|
||||||
supportedInputIcons.shift();
|
supportedInputIcons.shift();
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
declare const arguments: any;
|
declare let $guideUI$: any;
|
||||||
|
declare const $onShowStreamMenu$: any;
|
||||||
const options = arguments[0];
|
declare const $offset$: any;
|
||||||
|
|
||||||
// Expose onShowStreamMenu
|
// Expose onShowStreamMenu
|
||||||
window.BX_EXPOSED.showStreamMenu = options.onShowStreamMenu;
|
window.BX_EXPOSED.showStreamMenu = $onShowStreamMenu$;
|
||||||
// Restore the "..." button
|
// Restore the "..." button
|
||||||
options.guideUI = null;
|
$guideUI$ = null;
|
||||||
|
|
||||||
window.BX_EXPOSED.reactUseEffect(() => {
|
window.BX_EXPOSED.reactUseEffect(() => {
|
||||||
window.BxEventBus.Stream.emit('ui.streamHud.rendered', { expanded: options.offset.x === 0 });
|
window.BxEventBus.Stream.emit('ui.streamHud.rendered', { expanded: $offset$.x === 0 });
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ uniform sampler2D data;
|
|||||||
uniform vec2 iResolution;
|
uniform vec2 iResolution;
|
||||||
|
|
||||||
const int FILTER_UNSHARP_MASKING = 1;
|
const int FILTER_UNSHARP_MASKING = 1;
|
||||||
// const int FILTER_CAS = 2;
|
const int FILTER_CAS = 2;
|
||||||
|
|
||||||
// constrast = 0.8
|
// constrast = 0.8
|
||||||
const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;
|
const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;
|
||||||
@ -14,6 +14,7 @@ const float CAS_CONTRAST_PEAK = 0.8 * -3.0 + 8.0;
|
|||||||
const vec3 LUMINOSITY_FACTOR = vec3(0.299, 0.587, 0.114);
|
const vec3 LUMINOSITY_FACTOR = vec3(0.299, 0.587, 0.114);
|
||||||
|
|
||||||
uniform int filterId;
|
uniform int filterId;
|
||||||
|
uniform bool qualityMode;
|
||||||
uniform float sharpenFactor;
|
uniform float sharpenFactor;
|
||||||
uniform float brightness;
|
uniform float brightness;
|
||||||
uniform float contrast;
|
uniform float contrast;
|
||||||
@ -28,16 +29,22 @@ vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {
|
|||||||
// a b c
|
// a b c
|
||||||
// d e f
|
// d e f
|
||||||
// g h i
|
// g h i
|
||||||
vec3 a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;
|
|
||||||
vec3 b = texture(tex, coord + texelSize * vec2(0, 1)).rgb;
|
vec3 b = texture(tex, coord + texelSize * vec2(0, 1)).rgb;
|
||||||
vec3 c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;
|
|
||||||
|
|
||||||
vec3 d = texture(tex, coord + texelSize * vec2(-1, 0)).rgb;
|
vec3 d = texture(tex, coord + texelSize * vec2(-1, 0)).rgb;
|
||||||
vec3 f = texture(tex, coord + texelSize * vec2(1, 0)).rgb;
|
vec3 f = texture(tex, coord + texelSize * vec2(1, 0)).rgb;
|
||||||
|
|
||||||
vec3 g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;
|
|
||||||
vec3 h = texture(tex, coord + texelSize * vec2(0, -1)).rgb;
|
vec3 h = texture(tex, coord + texelSize * vec2(0, -1)).rgb;
|
||||||
vec3 i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;
|
|
||||||
|
vec3 a;
|
||||||
|
vec3 c;
|
||||||
|
vec3 g;
|
||||||
|
vec3 i;
|
||||||
|
|
||||||
|
if (filterId == FILTER_UNSHARP_MASKING || qualityMode) {
|
||||||
|
a = texture(tex, coord + texelSize * vec2(-1, 1)).rgb;
|
||||||
|
c = texture(tex, coord + texelSize * vec2(1, 1)).rgb;
|
||||||
|
g = texture(tex, coord + texelSize * vec2(-1, -1)).rgb;
|
||||||
|
i = texture(tex, coord + texelSize * vec2(1, -1)).rgb;
|
||||||
|
}
|
||||||
|
|
||||||
// USM
|
// USM
|
||||||
if (filterId == FILTER_UNSHARP_MASKING) {
|
if (filterId == FILTER_UNSHARP_MASKING) {
|
||||||
@ -55,10 +62,12 @@ vec3 clarityBoost(sampler2D tex, vec2 coord, vec3 e) {
|
|||||||
// g h i h
|
// g h i h
|
||||||
// These are 2.0x bigger (factored out the extra multiply).
|
// These are 2.0x bigger (factored out the extra multiply).
|
||||||
vec3 minRgb = min(min(min(d, e), min(f, b)), h);
|
vec3 minRgb = min(min(min(d, e), min(f, b)), h);
|
||||||
minRgb += min(min(a, c), min(g, i));
|
|
||||||
|
|
||||||
vec3 maxRgb = max(max(max(d, e), max(f, b)), h);
|
vec3 maxRgb = max(max(max(d, e), max(f, b)), h);
|
||||||
maxRgb += max(max(a, c), max(g, i));
|
|
||||||
|
if (qualityMode) {
|
||||||
|
minRgb += min(min(a, c), min(g, i));
|
||||||
|
maxRgb += max(max(a, c), max(g, i));
|
||||||
|
}
|
||||||
|
|
||||||
// Smooth minimum distance to signal limit divided by smooth max.
|
// Smooth minimum distance to signal limit divided by smooth max.
|
||||||
vec3 reciprocalMaxRgb = 1.0 / maxRgb;
|
vec3 reciprocalMaxRgb = 1.0 / maxRgb;
|
||||||
@ -85,10 +94,12 @@ void main() {
|
|||||||
vec3 color = texture(data, uv).rgb;
|
vec3 color = texture(data, uv).rgb;
|
||||||
|
|
||||||
// Clarity boost
|
// Clarity boost
|
||||||
color = sharpenFactor > 0.0 ? clarityBoost(data, uv, color) : color;
|
if (sharpenFactor > 0.0) {
|
||||||
|
color = clarityBoost(data, uv, color);
|
||||||
|
}
|
||||||
|
|
||||||
// Saturation
|
// Saturation
|
||||||
color = saturation != 1.0 ? mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation) : color;
|
color = mix(vec3(dot(color, LUMINOSITY_FACTOR)), color, saturation);
|
||||||
|
|
||||||
// Contrast
|
// Contrast
|
||||||
color = contrast * (color - 0.5) + 0.5;
|
color = contrast * (color - 0.5) + 0.5;
|
||||||
|
@ -3,7 +3,7 @@ import { compressCodeFile } from "@macros/build" with { type: "macro" };
|
|||||||
import { StreamPref } from "@/enums/pref-keys";
|
import { StreamPref } from "@/enums/pref-keys";
|
||||||
import { getStreamPref } from "@/utils/pref-utils";
|
import { getStreamPref } from "@/utils/pref-utils";
|
||||||
import { BaseCanvasPlayer } from "../base-canvas-player";
|
import { BaseCanvasPlayer } from "../base-canvas-player";
|
||||||
import { StreamPlayerType } from "@/enums/pref-values";
|
import { StreamPlayerType, StreamVideoProcessingMode } from "@/enums/pref-values";
|
||||||
|
|
||||||
|
|
||||||
export class WebGL2Player extends BaseCanvasPlayer {
|
export class WebGL2Player extends BaseCanvasPlayer {
|
||||||
@ -25,7 +25,8 @@ export class WebGL2Player extends BaseCanvasPlayer {
|
|||||||
gl.uniform2f(gl.getUniformLocation(program, 'iResolution'), this.$canvas.width, this.$canvas.height);
|
gl.uniform2f(gl.getUniformLocation(program, 'iResolution'), this.$canvas.width, this.$canvas.height);
|
||||||
|
|
||||||
gl.uniform1i(gl.getUniformLocation(program, 'filterId'), filterId);
|
gl.uniform1i(gl.getUniformLocation(program, 'filterId'), filterId);
|
||||||
gl.uniform1f(gl.getUniformLocation(program, 'sharpenFactor'), this.options.sharpness);
|
gl.uniform1i(gl.getUniformLocation(program, 'qualityMode'), this.options.processingMode === StreamVideoProcessingMode.QUALITY ? 1 : 0);
|
||||||
|
gl.uniform1f(gl.getUniformLocation(program, 'sharpenFactor'), this.options.sharpness / (this.options.processingMode === StreamVideoProcessingMode.QUALITY ? 1 : 1.2));
|
||||||
gl.uniform1f(gl.getUniformLocation(program, 'brightness'), this.options.brightness / 100);
|
gl.uniform1f(gl.getUniformLocation(program, 'brightness'), this.options.brightness / 100);
|
||||||
gl.uniform1f(gl.getUniformLocation(program, 'contrast'), this.options.contrast / 100);
|
gl.uniform1f(gl.getUniformLocation(program, 'contrast'), this.options.contrast / 100);
|
||||||
gl.uniform1f(gl.getUniformLocation(program, 'saturation'), this.options.saturation / 100);
|
gl.uniform1f(gl.getUniformLocation(program, 'saturation'), this.options.saturation / 100);
|
||||||
|
@ -82,6 +82,10 @@ export class SettingsManager {
|
|||||||
},
|
},
|
||||||
[StreamPref.VIDEO_PROCESSING]: {
|
[StreamPref.VIDEO_PROCESSING]: {
|
||||||
onChange: updateVideoPlayer,
|
onChange: updateVideoPlayer,
|
||||||
|
onChangeUi: onChangeVideoPlayerType,
|
||||||
|
},
|
||||||
|
[StreamPref.VIDEO_PROCESSING_MODE]: {
|
||||||
|
onChange: updateVideoPlayer,
|
||||||
},
|
},
|
||||||
[StreamPref.VIDEO_SHARPNESS]: {
|
[StreamPref.VIDEO_SHARPNESS]: {
|
||||||
onChange: updateVideoPlayer,
|
onChange: updateVideoPlayer,
|
||||||
|
@ -8,6 +8,7 @@ import type { StreamPlayerOptions } from "@/types/stream";
|
|||||||
|
|
||||||
export function onChangeVideoPlayerType() {
|
export function onChangeVideoPlayerType() {
|
||||||
const playerType = getStreamPref(StreamPref.VIDEO_PLAYER_TYPE);
|
const playerType = getStreamPref(StreamPref.VIDEO_PLAYER_TYPE);
|
||||||
|
const processing = getStreamPref(StreamPref.VIDEO_PROCESSING);
|
||||||
const settingsManager = SettingsManager.getInstance();
|
const settingsManager = SettingsManager.getInstance();
|
||||||
if (!settingsManager.hasElement(StreamPref.VIDEO_PROCESSING)) {
|
if (!settingsManager.hasElement(StreamPref.VIDEO_PROCESSING)) {
|
||||||
return;
|
return;
|
||||||
@ -16,6 +17,7 @@ export function onChangeVideoPlayerType() {
|
|||||||
let isDisabled = false;
|
let isDisabled = false;
|
||||||
|
|
||||||
const $videoProcessing = settingsManager.getElement(StreamPref.VIDEO_PROCESSING) as HTMLSelectElement;
|
const $videoProcessing = settingsManager.getElement(StreamPref.VIDEO_PROCESSING) as HTMLSelectElement;
|
||||||
|
const $videoProcessingMode = settingsManager.getElement(StreamPref.VIDEO_PROCESSING_MODE) as HTMLSelectElement;
|
||||||
const $videoSharpness = settingsManager.getElement(StreamPref.VIDEO_SHARPNESS);
|
const $videoSharpness = settingsManager.getElement(StreamPref.VIDEO_SHARPNESS);
|
||||||
const $videoPowerPreference = settingsManager.getElement(StreamPref.VIDEO_POWER_PREFERENCE);
|
const $videoPowerPreference = settingsManager.getElement(StreamPref.VIDEO_POWER_PREFERENCE);
|
||||||
const $videoMaxFps = settingsManager.getElement(StreamPref.VIDEO_MAX_FPS);
|
const $videoMaxFps = settingsManager.getElement(StreamPref.VIDEO_MAX_FPS);
|
||||||
@ -40,6 +42,7 @@ export function onChangeVideoPlayerType() {
|
|||||||
$videoSharpness.dataset.disabled = isDisabled.toString();
|
$videoSharpness.dataset.disabled = isDisabled.toString();
|
||||||
|
|
||||||
// Hide Power Preference setting if renderer isn't WebGL2
|
// Hide Power Preference setting if renderer isn't WebGL2
|
||||||
|
$videoProcessingMode.closest('.bx-settings-row')!.classList.toggle('bx-gone', !(playerType === StreamPlayerType.WEBGL2 && processing === StreamVideoProcessing.CAS));
|
||||||
$videoPowerPreference.closest('.bx-settings-row')!.classList.toggle('bx-gone', playerType !== StreamPlayerType.WEBGL2);
|
$videoPowerPreference.closest('.bx-settings-row')!.classList.toggle('bx-gone', playerType !== StreamPlayerType.WEBGL2);
|
||||||
$videoMaxFps.closest('.bx-settings-row')!.classList.toggle('bx-gone', playerType === StreamPlayerType.VIDEO);
|
$videoMaxFps.closest('.bx-settings-row')!.classList.toggle('bx-gone', playerType === StreamPlayerType.VIDEO);
|
||||||
}
|
}
|
||||||
@ -59,6 +62,7 @@ export function updateVideoPlayer() {
|
|||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
processing: getStreamPref(StreamPref.VIDEO_PROCESSING),
|
processing: getStreamPref(StreamPref.VIDEO_PROCESSING),
|
||||||
|
processingMode: getStreamPref(StreamPref.VIDEO_PROCESSING_MODE),
|
||||||
sharpness: getStreamPref(StreamPref.VIDEO_SHARPNESS),
|
sharpness: getStreamPref(StreamPref.VIDEO_SHARPNESS),
|
||||||
saturation: getStreamPref(StreamPref.VIDEO_SATURATION),
|
saturation: getStreamPref(StreamPref.VIDEO_SATURATION),
|
||||||
contrast: getStreamPref(StreamPref.VIDEO_CONTRAST),
|
contrast: getStreamPref(StreamPref.VIDEO_CONTRAST),
|
||||||
|
@ -452,6 +452,7 @@ export class SettingsDialog extends NavigationDialog {
|
|||||||
StreamPref.VIDEO_MAX_FPS,
|
StreamPref.VIDEO_MAX_FPS,
|
||||||
StreamPref.VIDEO_POWER_PREFERENCE,
|
StreamPref.VIDEO_POWER_PREFERENCE,
|
||||||
StreamPref.VIDEO_PROCESSING,
|
StreamPref.VIDEO_PROCESSING,
|
||||||
|
StreamPref.VIDEO_PROCESSING_MODE,
|
||||||
StreamPref.VIDEO_RATIO,
|
StreamPref.VIDEO_RATIO,
|
||||||
StreamPref.VIDEO_POSITION,
|
StreamPref.VIDEO_POSITION,
|
||||||
StreamPref.VIDEO_SHARPNESS,
|
StreamPref.VIDEO_SHARPNESS,
|
||||||
|
3
src/types/stream.d.ts
vendored
3
src/types/stream.d.ts
vendored
@ -1,7 +1,8 @@
|
|||||||
import type { StreamVideoProcessing } from "@/enums/pref-values";
|
import type { StreamVideoProcessing, StreamVideoProcessingMode } from "@/enums/pref-values";
|
||||||
|
|
||||||
type StreamPlayerOptions = {
|
type StreamPlayerOptions = {
|
||||||
processing: StreamVideoProcessing,
|
processing: StreamVideoProcessing,
|
||||||
|
processingMode: StreamVideoProcessingMode,
|
||||||
sharpness: number,
|
sharpness: number,
|
||||||
saturation: number,
|
saturation: number,
|
||||||
contrast: number,
|
contrast: number,
|
||||||
|
@ -22,6 +22,7 @@ export function patchVideoApi() {
|
|||||||
|
|
||||||
const playerOptions = {
|
const playerOptions = {
|
||||||
processing: getStreamPref(StreamPref.VIDEO_PROCESSING),
|
processing: getStreamPref(StreamPref.VIDEO_PROCESSING),
|
||||||
|
processingMode: getStreamPref(StreamPref.VIDEO_PROCESSING_MODE),
|
||||||
sharpness: getStreamPref(StreamPref.VIDEO_SHARPNESS),
|
sharpness: getStreamPref(StreamPref.VIDEO_SHARPNESS),
|
||||||
saturation: getStreamPref(StreamPref.VIDEO_SATURATION),
|
saturation: getStreamPref(StreamPref.VIDEO_SATURATION),
|
||||||
contrast: getStreamPref(StreamPref.VIDEO_CONTRAST),
|
contrast: getStreamPref(StreamPref.VIDEO_CONTRAST),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { StreamPref, StorageKey, type PrefTypeMap } from "@/enums/pref-keys";
|
import { StreamPref, StorageKey, type PrefTypeMap } from "@/enums/pref-keys";
|
||||||
import { DeviceVibrationMode, StreamPlayerType, StreamVideoProcessing, VideoPowerPreference, VideoRatio, VideoPosition, StreamStat, StreamStatPosition } from "@/enums/pref-values";
|
import { DeviceVibrationMode, StreamPlayerType, StreamVideoProcessing, VideoPowerPreference, VideoRatio, VideoPosition, StreamStat, StreamStatPosition, StreamVideoProcessingMode } from "@/enums/pref-values";
|
||||||
import { STATES } from "../global";
|
import { STATES } from "../global";
|
||||||
import { KeyboardShortcutDefaultId } from "../local-db/keyboard-shortcuts-table";
|
import { KeyboardShortcutDefaultId } from "../local-db/keyboard-shortcuts-table";
|
||||||
import { MkbMappingDefaultPresetId } from "../local-db/mkb-mapping-presets-table";
|
import { MkbMappingDefaultPresetId } from "../local-db/mkb-mapping-presets-table";
|
||||||
@ -179,6 +179,18 @@ export class StreamSettingsStorage extends BaseSettingsStorage<StreamPref> {
|
|||||||
highest: StreamVideoProcessing.CAS,
|
highest: StreamVideoProcessing.CAS,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[StreamPref.VIDEO_PROCESSING_MODE]: {
|
||||||
|
label: t('clarity-boost-mode'),
|
||||||
|
default: StreamVideoProcessingMode.PERFORMANCE,
|
||||||
|
options: {
|
||||||
|
[StreamVideoProcessingMode.PERFORMANCE]: t('performance'),
|
||||||
|
[StreamVideoProcessingMode.QUALITY]: t('quality'),
|
||||||
|
},
|
||||||
|
suggest: {
|
||||||
|
lowest: StreamVideoProcessingMode.PERFORMANCE,
|
||||||
|
highest: StreamVideoProcessingMode.QUALITY,
|
||||||
|
},
|
||||||
|
},
|
||||||
[StreamPref.VIDEO_POWER_PREFERENCE]: {
|
[StreamPref.VIDEO_POWER_PREFERENCE]: {
|
||||||
label: t('renderer-configuration'),
|
label: t('renderer-configuration'),
|
||||||
default: VideoPowerPreference.DEFAULT,
|
default: VideoPowerPreference.DEFAULT,
|
||||||
|
@ -65,6 +65,7 @@ const Texts = {
|
|||||||
"center": "Center",
|
"center": "Center",
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"clarity-boost": "Clarity boost",
|
"clarity-boost": "Clarity boost",
|
||||||
|
"clarity-boost-mode": "Clarity boost mode",
|
||||||
"clarity-boost-warning": "These settings don't work when the Clarity Boost mode is ON",
|
"clarity-boost-warning": "These settings don't work when the Clarity Boost mode is ON",
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"clear-data": "Clear data",
|
"clear-data": "Clear data",
|
||||||
@ -227,6 +228,7 @@ const Texts = {
|
|||||||
"only-supports-some-games": "Only supports some games",
|
"only-supports-some-games": "Only supports some games",
|
||||||
"opacity": "Opacity",
|
"opacity": "Opacity",
|
||||||
"other": "Other",
|
"other": "Other",
|
||||||
|
"performance": "Performance",
|
||||||
"playing": "Playing",
|
"playing": "Playing",
|
||||||
"playtime": "Playtime",
|
"playtime": "Playtime",
|
||||||
"poland": "Poland",
|
"poland": "Poland",
|
||||||
@ -264,6 +266,7 @@ const Texts = {
|
|||||||
],
|
],
|
||||||
"press-to-bind": "Press a key or do a mouse click to bind...",
|
"press-to-bind": "Press a key or do a mouse click to bind...",
|
||||||
"prompt-preset-name": "Preset's name:",
|
"prompt-preset-name": "Preset's name:",
|
||||||
|
"quality": "Quality",
|
||||||
"recommended": "Recommended",
|
"recommended": "Recommended",
|
||||||
"recommended-settings-for-device": [
|
"recommended-settings-for-device": [
|
||||||
(e: any) => `Recommended settings for ${e.device}`,
|
(e: any) => `Recommended settings for ${e.device}`,
|
||||||
@ -319,6 +322,7 @@ const Texts = {
|
|||||||
"separate-touch-controller": "Separate Touch controller & Controller #1",
|
"separate-touch-controller": "Separate Touch controller & Controller #1",
|
||||||
"separate-touch-controller-note": "Touch controller is Player 1, Controller #1 is Player 2",
|
"separate-touch-controller-note": "Touch controller is Player 1, Controller #1 is Player 2",
|
||||||
"server": "Server",
|
"server": "Server",
|
||||||
|
"server-list-error": "Can't get the server list",
|
||||||
"server-locations": "Server locations",
|
"server-locations": "Server locations",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"settings-for": "Settings for",
|
"settings-for": "Settings for",
|
||||||
@ -368,6 +372,7 @@ const Texts = {
|
|||||||
"tc-custom-layout-style": "Custom layout's button style",
|
"tc-custom-layout-style": "Custom layout's button style",
|
||||||
"tc-muted-colors": "Muted colors",
|
"tc-muted-colors": "Muted colors",
|
||||||
"tc-standard-layout-style": "Standard layout's button style",
|
"tc-standard-layout-style": "Standard layout's button style",
|
||||||
|
"test-controller": "Test controller",
|
||||||
"text-size": "Text size",
|
"text-size": "Text size",
|
||||||
"theme": "Theme",
|
"theme": "Theme",
|
||||||
"toggle": "Toggle",
|
"toggle": "Toggle",
|
||||||
|
Reference in New Issue
Block a user