window resizing works, need to refine further
This commit is contained in:
parent
9a16ada0f6
commit
e674df1cd3
13 changed files with 721 additions and 710 deletions
|
@ -1,25 +1,26 @@
|
||||||
package xyz.brysonsteck.ServerCraft
|
package xyz.brysonsteck.ServerCraft
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene
|
||||||
import javafx.scene.image.Image
|
import javafx.scene.image.Image
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage
|
||||||
import java.awt.Desktop;
|
|
||||||
|
|
||||||
class App : Application() {
|
class App : Application() {
|
||||||
|
|
||||||
override fun start(stage: Stage) {
|
override fun start(stage: Stage) {
|
||||||
var scene = Scene(loadFXML("primary"), 963.0, 713.0)
|
var scene = Scene(loadFXML("primary"), 963.0, 713.0)
|
||||||
|
// Application.setUserAgentStylesheet(CupertinoLight().getUserAgentStylesheet())
|
||||||
|
scene.stylesheets.add(this.javaClass.getResource("css/style.css").toExternalForm())
|
||||||
stage.icons.add(Image(this.javaClass.getResourceAsStream("app.png")))
|
stage.icons.add(Image(this.javaClass.getResourceAsStream("app.png")))
|
||||||
stage.setResizable(false)
|
stage.setResizable(true)
|
||||||
stage.title = "ServerCraft"
|
stage.title = "ServerCraft"
|
||||||
stage.scene = scene
|
stage.scene = scene
|
||||||
stage.show()
|
stage.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun loadFXML(fxml: String) : Parent {
|
public fun loadFXML(fxml: String): Parent {
|
||||||
val fxmlLoader = FXMLLoader(this.javaClass.getResource(fxml + ".fxml"))
|
val fxmlLoader = FXMLLoader(this.javaClass.getResource(fxml + ".fxml"))
|
||||||
return fxmlLoader.load()
|
return fxmlLoader.load()
|
||||||
}
|
}
|
||||||
|
@ -27,5 +28,4 @@ class App : Application() {
|
||||||
public fun run() {
|
public fun run() {
|
||||||
launch()
|
launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,4 @@ package xyz.brysonsteck.ServerCraft
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
App().run()
|
App().run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,21 @@
|
||||||
package xyz.brysonsteck.ServerCraft.controllers
|
package xyz.brysonsteck.ServerCraft.controllers
|
||||||
|
|
||||||
|
import java.awt.Desktop
|
||||||
|
import java.net.URI
|
||||||
|
import java.util.Properties
|
||||||
|
import javafx.event.ActionEvent
|
||||||
import javafx.fxml.FXML
|
import javafx.fxml.FXML
|
||||||
import javafx.application.Platform
|
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
import javafx.scene.control.Hyperlink
|
import javafx.scene.control.Hyperlink
|
||||||
import javafx.scene.control.Label
|
import javafx.scene.control.Label
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import javafx.event.ActionEvent
|
|
||||||
import java.awt.Desktop
|
|
||||||
import java.net.URI
|
|
||||||
import java.util.Properties
|
|
||||||
import xyz.brysonsteck.ServerCraft.App
|
import xyz.brysonsteck.ServerCraft.App
|
||||||
|
|
||||||
class InfoController {
|
class InfoController {
|
||||||
@FXML
|
@FXML lateinit private var version: Label
|
||||||
lateinit private var version: Label
|
|
||||||
|
|
||||||
private val emails = mapOf(
|
private val emails = mapOf("bryson" to "me@brysonsteck.xyz")
|
||||||
"bryson" to "me@brysonsteck.xyz"
|
private val websites = mapOf("bryson" to "https://brysonsteck.xyz")
|
||||||
)
|
|
||||||
private val websites = mapOf(
|
|
||||||
"bryson" to "https://brysonsteck.xyz"
|
|
||||||
)
|
|
||||||
private val source = "https://codeberg.org/brysonsteck/ServerCraft"
|
private val source = "https://codeberg.org/brysonsteck/ServerCraft"
|
||||||
private val license = "https://www.gnu.org/licenses/gpl-3.0.html"
|
private val license = "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
|
|
||||||
|
@ -79,8 +73,8 @@ class InfoController {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private fun closeInfo(e: ActionEvent) {
|
private fun closeInfo(e: ActionEvent) {
|
||||||
val source = e.getSource() as Node
|
val source = e.getSource() as Node
|
||||||
val stage = source.getScene().getWindow() as Stage
|
val stage = source.getScene().getWindow() as Stage
|
||||||
stage.close();
|
stage.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,136 +1,76 @@
|
||||||
package xyz.brysonsteck.ServerCraft.controllers
|
package xyz.brysonsteck.ServerCraft.controllers
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.javafx.JavaFx
|
|
||||||
import org.rauschig.jarchivelib.*
|
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.BufferedReader
|
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.awt.Checkbox
|
|
||||||
import java.awt.Desktop
|
|
||||||
import java.util.Properties
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.net.URI
|
|
||||||
|
|
||||||
import javafx.beans.value.ChangeListener
|
|
||||||
import javafx.beans.value.ObservableValue
|
|
||||||
import javafx.concurrent.Task
|
|
||||||
import javafx.beans.property.BooleanProperty
|
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
|
import javafx.event.ActionEvent
|
||||||
import javafx.fxml.FXML
|
import javafx.fxml.FXML
|
||||||
import javafx.fxml.FXMLLoader
|
import javafx.fxml.FXMLLoader
|
||||||
import javafx.geometry.Insets
|
import javafx.scene.Scene
|
||||||
import javafx.scene.control.Button
|
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.ButtonBar
|
||||||
import javafx.scene.control.CheckBox
|
import javafx.scene.control.CheckBox
|
||||||
|
import javafx.scene.control.ChoiceBox
|
||||||
|
import javafx.scene.control.Label
|
||||||
import javafx.scene.control.ProgressBar
|
import javafx.scene.control.ProgressBar
|
||||||
import javafx.scene.control.Hyperlink
|
|
||||||
import javafx.scene.control.ScrollPane
|
import javafx.scene.control.ScrollPane
|
||||||
import javafx.scene.layout.Border
|
import javafx.scene.control.Spinner
|
||||||
import javafx.scene.layout.BorderStroke
|
import javafx.scene.control.TextField
|
||||||
import javafx.scene.layout.GridPane
|
|
||||||
import javafx.scene.layout.Pane
|
|
||||||
import javafx.scene.layout.HBox
|
|
||||||
import javafx.scene.layout.VBox
|
|
||||||
import javafx.scene.text.TextAlignment
|
|
||||||
import javafx.scene.text.Text
|
|
||||||
import javafx.scene.Scene
|
|
||||||
import javafx.scene.input.MouseEvent
|
|
||||||
import javafx.scene.image.Image
|
import javafx.scene.image.Image
|
||||||
import javafx.scene.image.ImageView
|
import javafx.scene.image.ImageView
|
||||||
import javafx.stage.FileChooser
|
import javafx.scene.layout.HBox
|
||||||
import javafx.stage.FileChooser.ExtensionFilter
|
import javafx.scene.layout.Pane
|
||||||
import javafx.stage.DirectoryChooser
|
import javafx.stage.DirectoryChooser
|
||||||
import javafx.stage.Modality
|
import javafx.stage.Modality
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import javafx.event.EventHandler
|
import kotlinx.coroutines.*
|
||||||
import javafx.event.ActionEvent
|
import kotlinx.coroutines.javafx.JavaFx
|
||||||
import org.rauschig.jarchivelib.*
|
import org.rauschig.jarchivelib.*
|
||||||
|
|
||||||
import xyz.brysonsteck.ServerCraft.server.Server
|
|
||||||
import xyz.brysonsteck.ServerCraft.server.Download
|
|
||||||
import xyz.brysonsteck.ServerCraft.App
|
import xyz.brysonsteck.ServerCraft.App
|
||||||
import xyz.brysonsteck.ServerCraft.dialogs.Dialog
|
|
||||||
import xyz.brysonsteck.ServerCraft.dialogs.CommonDialog
|
import xyz.brysonsteck.ServerCraft.dialogs.CommonDialog
|
||||||
import xyz.brysonsteck.ServerCraft.dialogs.KillDialog
|
import xyz.brysonsteck.ServerCraft.dialogs.Dialog
|
||||||
import xyz.brysonsteck.ServerCraft.dialogs.EulaDialog
|
import xyz.brysonsteck.ServerCraft.dialogs.EulaDialog
|
||||||
|
import xyz.brysonsteck.ServerCraft.dialogs.KillDialog
|
||||||
|
import xyz.brysonsteck.ServerCraft.server.Download
|
||||||
|
import xyz.brysonsteck.ServerCraft.server.Server
|
||||||
|
|
||||||
class PrimaryController {
|
class PrimaryController {
|
||||||
@FXML
|
@FXML lateinit private var primary: Pane
|
||||||
lateinit private var primary: Pane
|
@FXML lateinit private var currentDirectoryLabel: Label
|
||||||
@FXML
|
@FXML lateinit private var worldNameField: TextField
|
||||||
lateinit private var currentDirectoryLabel: Label
|
@FXML lateinit private var seedField: TextField
|
||||||
@FXML
|
@FXML lateinit private var portSpinner: Spinner<kotlin.Int>
|
||||||
lateinit private var worldNameField: TextField
|
@FXML lateinit private var difficultyBox: ChoiceBox<String>
|
||||||
@FXML
|
@FXML lateinit private var gamemodeBox: ChoiceBox<String>
|
||||||
lateinit private var seedField: TextField
|
@FXML lateinit private var worldTypeBox: ChoiceBox<String>
|
||||||
@FXML
|
@FXML lateinit private var worldSettingsPane: HBox
|
||||||
lateinit private var portSpinner: Spinner<kotlin.Int>
|
@FXML lateinit private var parentPane: Pane
|
||||||
@FXML
|
@FXML lateinit private var directoryPane: Pane
|
||||||
lateinit private var difficultyBox: ChoiceBox<String>
|
@FXML lateinit private var buttonBar: ButtonBar
|
||||||
@FXML
|
@FXML lateinit private var flightCheckbox: CheckBox
|
||||||
lateinit private var gamemodeBox: ChoiceBox<String>
|
@FXML lateinit private var netherCheckbox: CheckBox
|
||||||
@FXML
|
@FXML lateinit private var structuresCheckbox: CheckBox
|
||||||
lateinit private var worldTypeBox: ChoiceBox<String>
|
@FXML lateinit private var pvpCheckbox: CheckBox
|
||||||
@FXML
|
@FXML lateinit private var whitelistCheckbox: CheckBox
|
||||||
lateinit private var worldSettingsPane: HBox
|
@FXML lateinit private var cmdBlocksCheckbox: CheckBox
|
||||||
@FXML
|
@FXML lateinit private var playerCountCheckbox: CheckBox
|
||||||
lateinit private var parentPane: Pane
|
@FXML lateinit private var maxPlayerSpinner: Spinner<kotlin.Int>
|
||||||
@FXML
|
@FXML lateinit private var maxSizeSpinner: Spinner<kotlin.Int>
|
||||||
lateinit private var directoryPane: Pane
|
@FXML lateinit private var memorySpinner: Spinner<kotlin.Int>
|
||||||
@FXML
|
@FXML lateinit private var spawnSpinner: Spinner<kotlin.Int>
|
||||||
lateinit private var buttonBar: ButtonBar
|
@FXML lateinit private var simulationSpinner: Spinner<kotlin.Int>
|
||||||
@FXML
|
@FXML lateinit private var renderSpinner: Spinner<kotlin.Int>
|
||||||
lateinit private var flightCheckbox: CheckBox
|
@FXML lateinit private var maxTickSpinner: Spinner<kotlin.Int>
|
||||||
@FXML
|
@FXML lateinit private var statusBar: Label
|
||||||
lateinit private var netherCheckbox: CheckBox
|
@FXML lateinit private var progressBar: ProgressBar
|
||||||
@FXML
|
@FXML lateinit private var startButton: Button
|
||||||
lateinit private var structuresCheckbox: CheckBox
|
@FXML lateinit private var buildButton: Button
|
||||||
@FXML
|
@FXML lateinit private var defaultsButton: Button
|
||||||
lateinit private var pvpCheckbox: CheckBox
|
@FXML lateinit private var dropDownIcon: ImageView
|
||||||
@FXML
|
@FXML lateinit private var console: Label
|
||||||
lateinit private var whitelistCheckbox: CheckBox
|
@FXML lateinit private var scrollPane: ScrollPane
|
||||||
@FXML
|
|
||||||
lateinit private var cmdBlocksCheckbox: CheckBox
|
|
||||||
@FXML
|
|
||||||
lateinit private var playerCountCheckbox: CheckBox
|
|
||||||
@FXML
|
|
||||||
lateinit private var maxPlayerSpinner: 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 statusBar: Label
|
|
||||||
@FXML
|
|
||||||
lateinit private var progressBar: ProgressBar
|
|
||||||
@FXML
|
|
||||||
lateinit private var startButton: Button
|
|
||||||
@FXML
|
|
||||||
lateinit private var buildButton: Button
|
|
||||||
@FXML
|
|
||||||
lateinit private var defaultsButton: Button
|
|
||||||
@FXML
|
|
||||||
lateinit private var dropDownIcon: ImageView
|
|
||||||
@FXML
|
|
||||||
lateinit private var console: Label
|
|
||||||
@FXML
|
|
||||||
lateinit private var scrollPane: ScrollPane
|
|
||||||
|
|
||||||
lateinit private var server: Server
|
lateinit private var server: Server
|
||||||
lateinit private var killDialog: Dialog
|
lateinit private var killDialog: Dialog
|
||||||
|
@ -150,97 +90,84 @@ class PrimaryController {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public fun initialize() {
|
public fun initialize() {
|
||||||
scrollPane.vvalueProperty().bind(console.heightProperty());
|
// scrollPane.vvalueProperty().bind(console.heightProperty());
|
||||||
difficultyBox.items = FXCollections.observableArrayList(
|
difficultyBox.items =
|
||||||
"Peaceful",
|
FXCollections.observableArrayList("Peaceful", "Easy", "Normal", "Hard", "Hardcore")
|
||||||
"Easy",
|
|
||||||
"Normal",
|
|
||||||
"Hard",
|
|
||||||
"Hardcore"
|
|
||||||
)
|
|
||||||
difficultyBox.value = "Normal"
|
difficultyBox.value = "Normal"
|
||||||
difficultyBox.selectionModel.selectedIndexProperty().addListener { _, _, new ->
|
difficultyBox.selectionModel.selectedIndexProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("difficulty", difficultyBox.items[new as Int])
|
onPropChange("difficulty", difficultyBox.items[new as Int])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gamemodeBox.items = FXCollections.observableArrayList(
|
gamemodeBox.items =
|
||||||
"Survival",
|
FXCollections.observableArrayList("Survival", "Creative", "Adventure", "Spectator")
|
||||||
"Creative",
|
|
||||||
"Adventure",
|
|
||||||
"Spectator"
|
|
||||||
)
|
|
||||||
gamemodeBox.value = "Survival"
|
gamemodeBox.value = "Survival"
|
||||||
gamemodeBox.selectionModel.selectedIndexProperty().addListener { _, _, new ->
|
gamemodeBox.selectionModel.selectedIndexProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("gamemode", gamemodeBox.items[new as Int])
|
onPropChange("gamemode", gamemodeBox.items[new as Int])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
worldTypeBox.items = FXCollections.observableArrayList(
|
worldTypeBox.items =
|
||||||
"Normal",
|
FXCollections.observableArrayList("Normal", "Superflat", "Large Biomes", "Amplified")
|
||||||
"Superflat",
|
|
||||||
"Large Biomes",
|
|
||||||
"Amplified"
|
|
||||||
)
|
|
||||||
worldTypeBox.value = "Normal"
|
worldTypeBox.value = "Normal"
|
||||||
worldTypeBox.selectionModel.selectedIndexProperty().addListener { _, _, new ->
|
worldTypeBox.selectionModel.selectedIndexProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("level-type", worldTypeBox.items[new as Int])
|
onPropChange("level-type", worldTypeBox.items[new as Int])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxPlayerSpinner.editor.textProperty().addListener { _, _, new ->
|
maxPlayerSpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("max-players", new)
|
onPropChange("max-players", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxSizeSpinner.editor.textProperty().addListener { _, _, new ->
|
maxSizeSpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("max-world-size", new)
|
onPropChange("max-world-size", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portSpinner.editor.textProperty().addListener { _, _, new ->
|
portSpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("server-port", new)
|
onPropChange("server-port", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderSpinner.editor.textProperty().addListener { _, _, new ->
|
renderSpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("view-distance", new)
|
onPropChange("view-distance", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memorySpinner.editor.textProperty().addListener { _, _, new ->
|
memorySpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("jvm-ram", new)
|
onPropChange("jvm-ram", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spawnSpinner.editor.textProperty().addListener { _, _, new ->
|
spawnSpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("spawn-protection", new)
|
onPropChange("spawn-protection", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
simulationSpinner.editor.textProperty().addListener { _, _, new ->
|
simulationSpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("simulation-distance", new)
|
onPropChange("simulation-distance", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxTickSpinner.editor.textProperty().addListener { _, _, new ->
|
maxTickSpinner.editor.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("max-tick-time", new)
|
onPropChange("max-tick-time", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
worldNameField.textProperty().addListener { _, _, new ->
|
worldNameField.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("level-name", new)
|
onPropChange("level-name", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seedField.textProperty().addListener { _, _, new ->
|
seedField.textProperty().addListener { _, _, new ->
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
onPropChange("level-seed", new)
|
onPropChange("level-seed", new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
killDialog = KillDialog()
|
killDialog = KillDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private fun onDirectoryButtonClick() {
|
private fun onDirectoryButtonClick() {
|
||||||
val dirChooser = DirectoryChooser()
|
val dirChooser = DirectoryChooser()
|
||||||
|
@ -293,14 +220,17 @@ class PrimaryController {
|
||||||
spawnSpinner.valueFactory.value = server.getProp("spawn-protection").toIntOrNull()
|
spawnSpinner.valueFactory.value = server.getProp("spawn-protection").toIntOrNull()
|
||||||
simulationSpinner.valueFactory.value = server.getProp("simulation-distance").toIntOrNull()
|
simulationSpinner.valueFactory.value = server.getProp("simulation-distance").toIntOrNull()
|
||||||
maxTickSpinner.valueFactory.value = server.getProp("max-tick-time").toIntOrNull()
|
maxTickSpinner.valueFactory.value = server.getProp("max-tick-time").toIntOrNull()
|
||||||
difficultyBox.value = if (parseBool(server.getProp("hardcore"))) {
|
difficultyBox.value =
|
||||||
"Hardcore"
|
if (parseBool(server.getProp("hardcore"))) {
|
||||||
} else {
|
"Hardcore"
|
||||||
server.getProp("difficulty").replaceFirstChar { it.uppercase() }
|
} else {
|
||||||
}
|
server.getProp("difficulty").replaceFirstChar { it.uppercase() }
|
||||||
|
}
|
||||||
gamemodeBox.value = server.getProp("gamemode").replaceFirstChar { it.uppercase() }
|
gamemodeBox.value = server.getProp("gamemode").replaceFirstChar { it.uppercase() }
|
||||||
worldTypeBox.value = server.getProp("level-type").removePrefix("minecraft:")
|
worldTypeBox.value =
|
||||||
.split('_').joinToString(" ") { it.replaceFirstChar(Char::uppercaseChar)}
|
server.getProp("level-type").removePrefix("minecraft:").split('_').joinToString(" ") {
|
||||||
|
it.replaceFirstChar(Char::uppercaseChar)
|
||||||
|
}
|
||||||
worldNameField.text = server.getProp("level-name")
|
worldNameField.text = server.getProp("level-name")
|
||||||
seedField.text = server.getProp("level-seed")
|
seedField.text = server.getProp("level-seed")
|
||||||
loading = false
|
loading = false
|
||||||
|
@ -373,7 +303,13 @@ class PrimaryController {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private fun onDefaults() {
|
private fun onDefaults() {
|
||||||
val res = CommonDialog("info", "Reset all settings?", "Reset settings to defaults?\nThere is NO GOING BACK!").show()
|
val res =
|
||||||
|
CommonDialog(
|
||||||
|
"info",
|
||||||
|
"Reset all settings?",
|
||||||
|
"Reset settings to defaults?\nThere is NO GOING BACK!"
|
||||||
|
)
|
||||||
|
.show()
|
||||||
if (res) {
|
if (res) {
|
||||||
server.loadProps()
|
server.loadProps()
|
||||||
applyProps()
|
applyProps()
|
||||||
|
@ -387,7 +323,7 @@ class PrimaryController {
|
||||||
val scene = Scene(FXMLLoader(App().javaClass.getResource("info.fxml")).load(), 398.0, 358.0)
|
val scene = Scene(FXMLLoader(App().javaClass.getResource("info.fxml")).load(), 398.0, 358.0)
|
||||||
stage.icons.add(Image(App().javaClass.getResourceAsStream("app.png")))
|
stage.icons.add(Image(App().javaClass.getResourceAsStream("app.png")))
|
||||||
stage.setResizable(false)
|
stage.setResizable(false)
|
||||||
stage.initModality(Modality.APPLICATION_MODAL);
|
stage.initModality(Modality.APPLICATION_MODAL)
|
||||||
stage.title = "About ServerCraft"
|
stage.title = "About ServerCraft"
|
||||||
stage.scene = scene
|
stage.scene = scene
|
||||||
stage.show()
|
stage.show()
|
||||||
|
@ -399,7 +335,7 @@ class PrimaryController {
|
||||||
building = false
|
building = false
|
||||||
statusBar.text = "Cancelling..."
|
statusBar.text = "Cancelling..."
|
||||||
buildButton.isDisable = true
|
buildButton.isDisable = true
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
building = true
|
building = true
|
||||||
worldSettingsPane.isDisable = true
|
worldSettingsPane.isDisable = true
|
||||||
|
@ -429,24 +365,28 @@ class PrimaryController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// download files
|
// download files
|
||||||
val downloads = mapOf(
|
val downloads =
|
||||||
"Java 20" to "https://download.java.net/java/GA/jdk20.0.1/b4887098932d415489976708ad6d1a4b/9/GPL/${javaFile}",
|
mapOf(
|
||||||
"BuildTools" to "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar",
|
"Java 20" to
|
||||||
)
|
"https://download.java.net/java/GA/jdk20.0.1/b4887098932d415489976708ad6d1a4b/9/GPL/${javaFile}",
|
||||||
val destinations = mapOf (
|
"BuildTools" to
|
||||||
"Java 20" to directory + "ServerCraft" + File.separator + "Java" + File.separator,
|
"https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar",
|
||||||
"BuildTools" to directory + "ServerCraft" + File.separator + "Spigot" + File.separator
|
)
|
||||||
)
|
val destinations =
|
||||||
|
mapOf(
|
||||||
|
"Java 20" to
|
||||||
|
directory + "ServerCraft" + File.separator + "Java" + File.separator,
|
||||||
|
"BuildTools" to
|
||||||
|
directory + "ServerCraft" + File.separator + "Spigot" + File.separator
|
||||||
|
)
|
||||||
val spigotBuilt = File(destinations["BuildTools"]).exists()
|
val spigotBuilt = File(destinations["BuildTools"]).exists()
|
||||||
val javaExtracted = File(destinations["Java 20"] + "jdk-20.0.1").exists()
|
val javaExtracted = File(destinations["Java 20"] + "jdk-20.0.1").exists()
|
||||||
destinations.forEach {
|
destinations.forEach { File(it.value).mkdir() }
|
||||||
File(it.value).mkdir()
|
|
||||||
}
|
|
||||||
downloads.forEach {
|
downloads.forEach {
|
||||||
if (it.key == "Java 20" && javaExtracted) {
|
if (it.key == "Java 20" && javaExtracted) {
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.JavaFx){
|
withContext(Dispatchers.JavaFx) {
|
||||||
statusBar.text = "Downloading ${it.key}..."
|
statusBar.text = "Downloading ${it.key}..."
|
||||||
progressBar.progress = ProgressBar.INDETERMINATE_PROGRESS
|
progressBar.progress = ProgressBar.INDETERMINATE_PROGRESS
|
||||||
log("Downloading ${it.key} from ${it.value}\n")
|
log("Downloading ${it.key} from ${it.value}\n")
|
||||||
|
@ -455,15 +395,18 @@ class PrimaryController {
|
||||||
download.start()
|
download.start()
|
||||||
while (download.status == Download.Status.DOWNLOADING) {
|
while (download.status == Download.Status.DOWNLOADING) {
|
||||||
var prog = (download.downloaded.toDouble() / download.contentLength.toDouble())
|
var prog = (download.downloaded.toDouble() / download.contentLength.toDouble())
|
||||||
// for whatever reason I need to print something to the screen in order for it to update the progress bar
|
// for whatever reason I need to print something to the screen in order for it to update
|
||||||
withContext(Dispatchers.JavaFx) {log("Progress: ${prog * 100}%\n")}
|
// the progress bar
|
||||||
|
withContext(Dispatchers.JavaFx) { log("Progress: ${prog * 100}%\n") }
|
||||||
if (prog >= 0.01) {
|
if (prog >= 0.01) {
|
||||||
withContext(Dispatchers.JavaFx) {progressBar.progress = prog}
|
withContext(Dispatchers.JavaFx) { progressBar.progress = prog }
|
||||||
}
|
}
|
||||||
if (!building) download.status = Download.Status.CANCELLED
|
if (!building) download.status = Download.Status.CANCELLED
|
||||||
Thread.sleep(300)
|
Thread.sleep(300)
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.JavaFx) {log("Download of ${it.key} complete with status: ${download.status}\n")}
|
withContext(Dispatchers.JavaFx) {
|
||||||
|
log("Download of ${it.key} complete with status: ${download.status}\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract java archive
|
// extract java archive
|
||||||
|
@ -473,18 +416,38 @@ class PrimaryController {
|
||||||
statusBar.text = "Extracting Java archive..."
|
statusBar.text = "Extracting Java archive..."
|
||||||
log("Extracting Java archive to ${directory + "ServerCraft" + File.separator + "Java"}\n")
|
log("Extracting Java archive to ${directory + "ServerCraft" + File.separator + "Java"}\n")
|
||||||
}
|
}
|
||||||
var stream = archiver.stream(File(directory + "ServerCraft" + File.separator + "Java" + File.separator + javaFile))
|
var stream =
|
||||||
|
archiver.stream(
|
||||||
|
File(
|
||||||
|
directory +
|
||||||
|
"ServerCraft" +
|
||||||
|
File.separator +
|
||||||
|
"Java" +
|
||||||
|
File.separator +
|
||||||
|
javaFile
|
||||||
|
)
|
||||||
|
)
|
||||||
val dest = File(directory + "ServerCraft" + File.separator + "Java")
|
val dest = File(directory + "ServerCraft" + File.separator + "Java")
|
||||||
var entries = 0.0
|
var entries = 0.0
|
||||||
while(stream.getNextEntry() != null && building) {
|
while (stream.getNextEntry() != null && building) {
|
||||||
entries++
|
entries++
|
||||||
}
|
}
|
||||||
stream = archiver.stream(File(directory + "ServerCraft" + File.separator + "Java" + File.separator + javaFile))
|
stream =
|
||||||
|
archiver.stream(
|
||||||
|
File(
|
||||||
|
directory +
|
||||||
|
"ServerCraft" +
|
||||||
|
File.separator +
|
||||||
|
"Java" +
|
||||||
|
File.separator +
|
||||||
|
javaFile
|
||||||
|
)
|
||||||
|
)
|
||||||
var entry = stream.getNextEntry()
|
var entry = stream.getNextEntry()
|
||||||
var currentEntry = 0.0
|
var currentEntry = 0.0
|
||||||
do {
|
do {
|
||||||
withContext(Dispatchers.JavaFx) {
|
withContext(Dispatchers.JavaFx) {
|
||||||
progressBar.progress = currentEntry/entries
|
progressBar.progress = currentEntry / entries
|
||||||
log(entry.name + "\n")
|
log(entry.name + "\n")
|
||||||
}
|
}
|
||||||
entry.extract(dest)
|
entry.extract(dest)
|
||||||
|
@ -498,7 +461,16 @@ class PrimaryController {
|
||||||
progressBar.progress = ProgressBar.INDETERMINATE_PROGRESS
|
progressBar.progress = ProgressBar.INDETERMINATE_PROGRESS
|
||||||
statusBar.text = "Building Minecraft Server..."
|
statusBar.text = "Building Minecraft Server..."
|
||||||
}
|
}
|
||||||
val builder = ProcessBuilder("${directory}ServerCraft${File.separator}Java${File.separator}jdk-20.0.1${File.separator}bin${File.separator}java", "-jar", "BuildTools.jar", "--rev", "latest", "-o", ".." + File.separator + ".." + File.separator)
|
val builder =
|
||||||
|
ProcessBuilder(
|
||||||
|
"${directory}ServerCraft${File.separator}Java${File.separator}jdk-20.0.1${File.separator}bin${File.separator}java",
|
||||||
|
"-jar",
|
||||||
|
"BuildTools.jar",
|
||||||
|
"--rev",
|
||||||
|
"latest",
|
||||||
|
"-o",
|
||||||
|
".." + File.separator + ".." + File.separator
|
||||||
|
)
|
||||||
builder.directory(File(directory + "ServerCraft" + File.separator + "Spigot"))
|
builder.directory(File(directory + "ServerCraft" + File.separator + "Spigot"))
|
||||||
val proc = builder.start()
|
val proc = builder.start()
|
||||||
val reader = InputStreamReader(proc.inputStream)
|
val reader = InputStreamReader(proc.inputStream)
|
||||||
|
@ -509,40 +481,48 @@ class PrimaryController {
|
||||||
if (!building) {
|
if (!building) {
|
||||||
proc.destroy()
|
proc.destroy()
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.JavaFx) {log(cbuf.joinToString(separator=""))}
|
withContext(Dispatchers.JavaFx) { log(cbuf.joinToString(separator = "")) }
|
||||||
cbuf = CharArray(1000)
|
cbuf = CharArray(1000)
|
||||||
reader.read(cbuf, 0, 1000)
|
reader.read(cbuf, 0, 1000)
|
||||||
currentline++
|
currentline++
|
||||||
if (currentline > 15) {
|
if (currentline > 15) {
|
||||||
withContext(Dispatchers.JavaFx) {progressBar.progress = if (spigotBuilt) {currentline/1100.0} else {currentline/14122.0} }
|
withContext(Dispatchers.JavaFx) {
|
||||||
|
progressBar.progress =
|
||||||
|
if (spigotBuilt) {
|
||||||
|
currentline / 1100.0
|
||||||
|
} else {
|
||||||
|
currentline / 14122.0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cbuf = CharArray(1000)
|
cbuf = CharArray(1000)
|
||||||
reader.read(cbuf, 0, 1000)
|
reader.read(cbuf, 0, 1000)
|
||||||
withContext(Dispatchers.JavaFx) {log(cbuf.joinToString(separator=""))}
|
withContext(Dispatchers.JavaFx) { log(cbuf.joinToString(separator = "")) }
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
withContext(Dispatchers.JavaFx) {log("Stream Closed\n")}
|
withContext(Dispatchers.JavaFx) { log("Stream Closed\n") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progressBar.isVisible = false
|
progressBar.isVisible = false
|
||||||
findServerJar()
|
findServerJar()
|
||||||
withContext(Dispatchers.JavaFx){
|
withContext(Dispatchers.JavaFx) {
|
||||||
worldSettingsPane.isDisable = false
|
worldSettingsPane.isDisable = false
|
||||||
directoryPane.isDisable = false
|
directoryPane.isDisable = false
|
||||||
parentPane.isDisable = false
|
parentPane.isDisable = false
|
||||||
defaultsButton.isDisable = false
|
defaultsButton.isDisable = false
|
||||||
buildButton.text = "Build Server"
|
buildButton.text = "Build Server"
|
||||||
buildButton.isDisable = false
|
buildButton.isDisable = false
|
||||||
statusBar.text = if (building) {
|
statusBar.text =
|
||||||
findServerJar()
|
if (building) {
|
||||||
buildButton.text = "Rebuild Server"
|
findServerJar()
|
||||||
startButton.isDisable = false
|
buildButton.text = "Rebuild Server"
|
||||||
"Ready."
|
startButton.isDisable = false
|
||||||
} else {
|
"Ready."
|
||||||
"Server build cancelled."
|
} else {
|
||||||
}
|
"Server build cancelled."
|
||||||
building = false;
|
}
|
||||||
|
building = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -551,18 +531,19 @@ class PrimaryController {
|
||||||
private fun onStart() {
|
private fun onStart() {
|
||||||
if (started) {
|
if (started) {
|
||||||
killDialog.show()
|
killDialog.show()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (!File(directory + "eula.txt").exists()) {
|
if (!File(directory + "eula.txt").exists()) {
|
||||||
val res = EulaDialog().show()
|
val res = EulaDialog().show()
|
||||||
if (res) {
|
if (res) {
|
||||||
File(directory + "eula.txt").writeText("eula=true")
|
File(directory + "eula.txt").writeText("eula=true")
|
||||||
} else {
|
} else {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
started = true
|
started = true
|
||||||
statusBar.text = "The Minecraft Server is now running. Shutdown the server to unlock the settings."
|
statusBar.text =
|
||||||
|
"The Minecraft Server is now running. Shutdown the server to unlock the settings."
|
||||||
worldSettingsPane.isDisable = true
|
worldSettingsPane.isDisable = true
|
||||||
directoryPane.isDisable = true
|
directoryPane.isDisable = true
|
||||||
parentPane.isDisable = true
|
parentPane.isDisable = true
|
||||||
|
@ -571,7 +552,13 @@ class PrimaryController {
|
||||||
startButton.text = "Kill Server"
|
startButton.text = "Kill Server"
|
||||||
@Suppress("OPT_IN_USAGE")
|
@Suppress("OPT_IN_USAGE")
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
val builder = ProcessBuilder("${directory}ServerCraft${File.separator}Java${File.separator}jdk-20.0.1${File.separator}bin${File.separator}java", "-Xmx${server.getProp("jvm-ram")}M", "-jar", "${server.jar}")
|
val builder =
|
||||||
|
ProcessBuilder(
|
||||||
|
"${directory}ServerCraft${File.separator}Java${File.separator}jdk-20.0.1${File.separator}bin${File.separator}java",
|
||||||
|
"-Xmx${server.getProp("jvm-ram")}M",
|
||||||
|
"-jar",
|
||||||
|
"${server.jar}"
|
||||||
|
)
|
||||||
builder.directory(File(directory))
|
builder.directory(File(directory))
|
||||||
val proc = builder.start()
|
val proc = builder.start()
|
||||||
val reader = InputStreamReader(proc.inputStream)
|
val reader = InputStreamReader(proc.inputStream)
|
||||||
|
@ -586,23 +573,24 @@ class PrimaryController {
|
||||||
}
|
}
|
||||||
proc.destroy()
|
proc.destroy()
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.JavaFx) {log(cbuf.joinToString(separator=""))}
|
withContext(Dispatchers.JavaFx) { log(cbuf.joinToString(separator = "")) }
|
||||||
cbuf = CharArray(1000)
|
cbuf = CharArray(1000)
|
||||||
reader.read(cbuf, 0, 1000)
|
reader.read(cbuf, 0, 1000)
|
||||||
}
|
}
|
||||||
cbuf = CharArray(1000)
|
cbuf = CharArray(1000)
|
||||||
reader.read(cbuf, 0, 1000)
|
reader.read(cbuf, 0, 1000)
|
||||||
withContext(Dispatchers.JavaFx) {log(cbuf.joinToString(separator=""))}
|
withContext(Dispatchers.JavaFx) { log(cbuf.joinToString(separator = "")) }
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
withContext(Dispatchers.JavaFx) {log("Stream Closed\n")}
|
withContext(Dispatchers.JavaFx) { log("Stream Closed\n") }
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.JavaFx) {
|
withContext(Dispatchers.JavaFx) {
|
||||||
statusBar.text = if (killDialog.result) {
|
statusBar.text =
|
||||||
killDialog.result = false
|
if (killDialog.result) {
|
||||||
"Server killed."
|
killDialog.result = false
|
||||||
} else {
|
"Server killed."
|
||||||
"Server stopped."
|
} else {
|
||||||
}
|
"Server stopped."
|
||||||
|
}
|
||||||
worldSettingsPane.isDisable = false
|
worldSettingsPane.isDisable = false
|
||||||
directoryPane.isDisable = false
|
directoryPane.isDisable = false
|
||||||
parentPane.isDisable = false
|
parentPane.isDisable = false
|
||||||
|
@ -612,19 +600,18 @@ class PrimaryController {
|
||||||
startButton.text = "Start Server"
|
startButton.text = "Start Server"
|
||||||
started = false
|
started = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadServerDir(dir: String): Boolean {
|
private fun loadServerDir(dir: String): Boolean {
|
||||||
directory = dir
|
directory = dir
|
||||||
// exit if doesn't exist for whatever reason
|
// exit if doesn't exist for whatever reason
|
||||||
if (!File(directory).isDirectory) {
|
if (!File(directory).isDirectory) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// add system dir separator for cleaner code
|
// add system dir separator for cleaner code
|
||||||
if (directory[directory.length-1] != File.separatorChar)
|
if (directory[directory.length - 1] != File.separatorChar) directory += File.separatorChar
|
||||||
directory += File.separatorChar
|
|
||||||
|
|
||||||
val hasDummy = File(directory + "ServerCraft").isDirectory
|
val hasDummy = File(directory + "ServerCraft").isDirectory
|
||||||
val hasProperties = File(directory + File.separator + "server.properties").isFile
|
val hasProperties = File(directory + File.separator + "server.properties").isFile
|
||||||
|
@ -641,19 +628,27 @@ class PrimaryController {
|
||||||
statusBar.text = "Server needs to be built before starting."
|
statusBar.text = "Server needs to be built before starting."
|
||||||
} else if (!hasDummy && hasServer) {
|
} else if (!hasDummy && hasServer) {
|
||||||
// server created externally
|
// server created externally
|
||||||
val result = CommonDialog("warning", directory, "This server directory was not created by \nServerCraft. Errors may occur; copying\nthe world directories to a new folder may be\nsafer. Proceed anyway?").show()
|
val result =
|
||||||
|
CommonDialog(
|
||||||
|
"warning",
|
||||||
|
directory,
|
||||||
|
"This server directory was not created by \nServerCraft. Errors may occur; copying\nthe world directories to a new folder may be\nsafer. Proceed anyway?"
|
||||||
|
)
|
||||||
|
.show()
|
||||||
statusBar.text = "Ready."
|
statusBar.text = "Ready."
|
||||||
if (result) {
|
if (result) {
|
||||||
startButton.isDisable = true
|
startButton.isDisable = true
|
||||||
File(directory + "ServerCraft").mkdir()
|
File(directory + "ServerCraft").mkdir()
|
||||||
buildButton.text = "Build Server"
|
buildButton.text = "Build Server"
|
||||||
statusBar.text = "Server converted. Build the server to start."
|
statusBar.text = "Server converted. Build the server to start."
|
||||||
server.loadProps(dir, convert=true)
|
server.loadProps(dir, convert = true)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
// assume clean directory
|
// assume clean directory
|
||||||
val result = CommonDialog("info", directory, "There is no server in this directory.\nCreate one?").show()
|
val result =
|
||||||
|
CommonDialog("info", directory, "There is no server in this directory.\nCreate one?")
|
||||||
|
.show()
|
||||||
if (result) {
|
if (result) {
|
||||||
File(directory + "ServerCraft").mkdir()
|
File(directory + "ServerCraft").mkdir()
|
||||||
startButton.isDisable = true
|
startButton.isDisable = true
|
||||||
|
@ -671,7 +666,7 @@ class PrimaryController {
|
||||||
server.loadProps()
|
server.loadProps()
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findServerJar(): Boolean {
|
private fun findServerJar(): Boolean {
|
||||||
|
@ -681,10 +676,7 @@ class PrimaryController {
|
||||||
// patch number
|
// patch number
|
||||||
for (j in 15 downTo 0) {
|
for (j in 15 downTo 0) {
|
||||||
var spigotFile: String = ""
|
var spigotFile: String = ""
|
||||||
if (j == 0)
|
if (j == 0) spigotFile += "spigot-1.$i.jar" else spigotFile += "spigot-1.$i.$j.jar"
|
||||||
spigotFile += "spigot-1.$i.jar"
|
|
||||||
else
|
|
||||||
spigotFile += "spigot-1.$i.$j.jar";
|
|
||||||
|
|
||||||
if (File(directory + spigotFile).isFile) {
|
if (File(directory + spigotFile).isFile) {
|
||||||
server.jar = directory + spigotFile
|
server.jar = directory + spigotFile
|
||||||
|
@ -701,4 +693,4 @@ class PrimaryController {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package xyz.brysonsteck.ServerCraft.dialogs
|
package xyz.brysonsteck.ServerCraft.dialogs
|
||||||
|
|
||||||
import javafx.scene.control.Button
|
|
||||||
import javafx.event.EventHandler
|
|
||||||
import javafx.event.ActionEvent
|
import javafx.event.ActionEvent
|
||||||
|
import javafx.event.EventHandler
|
||||||
|
import javafx.scene.control.Button
|
||||||
|
|
||||||
class CommonDialog: Dialog {
|
class CommonDialog : Dialog {
|
||||||
override var type: String
|
override var type: String
|
||||||
override var title: String
|
override var title: String
|
||||||
override var msg: String
|
override var msg: String
|
||||||
|
@ -18,17 +18,18 @@ class CommonDialog: Dialog {
|
||||||
this.msg = msg
|
this.msg = msg
|
||||||
|
|
||||||
noButton = Button("No")
|
noButton = Button("No")
|
||||||
noButton.onAction = EventHandler<ActionEvent>() {
|
noButton.onAction =
|
||||||
result = false
|
EventHandler<ActionEvent>() {
|
||||||
dialog.hide()
|
result = false
|
||||||
}
|
dialog.hide()
|
||||||
|
}
|
||||||
yesButton = Button("Yes")
|
yesButton = Button("Yes")
|
||||||
yesButton.onAction = EventHandler<ActionEvent>() {
|
yesButton.onAction =
|
||||||
result = true
|
EventHandler<ActionEvent>() {
|
||||||
dialog.hide()
|
result = true
|
||||||
}
|
dialog.hide()
|
||||||
|
}
|
||||||
yesButton.isDefaultButton = true
|
yesButton.isDefaultButton = true
|
||||||
neutralButton = null
|
neutralButton = null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
package xyz.brysonsteck.ServerCraft.dialogs
|
package xyz.brysonsteck.ServerCraft.dialogs
|
||||||
|
|
||||||
|
import javafx.geometry.Insets
|
||||||
|
import javafx.scene.Scene
|
||||||
import javafx.scene.control.Button
|
import javafx.scene.control.Button
|
||||||
import javafx.scene.control.ButtonBar
|
import javafx.scene.control.ButtonBar
|
||||||
import javafx.scene.control.Label
|
import javafx.scene.control.Label
|
||||||
import javafx.scene.image.Image
|
import javafx.scene.image.Image
|
||||||
import javafx.scene.image.ImageView
|
import javafx.scene.image.ImageView
|
||||||
import javafx.scene.layout.Pane
|
import javafx.scene.layout.Pane
|
||||||
import javafx.scene.Scene
|
|
||||||
import javafx.stage.Modality
|
import javafx.stage.Modality
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import javafx.geometry.Insets
|
|
||||||
import javafx.event.EventHandler
|
|
||||||
import javafx.event.ActionEvent
|
|
||||||
import xyz.brysonsteck.ServerCraft.App
|
import xyz.brysonsteck.ServerCraft.App
|
||||||
|
|
||||||
abstract class Dialog {
|
abstract class Dialog {
|
||||||
|
@ -33,7 +31,7 @@ abstract class Dialog {
|
||||||
val icon = Image("$resources")
|
val icon = Image("$resources")
|
||||||
dialog.icons.add(Image(App().javaClass.getResourceAsStream("app.png")))
|
dialog.icons.add(Image(App().javaClass.getResourceAsStream("app.png")))
|
||||||
dialog.setResizable(false)
|
dialog.setResizable(false)
|
||||||
dialog.initModality(Modality.APPLICATION_MODAL);
|
dialog.initModality(Modality.APPLICATION_MODAL)
|
||||||
dialog.title = title
|
dialog.title = title
|
||||||
val imagePane = Pane()
|
val imagePane = Pane()
|
||||||
imagePane.layoutX = 14.0
|
imagePane.layoutX = 14.0
|
||||||
|
@ -64,14 +62,13 @@ abstract class Dialog {
|
||||||
ButtonBar.setButtonData(neutralButton, ButtonBar.ButtonData.LEFT)
|
ButtonBar.setButtonData(neutralButton, ButtonBar.ButtonData.LEFT)
|
||||||
buttonBar.buttons.add(neutralButton)
|
buttonBar.buttons.add(neutralButton)
|
||||||
}
|
}
|
||||||
val dialogScene = Scene(scenePane, 400.0, 150.0);
|
val dialogScene = Scene(scenePane, 400.0, 150.0)
|
||||||
dialog.setScene(dialogScene);
|
dialog.setScene(dialogScene)
|
||||||
if (hold) {
|
if (hold) {
|
||||||
dialog.showAndWait();
|
dialog.showAndWait()
|
||||||
} else {
|
} else {
|
||||||
dialog.show();
|
dialog.show()
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package xyz.brysonsteck.ServerCraft.dialogs
|
package xyz.brysonsteck.ServerCraft.dialogs
|
||||||
|
|
||||||
import xyz.brysonsteck.ServerCraft.dialogs.Dialog
|
|
||||||
import javafx.scene.control.Button
|
|
||||||
import javafx.event.EventHandler
|
|
||||||
import javafx.event.ActionEvent
|
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
import javafx.event.ActionEvent
|
||||||
|
import javafx.event.EventHandler
|
||||||
|
import javafx.scene.control.Button
|
||||||
|
|
||||||
class EulaDialog: Dialog {
|
class EulaDialog : Dialog {
|
||||||
override val type: String
|
override val type: String
|
||||||
override val title: String
|
override val title: String
|
||||||
override val msg: String
|
override val msg: String
|
||||||
|
@ -18,38 +17,40 @@ class EulaDialog: Dialog {
|
||||||
constructor() {
|
constructor() {
|
||||||
type = "warning"
|
type = "warning"
|
||||||
title = "Minecraft End User License Agreement (EULA)"
|
title = "Minecraft End User License Agreement (EULA)"
|
||||||
msg = "Do you agree to the terms of the Minecraft End User License Agreement?"
|
msg = "Do you agree to the terms of the Minecraft\nEnd User License Agreement?"
|
||||||
|
|
||||||
noButton = Button("I Disagree")
|
noButton = Button("I Disagree")
|
||||||
noButton.onAction = EventHandler<ActionEvent>() {
|
noButton.onAction =
|
||||||
result = false
|
EventHandler<ActionEvent>() {
|
||||||
dialog.hide()
|
result = false
|
||||||
}
|
dialog.hide()
|
||||||
|
}
|
||||||
noButton.isDefaultButton = true
|
noButton.isDefaultButton = true
|
||||||
yesButton = Button("I Agree")
|
yesButton = Button("I Agree")
|
||||||
yesButton.onAction = EventHandler<ActionEvent>() {
|
yesButton.onAction =
|
||||||
result = true
|
EventHandler<ActionEvent>() {
|
||||||
dialog.hide()
|
result = true
|
||||||
}
|
dialog.hide()
|
||||||
|
}
|
||||||
neutralButton = Button("View EULA")
|
neutralButton = Button("View EULA")
|
||||||
neutralButton.onAction = EventHandler<ActionEvent>() {
|
neutralButton.onAction =
|
||||||
val desktop = Desktop.getDesktop()
|
EventHandler<ActionEvent>() {
|
||||||
if (desktop.isSupported(Desktop.Action.BROWSE)) {
|
val desktop = Desktop.getDesktop()
|
||||||
// most likely running on Windows or macOS
|
if (desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||||
try {
|
// most likely running on Windows or macOS
|
||||||
desktop.browse(URI("https://account.mojang.com/documents/minecraft_eula"))
|
try {
|
||||||
} catch (e: Exception) {
|
desktop.browse(URI("https://www.minecraft.net/en-us/eula"))
|
||||||
println(e)
|
} catch (e: Exception) {
|
||||||
}
|
println(e)
|
||||||
} else {
|
}
|
||||||
// assume running on linux
|
} else {
|
||||||
try {
|
// assume running on linux
|
||||||
Runtime.getRuntime().exec("xdg-open https://account.mojang.com/documents/minecraft_eula");
|
try {
|
||||||
} catch (e: Exception) {
|
Runtime.getRuntime().exec("xdg-open https://www.minecraft.net/en-us/eula")
|
||||||
println(e)
|
} catch (e: Exception) {
|
||||||
}
|
println(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package xyz.brysonsteck.ServerCraft.dialogs
|
package xyz.brysonsteck.ServerCraft.dialogs
|
||||||
|
|
||||||
import javafx.scene.control.Button
|
|
||||||
import javafx.event.EventHandler
|
|
||||||
import javafx.event.ActionEvent
|
import javafx.event.ActionEvent
|
||||||
|
import javafx.event.EventHandler
|
||||||
|
import javafx.scene.control.Button
|
||||||
|
|
||||||
class KillDialog: Dialog {
|
class KillDialog : Dialog {
|
||||||
override val type: String
|
override val type: String
|
||||||
override val title: String
|
override val title: String
|
||||||
override val msg: String
|
override val msg: String
|
||||||
|
@ -15,20 +15,23 @@ class KillDialog: Dialog {
|
||||||
constructor() {
|
constructor() {
|
||||||
type = "warning"
|
type = "warning"
|
||||||
title = "Server is still running!"
|
title = "Server is still running!"
|
||||||
msg = "You should only kill the server if absolutely necessary, i.e. not being responsive after long periods of time. Data loss may occur. Continue anyway?"
|
msg =
|
||||||
|
"You should only kill the server if absolutely necessary, i.e. not being responsive after long periods of time. Data loss may occur. Continue anyway?"
|
||||||
hold = false
|
hold = false
|
||||||
|
|
||||||
noButton = Button("No")
|
noButton = Button("No")
|
||||||
noButton.onAction = EventHandler<ActionEvent>() {
|
noButton.onAction =
|
||||||
result = false
|
EventHandler<ActionEvent>() {
|
||||||
dialog.hide()
|
result = false
|
||||||
}
|
dialog.hide()
|
||||||
|
}
|
||||||
yesButton = Button("Yes")
|
yesButton = Button("Yes")
|
||||||
yesButton.onAction = EventHandler<ActionEvent>() {
|
yesButton.onAction =
|
||||||
result = true
|
EventHandler<ActionEvent>() {
|
||||||
dialog.hide()
|
result = true
|
||||||
}
|
dialog.hide()
|
||||||
|
}
|
||||||
yesButton.isDefaultButton = true
|
yesButton.isDefaultButton = true
|
||||||
neutralButton = null
|
neutralButton = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
package xyz.brysonsteck.ServerCraft.server
|
package xyz.brysonsteck.ServerCraft.server
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*
|
||||||
import java.net.*;
|
import java.net.*
|
||||||
import java.util.*;
|
import java.util.*
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
class Download: Runnable {
|
class Download : Runnable {
|
||||||
public enum class Status {
|
public enum class Status {
|
||||||
DOWNLOADING, PAUSED, COMPLETE, CANCELLED, ERROR
|
DOWNLOADING,
|
||||||
|
PAUSED,
|
||||||
|
COMPLETE,
|
||||||
|
CANCELLED,
|
||||||
|
ERROR
|
||||||
}
|
}
|
||||||
public var size: Int
|
public var size: Int
|
||||||
public var downloaded: Int
|
public var downloaded: Int
|
||||||
|
@ -19,7 +23,7 @@ class Download: Runnable {
|
||||||
private var url: URL
|
private var url: URL
|
||||||
private var dir: String
|
private var dir: String
|
||||||
|
|
||||||
constructor (url: URL, dir: String) {
|
constructor(url: URL, dir: String) {
|
||||||
this.url = url
|
this.url = url
|
||||||
this.dir = dir
|
this.dir = dir
|
||||||
size = -1
|
size = -1
|
||||||
|
@ -38,19 +42,19 @@ class Download: Runnable {
|
||||||
return filename.substring(filename.lastIndexOf('/') + 1)
|
return filename.substring(filename.lastIndexOf('/') + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
var stream: InputStream? = null
|
var stream: InputStream? = null
|
||||||
var file: RandomAccessFile? = null
|
var file: RandomAccessFile? = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Open connection to URL.
|
// Open connection to URL.
|
||||||
var connection = url.openConnection() as HttpsURLConnection;
|
var connection = url.openConnection() as HttpsURLConnection
|
||||||
|
|
||||||
// Specify what portion of file to download.
|
// Specify what portion of file to download.
|
||||||
connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
|
connection.setRequestProperty("Range", "bytes=" + downloaded + "-")
|
||||||
|
|
||||||
// Connect to server.
|
// Connect to server.
|
||||||
connection.connect();
|
connection.connect()
|
||||||
|
|
||||||
// Make sure response code is in the 200 range.
|
// Make sure response code is in the 200 range.
|
||||||
if (connection.responseCode / 100 != 2) {
|
if (connection.responseCode / 100 != 2) {
|
||||||
|
@ -58,64 +62,63 @@ class Download: Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for valid content length.
|
// Check for valid content length.
|
||||||
contentLength = connection.getContentLength();
|
contentLength = connection.getContentLength()
|
||||||
if (contentLength < 1) {
|
if (contentLength < 1) {
|
||||||
status = Status.ERROR
|
status = Status.ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the size for this download if it
|
/* Set the size for this download if it
|
||||||
hasn't been already set. */
|
hasn't been already set. */
|
||||||
if (size == -1) {
|
if (size == -1) {
|
||||||
size = contentLength;
|
size = contentLength
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file and seek to the end of it.
|
// Open file and seek to the end of it.
|
||||||
file = RandomAccessFile(dir + getFilename(url), "rw");
|
file = RandomAccessFile(dir + getFilename(url), "rw")
|
||||||
file.seek(downloaded.toLong());
|
file.seek(downloaded.toLong())
|
||||||
|
|
||||||
stream = connection.getInputStream();
|
stream = connection.getInputStream()
|
||||||
while (status == Status.DOWNLOADING) {
|
while (status == Status.DOWNLOADING) {
|
||||||
/* Size buffer according to how much of the
|
/* Size buffer according to how much of the
|
||||||
file is left to download. */
|
file is left to download. */
|
||||||
val buffer: ByteArray;
|
val buffer: ByteArray
|
||||||
if (size - downloaded > MAX_BUFFER_SIZE as Int) {
|
if (size - downloaded > MAX_BUFFER_SIZE as Int) {
|
||||||
buffer = ByteArray(MAX_BUFFER_SIZE)
|
buffer = ByteArray(MAX_BUFFER_SIZE)
|
||||||
} else {
|
} else {
|
||||||
buffer = ByteArray(size - downloaded);
|
buffer = ByteArray(size - downloaded)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from server into buffer.
|
// Read from server into buffer.
|
||||||
val read = stream.read(buffer);
|
val read = stream.read(buffer)
|
||||||
if (read == -1)
|
if (read == -1) break
|
||||||
break;
|
|
||||||
|
|
||||||
// Write buffer to file.
|
// Write buffer to file.
|
||||||
file.write(buffer, 0, read);
|
file.write(buffer, 0, read)
|
||||||
downloaded += read;
|
downloaded += read
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change status to complete if this point was
|
/* Change status to complete if this point was
|
||||||
reached because downloading has finished. */
|
reached because downloading has finished. */
|
||||||
if (status == Status.DOWNLOADING) {
|
if (status == Status.DOWNLOADING) {
|
||||||
status = Status.COMPLETE;
|
status = Status.COMPLETE
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println(e)
|
println(e)
|
||||||
status = Status.ERROR
|
status = Status.ERROR
|
||||||
} finally {
|
} finally {
|
||||||
// Close file.
|
// Close file.
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
try {
|
try {
|
||||||
file.close();
|
file.close()
|
||||||
} catch (e: Exception) {}
|
} catch (e: Exception) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close connection to server.
|
// Close connection to server.
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
try {
|
try {
|
||||||
stream.close();
|
stream.close()
|
||||||
} catch (e: Exception) {}
|
} catch (e: Exception) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package xyz.brysonsteck.ServerCraft.server
|
package xyz.brysonsteck.ServerCraft.server
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
|
|
||||||
|
@ -41,19 +40,34 @@ public class Server {
|
||||||
var ins = File(dir + File.separator + "server.properties").inputStream()
|
var ins = File(dir + File.separator + "server.properties").inputStream()
|
||||||
props.load(ins)
|
props.load(ins)
|
||||||
try {
|
try {
|
||||||
ins = File(dir + File.separator + "ServerCraft" + File.separator + "ServerCraft.properties").inputStream()
|
ins =
|
||||||
|
File(dir + File.separator + "ServerCraft" + File.separator + "ServerCraft.properties")
|
||||||
|
.inputStream()
|
||||||
props.load(ins)
|
props.load(ins)
|
||||||
} catch (e: FileNotFoundException) {
|
} catch (e: FileNotFoundException) {
|
||||||
if (convert) {
|
if (convert) {
|
||||||
// create the file in question, as this is an external server being converted into a ServerCraft managed one
|
// create the file in question, as this is an external server being converted into a
|
||||||
File(dir + File.separator + "ServerCraft" + File.separator + "ServerCraft.properties").createNewFile()
|
// ServerCraft managed one
|
||||||
|
File(dir + File.separator + "ServerCraft" + File.separator + "ServerCraft.properties")
|
||||||
|
.createNewFile()
|
||||||
// also apply app-specific properties
|
// also apply app-specific properties
|
||||||
props.setProperty("jvm-ram", 1024.toString())
|
props.setProperty("jvm-ram", 1024.toString())
|
||||||
// then write to file
|
// then write to file
|
||||||
val temp = Properties()
|
val temp = Properties()
|
||||||
val outs = File(dir + File.separator + "ServerCraft" + File.separator + "ServerCraft.properties").outputStream()
|
val outs =
|
||||||
|
File(
|
||||||
|
dir +
|
||||||
|
File.separator +
|
||||||
|
"ServerCraft" +
|
||||||
|
File.separator +
|
||||||
|
"ServerCraft.properties"
|
||||||
|
)
|
||||||
|
.outputStream()
|
||||||
temp.setProperty("jvm-ram", props.getProperty("jvm-ram"))
|
temp.setProperty("jvm-ram", props.getProperty("jvm-ram"))
|
||||||
temp.store(outs, "ServerCraft settings backup\nSometimes, Minecraft will completely overwrite the server.properties file,\ncompletely destroying these app-specific settings. This file backs up these settings\njust in case. :)\nhttps://codeberg.org/brysonsteck/ServerCraft")
|
temp.store(
|
||||||
|
outs,
|
||||||
|
"ServerCraft settings backup\nSometimes, Minecraft will completely overwrite the server.properties file,\ncompletely destroying these app-specific settings. This file backs up these settings\njust in case. :)\nhttps://codeberg.org/brysonsteck/ServerCraft"
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
println(e)
|
println(e)
|
||||||
}
|
}
|
||||||
|
@ -62,11 +76,19 @@ public class Server {
|
||||||
|
|
||||||
private fun writeProps() {
|
private fun writeProps() {
|
||||||
var outs = File(dir + File.separator + "server.properties").outputStream()
|
var outs = File(dir + File.separator + "server.properties").outputStream()
|
||||||
props.store(outs, "Minecraft server properties\nCreated with ServerCraft: https://codeberg.org/brysonsteck/ServerCraft")
|
props.store(
|
||||||
|
outs,
|
||||||
|
"Minecraft server properties\nCreated with ServerCraft: https://codeberg.org/brysonsteck/ServerCraft"
|
||||||
|
)
|
||||||
val temp = Properties()
|
val temp = Properties()
|
||||||
outs = File(dir + File.separator + "ServerCraft" + File.separator + "ServerCraft.properties").outputStream()
|
outs =
|
||||||
|
File(dir + File.separator + "ServerCraft" + File.separator + "ServerCraft.properties")
|
||||||
|
.outputStream()
|
||||||
temp.setProperty("jvm-ram", props.getProperty("jvm-ram"))
|
temp.setProperty("jvm-ram", props.getProperty("jvm-ram"))
|
||||||
temp.store(outs, "ServerCraft settings backup\nSometimes, Minecraft will completely overwrite the server.properties file,\ncompletely destroying these app-specific settings. This file backs up these settings\njust in case. :)\nhttps://codeberg.org/brysonsteck/ServerCraft")
|
temp.store(
|
||||||
|
outs,
|
||||||
|
"ServerCraft settings backup\nSometimes, Minecraft will completely overwrite the server.properties file,\ncompletely destroying these app-specific settings. This file backs up these settings\njust in case. :)\nhttps://codeberg.org/brysonsteck/ServerCraft"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getProp(prop: String): String {
|
public fun getProp(prop: String): String {
|
||||||
|
@ -77,5 +99,4 @@ public class Server {
|
||||||
props.setProperty(key, value.toString())
|
props.setProperty(key, value.toString())
|
||||||
writeProps()
|
writeProps()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
-fx-background-color: "#F4F4F4";
|
-fx-background-color: "#F4F4F4";
|
||||||
-fx-border-color: "#DCDCDC";
|
-fx-border-color: "#DCDCDC";
|
||||||
-fx-border-width: 0 0 1 0
|
-fx-border-width: 0 0 1 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
.root{
|
||||||
|
-fx-font-size: 11pt;
|
||||||
|
-fx-font-family: "Inter";
|
||||||
|
}
|
|
@ -8,379 +8,374 @@
|
||||||
<?import javafx.scene.control.ContextMenu?>
|
<?import javafx.scene.control.ContextMenu?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.MenuItem?>
|
<?import javafx.scene.control.MenuItem?>
|
||||||
<?import javafx.scene.control.ProgressBar?>
|
|
||||||
<?import javafx.scene.control.ScrollPane?>
|
|
||||||
<?import javafx.scene.control.Separator?>
|
<?import javafx.scene.control.Separator?>
|
||||||
<?import javafx.scene.control.Spinner?>
|
<?import javafx.scene.control.Spinner?>
|
||||||
<?import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory?>
|
<?import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory?>
|
||||||
<?import javafx.scene.control.TextField?>
|
<?import javafx.scene.control.TextField?>
|
||||||
<?import javafx.scene.control.TitledPane?>
|
<?import javafx.scene.control.TitledPane?>
|
||||||
<?import javafx.scene.control.Tooltip?>
|
<?import javafx.scene.control.Tooltip?>
|
||||||
<?import javafx.scene.image.Image?>
|
|
||||||
<?import javafx.scene.image.ImageView?>
|
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<Pane fx:id="primary" maxHeight="873.0" maxWidth="963.0" minHeight="713.0" minWidth="963.0" prefHeight="873.0" prefWidth="963.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="xyz.brysonsteck.ServerCraft.controllers.PrimaryController">
|
|
||||||
|
<AnchorPane fx:id="primary" minHeight="200.0" minWidth="200.0" prefHeight="633.0" prefWidth="1054.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="xyz.brysonsteck.ServerCraft.controllers.PrimaryController">
|
||||||
<children>
|
<children>
|
||||||
<HBox fx:id="directoryPane" prefHeight="39.0" prefWidth="963.0">
|
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<children>
|
<children>
|
||||||
<Button id="openFile" fx:id="chooseDirectoryButton" lineSpacing="10.0" mnemonicParsing="false" onAction="#onDirectoryButtonClick" text="Choose Directory...">
|
<HBox fx:id="directoryPane" minHeight="-Infinity" VBox.vgrow="NEVER">
|
||||||
<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="<NONE>">
|
|
||||||
<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:" HBox.hgrow="ALWAYS">
|
|
||||||
<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" text="world">
|
|
||||||
<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" promptText="Leave empty for random seed" HBox.hgrow="ALWAYS">
|
|
||||||
<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:" HBox.hgrow="ALWAYS">
|
|
||||||
<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" editable="true" prefWidth="95.0">
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets top="2.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="25565" max="60000" min="20000" />
|
|
||||||
</valueFactory>
|
|
||||||
</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" onAction="#onCheckboxClick" text="Allow Flight" />
|
|
||||||
<CheckBox fx:id="netherCheckbox" layoutX="14.0" layoutY="42.0" mnemonicParsing="false" onAction="#onCheckboxClick" selected="true" text="Allow The Nether" />
|
|
||||||
<CheckBox fx:id="structuresCheckbox" alignment="TOP_LEFT" layoutX="14.0" layoutY="70.0" mnemonicParsing="false" onAction="#onCheckboxClick" selected="true" text="Generate Structures (such as villages and strongholds)" />
|
|
||||||
<CheckBox fx:id="pvpCheckbox" layoutX="14.0" layoutY="109.0" mnemonicParsing="false" onAction="#onCheckboxClick" selected="true" text="Allow PvP" />
|
|
||||||
<CheckBox fx:id="whitelistCheckbox" alignment="TOP_LEFT" layoutX="14.0" layoutY="138.0" mnemonicParsing="false" onAction="#onCheckboxClick" text="Enable Whitelist (Only users you specify can join)" />
|
|
||||||
<HBox layoutX="6.0" layoutY="174.0">
|
|
||||||
<children>
|
|
||||||
<Label text="Maximum Players:" HBox.hgrow="ALWAYS">
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</Label>
|
|
||||||
<Spinner fx:id="maxPlayerSpinner" editable="true" prefHeight="23.0" prefWidth="99.0">
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="20" max="1000" min="0" />
|
|
||||||
</valueFactory>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</Spinner>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<HBox layoutX="6.0" layoutY="207.0">
|
|
||||||
<children>
|
|
||||||
<Label text="Maximum World Size (in blocks):" HBox.hgrow="ALWAYS">
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets />
|
|
||||||
</HBox.margin>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</Label>
|
|
||||||
<Spinner fx:id="maxSizeSpinner" editable="true" prefHeight="23.0" prefWidth="155.0">
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="29999984" max="29999984" min="1" />
|
|
||||||
</valueFactory>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</Spinner>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
|
||||||
</content>
|
|
||||||
</TitledPane>
|
|
||||||
<TitledPane fx:id="advancedPane" expanded="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" onAction="#onCheckboxClick" text="Enable Command Blocks" />
|
|
||||||
<CheckBox fx:id="playerCountCheckbox" layoutX="14.0" layoutY="41.0" mnemonicParsing="false" onAction="#onCheckboxClick" text="Hide Online Player Count" />
|
|
||||||
<HBox layoutX="7.0" layoutY="65.0">
|
|
||||||
<children>
|
|
||||||
<Label ellipsisString="" text="Server Memory in MB:" textOverrun="CLIP" HBox.hgrow="ALWAYS">
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip text="This is the amount of RAM that will get passed to Minecraft/the JVM. For simple servers, 1024 MB will be plenty. If you typically have more than 5 concurrent players, consider allocating more." />
|
|
||||||
</tooltip>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</Label>
|
|
||||||
<Spinner fx:id="memorySpinner" editable="true" prefHeight="23.0" prefWidth="99.0">
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="1024" max="65536" min="512" />
|
|
||||||
</valueFactory>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</Spinner>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<HBox layoutX="7.0" layoutY="96.0">
|
|
||||||
<children>
|
|
||||||
<Label text="Spawn Protection Radius:" HBox.hgrow="ALWAYS">
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip text="All blocks in a radius from 0,~,0 will be unbreakable. If you want to break blocks within spawn, change this value." />
|
|
||||||
</tooltip>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets />
|
|
||||||
</HBox.margin>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</Label>
|
|
||||||
<Spinner fx:id="spawnSpinner" editable="true" prefHeight="23.0" prefWidth="99.0">
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="16" max="29999984" min="0" />
|
|
||||||
</valueFactory>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</Spinner>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<HBox layoutX="7.0" layoutY="127.0">
|
|
||||||
<children>
|
|
||||||
<Label text="Simulation Distance:" HBox.hgrow="ALWAYS">
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip text="The radius of chunks for each player where ticks will be updated. In other words, anything outside these circles, such as furnaces, mobs, etc, will not be updated or simulated." />
|
|
||||||
</tooltip>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets />
|
|
||||||
</HBox.margin>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</Label>
|
|
||||||
<Spinner fx:id="simulationSpinner" editable="true" prefWidth="80.0">
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="10" max="40" min="0" />
|
|
||||||
</valueFactory>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</Spinner>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<HBox layoutX="7.0" layoutY="160.0">
|
|
||||||
<children>
|
|
||||||
<Label text="Render Distance:" HBox.hgrow="ALWAYS">
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip text="The radius of chunks where the server will render the view distance. Any value higher on a client than what is set will be ignored. Higher values will be more demanding on the server." />
|
|
||||||
</tooltip>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets />
|
|
||||||
</HBox.margin>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</Label>
|
|
||||||
<Spinner fx:id="renderSpinner" editable="true" prefWidth="80.0">
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="10" max="40" min="2" />
|
|
||||||
</valueFactory>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</Spinner>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<HBox layoutX="7.0" layoutY="192.0">
|
|
||||||
<children>
|
|
||||||
<Label text="Maximum Tick Time (in milliseconds):" HBox.hgrow="ALWAYS">
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip text="If the server cannot update ticks (i.e. "lags") for longer than this amount of time, the server will shutdown. 60000 ms (60 seconds) is the default." />
|
|
||||||
</tooltip>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</Label>
|
|
||||||
<Spinner fx:id="maxTickSpinner" editable="true">
|
|
||||||
<valueFactory>
|
|
||||||
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="60000" max="180000" min="10000" />
|
|
||||||
</valueFactory>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</Spinner>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
</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>
|
|
||||||
</children>
|
|
||||||
</Pane>
|
|
||||||
<ButtonBar fx:id="buttonBar" buttonOrder="L+R" layoutY="635.0" prefHeight="40.0" prefWidth="963.0">
|
|
||||||
<buttons>
|
|
||||||
<Button fx:id="infoButton" mnemonicParsing="false" onAction="#onInfo" text="About ServerCraft" ButtonBar.buttonData="LEFT" />
|
|
||||||
<Button fx:id="defaultsButton" disable="true" mnemonicParsing="false" onAction="#onDefaults" text="Reset to Defaults" ButtonBar.buttonData="LEFT" />
|
|
||||||
<Button fx:id="buildButton" disable="true" mnemonicParsing="false" onAction="#onBuild" text="Build Server" ButtonBar.buttonData="RIGHT" />
|
|
||||||
<Button fx:id="startButton" defaultButton="true" disable="true" mnemonicParsing="false" onAction="#onStart" prefWidth="120.0" text="Start Server" ButtonBar.buttonData="RIGHT" />
|
|
||||||
</buttons>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
|
||||||
</padding>
|
|
||||||
</ButtonBar>
|
|
||||||
<Pane layoutY="680.0" prefHeight="196.0" prefWidth="963.0" style="-fx-background-color: ddd;">
|
|
||||||
<children>
|
|
||||||
<HBox prefWidth="963.0">
|
|
||||||
<children>
|
<children>
|
||||||
<Label text="Status:">
|
<Button id="openFile" fx:id="chooseDirectoryButton" lineSpacing="10.0" mnemonicParsing="false" onAction="#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 maxHeight="1.7976931348623157E308" orientation="VERTICAL">
|
||||||
|
<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>
|
||||||
<Font name="System Bold" size="13.0" />
|
<Font name="System Bold" size="13.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label fx:id="statusBar" text="Ready.">
|
<Label id="currentFilename" fx:id="currentDirectoryLabel" text="<NONE>">
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets left="5.0" />
|
<Insets bottom="5.0" right="5.0" top="5.0" />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</Label>
|
</Label>
|
||||||
<ProgressBar fx:id="progressBar" prefWidth="400.0" visible="false">
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets left="10.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</ProgressBar>
|
|
||||||
</children>
|
</children>
|
||||||
<padding>
|
|
||||||
<Insets bottom="9.0" left="9.0" right="9.0" top="9.0" />
|
|
||||||
</padding>
|
|
||||||
</HBox>
|
|
||||||
<ImageView fx:id="dropDownIcon" fitHeight="66.0" fitWidth="39.0" layoutX="923.0" layoutY="-3.0" onMouseClicked="#onToggleConsole" pickOnBounds="true" preserveRatio="true">
|
|
||||||
<image>
|
|
||||||
<Image url="@icons/arrow_down.png" />
|
|
||||||
</image>
|
|
||||||
</ImageView>
|
|
||||||
<ScrollPane fx:id="scrollPane" layoutY="34.0" prefHeight="162.0" prefWidth="963.0" vbarPolicy="ALWAYS">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
|
<Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<content>
|
</HBox>
|
||||||
<Label fx:id="console" prefWidth="935.0" text="Console Output: " wrapText="true">
|
<HBox fx:id="worldSettingsPane" disable="true" minHeight="-Infinity" prefHeight="43.0" prefWidth="964.0">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
|
||||||
|
</padding>
|
||||||
|
<children>
|
||||||
|
<Label text="World Name:" HBox.hgrow="ALWAYS">
|
||||||
<font>
|
<font>
|
||||||
<Font name="Monospaced Regular" size="13.0" />
|
<Font name="System Bold" size="13.0" />
|
||||||
</font>
|
</font>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="6.0" />
|
||||||
|
</HBox.margin>
|
||||||
</Label>
|
</Label>
|
||||||
</content>
|
<TextField fx:id="worldNameField" text="world">
|
||||||
</ScrollPane>
|
<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 prefHeight="0.0" 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" promptText="Leave empty for random seed" HBox.hgrow="ALWAYS">
|
||||||
|
<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:" HBox.hgrow="ALWAYS">
|
||||||
|
<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" editable="true" prefWidth="95.0">
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets top="2.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="25565" max="60000" min="20000" />
|
||||||
|
</valueFactory>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
<opaqueInsets>
|
||||||
|
<Insets bottom="3.0" />
|
||||||
|
</opaqueInsets>
|
||||||
|
</HBox>
|
||||||
|
<GridPane fx:id="parentPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" VBox.vgrow="ALWAYS">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints halignment="CENTER" hgrow="NEVER" minWidth="10.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="317.0" minWidth="10.0" prefWidth="177.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<VBox prefHeight="505.0" prefWidth="584.0" GridPane.hgrow="ALWAYS">
|
||||||
|
<children>
|
||||||
|
<TitledPane fx:id="settingsPane" animated="false" collapsible="false" prefHeight="273.0" prefWidth="627.0" text="Server Settings">
|
||||||
|
<content>
|
||||||
|
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
|
||||||
|
<children>
|
||||||
|
<CheckBox fx:id="flightCheckbox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onAction="#onCheckboxClick" text="Allow Flight" />
|
||||||
|
<CheckBox fx:id="netherCheckbox" layoutX="14.0" layoutY="42.0" mnemonicParsing="false" onAction="#onCheckboxClick" selected="true" text="Allow The Nether" />
|
||||||
|
<CheckBox fx:id="structuresCheckbox" alignment="TOP_LEFT" layoutX="14.0" layoutY="70.0" mnemonicParsing="false" onAction="#onCheckboxClick" selected="true" text="Generate Structures (such as villages and strongholds)" />
|
||||||
|
<CheckBox fx:id="pvpCheckbox" layoutX="14.0" layoutY="109.0" mnemonicParsing="false" onAction="#onCheckboxClick" selected="true" text="Allow PvP" />
|
||||||
|
<CheckBox fx:id="whitelistCheckbox" alignment="TOP_LEFT" layoutX="14.0" layoutY="138.0" mnemonicParsing="false" onAction="#onCheckboxClick" text="Enable Whitelist (Only users you specify can join)" />
|
||||||
|
<HBox layoutX="6.0" layoutY="174.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Maximum Players:" HBox.hgrow="ALWAYS">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Spinner fx:id="maxPlayerSpinner" editable="true" prefHeight="23.0" prefWidth="99.0">
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="20" max="1000" min="0" />
|
||||||
|
</valueFactory>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
<HBox layoutX="6.0" layoutY="207.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Maximum World Size (in blocks):" HBox.hgrow="ALWAYS">
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets />
|
||||||
|
</HBox.margin>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Spinner fx:id="maxSizeSpinner" editable="true" prefHeight="23.0" prefWidth="155.0">
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="29999984" max="29999984" min="1" />
|
||||||
|
</valueFactory>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
</TitledPane>
|
||||||
|
<TitledPane fx:id="advancedPane" expanded="false" 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" onAction="#onCheckboxClick" text="Enable Command Blocks" />
|
||||||
|
<CheckBox fx:id="playerCountCheckbox" layoutX="14.0" layoutY="41.0" mnemonicParsing="false" onAction="#onCheckboxClick" text="Hide Online Player Count" />
|
||||||
|
<HBox layoutX="7.0" layoutY="65.0">
|
||||||
|
<children>
|
||||||
|
<Label ellipsisString="" text="Server Memory in MB:" textOverrun="CLIP" HBox.hgrow="ALWAYS">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip text="This is the amount of RAM that will get passed to Minecraft/the JVM. For simple servers, 1024 MB will be plenty. If you typically have more than 5 concurrent players, consider allocating more." />
|
||||||
|
</tooltip>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Spinner fx:id="memorySpinner" editable="true" prefHeight="23.0" prefWidth="99.0">
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="1024" max="65536" min="512" />
|
||||||
|
</valueFactory>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
<HBox layoutX="7.0" layoutY="96.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Spawn Protection Radius:" HBox.hgrow="ALWAYS">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip text="All blocks in a radius from 0,~,0 will be unbreakable. If you want to break blocks within spawn, change this value." />
|
||||||
|
</tooltip>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets />
|
||||||
|
</HBox.margin>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Spinner fx:id="spawnSpinner" editable="true" prefHeight="23.0" prefWidth="99.0">
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="16" max="29999984" min="0" />
|
||||||
|
</valueFactory>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
<HBox layoutX="7.0" layoutY="127.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Simulation Distance:" HBox.hgrow="ALWAYS">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip text="The radius of chunks for each player where ticks will be updated. In other words, anything outside these circles, such as furnaces, mobs, etc, will not be updated or simulated." />
|
||||||
|
</tooltip>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets />
|
||||||
|
</HBox.margin>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Spinner fx:id="simulationSpinner" editable="true" prefWidth="80.0">
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="10" max="40" min="0" />
|
||||||
|
</valueFactory>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
<HBox layoutX="7.0" layoutY="160.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Render Distance:" HBox.hgrow="ALWAYS">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip text="The radius of chunks where the server will render the view distance. Any value higher on a client than what is set will be ignored. Higher values will be more demanding on the server." />
|
||||||
|
</tooltip>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets />
|
||||||
|
</HBox.margin>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Spinner fx:id="renderSpinner" editable="true" prefWidth="80.0">
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="10" max="40" min="2" />
|
||||||
|
</valueFactory>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
<HBox layoutX="7.0" layoutY="192.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Maximum Tick Time (in milliseconds):" HBox.hgrow="ALWAYS">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip text="If the server cannot update ticks (i.e. "lags") for longer than this amount of time, the server will shutdown. 60000 ms (60 seconds) is the default." />
|
||||||
|
</tooltip>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Spinner fx:id="maxTickSpinner" editable="true">
|
||||||
|
<valueFactory>
|
||||||
|
<SpinnerValueFactory.IntegerSpinnerValueFactory amountToStepBy="1" initialValue="60000" max="180000" min="10000" />
|
||||||
|
</valueFactory>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Spinner>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
<padding>
|
||||||
|
<Insets top="7.0" />
|
||||||
|
</padding>
|
||||||
|
</TitledPane>
|
||||||
|
</children>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
|
||||||
|
</padding>
|
||||||
|
</VBox>
|
||||||
|
<VBox GridPane.columnIndex="1" GridPane.hgrow="ALWAYS">
|
||||||
|
<children>
|
||||||
|
<TitledPane fx:id="difficultyPane" animated="false" collapsible="false" text="Difficulty" VBox.vgrow="NEVER">
|
||||||
|
<content>
|
||||||
|
<AnchorPane minHeight="0.0" minWidth="0.0">
|
||||||
|
<children>
|
||||||
|
<ChoiceBox fx:id="difficultyBox" layoutX="14.0" layoutY="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
|
<contextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<items>
|
||||||
|
<MenuItem mnemonicParsing="false" />
|
||||||
|
</items>
|
||||||
|
</ContextMenu>
|
||||||
|
</contextMenu>
|
||||||
|
</ChoiceBox>
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
</TitledPane>
|
||||||
|
<TitledPane fx:id="gamemodePane" animated="false" collapsible="false" text="Gamemode" VBox.vgrow="NEVER">
|
||||||
|
<content>
|
||||||
|
<AnchorPane>
|
||||||
|
<children>
|
||||||
|
<ChoiceBox fx:id="gamemodeBox" layoutX="14.0" layoutY="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
<padding>
|
||||||
|
<Insets top="7.0" />
|
||||||
|
</padding>
|
||||||
|
</TitledPane>
|
||||||
|
<TitledPane fx:id="worldTypePane" animated="false" collapsible="false" text="World Type">
|
||||||
|
<content>
|
||||||
|
<AnchorPane minHeight="0.0" minWidth="0.0">
|
||||||
|
<children>
|
||||||
|
<ChoiceBox fx:id="worldTypeBox" layoutX="14.0" layoutY="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
<padding>
|
||||||
|
<Insets top="7.0" />
|
||||||
|
</padding>
|
||||||
|
</TitledPane>
|
||||||
|
</children>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets bottom="7.0" left="7.0" right="7.0" top="7.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</VBox>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" VBox.vgrow="NEVER">
|
||||||
|
<children>
|
||||||
|
<ButtonBar fx:id="buttonBar" buttonMinWidth="75.0" buttonOrder="L+R" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS">
|
||||||
|
<buttons>
|
||||||
|
<Button fx:id="infoButton" mnemonicParsing="false" onAction="#onInfo" text="About ServerCraft" ButtonBar.buttonData="LEFT" />
|
||||||
|
<Button fx:id="defaultsButton" disable="true" mnemonicParsing="false" onAction="#onDefaults" text="Reset to Defaults" ButtonBar.buttonData="LEFT" />
|
||||||
|
<Button fx:id="buildButton" disable="true" mnemonicParsing="false" onAction="#onBuild" text="Build Server" ButtonBar.buttonData="RIGHT" />
|
||||||
|
<Button fx:id="startButton" defaultButton="true" disable="true" mnemonicParsing="false" onAction="#onStart" prefWidth="120.0" text="Start Server" ButtonBar.buttonData="RIGHT" />
|
||||||
|
</buttons>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</ButtonBar>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</VBox>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</AnchorPane>
|
||||||
|
|
Loading…
Add table
Reference in a new issue