Skip to content

Commit

Permalink
Merge pull request #119 from BUTR/dev
Browse files Browse the repository at this point in the history
Release 1.0.10
  • Loading branch information
Aragas authored May 31, 2024
2 parents 97452ad + 48cb413 commit 17a2f23
Show file tree
Hide file tree
Showing 26 changed files with 366 additions and 192 deletions.
8 changes: 8 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
---------------------------------------------------------------------------------------------------
Version: 1.0.10
* Fixed interference with other games
* Fixed CLI parameters passing
* Fixed current save tracking on Vortex launch
---------------------------------------------------------------------------------------------------
Version: 1.0.9
* Fixed primary tool persistence
---------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -27,6 +32,9 @@ Version: 1.0.2
* Validation fixes
* Load Order not being an array fix
---------------------------------------------------------------------------------------------------
Version: 1.0.1
* Initial release
---------------------------------------------------------------------------------------------------
Version: 1.0.0
* Initial release
---------------------------------------------------------------------------------------------------
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "game-mount-and-blade-ii-bannerlord-butr",
"version": "1.0.9",
"version": "1.0.10",
"description": "A Vortex extension for Mount and Blade II: Bannerlord mod management.",
"author": "BUTR Team & Nexus Mods",
"license": "GPL-3.0+",
Expand Down
14 changes: 0 additions & 14 deletions src/actions.ts

This file was deleted.

