From ec563dc7f4414c77432d51c082d94943b9b730b9 Mon Sep 17 00:00:00 2001 From: Matt Lishman Date: Wed, 8 Feb 2023 22:04:21 +0000 Subject: [PATCH] feat: use the first custom executable from MO2 when launching the game --- .../services/modOrganizer.service.test.ts | 37 +++++++++++++++++++ src/main/services/modOrganizer.service.ts | 10 ++++- src/types/ModOrganizer.ini.d.ts | 10 +++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/types/ModOrganizer.ini.d.ts diff --git a/src/__tests__/unit/services/modOrganizer.service.test.ts b/src/__tests__/unit/services/modOrganizer.service.test.ts index ed40d2b1..ed4738f7 100644 --- a/src/__tests__/unit/services/modOrganizer.service.test.ts +++ b/src/__tests__/unit/services/modOrganizer.service.test.ts @@ -15,6 +15,7 @@ import { GameService } from "@/main/services/game.service"; import { ProfileService } from "@/main/services/profile.service"; import { SystemService } from "@/main/services/system.service"; import { GraphicsService } from "@/main/services/graphics.service"; +import mockFs from "mock-fs"; describe("ModOrganizer service", () => { let mockEnbService: StubbedInstanceWithSinonAccessor; @@ -39,6 +40,10 @@ describe("ModOrganizer service", () => { mockGraphicsService = createStubInstance(GraphicsService); }); + afterEach(() => { + mockFs.restore(); + }); + it("should determine if Mod Organizer is running", async () => { mockSystemService.stubs.isProcessRunning .withArgs(MO2Names.MO2EXE) @@ -57,4 +62,36 @@ describe("ModOrganizer service", () => { expect(await modOrganizerService.isRunning()).to.eql(true); }); + + it("should get the first binary", async () => { + const mockModDirectory = "mock/mod/directory"; + + mockFs({ + [mockModDirectory]: { + [MO2Names.MO2Settings]: ` + [customExecutables] + size=1 + 1\\binary=mock/first/custom/executable.exe + 1\\title=SKSE + `, + }, + }); + + mockConfigService.stubs.modDirectory.returns(mockModDirectory); + + modOrganizerService = new ModOrganizerService( + mockEnbService, + mockErrorService, + mockConfigService, + mockResolutionService, + mockGameService, + mockProfileService, + mockSystemService, + mockGraphicsService + ); + + expect(await modOrganizerService.getFirstCustomExecutableTitle()).to.eql( + "SKSE" + ); + }); }); diff --git a/src/main/services/modOrganizer.service.ts b/src/main/services/modOrganizer.service.ts index 2a143a2f..0c5790f0 100644 --- a/src/main/services/modOrganizer.service.ts +++ b/src/main/services/modOrganizer.service.ts @@ -19,6 +19,7 @@ import { GameService } from "@/main/services/game.service"; import { ProfileService } from "@/main/services/profile.service"; import { SystemService } from "@/main/services/system.service"; import { GraphicsService } from "@/main/services/graphics.service"; +import { ModOrganizerIni } from "@/ModOrganizer.ini"; export const enum MO2Names { MO2EXE = "ModOrganizer.exe", @@ -85,7 +86,12 @@ export class ModOrganizerService { `${this.configService.modDirectory()}/${MO2Names.MO2Settings}`, "utf-8" ) - ); + ) as ModOrganizerIni; + } + + async getFirstCustomExecutableTitle() { + const settings = await this.readSettings(); + return settings["customExecutables"]["1\\title"]; } async updateSelectedProfile(profile: string) { @@ -202,7 +208,7 @@ export class ModOrganizerService { ); const profile = userPreferences.get(USER_PREFERENCE_KEYS.PRESET); - const mo2Command = `"${MO2Path}" -p "${profile}" "moshortcut://:SKSE"`; + const mo2Command = `"${MO2Path}" -p "${profile}" "moshortcut://:${await this.getFirstCustomExecutableTitle()}"`; logger.debug(`Executing MO2 command: ${mo2Command}`); const { stderr } = await promisify(childProcess.exec)(mo2Command); diff --git a/src/types/ModOrganizer.ini.d.ts b/src/types/ModOrganizer.ini.d.ts new file mode 100644 index 00000000..27729914 --- /dev/null +++ b/src/types/ModOrganizer.ini.d.ts @@ -0,0 +1,10 @@ +import { IIniObject } from "js-ini/lib/interfaces/ini-object"; + +export interface ModOrganizerIni extends IIniObject { + General: object; + customExecutables: { + size: number; + [key: string]: unknown; + }; + Settings: object; +}