feat(server): ground work

This commit is contained in:
ineanto 2023-11-26 21:07:41 +01:00
parent 7b743c95fb
commit b9a43c459c
19 changed files with 138 additions and 32 deletions

View file

@ -3,8 +3,8 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") version "1.8.10" kotlin("jvm") version "1.9.10"
id("org.jetbrains.compose") version "1.3.1" id("org.jetbrains.compose") version "1.5.2"
} }
group = "xyz.atnrch" group = "xyz.atnrch"
@ -20,8 +20,8 @@ dependencies {
implementation(compose.desktop.currentOs) implementation(compose.desktop.currentOs)
implementation(compose.materialIconsExtended) implementation(compose.materialIconsExtended)
implementation(compose.material3) implementation(compose.material3)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.6.4") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.7.3")
implementation("com.google.code.gson:gson:2.10") implementation("com.google.code.gson:gson:2.10.1")
} }
tasks.withType<KotlinCompile> { tasks.withType<KotlinCompile> {
@ -30,7 +30,7 @@ tasks.withType<KotlinCompile> {
compose.desktop { compose.desktop {
application { application {
mainClass = "xyz.atnrch.wrench.WrenchApp" mainClass = "xyz.atnrch.wrench.Wrench"
nativeDistributions { nativeDistributions {
includeAllModules = true includeAllModules = true
targetFormats(TargetFormat.AppImage) targetFormats(TargetFormat.AppImage)

View file

@ -7,22 +7,37 @@ import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState import androidx.compose.ui.window.rememberWindowState
import xyz.atnrch.wrench.gui.WrenchScaffold import xyz.atnrch.wrench.gui.WrenchScaffold
import xyz.atnrch.wrench.logger.Logger import xyz.atnrch.wrench.logger.Logger
import java.io.File
import java.nio.file.Paths import java.nio.file.Paths
import javax.swing.UIManager import javax.swing.UIManager
class WrenchApp { class Wrench {
companion object { companion object {
const val PREFIX: String = "(Wrench)" const val PREFIX: String = "(Wrench)"
private val ROOT_FOLDER_PATH = System.getProperty("user.dir") + File.separator + "WrenchData"
private val SERVER_FOLDER_PATH = ROOT_FOLDER_PATH + File.separator + "servers"
val ROOT_FOLDER: File = Paths.get(ROOT_FOLDER_PATH).toFile()
val SERVER_FOLDER: File = Paths.get(SERVER_FOLDER_PATH).toFile()
@JvmStatic @JvmStatic
fun main(args: Array<String>) = application { fun main(args: Array<String>) = application {
val state = rememberWindowState(width = 1000.dp, height = 1024.dp) val state = rememberWindowState(width = 1000.dp, height = 1024.dp)
Window( Window(
state = state, state = state,
onCloseRequest = ::exitApplication onCloseRequest = {
// For debug purposes, clean the server folder on exit
SERVER_FOLDER.listFiles()?.forEach { it.delete() }
SERVER_FOLDER.delete()
exitApplication()
}
) { ) {
Logger.info("Starting Wrench...") Logger.info("Starting Wrench...")
Logger.info("Working Directory: ${Paths.get("").toAbsolutePath()}")
Logger.info("Creating folders...")
ROOT_FOLDER.mkdir()
SERVER_FOLDER.mkdir()
Logger.info("Root folder location: $ROOT_FOLDER")
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
MaterialTheme { WrenchScaffold(state) } MaterialTheme { WrenchScaffold(state) }
} }

View file

@ -10,7 +10,7 @@ import androidx.compose.ui.window.WindowState
import xyz.atnrch.wrench.gui.appearance.UIColors import xyz.atnrch.wrench.gui.appearance.UIColors
import xyz.atnrch.wrench.gui.component.SnackBarDataHolder import xyz.atnrch.wrench.gui.component.SnackBarDataHolder
import xyz.atnrch.wrench.gui.filemanager.bottom.FileAppBottomBar import xyz.atnrch.wrench.gui.filemanager.bottom.FileAppBottomBar
import xyz.atnrch.wrench.gui.filemanager.bottom.FloatingAddButton import xyz.atnrch.wrench.gui.filemanager.bottom.FileManagerAddButton
import xyz.atnrch.wrench.gui.server.bottom.ServerAppBottomBar import xyz.atnrch.wrench.gui.server.bottom.ServerAppBottomBar
import xyz.atnrch.wrench.storage.LayoutStorage import xyz.atnrch.wrench.storage.LayoutStorage
import xyz.atnrch.wrench.watcher.Watcher import xyz.atnrch.wrench.watcher.Watcher
@ -45,7 +45,7 @@ fun WrenchScaffold(state: WindowState) {
Scaffold( Scaffold(
scaffoldState = scaffoldState, scaffoldState = scaffoldState,
topBar = { TopBar(layoutStorage, tabIndex, entries.values) }, topBar = { TopBar(layoutStorage, tabIndex, entries.values) },
floatingActionButton = { if (tabIndex == 0) FloatingAddButton(watcherManager) }, floatingActionButton = { if (tabIndex == 0) FileManagerAddButton(watcherManager) },
isFloatingActionButtonDocked = true, isFloatingActionButtonDocked = true,
backgroundColor = UIColors.PRIMARY, backgroundColor = UIColors.PRIMARY,
bottomBar = { bottomBar = {

View file

@ -18,7 +18,7 @@ import xyz.atnrch.wrench.logger.Logger
import xyz.atnrch.wrench.watcher.WatcherManager import xyz.atnrch.wrench.watcher.WatcherManager
@Composable @Composable
fun FloatingAddButton( fun FileManagerAddButton(
watcherManager: WatcherManager watcherManager: WatcherManager
) { ) {
FloatingActionButton( FloatingActionButton(

View file

@ -9,14 +9,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import xyz.atnrch.wrench.gui.appearance.Fonts import xyz.atnrch.wrench.gui.appearance.Fonts
import xyz.atnrch.wrench.gui.appearance.UIColors import xyz.atnrch.wrench.gui.appearance.UIColors
@OptIn(ExperimentalUnitApi::class)
@Composable @Composable
fun EmptyFileManagerView() { fun EmptyFileManagerView() {
Box( Box(

View file

@ -9,7 +9,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.PointerButton import androidx.compose.ui.input.pointer.PointerButton
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.TextUnitType
import xyz.atnrch.wrench.gui.appearance.Fonts import xyz.atnrch.wrench.gui.appearance.Fonts
@ -17,7 +16,7 @@ import xyz.atnrch.wrench.gui.appearance.UIColors
import xyz.atnrch.wrench.gui.component.ACTIVE_COMPOSABLE import xyz.atnrch.wrench.gui.component.ACTIVE_COMPOSABLE
import xyz.atnrch.wrench.watcher.WatcherEntry import xyz.atnrch.wrench.watcher.WatcherEntry
@OptIn(ExperimentalUnitApi::class, ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun InputTextEntry( fun InputTextEntry(
id: Int, id: Int,

View file

@ -10,12 +10,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@OptIn(ExperimentalUnitApi::class)
@Composable @Composable
fun InputTopText() { fun InputTopText() {
Box( Box(

View file

@ -9,7 +9,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -20,7 +19,6 @@ import xyz.atnrch.wrench.watcher.WatcherManager
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.pathString import kotlin.io.path.pathString
@OptIn(ExperimentalUnitApi::class)
@Composable @Composable
fun OutputEntries( fun OutputEntries(
watcherManager: WatcherManager, watcherManager: WatcherManager,

View file

@ -12,7 +12,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.*
@OptIn(ExperimentalUnitApi::class)
@Composable @Composable
fun OutputTopText() { fun OutputTopText() {
Box( Box(

View file

@ -1,9 +1,9 @@
package xyz.atnrch.wrench.gui.server package xyz.atnrch.wrench.gui.server
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import xyz.atnrch.wrench.gui.server.center.UnderConstructionView import xyz.atnrch.wrench.gui.server.center.ServerList
@Composable @Composable
fun ServerManagerDisplay() { fun ServerManagerDisplay() {
UnderConstructionView() ServerList()
} }

View file

@ -13,7 +13,7 @@ fun ServerButtonBar(
onCurrentClick: (Int) -> Unit, onCurrentClick: (Int) -> Unit,
) { ) {
Spacer(Modifier.width(10.dp)) Spacer(Modifier.width(10.dp))
AddServerStateButton(minMode) StartServerStateButton(minMode)
/*if (currentClick != -1) { /*if (currentClick != -1) {
Spacer(Modifier.width(10.dp)) Spacer(Modifier.width(10.dp))
AddOutputButton(minMode, watcherManager, outputs, currentClick) AddOutputButton(minMode, watcherManager, outputs, currentClick)

View file

@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
import xyz.atnrch.wrench.gui.appearance.UIColors import xyz.atnrch.wrench.gui.appearance.UIColors
@Composable @Composable
fun AddServerStateButton( fun StartServerStateButton(
minMode: Boolean, minMode: Boolean,
) { ) {
Button( Button(
@ -34,13 +34,13 @@ fun AddServerStateButton(
bottom = 6.dp bottom = 6.dp
), ),
shape = RoundedCornerShape(100), shape = RoundedCornerShape(100),
border = BorderStroke(2.dp, UIColors.ORANGE), border = BorderStroke(2.dp, UIColors.GREEN),
modifier = Modifier.shadow(24.dp, RoundedCornerShape(100), false) modifier = Modifier.shadow(24.dp, RoundedCornerShape(100), false)
) { ) {
Icon( Icon(
Icons.Filled.Start, Icons.Filled.Start,
tint = UIColors.ORANGE, tint = UIColors.GREEN,
contentDescription = "Add output", contentDescription = "Start Server",
modifier = Modifier.size(22.dp) modifier = Modifier.size(22.dp)
) )
if(!minMode) { if(!minMode) {

View file

@ -9,14 +9,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import xyz.atnrch.wrench.gui.appearance.Fonts import xyz.atnrch.wrench.gui.appearance.Fonts
import xyz.atnrch.wrench.gui.appearance.UIColors import xyz.atnrch.wrench.gui.appearance.UIColors
@OptIn(ExperimentalUnitApi::class)
@Composable @Composable
fun UnderConstructionView() { fun UnderConstructionView() {
Box( Box(

View file

@ -0,0 +1,51 @@
package xyz.atnrch.wrench.gui.server.center
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Text
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.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp
import xyz.atnrch.wrench.gui.appearance.Fonts
import xyz.atnrch.wrench.gui.appearance.UIColors
@Composable
fun ServerList() {
Box(
modifier = Modifier.fillMaxSize()
.background(UIColors.PRIMARY)
.padding(10.dp)
) {
val stateVertical = rememberScrollState(0)
Box(
modifier = Modifier
.fillMaxSize()
.verticalScroll(stateVertical)
.padding(end = 12.dp, bottom = 12.dp)
) {
Column {
for (item in 0..5) {
Text(
text = "SERVER $item",
fontSize = TextUnit(20F, TextUnitType.Sp),
fontFamily = Fonts.ROBOTO_BOLD,
color = Color.White
)
if (item < 5) {
Spacer(modifier = Modifier.height(50.dp))
}
}
}
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd)
.fillMaxHeight(),
adapter = rememberScrollbarAdapter(stateVertical)
)
}
}

View file

@ -1,11 +1,11 @@
package xyz.atnrch.wrench.logger package xyz.atnrch.wrench.logger
import xyz.atnrch.wrench.WrenchApp import xyz.atnrch.wrench.Wrench
class Logger { class Logger {
companion object { companion object {
private fun log(level: Level, log: String) { private fun log(level: Level, log: String) {
println("${WrenchApp.PREFIX} ${level.getName()} - $log") println("${Wrench.PREFIX} ${level.getName()} - $log")
} }
fun debug(log: String) { fun debug(log: String) {

View file

@ -0,0 +1,20 @@
package xyz.atnrch.wrench.server
import xyz.atnrch.wrench.Wrench
import xyz.atnrch.wrench.logger.Logger
import java.io.File
import java.util.*
import kotlin.random.Random
class Server internal constructor(var name: String, var type: ServerType) {
var id = UUID.randomUUID().toString().take(5) // Much ❤ to Dave Brubeck!
var folder = File(Wrench.SERVER_FOLDER, "${File.separator}${id}")
internal constructor(type: ServerType) : this("Server ${Random.nextInt(99)}", type)
init {
Logger.info("(Server) Registering new server \"${name}\" (${type.name}/${id})")
Logger.info("(Server/$id) Creating folders...")
folder.mkdir()
}
}

View file

@ -0,0 +1,23 @@
package xyz.atnrch.wrench.server
enum class ServerStatus {
/**
* Servers in this state are waiting to be cleaned up.
*/
DEAD,
/**
* Servers in this state are offline and can be started at any moment.
*/
OFFLINE,
/**
* Servers in this state are running and can be stopped at any moment.
*/
RUNNING,
/**
* Servers in this state are actively restarting.
*/
RESTARTING
}

View file

@ -0,0 +1,6 @@
package xyz.atnrch.wrench.server
enum class ServerType {
UNDEFINED,
MINECRAFT
}

View file

@ -2,6 +2,7 @@ package xyz.atnrch.wrench.storage
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import xyz.atnrch.wrench.Wrench
import xyz.atnrch.wrench.watcher.WatcherEntry import xyz.atnrch.wrench.watcher.WatcherEntry
import java.io.File import java.io.File
import java.io.FileReader import java.io.FileReader
@ -12,7 +13,7 @@ class LayoutStorage(private val onWatcherEntriesUpdate: (List<WatcherEntry>) ->
private val gson: Gson = Gson().newBuilder() private val gson: Gson = Gson().newBuilder()
.setPrettyPrinting() .setPrettyPrinting()
.create() .create()
private val file = File("./layout.json") private val file = File(Wrench.ROOT_FOLDER, "${File.separator}layout.json")
fun storeLayout(list: List<SerializedWatcherEntry>) { fun storeLayout(list: List<SerializedWatcherEntry>) {
val writer = FileWriter(file) val writer = FileWriter(file)