mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
Merge pull request #720 from Zagrios/bugfix/fix-oculus-launch
[bugfix] fix oculus launch by using sideloading
This commit is contained in:
@@ -854,13 +854,12 @@
|
||||
"stay": "Angemeldet bleiben",
|
||||
"connect-to-meta": "Mit Meta verbinden"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Achtung",
|
||||
"body": {
|
||||
"must-be-installed-once": "Sie müssen Beat Saber aus dem Oculus Store auf diesem Gerät installiert haben, andernfalls wird Beat Saber nach dem Start automatisch geschlossen.",
|
||||
"will-backup": "Um diese Version zu starten, wird der ursprüngliche Installationsordner von Beat Saber in deiner Oculus-Bibliothek umbenannt und beim Schließen von Beat Saber automatisch wiederhergestellt."
|
||||
},
|
||||
"not-remind-me": "Nicht mehr erinnern",
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Sideloading aktivieren",
|
||||
"info-1": "Um Beat Saber starten zu können, muss die Möglichkeit aktiviert werden, Sideloading-Apps auszuführen. BSManager wird Administratorrechte anfordern, um diese Funktion automatisch zu aktivieren.",
|
||||
"info-2": "Die Sideloading-Funktion ermöglicht das Starten von Spielen, die sich außerhalb Ihres Oculus-Bibliotheksordners befinden.",
|
||||
"info-3": "Nachdem das Sideloading aktiviert wurde, bleibt die Funktion aktiv, und Sie werden nicht mehr aufgefordert, sie zu aktivieren.",
|
||||
"i-want-to-do-it-myself": "Ich möchte es selbst machen",
|
||||
"understood": "Verstanden"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
|
||||
@@ -849,13 +849,12 @@
|
||||
"stay": "Remember me",
|
||||
"connect-to-meta": "Connect to Meta"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Warning",
|
||||
"body": {
|
||||
"must-be-installed-once": "You must have Beat Saber installed from the Oculus Store on this device, otherwise Beat Saber might automatically close after launching.",
|
||||
"will-backup": "To launch this version, the original installation folder of Beat Saber located in your Oculus library will be renamed and will be automatically restored when Beat Saber is closed."
|
||||
},
|
||||
"not-remind-me": "Do not remind me",
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Enable Sideloading",
|
||||
"info-1": "In order to launch Beat Saber, the ability to run sideloaded apps must be enabled. BSManager will request administrator rights to enable this feature automatically.",
|
||||
"info-2": "The sideloaded apps feature allows launching games located outside your Oculus library folder.",
|
||||
"info-3": "After sideloading is activated, the feature will remain active, and you will no longer be prompted to enable it.",
|
||||
"i-want-to-do-it-myself": "I want to do it myself",
|
||||
"understood": "Understood"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
|
||||
@@ -854,13 +854,12 @@
|
||||
"stay": "Recuérdame",
|
||||
"connect-to-meta": "Conectarse a Meta"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Atención",
|
||||
"body": {
|
||||
"must-be-installed-once": "Debes tener Beat Saber instalado desde la tienda de Oculus en este dispositivo, de lo contrario, Beat Saber se cerrará automáticamente después de iniciarse.",
|
||||
"will-backup": "Para lanzar esta versión, la carpeta de instalación original de Beat Saber ubicada en tu biblioteca de Oculus será renombrada y se restaurará automáticamente al cerrar Beat Saber."
|
||||
},
|
||||
"not-remind-me": "No volver a recordármelo",
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Habilitar Sideloading",
|
||||
"info-1": "Para poder iniciar Beat Saber, se debe habilitar la capacidad de ejecutar aplicaciones en sideloading. BSManager solicitará permisos de administrador para habilitar esta función automáticamente.",
|
||||
"info-2": "La función de sideloading permite iniciar juegos ubicados fuera de la carpeta de la biblioteca de Oculus.",
|
||||
"info-3": "Una vez que se active el sideloading, la función permanecerá activa y ya no se le pedirá que la habilite.",
|
||||
"i-want-to-do-it-myself": "Quiero hacerlo yo mismo",
|
||||
"understood": "Entendido"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
|
||||
@@ -855,13 +855,12 @@
|
||||
"stay": "Se souvenir de moi",
|
||||
"connect-to-meta": "Se connecter à Meta"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Attention",
|
||||
"body": {
|
||||
"must-be-installed-once": "Vous devez avoir Beat Saber installé depuis le Oculus Store sur cet appareil, sinon Beat Saber se fermera automatiquement après le lancement.",
|
||||
"will-backup": "Afin de lancer cette version, le dossier d'installation original de Beat Saber se trouvant dans votre bibliothèque Oculus va être renommé et sera automatiquement restauré à l'arrêt de Beat Saber."
|
||||
},
|
||||
"not-remind-me": "Ne plus me rappeler",
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Activer le sideloading",
|
||||
"info-1": "Pour lancer Beat Saber, la possibilité d'exécuter des applications en sideloading doit être activée. BSManager demandera les droits administrateur pour activer cette fonctionnalité automatiquement.",
|
||||
"info-2": "La fonctionnalité de sideloading permet de lancer des jeux situés en dehors de votre dossier de bibliothèque Oculus.",
|
||||
"info-3": "Une fois le sideloading activé, la fonctionnalité restera active et vous ne serez plus invité à l’activer.",
|
||||
"i-want-to-do-it-myself": "Je veux le faire moi-même",
|
||||
"understood": "J'ai compris"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
|
||||
@@ -854,14 +854,13 @@
|
||||
"stay": "記憶する",
|
||||
"connect-to-meta": "Metaに接続する"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "注意",
|
||||
"body": {
|
||||
"must-be-installed-once": "このデバイスにOculusストアからBeat Saberをインストールしておく必要があります。そうしないと、Beat Saberは起動後に自動的に閉じます。",
|
||||
"will-backup": "このバージョンを起動するために、OculusライブラリにあるBeat Saberの元のインストールフォルダは名前が変更され、Beat Saberの終了時に自動的に復元されます。"
|
||||
},
|
||||
"not-remind-me": "二度と表示しないでください",
|
||||
"understood": "分かった"
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "サイドローディングを有効化",
|
||||
"info-1": "Beat Saberを起動するには、サイドローディングアプリを実行する機能を有効にする必要があります。BSManagerは、この機能を自動的に有効にするために管理者権限を要求します。",
|
||||
"info-2": "サイドローディング機能により、Oculusライブラリフォルダ外にあるゲームを起動できます。",
|
||||
"info-3": "サイドローディングを有効化すると、この機能はアクティブなままとなり、再度有効化を求められることはありません。",
|
||||
"i-want-to-do-it-myself": "自分でやりたい",
|
||||
"understood": "了解しました"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Oculusトークン",
|
||||
|
||||
@@ -854,13 +854,12 @@
|
||||
"stay": "기억하기",
|
||||
"connect-to-meta": "Meta에 연결하기"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "주의",
|
||||
"body": {
|
||||
"must-be-installed-once": "이 장치에 Oculus 스토어에서 Beat Saber를 설치해야 합니다. 그렇지 않으면 Beat Saber가 실행 후 자동으로 종료됩니다..",
|
||||
"will-backup": "이 버전을 실행하기 위해 Oculus 라이브러리에 있는 Beat Saber의 원래 설치 폴더의 이름이 변경되며, Beat Saber가 종료되면 자동으로 복원됩니다."
|
||||
},
|
||||
"not-remind-me": "다시 표시하지 않기",
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "사이드로딩 활성화",
|
||||
"info-1": "Beat Saber를 실행하려면 사이드로딩 앱을 실행할 수 있는 기능을 활성화해야 합니다. BSManager는 이 기능을 자동으로 활성화하기 위해 관리자 권한을 요청할 것입니다.",
|
||||
"info-2": "사이드로딩 기능을 사용하면 Oculus 라이브러리 폴더 외부에 있는 게임을 실행할 수 있습니다.",
|
||||
"info-3": "사이드로딩(sideloading)이 활성화되면 이 기능은 계속 활성 상태를 유지하며, 더 이상 활성화를 요청받지 않습니다.",
|
||||
"i-want-to-do-it-myself": "스스로 하고 싶습니다",
|
||||
"understood": "알겠습니다"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
|
||||
@@ -854,14 +854,13 @@
|
||||
"stay": "Запомнить меня",
|
||||
"connect-to-meta": "Подключиться к Meta"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "Внимание",
|
||||
"body": {
|
||||
"must-be-installed-once": "Вы должны установить Beat Saber из магазина Oculus на этом устройстве, в противном случае Beat Saber автоматически закроется после запуска.",
|
||||
"will-backup": "Для запуска этой версии исходная папка установки Beat Saber, находящаяся в вашей библиотеке Oculus, будет переименована и автоматически восстановлена при выходе из Beat Saber."
|
||||
},
|
||||
"not-remind-me": "Больше не напоминать",
|
||||
"understood": "Понял"
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "Включить Sideloading",
|
||||
"info-1": "Чтобы запустить Beat Saber, необходимо включить возможность запуска приложений через sideloading. BSManager запросит права администратора для автоматического включения этой функции.",
|
||||
"info-2": "Функция sideloading позволяет запускать игры, расположенные за пределами папки библиотеки Oculus.",
|
||||
"info-3": "После активации сайдлоадинга функция останется активной, и вам больше не будет предложено её включить.",
|
||||
"i-want-to-do-it-myself": "Я хочу сделать это сам",
|
||||
"understood": "Понято"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Токен Oculus",
|
||||
|
||||
@@ -854,14 +854,13 @@
|
||||
"stay": "記住我",
|
||||
"connect-to-meta": "連接到 Meta"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "警告",
|
||||
"body": {
|
||||
"must-be-installed-once": "您必須在此設備上從Oculus商店安裝Beat Saber,否則Beat Saber將在啟動後自動關閉。",
|
||||
"will-backup": "為了啟動這個版本,位於您的Oculus庫中的Beat Saber的原始安裝文件夾將被重新命名,並且在Beat Saber關閉時會自動恢復。"
|
||||
},
|
||||
"not-remind-me": "不再提醒我",
|
||||
"understood": "明白了"
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "啟用旁載",
|
||||
"info-1": "為了啟動 Beat Saber,必須啟用執行旁載應用程式的功能。BSManager 將請求管理員權限以自動啟用此功能。",
|
||||
"info-2": "旁載功能允許啟動位於 Oculus 資料庫資料夾之外的遊戲。",
|
||||
"info-3": "啟用 sideloading 後,此功能將保持啟用狀態,您將不再被提示啟用它。",
|
||||
"i-want-to-do-it-myself": "我想自己完成",
|
||||
"understood": "了解"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
"title": "Oculus令牌",
|
||||
|
||||
@@ -854,13 +854,12 @@
|
||||
"stay": "记住我",
|
||||
"connect-to-meta": "连接到 Meta"
|
||||
},
|
||||
"original-version-backup-oculus": {
|
||||
"title": "警告",
|
||||
"body": {
|
||||
"must-be-installed-once": "您必须在此设备上从Oculus商店安装Beat Saber,否则Beat Saber将在启动后自动关闭。",
|
||||
"will-backup": "为了启动这个版本,位于您的Oculus库中的Beat Saber的原始安装文件夹将被重命名,并且在Beat Saber关闭时会自动恢复。"
|
||||
},
|
||||
"not-remind-me": "不再提醒我",
|
||||
"enable-oculus-sideloaded-apps": {
|
||||
"title": "启用旁加载",
|
||||
"info-1": "为了启动 Beat Saber,必须启用运行旁加载应用程序的功能。BSManager 将请求管理员权限以自动启用此功能。",
|
||||
"info-2": "旁加载功能允许启动位于 Oculus 库文件夹之外的游戏。",
|
||||
"info-3": "激活 sideloading 后,该功能将保持激活状态,您将不再被提示启用它。",
|
||||
"i-want-to-do-it-myself": "我想自己完成",
|
||||
"understood": "明白了"
|
||||
},
|
||||
"enter-meta-token": {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -0,0 +1,11 @@
|
||||
Enabling Oculus sideloading allows games located outside if your Oculus library to be played on your Oculus Quest.
|
||||
|
||||
- **Step 1:** Start the regedit application by pressing `Win + R` and typing `regedit` in the dialog box.
|
||||
- **Step 2:** Navigate to `HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Oculus VR, LLC\Oculus`.
|
||||
- **Step 3:** Right-click on the right panel and select `New > DWORD (32-bit) Value`.
|
||||
- **Step 4:** Name the new value `AllowDevSideloaded` and set the value to `1`.
|
||||
|
||||
You should end up with something like this:
|
||||

|
||||
|
||||
After completing these steps, you should be able to start Beat Saber from BSManager and play it on your Oculus Quest. If you are still having issues, please join our [Discord](https://discord.gg/uSqbHVpKdV) server for further assistance.
|
||||
@@ -0,0 +1,2 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "oculus-allow-dev-sideloaded"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"winreg",
|
||||
"winres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winres"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
|
||||
dependencies = [
|
||||
"toml",
|
||||
]
|
||||
Vendored
+7
-9
@@ -1,22 +1,20 @@
|
||||
[package]
|
||||
name = "oculus_symlink_cleaner"
|
||||
name = "oculus-allow-dev-sideloaded"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
winres = "0.1.12"
|
||||
|
||||
[dependencies]
|
||||
sysinfo = "0.30.6"
|
||||
winreg = "0.52.0"
|
||||
|
||||
[package.metadata.winres]
|
||||
FileDescription = "Enable Sideloaded Apps"
|
||||
LegalCopyright = "Copyright © 2024 Zagrios"
|
||||
CompanyName = "Zagrios"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
|
||||
[package.metadata.winres]
|
||||
FileDescription = "Clean Oculus Symlink after Beat Saber ends"
|
||||
LegalCopyright = "Copyright © 2024 Zagrios"
|
||||
CompanyName = "Zagrios"
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
extern crate winres;
|
||||
|
||||
fn main() {
|
||||
if cfg!(target_os = "windows") {
|
||||
let mut res = winres::WindowsResource::new();
|
||||
res.set_manifest(r#"
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
"#);
|
||||
res.set_icon("./icon.ico");
|
||||
res.compile().unwrap();
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
@@ -0,0 +1,22 @@
|
||||
use winreg::enums::HKEY_LOCAL_MACHINE;
|
||||
use winreg::RegKey;
|
||||
|
||||
const PATH: &str = "SOFTWARE\\Wow6432Node\\Oculus VR, LLC\\Oculus";
|
||||
|
||||
fn main() {
|
||||
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
|
||||
|
||||
// Create (or open if it already exists) the subkey
|
||||
let (key, _) = match hklm.create_subkey(PATH) {
|
||||
Ok(res) => res,
|
||||
Err(err) => return println!("{}", err.to_string()),
|
||||
};
|
||||
|
||||
let res = key.set_value("AllowDevSideloaded", &1u32);
|
||||
|
||||
if let Err(err) = res {
|
||||
return println!("{}", err.to_string());
|
||||
}
|
||||
|
||||
println!("AllowDevSideloaded = 1 has been successfully set in {PATH}");
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
-281
@@ -1,281 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oculus_symlink_cleaner"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sysinfo",
|
||||
"winres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.30.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6746919caf9f2a85bff759535664c060109f21975c5ac2e8652e60102bd4d196"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"ntapi",
|
||||
"once_cell",
|
||||
"rayon",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
|
||||
[[package]]
|
||||
name = "winres"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
|
||||
dependencies = [
|
||||
"toml",
|
||||
]
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
extern crate winres;
|
||||
|
||||
fn main() {
|
||||
if cfg!(target_os = "windows") {
|
||||
let mut res = winres::WindowsResource::new();
|
||||
res.set_icon("./icon.ico");
|
||||
res.compile().unwrap();
|
||||
}
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
use sysinfo::{Pid, ProcessRefreshKind, System};
|
||||
use std::{env, thread, time::Duration, fs};
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
const BEAT_SABER_OCULUS_FOLDER_NAME: &str = "hyperbolic-magnetism-beat-saber";
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 3 {
|
||||
eprintln!("Usage: {} <pid> <path_to_directory>", args[0]);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let pid: Pid = Pid::from_str(&args[1]).expect("Invalid pid");
|
||||
let directory_path = Path::new(&args[2]);
|
||||
|
||||
if directory_path.file_name() != Some(OsStr::new(BEAT_SABER_OCULUS_FOLDER_NAME)) {
|
||||
eprintln!("Directory name is not {}", BEAT_SABER_OCULUS_FOLDER_NAME);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// we want to monitor only processes
|
||||
let mut system = System::new_with_specifics(sysinfo::RefreshKind::new().with_processes(ProcessRefreshKind::everything()));
|
||||
|
||||
loop {
|
||||
system.refresh_processes();
|
||||
let process = system.process(pid);
|
||||
|
||||
match process {
|
||||
Some(_) => {
|
||||
println!("Process {} is still running.", pid);
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
},
|
||||
None => {
|
||||
println!("Process {} has stopped, deleting directory {:?}", pid, directory_path);
|
||||
match delete_dir_if_is_symlink(directory_path) {
|
||||
Ok(_) => {
|
||||
println!("Directory {:?} deleted successfully.", directory_path);
|
||||
if let Err(e) = rename_specific_backup_directory(directory_path.parent().unwrap()) {
|
||||
eprintln!("Failed to rename backup directory: {}", e);
|
||||
}
|
||||
},
|
||||
Err(e) => eprintln!("Failed to delete directory {:?}: {}", directory_path, e),
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_dir_if_is_symlink(path: &Path) -> Result<(), Box<dyn std::error::Error>>{
|
||||
match path.symlink_metadata()?.file_type().is_symlink() {
|
||||
true => {
|
||||
fs::remove_dir_all(path)?;
|
||||
Ok(())
|
||||
},
|
||||
false => {
|
||||
eprintln!("Path {:?} is not a symlink.", path);
|
||||
Err("Path is not a symlink.".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_specific_backup_directory(parent_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let backup_dir_name = format!("{}.bsmbak", BEAT_SABER_OCULUS_FOLDER_NAME);
|
||||
let backup_path = parent_path.join(&backup_dir_name);
|
||||
if backup_path.exists() && backup_path.is_dir() {
|
||||
let new_path = parent_path.join(BEAT_SABER_OCULUS_FOLDER_NAME);
|
||||
fs::rename(&backup_path, &new_path)?;
|
||||
println!("Renamed {:?} to {:?}", backup_path, new_path);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("Backup directory {:?} does not exist or is not a directory.", backup_path).into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,3 +15,4 @@ import "./bs-model-ipcs";
|
||||
import "./bs-version-download/bs-download-ipcs";
|
||||
import "./static-configuration.ipcs";
|
||||
import "./linux.ipcs.ts";
|
||||
import "./oculus.ipcs";
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { OculusService } from "../services/oculus.service";
|
||||
import { IpcService } from "../services/ipc.service";
|
||||
import { from } from "rxjs";
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
ipc.on("is-oculus-sideloaded-apps-enabled", (_, reply) => {
|
||||
const oculusService = OculusService.getInstance();
|
||||
reply(from(oculusService.isSideLoadedAppsEnabled()));
|
||||
});
|
||||
|
||||
ipc.on("enable-oculus-sideloaded-apps", (_, reply) => {
|
||||
const oculusService = OculusService.getInstance();
|
||||
reply(from(oculusService.enableSideloadedApps()));
|
||||
});
|
||||
@@ -1,20 +1,15 @@
|
||||
import { Observable, ReplaySubject, catchError, lastValueFrom, of, take, timeout } from "rxjs";
|
||||
import { Observable, ReplaySubject } from "rxjs";
|
||||
import { StoreLauncherInterface } from "./store-launcher.interface";
|
||||
import { BSLaunchError, BSLaunchEvent, BSLaunchEventData, LaunchOption } from "../../../shared/models/bs-launch";
|
||||
import { OculusService } from "../oculus.service";
|
||||
import { BS_EXECUTABLE, OCULUS_BS_BACKUP_DIR, OCULUS_BS_DIR } from "../../constants";
|
||||
import { BS_EXECUTABLE } from "../../constants";
|
||||
import path from "path";
|
||||
import log from "electron-log";
|
||||
import { sToMs } from "../../../shared/helpers/time.helpers";
|
||||
import { lstat, pathExists, readdir, readlink, rename, symlink, unlink } from "fs-extra";
|
||||
import { pathExists } from "fs-extra";
|
||||
import { AbstractLauncherService } from "./abstract-launcher.service";
|
||||
import { isProcessRunning } from "../../helpers/os.helpers";
|
||||
import { CustomError } from "../../../shared/models/exceptions/custom-error.class";
|
||||
import { InstallationLocationService } from "../installation-location.service";
|
||||
import { ensurePathNotAlreadyExist } from "../../helpers/fs.helpers";
|
||||
import { UtilsService } from "../utils.service";
|
||||
import { spawn } from "child_process";
|
||||
import { tryit } from "../../../shared/helpers/error.helpers";
|
||||
|
||||
export class OculusLauncherService extends AbstractLauncherService implements StoreLauncherInterface {
|
||||
|
||||
@@ -28,7 +23,6 @@ export class OculusLauncherService extends AbstractLauncherService implements St
|
||||
}
|
||||
|
||||
private readonly oculus: OculusService;
|
||||
private readonly pathsService: InstallationLocationService;
|
||||
private readonly util: UtilsService;
|
||||
|
||||
private readonly oculusLib$ = new ReplaySubject<string>();
|
||||
@@ -36,120 +30,11 @@ export class OculusLauncherService extends AbstractLauncherService implements St
|
||||
private constructor() {
|
||||
super();
|
||||
this.oculus = OculusService.getInstance();
|
||||
this.pathsService = InstallationLocationService.getInstance();
|
||||
this.util = UtilsService.getInstance();
|
||||
|
||||
this.oculus.tryGetGameFolder([OCULUS_BS_DIR, OCULUS_BS_BACKUP_DIR]).then(async dirPath => {
|
||||
if(dirPath){
|
||||
return this.oculusLib$.next( path.join(dirPath, "..") );
|
||||
}
|
||||
const defaultLib = ((await this.oculus.getOculusLibs()) || []).find(lib => lib.isDefault);
|
||||
if(defaultLib?.path){ return this.oculusLib$.next(path.join(defaultLib.path, "Software")); }
|
||||
this.oculusLib$.next(null);
|
||||
}).catch(err => {
|
||||
log.error("Error while getting Oculus libs", err);
|
||||
this.oculusLib$.next(null);
|
||||
});
|
||||
}
|
||||
|
||||
public async deleteBsSymlinks(): Promise<void> {
|
||||
const oculusLibPath = await lastValueFrom(this.oculusLib$.pipe(take(1), timeout(sToMs(30)), catchError(() => of(null))));
|
||||
|
||||
if(!oculusLibPath || !(await pathExists(oculusLibPath))){
|
||||
throw new Error("Oculus library not found, deleteBsSymlinks");
|
||||
}
|
||||
|
||||
const libContents = await readdir(oculusLibPath);
|
||||
const symlinks = (await Promise.all(libContents.map(async dir => {
|
||||
return (await lstat(path.join(oculusLibPath, dir))).isSymbolicLink() ? dir : null;
|
||||
}))).filter(Boolean);
|
||||
|
||||
log.info("Symlinks found in Oculus library", symlinks);
|
||||
|
||||
const bsSymlinks = symlinks.filter(dirent => dirent.startsWith(OCULUS_BS_DIR));
|
||||
|
||||
const bsmSymlinks = (await Promise.all(bsSymlinks.map(async symlink => {
|
||||
const symlinkPath = path.join(oculusLibPath, symlink);
|
||||
const targetPath = await readlink(symlinkPath).catch(err => log.error(err));
|
||||
|
||||
log.info("Oculus Symlink", symlink, "target", targetPath);
|
||||
|
||||
if(!targetPath){ return null; }
|
||||
|
||||
const bsmVersionsDir = path.join(this.pathsService.INSTALLATION_FOLDER, this.pathsService.VERSIONS_FOLDER);
|
||||
|
||||
if(!targetPath.includes(bsmVersionsDir)){ return null; }
|
||||
|
||||
return symlink;
|
||||
}))).filter(Boolean);
|
||||
|
||||
await Promise.all(bsmSymlinks.map(symlink => {
|
||||
log.info("Delete symlink", symlink);
|
||||
return unlink(path.join(oculusLibPath, symlink));
|
||||
}));
|
||||
}
|
||||
|
||||
private async backupOriginalBeatSaber(): Promise<void>{
|
||||
const bsFolder = await this.oculus.getGameFolder(OCULUS_BS_DIR);
|
||||
if(!bsFolder){ return; }
|
||||
const backupPath = await ensurePathNotAlreadyExist(path.join(bsFolder, "..", OCULUS_BS_BACKUP_DIR));
|
||||
log.info("Backing up original Beat Saber", bsFolder, backupPath);
|
||||
return rename(bsFolder, backupPath);
|
||||
}
|
||||
|
||||
public async restoreOriginalBeatSaber(): Promise<void>{
|
||||
const bsFolderBackupPath = await this.oculus.getGameFolder(OCULUS_BS_BACKUP_DIR);
|
||||
if(!(await pathExists(bsFolderBackupPath))){ return; }
|
||||
const originalPath = path.join(bsFolderBackupPath, "..", OCULUS_BS_DIR);
|
||||
log.info("Restoring original Beat Saber", bsFolderBackupPath, originalPath);
|
||||
return rename(bsFolderBackupPath, originalPath);
|
||||
}
|
||||
|
||||
private launchSymlinkCleaner(pid: number, symlinkPath: string){
|
||||
|
||||
log.info("Launch Symlink Cleaner", pid, symlinkPath);
|
||||
|
||||
const exeName = "oculus_symlink_cleaner.exe";
|
||||
const scriptPath = this.util.getAssetsScriptsPath();
|
||||
spawn(path.join(scriptPath, exeName), [`${pid}`, symlinkPath], { detached: true, stdio: "ignore" });
|
||||
}
|
||||
|
||||
public launch(launchOptions: LaunchOption): Observable<BSLaunchEventData> {
|
||||
|
||||
const prepareOriginalVersion: () => Promise<string> = async () => {
|
||||
await this.restoreOriginalBeatSaber();
|
||||
const bsPath = await this.oculus.getGameFolder(OCULUS_BS_DIR);
|
||||
if(!bsPath){
|
||||
throw new Error("Oculus Beat Saber path not found");
|
||||
}
|
||||
return bsPath;
|
||||
}
|
||||
|
||||
const prepareDowngradedVersion: () => Promise<string> = async () => {
|
||||
|
||||
const originalVersionPath = await prepareOriginalVersion().catch(() => null);
|
||||
if (!originalVersionPath) {
|
||||
throw CustomError.fromError(new Error("Original Oculus Beat Saber not installed"), BSLaunchError.ORIGINAL_OCULUS_NOT_INSTALLED);
|
||||
}
|
||||
|
||||
const oculusLib = await lastValueFrom(this.oculusLib$.pipe(take(1), timeout(sToMs(30)), catchError(() => of(null))));
|
||||
|
||||
if(!oculusLib){
|
||||
throw CustomError.fromError(new Error("No Oculus library found"), BSLaunchError.OCULUS_LIB_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Backup original Beat Saber folder
|
||||
await this.backupOriginalBeatSaber();
|
||||
|
||||
// Create symlink in the oculus library from the BSM BS version
|
||||
const symlinkTarget = await this.localVersions.getInstalledVersionPath(launchOptions.version);
|
||||
const symlinkPath = path.join(oculusLib, OCULUS_BS_DIR);
|
||||
log.info("Creating symlink", symlinkTarget, symlinkPath);
|
||||
await symlink(symlinkTarget, symlinkPath, "junction");
|
||||
|
||||
return symlinkPath;
|
||||
}
|
||||
|
||||
return new Observable<BSLaunchEventData>(obs => {
|
||||
(async () => {
|
||||
|
||||
@@ -159,11 +44,7 @@ export class OculusLauncherService extends AbstractLauncherService implements St
|
||||
throw CustomError.fromError(new Error("Cannot start two instance of Beat Saber for Oculus"), BSLaunchError.BS_ALREADY_RUNNING);
|
||||
}
|
||||
|
||||
// Remove previously symlinks created by BSM
|
||||
await this.deleteBsSymlinks().catch(err => log.error("Error while deleting BSM symlinks", err));
|
||||
|
||||
const bsPath = await (launchOptions.version.oculus ? prepareOriginalVersion() : prepareDowngradedVersion());
|
||||
|
||||
const bsPath = await this.localVersions.getInstalledVersionPath(launchOptions.version);
|
||||
const exePath = path.join(bsPath, BS_EXECUTABLE);
|
||||
|
||||
if(!(await pathExists(exePath))){
|
||||
@@ -178,13 +59,6 @@ export class OculusLauncherService extends AbstractLauncherService implements St
|
||||
// Launch Beat Saber
|
||||
const process = this.launchBs(exePath, this.buildBsLaunchArgs(launchOptions));
|
||||
|
||||
if(launchOptions.version.oculus !== true && process?.process?.pid){
|
||||
const { error } = tryit(() => this.launchSymlinkCleaner(process.process.pid, bsPath));
|
||||
if(error){
|
||||
log.error("Error while launching symlink cleaner", error);
|
||||
}
|
||||
}
|
||||
|
||||
return process.exit.catch(err => {
|
||||
throw CustomError.fromError(err, BSLaunchError.BS_EXIT_ERROR);
|
||||
});
|
||||
|
||||
@@ -7,14 +7,14 @@ import { shell } from "electron";
|
||||
import { isProcessRunning } from "../helpers/os.helpers";
|
||||
import { sToMs } from "../../shared/helpers/time.helpers";
|
||||
import { execOnOs } from "../helpers/env.helpers";
|
||||
import { UtilsService } from "./utils.service";
|
||||
import { exec } from "child_process";
|
||||
|
||||
const { list } = (execOnOs({ win32: () => require("regedit-rs") }, true) ?? {}) as typeof import("regedit-rs");
|
||||
|
||||
export class OculusService {
|
||||
private static instance: OculusService;
|
||||
|
||||
private oculusLibraries: OculusLibrary[];
|
||||
|
||||
public static getInstance(): OculusService {
|
||||
if (!OculusService.instance) {
|
||||
OculusService.instance = new OculusService();
|
||||
@@ -22,7 +22,14 @@ export class OculusService {
|
||||
return OculusService.instance;
|
||||
}
|
||||
|
||||
private constructor() {}
|
||||
|
||||
private readonly utils: UtilsService;
|
||||
|
||||
private oculusLibraries: OculusLibrary[];
|
||||
|
||||
private constructor() {
|
||||
this.utils = UtilsService.getInstance();
|
||||
}
|
||||
|
||||
public async getOculusLibs(): Promise<OculusLibrary[]> {
|
||||
if (process.platform !== "win32") {
|
||||
@@ -120,6 +127,67 @@ export class OculusService {
|
||||
}, sToMs(30));
|
||||
});
|
||||
}
|
||||
|
||||
public async isSideLoadedAppsEnabled(): Promise<boolean> {
|
||||
if(process.platform !== "win32"){
|
||||
log.info("Cannot check sideloaded apps on non-windows platforms");
|
||||
throw new Error("Cannot check sideloaded apps on non-windows platforms");
|
||||
}
|
||||
|
||||
const regPath = "HKLM\\SOFTWARE\\Wow6432Node\\Oculus VR, LLC\\Oculus";
|
||||
const res = await list(regPath).then(res => res[regPath]);
|
||||
|
||||
if(!res.exists){
|
||||
log.info("Registry key not found", regPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
const value = res.values?.AllowDevSideloaded;
|
||||
|
||||
if(!value){
|
||||
log.info("Registry value not found", "AllowDevSideloaded");
|
||||
return false;
|
||||
}
|
||||
|
||||
return value.value === 1;
|
||||
}
|
||||
|
||||
public async enableSideloadedApps(): Promise<void> {
|
||||
if(process.platform !== "win32"){
|
||||
log.info("Cannot enable sideloaded apps on non-windows platforms");
|
||||
return;
|
||||
}
|
||||
|
||||
const enabled = await this.isSideLoadedAppsEnabled();
|
||||
|
||||
if(enabled){
|
||||
log.info("Sideloaded apps already enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
const exePath = path.join(this.utils.getAssetsScriptsPath(), "oculus-allow-dev-sideloaded.exe");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
log.info("Enabling sideloaded apps");
|
||||
const process = exec(exePath);
|
||||
process.on("exit", code => {
|
||||
if(code === 0){
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Failed to enable sideloaded apps, exit code: ${code}`));
|
||||
}
|
||||
});
|
||||
|
||||
process.on("error", err => {
|
||||
log.error("Error while enabling sideloaded apps", err);
|
||||
reject(err);
|
||||
});
|
||||
|
||||
process.stdout.on("data", data => {
|
||||
log.info(data.toString?.() ?? data);
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export interface OculusLibrary {
|
||||
|
||||
+11
-16
@@ -2,31 +2,26 @@ import { ModalComponent, ModalExitCode } from "renderer/services/modale.service"
|
||||
import BeatConflict from "../../../../../assets/images/apngs/beat-conflict.png";
|
||||
import { BsmButton } from "renderer/components/shared/bsm-button.component";
|
||||
import { BsmImage } from "renderer/components/shared/bsm-image.component";
|
||||
import { BsmCheckbox } from "renderer/components/shared/bsm-checkbox.component";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
import { useTranslationV2 } from "renderer/hooks/use-translation.hook";
|
||||
|
||||
export const OriginalOculusVersionBackupModal: ModalComponent<boolean, void> = ({ resolver }) => {
|
||||
export const EnableOculusSideloadedApps: ModalComponent<void, void> = ({ resolver }) => {
|
||||
|
||||
const t = useTranslation();
|
||||
const [dontShowAgain, setDontShowAgain] = useState(false);
|
||||
const { text: t } = useTranslationV2();
|
||||
|
||||
const submit = () => {
|
||||
resolver({ exitCode: ModalExitCode.COMPLETED, data: dontShowAgain });
|
||||
resolver({ exitCode: ModalExitCode.COMPLETED });
|
||||
}
|
||||
|
||||
return (
|
||||
<form className="max-w-[450px] text-gray-800 dark:text-gray-200">
|
||||
<h1 className="text-3xl uppercase tracking-wide w-full text-center text-gray-800 dark:text-gray-200">{t("modals.original-version-backup-oculus.title")}</h1>
|
||||
<BsmImage className="mx-auto h-20" image={BeatConflict} />
|
||||
<h1 className="text-3xl uppercase tracking-wide w-full text-center text-gray-800 dark:text-gray-200">{t("modals.enable-oculus-sideloaded-apps.title")}</h1>
|
||||
<BsmImage className="mx-auto h-24" image={BeatConflict} />
|
||||
|
||||
<p className="text-sm italic mb-4 font-bold">{t("modals.original-version-backup-oculus.body.must-be-installed-once")}</p>
|
||||
<p className="mb-4">{t("modals.original-version-backup-oculus.body.will-backup")}</p>
|
||||
<p className="mb-4">{t("modals.enable-oculus-sideloaded-apps.info-1")}</p>
|
||||
<p className="mb-4">{t("modals.enable-oculus-sideloaded-apps.info-2")}</p>
|
||||
<p className="mb-4">{t("modals.enable-oculus-sideloaded-apps.info-3")}</p>
|
||||
|
||||
<div className="flex flex-row justify-start items-center gap-1.5 my-4" >
|
||||
<BsmCheckbox className="relative z-[1] w-6 aspect-square" checked={dontShowAgain} onChange={setDontShowAgain} />
|
||||
<span>{t("modals.original-version-backup-oculus.not-remind-me")}</span>
|
||||
</div>
|
||||
<a className="underline mb-5 block" href="https://github.com/Zagrios/bs-manager/wiki/Activate-Oculus-sideloading" target="_blank">{t("modals.enable-oculus-sideloaded-apps.i-want-to-do-it-myself")}</a>
|
||||
|
||||
<div className="grid grid-flow-col grid-cols-2 gap-4">
|
||||
<BsmButton
|
||||
@@ -43,7 +38,7 @@ export const OriginalOculusVersionBackupModal: ModalComponent<boolean, void> = (
|
||||
className="rounded-md transition-all h-10 flex items-center justify-center"
|
||||
onClick={submit}
|
||||
withBar={false}
|
||||
text="modals.original-version-backup-oculus.understood"
|
||||
text="modals.enable-oculus-sideloaded-apps.understood"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
@@ -7,7 +7,7 @@ import { ConfigurationService } from "./configuration.service";
|
||||
import { ThemeService } from "./theme.service";
|
||||
import { BsStore } from "shared/models/bs-store.enum";
|
||||
import { ModalExitCode, ModalService } from "./modale.service";
|
||||
import { OriginalOculusVersionBackupModal } from "renderer/components/modal/modal-types/original-oculus-version-backup.modal";
|
||||
import { EnableOculusSideloadedApps } from "renderer/components/modal/modal-types/enable-oculus-sideloaded-apps";
|
||||
import { CustomError } from "shared/models/exceptions/custom-error.class";
|
||||
import { sToMs } from "shared/helpers/time.helpers";
|
||||
import { NeedLaunchAdminModal } from "renderer/components/modal/modal-types/need-launch-admin-modal.component";
|
||||
@@ -80,6 +80,20 @@ export class BSLauncherService {
|
||||
return true;
|
||||
}
|
||||
|
||||
private async enableSideloadedAppsIfNeeded(): Promise<void> {
|
||||
if(window.electron.platform !== "win32"){ return; }
|
||||
const isSideloadedAppsEnabled = await lastValueFrom(this.ipcService.sendV2("is-oculus-sideloaded-apps-enabled"));
|
||||
if(isSideloadedAppsEnabled){ return; }
|
||||
|
||||
const modalRes = await this.modals.openModal(EnableOculusSideloadedApps);
|
||||
|
||||
if(modalRes.exitCode !== ModalExitCode.COMPLETED){
|
||||
throw new Error("Enable sideloaded apps canceled");
|
||||
}
|
||||
|
||||
await lastValueFrom(this.ipcService.sendV2("enable-oculus-sideloaded-apps"));
|
||||
}
|
||||
|
||||
public doLaunch(launchOptions: LaunchOption): Observable<BSLaunchEventData>{
|
||||
return this.ipcService.sendV2("bs-launch.launch", launchOptions);
|
||||
}
|
||||
@@ -89,10 +103,9 @@ export class BSLauncherService {
|
||||
return new Observable<BSLaunchEventData>(obs => {
|
||||
(async () => {
|
||||
|
||||
if(launchOptions.version.metadata?.store === BsStore.OCULUS && !this.notRewindBackupOculus()){
|
||||
const { exitCode, data: notRewind } = await this.modals.openModal(OriginalOculusVersionBackupModal);
|
||||
if(exitCode !== ModalExitCode.COMPLETED){ return; }
|
||||
this.setNotRewindBackupOculus(notRewind);
|
||||
// If downgraded from oculus and its not the official version
|
||||
if(launchOptions.version.metadata?.store === BsStore.OCULUS && !launchOptions.version.oculus){
|
||||
await this.enableSideloadedAppsIfNeeded();
|
||||
}
|
||||
|
||||
if(launchOptions.version.metadata?.store !== BsStore.OCULUS){
|
||||
|
||||
@@ -161,6 +161,10 @@ export interface IpcChannelMapping {
|
||||
/* ** linux.ipcs ** */
|
||||
"linux.verify-proton-folder": { request: void, response: boolean };
|
||||
|
||||
/* ** oculus.ipcs ** */
|
||||
"is-oculus-sideloaded-apps-enabled": { request: void, response: boolean };
|
||||
"enable-oculus-sideloaded-apps": { request: void, response: void };
|
||||
|
||||
/* ** OTHERS (if your IPC channel is not in a "-ipcs" file, put it here) ** */
|
||||
"shortcut-launch-options": { request: void, response: LaunchOption };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user