diff --git a/xmcl-keystone-ui/src/composables/instanceVersionDiagnose.ts b/xmcl-keystone-ui/src/composables/instanceVersionDiagnose.ts index 907bbe90f..00d0564e1 100644 --- a/xmcl-keystone-ui/src/composables/instanceVersionDiagnose.ts +++ b/xmcl-keystone-ui/src/composables/instanceVersionDiagnose.ts @@ -98,7 +98,7 @@ export function useInstanceVersionDiagnose(runtime: Ref, resolv if (librariesIssue.length > 0) { const options = { named: { count: librariesIssue.length } } ops.push(async () => { - await installLibraries(librariesIssue.map(v => v.library)) + await installLibraries(librariesIssue.map(v => v.library), version.id, librariesIssue.length < 15) }) items.push(librariesIssue.some(v => v.type === 'corrupted') ? reactive({ @@ -117,7 +117,7 @@ export function useInstanceVersionDiagnose(runtime: Ref, resolv if (assetsIssue.length > 0) { const options = { named: { count: assetsIssue.length } } ops.push(async () => { - await installAssets(assetsIssue.map(v => v.asset)) + await installAssets(assetsIssue.map(v => v.asset), version.id, assetsIssue.length < 15) }) items.push(assetsIssue.some(v => v.type === 'corrupted') ? reactive({ diff --git a/xmcl-runtime-api/src/services/InstallService.ts b/xmcl-runtime-api/src/services/InstallService.ts index a8d94260b..b20c3a9d0 100644 --- a/xmcl-runtime-api/src/services/InstallService.ts +++ b/xmcl-runtime-api/src/services/InstallService.ts @@ -152,7 +152,7 @@ export interface InstallService { * Install assets to the version * @param version The local version id */ - installAssets(assets: Asset[]): Promise + installAssets(assets: Asset[], version?: string, force?: boolean): Promise /** * Download and install a minecraft version */ @@ -160,7 +160,7 @@ export interface InstallService { /** * Install provided libraries to game. */ - installLibraries(libraries: InstallableLibrary[]): Promise + installLibraries(libraries: InstallableLibrary[], version?: string, force?: boolean): Promise /** * Install neoForged to the minecraft */ diff --git a/xmcl-runtime/lib/services/InstallService.ts b/xmcl-runtime/lib/services/InstallService.ts index 6b984c968..c954b4cb5 100644 --- a/xmcl-runtime/lib/services/InstallService.ts +++ b/xmcl-runtime/lib/services/InstallService.ts @@ -7,7 +7,7 @@ import { AbortableTask, task } from '@xmcl/task' import { XMLParser } from 'fast-xml-parser' import { existsSync } from 'fs' import { ensureFile } from 'fs-extra/esm' -import { readFile, writeFile } from 'fs/promises' +import { readFile, unlink, writeFile } from 'fs/promises' import { Dispatcher, errors, request } from 'undici' import { URL } from 'url' import { LauncherApp } from '../app/LauncherApp' @@ -503,10 +503,22 @@ export class InstallService extends AbstractService implements IInstallService { } @Lock(LockKey.assets) - async installAssets(assets: Asset[], version?: string) { + async installAssets(assets: Asset[], version?: string, force?: boolean) { const option = this.getInstallOptions() const location = this.getPath() - const task = installResolvedAssetsTask(assets, new MinecraftFolder(location), option).setName('installAssets', { id: version }) + const folder = new MinecraftFolder(location) + if (force) { + // Remove assets before download + const promises = [] as Promise[] + for (const a of assets) { + const path = folder.getAsset(a.hash) + if (path) { + promises.push(unlink(path).catch(() => { })) + } + } + await Promise.all(promises) + } + const task = installResolvedAssetsTask(assets, folder, option).setName('installAssets', { id: version }) await this.submit(task) } @@ -538,7 +550,7 @@ export class InstallService extends AbstractService implements IInstallService { } @Lock(LockKey.libraries) - async installLibraries(libraries: InstallableLibrary[], version?: string) { + async installLibraries(libraries: InstallableLibrary[], version?: string, force?: boolean) { let resolved: ResolvedLibrary[] if ('downloads' in libraries[0]) { resolved = Version.resolveLibraries(libraries) @@ -546,8 +558,20 @@ export class InstallService extends AbstractService implements IInstallService { resolved = libraries as any } const option = this.getInstallOptions() - const task = installResolvedLibrariesTask(resolved, this.getPath(), option).setName('installLibraries', { id: version }) + const folder = MinecraftFolder.from(this.getPath()) + const task = installResolvedLibrariesTask(resolved, folder, option).setName('installLibraries', { id: version }) try { + if (force) { + // remove lib before download + const promises = [] as Promise[] + for (const lib of resolved) { + const path = folder.getLibraryByPath(lib.path) + if (path) { + promises.push(unlink(path).catch(() => { })) + } + } + await Promise.all(promises) + } await this.submit(task) } catch (e) { this.warn('An error ocurred during install libraries:')