mirror of
https://github.com/packwiz/packwiz-installer.git
synced 2025-04-18 20:46:30 +02:00
Improvements to MultiMC metadata updating
Reformatted and refactored names to fit Kotlin conventions Closed manifest file reader properly Fixed switching between loaders, improved intermediary logic Improved error messages
This commit is contained in:
parent
ab3de9a246
commit
02b01b90d7
@ -11,98 +11,109 @@ import java.io.File
|
||||
import java.nio.file.Paths
|
||||
|
||||
class LauncherUtils internal constructor(private val opts: UpdateManager.Options, val ui: IUserInterface) {
|
||||
enum class LauncherStatus {
|
||||
Succesful,
|
||||
NoChanges,
|
||||
Cancelled,
|
||||
NotFound, // We'll use the NotFound as the neutral return type for now
|
||||
}
|
||||
enum class LauncherStatus {
|
||||
SUCCESSFUL,
|
||||
NO_CHANGES,
|
||||
CANCELLED,
|
||||
NOT_FOUND, // When there is no mmc-pack.json file found (i.e. MultiMC is not being used)
|
||||
}
|
||||
|
||||
fun handleMultiMC(pf: PackFile, gson: Gson): LauncherStatus {
|
||||
// MultiMC MC and loader version checker
|
||||
val manifestPath = Paths.get(opts.multimcFolder, "mmc-pack.json").toString()
|
||||
val manifestFile = File(manifestPath)
|
||||
fun handleMultiMC(pf: PackFile, gson: Gson): LauncherStatus {
|
||||
// MultiMC MC and loader version checker
|
||||
val manifestPath = Paths.get(opts.multimcFolder, "mmc-pack.json").toString()
|
||||
val manifestFile = File(manifestPath)
|
||||
|
||||
if (!manifestFile.exists()) {
|
||||
return LauncherStatus.NotFound
|
||||
}
|
||||
if (!manifestFile.exists()) {
|
||||
return LauncherStatus.NOT_FOUND
|
||||
}
|
||||
|
||||
val multimcManifest = try {
|
||||
JsonParser.parseReader(manifestFile.reader())
|
||||
} catch (e: JsonIOException) {
|
||||
throw Exception("Cannot read the MultiMC pack file", e)
|
||||
} catch (e: JsonSyntaxException) {
|
||||
throw Exception("Invalid MultiMC pack file", e)
|
||||
}.asJsonObject
|
||||
val multimcManifest = manifestFile.reader().use {
|
||||
try {
|
||||
JsonParser.parseReader(it)
|
||||
} catch (e: JsonIOException) {
|
||||
throw Exception("Cannot read the MultiMC pack file", e)
|
||||
} catch (e: JsonSyntaxException) {
|
||||
throw Exception("Invalid MultiMC pack file", e)
|
||||
}.asJsonObject
|
||||
}
|
||||
|
||||
Log.info("Loaded MultiMC config")
|
||||
Log.info("Loaded MultiMC config")
|
||||
|
||||
// We only support format 1, if it gets updated in the future we'll have to handle that
|
||||
// There's only version 1 for now tho, so that's good
|
||||
if (multimcManifest["formatVersion"].asInt != 1) {
|
||||
throw Exception("Invalid MultiMC format version")
|
||||
}
|
||||
// We only support format 1, if it gets updated in the future we'll have to handle that
|
||||
// There's only version 1 for now tho, so that's good
|
||||
if (multimcManifest["formatVersion"]?.asInt != 1) {
|
||||
throw Exception("Unsupported MultiMC format version ${multimcManifest["formatVersion"]}")
|
||||
}
|
||||
|
||||
var manifestModified = false
|
||||
val modLoaders = hashMapOf("net.minecraft" to "minecraft", "net.minecraftforge" to "forge", "net.fabricmc.fabric-loader" to "fabric", "org.quiltmc.quilt-loader" to "quilt", "com.mumfrey.liteloader" to "liteloader")
|
||||
val modLoadersClasses = modLoaders.entries.associate{(k,v)-> v to k}
|
||||
var modLoaderFound = false
|
||||
val modLoadersFound = HashMap<String, String>() // Key: modLoader, Value: Version
|
||||
val components = multimcManifest["components"].asJsonArray
|
||||
for (componentObj in components) {
|
||||
val component = componentObj.asJsonObject
|
||||
var manifestModified = false
|
||||
val modLoaders = hashMapOf(
|
||||
"net.minecraft" to "minecraft",
|
||||
"net.minecraftforge" to "forge",
|
||||
"net.fabricmc.fabric-loader" to "fabric",
|
||||
"org.quiltmc.quilt-loader" to "quilt",
|
||||
"com.mumfrey.liteloader" to "liteloader")
|
||||
val modLoadersClasses = modLoaders.entries.associate{(k,v)-> v to k}
|
||||
val loaderVersionsFound = HashMap<String, String?>()
|
||||
val outdatedLoaders = mutableSetOf<String>()
|
||||
val components = multimcManifest["components"]?.asJsonArray ?: throw Exception("Invalid mmc-pack.json: no components key")
|
||||
components.removeAll {
|
||||
val component = it.asJsonObject
|
||||
|
||||
val version = component["version"].asString
|
||||
// If we find any of the modloaders we support, we save it and check the version
|
||||
if (modLoaders.containsKey(component["uid"].asString)) {
|
||||
val modLoader = modLoaders.getValue(component["uid"].asString)
|
||||
if (modLoader != "minecraft")
|
||||
modLoaderFound = true // Only set to true if modLoader isn't Minecraft
|
||||
modLoadersFound[modLoader] = version
|
||||
if (version != pf.versions?.get(modLoader)) {
|
||||
manifestModified = true
|
||||
component.addProperty("version", pf.versions?.get(modLoader))
|
||||
}
|
||||
}
|
||||
}
|
||||
val version = component["version"]?.asString
|
||||
// If we find any of the modloaders we support, we save it and check the version
|
||||
if (modLoaders.containsKey(component["uid"]?.asString)) {
|
||||
val modLoader = modLoaders.getValue(component["uid"]!!.asString)
|
||||
loaderVersionsFound[modLoader] = version
|
||||
if (version != pf.versions?.get(modLoader)) {
|
||||
outdatedLoaders.add(modLoader)
|
||||
true // Delete component; cached metadata is invalid and will be re-added
|
||||
} else {
|
||||
false // Already up to date; cached metadata is valid
|
||||
}
|
||||
} else { false } // Not a known loader / MC
|
||||
}
|
||||
|
||||
// If we can't find the mod loader in the MultiMC file, we add it
|
||||
if (!modLoaderFound) {
|
||||
// Using this filter and loop to handle multiple handlers
|
||||
for ((_, loader) in modLoaders
|
||||
.filter { it.value != "minecraft" && !modLoadersFound.containsKey(it.value) && pf.versions?.containsKey(it.value) == true }
|
||||
) {
|
||||
components.add(gson.toJsonTree(hashMapOf("uid" to modLoadersClasses.get(loader), "version" to pf.versions?.get(loader))))
|
||||
}
|
||||
}
|
||||
for ((_, loader) in modLoaders
|
||||
.filter {
|
||||
(!loaderVersionsFound.containsKey(it.value) || outdatedLoaders.contains(it.value))
|
||||
&& pf.versions?.containsKey(it.value) == true }
|
||||
) {
|
||||
manifestModified = true
|
||||
components.add(gson.toJsonTree(
|
||||
hashMapOf("uid" to modLoadersClasses[loader], "version" to pf.versions?.get(loader)))
|
||||
)
|
||||
}
|
||||
|
||||
// If mc version change detected, and fabric mappings are found, delete them, MultiMC will add and re-dl the correct one
|
||||
if (modLoadersFound["minecraft"] != pf.versions?.getValue("minecraft"))
|
||||
components.find { it.asJsonObject["uid"].asString == "net.fabricmc.intermediary" }?.asJsonObject?.let { components.remove(it) }
|
||||
// If inconsistent Intermediary mappings version is found, delete it - MultiMC will add and re-dl the correct one
|
||||
components.find { it.isJsonObject && it.asJsonObject["uid"]?.asString == "net.fabricmc.intermediary" }?.let {
|
||||
if (it.asJsonObject["version"]?.asString != pf.versions?.get("minecraft")) {
|
||||
components.remove(it)
|
||||
manifestModified = true
|
||||
}
|
||||
}
|
||||
|
||||
if (manifestModified) {
|
||||
// The manifest has been modified, so before saving it we'll ask the user
|
||||
// if they wanna update it, continue without updating it, or exit
|
||||
val oldVers = modLoadersFound.map { Pair(it.key, it.value) }
|
||||
val newVers = pf.versions!!.map { Pair(it.key, it.value) }
|
||||
if (manifestModified) {
|
||||
// The manifest has been modified, so before saving it we'll ask the user
|
||||
// if they wanna update it, continue without updating it, or exit
|
||||
val oldVers = loaderVersionsFound.map { Pair(it.key, it.value) }
|
||||
val newVers = pf.versions!!.map { Pair(it.key, it.value) }
|
||||
|
||||
when (ui.showUpdateConfirmationDialog(oldVers, newVers)) {
|
||||
IUserInterface.UpdateConfirmationResult.CANCELLED -> {
|
||||
return LauncherStatus.CANCELLED
|
||||
}
|
||||
IUserInterface.UpdateConfirmationResult.CONTINUE -> {
|
||||
return LauncherStatus.SUCCESSFUL
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
when (ui.showUpdateConfirmationDialog(oldVers, newVers)) {
|
||||
IUserInterface.UpdateConfirmationResult.CANCELLED -> {
|
||||
return LauncherStatus.Cancelled
|
||||
}
|
||||
IUserInterface.UpdateConfirmationResult.CONTINUE -> {
|
||||
return LauncherStatus.Succesful // Returning succesful as... Well, the user is telling us to continue
|
||||
}
|
||||
else -> {} // Compiler is giving warning about "non-exhaustive when", so i'll just add an empty one
|
||||
}
|
||||
manifestFile.writeText(gson.toJson(multimcManifest))
|
||||
Log.info("Successfully updated mmc-pack.json based on version metadata")
|
||||
|
||||
manifestFile.writeText(gson.toJson(multimcManifest))
|
||||
Log.info("Updated modpack Minecrafts and/or the modloaders version")
|
||||
return LauncherStatus.SUCCESSFUL
|
||||
}
|
||||
|
||||
return LauncherStatus.Succesful
|
||||
}
|
||||
|
||||
return LauncherStatus.NoChanges
|
||||
}
|
||||
return LauncherStatus.NO_CHANGES
|
||||
}
|
||||
}
|
@ -105,8 +105,9 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse
|
||||
ui.submitProgress(InstallProgress("Loading MultiMC pack file..."))
|
||||
try {
|
||||
when (lu.handleMultiMC(pf, gson)) {
|
||||
LauncherUtils.LauncherStatus.Cancelled -> cancelled = true
|
||||
LauncherUtils.LauncherStatus.NotFound -> Log.info("MultiMC not detected")
|
||||
LauncherUtils.LauncherStatus.CANCELLED -> cancelled = true
|
||||
LauncherUtils.LauncherStatus.NOT_FOUND -> Log.info("MultiMC not detected")
|
||||
else -> {}
|
||||
}
|
||||
handleCancellation()
|
||||
} catch (e: Exception) {
|
||||
|
@ -202,17 +202,16 @@ class GUIHandler : IUserInterface {
|
||||
|
||||
|
||||
val options = arrayOf("Cancel", "Continue anyways", "Update")
|
||||
val result = JOptionPane.showOptionDialog(frmPackwizlauncher,
|
||||
message,
|
||||
val result = JOptionPane.showOptionDialog(frmPackwizlauncher, message,
|
||||
"Updating MultiMC versions",
|
||||
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0])
|
||||
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[2])
|
||||
future.complete(
|
||||
when (result) {
|
||||
JOptionPane.CLOSED_OPTION, 0 -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
||||
1 -> IUserInterface.UpdateConfirmationResult.CONTINUE
|
||||
2 -> IUserInterface.UpdateConfirmationResult.UPDATE
|
||||
else -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
||||
}
|
||||
when (result) {
|
||||
JOptionPane.CLOSED_OPTION, 0 -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
||||
1 -> IUserInterface.UpdateConfirmationResult.CONTINUE
|
||||
2 -> IUserInterface.UpdateConfirmationResult.UPDATE
|
||||
else -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
||||
}
|
||||
)
|
||||
}
|
||||
return future.get()
|
||||
|
Loading…
x
Reference in New Issue
Block a user