diff --git a/pom.xml b/pom.xml index 0d5610083..ec08c0e7e 100644 --- a/pom.xml +++ b/pom.xml @@ -33,10 +33,10 @@ - - 14 - 14 - + + 14 + 14 + @@ -54,11 +54,23 @@ guava 29.0-jre - dnsjava dnsjava 3.2.2 + + org.openjfx + javafx-controls + 14.0.1 + pom + + + org.openjfx + javafx-fxml + 14.0.1 + pom + + \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/Launcher.java b/src/main/java/de/bixilon/minosoft/Launcher.java new file mode 100644 index 000000000..88e6e3cde --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/Launcher.java @@ -0,0 +1,49 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft; + +import de.bixilon.minosoft.gui.main.GUITools; +import de.bixilon.minosoft.gui.main.Server; +import de.bixilon.minosoft.gui.main.ServerListCell; +import javafx.application.Application; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.Scene; +import javafx.scene.control.ListView; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; + + +public class Launcher extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + ListView listView = new ListView<>(); + listView.setCellFactory((lv) -> ServerListCell.newInstance()); + + ObservableList servers = FXCollections.observableArrayList(); + servers.addAll(Minosoft.serverList); + listView.setItems(servers); + + Scene scene = new Scene(new BorderPane(listView), 400, 450); + primaryStage.setScene(scene); + primaryStage.setTitle("Minosoft"); + primaryStage.getIcons().add(GUITools.logo); + primaryStage.show(); + } +} \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/Minosoft.java b/src/main/java/de/bixilon/minosoft/Minosoft.java index f12b839b7..64de9852e 100644 --- a/src/main/java/de/bixilon/minosoft/Minosoft.java +++ b/src/main/java/de/bixilon/minosoft/Minosoft.java @@ -15,12 +15,10 @@ package de.bixilon.minosoft; import de.bixilon.minosoft.config.Configuration; import de.bixilon.minosoft.config.GameConfiguration; -import de.bixilon.minosoft.game.datatypes.Player; import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Versions; +import de.bixilon.minosoft.gui.main.Server; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.logging.LogLevels; -import de.bixilon.minosoft.protocol.network.Connection; -import de.bixilon.minosoft.protocol.protocol.ConnectionReasons; import de.bixilon.minosoft.util.FolderUtil; import de.bixilon.minosoft.util.OSUtil; import de.bixilon.minosoft.util.Util; @@ -33,7 +31,8 @@ import java.util.UUID; public class Minosoft { static Configuration config; - static ArrayList accountList; + public static ArrayList accountList; + public static ArrayList serverList; public static void main(String[] args) { // init log thread @@ -49,7 +48,7 @@ public class Minosoft { e.printStackTrace(); return; } - Log.info(String.format("Loaded config file (version=%s)", config.getInteger(GameConfiguration.CONFIG_VERSION))); + Log.info(String.format("Loaded config file (version=%s)", config.getInt(GameConfiguration.CONFIG_VERSION))); // set log level from config Log.setLevel(LogLevels.valueOf(config.getString(GameConfiguration.GENERAL_LOG_LEVEL))); Log.info(String.format("Logging info with level: %s", Log.getLevel())); @@ -83,8 +82,9 @@ public class Minosoft { } else { Log.mojang("Could not refresh session, you will not be able to join premium servers!"); } - Connection c = new Connection(1, config.getString("debug.host"), new Player(account)); - c.resolve(ConnectionReasons.CONNECT); // resolve dns address and connect + + serverList = config.getServers(); + Launcher.main(args); } /** diff --git a/src/main/java/de/bixilon/minosoft/PingCallback.java b/src/main/java/de/bixilon/minosoft/PingCallback.java new file mode 100644 index 000000000..1b67d90a8 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/PingCallback.java @@ -0,0 +1,18 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft; + +public interface PingCallback { + void handle(ServerListPing ping); +} diff --git a/src/main/java/de/bixilon/minosoft/ServerListPing.java b/src/main/java/de/bixilon/minosoft/ServerListPing.java index d1c237967..1f0032dd4 100644 --- a/src/main/java/de/bixilon/minosoft/ServerListPing.java +++ b/src/main/java/de/bixilon/minosoft/ServerListPing.java @@ -15,6 +15,8 @@ package de.bixilon.minosoft; import com.google.gson.JsonObject; import de.bixilon.minosoft.game.datatypes.TextComponent; +import de.bixilon.minosoft.gui.main.GUITools; +import javafx.scene.image.Image; public class ServerListPing { final JsonObject raw; @@ -40,7 +42,14 @@ public class ServerListPing { } public String getBase64EncodedFavicon() { - return raw.get("favicon").getAsString(); + if (raw.has("favicon")) { + return raw.get("favicon").getAsString().replace("data:image/png;base64,", ""); + } + return null; + } + + public Image getFavicon() { + return GUITools.getImageFromBase64(getBase64EncodedFavicon()); } public TextComponent getMotd() { diff --git a/src/main/java/de/bixilon/minosoft/config/Configuration.java b/src/main/java/de/bixilon/minosoft/config/Configuration.java index 184a7c3ca..f5f2cff0b 100644 --- a/src/main/java/de/bixilon/minosoft/config/Configuration.java +++ b/src/main/java/de/bixilon/minosoft/config/Configuration.java @@ -14,6 +14,7 @@ package de.bixilon.minosoft.config; import de.bixilon.minosoft.Config; +import de.bixilon.minosoft.gui.main.Server; import de.bixilon.minosoft.util.mojang.api.MojangAccount; import org.yaml.snakeyaml.Yaml; @@ -56,12 +57,12 @@ public class Configuration { return getBoolean(config.getPath()); } - public int getInteger(String path) { + public int getInt(String path) { return (int) get(path); } - public int getInteger(ConfigEnum config) { - return getInteger(config.getPath()); + public int getInt(ConfigEnum config) { + return getInt(config.getPath()); } public String getString(String path) { @@ -80,11 +81,11 @@ public class Configuration { put(path, value); } - public void putInteger(ConfigEnum config, int value) { - putInteger(config.getPath(), value); + public void putInt(ConfigEnum config, int value) { + putInt(config.getPath(), value); } - public void putInteger(String path, int value) { + public void putInt(String path, int value) { put(path, value); } @@ -104,6 +105,17 @@ public class Configuration { putString(basePath + "playerName", account.getPlayerName()); } + public void putServer(Server server) { + String basePath = String.format("servers.%d.", server.getId()); + putString(basePath + "name", server.getName()); + putString(basePath + "address", server.getAddress()); + putString(basePath + "account", server.getAccount()); + putInt(basePath + "version", server.getDesiredVersion()); + if (server.getBase64Favicon() != null) { + putString(basePath + "favicon", server.getBase64Favicon()); + } + } + public Object get(String path) { if (path.contains(".")) { // split @@ -151,15 +163,34 @@ public class Configuration { public ArrayList getMojangAccounts() { ArrayList accounts = new ArrayList<>(); - LinkedHashMap objects = (LinkedHashMap) get("account.accounts"); + LinkedHashMap> objects = (LinkedHashMap>) get("account.accounts"); if (objects == null) { return accounts; } - for (Map.Entry set : objects.entrySet()) { - LinkedHashMap entry = (LinkedHashMap) set.getValue(); + for (Map.Entry> set : objects.entrySet()) { + LinkedHashMap entry = set.getValue(); accounts.add(new MojangAccount((String) entry.get("accessToken"), set.getKey(), UUID.fromString((String) entry.get("uuid")), (String) entry.get("playerName"), (String) entry.get("mojangUserName"))); } return accounts; } + + public ArrayList getServers() { + ArrayList servers = new ArrayList<>(); + LinkedHashMap> objects = (LinkedHashMap>) get("servers"); + if (objects == null) { + return servers; + } + for (Map.Entry> set : objects.entrySet()) { + LinkedHashMap entry = set.getValue(); + String favicon = null; + if (entry.containsKey("favicon")) { + favicon = (String) entry.get("favicon"); + } + servers.add(new Server(Integer.parseInt(set.getKey()), (String) entry.get("name"), (String) entry.get("address"), (String) entry.get("account"), (int) entry.get("version"), favicon)); + } + return servers; + } + } + diff --git a/src/main/java/de/bixilon/minosoft/gui/main/GUITools.java b/src/main/java/de/bixilon/minosoft/gui/main/GUITools.java new file mode 100644 index 000000000..7effef3c4 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/main/GUITools.java @@ -0,0 +1,30 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.main; + +import javafx.scene.image.Image; + +import java.io.ByteArrayInputStream; +import java.util.Base64; + +public class GUITools { + public final static Image logo = new Image(GUITools.class.getResourceAsStream("/icons/windowIcon.png")); + + public static Image getImageFromBase64(String base64) { + if (base64 == null) { + return null; + } + return new Image(new ByteArrayInputStream(Base64.getDecoder().decode(base64))); + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/main/Server.java b/src/main/java/de/bixilon/minosoft/gui/main/Server.java new file mode 100644 index 000000000..41408b95b --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/main/Server.java @@ -0,0 +1,101 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.main; + +import de.bixilon.minosoft.Config; +import de.bixilon.minosoft.Minosoft; +import javafx.scene.image.Image; + +import javax.annotation.Nullable; + +public class Server { + final int id; + String name; + String address; + String account; + int desiredVersion; + String favicon; + + public Server(int id, String name, String address, String account, int desiredVersion) { + this.id = id; + this.name = name; + this.address = address; + this.account = account; + this.desiredVersion = desiredVersion; + } + + public Server(int id, String name, String address, String account, int desiredVersion, String favicon) { + this.id = id; + this.name = name; + this.address = address; + this.account = account; + this.desiredVersion = desiredVersion; + this.favicon = favicon; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public int getDesiredVersion() { + return desiredVersion; + } + + public void setDesiredVersion(int desiredVersion) { + this.desiredVersion = desiredVersion; + } + + @Nullable + public String getBase64Favicon() { + return favicon; + } + + public void setBase64Favicon(String favicon) { + this.favicon = favicon; + } + + @Nullable + public Image getFavicon() { + return GUITools.getImageFromBase64(getBase64Favicon()); + } + + public int getId() { + return id; + } + + public void saveToConfig() { + Minosoft.getConfig().putServer(this); + Minosoft.getConfig().saveToFile(Config.configFileName); + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java new file mode 100644 index 000000000..5525b53a6 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java @@ -0,0 +1,129 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.main; + +import de.bixilon.minosoft.Minosoft; +import de.bixilon.minosoft.game.datatypes.Player; +import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Version; +import de.bixilon.minosoft.game.datatypes.objectLoader.versions.Versions; +import de.bixilon.minosoft.protocol.network.Connection; +import de.bixilon.minosoft.protocol.protocol.ConnectionReasons; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.MenuItem; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +public class ServerListCell extends ListCell implements Initializable { + + @FXML + public ImageView icon; + @FXML + public Label motd; + @FXML + public Label version; + @FXML + public ImageView ping; //ToDo + @FXML + public Label players; + @FXML + public MenuItem optionsConnect; + @FXML + public MenuItem optionsEdit; + @FXML + public MenuItem optionsDelete; + @FXML + private Label serverName; + @FXML + private AnchorPane root; + private Server model; + + public static ServerListCell newInstance() { + FXMLLoader loader = new FXMLLoader(ServerListCell.class.getResource("/layout/cells/server.fxml")); + try { + loader.load(); + return loader.getController(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /** + * Initializes the controller class. + */ + @Override + public void initialize(URL url, ResourceBundle rb) { + updateSelected(false); + setGraphic(root); + } + + public AnchorPane getRoot() { + return root; + } + + @Override + protected void updateItem(Server server, boolean empty) { + super.updateItem(server, empty); + getRoot().getChildrenUnmodifiable().forEach(c -> c.setVisible(!empty)); + if (!empty && server != null && !server.equals(this.model)) { + serverName.setText(server.getName()); + Image favicon = server.getFavicon(); + if (favicon == null) { + favicon = GUITools.logo; + } + icon.setImage(favicon); + + Connection c = new Connection(server.getId(), server.getAddress(), new Player(Minosoft.accountList.get(0))); + c.addPingCallback(ping -> Platform.runLater(() -> { + if (ping == null) { + // Offline + players.setText(""); + version.setText("Offline"); + optionsConnect.setDisable(true); + return; + } + players.setText(String.format("%d/%d", ping.getPlayerOnline(), ping.getMaxPlayers())); + Version serverVersion = Versions.getVersionById(ping.getProtocolNumber()); + if (serverVersion == null) { + version.setText(String.format("UNKNOWN(%d)", ping.getProtocolNumber())); + } else { + version.setText(serverVersion.getVersionName()); + } + motd.setText(ping.getMotd().getRawMessage()); + if (ping.getFavicon() != null) { + server.setBase64Favicon(ping.getBase64EncodedFavicon()); + server.saveToConfig(); + icon.setImage(ping.getFavicon()); + } + })); + c.resolve(ConnectionReasons.PING); // resolve dns address and connect + } + this.model = server; + } + + @Override + public void updateSelected(boolean selected) { + super.updateSelected(selected); + } +} \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java index 216978c30..b434361bf 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java @@ -14,6 +14,8 @@ package de.bixilon.minosoft.protocol.network; import de.bixilon.minosoft.Minosoft; +import de.bixilon.minosoft.PingCallback; +import de.bixilon.minosoft.ServerListPing; import de.bixilon.minosoft.config.GameConfiguration; import de.bixilon.minosoft.game.datatypes.Player; import de.bixilon.minosoft.game.datatypes.VelocityHandler; @@ -45,13 +47,15 @@ public class Connection { final PacketSender sender = new PacketSender(this); final ArrayList handlingQueue = new ArrayList<>(); final VelocityHandler velocityHandler = new VelocityHandler(this); + final ArrayList pingCallbacks = new ArrayList<>(); final int connectionId; + final Player player; + int desiredVersionNumber = -1; ServerAddress address; PluginChannelHandler pluginChannelHandler; Thread handleThread; Version version = Versions.getLowestVersionSupported(); // default final CustomMapping customMapping = new CustomMapping(version); - final Player player; ConnectionStates state = ConnectionStates.DISCONNECTED; ConnectionReasons reason; ConnectionReasons nextReason; @@ -166,8 +170,10 @@ public class Connection { Log.warn(String.format("Could not connect to %s, trying next hostname: %s", address, nextAddress)); this.address = nextAddress; resolve(address); + } else { + // no connection and no servers available anymore... sorry, but you can not play today :( + handleCallbacks(null); } - // else: failed break; } } @@ -295,7 +301,7 @@ public class Connection { public int getPacketCommand(Packets.Serverbound packet) { Integer command = null; - if (getReason() != ConnectionReasons.GET_VERSION) { + if (getReason() == ConnectionReasons.CONNECT) { command = version.getCommandByPacket(packet); } if (command == null) { @@ -306,7 +312,7 @@ public class Connection { public Packets.Clientbound getPacketByCommand(ConnectionStates state, int command) { Packets.Clientbound packet = null; - if (getReason() != ConnectionReasons.GET_VERSION) { + if (getReason() == ConnectionReasons.CONNECT) { packet = version.getPacketByCommand(state, command); } if (packet == null) { @@ -322,4 +328,26 @@ public class Connection { public int getConnectionId() { return connectionId; } + + public void addPingCallback(PingCallback pingCallback) { + pingCallbacks.add(pingCallback); + } + + public ArrayList getPingCallbacks() { + return pingCallbacks; + } + + public int getDesiredVersionNumber() { + return desiredVersionNumber; + } + + public void setDesiredVersionNumber(int desiredVersionNumber) { + this.desiredVersionNumber = desiredVersionNumber; + } + + public void handleCallbacks(ServerListPing ping) { + for (PingCallback callback : getPingCallbacks()) { + callback.handle(ping); + } + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/Network.java b/src/main/java/de/bixilon/minosoft/protocol/network/Network.java index 9f4386539..7b21fe2aa 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/Network.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/Network.java @@ -31,9 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketTimeoutException; +import java.net.*; import java.util.ArrayList; public class Network { @@ -201,7 +199,7 @@ public class Network { connection.setConnectionState(ConnectionStates.DISCONNECTED); } catch (IOException e) { // Could not connect - if (e instanceof SocketTimeoutException) { + if (e instanceof SocketTimeoutException || e instanceof ConnectException || e instanceof UnknownHostException) { connection.setConnectionState(ConnectionStates.FAILED); } e.printStackTrace(); diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java index d50177e1d..3e3a332f3 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -13,7 +13,6 @@ package de.bixilon.minosoft.protocol.protocol; -import de.bixilon.minosoft.Minosoft; import de.bixilon.minosoft.game.datatypes.GameModes; import de.bixilon.minosoft.game.datatypes.entities.Entity; import de.bixilon.minosoft.game.datatypes.entities.meta.HumanMetaData; @@ -56,21 +55,21 @@ public class PacketHandler { } public void handle(PacketStatusResponse pkg) { - if (connection.getReason() == ConnectionReasons.GET_VERSION) { - // now we know the version, set it, if the config allows it - Version version; - int versionId = Minosoft.getConfig().getInteger("debug.version"); - if (versionId == -1) { - versionId = pkg.getResponse().getProtocolNumber(); - } - version = Versions.getVersionById(versionId); - if (version == null) { - Log.fatal(String.format("Server is running on unknown version or a invalid version was forced (version=%d). Exiting...", versionId)); - System.exit(1); - } - Log.info(String.format("Status response received: %s/%s online. MotD: '%s'", pkg.getResponse().getPlayerOnline(), pkg.getResponse().getMaxPlayers(), pkg.getResponse().getMotd().getColoredMessage())); + // now we know the version, set it, if the config allows it + Version version; + int versionId = connection.getDesiredVersionNumber(); + if (versionId == -1) { + versionId = pkg.getResponse().getProtocolNumber(); + } + version = Versions.getVersionById(versionId); + if (version == null) { + Log.fatal(String.format("Server is running on unknown version or a invalid version was forced (version=%d). Disconnecting...", versionId)); + connection.disconnect(); + } else { connection.setVersion(version); } + Log.info(String.format("Status response received: %s/%s online. MotD: '%s'", pkg.getResponse().getPlayerOnline(), pkg.getResponse().getMaxPlayers(), pkg.getResponse().getMotd().getColoredMessage())); + connection.handleCallbacks(pkg.getResponse()); } public void handle(PacketStatusPong pkg) { diff --git a/src/main/resources/config/game.yml b/src/main/resources/config/game.yml index e657ebb87..1d87a0c57 100644 --- a/src/main/resources/config/game.yml +++ b/src/main/resources/config/game.yml @@ -15,7 +15,4 @@ account: clientToken: "randomGenerated" accounts: -# this will be removed soon, only for debugging (pre alpha stage): some features are not implemented yet -/- -debug: - server: "127.0.0.1" - version: -1 \ No newline at end of file +servers: diff --git a/src/main/resources/icons/windowIcon.png b/src/main/resources/icons/windowIcon.png new file mode 100644 index 000000000..1ae5d4d30 Binary files /dev/null and b/src/main/resources/icons/windowIcon.png differ