Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clusterfuck of half broken changes and ideas #31

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ compose.desktop {
}
}

val linuxAppDir = project.file("packaging/appimage/Mine in Abyss.AppDir")
val linuxAppDir = project.file("packaging/appimage/Wynntils.AppDir")
val appImageTool = project.file("deps/appimagetool.AppImage")
val composePackageDir = "$buildDir/compose/binaries/main/${
when {
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
4 changes: 4 additions & 0 deletions src/main/kotlin/com/mineinabyss/launchy/data/Config.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.mineinabyss.launchy.data

import com.mineinabyss.launchy.ui.screens.settings.ClientSettings
import com.mineinabyss.launchy.ui.screens.settings.JavaSettings
import com.mineinabyss.launchy.ui.screens.settings.MinecraftSettings
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import java.io.*
Expand All @@ -11,6 +14,7 @@ import kotlin.io.path.writeText
@Serializable
data class Config(
val minecraftDir: String? = null,
val clientSettings: ClientSettings = ClientSettings(MinecraftSettings(), JavaSettings()),
val fullEnabledGroups: Set<GroupName> = setOf(),
val fullDisabledGroups: Set<GroupName> = setOf(),
val toggledMods: Set<ModName> = setOf(),
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/com/mineinabyss/launchy/data/Typealiases.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.mineinabyss.launchy.data

import androidx.compose.runtime.Composable

typealias ModName = String
typealias GroupName = String
typealias DownloadURL = String
typealias ConfigURL = String
typealias ComposableFun = @Composable () -> Unit
51 changes: 26 additions & 25 deletions src/main/kotlin/com/mineinabyss/launchy/logic/FabricInstaller.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ package com.mineinabyss.launchy.logic

import mjson.Json
import mjson.Json.read
import net.fabricmc.installer.client.ProfileInstaller
import net.fabricmc.installer.client.ProfileInstaller.LauncherType
import net.fabricmc.installer.util.Reference
import net.fabricmc.installer.util.Utils
import org.json.JSONObject
Expand Down Expand Up @@ -36,13 +36,13 @@ object FabricInstaller {
gameVersion: String,
loaderName: String,
loaderVersion: String,
launchyState: LaunchyState
): Boolean {
val versionId = String.format("%s-%s-%s", loaderName, loaderVersion, gameVersion)
val launcherType: ProfileInstaller.LauncherType = (if (System.getProperty("os.name")
.contains("Windows")
) getLauncherType(vanillaGameDir) else /* Return standalone if we aren't on Windows.*/ ProfileInstaller.LauncherType.WIN32)
val launcherType: LauncherType = (if ("Windows" in System.getProperty("os.name"))
getLauncherType(vanillaGameDir) else /* Return standalone if we aren't on Windows.*/ LauncherType.WIN32)
installVersion(vanillaGameDir, gameVersion, loaderName, loaderVersion, launcherType)
installProfile(vanillaGameDir, instanceDir, profileName, versionId, launcherType)
installProfile(vanillaGameDir, instanceDir, profileName, versionId, launcherType, launchyState)
return true
}

Expand All @@ -51,7 +51,7 @@ object FabricInstaller {
gameVersion: String,
loaderName: String,
loaderVersion: String,
launcherType: ProfileInstaller.LauncherType
launcherType: LauncherType
) {
println("Installing $gameVersion with fabric $loaderVersion to launcher $launcherType")
val versionId = "$loaderName-$loaderVersion-$gameVersion"
Expand All @@ -71,20 +71,22 @@ object FabricInstaller {
Utils.writeToFile(profileJsonPath, profileJson.toString())
}

private fun installProfile(
fun installProfile(
mcDir: Path,
instanceDir: Path,
profileName: String,
versionId: String,
launcherType: ProfileInstaller.LauncherType
launcherType: LauncherType,
launchyState: LaunchyState
) {
val launcherProfiles: Path = mcDir.resolve(launcherType.profileJsonName)
if (!Files.exists(launcherProfiles)) {
println("Could not find launcher_profiles")
return
}
println("Creating profile")

val jsonObject = JSONObject(Utils.readString(launcherProfiles))
println("Creating profile")
val profiles: JSONObject = jsonObject.getJSONObject("profiles")
var foundProfileName: String? = profileName
val it: Iterator<String> = profiles.keys()
Expand All @@ -98,20 +100,19 @@ object FabricInstaller {
foundProfileName = key
}
}

val javaSettings = launchyState.clientSettings.java
// If the profile already exists, use it instead of making a new one so that user's settings are kept (e.g icon)
val profile: JSONObject =
if (profiles.has(foundProfileName)) profiles.getJSONObject(foundProfileName) else createProfile(
profileName,
instanceDir,
versionId,
)
if (profiles.has(foundProfileName))
profiles.getJSONObject(foundProfileName)
else createProfile(profileName, instanceDir, versionId)
profile.put("name", profileName)
profile.put("lastUsed", Utils.ISO_8601.format(Date())) // Update timestamp to bring to top of profile list
profile.put("lastVersionId", versionId)
profile.put("javaArgs", "-Xmx${javaSettings.maxRamAmount}G -Xms${javaSettings.minRamAmount}G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M")
profiles.put(foundProfileName, profile)
jsonObject.put("profiles", profiles)
Utils.writeToFile(launcherProfiles, jsonObject.toString())
Utils.writeToFile(mcDir.resolve(launcherType.profileJsonName), jsonObject.toString())
}

private fun createProfile(name: String, instanceDir: Path, versionId: String): JSONObject {
Expand Down Expand Up @@ -157,7 +158,7 @@ object FabricInstaller {
}
}

private fun showLauncherTypeSelection(): ProfileInstaller.LauncherType? {
private fun showLauncherTypeSelection(): LauncherType? {
val options = arrayOf<String>(
Utils.BUNDLE.getString("prompt.launcher.type.xbox"),
Utils.BUNDLE.getString("prompt.launcher.type.win32")
Expand All @@ -175,17 +176,17 @@ object FabricInstaller {
return if (result == JOptionPane.CLOSED_OPTION) {
null
} else {
if (result == JOptionPane.YES_OPTION) ProfileInstaller.LauncherType.MICROSOFT_STORE else ProfileInstaller.LauncherType.WIN32
if (result == JOptionPane.YES_OPTION) LauncherType.MICROSOFT_STORE else LauncherType.WIN32
}
}

fun getLauncherType(vanillaGameDir: Path): ProfileInstaller.LauncherType {
var launcherType: ProfileInstaller.LauncherType?
val types: List<ProfileInstaller.LauncherType> = getInstalledLauncherTypes(vanillaGameDir)
fun getLauncherType(vanillaGameDir: Path): LauncherType {
var launcherType: LauncherType?
val types: List<LauncherType> = getInstalledLauncherTypes(vanillaGameDir)
if (types.size == 0) {
// Default to WIN32, since nothing will happen anyway
println("No launchers found, profile installation will not take place!")
launcherType = ProfileInstaller.LauncherType.WIN32
launcherType = LauncherType.WIN32
} else if (types.size == 1) {
println("Found only one launcher (" + types[0] + "), will proceed with that!")
launcherType = types[0]
Expand All @@ -194,14 +195,14 @@ object FabricInstaller {
launcherType = showLauncherTypeSelection()
if (launcherType == null) {
System.out.println(Utils.BUNDLE.getString("prompt.ready.install"))
launcherType = ProfileInstaller.LauncherType.WIN32
launcherType = LauncherType.WIN32
}
}
return launcherType
}

fun getInstalledLauncherTypes(mcDir: Path): List<ProfileInstaller.LauncherType> {
return Arrays.stream(ProfileInstaller.LauncherType.values()).filter { launcherType ->
fun getInstalledLauncherTypes(mcDir: Path): List<LauncherType> {
return Arrays.stream(LauncherType.values()).filter { launcherType ->
Files.exists(
mcDir.resolve(
launcherType.profileJsonName
Expand Down
19 changes: 15 additions & 4 deletions src/main/kotlin/com/mineinabyss/launchy/logic/LaunchyState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ class LaunchyState(
"Mine in Abyss"
)
}
val settingsUpToDate by derivedStateOf {
clientSettings == config.clientSettings
}

val updatesQueued by derivedStateOf { queuedUpdates.isNotEmpty() }
val installsQueued by derivedStateOf { queuedInstalls.isNotEmpty() }
val deletionsQueued by derivedStateOf { queuedDeletions.isNotEmpty() }
Expand All @@ -126,6 +130,7 @@ class LaunchyState(
)

var handledFirstLaunch by mutableStateOf(config.handledFirstLaunch)
var clientSettings by mutableStateOf(config.clientSettings)

fun setModEnabled(mod: Mod, enabled: Boolean) {
if (enabled) {
Expand Down Expand Up @@ -175,6 +180,14 @@ class LaunchyState(
}

fun installFabric() {
installProfile()
installedFabricVersion = "Installing..."
installedFabricVersion = versions.fabricVersion
installedMinecraftVersion = "Installing..."
installedMinecraftVersion = versions.minecraftVersion
}

fun installProfile() {
installingProfile = true
FabricInstaller.installToLauncher(
Dirs.minecraft,
Expand All @@ -183,12 +196,9 @@ class LaunchyState(
versions.minecraftVersion,
"fabric-loader",
versions.fabricVersion,
this
)
installingProfile = false
installedFabricVersion = "Installing..."
installedFabricVersion = versions.fabricVersion
installedMinecraftVersion = "Installing..."
installedMinecraftVersion = versions.minecraftVersion
}

suspend fun download(mod: Mod) {
Expand Down Expand Up @@ -265,6 +275,7 @@ class LaunchyState(
installedMinecraftVersion = installedMinecraftVersion,
handledImportOptions = handledImportOptions,
handledFirstLaunch = handledFirstLaunch,
clientSettings = clientSettings
).save()
}

Expand Down
52 changes: 52 additions & 0 deletions src/main/kotlin/com/mineinabyss/launchy/ui/TopBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import androidx.compose.animation.slideOut
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.window.WindowDraggableArea
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ManageAccounts
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.outlined.SettingsApplications
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material.icons.rounded.CropSquare
Expand All @@ -15,10 +18,13 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import com.mineinabyss.launchy.ui.screens.Screen
import com.mineinabyss.launchy.ui.screens.screen
import com.mineinabyss.launchy.ui.state.TopBarState

@Composable
Expand All @@ -33,6 +39,52 @@ fun WindowButton(icon: ImageVector, onClick: () -> Unit) {
}
}

@Composable
fun TabIconButton(label: String = "", icon: ImageVector, onClick: () -> Unit) {
Button(onClick, shape = RectangleShape, colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background, disabledContainerColor = MaterialTheme.colorScheme.onPrimaryContainer)) {
Icon(icon, "", tint = MaterialTheme.colorScheme.onPrimaryContainer)
Text(label, color = MaterialTheme.colorScheme.onPrimaryContainer)
}
}

@Composable
fun TabIconBar(
state: TopBarState,
transparent: Boolean,
tabIconScreens: Set<Screen>,
onTabIconClicked: (() -> Unit),
) = state.windowScope.WindowDraggableArea {
Box(
Modifier.fillMaxWidth().height(40.dp)
) {
AnimatedVisibility(
!transparent,
enter = slideIn(initialOffset = { IntOffset(0, -120) }),
exit = slideOut(targetOffset = { IntOffset(0, -120) })
) {
Surface(tonalElevation = 1.dp, modifier = Modifier.fillMaxSize()) {}
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround,
) {
Spacer(Modifier.width(5.dp))
Row(
Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
TabIconButton("Accounts", Icons.Outlined.ManageAccounts) { screen = Screen.Account }
TabIconButton("Java", Icons.Outlined.SettingsApplications) { screen = Screen.Java }
TabIconButton("Mods", Icons.Outlined.Settings) { screen = Screen.Mods }
}
Row {

}
}
}
}

@Composable
fun AppTopBar(
state: TopBarState,
Expand Down
25 changes: 19 additions & 6 deletions src/main/kotlin/com/mineinabyss/launchy/ui/screens/Screens.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,20 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import com.mineinabyss.launchy.data.ComposableFun
import com.mineinabyss.launchy.ui.AppTopBar
import com.mineinabyss.launchy.ui.screens.main.MainScreen
import com.mineinabyss.launchy.ui.screens.settings.SettingsScreen
import com.mineinabyss.launchy.ui.screens.settings.AccountScreen
import com.mineinabyss.launchy.ui.screens.settings.JavaScreen
import com.mineinabyss.launchy.ui.screens.settings.ModsScreen
import com.mineinabyss.launchy.ui.screens.settings.Tabs
import com.mineinabyss.launchy.ui.state.TopBar

sealed class Screen(val transparentTopBar: Boolean = false) {
object Default : Screen(transparentTopBar = true)
object Java : Screen()
object Mods : Screen()
object Account : Screen()
object Settings : Screen()
}

Expand All @@ -31,8 +38,14 @@ fun Screens() {
}

TranslucentTopBar(screen) {
TransitionSlideUp(screen == Screen.Settings) {
SettingsScreen()
TransitionSlideUp(screen != Screen.Default) {
when (screen) {
Screen.Account -> AccountScreen()
Screen.Java -> JavaScreen()
Screen.Mods -> ModsScreen()
else -> {}
}
Tabs()
}
}

Expand All @@ -45,7 +58,7 @@ fun Screens() {
}

@Composable
fun TranslucentTopBar(currentScreen: Screen, content: @Composable () -> Unit) {
fun TranslucentTopBar(currentScreen: Screen, content: ComposableFun) {
Column {
AnimatedVisibility(!currentScreen.transparentTopBar, enter = fadeIn(), exit = fadeOut()) {
Spacer(Modifier.height(40.dp))
Expand All @@ -55,14 +68,14 @@ fun TranslucentTopBar(currentScreen: Screen, content: @Composable () -> Unit) {
}

@Composable
fun TransitionFade(enabled: Boolean, content: @Composable () -> Unit) {
fun TransitionFade(enabled: Boolean, content: ComposableFun) {
AnimatedVisibility(enabled, enter = fadeIn(), exit = fadeOut()) {
content()
}
}

@Composable
fun TransitionSlideUp(enabled: Boolean, content: @Composable () -> Unit) {
fun TransitionSlideUp(enabled: Boolean, content: ComposableFun) {
AnimatedVisibility(
enabled,
enter = fadeIn() + slideIn(initialOffset = { IntOffset(0, 100) }),
Expand Down
Loading