-
Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathSMAPI.ts
90 lines (77 loc) · 3.23 KB
/
SMAPI.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { actions, types, selectors, util } from 'vortex-api';
import { GAME_ID } from './common';
import { gte } from 'semver';
import { SMAPI_MOD_ID, SMAPI_URL } from './constants';
export function findSMAPIMod(api: types.IExtensionApi): types.IMod {
const state = api.getState();
const profileId = selectors.lastActiveProfileForGame(state, GAME_ID);
const profile = selectors.profileById(state, profileId);
const isActive = (modId: string) => util.getSafe(profile, ['modState', modId, 'enabled'], false);
const isSMAPI = (mod: types.IMod) =>
mod.type === 'SMAPI' && mod.attributes?.modId === 2400;
const mods: { [modId: string]: types.IMod } = util.getSafe(state, ['persistent', 'mods', GAME_ID], {});
const SMAPIMods: types.IMod[] = Object.values(mods).filter((mod: types.IMod) =>
isSMAPI(mod) && isActive(mod.id));
return (SMAPIMods.length === 0)
? undefined
: SMAPIMods.length > 1
? SMAPIMods.reduce((prev, iter) => {
if (prev === undefined) {
return iter;
}
return (gte(iter.attributes.version ?? '0.0.0', prev.attributes.version ?? '0.0.0')) ? iter : prev;
}, undefined)
: SMAPIMods[0];
}
export async function deploySMAPI(api: types.IExtensionApi) {
await util.toPromise(cb => api.events.emit('deploy-mods', cb));
await util.toPromise(cb => api.events.emit('start-quick-discovery', () => cb(null)));
const discovery = selectors.discoveryByGame(api.getState(), GAME_ID);
const tool = discovery?.tools?.['smapi'];
if (tool) {
api.store.dispatch(actions.setPrimaryTool(GAME_ID, tool.id));
}
}
export async function downloadSMAPI(api: types.IExtensionApi, update?: boolean) {
api.dismissNotification('smapi-missing');
api.sendNotification({
id: 'smapi-installing',
message: update ? 'Updating SMAPI' : 'Installing SMAPI',
type: 'activity',
noDismiss: true,
allowSuppress: false,
});
if (api.ext?.ensureLoggedIn !== undefined) {
await api.ext.ensureLoggedIn();
}
try {
const modFiles = await api.ext.nexusGetModFiles(GAME_ID, SMAPI_MOD_ID);
const fileTime = (input: any) => Number.parseInt(input.uploaded_time, 10);
const file = modFiles
.filter(file => file.category_id === 1)
.sort((lhs, rhs) => fileTime(lhs) - fileTime(rhs))[0];
if (file === undefined) {
throw new util.ProcessCanceled('No SMAPI main file found');
}
const dlInfo = {
game: GAME_ID,
name: 'SMAPI',
};
const nxmUrl = `nxm://${GAME_ID}/mods/${SMAPI_MOD_ID}/files/${file.file_id}`;
const dlId = await util.toPromise<string>(cb =>
api.events.emit('start-download', [nxmUrl], dlInfo, undefined, cb, undefined, { allowInstall: false }));
const modId = await util.toPromise<string>(cb =>
api.events.emit('start-install-download', dlId, { allowAutoEnable: false }, cb));
const profileId = selectors.lastActiveProfileForGame(api.getState(), GAME_ID);
await actions.setModsEnabled(api, profileId, [modId], true, {
allowAutoDeploy: false,
installed: true,
});
await deploySMAPI(api);
} catch (err) {
api.showErrorNotification('Failed to download/install SMAPI', err);
util.opn(SMAPI_URL).catch(() => null);
} finally {
api.dismissNotification('smapi-installing');
}
}