From f14495efa0758cd46914e08c68585d2038918796 Mon Sep 17 00:00:00 2001 From: Vitalii Mikhailov Date: Sun, 9 Jun 2024 14:56:58 +0300 Subject: [PATCH] Better type guards Added mandatory folders for game discovery Fixed discovery undefined issue --- changelog.txt | 4 ++ package.json | 2 +- src/game.ts | 2 +- src/index.ts | 72 +++++++++++++++--------------- src/utils/blse/shared.ts | 2 +- src/utils/settings/utils.ts | 8 ++-- src/utils/vortex.ts | 19 ++++---- src/utils/vortexLauncherManager.ts | 4 +- 8 files changed, 57 insertions(+), 56 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2460802..e5abb2b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,8 @@ --------------------------------------------------------------------------------------------------- +Version: 1.0.13 +* Added mandatory folders for manual game path hint +* Fixed undefined tools bug +--------------------------------------------------------------------------------------------------- Version: 1.0.12 * Fixed undefined gameId bug * Reusing localization from BLSE diff --git a/package.json b/package.json index f8d2999..2f54216 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "game-mount-and-blade-ii-bannerlord-butr", - "version": "1.0.12", + "version": "1.0.13", "description": "A Vortex extension for Mount and Blade II: Bannerlord mod management.", "author": "BUTR Team & Nexus Mods", "license": "GPL-3.0+", diff --git a/src/game.ts b/src/game.ts index d6e4742..5a6d76f 100644 --- a/src/game.ts +++ b/src/game.ts @@ -20,7 +20,7 @@ export class BannerlordGame implements types.IGame { gog: GOG_IDS.map((x) => ({ id: x })), epic: [{ id: EPICAPP_ID }], }; - public requiredFiles: string[] = []; + public requiredFiles: string[] = ['bin', 'Modules']; public parameters: string[] = []; public requiresCleanup = true; public details: { [key: string]: unknown } = { diff --git a/src/index.ts b/src/index.ts index f452ff8..009f88f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,12 +42,12 @@ const main = (context: types.IExtensionContext): boolean => { return SaveManager.getInstance(context.api, getLauncherManager); }; - context.registerReducer([`settings`, GAME_ID], reducer); + context.registerReducer(/*path:*/ [`settings`, GAME_ID], /*spec:*/ reducer); context.registerSettings( - `Interface`, - Settings, - (): ISettingsProps => ({ + /*title:*/ `Interface`, + /*element:*/ Settings, + /*props?:*/ (): ISettingsProps => ({ getLocalizationManager: getLocalizationManager, onSetSortOnDeploy: (profileId: string, sort: boolean) => context.api.store?.dispatch(actionsSettings.setSortOnDeploy(profileId, sort)), @@ -56,10 +56,10 @@ const main = (context: types.IExtensionContext): boolean => { onSetBetaSorting: (profileId: string, betaSorting: boolean) => context.api.store?.dispatch(actionsSettings.setBetaSorting(profileId, betaSorting)), }), - () => { + /*visible?:*/ () => { return selectors.activeGameId(context.api.getState()) === GAME_ID; }, - 51 + /*priority?:*/ 51 ); context.registerGame(new BannerlordGame(context.api, getLauncherManager, getLocalizationManager)); @@ -80,60 +80,60 @@ const main = (context: types.IExtensionContext): boolean => { } */ - context.registerLoadOrder(getLoadOrderManager()); + context.registerLoadOrder(/*gameInfo:*/ getLoadOrderManager()); context.registerMainPage( - 'savegame', - 'Saves', - SaveList, - new SavePageOptions(context, getLauncherManager, getSaveManager, getLocalizationManager) + /*icon:*/ 'savegame', + /*title:*/ 'Saves', + /*element:*/ SaveList, + /*options:*/ new SavePageOptions(context, getLauncherManager, getSaveManager, getLocalizationManager) ); context.registerInstaller( - 'bannerlord-blse-installer', - 30, - toBluebird(testBLSE), - toBluebird((files: string[]) => installBLSE(context.api, files)) + /*id:*/ 'bannerlord-blse-installer', + /*priority:*/ 30, + /*testSupported:*/ toBluebird(testBLSE), + /*install:*/ toBluebird((files: string[]) => installBLSE(context.api, files)) ); context.registerModType( - 'bannerlord-blse', - 30, - (gameId) => gameId === GAME_ID, - (game) => getInstallPathBLSE(context.api, game), - toBluebird(isModTypeBLSE) + /*id:*/ 'bannerlord-blse', + /*priority:*/ 30, + /*isSupported:*/ (gameId) => gameId === GAME_ID, + /*getPath:*/ (game) => getInstallPathBLSE(context.api, game), + /*test:*/ toBluebird(isModTypeBLSE) ); context.registerInstaller( - `bannerlord-module-installer`, - 25, - toBluebird(async (files: string[], gameId: string) => { + /*id:*/ `bannerlord-module-installer`, + /*priority:*/ 25, + /*testSupported:*/ toBluebird(async (files: string[], gameId: string) => { const launcherManager = getLauncherManager(); return await launcherManager.testModule(files, gameId); }), - toBluebird(async (files: string[], destinationPath: string) => { + /*install:*/ toBluebird(async (files: string[], destinationPath: string) => { const launcherManager = getLauncherManager(); return await launcherManager.installModule(files, destinationPath); }) ); context.registerModType( - 'bannerlord-module', - 25, - (gameId) => gameId === GAME_ID, - (game) => getInstallPathModule(context.api, game), - toBluebird(isModTypeModule) + /*id:*/ 'bannerlord-module', + /*priority:*/ 25, + /*isSupported:*/ (gameId) => gameId === GAME_ID, + /*getPath:*/ (game) => getInstallPathModule(context.api, game), + /*test:*/ toBluebird(isModTypeModule) ); context.registerAction( - `fb-load-order-icons`, - 200, - `loot-sort`, - {}, - `Auto Sort`, - (_instanceIds?: string[]): boolean | void => { + /*group:*/ `fb-load-order-icons`, + /*position:*/ 200, + /*iconOrComponent:*/ `loot-sort`, + /*options:*/ {}, + /*titleOrProps?:*/ `Auto Sort`, + /*actionOrCondition?:*/ (_instanceIds?: string[]): boolean | void => { const launcherManager = getLauncherManager(); launcherManager.autoSort(); }, - (_instanceIds?: string[]): boolean => { + /*condition?:*/ (_instanceIds?: string[]): boolean => { const state = context.api.getState(); const gameId = selectors.activeGameId(state); return gameId === GAME_ID; diff --git a/src/utils/blse/shared.ts b/src/utils/blse/shared.ts index 10c23fb..186bd2c 100644 --- a/src/utils/blse/shared.ts +++ b/src/utils/blse/shared.ts @@ -67,7 +67,7 @@ export const deployBLSE = async (api: types.IExtensionApi): Promise => { await util.toPromise((cb) => api.events.emit('start-quick-discovery', () => cb(null))); const discovery = selectors.currentGameDiscovery(api.getState()); - const tool = discovery.tools?.['blse-cli']; + const tool = discovery?.tools?.['blse-cli']; if (tool) { api.store?.dispatch(actions.setPrimaryTool(GAME_ID, tool.id)); } diff --git a/src/utils/settings/utils.ts b/src/utils/settings/utils.ts index 4adf814..dc22f9d 100644 --- a/src/utils/settings/utils.ts +++ b/src/utils/settings/utils.ts @@ -1,6 +1,6 @@ import { hasSettings, hasSettingsBannerlord } from '..'; -export const getSortOnDeployFromSettings = (state: unknown, profileId: string) => { +export const getSortOnDeployFromSettings = (state: object, profileId: string) => { if (!hasSettings(state)) { return null; } @@ -12,7 +12,7 @@ export const getSortOnDeployFromSettings = (state: unknown, profileId: string) = return state.settings.mountandblade2bannerlord?.sortOnDeploy?.[profileId]; }; -export const getFixCommonIssuesFromSettings = (state: unknown, profileId: string) => { +export const getFixCommonIssuesFromSettings = (state: object, profileId: string) => { if (!hasSettings(state)) { return null; } @@ -24,7 +24,7 @@ export const getFixCommonIssuesFromSettings = (state: unknown, profileId: string return state.settings.mountandblade2bannerlord?.fixCommonIssues?.[profileId]; }; -export const getBetaSortingFromSettings = (state: unknown, profileId: string) => { +export const getBetaSortingFromSettings = (state: object, profileId: string) => { if (!hasSettings(state)) { return null; } @@ -36,7 +36,7 @@ export const getBetaSortingFromSettings = (state: unknown, profileId: string) => return state.settings.mountandblade2bannerlord?.betaSorting?.[profileId]; }; -export const getSaveFromSettings = (state: unknown, profileId: string) => { +export const getSaveFromSettings = (state: object, profileId: string) => { if (!hasSettings(state)) { return null; } diff --git a/src/utils/vortex.ts b/src/utils/vortex.ts index c1c9f14..d935788 100644 --- a/src/utils/vortex.ts +++ b/src/utils/vortex.ts @@ -16,7 +16,6 @@ import { BLSE_CLI_EXE, GAME_ID, XBOX_ID } from '../common'; import { ISettingsWithBannerlord, ISettingsInterfaceWithPrimaryTool, - IStatePersistent, IStatePersistentWithLoadOrder, GetLocalizationManager, GetLauncherManager, @@ -31,22 +30,20 @@ type RequiresLauncherResult = { addInfo?: unknown; }; -export const hasPersistentLoadOrder = (persistent: IStatePersistent): persistent is IStatePersistentWithLoadOrder => { - return typeof (persistent as never)[nameof('loadOrder')] === 'object'; +export const hasPersistentLoadOrder = (persistent: object): persistent is IStatePersistentWithLoadOrder => { + return nameof('loadOrder') in persistent; }; -export const hasSettings = (hasSettings: unknown): hasSettings is HasSettings => { - return typeof (hasSettings as never)[nameof('settings')] === 'object'; +export const hasSettings = (hasSettings: object): hasSettings is HasSettings => { + return nameof('settings') in hasSettings; }; -export const hasSettingsBannerlord = (settings: types.ISettings): settings is ISettingsWithBannerlord => { - return typeof (settings as never)[GAME_ID] === 'object'; +export const hasSettingsBannerlord = (settings: object): settings is ISettingsWithBannerlord => { + return GAME_ID in settings; }; -export const hasSettingsInterfacePrimaryTool = ( - settings: types.ISettingsInterface -): settings is ISettingsInterfaceWithPrimaryTool => { - return typeof (settings as never)[nameof('primaryTool')] === 'object'; +export const hasSettingsInterfacePrimaryTool = (settings: object): settings is ISettingsInterfaceWithPrimaryTool => { + return nameof('primaryTool') in settings; }; const launchGameStore = async (api: types.IExtensionApi, store: string): Promise => { diff --git a/src/utils/vortexLauncherManager.ts b/src/utils/vortexLauncherManager.ts index 2bc4964..11ba43c 100644 --- a/src/utils/vortexLauncherManager.ts +++ b/src/utils/vortexLauncherManager.ts @@ -289,7 +289,7 @@ export class VortexLauncherManager { const params = gameParameters.filter((x) => x !== ' ' && x.length > 0).join(' '); const discovery = selectors.currentGameDiscovery(this._api.getState()); - const cliTools = Object.values(discovery.tools ?? {}).filter((tool) => tool.id && tool.id.endsWith('-cli')); + const cliTools = Object.values(discovery?.tools ?? {}).filter((tool) => tool.id && tool.id.endsWith('-cli')); const batchedActions = cliTools.map((tool) => actions.addDiscoveredTool(GAME_ID, tool.id, { ...tool, parameters: [params] }, true) ); @@ -419,7 +419,7 @@ export class VortexLauncherManager { private getInstallPath = (): string => { const state = this._api.getState(); const discovery = selectors.currentGameDiscovery(state); - return discovery.path ?? ''; + return discovery?.path ?? ''; }; /** * Callback