diff --git a/src/main/java/net/doubledoordev/backend/Main.java b/src/main/java/net/doubledoordev/backend/Main.java index b8b3780..2ddf0ad 100644 --- a/src/main/java/net/doubledoordev/backend/Main.java +++ b/src/main/java/net/doubledoordev/backend/Main.java @@ -61,7 +61,9 @@ import java.util.UUID; import static net.doubledoordev.backend.util.Constants.NAME; +import static net.doubledoordev.backend.util.Constants.SERVERS; import static net.doubledoordev.backend.util.Settings.SETTINGS; +import static net.doubledoordev.backend.util.Settings.getServerByName; /** * @author Dries007 @@ -146,6 +148,21 @@ public static void main(String[] args) throws Exception LOGGER.info("Use the help command for help."); CommandHandler.init(); + + for (Server server : SETTINGS.servers.values()) + { + if (server.getAutoStart()) + { + try + { + server.startServer(); + } + catch (Exception ignored) + { + ignored.printStackTrace(); + } + } + } } @SuppressWarnings("ResultOfMethodCallIgnored") @@ -158,6 +175,7 @@ public static synchronized void shutdown() { running = false; Settings.save(); + Cache.init(); LOGGER.info("Attempting graceful shutdown of all servers..."); for (final Server server : Settings.SETTINGS.servers.values()) { diff --git a/src/main/java/net/doubledoordev/backend/commands/CommandHandler.java b/src/main/java/net/doubledoordev/backend/commands/CommandHandler.java index 51cbb24..9052c7e 100644 --- a/src/main/java/net/doubledoordev/backend/commands/CommandHandler.java +++ b/src/main/java/net/doubledoordev/backend/commands/CommandHandler.java @@ -41,13 +41,21 @@ package net.doubledoordev.backend.commands; +import com.sk89q.intake.Command; import com.sk89q.intake.CommandException; +import com.sk89q.intake.CommandMapping; import com.sk89q.intake.context.CommandLocals; import com.sk89q.intake.dispatcher.Dispatcher; import com.sk89q.intake.fluent.CommandGraph; import com.sk89q.intake.parametric.ParametricBuilder; +import com.sk89q.intake.parametric.annotation.Optional; +import com.sk89q.intake.parametric.annotation.Switch; +import com.sk89q.intake.parametric.annotation.Text; import com.sk89q.intake.util.auth.AuthorizationException; import net.doubledoordev.backend.Main; +import net.doubledoordev.backend.server.Server; +import net.doubledoordev.backend.server.WorldManager; +import net.doubledoordev.backend.util.Cache; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -55,6 +63,9 @@ import java.io.IOException; import java.io.InputStreamReader; +import static net.doubledoordev.backend.util.Constants.JOINER_COMMA_SPACE; +import static net.doubledoordev.backend.util.Settings.SETTINGS; + /** * Using sk89q's Intake lib * @@ -62,6 +73,7 @@ */ public class CommandHandler implements Runnable { + public static final CommandHandler INSTANCE = new CommandHandler(); public static final Logger CMDLOGGER = LogManager.getLogger("cmd"); public final Dispatcher dispatcher; @@ -73,7 +85,6 @@ private CommandHandler() dispatcher = new CommandGraph() .builder(parametricBuilder) .commands() - .registerMethods(new Commands(this)) .registerMethods(this) .graph() .getDispatcher(); @@ -81,7 +92,7 @@ private CommandHandler() public static void init() { - new Thread(new CommandHandler(), "CommandHandler").start(); + new Thread(INSTANCE, "CommandHandler").start(); } @Override @@ -92,12 +103,121 @@ public void run() { try { - dispatcher.call(reader.readLine(), new CommandLocals(), new String[0]); + String command = reader.readLine(); + if (dispatcher.get(command.split(" ")[0]) != null) dispatcher.call(command, new CommandLocals(), new String[0]); + else throw new CommandNotFoundException(command); } catch (CommandException | IOException | AuthorizationException e) { CMDLOGGER.warn(e); + e.printStackTrace(); + } + } + } + + @Command(aliases = {"help", "?"}, desc = "Get a list of commands", help = "Use this to get help", usage = "[Command]", max = 1) + public void cmdHelp(@Optional String command) throws CommandException + { + // Command list + if (command == null) + { + CMDLOGGER.info("--==## Command list ##==--"); + for (CommandMapping cmd : dispatcher.getCommands()) + { + CMDLOGGER.info(cmd.getPrimaryAlias() + ' ' + cmd.getDescription().getUsage() + " => " + cmd.getDescription().getShortDescription()); // Looks like this: Name ListOfParameters => Description } } + else + { + CommandMapping cmd = dispatcher.get(command); + + if (cmd == null) throw new CommandNotFoundException(command); + + CMDLOGGER.info(String.format("--==## Help for %s ##==--", command)); + CMDLOGGER.info(String.format("Name: %s \t Aliases: %s", cmd.getPrimaryAlias(), JOINER_COMMA_SPACE.join(cmd.getAllAliases()))); + CMDLOGGER.info(String.format("Usage: %s %s", cmd.getPrimaryAlias(), cmd.getDescription().getUsage())); + CMDLOGGER.info(String.format("Short description: %s", cmd.getDescription().getShortDescription())); + CMDLOGGER.info(String.format("Help text: %s", cmd.getDescription().getHelp())); + } + } + + @Command(aliases = {"serverlist", "servers"}, desc = "List all servers", max = 0) + public void cmdServerList() + { + CMDLOGGER.info("All servers:"); + CMDLOGGER.info(JOINER_COMMA_SPACE.join(SETTINGS.getServers())); + CMDLOGGER.info("Online servers:"); + CMDLOGGER.info(JOINER_COMMA_SPACE.join(SETTINGS.getOnlineServers())); + } + + @Command(aliases = "message", desc = "Send message to servers (with /say)", usage = " ", min = 2) + public void cmdMessage(Server[] servers, @Text String msg) throws CommandException + { + for (Server server : servers) + { + if (!server.getOnline()) continue; + server.send(String.format("/say %s", msg)); + } + } + + @Command(aliases = "backup", desc = "Make full backup of one or more servers", usage = "", min = 1, max = 1) + public void cmdBackup(Server[] servers) throws CommandException + { + for (Server server : servers) + { + try + { + server.getWorldManager().bypassLimits = true; + server.getWorldManager().makeAllOfTheBackup(); + } + catch (WorldManager.BackupException e) + { + CMDLOGGER.warn("Error when making a backup of " + server.getName()); + CMDLOGGER.warn(e); + } + } + } + + @Command(aliases = "stop", desc = "Stop one or more servers", usage = " [-f (force the stop)] [message ...]", min = 1) + public void cmdStop(Server[] servers, @Optional @Switch('f') boolean force, @Optional("Stopping the server.") @Text String msg) throws CommandException + { + for (Server server : servers) + { + if (!server.getOnline()) continue; + if (server.stopServer(msg)) CMDLOGGER.info(String.format("Shutdown command send to %s", server.getName())); + else CMDLOGGER.warn(String.format("Server %s did not shutdown with a message.", server.getName())); + } + } + + @Command(aliases = "start", desc = "Start one or more servers", usage = "", min = 1) + public void cmdStart(Server[] servers, @Optional @Switch('f') boolean force, @Optional("Stopping the server.") @Text String msg) throws CommandException + { + for (Server server : servers) + { + if (server.getOnline()) continue; + try + { + server.startServer(); + } + catch (Exception e) + { + CMDLOGGER.warn("Not able to start server " + server.getName()); + CMDLOGGER.warn(e); + } + } + } + + @Command(aliases = "version", desc = "Get current version and latest version available.", usage = "", min = 0, max = 0) + public void cmdVersion() throws CommandException + { + CMDLOGGER.info("Current version: {}. Build: {}", Main.version, Main.build); + CMDLOGGER.info("Latest version available: {}", Cache.getUpdateVersion()); + } + + @Command(aliases = {"shutdown", "exit"}, usage = "", desc = "Stop the backend", max = 0, flags = "f") + public void cmdShutdown(@Optional @Switch('f') boolean force) throws CommandException + { + if (force) System.exit(0); + Main.shutdown(); } } diff --git a/src/main/java/net/doubledoordev/backend/commands/Commands.java b/src/main/java/net/doubledoordev/backend/commands/Commands.java deleted file mode 100644 index b17c4c1..0000000 --- a/src/main/java/net/doubledoordev/backend/commands/Commands.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Unless otherwise specified through the '@author' tag or comments at - * the top of the file or on a specific portion of the code the following license applies: - * - * Copyright (c) 2014, DoubleDoorDevelopment - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * The header specified or the above copyright notice, this list of conditions - * and the following disclaimer below must be displayed at the top of the source code - * of any web page received while using any part of the service this software provides. - * - * The header to be displayed: - * This page was generated by DoubleDoorDevelopment's D3Backend or a derivative thereof. - * - * Neither the name of the project nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.doubledoordev.backend.commands; - -import com.sk89q.intake.Command; -import com.sk89q.intake.CommandException; -import com.sk89q.intake.CommandMapping; -import com.sk89q.intake.dispatcher.Dispatcher; -import com.sk89q.intake.parametric.annotation.Optional; -import com.sk89q.intake.parametric.annotation.Switch; -import com.sk89q.intake.parametric.annotation.Text; -import net.doubledoordev.backend.server.Server; -import net.doubledoordev.backend.server.WorldManager; - -import static net.doubledoordev.backend.commands.CommandHandler.CMDLOGGER; -import static net.doubledoordev.backend.util.Constants.JOINER_COMMA_SPACE; -import static net.doubledoordev.backend.util.Settings.SETTINGS; - -/** - * @author Dries007 - */ -public class Commands -{ - private final Dispatcher dispatcher; - - public Commands(CommandHandler commandHandler) - { - this.dispatcher = commandHandler.dispatcher; - } - - @Command(aliases = {"help", "?"}, desc = "Get a list of commands", help = "Use this to get help", usage = "[Command]", max = 1) - public void cmdHelp(@Optional String command) throws CommandException - { - // Command list - if (command == null) - { - CMDLOGGER.info("--==## Command list ##==--"); - for (CommandMapping cmd : dispatcher.getCommands()) - { - CMDLOGGER.info(cmd.getPrimaryAlias() + ' ' + cmd.getDescription().getUsage() + " => " + cmd.getDescription().getShortDescription()); // Looks like this: Name ListOfParameters => Description - } - } - else - { - CommandMapping cmd = dispatcher.get(command); - - if (cmd == null) throw new CommandNotFoundException(command); - - CMDLOGGER.info(String.format("--==## Help for %s ##==--", command)); - CMDLOGGER.info(String.format("Name: %s \t Aliases: %s", cmd.getPrimaryAlias(), JOINER_COMMA_SPACE.join(cmd.getAllAliases()))); - CMDLOGGER.info(String.format("Usage: %s %s", cmd.getPrimaryAlias(), cmd.getDescription().getUsage())); - CMDLOGGER.info(String.format("Short description: %s", cmd.getDescription().getShortDescription())); - CMDLOGGER.info(String.format("Help text: %s", cmd.getDescription().getHelp())); - } - } - - @Command(aliases = {"serverlist", "servers"}, desc = "List all servers", max = 0) - public void cmdServerList() - { - CMDLOGGER.info("All servers:"); - CMDLOGGER.info(JOINER_COMMA_SPACE.join(SETTINGS.getServers())); - CMDLOGGER.info("Online servers:"); - CMDLOGGER.info(JOINER_COMMA_SPACE.join(SETTINGS.getOnlineServers())); - } - - @Command(aliases = "message", desc = "Send message to servers (with /say)", usage = " ", min = 2) - public void cmdMessage(Server[] servers, @Text String msg) throws CommandException - { - for (Server server : servers) - { - if (!server.getOnline()) continue; - server.send(String.format("/say %s", msg)); - } - } - - @Command(aliases = "backup", desc = "Make full backup of one or more servers", usage = "", min = 1, max = 1) - public void cmdBackup(Server[] servers) throws CommandException - { - for (Server server : servers) - { - try - { - server.getWorldManager().bypassLimits = true; - server.getWorldManager().makeAllOfTheBackup(); - } - catch (WorldManager.BackupException e) - { - CMDLOGGER.warn("Error when making a backup of " + server.getName()); - CMDLOGGER.warn(e); - } - } - } - - @Command(aliases = "stop", desc = "Stop one or more servers", usage = " [-f (force the stop)] [message ...]", min = 1) - public void cmdStop(Server[] servers, @Optional @Switch('f') boolean force, @Optional("Stopping the server.") @Text String msg) throws CommandException - { - for (Server server : servers) - { - if (!server.getOnline()) continue; - if (server.stopServer(msg)) CMDLOGGER.info(String.format("Shutdown command send to %s", server.getName())); - else CMDLOGGER.warn(String.format("Server %s did not shutdown with a message.", server.getName())); - } - } - - @Command(aliases = "start", desc = "Start one or more servers", usage = "", min = 1) - public void cmdStart(Server[] servers, @Optional @Switch('f') boolean force, @Optional("Stopping the server.") @Text String msg) throws CommandException - { - for (Server server : servers) - { - if (server.getOnline()) continue; - try - { - server.startServer(); - } - catch (Exception e) - { - CMDLOGGER.warn("Not able to start server " + server.getName()); - CMDLOGGER.warn(e); - } - } - } -} diff --git a/src/main/java/net/doubledoordev/backend/server/Server.java b/src/main/java/net/doubledoordev/backend/server/Server.java index 2874af9..0a8a344 100644 --- a/src/main/java/net/doubledoordev/backend/server/Server.java +++ b/src/main/java/net/doubledoordev/backend/server/Server.java @@ -162,18 +162,6 @@ public void run() }).start(); } - // Handle autostart - if (!getOnline() && getAutoStart()) - { - try - { - startServer(); - } - catch (Exception ignored) - { - } - } - if (isNewServer) { try diff --git a/src/main/java/net/doubledoordev/backend/util/Cache.java b/src/main/java/net/doubledoordev/backend/util/Cache.java index c5b0193..2a91e9d 100644 --- a/src/main/java/net/doubledoordev/backend/util/Cache.java +++ b/src/main/java/net/doubledoordev/backend/util/Cache.java @@ -91,6 +91,8 @@ public void run() JsonObject latest = versionList.getAsJsonObject("promos"); HashSet buildsWithoutInstaller = new HashSet<>(); + if (!Main.running) return; + { LinkedList list = new LinkedList<>(); for (Map.Entry element : latest.entrySet()) @@ -140,6 +142,8 @@ public void run() // timeout or something like that } } + + if (!Main.running) return; } Main.LOGGER.debug("[Cache] Excluded FORGE versions: " + buildsWithoutInstaller.toString()); @@ -303,8 +307,6 @@ public static String getUpdateVersion() return updatedVersion; } - // TODO: update checker - public static void init() { if (instance != null) return;