From c515f495af9727995395fc9133b793268e7cba58 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Mon, 4 Jan 2021 17:42:02 +0100 Subject: [PATCH] VersionParser, more server cli features --- .../InvalidVersionCommandParseException.kt | 26 +++++++++++ .../parser/minosoft/VersionParser.java | 43 ++++++++++++++++++ .../data/mappings/versions/Versions.java | 6 +++ .../de/bixilon/minosoft/gui/main/Server.java | 20 ++++++--- .../minosoft/gui/main/ServerListCell.java | 4 +- .../commands/commands/CommandServer.java | 44 +++++++++++++++++-- 6 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/data/commands/parser/exceptions/minosoft/InvalidVersionCommandParseException.kt create mode 100644 src/main/java/de/bixilon/minosoft/data/commands/parser/minosoft/VersionParser.java diff --git a/src/main/java/de/bixilon/minosoft/data/commands/parser/exceptions/minosoft/InvalidVersionCommandParseException.kt b/src/main/java/de/bixilon/minosoft/data/commands/parser/exceptions/minosoft/InvalidVersionCommandParseException.kt new file mode 100644 index 000000000..1d9b4a868 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/commands/parser/exceptions/minosoft/InvalidVersionCommandParseException.kt @@ -0,0 +1,26 @@ +/* + * 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.data.commands.parser.exceptions.minosoft + +import de.bixilon.minosoft.data.commands.CommandStringReader +import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException + +class InvalidVersionCommandParseException : CommandParseException { + constructor(command: CommandStringReader, currentArgument: String) : super(ERROR_MESSAGE, command, currentArgument) + + constructor(command: CommandStringReader, currentArgument: String, cause: Throwable) : super(ERROR_MESSAGE, command, currentArgument, cause) + + companion object { + private const val ERROR_MESSAGE = "Invalid version!" + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/commands/parser/minosoft/VersionParser.java b/src/main/java/de/bixilon/minosoft/data/commands/parser/minosoft/VersionParser.java new file mode 100644 index 000000000..5d87015da --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/commands/parser/minosoft/VersionParser.java @@ -0,0 +1,43 @@ +/* + * 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.data.commands.parser.minosoft; + +import de.bixilon.minosoft.data.commands.CommandStringReader; +import de.bixilon.minosoft.data.commands.parser.CommandParser; +import de.bixilon.minosoft.data.commands.parser.exceptions.BlankStringCommandParseException; +import de.bixilon.minosoft.data.commands.parser.exceptions.CommandParseException; +import de.bixilon.minosoft.data.commands.parser.exceptions.minosoft.InvalidVersionCommandParseException; +import de.bixilon.minosoft.data.commands.parser.properties.ParserProperties; +import de.bixilon.minosoft.data.mappings.versions.Version; +import de.bixilon.minosoft.data.mappings.versions.Versions; +import de.bixilon.minosoft.protocol.network.Connection; + +import javax.annotation.Nullable; + +public class VersionParser extends CommandParser { + public static final VersionParser VERSION_PARSER = new VersionParser(); + + @Override + public Object parse(Connection connection, @Nullable ParserProperties properties, CommandStringReader stringReader) throws CommandParseException { + String rawVersionName = stringReader.readString(); + if (rawVersionName.isBlank()) { + throw new BlankStringCommandParseException(stringReader, rawVersionName); + } + Version version = Versions.getVersionByName(rawVersionName); + if (version == null) { + throw new InvalidVersionCommandParseException(stringReader, rawVersionName); + } + return version; + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/versions/Versions.java b/src/main/java/de/bixilon/minosoft/data/mappings/versions/Versions.java index 7bc562125..d45ceba4d 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/versions/Versions.java +++ b/src/main/java/de/bixilon/minosoft/data/mappings/versions/Versions.java @@ -34,6 +34,7 @@ public class Versions { public static final Version LOWEST_VERSION_SUPPORTED = new Version("Automatic", -1, -1, null, null); private static final HashBiMap VERSION_ID_MAP = HashBiMap.create(500); private static final HashBiMap VERSION_PROTOCOL_ID_MAP = HashBiMap.create(500); + private static final HashBiMap VERSION_NAME_MAP = HashBiMap.create(500); private static final HashSet LOADED_VERSIONS = new HashSet<>(); public static VersionMapping PRE_FLATTENING_MAPPING; @@ -45,6 +46,10 @@ public class Versions { return VERSION_PROTOCOL_ID_MAP.get(protocolId); } + public static Version getVersionByName(String name) { + return VERSION_NAME_MAP.get(name); + } + public static void loadAvailableVersions(JsonObject json) { for (String versionId : json.keySet()) { loadVersion(json, versionId); @@ -97,6 +102,7 @@ public class Versions { Version version = new Version(versionName, versionId, protocolId, serverboundPacketMapping, clientboundPacketMapping); VERSION_ID_MAP.put(version.getVersionId(), version); VERSION_PROTOCOL_ID_MAP.put(version.getProtocolId(), version); + VERSION_NAME_MAP.put(version.getVersionName(), version); return version; } diff --git a/src/main/java/de/bixilon/minosoft/gui/main/Server.java b/src/main/java/de/bixilon/minosoft/gui/main/Server.java index eec94b5e3..ea218b7ad 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/Server.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/Server.java @@ -15,7 +15,9 @@ package de.bixilon.minosoft.gui.main; import com.google.gson.JsonObject; import de.bixilon.minosoft.Minosoft; +import de.bixilon.minosoft.data.mappings.versions.Version; import de.bixilon.minosoft.data.text.BaseComponent; +import de.bixilon.minosoft.data.text.ChatComponent; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.protocol.protocol.ConnectionReasons; import de.bixilon.minosoft.protocol.protocol.LANServerListener; @@ -29,8 +31,8 @@ public class Server { private static int highestServerId; private final int id; private final ArrayList connections = new ArrayList<>(); - private BaseComponent name; - private BaseComponent addressName; + private ChatComponent name; + private ChatComponent addressName; private String address; private int desiredVersion; private byte[] favicon; @@ -38,12 +40,12 @@ public class Server { private boolean readOnly; private ServerListCell cell; - public Server(int id, BaseComponent name, String address, int desiredVersion, byte[] favicon) { + public Server(int id, ChatComponent name, String address, int desiredVersion, byte[] favicon) { this(id, name, address, desiredVersion); this.favicon = favicon; } - public Server(int id, BaseComponent name, String address, int desiredVersion) { + public Server(int id, ChatComponent name, String address, int desiredVersion) { this.id = id; if (id > highestServerId) { highestServerId = id; @@ -54,6 +56,10 @@ public class Server { this.desiredVersion = desiredVersion; } + public Server(ChatComponent name, String address, Version version) { + this(getNextServerId(), name, address, version.getVersionId()); + } + public Server(ServerAddress address) { this.id = getNextServerId(); this.name = new BaseComponent(String.format("LAN Server #%d", LANServerListener.getServerMap().size())); @@ -67,7 +73,7 @@ public class Server { } public static Server deserialize(JsonObject json) { - Server server = new Server(json.get("id").getAsInt(), new BaseComponent(json.get("name").getAsString()), json.get("address").getAsString(), json.get("version").getAsInt()); + Server server = new Server(json.get("id").getAsInt(), ChatComponent.valueOf(json.get("name").getAsString()), json.get("address").getAsString(), json.get("version").getAsInt()); if (json.has("favicon")) { server.setFavicon(Base64.getDecoder().decode(json.get("favicon").getAsString())); } @@ -117,8 +123,8 @@ public class Server { return String.format("%s (%s)", getName(), getAddress()); } - public BaseComponent getName() { - if (this.name.isEmpty()) { + public ChatComponent getName() { + if (this.name == null || ((BaseComponent) this.name).isEmpty()) { return this.addressName; } return this.name; diff --git a/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java index 31f99ba8c..2d9ffb427 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java @@ -23,7 +23,7 @@ import de.bixilon.minosoft.data.locale.Strings; import de.bixilon.minosoft.data.mappings.versions.Version; import de.bixilon.minosoft.data.mappings.versions.Versions; import de.bixilon.minosoft.data.player.PingBars; -import de.bixilon.minosoft.data.text.BaseComponent; +import de.bixilon.minosoft.data.text.ChatComponent; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.modding.event.EventInvokerCallback; import de.bixilon.minosoft.modding.event.events.ConnectionStateChangeEvent; @@ -213,7 +213,7 @@ public class ServerListCell extends ListCell implements Initializable { }))); } - public void setName(BaseComponent name) { + public void setName(ChatComponent name) { this.nameField.getChildren().setAll(name.getJavaFXText()); for (Node node : this.nameField.getChildren()) { node.setStyle("-fx-font-size: 15pt ;"); diff --git a/src/main/java/de/bixilon/minosoft/terminal/commands/commands/CommandServer.java b/src/main/java/de/bixilon/minosoft/terminal/commands/commands/CommandServer.java index 83eaa8667..d16cbc933 100644 --- a/src/main/java/de/bixilon/minosoft/terminal/commands/commands/CommandServer.java +++ b/src/main/java/de/bixilon/minosoft/terminal/commands/commands/CommandServer.java @@ -15,10 +15,22 @@ package de.bixilon.minosoft.terminal.commands.commands; import com.github.freva.asciitable.AsciiTable; import de.bixilon.minosoft.Minosoft; +import de.bixilon.minosoft.data.commands.CommandArgumentNode; import de.bixilon.minosoft.data.commands.CommandLiteralNode; import de.bixilon.minosoft.data.commands.CommandNode; +import de.bixilon.minosoft.data.commands.parser.IntegerParser; +import de.bixilon.minosoft.data.commands.parser.StringParser; +import de.bixilon.minosoft.data.commands.parser.minosoft.VersionParser; +import de.bixilon.minosoft.data.commands.parser.properties.IntegerParserProperties; +import de.bixilon.minosoft.data.commands.parser.properties.StringParserProperties; +import de.bixilon.minosoft.data.mappings.versions.Version; import de.bixilon.minosoft.data.mappings.versions.Versions; +import de.bixilon.minosoft.data.text.ChatComponent; +import de.bixilon.minosoft.gui.main.Server; +import de.bixilon.minosoft.gui.main.ServerListCell; +import javafx.application.Platform; +import javax.annotation.Nullable; import java.util.ArrayList; public class CommandServer extends Command { @@ -31,11 +43,37 @@ public class CommandServer extends Command { ArrayList tableData = new ArrayList<>(); for (var entry : Minosoft.getConfig().getServerList().entrySet()) { - tableData.add(new Object[]{entry.getKey(), entry.getValue().getAddress(), Versions.getVersionById(entry.getValue().getDesiredVersionId())}); + tableData.add(new Object[]{entry.getKey(), entry.getValue().getName(), entry.getValue().getAddress(), Versions.getVersionById(entry.getValue().getDesiredVersionId())}); } - print(AsciiTable.getTable(new String[]{"ID", "ADDRESS", "DESIRED VERSION"}, tableData.toArray(new Object[0][0]))); - }))); + print(AsciiTable.getTable(new String[]{"ID", "NAME", "ADDRESS", "DESIRED VERSION"}, tableData.toArray(new Object[0][0]))); + }), + new CommandLiteralNode("add", + new CommandArgumentNode("name", StringParser.STRING_PARSER, new StringParserProperties(StringParserProperties.StringSettings.QUOTABLE_PHRASE, false), + new CommandArgumentNode("address", StringParser.STRING_PARSER, new StringParserProperties(StringParserProperties.StringSettings.QUOTABLE_PHRASE, false), (stack) -> addServer(stack.getNonLiteralArgument(0), stack.getNonLiteralArgument(1), null), + new CommandArgumentNode("version", VersionParser.VERSION_PARSER, ((stack) -> addServer(stack.getNonLiteralArgument(0), stack.getNonLiteralArgument(1), stack.getNonLiteralArgument(2))))))), + + new CommandLiteralNode("delete", new CommandArgumentNode("id", IntegerParser.INTEGER_PARSER, new IntegerParserProperties(0, Integer.MAX_VALUE), (stack -> { + Server server = Minosoft.getConfig().getServerList().get(stack.getInt(0)); + if (server == null) { + printError("Server not found!"); + return; + } + Minosoft.getConfig().removeServer(server); + ServerListCell.SERVER_LIST_VIEW.getItems().remove(server); + }))) + )); return parent; } + + private void addServer(String name, String address, @Nullable Version version) { + if (version == null) { + version = Versions.LOWEST_VERSION_SUPPORTED; + } + Server server = new Server(ChatComponent.valueOf(name), address, version); + + server.saveToConfig(); + print("Added server %s (address=%s, version=%d)", server.getName(), server.getAddress(), server.getDesiredVersionId()); + Platform.runLater(() -> ServerListCell.SERVER_LIST_VIEW.getItems().add(server)); + } }