mirror of
				https://github.com/packwiz/packwiz-installer.git
				synced 2025-10-31 19:04:32 +01:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 7420866dfc | ||
|  | 1ebb28c3cc | ||
|  | c9543f74ee | 
| @@ -21,6 +21,7 @@ import java.nio.file.StandardCopyOption | |||||||
|  |  | ||||||
| internal class DownloadTask private constructor(val metadata: IndexFile.File, val index: IndexFile, private val downloadSide: Side) : IOptionDetails { | internal class DownloadTask private constructor(val metadata: IndexFile.File, val index: IndexFile, private val downloadSide: Side) : IOptionDetails { | ||||||
| 	var cachedFile: ManifestFile.File? = null | 	var cachedFile: ManifestFile.File? = null | ||||||
|  | 		private set | ||||||
|  |  | ||||||
| 	private var err: Exception? = null | 	private var err: Exception? = null | ||||||
| 	val exceptionDetails get() = err?.let { e -> ExceptionDetails(name, e) } | 	val exceptionDetails get() = err?.let { e -> ExceptionDetails(name, e) } | ||||||
| @@ -28,10 +29,24 @@ internal class DownloadTask private constructor(val metadata: IndexFile.File, va | |||||||
| 	fun failed() = err != null | 	fun failed() = err != null | ||||||
|  |  | ||||||
| 	var alreadyUpToDate = false | 	var alreadyUpToDate = false | ||||||
|  | 		private set | ||||||
| 	private var metadataRequired = true | 	private var metadataRequired = true | ||||||
| 	private var invalidated = false | 	private var invalidated = false | ||||||
| 	// If file is new or isOptional changed to true, the option needs to be presented again | 	// If file is new or isOptional changed to true, the option needs to be presented again | ||||||
| 	private var newOptional = true | 	private var newOptional = true | ||||||
|  | 	var completionStatus = CompletionStatus.INCOMPLETE | ||||||
|  | 		private set | ||||||
|  |  | ||||||
|  | 	enum class CompletionStatus { | ||||||
|  | 		INCOMPLETE, | ||||||
|  | 		DOWNLOADED, | ||||||
|  | 		ALREADY_EXISTS_CACHED, | ||||||
|  | 		ALREADY_EXISTS_VALIDATED, | ||||||
|  | 		SKIPPED_DISABLED, | ||||||
|  | 		SKIPPED_WRONG_SIDE, | ||||||
|  | 		DELETED_DISABLED, | ||||||
|  | 		DELETED_WRONG_SIDE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	val isOptional get() = metadata.linkedFile?.option?.optional ?: false | 	val isOptional get() = metadata.linkedFile?.option?.optional ?: false | ||||||
|  |  | ||||||
| @@ -76,6 +91,7 @@ internal class DownloadTask private constructor(val metadata: IndexFile.File, va | |||||||
| 			if (currHash == cachedFile.hash) { // Already up to date | 			if (currHash == cachedFile.hash) { // Already up to date | ||||||
| 				alreadyUpToDate = true | 				alreadyUpToDate = true | ||||||
| 				metadataRequired = false | 				metadataRequired = false | ||||||
|  | 				completionStatus = CompletionStatus.ALREADY_EXISTS_CACHED | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (cachedFile.isOptional) { | 		if (cachedFile.isOptional) { | ||||||
| @@ -143,6 +159,7 @@ internal class DownloadTask private constructor(val metadata: IndexFile.File, va | |||||||
| 					fileSource.buffer().readAll(blackholeSink()) | 					fileSource.buffer().readAll(blackholeSink()) | ||||||
| 					if (hash == fileSource.hash) { | 					if (hash == fileSource.hash) { | ||||||
| 						alreadyUpToDate = true | 						alreadyUpToDate = true | ||||||
|  | 						completionStatus = CompletionStatus.ALREADY_EXISTS_VALIDATED | ||||||
|  |  | ||||||
| 						// Update the manifest file | 						// Update the manifest file | ||||||
| 						cachedFile = (cachedFile ?: ManifestFile.File()).also { | 						cachedFile = (cachedFile ?: ManifestFile.File()).also { | ||||||
| @@ -181,10 +198,18 @@ internal class DownloadTask private constructor(val metadata: IndexFile.File, va | |||||||
| 				if (it.cachedLocation != null) { | 				if (it.cachedLocation != null) { | ||||||
| 					// Ensure wrong-side or optional false files are removed | 					// Ensure wrong-side or optional false files are removed | ||||||
| 					try { | 					try { | ||||||
| 						Files.deleteIfExists(it.cachedLocation!!.nioPath) | 						completionStatus = if (Files.deleteIfExists(it.cachedLocation!!.nioPath)) { | ||||||
|  | 							if (correctSide()) { CompletionStatus.DELETED_DISABLED } else { CompletionStatus.DELETED_WRONG_SIDE } | ||||||
|  | 						} else { | ||||||
|  | 							if (correctSide()) { CompletionStatus.SKIPPED_DISABLED } else { CompletionStatus.SKIPPED_WRONG_SIDE } | ||||||
|  | 						} | ||||||
| 					} catch (e: IOException) { | 					} catch (e: IOException) { | ||||||
| 						Log.warn("Failed to delete file", e) | 						Log.warn("Failed to delete file", e) | ||||||
| 					} | 					} | ||||||
|  | 				} else { | ||||||
|  | 					completionStatus = | ||||||
|  | 						if (correctSide()) { CompletionStatus.SKIPPED_DISABLED } | ||||||
|  | 						else { CompletionStatus.SKIPPED_WRONG_SIDE } | ||||||
| 				} | 				} | ||||||
| 				it.cachedLocation = null | 				it.cachedLocation = null | ||||||
| 				return | 				return | ||||||
| @@ -284,6 +309,8 @@ internal class DownloadTask private constructor(val metadata: IndexFile.File, va | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		completionStatus = CompletionStatus.DOWNLOADED | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	companion object { | 	companion object { | ||||||
|   | |||||||
| @@ -48,6 +48,7 @@ class LauncherUtils internal constructor(private val opts: UpdateManager.Options | |||||||
| 		val modLoaders = hashMapOf( | 		val modLoaders = hashMapOf( | ||||||
| 			"net.minecraft" to "minecraft", | 			"net.minecraft" to "minecraft", | ||||||
| 			"net.minecraftforge" to "forge", | 			"net.minecraftforge" to "forge", | ||||||
|  | 			"net.neoforged" to "neoforge", | ||||||
| 			"net.fabricmc.fabric-loader" to "fabric", | 			"net.fabricmc.fabric-loader" to "fabric", | ||||||
| 			"org.quiltmc.quilt-loader" to "quilt", | 			"org.quiltmc.quilt-loader" to "quilt", | ||||||
| 			"com.mumfrey.liteloader" to "liteloader" | 			"com.mumfrey.liteloader" to "liteloader" | ||||||
| @@ -59,6 +60,7 @@ class LauncherUtils internal constructor(private val opts: UpdateManager.Options | |||||||
| 			"org.lwjgl" to -1, | 			"org.lwjgl" to -1, | ||||||
| 			"org.lwjgl3" to -1, | 			"org.lwjgl3" to -1, | ||||||
| 			"net.minecraftforge" to 5, | 			"net.minecraftforge" to 5, | ||||||
|  | 			"net.neoforged" to 5, | ||||||
| 			"net.fabricmc.fabric-loader" to 10, | 			"net.fabricmc.fabric-loader" to 10, | ||||||
| 			"org.quiltmc.quilt-loader" to 10, | 			"org.quiltmc.quilt-loader" to 10, | ||||||
| 			"com.mumfrey.liteloader" to 10, | 			"com.mumfrey.liteloader" to 10, | ||||||
|   | |||||||
| @@ -127,40 +127,44 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse | |||||||
|  |  | ||||||
| 		ui.submitProgress(InstallProgress("Checking local files...")) | 		ui.submitProgress(InstallProgress("Checking local files...")) | ||||||
|  |  | ||||||
| 		// Invalidation checking must be done here, as it must happen before pack/index hashes are checked | 		// If the side changes, invalidate EVERYTHING (even when the index hasn't changed) | ||||||
|  | 		val invalidateAll = opts.side != manifest.cachedSide | ||||||
| 		val invalidatedUris: MutableList<PackwizFilePath> = ArrayList() | 		val invalidatedUris: MutableList<PackwizFilePath> = ArrayList() | ||||||
| 		for ((fileUri, file) in manifest.cachedFiles) { | 		if (!invalidateAll) { | ||||||
| 			// ignore onlyOtherSide files | 			// Invalidation checking must be done here, as it must happen before pack/index hashes are checked | ||||||
| 			if (file.onlyOtherSide) { | 			for ((fileUri, file) in manifest.cachedFiles) { | ||||||
| 				continue | 				// ignore onlyOtherSide files | ||||||
| 			} | 				if (file.onlyOtherSide) { | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 			var invalid = false | 				var invalid = false | ||||||
| 			// if isn't optional, or is optional but optionValue == true | 				// if isn't optional, or is optional but optionValue == true | ||||||
| 			if (!file.isOptional || file.optionValue) { | 				if (!file.isOptional || file.optionValue) { | ||||||
| 				if (file.cachedLocation != null) { | 					if (file.cachedLocation != null) { | ||||||
| 					if (!file.cachedLocation!!.nioPath.toFile().exists()) { | 						if (!file.cachedLocation!!.nioPath.toFile().exists()) { | ||||||
|  | 							invalid = true | ||||||
|  | 						} | ||||||
|  | 					} else { | ||||||
|  | 						// if cachedLocation == null, should probably be installed!! | ||||||
| 						invalid = true | 						invalid = true | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} | ||||||
| 					// if cachedLocation == null, should probably be installed!! | 				if (invalid) { | ||||||
| 					invalid = true | 					Log.info("File ${fileUri.filename} invalidated, marked for redownloading") | ||||||
|  | 					invalidatedUris.add(fileUri) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if (invalid) { |  | ||||||
| 				Log.info("File ${fileUri.filename} invalidated, marked for redownloading") |  | ||||||
| 				invalidatedUris.add(fileUri) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (manifest.packFileHash?.let { it == packFileSource.hash } == true && invalidatedUris.isEmpty()) { | 			if (manifest.packFileHash?.let { it == packFileSource.hash } == true && invalidatedUris.isEmpty()) { | ||||||
| 			// todo: --force? | 				// todo: --force? | ||||||
| 			ui.submitProgress(InstallProgress("Modpack is already up to date!", 1, 1)) | 				ui.submitProgress(InstallProgress("Modpack is already up to date!", 1, 1)) | ||||||
| 			if (manifest.cachedFiles.any { it.value.isOptional }) { | 				if (manifest.cachedFiles.any { it.value.isOptional }) { | ||||||
| 				ui.awaitOptionalButton(false, opts.timeout) | 					ui.awaitOptionalButton(false, opts.timeout) | ||||||
| 			} | 				} | ||||||
| 			if (!ui.optionsButtonPressed) { | 				if (!ui.optionsButtonPressed) { | ||||||
| 				return | 					return | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -177,6 +181,7 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse | |||||||
| 				pf.index.hashFormat, | 				pf.index.hashFormat, | ||||||
| 				manifest, | 				manifest, | ||||||
| 				invalidatedUris, | 				invalidatedUris, | ||||||
|  | 				invalidateAll, | ||||||
| 				clientHolder | 				clientHolder | ||||||
| 			) | 			) | ||||||
| 		} catch (e1: Exception) { | 		} catch (e1: Exception) { | ||||||
| @@ -202,18 +207,20 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	private fun processIndex(indexUri: PackwizPath<*>, indexHash: Hash<*>, hashFormat: HashFormat<*>, manifest: ManifestFile, invalidatedFiles: List<PackwizFilePath>, clientHolder: ClientHolder) { | 	private fun processIndex(indexUri: PackwizPath<*>, indexHash: Hash<*>, hashFormat: HashFormat<*>, manifest: ManifestFile, invalidatedFiles: List<PackwizFilePath>, invalidateAll: Boolean, clientHolder: ClientHolder) { | ||||||
| 		if (manifest.indexFileHash == indexHash && invalidatedFiles.isEmpty()) { | 		if (!invalidateAll) { | ||||||
| 			ui.submitProgress(InstallProgress("Modpack files are already up to date!", 1, 1)) | 			if (manifest.indexFileHash == indexHash && invalidatedFiles.isEmpty()) { | ||||||
| 			if (manifest.cachedFiles.any { it.value.isOptional }) { | 				ui.submitProgress(InstallProgress("Modpack files are already up to date!", 1, 1)) | ||||||
| 				ui.awaitOptionalButton(false, opts.timeout) | 				if (manifest.cachedFiles.any { it.value.isOptional }) { | ||||||
| 			} | 					ui.awaitOptionalButton(false, opts.timeout) | ||||||
| 			if (!ui.optionsButtonPressed) { | 				} | ||||||
| 				return | 				if (!ui.optionsButtonPressed) { | ||||||
| 			} | 					return | ||||||
| 			if (ui.cancelButtonPressed) { | 				} | ||||||
| 				showCancellationDialog() | 				if (ui.cancelButtonPressed) { | ||||||
| 				return | 					showCancellationDialog() | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		manifest.indexFileHash = indexHash | 		manifest.indexFileHash = indexHash | ||||||
| @@ -240,31 +247,17 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		ui.submitProgress(InstallProgress("Checking local files...")) | 		ui.submitProgress(InstallProgress("Checking local files...")) | ||||||
| 		// TODO: use kotlin filtering/FP rather than an iterator? |  | ||||||
| 		val it: MutableIterator<Map.Entry<PackwizFilePath, ManifestFile.File>> = manifest.cachedFiles.entries.iterator() | 		val it: MutableIterator<Map.Entry<PackwizFilePath, ManifestFile.File>> = manifest.cachedFiles.entries.iterator() | ||||||
| 		while (it.hasNext()) { | 		while (it.hasNext()) { | ||||||
| 			val (uri, file) = it.next() | 			val (uri, file) = it.next() | ||||||
| 			if (file.cachedLocation != null) { | 			if (file.cachedLocation != null) { | ||||||
| 				var alreadyDeleted = false | 				if (indexFile.files.none { it.file.rebase(opts.packFolder) == uri }) { // File has been removed from the index | ||||||
| 				// Delete if option value has been set to false |  | ||||||
| 				if (file.isOptional && !file.optionValue) { |  | ||||||
| 					try { | 					try { | ||||||
| 						Files.deleteIfExists(file.cachedLocation!!.nioPath) | 						Files.deleteIfExists(file.cachedLocation!!.nioPath) | ||||||
| 					} catch (e: IOException) { | 					} catch (e: IOException) { | ||||||
| 						Log.warn("Failed to delete optional disabled file", e) | 						Log.warn("Failed to delete file removed from index", e) | ||||||
| 					} |  | ||||||
| 					// Set to null, as it doesn't exist anymore |  | ||||||
| 					file.cachedLocation = null |  | ||||||
| 					alreadyDeleted = true |  | ||||||
| 				} |  | ||||||
| 				if (indexFile.files.none { it.file.rebase(opts.packFolder) == uri }) { // File has been removed from the index |  | ||||||
| 					if (!alreadyDeleted) { |  | ||||||
| 						try { |  | ||||||
| 							Files.deleteIfExists(file.cachedLocation!!.nioPath) |  | ||||||
| 						} catch (e: IOException) { |  | ||||||
| 							Log.warn("Failed to delete file removed from index", e) |  | ||||||
| 						} |  | ||||||
| 					} | 					} | ||||||
|  | 					Log.info("Deleted ${file.cachedLocation!!.filename} (removed from pack)") | ||||||
| 					it.remove() | 					it.remove() | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @@ -281,9 +274,6 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse | |||||||
| 			Log.warn("Index is empty!") | 			Log.warn("Index is empty!") | ||||||
| 		} | 		} | ||||||
| 		val tasks = createTasksFromIndex(indexFile, opts.side) | 		val tasks = createTasksFromIndex(indexFile, opts.side) | ||||||
| 		// If the side changes, invalidate EVERYTHING just in case |  | ||||||
| 		// Might not be needed, but done just to be safe |  | ||||||
| 		val invalidateAll = opts.side != manifest.cachedSide |  | ||||||
| 		if (invalidateAll) { | 		if (invalidateAll) { | ||||||
| 			Log.info("Side changed, invalidating all mods") | 			Log.info("Side changed, invalidating all mods") | ||||||
| 		} | 		} | ||||||
| @@ -397,7 +387,16 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse | |||||||
| 			val progress = if (exDetails != null) { | 			val progress = if (exDetails != null) { | ||||||
| 				"Failed to download ${exDetails.name}: ${exDetails.exception.message}" | 				"Failed to download ${exDetails.name}: ${exDetails.exception.message}" | ||||||
| 			} else { | 			} else { | ||||||
| 				"Downloaded ${task.name}" | 				when (task.completionStatus) { | ||||||
|  | 					DownloadTask.CompletionStatus.INCOMPLETE -> "${task.name} pending (you should never see this...)" | ||||||
|  | 					DownloadTask.CompletionStatus.DOWNLOADED -> "Downloaded ${task.name}" | ||||||
|  | 					DownloadTask.CompletionStatus.ALREADY_EXISTS_CACHED -> "${task.name} already exists (cached)" | ||||||
|  | 					DownloadTask.CompletionStatus.ALREADY_EXISTS_VALIDATED -> "${task.name} already exists (validated)" | ||||||
|  | 					DownloadTask.CompletionStatus.SKIPPED_DISABLED -> "Skipped ${task.name} (disabled)" | ||||||
|  | 					DownloadTask.CompletionStatus.SKIPPED_WRONG_SIDE -> "Skipped ${task.name} (wrong side)" | ||||||
|  | 					DownloadTask.CompletionStatus.DELETED_DISABLED -> "Deleted ${task.name} (disabled)" | ||||||
|  | 					DownloadTask.CompletionStatus.DELETED_WRONG_SIDE -> "Deleted ${task.name} (wrong side)" | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 			ui.submitProgress(InstallProgress(progress, i + 1, tasks.size)) | 			ui.submitProgress(InstallProgress(progress, i + 1, tasks.size)) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user