51 changes: 27 additions & 24 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// eslint-disable-next-line no-restricted-imports
import Bluebird, { Promise, method as toBluebird } from 'bluebird';
import path from 'path';
import { actions, selectors, types, util, log } from 'vortex-api';
import { setCurrentSave, setSortOnDeploy } from './actions';
import { selectors, types, log } from 'vortex-api';
import { GAME_ID } from './common';
import { BannerlordGame } from './game';
import {
Expand All @@ -14,9 +13,12 @@ import {
getInstallPathBLSE,
testBLSE,
installBLSE,
didPurgeBLSE,
didPurgeEvent,
didDeployEvent,
addedFiles,
SaveManager,
reducer,
actionsSettings,
} from './utils';
import { SaveList, SavePageOptions, Settings } from './views';
import { IAddedFiles } from './types';
Expand All @@ -27,25 +29,14 @@ const main = (context: types.IExtensionContext): boolean => {

const launcherManager = new VortexLauncherManager(context.api);

// Register Settings
const reducer: types.IReducerSpec = {
reducers: {
[setSortOnDeploy as never]: (state, payload) =>
util.setSafe(state, [`sortOnDeploy`, payload.profileId], payload.sort),
[actions.setLoadOrder as never]: (state, payload) => util.setSafe(state, [payload.id], payload.order),
[setCurrentSave as never]: (state, payload) => util.setSafe(state, [`saveList`], payload),
},
defaults: {
sortOnDeploy: {},
},
};

const getLOManager = () => LoadOrderManager.getInstance(context.api, launcherManager);
const getLoadOrderManager = () => LoadOrderManager.getInstance(context.api, launcherManager);
const getSaveManager = () => SaveManager.getInstance(context.api, launcherManager);

// Register Settings
context.registerReducer([`settings`, GAME_ID], reducer);

const settingsOnSetSortOnDeploy = (profileId: string, sort: boolean) =>
context.api.store?.dispatch(setSortOnDeploy(profileId, sort));
context.api.store?.dispatch(actionsSettings.setSortOnDeploy(profileId, sort));
const settingsProps = () => ({
t: context.api.translate,
onSetSortOnDeploy: settingsOnSetSortOnDeploy,
Expand Down Expand Up @@ -73,9 +64,14 @@ const main = (context: types.IExtensionContext): boolean => {
}
*/

context.registerLoadOrder(getLOManager());
context.registerLoadOrder(getLoadOrderManager());

context.registerMainPage('savegame', 'Saves', SaveList, new SavePageOptions(context, launcherManager));
context.registerMainPage(
'savegame',
'Saves',
SaveList,
new SavePageOptions(context, launcherManager, getSaveManager())
);

// Register Installer.
context.registerInstaller(
Expand Down Expand Up @@ -125,12 +121,17 @@ const main = (context: types.IExtensionContext): boolean => {
return;
}
try {
await getLOManager().deserializeLoadOrder();
return;
await getLoadOrderManager().deserializeLoadOrder();
} catch (err) {
context.api.showErrorNotification?.('Failed to deserialize load order file', err);
return;
}
try {
getSaveManager().reloadSave();
} catch (err) {
context.api.showErrorNotification?.('Failed to reload the currect save file', err);
return;
}
});

/*
Expand All @@ -154,9 +155,11 @@ const main = (context: types.IExtensionContext): boolean => {

// TODO: lister to profile switch events and check for BLSE
// Set BLSE CLI as primary tool on deployment if no primary tool is set
context.api.onAsync('did-deploy', (profileId: string) => didDeployEvent(context.api, profileId, getLOManager));
context.api.onAsync('did-deploy', (profileId: string) =>
didDeployEvent(context.api, profileId, getLoadOrderManager)
);
// Remove BLSE CLI as primary tool on purge if it is set
context.api.onAsync('did-purge', (profileId: string) => didPurgeBLSE(context.api, profileId));
context.api.onAsync('did-purge', (profileId: string) => didPurgeEvent(context.api, profileId));
})
);
// Register Callbacks
Expand Down
19 changes: 12 additions & 7 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,18 @@ export interface ISettingsInterfaceWithPrimaryTool extends types.ISettingsInterf
* Vortex
*/
export interface ISettingsWithBannerlord extends types.ISettings {
[GAME_ID]?: {
saveList?: {
saveName?: string;
};
sortOnDeploy: {
[profileId: string]: boolean;
};
[GAME_ID]?: IBannerlordSettings;
}

/**
* Vortex
*/
export interface IBannerlordSettings {
saveName: {
[profileId: string]: string | null;
};
sortOnDeploy: {
[profileId: string]: boolean;
};
}

Expand Down
29 changes: 15 additions & 14 deletions src/utils/blse/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,24 @@ import { LoadOrderManager } from '../loadOrder';
export const didDeployEvent = async (
api: types.IExtensionApi,
profileId: string,
getLOManager: () => LoadOrderManager
getLoadOrderManager: () => LoadOrderManager
) => {
const state = api.getState();
const profile = selectors.profileById(state, profileId);
if (profile.gameId !== GAME_ID) {
return Promise.resolve();
}

try {
await getLOManager().deserializeLoadOrder();
await getLoadOrderManager().deserializeLoadOrder();
} catch (err) {
api.showErrorNotification?.('Failed to deserialize load order file', err);
}

return didDeployBLSE(api, profileId);
return didDeployBLSE(api, state, profile);
};

/**
* Event function, be careful
*/
export const didDeployBLSE = async (api: types.IExtensionApi, profileId: string) => {
const state = api.getState();
const profile = selectors.profileById(state, profileId);
if (profile.gameId !== GAME_ID) {
return Promise.resolve();
}

const didDeployBLSE = async (api: types.IExtensionApi, state: types.IState, profile: types.IProfile) => {
if (!hasSettingsInterfacePrimaryTool(state.settings.interface)) {
return Promise.resolve();
}
Expand All @@ -51,13 +48,17 @@ export const didDeployBLSE = async (api: types.IExtensionApi, profileId: string)
/**
* Event function, be careful
*/
export const didPurgeBLSE = async (api: types.IExtensionApi, profileId: string) => {
export const didPurgeEvent = async (api: types.IExtensionApi, profileId: string) => {
const state = api.getState();
const profile = selectors.profileById(state, profileId);
if (profile.gameId !== GAME_ID) {
return Promise.resolve();
}

await didPurgeBLSE(api, state, profile);
};

const didPurgeBLSE = async (api: types.IExtensionApi, state: types.IState, profile: types.IProfile) => {
if (!hasSettingsInterfacePrimaryTool(state.settings.interface)) {
return Promise.resolve();
}
Expand Down
7 changes: 6 additions & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ export * from './blse';
export * from './butr';
export * from './loadOrder';
export * from './module';
export * from './redux';
export * from './save';
export * from './settings';
export * from './events';
export * from './game';
export * from './moduleUtil';
export * from './nameIn';
export * from './nameof';
export * from './reducers';
export * from './redux';
export * from './store';
export * from './tools';
export * from './util';
Expand Down
26 changes: 26 additions & 0 deletions src/utils/loadOrder/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// This is a risk, since we won't notice if the API changes
// TODO: Ask IDCs to provider a proper type system
import { types } from 'vortex-api';

export const setFBForceUpdate = (profileId: string) => ({
type: 'SET_FB_FORCE_UPDATE',
payload: {
profileId,
},
});

export const setFBLoadOrderEntry = (profileId: string, loEntry: types.ILoadOrderEntry) => ({
type: 'SET_FB_LOAD_ORDER_ENTRY',
payload: {
profileId,
loEntry,
},
});

export const setFBLoadOrder = (profileId: string, loadOrder: types.LoadOrder) => ({
type: 'SET_FB_LOAD_ORDER',
payload: {
profileId,
loadOrder,
},
});
1 change: 1 addition & 0 deletions src/utils/loadOrder/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * as actionsLoadOrder from './actions';
export * from './converter';
export * from './manager';
export * from './persistence';
12 changes: 4 additions & 8 deletions src/utils/loadOrder/manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import {
ModAnalyzerProxy,
VortexLauncherManager,
versionToString,
actionsLoadOrder,
} from '..';
import { GAME_ID } from '../../common';
import { LoadOrderInfoPanel, BannerlordItemRenderer } from '../../views';
import { IModuleCompatibilityInfoCache, RequiredProperties, VortexLoadOrderStorage } from '../../types';

export class LoadOrderManager implements types.ILoadOrderGameInfo {
private static _instance: LoadOrderManager;

private _api: types.IExtensionApi;
private _manager: VortexLauncherManager;
private _isInitialized = false;
Expand Down Expand Up @@ -91,14 +93,8 @@ export class LoadOrderManager implements types.ILoadOrderGameInfo {
}

private forceRefresh = (): void => {
const profileId = selectors.activeProfile(this._api.getState()).id;
const action = {
type: 'SET_FB_FORCE_UPDATE',
payload: {
profileId,
},
};
this._api.store?.dispatch(action);
const profile = selectors.activeProfile(this._api.getState());
this._api.store?.dispatch(actionsLoadOrder.setFBForceUpdate(profile.id));
};

public serializeLoadOrder = (loadOrder: VortexLoadOrderStorage): Promise<void> => {
Expand Down
22 changes: 0 additions & 22 deletions src/utils/nameIn.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/utils/nameof.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function nameof<TObject>(obj: TObject, key: keyof TObject): string;
export function nameof<TObject>(key: keyof TObject): string;
export function nameof(key1: unknown, key2?: unknown): unknown {
return key2 ?? key1;
}
39 changes: 39 additions & 0 deletions src/utils/reducers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { actions, types, util } from 'vortex-api';
import { actionsSettings, actionsSave, ReducerHandler, ReducerHandlerState, createReducer, nameof } from '.';
import { IBannerlordSettings } from '../types';

// TODO: Ask IDCs to provider a proper type system?
type SetLoadOrderPayload = {
id: string;
order: unknown[];
};

const setSaveInState = (state: ReducerHandlerState, payload: actionsSave.SetCurrentSavePayload) => {
return util.setSafe(state, [nameof<IBannerlordSettings>('saveName'), payload.profileId], payload.saveId);
};

const setSortOnDeployInState = (state: ReducerHandlerState, payload: actionsSettings.SetSortOnDeployPayload) => {
return util.setSafe(state, [nameof<IBannerlordSettings>('sortOnDeploy'), payload.profileId], payload.sort);
};

const setLoadOrderInState = (state: ReducerHandlerState, payload: SetLoadOrderPayload) => {
return util.setSafe(state, [payload.id], payload.order);
};

const getReducers = () => {
const reducers: { [key: string]: ReducerHandler<unknown> } = {};
createReducer(actionsSettings.setSortOnDeploy, setSortOnDeployInState, reducers);
createReducer(actions.setLoadOrder, setLoadOrderInState, reducers);
createReducer(actionsSave.setCurrentSave, setSaveInState, reducers);
return reducers;
};

const getDefaults = () => ({
[nameof<IBannerlordSettings>('sortOnDeploy')]: {},
[nameof<IBannerlordSettings>('saveName')]: {},
});

export const reducer: types.IReducerSpec = {
reducers: getReducers(),
defaults: getDefaults(),
};
15 changes: 15 additions & 0 deletions src/utils/redux.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { BaseActionCreator, ComplexActionCreator } from 'redux-act';

export type ReducerHandlerState = {
[key: string]: unknown;
};

export type ReducerHandler<P> = (state: ReducerHandlerState, payload: P) => ReducerHandlerState;

export const createReducer = <P, M>(
actionCreator: BaseActionCreator<ComplexActionCreator<P, M>>,
action: ReducerHandler<P>,
reducers: { [key: string]: ReducerHandler<P> }
) => {
reducers[actionCreator.getType()] = action;
};
Loading

0 comments on commit 17a2f23

Please sign in to comment.