mirror of
https://github.com/packwiz/packwiz-installer.git
synced 2025-04-19 21:16: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
|
import java.nio.file.Paths
|
||||||
|
|
||||||
class LauncherUtils internal constructor(private val opts: UpdateManager.Options, val ui: IUserInterface) {
|
class LauncherUtils internal constructor(private val opts: UpdateManager.Options, val ui: IUserInterface) {
|
||||||
enum class LauncherStatus {
|
enum class LauncherStatus {
|
||||||
Succesful,
|
SUCCESSFUL,
|
||||||
NoChanges,
|
NO_CHANGES,
|
||||||
Cancelled,
|
CANCELLED,
|
||||||
NotFound, // We'll use the NotFound as the neutral return type for now
|
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 {
|
fun handleMultiMC(pf: PackFile, gson: Gson): LauncherStatus {
|
||||||
// MultiMC MC and loader version checker
|
// MultiMC MC and loader version checker
|
||||||
val manifestPath = Paths.get(opts.multimcFolder, "mmc-pack.json").toString()
|
val manifestPath = Paths.get(opts.multimcFolder, "mmc-pack.json").toString()
|
||||||
val manifestFile = File(manifestPath)
|
val manifestFile = File(manifestPath)
|
||||||
|
|
||||||
if (!manifestFile.exists()) {
|
if (!manifestFile.exists()) {
|
||||||
return LauncherStatus.NotFound
|
return LauncherStatus.NOT_FOUND
|
||||||
}
|
}
|
||||||
|
|
||||||
val multimcManifest = try {
|
val multimcManifest = manifestFile.reader().use {
|
||||||
JsonParser.parseReader(manifestFile.reader())
|
try {
|
||||||
} catch (e: JsonIOException) {
|
JsonParser.parseReader(it)
|
||||||
throw Exception("Cannot read the MultiMC pack file", e)
|
} catch (e: JsonIOException) {
|
||||||
} catch (e: JsonSyntaxException) {
|
throw Exception("Cannot read the MultiMC pack file", e)
|
||||||
throw Exception("Invalid MultiMC pack file", e)
|
} catch (e: JsonSyntaxException) {
|
||||||
}.asJsonObject
|
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
|
// 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
|
// There's only version 1 for now tho, so that's good
|
||||||
if (multimcManifest["formatVersion"].asInt != 1) {
|
if (multimcManifest["formatVersion"]?.asInt != 1) {
|
||||||
throw Exception("Invalid MultiMC format version")
|
throw Exception("Unsupported MultiMC format version ${multimcManifest["formatVersion"]}")
|
||||||
}
|
}
|
||||||
|
|
||||||
var manifestModified = false
|
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 modLoaders = hashMapOf(
|
||||||
val modLoadersClasses = modLoaders.entries.associate{(k,v)-> v to k}
|
"net.minecraft" to "minecraft",
|
||||||
var modLoaderFound = false
|
"net.minecraftforge" to "forge",
|
||||||
val modLoadersFound = HashMap<String, String>() // Key: modLoader, Value: Version
|
"net.fabricmc.fabric-loader" to "fabric",
|
||||||
val components = multimcManifest["components"].asJsonArray
|
"org.quiltmc.quilt-loader" to "quilt",
|
||||||
for (componentObj in components) {
|
"com.mumfrey.liteloader" to "liteloader")
|
||||||
val component = componentObj.asJsonObject
|
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
|
val version = component["version"]?.asString
|
||||||
// If we find any of the modloaders we support, we save it and check the version
|
// If we find any of the modloaders we support, we save it and check the version
|
||||||
if (modLoaders.containsKey(component["uid"].asString)) {
|
if (modLoaders.containsKey(component["uid"]?.asString)) {
|
||||||
val modLoader = modLoaders.getValue(component["uid"].asString)
|
val modLoader = modLoaders.getValue(component["uid"]!!.asString)
|
||||||
if (modLoader != "minecraft")
|
loaderVersionsFound[modLoader] = version
|
||||||
modLoaderFound = true // Only set to true if modLoader isn't Minecraft
|
if (version != pf.versions?.get(modLoader)) {
|
||||||
modLoadersFound[modLoader] = version
|
outdatedLoaders.add(modLoader)
|
||||||
if (version != pf.versions?.get(modLoader)) {
|
true // Delete component; cached metadata is invalid and will be re-added
|
||||||
manifestModified = true
|
} else {
|
||||||
component.addProperty("version", pf.versions?.get(modLoader))
|
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
|
for ((_, loader) in modLoaders
|
||||||
if (!modLoaderFound) {
|
.filter {
|
||||||
// Using this filter and loop to handle multiple handlers
|
(!loaderVersionsFound.containsKey(it.value) || outdatedLoaders.contains(it.value))
|
||||||
for ((_, loader) in modLoaders
|
&& pf.versions?.containsKey(it.value) == true }
|
||||||
.filter { it.value != "minecraft" && !modLoadersFound.containsKey(it.value) && pf.versions?.containsKey(it.value) == true }
|
) {
|
||||||
) {
|
manifestModified = true
|
||||||
components.add(gson.toJsonTree(hashMapOf("uid" to modLoadersClasses.get(loader), "version" to pf.versions?.get(loader))))
|
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 inconsistent Intermediary mappings version is found, delete it - MultiMC will add and re-dl the correct one
|
||||||
if (modLoadersFound["minecraft"] != pf.versions?.getValue("minecraft"))
|
components.find { it.isJsonObject && it.asJsonObject["uid"]?.asString == "net.fabricmc.intermediary" }?.let {
|
||||||
components.find { it.asJsonObject["uid"].asString == "net.fabricmc.intermediary" }?.asJsonObject?.let { components.remove(it) }
|
if (it.asJsonObject["version"]?.asString != pf.versions?.get("minecraft")) {
|
||||||
|
components.remove(it)
|
||||||
|
manifestModified = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (manifestModified) {
|
if (manifestModified) {
|
||||||
// The manifest has been modified, so before saving it we'll ask the user
|
// 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
|
// if they wanna update it, continue without updating it, or exit
|
||||||
val oldVers = modLoadersFound.map { Pair(it.key, it.value) }
|
val oldVers = loaderVersionsFound.map { Pair(it.key, it.value) }
|
||||||
val newVers = pf.versions!!.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)) {
|
manifestFile.writeText(gson.toJson(multimcManifest))
|
||||||
IUserInterface.UpdateConfirmationResult.CANCELLED -> {
|
Log.info("Successfully updated mmc-pack.json based on version metadata")
|
||||||
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))
|
return LauncherStatus.SUCCESSFUL
|
||||||
Log.info("Updated modpack Minecrafts and/or the modloaders version")
|
}
|
||||||
|
|
||||||
return LauncherStatus.Succesful
|
return LauncherStatus.NO_CHANGES
|
||||||
}
|
}
|
||||||
|
|
||||||
return LauncherStatus.NoChanges
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -105,8 +105,9 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse
|
|||||||
ui.submitProgress(InstallProgress("Loading MultiMC pack file..."))
|
ui.submitProgress(InstallProgress("Loading MultiMC pack file..."))
|
||||||
try {
|
try {
|
||||||
when (lu.handleMultiMC(pf, gson)) {
|
when (lu.handleMultiMC(pf, gson)) {
|
||||||
LauncherUtils.LauncherStatus.Cancelled -> cancelled = true
|
LauncherUtils.LauncherStatus.CANCELLED -> cancelled = true
|
||||||
LauncherUtils.LauncherStatus.NotFound -> Log.info("MultiMC not detected")
|
LauncherUtils.LauncherStatus.NOT_FOUND -> Log.info("MultiMC not detected")
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
handleCancellation()
|
handleCancellation()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -202,17 +202,16 @@ class GUIHandler : IUserInterface {
|
|||||||
|
|
||||||
|
|
||||||
val options = arrayOf("Cancel", "Continue anyways", "Update")
|
val options = arrayOf("Cancel", "Continue anyways", "Update")
|
||||||
val result = JOptionPane.showOptionDialog(frmPackwizlauncher,
|
val result = JOptionPane.showOptionDialog(frmPackwizlauncher, message,
|
||||||
message,
|
|
||||||
"Updating MultiMC versions",
|
"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(
|
future.complete(
|
||||||
when (result) {
|
when (result) {
|
||||||
JOptionPane.CLOSED_OPTION, 0 -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
JOptionPane.CLOSED_OPTION, 0 -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
||||||
1 -> IUserInterface.UpdateConfirmationResult.CONTINUE
|
1 -> IUserInterface.UpdateConfirmationResult.CONTINUE
|
||||||
2 -> IUserInterface.UpdateConfirmationResult.UPDATE
|
2 -> IUserInterface.UpdateConfirmationResult.UPDATE
|
||||||
else -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
else -> IUserInterface.UpdateConfirmationResult.CANCELLED
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return future.get()
|
return future.get()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user