Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions assets/jsons/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,16 @@
"actions": {
"STEAM_NOT_RUNNING": "Launch Steam"
}
},
"warnings": {
"titles": {
"FPFC_NEED_ADMIN": "FPFC mode setup incomplete",
"UNABLE_TO_LAUNCH_STEAM": "Could not launch Steam"
},
"msg": {
"FPFC_NEED_ADMIN": "BSManager needs administrator privileges to properly set up FPFC mode. Run BSManager as administrator for the best experience.",
"UNABLE_TO_LAUNCH_STEAM": "Steam could not be started automatically."
}
}
},
"steam": {
Expand Down
48 changes: 30 additions & 18 deletions src/main/services/bs-launcher/steam-launcher.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,25 @@
return this.steam.getGameFolder(STEAMVR_APP_ID, "SteamVR");
}

private async backupSteamVR(): Promise<void> {
private timedRename(src: string, dest: string): Promise<void> {
return Promise.race([
rename(src, dest),
new Promise<never>((_, reject) => setTimeout(() => reject(new Error("Rename timed out")), 5000)),
]);
}

private async backupSteamVR(): Promise<boolean> {
const steamVrFolder = await this.getSteamVRPath();
if (!(await pathExists(steamVrFolder))) {
return;
if (!steamVrFolder || !(await pathExists(steamVrFolder))) {
return false;
}
try {
await this.timedRename(steamVrFolder, `${steamVrFolder}.bak`);
return false;
} catch (err) {
log.warn("Could not backup SteamVR folder, skipping", err);
return err?.code === "EPERM" || err?.message?.includes("timed out");
}
return rename(steamVrFolder, `${steamVrFolder}.bak`).catch(err => {
log.error("Error while create backup of SteamVR", err);
});
}

private getStartBsAsAdminExePath(): string {
Expand All @@ -54,14 +65,11 @@

public async restoreSteamVR(): Promise<void> {
const steamVrFolder = await this.getSteamVRPath();
if (!steamVrFolder) { return; }
const steamVrBackup = `${steamVrFolder}.bak`;

if (!(await pathExists(steamVrBackup))) {
return;
}

return rename(steamVrBackup, steamVrFolder).catch(err => {
log.error("Error while restoring SteamVR", err);
if (!(await pathExists(steamVrBackup))) { return; }
return this.timedRename(steamVrBackup, steamVrFolder).catch(err => {
log.warn("Could not restore SteamVR folder", err);
});
}

Expand Down Expand Up @@ -109,7 +117,7 @@

public launch(launchOptions: LaunchOption): Observable<BSLaunchEventData>{

return new Observable<BSLaunchEventData>(obs => {(async () => {

Check failure on line 120 in src/main/services/bs-launcher/steam-launcher.service.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=Zagrios_bs-manager&issues=AZy9AdXjTcd1VpVZt3OU&open=AZy9AdXjTcd1VpVZt3OU&pullRequest=1025

const bsFolderPath = await this.localVersions.getInstalledVersionPath(launchOptions.version);
const bsExePath = path.join(bsFolderPath, BS_EXECUTABLE);
Expand All @@ -136,12 +144,16 @@
obs.next({ type: BSLaunchEvent.SKIPPING_STEAM_LAUNCH});
}

// Backup SteamVR when desktop mode is enabled
if(launchOptions.launchMods?.includes(LaunchMods.FPFC)){
await this.backupSteamVR().catch(() => {
return this.restoreSteamVR();
const isFpfc = launchOptions.launchMods?.includes(LaunchMods.FPFC);
const isOculus = launchOptions.launchMods?.includes(LaunchMods.OCULUS);
if(isFpfc && !isOculus){
const backupPermError = await this.backupSteamVR().catch(() => {
return this.restoreSteamVR().then(() => false);

Check failure on line 151 in src/main/services/bs-launcher/steam-launcher.service.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest functions more than 4 levels deep.

See more on https://sonarcloud.io/project/issues?id=Zagrios_bs-manager&issues=AZy9AdXjTcd1VpVZt3OV&open=AZy9AdXjTcd1VpVZt3OV&pullRequest=1025
});
} else {
if(backupPermError){
obs.next({type: BSLaunchWarning.FPFC_NEED_ADMIN});
}
} else if(!isFpfc) {
await this.restoreSteamVR().catch(log.error);
}

Expand Down
7 changes: 6 additions & 1 deletion src/renderer/services/bs-launcher.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,15 @@
}

private handleLaunchEvents(events$: Observable<BSLaunchEventData>): Observable<BSLaunchEventData>{
const eventToFilter = [...Object.values(BSLaunchWarning), BSLaunchEvent.STEAM_LAUNCHED]
const warningTypes: string[] = Object.values(BSLaunchWarning);
const eventToFilter = [...warningTypes, BSLaunchEvent.STEAM_LAUNCHED]

Check warning on line 49 in src/renderer/services/bs-launcher.service.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

`eventToFilter` should be a `Set`, and use `eventToFilter.has()` to check existence or non-existence.

See more on https://sonarcloud.io/project/issues?id=Zagrios_bs-manager&issues=AZy9AdVSTcd1VpVZt3OT&open=AZy9AdVSTcd1VpVZt3OT&pullRequest=1025

return events$.pipe(tap({
next: event => {
if(warningTypes.includes(event.type)){
this.notificationService.notifyWarning({title: `notifications.bs-launch.warnings.titles.${event.type}`, desc: `notifications.bs-launch.warnings.msg.${event.type}`, duration: sToMs(9)});
return;
}
if(eventToFilter.includes(event.type)){ return; }
this.notificationService.notifySuccess({title: `notifications.bs-launch.success.titles.${event.type}`, desc: `notifications.bs-launch.success.msg.${event.type}`});
},
Expand Down
1 change: 1 addition & 0 deletions src/shared/models/bs-launch/launch-event.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export enum BSLaunchEvent{

export enum BSLaunchWarning{
UNABLE_TO_LAUNCH_STEAM = "UNABLE_TO_LAUNCH_STEAM",
FPFC_NEED_ADMIN = "FPFC_NEED_ADMIN",
}

export type BSLaunchEventType = BSLaunchEvent | BSLaunchWarning;