diff --git a/src/main/kotlin/com/mineinabyss/launchy/logic/ModDownloader.kt b/src/main/kotlin/com/mineinabyss/launchy/logic/ModDownloader.kt index 65e2b9c..7e8fbad 100644 --- a/src/main/kotlin/com/mineinabyss/launchy/logic/ModDownloader.kt +++ b/src/main/kotlin/com/mineinabyss/launchy/logic/ModDownloader.kt @@ -17,7 +17,7 @@ import kotlin.io.path.* object ModDownloader { suspend fun GameInstanceState.installMCAndModLoaders(state: LaunchyState, modLoaders: InstanceModLoaders) { - state.runTask(Tasks.installModLoadersId, InProgressTask("Installing ${modLoaders.fabricLoader}")) { + state.runTask(Tasks.installModLoadersId, InProgressTask("Installing ${modLoaders.fullVersionName}")) { Launcher.download( modLoaders, instance.minecraftDir, @@ -92,9 +92,9 @@ object ModDownloader { * Primarily the mod loader/minecraft version. */ suspend fun GameInstanceState.ensureDependenciesReady(state: LaunchyState) = coroutineScope { - val currentDeps = userAgreedDeps + val currentDeps = userAgreedModLoaders if (currentDeps == null) { - userAgreedDeps = modpack.modLoaders + userAgreedModLoaders = modpack.modLoaders } installMCAndModLoaders(state, currentDeps ?: modpack.modLoaders) } @@ -145,7 +145,7 @@ object ModDownloader { */ suspend fun GameInstanceState.startInstall(state: LaunchyState, ignoreCachedCheck: Boolean = false): Result<*> = coroutineScope { - userAgreedDeps = modpack.modLoaders + userAgreedModLoaders = modpack.modLoaders ensureDependenciesReady(state) copyOverrides(state) diff --git a/src/main/kotlin/com/mineinabyss/launchy/state/modpack/DownloadQueueState.kt b/src/main/kotlin/com/mineinabyss/launchy/state/modpack/DownloadQueueState.kt index 453d182..f1674c3 100644 --- a/src/main/kotlin/com/mineinabyss/launchy/state/modpack/DownloadQueueState.kt +++ b/src/main/kotlin/com/mineinabyss/launchy/state/modpack/DownloadQueueState.kt @@ -43,12 +43,16 @@ class DownloadQueueState( (modpack.mods.mods - toggles.enabledMods).filter { modDownloadInfo.contains(it.modId) } } + val areModLoaderUpdatesAvailable by derivedStateOf { + modpack.modLoaders != userConfig.userAgreedDeps + } + val needsInstall by derivedStateOf { updates + newDownloads + failures } val areUpdatesQueued by derivedStateOf { updates.isNotEmpty() } val areNewDownloadsQueued by derivedStateOf { newDownloads.isNotEmpty() } val areDeletionsQueued by derivedStateOf { deletions.isNotEmpty() } val areOperationsQueued by derivedStateOf { - areUpdatesQueued || areNewDownloadsQueued || areDeletionsQueued + areUpdatesQueued || areNewDownloadsQueued || areDeletionsQueued || areModLoaderUpdatesAvailable } } diff --git a/src/main/kotlin/com/mineinabyss/launchy/state/modpack/GameInstanceState.kt b/src/main/kotlin/com/mineinabyss/launchy/state/modpack/GameInstanceState.kt index b4d831d..18f0e5b 100644 --- a/src/main/kotlin/com/mineinabyss/launchy/state/modpack/GameInstanceState.kt +++ b/src/main/kotlin/com/mineinabyss/launchy/state/modpack/GameInstanceState.kt @@ -15,14 +15,14 @@ class GameInstanceState( val toggles: ModTogglesState = ModTogglesState(modpack, userConfig) val queued = DownloadQueueState(userConfig, modpack, toggles) val downloads = DownloadState() - var userAgreedDeps by mutableStateOf(userConfig.userAgreedDeps) + var userAgreedModLoaders by mutableStateOf(userConfig.userAgreedDeps) fun saveToConfig() { userConfig.copy( fullEnabledGroups = modpack.mods.modGroups .filter { toggles.enabledMods.containsAll(it.value) }.keys .map { it.name }.toSet(), - userAgreedDeps = userAgreedDeps, + userAgreedDeps = userAgreedModLoaders, toggledMods = toggles.enabledMods.mapTo(mutableSetOf()) { it.info.name }, toggledConfigs = toggles.enabledConfigs.mapTo(mutableSetOf()) { it.info.name } + toggles.enabledMods.filter { it.info.forceConfigDownload } .mapTo(mutableSetOf()) { it.info.name }, diff --git a/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/main/buttons/PlayButton.kt b/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/main/buttons/PlayButton.kt index 16fcd7f..2b2878a 100644 --- a/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/main/buttons/PlayButton.kt +++ b/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/main/buttons/PlayButton.kt @@ -63,20 +63,25 @@ fun PlayButton( coroutineScope.launch(Dispatchers.IO) { val packState = foundPackState ?: getModpackState() ?: return@launch foundPackState = packState + val operationsQueued = packState.queued.areOperationsQueued + if (process == null) { when { // Assume this means not launched before - packState.userAgreedDeps == null -> { + packState.userAgreedModLoaders == null -> { AppDispatchers.profileLaunch.launchOrShowDialog { packState.startInstall(state) Launcher.launch(state, packState, state.profile) } } - packState.queued.areOperationsQueued -> { + operationsQueued -> { dialog = Dialog.Options( title = "Install changes before launch?", - message = "New mods have been selected/removed,\nwould you like to apply these changes?", + message = buildString { + appendLine("This instance has changes that are not installed yet,") + appendLine("would you like to apply these changes now?") + }, acceptText = "Install", declineText = "Skip", onAccept = { diff --git a/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/settings/InfoBar.kt b/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/settings/InfoBar.kt index d5cc6b1..03ac8e2 100644 --- a/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/settings/InfoBar.kt +++ b/src/main/kotlin/com/mineinabyss/launchy/ui/screens/modpack/settings/InfoBar.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Delete import androidx.compose.material.icons.rounded.Download +import androidx.compose.material.icons.rounded.HistoryEdu import androidx.compose.material.icons.rounded.Update import androidx.compose.material3.Icon import androidx.compose.material3.Surface @@ -48,7 +49,7 @@ fun InfoBar(modifier: Modifier = Modifier) { InstallButton( state.processFor(packState.instance) == null && !packState.downloads.isDownloading - && (packState.queued.areOperationsQueued || packState.userAgreedDeps == null) + && (packState.queued.areOperationsQueued || packState.userAgreedModLoaders == null) && state.inProgressTasks.isEmpty(), Modifier.width(Constants.SETTINGS_PRIMARY_BUTTON_WIDTH) ) @@ -56,6 +57,12 @@ fun InfoBar(modifier: Modifier = Modifier) { AnimatedVisibility(failures) { RetryFailedButton(failures) } + ActionButton( + shown = packState.queued.areModLoaderUpdatesAvailable, + icon = Icons.Rounded.HistoryEdu, + desc = "Mod loader updates:\n${packState.userAgreedModLoaders?.fullVersionName ?: "Not installed"} -> ${packState.modpack.modLoaders.fullVersionName}", + count = 1 + ) ActionButton( shown = packState.queued.areUpdatesQueued, icon = Icons.Rounded.Update,