|
1 |
| -import ManifestV2 from "src/model/ManifestV2"; |
2 | 1 | import ThunderstoreVersion from '../../model/ThunderstoreVersion';
|
3 |
| -import ThunderstoreMod from '../../model/ThunderstoreMod'; |
4 | 2 | import StatusEnum from '../../model/enums/StatusEnum';
|
5 | 3 | import axios, { AxiosResponse } from 'axios';
|
| 4 | +import ManifestV2 from "../../model/ManifestV2"; |
6 | 5 | import ThunderstoreCombo from '../../model/ThunderstoreCombo';
|
7 | 6 | import ZipExtract from '../installing/ZipExtract';
|
8 | 7 | import R2Error from '../../model/errors/R2Error';
|
@@ -83,71 +82,69 @@ export default class BetterThunderstoreDownloader extends ThunderstoreDownloader
|
83 | 82 | });
|
84 | 83 | }
|
85 | 84 |
|
86 |
| - public async download(profile: ImmutableProfile, mod: ThunderstoreMod, modVersion: ThunderstoreVersion, |
87 |
| - ignoreCache: boolean, |
88 |
| - callback: (progress: number, modName: string, status: number, err: R2Error | null) => void, |
89 |
| - completedCallback: (modList: ThunderstoreCombo[]) => void) { |
| 85 | + public async download( |
| 86 | + profile: ImmutableProfile, |
| 87 | + combo: ThunderstoreCombo, |
| 88 | + ignoreCache: boolean, |
| 89 | + totalProgressCallback: (progress: number, modName: string, status: number, err: R2Error | null) => void |
| 90 | + ): Promise<ThunderstoreCombo[]> { |
90 | 91 |
|
91 | 92 | const modList = await ProfileModList.getModList(profile);
|
92 | 93 | if (modList instanceof R2Error) {
|
93 |
| - return callback(0, mod.getName(), StatusEnum.FAILURE, modList); |
| 94 | + totalProgressCallback(0, combo.getMod().getName(), StatusEnum.FAILURE, modList); |
| 95 | + throw modList; |
94 | 96 | }
|
95 | 97 |
|
96 |
| - let dependencies: ThunderstoreCombo[] = []; |
97 |
| - await this.buildDependencySet(modVersion, dependencies, DependencySetBuilderMode.USE_EXACT_VERSION); |
98 |
| - this.sortDependencyOrder(dependencies); |
99 |
| - const combo = new ThunderstoreCombo(); |
100 |
| - combo.setMod(mod); |
101 |
| - combo.setVersion(modVersion); |
102 |
| - |
103 |
| - dependencies = await this.determineDependencyVersions(dependencies, combo, modVersion, modList); |
104 |
| - let downloadableDependencySize = this.calculateInitialDownloadSize(dependencies); |
| 98 | + const dependencies = await this.getDependenciesWithCorrectVersions(combo, modList); |
| 99 | + const allModsToDownload = [...dependencies, combo]; |
105 | 100 |
|
106 | 101 | let downloadCount = 0;
|
107 |
| - await this.downloadAndSave(combo, ignoreCache, async (progress: number, status: number, err: R2Error | null) => { |
| 102 | + const singleModProgressCallback = (progress: number, status: number, err: R2Error | null) => { |
108 | 103 | if (status === StatusEnum.FAILURE) {
|
109 |
| - callback(0, mod.getName(), status, err); |
110 |
| - } else if (status === StatusEnum.PENDING) { |
111 |
| - callback(this.generateProgressPercentage(progress, downloadCount, downloadableDependencySize + 1), mod.getName(), status, err); |
| 104 | + throw err; |
| 105 | + } |
| 106 | + |
| 107 | + let totalProgress: number; |
| 108 | + if (status === StatusEnum.PENDING) { |
| 109 | + totalProgress = this.generateProgressPercentage(progress, downloadCount, allModsToDownload.length); |
112 | 110 | } else if (status === StatusEnum.SUCCESS) {
|
| 111 | + totalProgress = this.generateProgressPercentage(100, downloadCount, allModsToDownload.length); |
113 | 112 | downloadCount += 1;
|
114 |
| - // If no dependencies, end here. |
115 |
| - if (dependencies.length === 0) { |
116 |
| - callback(100, mod.getName(), StatusEnum.PENDING, err); |
117 |
| - completedCallback([combo]); |
118 |
| - return; |
119 |
| - } |
| 113 | + } else { |
| 114 | + console.error(`Ignore unknown status code "${status}"`); |
| 115 | + return; |
| 116 | + } |
| 117 | + totalProgressCallback(totalProgress, combo.getMod().getName(), status, err); |
| 118 | + } |
120 | 119 |
|
121 |
| - // If dependencies, queue and download. |
122 |
| - await this.queueDownloadDependencies(dependencies.entries(), ignoreCache, (progress: number, modName: string, status: number, err: R2Error | null) => { |
123 |
| - if (status === StatusEnum.FAILURE) { |
124 |
| - callback(0, modName, status, err); |
125 |
| - } else if (status === StatusEnum.PENDING) { |
126 |
| - callback(this.generateProgressPercentage(progress, downloadCount, downloadableDependencySize + 1), modName, status, err); |
127 |
| - } else if (status === StatusEnum.SUCCESS) { |
128 |
| - callback(this.generateProgressPercentage(progress, downloadCount, downloadableDependencySize + 1), modName, StatusEnum.PENDING, err); |
129 |
| - downloadCount += 1; |
130 |
| - if (downloadCount >= dependencies.length + 1) { |
131 |
| - callback(100, modName, StatusEnum.PENDING, err); |
132 |
| - completedCallback([...dependencies, combo]); |
133 |
| - } |
134 |
| - } |
135 |
| - }); |
| 120 | + for (const combo of allModsToDownload) { |
| 121 | + if (!ignoreCache && await this.isVersionAlreadyDownloaded(combo)) { |
| 122 | + totalProgressCallback(100, combo.getMod().getName(), StatusEnum.SUCCESS, null); |
| 123 | + continue; |
136 | 124 | }
|
137 |
| - }) |
| 125 | + |
| 126 | + try { |
| 127 | + const response = await this._downloadCombo(combo, singleModProgressCallback); |
| 128 | + await this._saveDownloadResponse(response, combo, singleModProgressCallback); |
| 129 | + } catch(e) { |
| 130 | + throw R2Error.fromThrownValue(e, `Failed to download mod ${combo.getVersion().getFullName()}`); |
| 131 | + } |
| 132 | + } |
| 133 | + return allModsToDownload; |
138 | 134 | }
|
139 | 135 |
|
140 | 136 | // If combo is a modpack, use the modpack's dependency versions. If it isn't, get the latest versions.
|
141 |
| - public async determineDependencyVersions(dependencies: ThunderstoreCombo[], combo: ThunderstoreCombo, modVersion: ThunderstoreVersion, modList: ManifestV2[]) { |
142 |
| - let isModpack = combo.getMod().getCategories().find(value => value === "Modpacks") !== undefined; |
143 |
| - if (isModpack) { |
144 |
| - return dependencies; |
145 |
| - } |
146 |
| - dependencies = []; |
147 |
| - await this.buildDependencySet(modVersion, dependencies, DependencySetBuilderMode.USE_LATEST_VERSION); |
| 137 | + private async getDependenciesWithCorrectVersions(combo: ThunderstoreCombo, modList: ManifestV2[]) { |
| 138 | + const dependencies: ThunderstoreCombo[] = []; |
| 139 | + const isModpack = combo.getMod().getCategories().some(value => value === "Modpacks"); |
| 140 | + const versionMode = isModpack ? DependencySetBuilderMode.USE_EXACT_VERSION : DependencySetBuilderMode.USE_LATEST_VERSION; |
| 141 | + |
| 142 | + await this.buildDependencySet(combo.getVersion(), dependencies, versionMode); |
148 | 143 | this.sortDependencyOrder(dependencies);
|
149 | 144 | // #270: Remove already-installed dependencies to prevent updating.
|
150 |
| - return dependencies.filter(dep => modList.find(installed => installed.getName() === dep.getMod().getFullName()) === undefined); |
| 145 | + return dependencies.filter((dep) => { |
| 146 | + return !(modList.some(installed => installed.getName() === dep.getMod().getFullName())); |
| 147 | + }); |
151 | 148 | }
|
152 | 149 |
|
153 | 150 | public async downloadImportedMods(
|
|
0 commit comments