mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 01:16:46 -04:00
Launcher: server list: option to edit and connect
This commit is contained in:
parent
ff4445d6b9
commit
eb2c1eff63
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft;
|
package de.bixilon.minosoft;
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Version;
|
||||||
|
import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Versions;
|
||||||
import de.bixilon.minosoft.gui.main.GUITools;
|
import de.bixilon.minosoft.gui.main.GUITools;
|
||||||
import de.bixilon.minosoft.gui.main.Server;
|
import de.bixilon.minosoft.gui.main.Server;
|
||||||
import de.bixilon.minosoft.gui.main.ServerListCell;
|
import de.bixilon.minosoft.gui.main.ServerListCell;
|
||||||
@ -24,6 +26,9 @@ import javafx.scene.control.ListView;
|
|||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
public class Launcher extends Application {
|
public class Launcher extends Application {
|
||||||
|
|
||||||
@ -33,6 +38,18 @@ public class Launcher extends Application {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) {
|
public void start(Stage primaryStage) {
|
||||||
|
GUITools.versions.add(Versions.getLowestVersionSupported());
|
||||||
|
for (Map.Entry<Integer, Version> version : Versions.getVersionMap().entrySet()) {
|
||||||
|
GUITools.versions.add(version.getValue());
|
||||||
|
}
|
||||||
|
Comparator<Version> comparator = Comparator.comparingInt(Version::getProtocolVersion);
|
||||||
|
FXCollections.sort(GUITools.versions, comparator);
|
||||||
|
GUITools.versions.sort((a, b) -> {
|
||||||
|
if (a.getProtocolVersion() == -1) {
|
||||||
|
return -Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
return (b.getProtocolVersion() - a.getProtocolVersion());
|
||||||
|
});
|
||||||
ListView<Server> listView = new ListView<>();
|
ListView<Server> listView = new ListView<>();
|
||||||
listView.setCellFactory((lv) -> ServerListCell.newInstance());
|
listView.setCellFactory((lv) -> ServerListCell.newInstance());
|
||||||
|
|
||||||
@ -40,7 +57,7 @@ public class Launcher extends Application {
|
|||||||
servers.addAll(Minosoft.serverList);
|
servers.addAll(Minosoft.serverList);
|
||||||
listView.setItems(servers);
|
listView.setItems(servers);
|
||||||
|
|
||||||
Scene scene = new Scene(new BorderPane(listView), 400, 450);
|
Scene scene = new Scene(new BorderPane(listView), 550, 800);
|
||||||
primaryStage.setScene(scene);
|
primaryStage.setScene(scene);
|
||||||
primaryStage.setTitle("Minosoft");
|
primaryStage.setTitle("Minosoft");
|
||||||
primaryStage.getIcons().add(GUITools.logo);
|
primaryStage.getIcons().add(GUITools.logo);
|
||||||
|
@ -81,6 +81,9 @@ public class Version {
|
|||||||
if (super.equals(obj)) {
|
if (super.equals(obj)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (hashCode() != obj.hashCode()) {
|
if (hashCode() != obj.hashCode()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,10 @@ public class Versions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Version getLowestVersionSupported() {
|
public static Version getLowestVersionSupported() {
|
||||||
return new Version("13w41b", 0, null, null);
|
return new Version("Automatic", -1, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HashBiMap<Integer, Version> getVersionMap() {
|
||||||
|
return versionMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.main;
|
package de.bixilon.minosoft.gui.main;
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Version;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -20,6 +23,7 @@ import java.util.Base64;
|
|||||||
|
|
||||||
public class GUITools {
|
public class GUITools {
|
||||||
public final static Image logo = new Image(GUITools.class.getResourceAsStream("/icons/windowIcon.png"));
|
public final static Image logo = new Image(GUITools.class.getResourceAsStream("/icons/windowIcon.png"));
|
||||||
|
public final static ObservableList<Version> versions = FXCollections.observableArrayList();
|
||||||
|
|
||||||
public static Image getImageFromBase64(String base64) {
|
public static Image getImageFromBase64(String base64) {
|
||||||
if (base64 == null) {
|
if (base64 == null) {
|
||||||
|
@ -17,19 +17,24 @@ import de.bixilon.minosoft.Minosoft;
|
|||||||
import de.bixilon.minosoft.game.datatypes.Player;
|
import de.bixilon.minosoft.game.datatypes.Player;
|
||||||
import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Version;
|
import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Version;
|
||||||
import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Versions;
|
import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Versions;
|
||||||
|
import de.bixilon.minosoft.logging.Log;
|
||||||
import de.bixilon.minosoft.protocol.network.Connection;
|
import de.bixilon.minosoft.protocol.network.Connection;
|
||||||
import de.bixilon.minosoft.protocol.protocol.ConnectionReasons;
|
import de.bixilon.minosoft.protocol.protocol.ConnectionReasons;
|
||||||
|
import de.bixilon.minosoft.util.DNSUtil;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.Label;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.ListCell;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.MenuItem;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.util.Callback;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -57,7 +62,7 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
|||||||
private Label serverName;
|
private Label serverName;
|
||||||
@FXML
|
@FXML
|
||||||
private AnchorPane root;
|
private AnchorPane root;
|
||||||
private Server model;
|
private Server server;
|
||||||
|
|
||||||
public static ServerListCell newInstance() {
|
public static ServerListCell newInstance() {
|
||||||
FXMLLoader loader = new FXMLLoader(ServerListCell.class.getResource("/layout/cells/server.fxml"));
|
FXMLLoader loader = new FXMLLoader(ServerListCell.class.getResource("/layout/cells/server.fxml"));
|
||||||
@ -87,15 +92,21 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
|||||||
protected void updateItem(Server server, boolean empty) {
|
protected void updateItem(Server server, boolean empty) {
|
||||||
super.updateItem(server, empty);
|
super.updateItem(server, empty);
|
||||||
getRoot().getChildrenUnmodifiable().forEach(c -> c.setVisible(!empty));
|
getRoot().getChildrenUnmodifiable().forEach(c -> c.setVisible(!empty));
|
||||||
if (!empty && server != null && !server.equals(this.model)) {
|
if (!empty && server != null && !server.equals(this.server)) {
|
||||||
|
this.server = server;
|
||||||
serverName.setText(server.getName());
|
serverName.setText(server.getName());
|
||||||
Image favicon = server.getFavicon();
|
Image favicon = server.getFavicon();
|
||||||
if (favicon == null) {
|
if (favicon == null) {
|
||||||
favicon = GUITools.logo;
|
favicon = GUITools.logo;
|
||||||
}
|
}
|
||||||
icon.setImage(favicon);
|
icon.setImage(favicon);
|
||||||
|
optionsConnect.setOnAction(e -> {
|
||||||
|
Connection connection = new Connection(Connection.lastConnectionId++, server.getAddress(), new Player(Minosoft.accountList.get(0)));
|
||||||
|
connection.resolve(ConnectionReasons.CONNECT);
|
||||||
|
});
|
||||||
|
optionsEdit.setOnAction(e -> edit());
|
||||||
|
|
||||||
Connection connection = new Connection(server.getId(), server.getAddress(), new Player(Minosoft.accountList.get(0)));
|
Connection connection = new Connection(Connection.lastConnectionId++, server.getAddress(), null);
|
||||||
connection.addPingCallback(ping -> Platform.runLater(() -> {
|
connection.addPingCallback(ping -> Platform.runLater(() -> {
|
||||||
if (ping == null) {
|
if (ping == null) {
|
||||||
// Offline
|
// Offline
|
||||||
@ -105,7 +116,12 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
players.setText(String.format("%d/%d", ping.getPlayerOnline(), ping.getMaxPlayers()));
|
players.setText(String.format("%d/%d", ping.getPlayerOnline(), ping.getMaxPlayers()));
|
||||||
Version serverVersion = Versions.getVersionById(ping.getProtocolNumber());
|
Version serverVersion;
|
||||||
|
if (server.getDesiredVersion() == -1) {
|
||||||
|
serverVersion = Versions.getVersionById(ping.getProtocolNumber());
|
||||||
|
} else {
|
||||||
|
serverVersion = Versions.getVersionById(server.getDesiredVersion());
|
||||||
|
}
|
||||||
if (serverVersion == null) {
|
if (serverVersion == null) {
|
||||||
version.setText(ping.getServerVersion());
|
version.setText(ping.getServerVersion());
|
||||||
version.setTextFill(Color.RED);
|
version.setTextFill(Color.RED);
|
||||||
@ -120,13 +136,93 @@ public class ServerListCell extends ListCell<Server> implements Initializable {
|
|||||||
icon.setImage(ping.getFavicon());
|
icon.setImage(ping.getFavicon());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
connection.resolve(ConnectionReasons.PING); // resolve dns address and connect
|
connection.resolve(ConnectionReasons.PING); // resolve dns address and ping
|
||||||
}
|
}
|
||||||
this.model = server;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSelected(boolean selected) {
|
public void updateSelected(boolean selected) {
|
||||||
super.updateSelected(selected);
|
super.updateSelected(selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void edit() {
|
||||||
|
// Create the custom dialog.
|
||||||
|
Dialog<Pair<String, String>> dialog = new Dialog<>();
|
||||||
|
dialog.setTitle("Edit server: " + server.getName());
|
||||||
|
dialog.setHeaderText("Edit the details of the server");
|
||||||
|
|
||||||
|
|
||||||
|
// Set the button types.
|
||||||
|
ButtonType loginButtonType = new ButtonType("Save", ButtonBar.ButtonData.OK_DONE);
|
||||||
|
dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);
|
||||||
|
|
||||||
|
// Create the username and password labels and fields.
|
||||||
|
GridPane grid = new GridPane();
|
||||||
|
grid.setHgap(10);
|
||||||
|
grid.setVgap(10);
|
||||||
|
grid.setPadding(new Insets(20, 300, 10, 10));
|
||||||
|
|
||||||
|
TextField serverName = new TextField();
|
||||||
|
serverName.setPromptText("Servername");
|
||||||
|
serverName.setText(server.getName());
|
||||||
|
TextField serverAddress = new TextField();
|
||||||
|
serverAddress.setPromptText("Server address");
|
||||||
|
serverAddress.setText(server.getAddress());
|
||||||
|
|
||||||
|
ComboBox<Version> versionList = new ComboBox<>(GUITools.versions);
|
||||||
|
versionList.setCellFactory(new Callback<>() {
|
||||||
|
@Override
|
||||||
|
public ListCell<Version> call(ListView<Version> p) {
|
||||||
|
return new ListCell<>() {
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Version version, boolean empty) {
|
||||||
|
super.updateItem(version, empty);
|
||||||
|
if (!empty && version != null) {
|
||||||
|
setText(String.format("%s (%d)", version.getVersionName(), version.getProtocolVersion()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (server.getDesiredVersion() == -1) {
|
||||||
|
versionList.getSelectionModel().select(Versions.getLowestVersionSupported());
|
||||||
|
} else {
|
||||||
|
versionList.getSelectionModel().select(Versions.getVersionById(server.getDesiredVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.add(new Label("Servername:"), 0, 0);
|
||||||
|
grid.add(serverName, 1, 0);
|
||||||
|
grid.add(new Label("Server address:"), 0, 1);
|
||||||
|
grid.add(serverAddress, 1, 1);
|
||||||
|
grid.add(new Label("Version:"), 0, 2);
|
||||||
|
grid.add(versionList, 1, 2);
|
||||||
|
|
||||||
|
// Enable/Disable login button depending on whether a username was entered.
|
||||||
|
Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
|
||||||
|
|
||||||
|
// Do some validation (using the Java 8 lambda syntax).
|
||||||
|
serverAddress.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
loginButton.setDisable(newValue.trim().isEmpty());
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.getDialogPane().setContent(grid);
|
||||||
|
|
||||||
|
// Request focus on the username field by default.
|
||||||
|
Platform.runLater(serverName::requestFocus);
|
||||||
|
|
||||||
|
// Convert the result to a username-password-pair when the login button is clicked.
|
||||||
|
dialog.setResultConverter(dialogButton -> {
|
||||||
|
if (dialogButton == loginButtonType) {
|
||||||
|
ServerListCell.this.serverName.setText(serverName.getText());
|
||||||
|
ServerListCell.this.server.setName(serverName.getText());
|
||||||
|
ServerListCell.this.server.setDesiredVersion(versionList.getSelectionModel().getSelectedItem().getProtocolVersion());
|
||||||
|
ServerListCell.this.server.setAddress(DNSUtil.correctHostName(serverAddress.getText()));
|
||||||
|
ServerListCell.this.server.saveToConfig();
|
||||||
|
Log.info(String.format("Edited and saved server (serverName=%s, serverAddress=%s, version=%d)", server.getName(), server.getAddress(), server.getDesiredVersion()));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.showAndWait();
|
||||||
|
}
|
||||||
}
|
}
|
@ -41,6 +41,7 @@ import org.xbill.DNS.TextParseException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class Connection {
|
public class Connection {
|
||||||
|
public static int lastConnectionId;
|
||||||
final ArrayList<ServerAddress> addresses;
|
final ArrayList<ServerAddress> addresses;
|
||||||
final Network network = new Network(this);
|
final Network network = new Network(this);
|
||||||
final PacketHandler handler = new PacketHandler(this);
|
final PacketHandler handler = new PacketHandler(this);
|
||||||
@ -352,4 +353,5 @@ public class Connection {
|
|||||||
callback.handle(ping);
|
callback.handle(ping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ public class InByteBuffer {
|
|||||||
public byte readByte() {
|
public byte readByte() {
|
||||||
byte ret;
|
byte ret;
|
||||||
ret = bytes[pos];
|
ret = bytes[pos];
|
||||||
pos = pos + 1;
|
pos++;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public final class DNSUtil {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String correctHostName(String hostname) {
|
public static String correctHostName(String hostname) {
|
||||||
// replaces invalid chars to avoid copy and paste issues (like spaces, ...)
|
// replaces invalid chars to avoid copy and paste issues (like spaces, ...)
|
||||||
hostname = hostname.replaceAll("\\s", "");
|
hostname = hostname.replaceAll("\\s", "");
|
||||||
return hostname;
|
return hostname;
|
||||||
|
20
src/main/resources/layout/main.fxml
Normal file
20
src/main/resources/layout/main.fxml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
<VBox xmlns:fx="http://javafx.com/fxml/1" prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/11.0.1">
|
||||||
|
<MenuBar VBox.vgrow="NEVER">
|
||||||
|
<Menu mnemonicParsing="false" text="File">
|
||||||
|
<MenuItem mnemonicParsing="false" text="Preferences…"/>
|
||||||
|
<SeparatorMenuItem mnemonicParsing="false"/>
|
||||||
|
<MenuItem mnemonicParsing="false" text="Quit"/>
|
||||||
|
</Menu>
|
||||||
|
<Menu mnemonicParsing="false" text="Help">
|
||||||
|
<MenuItem id="menu_help_about" mnemonicParsing="false" text="About"/>
|
||||||
|
</Menu>
|
||||||
|
</MenuBar>
|
||||||
|
<AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
|
||||||
|
<ListView id="servers" layoutX="14.0" layoutY="14.0" prefHeight="327.0" prefWidth="402.0"/>
|
||||||
|
</AnchorPane>
|
||||||
|
</VBox>
|
Loading…
x
Reference in New Issue
Block a user