aboutsummaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/kotlin/xyz/brysonsteck/serverfordummies/App.kt30
-rw-r--r--app/src/main/kotlin/xyz/brysonsteck/serverfordummies/Main.kt5
-rw-r--r--app/src/main/kotlin/xyz/brysonsteck/serverfordummies/PrimaryController.kt124
-rw-r--r--app/src/main/kotlin/xyz/brysonsteck/serverfordummies/downloadFile.kt37
-rw-r--r--app/src/main/resources/xyz/brysonsteck/serverfordummies/primary.fxml253
-rw-r--r--app/src/test/kotlin/xyz/brysonsteck/serverfordummies/AppTest.kt14
6 files changed, 463 insertions, 0 deletions
diff --git a/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/App.kt b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/App.kt
new file mode 100644
index 0000000..0547a8f
--- /dev/null
+++ b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/App.kt
@@ -0,0 +1,30 @@
+/*
+ * This Kotlin source file was generated by the Gradle 'init' task.
+ */
+package xyz.brysonsteck.serverfordummies
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+class App : Application() {
+
+ override fun start(stage: Stage) {
+ var scene = Scene(loadFXML("primary"), 1500.0, 900.0)
+ stage.title = "Server For Dummies"
+ stage.scene = scene
+ stage.show()
+ }
+
+ private fun loadFXML(fxml: String) : Parent {
+ val fxmlLoader = FXMLLoader(this.javaClass.getResource(fxml + ".fxml"))
+ return fxmlLoader.load()
+ }
+
+ public fun run() {
+ launch()
+ }
+
+}
diff --git a/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/Main.kt b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/Main.kt
new file mode 100644
index 0000000..604825f
--- /dev/null
+++ b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/Main.kt
@@ -0,0 +1,5 @@
+package xyz.brysonsteck.serverfordummies
+
+fun main() {
+ App().run()
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/PrimaryController.kt b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/PrimaryController.kt
new file mode 100644
index 0000000..6e05579
--- /dev/null
+++ b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/PrimaryController.kt
@@ -0,0 +1,124 @@
+package xyz.brysonsteck.serverfordummies
+
+import java.io.File
+import java.io.IOException
+import java.awt.Checkbox
+import java.util.Properties
+
+import javafx.beans.value.ChangeListener
+import javafx.beans.value.ObservableValue
+import javafx.beans.property.BooleanProperty
+import javafx.collections.FXCollections
+import javafx.fxml.FXML
+import javafx.geometry.Insets
+import javafx.scene.control.Button
+import javafx.scene.control.ChoiceBox
+import javafx.scene.control.Label
+import javafx.scene.control.TextField
+import javafx.scene.control.Spinner
+import javafx.scene.control.TitledPane
+import javafx.scene.control.ButtonBar
+import javafx.scene.control.CheckBox
+import javafx.scene.layout.Border
+import javafx.scene.layout.BorderStroke
+import javafx.scene.layout.GridPane
+import javafx.scene.layout.Pane
+import javafx.scene.layout.HBox
+import javafx.scene.text.TextAlignment
+import javafx.scene.Scene
+import javafx.scene.input.MouseEvent
+import javafx.stage.FileChooser
+import javafx.stage.FileChooser.ExtensionFilter
+import javafx.stage.DirectoryChooser
+import javafx.event.EventHandler
+
+class PrimaryController {
+ @FXML
+ lateinit private var currentDirectoryLabel: Label
+ @FXML
+ lateinit private var worldNameField: TextField
+ @FXML
+ lateinit private var seedField: TextField
+ @FXML
+ lateinit private var portSpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var difficultyBox: ChoiceBox<String>
+ @FXML
+ lateinit private var gamemodeBox: ChoiceBox<String>
+ @FXML
+ lateinit private var worldTypeBox: ChoiceBox<String>
+ @FXML
+ lateinit private var worldSettingsPane: HBox
+ @FXML
+ lateinit private var parentPane: Pane
+ @FXML
+ lateinit private var buttonBar: ButtonBar
+ @FXML
+ lateinit private var flightCheckbox: CheckBox
+ @FXML
+ lateinit private var netherCheckbox: CheckBox
+ @FXML
+ lateinit private var structuresCheckbox: CheckBox
+ @FXML
+ lateinit private var pvpCheckbox: CheckBox
+ @FXML
+ lateinit private var whitelistCheckbox: CheckBox
+ @FXML
+ lateinit private var cmdBlocksCheckbox: CheckBox
+ @FXML
+ lateinit private var playerCountCheckbox: CheckBox
+ @FXML
+ lateinit private var maxPlayersSpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var maxSizeSpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var memorySpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var spawnSpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var simulationSpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var renderSpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var maxTickSpinner: Spinner<kotlin.Int>
+ @FXML
+ lateinit private var progressBar: ProgressBar
+
+ @FXML
+ private fun onDirectoryButtonClick() {
+ val dirChooser = DirectoryChooser()
+ dirChooser.title = "Open a server directory"
+ dirChooser.initialDirectory = File(System.getProperty("user.home"))
+ val result = dirChooser.showDialog(null)
+ if (result != null) {
+ currentDirectoryLabel.text = result.absolutePath
+ parentPane.isDisable = false
+ worldSettingsPane.isDisable = false
+ buttonBar.isDisable = false
+ }
+ }
+
+ @FXML
+ private fun onWorldNameChange() {
+
+ }
+
+ @FXML
+ private fun onSeedChange() {
+
+ }
+
+ @FXML
+ private fun onPortChange() {
+
+ }
+
+ @FXML
+ private fun onCheckboxClick() {
+ }
+
+ @FXML
+ private fun onSpinnerChange() {
+
+ }
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/downloadFile.kt b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/downloadFile.kt
new file mode 100644
index 0000000..bbaeab5
--- /dev/null
+++ b/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/downloadFile.kt
@@ -0,0 +1,37 @@
+import java.net.http.HttpClient
+import kotlinx.coroutines.flow
+
+sealed class DownloadStatus {
+
+ object Success : DownloadStatus()
+
+ data class Error(val message: String) : DownloadStatus()
+
+ data class Progress(val progress: Int): DownloadStatus()
+
+}
+
+// function from https://gist.githubusercontent.com/SG-K/63e379efcc3d1cd3ce4fb56ee0e29c42/raw/cd9a4a016401b7c54ec01303415b5871ffa26066/downloadFile.kt
+suspend fun HttpClient.downloadFile(file: File, url: String): Flow<DownloadStatus> {
+ return flow {
+ val response = call {
+ url(url)
+ method = HttpMethod.Get
+ }.response
+ val byteArray = ByteArray(response.contentLength()!!.toInt())
+ var offset = 0
+ do {
+ val currentRead = response.content.readAvailable(byteArray, offset, byteArray.size)
+ offset += currentRead
+ val progress = (offset * 100f / byteArray.size).roundToInt()
+ emit(DownloadStatus.Progress(progress))
+ } while (currentRead > 0)
+ response.close()
+ if (response.status.isSuccess()) {
+ file.writeBytes(byteArray)
+ emit(DownloadStatus.Success)
+ } else {
+ emit(DownloadStatus.Error("File not downloaded"))
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/resources/xyz/brysonsteck/serverfordummies/primary.fxml b/app/src/main/resources/xyz/brysonsteck/serverfordummies/primary.fxml
new file mode 100644
index 0000000..85b7370
--- /dev/null
+++ b/app/src/main/resources/xyz/brysonsteck/serverfordummies/primary.fxml
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.ButtonBar?>
+<?import javafx.scene.control.CheckBox?>
+<?import javafx.scene.control.ChoiceBox?>
+<?import javafx.scene.control.ContextMenu?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.MenuItem?>
+<?import javafx.scene.control.ProgressBar?>
+<?import javafx.scene.control.Separator?>
+<?import javafx.scene.control.Spinner?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.control.TitledPane?>
+<?import javafx.scene.control.Tooltip?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.Pane?>
+<?import javafx.scene.text.Font?>
+
+<Pane fx:id="primary" maxHeight="900.0" maxWidth="1500.0" minHeight="620.0" minWidth="963.0" prefHeight="708.0" prefWidth="963.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="xyz.brysonsteck.serverfordummies.PrimaryController">
+ <children>
+ <HBox prefHeight="39.0" prefWidth="963.0">
+ <children>
+ <Button id="openFile" fx:id="chooseDirectoryButton" lineSpacing="10.0" mnemonicParsing="false" onMouseClicked="#onDirectoryButtonClick" text="Choose Directory...">
+ <opaqueInsets>
+ <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
+ </opaqueInsets>
+ <HBox.margin>
+ <Insets />
+ </HBox.margin>
+ </Button>
+ <Separator orientation="VERTICAL" prefHeight="200.0">
+ <HBox.margin>
+ <Insets left="5.0" />
+ </HBox.margin>
+ </Separator>
+ <Label text="Server Directory:">
+ <HBox.margin>
+ <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
+ </HBox.margin>
+ <font>
+ <Font name="System Bold" size="13.0" />
+ </font>
+ </Label>
+ <Label id="currentFilename" fx:id="currentDirectoryLabel" text="&lt;NONE&gt;">
+ <HBox.margin>
+ <Insets bottom="5.0" right="5.0" top="5.0" />
+ </HBox.margin>
+ </Label>
+ </children>
+ <padding>
+ <Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
+ </padding>
+ </HBox>
+ <HBox fx:id="worldSettingsPane" disable="true" layoutY="39.0" prefHeight="41.0" prefWidth="963.0">
+ <padding>
+ <Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
+ </padding>
+ <children>
+ <Label text="World Name:">
+ <font>
+ <Font name="System Bold" size="13.0" />
+ </font>
+ <HBox.margin>
+ <Insets bottom="5.0" left="5.0" right="5.0" top="6.0" />
+ </HBox.margin>
+ </Label>
+ <TextField fx:id="worldNameField" onInputMethodTextChanged="#onWorldNameChange">
+ <HBox.margin>
+ <Insets top="2.0" />
+ </HBox.margin>
+ </TextField>
+ <Separator orientation="VERTICAL" prefHeight="200.0">
+ <HBox.margin>
+ <Insets left="5.0" />
+ </HBox.margin>
+ </Separator>
+ <Label text="Seed:">
+ <font>
+ <Font name="System Bold" size="13.0" />
+ </font>
+ <HBox.margin>
+ <Insets bottom="5.0" left="5.0" right="5.0" top="6.0" />
+ </HBox.margin>
+ </Label>
+ <TextField fx:id="seedField" onInputMethodTextChanged="#onSeedChange" prefHeight="23.0" prefWidth="448.0">
+ <HBox.margin>
+ <Insets top="2.0" />
+ </HBox.margin>
+ </TextField>
+ <Separator orientation="VERTICAL" prefHeight="200.0">
+ <HBox.margin>
+ <Insets left="5.0" />
+ </HBox.margin>
+ </Separator>
+ <Label text="Server Port:">
+ <font>
+ <Font name="System Bold" size="13.0" />
+ </font>
+ <HBox.margin>
+ <Insets bottom="5.0" left="5.0" right="5.0" top="6.0" />
+ </HBox.margin>
+ </Label>
+ <Spinner fx:id="portSpinner" onInputMethodTextChanged="#onPortChange" prefHeight="23.0" prefWidth="112.0">
+ <HBox.margin>
+ <Insets top="2.0" />
+ </HBox.margin>
+ </Spinner>
+ </children>
+ <opaqueInsets>
+ <Insets bottom="3.0" />
+ </opaqueInsets>
+ </HBox>
+ <Pane fx:id="parentPane" disable="true" layoutY="78.0" prefHeight="555.0" prefWidth="970.0">
+ <children>
+ <TitledPane fx:id="settingsPane" animated="false" collapsible="false" layoutX="10.0" layoutY="7.0" prefHeight="273.0" prefWidth="627.0" text="Server Settings">
+ <content>
+ <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="311.0" prefWidth="625.0">
+ <children>
+ <CheckBox fx:id="flightCheckbox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onMouseClicked="#onCheckboxClick" text="Allow Flight" />
+ <CheckBox fx:id="netherCheckbox" layoutX="14.0" layoutY="42.0" mnemonicParsing="false" onMouseClicked="#onCheckboxClick" text="Allow The Nether" />
+ <CheckBox fx:id="structuresCheckbox" alignment="TOP_LEFT" layoutX="14.0" layoutY="70.0" mnemonicParsing="false" onMouseClicked="#onCheckboxClick" prefHeight="45.0" prefWidth="231.0" text="Generate Structures&#10;(such as villages and strongholds)" />
+ <CheckBox fx:id="pvpCheckbox" layoutX="14.0" layoutY="109.0" mnemonicParsing="false" onMouseClicked="#onCheckboxClick" text="Allow PvP" />
+ <CheckBox fx:id="whitelistCheckbox" alignment="TOP_LEFT" layoutX="14.0" layoutY="138.0" mnemonicParsing="false" onMouseClicked="#onCheckboxClick" prefHeight="45.0" prefWidth="231.0" text="Enable Whitelist&#10;(Only users you specify can join)" />
+ <Spinner fx:id="maxPlayerSpinner" layoutX="130.0" layoutY="179.0" prefHeight="23.0" prefWidth="99.0" />
+ <Label layoutX="14.0" layoutY="183.0" text="Maximum Players:" />
+ <Spinner fx:id="maxSizeSpinner" layoutX="214.0" layoutY="212.0" prefHeight="23.0" prefWidth="155.0" />
+ <Label layoutX="14.0" layoutY="216.0" text="Maximum World Size (in blocks):" />
+ </children>
+ </AnchorPane>
+ </content>
+ </TitledPane>
+ <TitledPane fx:id="advancedPane" animated="false" layoutX="10.0" layoutY="289.0" prefHeight="259.0" prefWidth="627.0" text="Advanced Server Settings">
+ <content>
+ <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="269.0" prefWidth="625.0">
+ <children>
+ <CheckBox fx:id="cmdBlocksCheckbox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onMouseClicked="#onCheckboxClick" text="Enable Command Blocks" />
+ <CheckBox fx:id="playerCountCheckbox" layoutX="14.0" layoutY="41.0" mnemonicParsing="false" onMouseClicked="#onCheckboxClick" text="Hide Online Player Count" />
+ <Spinner fx:id="memorySpinner" layoutX="154.0" layoutY="69.0" prefHeight="23.0" prefWidth="99.0" />
+ <Label ellipsisString="" layoutX="14.0" layoutY="73.0" text="Server Memory in MB:" textOverrun="CLIP">
+ <tooltip>
+ <Tooltip text="This is the amount of RAM that will get passed to Minecraft/the JVM.&#10;For simple servers, 1024 MB will be plenty.&#10;If you typically have more than 5 concurrent players, consider allocating more." />
+ </tooltip>
+ </Label>
+ <Spinner fx:id="spawnSpinner" layoutX="172.0" layoutY="100.0" prefHeight="23.0" prefWidth="99.0" />
+ <Label layoutX="14.0" layoutY="104.0" text="Spawn Protection Radius:">
+ <tooltip>
+ <Tooltip text="All blocks in a radius from 0,~,0 will be unbreakable. &#10;If you want to break blocks within spawn, change this value." />
+ </tooltip>
+ </Label>
+ <Spinner fx:id="simulationSpinner" layoutX="147.0" layoutY="132.0" prefHeight="23.0" prefWidth="99.0" />
+ <Label layoutX="14.0" layoutY="136.0" text="Simulation Distance:">
+ <tooltip>
+ <Tooltip text="The radius of chunks for each player where ticks will be updated.&#10;In other words, anything outside these circles, such as furnaces, mobs, etc, will not be updated or simulated." />
+ </tooltip>
+ </Label>
+ <Spinner fx:id="renderSpinner" layoutX="124.0" layoutY="165.0" prefHeight="23.0" prefWidth="99.0" />
+ <Label layoutX="14.0" layoutY="169.0" text="Render Distance:">
+ <tooltip>
+ <Tooltip text="The radius of chunks where the server will render the view distance.&#10;Any value higher on a client than what is set will be ignored.&#10;Higher values will be more demanding on the server." />
+ </tooltip>
+ </Label>
+ <Label layoutX="14.0" layoutY="203.0" text="Maximum Tick Time (in milliseconds):">
+ <tooltip>
+ <Tooltip text="If the server cannot update ticks (i.e. &quot;lags&quot;) for longer than this amount of time, the server will shutdown.&#10;60000 ms (60 seconds) is the default." />
+ </tooltip>
+ </Label>
+ <Spinner fx:id="maxTickSpinner" layoutX="246.0" layoutY="199.0" prefHeight="23.0" prefWidth="99.0" />
+ </children>
+ </AnchorPane>
+ </content>
+ </TitledPane>
+ <TitledPane fx:id="difficultyPane" animated="false" collapsible="false" layoutX="649.0" layoutY="7.0" prefHeight="77.0" prefWidth="305.0" text="Difficulty">
+ <content>
+ <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="94.0" prefWidth="303.0">
+ <children>
+ <ChoiceBox fx:id="difficultyBox" layoutX="14.0" layoutY="14.0" prefHeight="23.0" prefWidth="276.0">
+ <contextMenu>
+ <ContextMenu>
+ <items>
+ <MenuItem mnemonicParsing="false" />
+ </items>
+ </ContextMenu>
+ </contextMenu>
+ </ChoiceBox>
+ </children>
+ </AnchorPane>
+ </content>
+ </TitledPane>
+ <TitledPane fx:id="gamemodePane" animated="false" collapsible="false" layoutX="649.0" layoutY="92.0" prefHeight="77.0" prefWidth="305.0" text="Gamemode">
+ <content>
+ <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="94.0" prefWidth="303.0">
+ <children>
+ <ChoiceBox fx:id="gamemodeBox" layoutX="14.0" layoutY="14.0" prefHeight="23.0" prefWidth="276.0" />
+ </children>
+ </AnchorPane>
+ </content>
+ </TitledPane>
+ <TitledPane fx:id="worldTypePane" animated="false" collapsible="false" layoutX="649.0" layoutY="178.0" prefHeight="77.0" prefWidth="305.0" text="World Type">
+ <content>
+ <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="94.0" prefWidth="303.0">
+ <children>
+ <ChoiceBox fx:id="worldTypeBox" layoutX="14.0" layoutY="14.0" prefHeight="23.0" prefWidth="276.0" />
+ </children>
+ </AnchorPane>
+ </content>
+ </TitledPane>
+ <TitledPane fx:id="worldTypePane1" animated="false" collapsible="false" layoutX="649.0" layoutY="265.0" prefHeight="283.0" prefWidth="305.0" text="Whitelist">
+ <content>
+ <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="94.0" prefWidth="303.0">
+ <children>
+ <ChoiceBox layoutX="14.0" layoutY="14.0" prefHeight="23.0" prefWidth="276.0" />
+ </children>
+ </AnchorPane>
+ </content>
+ </TitledPane>
+ </children>
+ </Pane>
+ <ButtonBar fx:id="buttonBar" disable="true" layoutY="635.0" prefHeight="40.0" prefWidth="963.0">
+ <buttons>
+ <Button mnemonicParsing="false" text="Build Server" />
+ <Button defaultButton="true" mnemonicParsing="false" text="Start Server" />
+ </buttons>
+ <padding>
+ <Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
+ </padding>
+ </ButtonBar>
+ <HBox layoutY="680.0" prefHeight="33.0" prefWidth="963.0" style="-fx-background-color: ddd;">
+ <children>
+ <Label text="Status:">
+ <font>
+ <Font name="System Bold" size="13.0" />
+ </font>
+ </Label>
+ <Label fx:id="statusBar" text="Ready.">
+ <HBox.margin>
+ <Insets left="5.0" />
+ </HBox.margin>
+ </Label>
+ <ProgressBar fx:id="progressBar" prefWidth="400.0" progress="0.0" visible="false">
+ <HBox.margin>
+ <Insets left="460.0" />
+ </HBox.margin>
+ </ProgressBar>
+ </children>
+ <padding>
+ <Insets bottom="9.0" left="9.0" right="9.0" top="9.0" />
+ </padding>
+ </HBox>
+ </children>
+</Pane>
diff --git a/app/src/test/kotlin/xyz/brysonsteck/serverfordummies/AppTest.kt b/app/src/test/kotlin/xyz/brysonsteck/serverfordummies/AppTest.kt
new file mode 100644
index 0000000..e1d1866
--- /dev/null
+++ b/app/src/test/kotlin/xyz/brysonsteck/serverfordummies/AppTest.kt
@@ -0,0 +1,14 @@
+/*
+ * This Kotlin source file was generated by the Gradle 'init' task.
+ */
+package xyz.brysonsteck.serverfordummies
+
+import kotlin.test.Test
+import kotlin.test.assertNotNull
+
+class AppTest {
+ // @Test fun appHasAGreeting() {
+ // val classUnderTest = App()
+ // assertNotNull(classUnderTest.greeting, "app should have a greeting")
+ // }
+}