package net.ME1312.SubServers.Host; import net.ME1312.Galaxi.Command.Command; import net.ME1312.Galaxi.Command.CommandProcessor.Status; import net.ME1312.Galaxi.Command.CommandSender; import net.ME1312.Galaxi.Command.CompletionHandler; import net.ME1312.Galaxi.Engine.CommandParser; import net.ME1312.Galaxi.Engine.GalaxiEngine; import net.ME1312.Galaxi.Library.Container.Container; import net.ME1312.Galaxi.Library.Container.Pair; import net.ME1312.Galaxi.Library.Container.Value; import net.ME1312.Galaxi.Library.Map.ObjectMap; import net.ME1312.Galaxi.Library.Merger; import net.ME1312.Galaxi.Library.Try; import net.ME1312.Galaxi.Library.Version.Version; import net.ME1312.SubData.Client.SubDataClient; import net.ME1312.SubServers.Client.Common.Network.API.*; import net.ME1312.SubServers.Client.Common.Network.Packet.PacketCreateServer; import net.ME1312.SubServers.Client.Common.Network.Packet.PacketUpdateServer; import net.ME1312.SubServers.Host.Library.TextColor; import net.ME1312.SubServers.Host.Network.Packet.PacketInExRunEvent; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Supplier; /** * Command Class */ public class SubCommand { private static Map proxyCache = Collections.emptyMap(); private static Map hostCache = Collections.emptyMap(); private static Map> groupCache = Collections.emptyMap(); private static Map serverCache = Collections.emptyMap(); private static Proxy proxyMasterCache = null; private static long cacheDate = 0; private final ExHost host; private static boolean canRun() { if (SubAPI.getInstance().getSubDataNetwork()[0] == null || SubAPI.getInstance().getSubDataNetwork()[0].isClosed()) { throw new IllegalStateException("SubData is not connected"); } else { return true; } } SubCommand(ExHost host) { this.host = host; } void load() { CompletionHandler defaultCompletor; new Command(host.info) { @Override public void command(CommandSender sender, String label, String[] rargs) { if (rargs.length > 0) { LinkedList args = new LinkedList(Arrays.asList(rargs)); args.removeFirst(); CommandParser console = GalaxiEngine.getInstance().getCommandProcessor(); String command = console.escapeCommand(rargs[0], args.toArray(new String[0])); if (console.runCommand(sender, command) == Status.UNKNOWN) { sender.sendMessage("Unknown Command: " + command); } } else { sender.sendMessage("Usage: /" + label + " [Args...]"); } } }.autocomplete((sender, label, rargs) -> { LinkedList args = new LinkedList(Arrays.asList(rargs)); args.removeFirst(); CommandParser console = GalaxiEngine.getInstance().getCommandProcessor(); return console.complete(sender, console.escapeCommand(rargs[0], args.toArray(new String[0]))).toArray(new String[0]); }).usage("", "[Args...]").description("An alias for commands").help( "This command is an alias for all registered commands for ease of use.", "", "Examples:", " /sub help -> /help", " /sub version ExamplePlugin -> /version ExamplePlugin" ).register("sub", "subserver", "subservers"); new Command(host.info) { @Override public void command(CommandSender sender, String label, String[] args) { if (canRun()) host.api.getGroups(groups -> host.api.getHosts(hosts -> host.api.getServers(servers -> host.api.getMasterProxy(proxymaster -> host.api.getProxies(proxies -> { int i = 0; boolean sent = false; String div = TextColor.RESET + ", "; if (groups.keySet().size() > 0) { sender.sendMessage("Group/Server List:"); for (String group : groups.keySet()) { String message = " "; message += TextColor.GOLD + group + TextColor.RESET + ": "; for (Server server : groups.get(group)) { if (i != 0) message += div; if (!(server instanceof SubServer)) { message += TextColor.WHITE; } else if (((SubServer) server).isRunning()) { if (((SubServer) server).getStopAction() == SubServer.StopAction.REMOVE_SERVER || ((SubServer) server).getStopAction() == SubServer.StopAction.RECYCLE_SERVER || ((SubServer) server).getStopAction() == SubServer.StopAction.DELETE_SERVER) { message += TextColor.AQUA; } else { message += TextColor.GREEN; } } else if (((SubServer) server).isAvailable() && ((SubServer) server).isEnabled() && ((SubServer) server).getCurrentIncompatibilities().size() == 0) { message += TextColor.YELLOW; } else { message += TextColor.RED; } message += server.getDisplayName() + ((server.getName().equals(server.getDisplayName()))?"":" ["+server.getName()+']'); i++; } if (i == 0) message += TextColor.RESET + "(none)"; sender.sendMessage(message); i = 0; sent = true; } if (!sent) sender.sendMessage(TextColor.RESET + "(none)"); sent = false; } sender.sendMessage("Host/SubServer List:"); for (Host host : hosts.values()) { String message = " "; if (host.isAvailable() && host.isEnabled()) { message += TextColor.AQUA; } else { message += TextColor.RED; } message += host.getDisplayName() + " [" + ((host.getName().equals(host.getDisplayName()))?"":host.getName()+TextColor.stripColor(div)) + host.getAddress().getHostAddress() + "]" + TextColor.RESET + ": "; for (SubServer subserver : host.getSubServers().values()) { if (i != 0) message += div; if (subserver.isRunning()) { if (subserver.getStopAction() == SubServer.StopAction.REMOVE_SERVER || subserver.getStopAction() == SubServer.StopAction.RECYCLE_SERVER || subserver.getStopAction() == SubServer.StopAction.DELETE_SERVER) { message += TextColor.AQUA; } else { message += TextColor.GREEN; } } else if (subserver.isAvailable() && subserver.isEnabled() && subserver.getCurrentIncompatibilities().size() == 0) { message += TextColor.YELLOW; } else { message += TextColor.RED; } message += subserver.getDisplayName() + " [" + ((subserver.getName().equals(subserver.getDisplayName()))?"":subserver.getName()+TextColor.stripColor(div)) + subserver.getAddress().getPort() + "]"; i++; } if (i == 0) message += TextColor.RESET + "(none)"; sender.sendMessage(message); i = 0; sent = true; } if (!sent) sender.sendMessage(TextColor.RESET + "(none)"); sender.sendMessage("Server List:"); String message = " "; for (Server server : servers.values()) if (!(server instanceof SubServer)) { if (i != 0) message += div; message += TextColor.WHITE + server.getDisplayName() + " [" + ((server.getName().equals(server.getDisplayName()))?"":server.getName()+TextColor.stripColor(div)) + server.getAddress().getAddress().getHostAddress()+':'+server.getAddress().getPort() + "]"; i++; } if (i == 0) message += TextColor.RESET + "(none)"; sender.sendMessage(message); if (proxies.keySet().size() > 0) { sender.sendMessage("Proxy List:"); message = " (master)"; for (Proxy proxy : proxies.values()) { message += div; if (proxy.getSubData()[0] != null) { message += TextColor.AQUA; } else { message += TextColor.RED; } message += proxy.getDisplayName() + ((proxy.getName().equals(proxy.getDisplayName()))?"":" ["+proxy.getName()+']'); } sender.sendMessage(message); } }))))); } }.description("List all known SubServers objects").help( "Sends you information about all known objects within SubServers", "in a detailed, yet concise, list format. This includes objects like:", "Proxies, Hosts, Groups, Servers and Subservers; the relationships between them; and their statuses.", "", "Example:", " /list" ).register("list"); new Command(host.info) { @Override public void command(CommandSender sender, String label, String[] args) { if (canRun()) { if (args.length > 0) { String type = (args.length > 1)?args[0]:null; String name = args[(type != null)?1:0]; Runnable getPlayer = () -> host.api.getRemotePlayer(name, player -> { if (player != null) { sender.sendMessage("Info on player: " + TextColor.WHITE + player.getName()); if (player.getProxyName() != null) sender.sendMessage(" -> Proxy: " + TextColor.WHITE + player.getProxyName()); if (player.getServerName() != null) sender.sendMessage(" -> Server: " + TextColor.WHITE + player.getServerName()); if (player.getAddress() != null) sender.sendMessage(" -> Address: " + TextColor.WHITE + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort()); sender.sendMessage(" -> UUID: " + TextColor.AQUA + player.getUniqueId()); } else { if (type == null) { sender.sendMessage("There is no object with that name"); } else { sender.sendMessage("There is no player with that name"); } } }); Runnable getServer = () -> host.api.getServer(name, server -> { if (server != null) { sender.sendMessage("Info on " + ((server instanceof SubServer)?"sub":"") + "server: " + TextColor.WHITE + server.getDisplayName()); if (!server.getName().equals(server.getDisplayName())) sender.sendMessage(" -> System Name: " + TextColor.WHITE + server.getName()); if (server instanceof SubServer) { sender.sendMessage(" -> Available: " + ((((SubServer) server).isAvailable())?TextColor.GREEN+"yes":TextColor.RED+"no")); sender.sendMessage(" -> Enabled: " + ((((SubServer) server).isEnabled())?TextColor.GREEN+"yes":TextColor.RED+"no")); if (!((SubServer) server).isEditable()) sender.sendMessage(" -> Editable: " + TextColor.RED + "no"); sender.sendMessage(" -> Host: " + TextColor.WHITE + ((SubServer) server).getHost()); if (((SubServer) server).getTemplate() != null) sender.sendMessage(" -> Template: " + TextColor.WHITE + ((SubServer) server).getTemplate()); } if (server.getGroups().size() > 0) sender.sendMessage(" -> Group" + ((server.getGroups().size() > 1)?"s:":": " + TextColor.WHITE + server.getGroups().get(0))); if (server.getGroups().size() > 1) for (String group : server.getGroups()) sender.sendMessage(" - " + TextColor.WHITE + group); sender.sendMessage(" -> Address: " + TextColor.WHITE + server.getAddress().getAddress().getHostAddress()+':'+server.getAddress().getPort()); if (server instanceof SubServer) sender.sendMessage(" -> " + ((((SubServer) server).isOnline())?"Online":"Running") + ": " + ((((SubServer) server).isRunning())?TextColor.GREEN+"yes":TextColor.RED+"no")); if (!(server instanceof SubServer) || ((SubServer) server).isRunning()) { sender.sendMessage(" -> Connected: " + ((server.getSubData()[0] != null)?TextColor.GREEN+"yes"+((server.getSubData().length > 1)?TextColor.AQUA+" +"+(server.getSubData().length-1)+" subchannel"+((server.getSubData().length == 2)?"":"s"):""):TextColor.RED+"no")); sender.sendMessage(" -> Players: " + TextColor.AQUA + server.getRemotePlayers().size() + " online"); } sender.sendMessage(" -> MOTD: " + TextColor.WHITE + TextColor.stripColor(server.getMotd())); if (server instanceof SubServer) { if (((SubServer) server).getStopAction() != SubServer.StopAction.NONE) sender.sendMessage(" -> Stop Action: " + TextColor.WHITE + ((SubServer) server).getStopAction().toString()); if (((SubServer) server).isStopping()) sender.sendMessage(" -> Stopping: " + TextColor.GREEN+"yes"); } sender.sendMessage(" -> Signature: " + TextColor.AQUA + server.getSignature()); if (server instanceof SubServer) sender.sendMessage(" -> Logging: " + ((((SubServer) server).isLogging())?TextColor.GREEN+"yes":TextColor.RED+"no")); sender.sendMessage(" -> Restricted: " + ((server.isRestricted())?TextColor.GREEN+"yes":TextColor.RED+"no")); if (server instanceof SubServer && ((SubServer) server).getIncompatibilities().size() > 0) { List current = new ArrayList(); for (String other : ((SubServer) server).getCurrentIncompatibilities()) current.add(other.toLowerCase()); sender.sendMessage(" -> Incompatibilities:"); for (String other : ((SubServer) server).getIncompatibilities()) sender.sendMessage(" - " + ((current.contains(other.toLowerCase()))?TextColor.WHITE:TextColor.GRAY) + other); } sender.sendMessage(" -> Hidden: " + ((server.isHidden())?TextColor.GREEN+"yes":TextColor.RED+"no")); } else { if (type == null) { getPlayer.run(); } else { sender.sendMessage("There is no server with that name"); } } }); Runnable getGroup = () -> host.api.getGroup(name, group -> { if (group != null) { sender.sendMessage("Info on group: " + TextColor.WHITE + group.key()); sender.sendMessage(" -> Servers: " + ((group.value().size() <= 0)?TextColor.GRAY + "(none)":TextColor.AQUA.toString() + group.value().size())); for (Server server : group.value()) sender.sendMessage(" - " + TextColor.WHITE + server.getDisplayName() + ((server.getName().equals(server.getDisplayName()))?"":" ["+server.getName()+']')); } else { if (type == null) { getServer.run(); } else { sender.sendMessage("There is no group with that name"); } } }); Runnable getHost = () -> host.api.getHost(name, host -> { if (host != null) { sender.sendMessage("Info on host: " + TextColor.WHITE + host.getDisplayName()); if (!host.getName().equals(host.getDisplayName())) sender.sendMessage(" -> System Name: " + TextColor.WHITE + host.getName()); sender.sendMessage(" -> Available: " + ((host.isAvailable())?TextColor.GREEN+"yes":TextColor.RED+"no")); sender.sendMessage(" -> Enabled: " + ((host.isEnabled())?TextColor.GREEN+"yes":TextColor.RED+"no")); sender.sendMessage(" -> Address: " + TextColor.WHITE + host.getAddress().getHostAddress()); if (host.getSubData().length > 0) sender.sendMessage(" -> Connected: " + ((host.getSubData()[0] != null)?TextColor.GREEN+"yes"+((host.getSubData().length > 1)?TextColor.AQUA+" +"+(host.getSubData().length-1)+" subchannel"+((host.getSubData().length == 2)?"":"s"):""):TextColor.RED+"no")); sender.sendMessage(" -> SubServers: " + ((host.getSubServers().keySet().size() <= 0)?TextColor.GRAY + "(none)":TextColor.AQUA.toString() + host.getSubServers().keySet().size())); for (SubServer subserver : host.getSubServers().values()) sender.sendMessage(" - " + ((subserver.isEnabled())?TextColor.WHITE:TextColor.GRAY) + subserver.getDisplayName() + ((subserver.getName().equals(subserver.getDisplayName()))?"":" ["+subserver.getName()+']')); sender.sendMessage(" -> Templates: " + ((host.getCreator().getTemplates().keySet().size() <= 0)?TextColor.GRAY + "(none)":TextColor.AQUA.toString() + host.getCreator().getTemplates().keySet().size())); for (SubCreator.ServerTemplate template : host.getCreator().getTemplates().values()) sender.sendMessage(" - " + ((template.isEnabled())?TextColor.WHITE:TextColor.GRAY) + template.getDisplayName() + ((template.getName().equals(template.getDisplayName()))?"":" ["+template.getName()+']')); sender.sendMessage(" -> Signature: " + TextColor.AQUA + host.getSignature()); } else { if (type == null) { getGroup.run(); } else { sender.sendMessage("There is no host with that name"); } } }); Runnable getProxy = () -> host.api.getProxy(name, proxy -> { if (proxy != null) { sender.sendMessage("Info on proxy: " + TextColor.WHITE + proxy.getDisplayName()); if (!proxy.getName().equals(proxy.getDisplayName())) sender.sendMessage(" -> System Name: " + TextColor.WHITE + proxy.getName()); if (!proxy.isMaster()) sender.sendMessage(" -> Connected: " + ((proxy.getSubData()[0] != null)?TextColor.GREEN+"yes"+((proxy.getSubData().length > 1)?TextColor.AQUA+" +"+(proxy.getSubData().length-1)+" subchannel"+((proxy.getSubData().length == 2)?"":"s"):""):TextColor.RED+"no")); else if (!proxy.getDisplayName().toLowerCase().contains("master")) sender.sendMessage(" -> Type: " + TextColor.WHITE + "Master"); sender.sendMessage(" -> Players: " + TextColor.AQUA + proxy.getPlayers().size() + " online"); sender.sendMessage(" -> Signature: " + TextColor.AQUA + proxy.getSignature()); } else { if (type == null) { getHost.run(); } else { sender.sendMessage("There is no proxy with that name"); } } }); if (type == null) { getProxy.run(); } else { switch (type.toLowerCase()) { case "p": case "proxy": getProxy.run(); break; case "h": case "host": getHost.run(); break; case "g": case "group": getGroup.run(); break; case "s": case "server": case "subserver": getServer.run(); break; case "u": case "user": case "player": getPlayer.run(); break; default: sender.sendMessage("There is no object type with that name"); } } } else { sender.sendMessage("Usage: /" + label + " [proxy|host|group|server|player] "); } } } }.autocomplete((sender, label, args) -> { String Last = (args.length > 0)?args[args.length - 1]:""; String last = Last.toLowerCase(); Supplier> getPlayers = () -> { LinkedList names = new LinkedList(); if (proxyMasterCache != null) for (Pair player : proxyMasterCache.getPlayers()) names.add(player.key()); for (Proxy proxy : proxyCache.values()) for (Pair player : proxy.getPlayers()) if (!names.contains(player.key())) names.add(player.key()); Collections.sort(names); return names; }; updateCache(); if (args.length == 1) { List list = new ArrayList(); List subcommands = new ArrayList(); subcommands.add("proxy"); subcommands.add("host"); subcommands.add("group"); subcommands.add("server"); subcommands.add("subserver"); subcommands.add("player"); for (String command : subcommands) { if (!list.contains(command) && command.toLowerCase().startsWith(last)) list.add(Last + command.substring(last.length())); } Proxy master = proxyMasterCache; if (master != null && !list.contains(master.getName()) && master.getName().toLowerCase().startsWith(last)) list.add(Last + master.getName().substring(last.length())); for (Proxy proxy : proxyCache.values()) { if (!list.contains(proxy.getName()) && proxy.getName().toLowerCase().startsWith(last)) list.add(Last + proxy.getName().substring(last.length())); } for (Host h : hostCache.values()) { if (!list.contains(h.getName()) && h.getName().toLowerCase().startsWith(last)) list.add(Last + h.getName().substring(last.length())); } for (String group : groupCache.keySet()) { if (!list.contains(group) && group.toLowerCase().startsWith(last)) list.add(Last + group.substring(last.length())); } for (Server server : serverCache.values()) { if (!list.contains(server.getName()) && server.getName().toLowerCase().startsWith(last)) list.add(Last + server.getName().substring(last.length())); } for (String player : getPlayers.get()) { if (!list.contains(player) && player.toLowerCase().startsWith(last)) list.add(Last + player.substring(last.length())); } return list.toArray(new String[0]); } else if (args.length == 2) { List list = new ArrayList(); switch (args[0].toLowerCase()) { case "p": case "proxy": Proxy master = proxyMasterCache; if (master != null && master.getName().toLowerCase().startsWith(last)) list.add(Last + master.getName().substring(last.length())); for (Proxy proxy : proxyCache.values()) { if (!list.contains(proxy.getName()) && proxy.getName().toLowerCase().startsWith(last)) list.add(Last + proxy.getName().substring(last.length())); } break; case "h": case "host": for (Host h : hostCache.values()) { if (h.getName().toLowerCase().startsWith(last)) list.add(Last + h.getName().substring(last.length())); } break; case "g": case "group": for (String group : groupCache.keySet()) { if (group.toLowerCase().startsWith(last)) list.add(Last + group.substring(last.length())); } break; case "s": case "server": case "subserver": for (Server server : serverCache.values()) { if ((!args[0].equalsIgnoreCase("subserver") || server instanceof SubServer) && server.getName().toLowerCase().startsWith(last)) list.add(Last + server.getName().substring(last.length())); } break; case "u": case "user": case "player": for (String player : getPlayers.get()) { if (player.toLowerCase().startsWith(last)) list.add(Last + player.substring(last.length())); } break; } return list.toArray(new String[0]); } else return new String[0]; }).usage("[proxy|host|group|server|player]", "").description("Gets information about a SubServers object").help( "Sends you all relevant information about a specific object within SubServers.", "This command can be really useful in troubleshooting. If you need a more in-depth look", "at an object than /sub list can give you, this is how you get it.", "", "If, for whatever reason, you have objects that share the same name,", "you can specify the type of object you are looking for as well.", "Specifying a type also makes the command faster since it doesn't have to search all object types.", "", "Examples:", " /info Server1", " /info server Server1" ).register("info", "status"); new Command(host.info) { @Override public void command(CommandSender sender, String label, String[] args) { if (canRun()) { if (args.length > 0) { selectServers(sender, args, 0, true, select -> { if (select.subservers.length > 0) { Container success = new Container(0); Container running = new Container(0); Merger merge = new Merger(() -> { if (running.value > 0) sender.sendMessage(running.value + " subserver"+((running.value == 1)?" was":"s were") + " already running"); if (success.value > 0) sender.sendMessage("Started " + success.value + " subserver"+((success.value == 1)?"":"s")); }); for (SubServer server : select.subservers) { merge.reserve(); server.start(null, response -> { switch (response) { case 3: case 4: sender.sendMessage("Subserver " + server.getName() + " has disappeared"); break; case 5: sender.sendMessage("The host for " + server.getName() + " is not available"); break; case 6: sender.sendMessage("The host for " + server.getName() + " is not enabled"); break; case 7: sender.sendMessage("Subserver " + server.getName() + " is not available"); break; case 8: sender.sendMessage("SubServer " + server.getName() + " is not enabled"); break; case 9: running.value++; break; case 10: sender.sendMessage("Subserver " + server.getName() + " cannot start while incompatible server(s) are running"); break; case 0: success.value++; break; } merge.release(); }); } } }); } else { sender.sendMessage("Usage: /" + label + " "); } } } }.autocomplete(defaultCompletor = new ServerCompletion(0, true, (sender, label, args, select) -> new String[0]) ).usage("").description("Starts one or more subservers").help( "Starts one or more subservers on the network.", "", "Example:", " /start Server1" ).register("start"); new Command(host.info) { @Override public void command(CommandSender sender, String label, String[] args) { if (canRun()) { if (args.length > 0) { selectServers(sender, args, 0, true, select -> { if (select.subservers.length > 0) { // Step 5: Start the stopped Servers once more Consumer starter = server -> server.start(response -> { switch (response) { case 3: case 4: sender.sendMessage("Could not restart server: Subserver " + server.getName() + " has disappeared"); break; case 5: sender.sendMessage("Could not restart server: The host for " + server.getName() + " is no longer available"); break; case 6: sender.sendMessage("Could not restart server: The host for " + server.getName() + " is no longer enabled"); break; case 7: sender.sendMessage("Could not restart server: Subserver " + server.getName() + " is no longer available"); break; case 8: sender.sendMessage("Could not restart server: Subserver " + server.getName() + " is no longer enabled"); break; case 10: sender.sendMessage("Could not restart server: Subserver " + server.getName() + " cannot start while incompatible server(s) are running"); break; case 9: case 0: // success! break; } }); // Step 4: Listen for stopped Servers final HashMap listening = new HashMap(); PacketInExRunEvent.callback("SubStoppedEvent", new Consumer>() { @Override public void accept(ObjectMap json) { try { if (listening.size() > 0) { PacketInExRunEvent.callback("SubStoppedEvent", this); String name = json.getString("server").toLowerCase(); if (listening.containsKey(name)) { Timer timer = new Timer("SubServers.Host::Server_Restart_Command_Handler(" + name + ")"); timer.schedule(new TimerTask() { @Override public void run() { starter.accept(listening.get(name)); listening.remove(name); timer.cancel(); } }, 100); } } } catch (Exception e) {} } }); // Step 1-3: Restart Servers / Receive command Responses Container success = new Container(0); Merger merge = new Merger(() -> { if (success.value > 0) sender.sendMessage("Restarting " + success.value + " subserver"+((success.value == 1)?"":"s")); }); for (SubServer server : select.subservers) { merge.reserve(); listening.put(server.getName().toLowerCase(), server); server.stop(response -> { if (response != 0) listening.remove(server.getName().toLowerCase()); switch (response) { case 3: case 4: sender.sendMessage("Could not restart server: Subserver " + server.getName() + " has disappeared"); break; case 5: starter.accept(server); case 0: success.value++; break; } merge.release(); }); } } }); } else { sender.sendMessage("Usage: /" + label + " "); } } } }.autocomplete(defaultCompletor).usage("").description("Starts or restarts one or more subservers").help( "Starts or restarts one or more subservers on the network.", "", "Example:", " /restart Server1" ).register("restart"); new Command(host.info) { @Override public void command(CommandSender sender, String handle, String[] args) { if (canRun()) { if (args.length > 0) { selectServers(sender, args, 0, true, select -> { if (select.subservers.length > 0) { Container success = new Container(0); Container running = new Container(0); Merger merge = new Merger(() -> { if (running.value > 0) sender.sendMessage(running.value + " subserver"+((running.value == 1)?" was":"s were") + " already offline"); if (success.value > 0) sender.sendMessage("Stopping " + success.value + " subserver"+((success.value == 1)?"":"s")); }); for (SubServer server : select.subservers) { merge.reserve(); server.stop(response -> { switch (response) { case 3: case 4: sender.sendMessage("Subserver " + server.getName() + " has disappeared"); break; case 5: running.value++; break; case 0: success.value++; break; } merge.release(); }); } } }); } else { sender.sendMessage("Usage: /" + handle + " "); } } } }.autocomplete(defaultCompletor).usage("").description("Stops one or more subservers").help( "Stops one or more subservers on the network.", "", "Example:", " /stop Server1" ).register("stop"); new Command(host.info) { @Override public void command(CommandSender sender, String handle, String[] args) { if (canRun()) { if (args.length > 0) { selectServers(sender, args, 0, true, select -> { if (select.subservers.length > 0) { Container success = new Container(0); Container running = new Container(0); Merger merge = new Merger(() -> { if (running.value > 0) sender.sendMessage(running.value + " subserver"+((running.value == 1)?" was":"s were") + " already offline"); if (success.value > 0) sender.sendMessage("Terminated " + success.value + " subserver"+((success.value == 1)?"":"s")); }); for (SubServer server : select.subservers) { merge.reserve(); server.terminate(response -> { switch (response) { case 3: case 4: sender.sendMessage("Subserver " + server.getName() + " has disappeared"); break; case 5: running.value++; break; case 0: success.value++; break; } merge.release(); }); } } }); } else { sender.sendMessage("Usage: /" + handle + " "); } } } }.autocomplete(defaultCompletor).usage("").description("Forcefully stops one or more subservers").help( "Forcefully stops one or more subservers on the network.", "", "Stopping subservers in this way can make you lose unsaved data though, so it", "is generally not recommended to use this command unless a server stops responding.", "", "Example:", " /terminate Server1" ).register("kill", "terminate"); new Command(host.info) { @Override public void command(CommandSender sender, String handle, String[] args) { if (canRun()) { if (args.length > 0) { selectServers(sender, args, 0, false, select -> { if (select.servers.length > 0) { if (select.args.length > 1) { StringBuilder builder = new StringBuilder(select.args[1]); for (int i = 2; i < select.args.length; i++) { builder.append(' '); builder.append(select.args[i]); } Container success = new Container(0); Container running = new Container(0); Merger merge = new Merger(() -> { if (running.value > 0) sender.sendMessage(running.value + " server"+((running.value == 1)?" was":"s were") + " offline"); if (success.value > 0) sender.sendMessage("Sent command to " + success.value + " server"+((success.value == 1)?"":"s")); }); for (Server server : select.servers) { merge.reserve(); server.command(builder.toString(), response -> { switch (response) { case 3: case 4: sender.sendMessage("Server " + server.getName() + " has disappeared"); break; case 5: running.value++; break; case 0: success.value++; break; } merge.release(); }); } } else { sender.sendMessage("No command was entered"); } } }); } else { sender.sendMessage("Usage: /" + handle + " [Args...]"); } } } }.autocomplete(new ServerCompletion(0, false, ((sender, label, args, select) -> new String[0]))).usage("", "", "[Args...]").description("Sends a command to the console of one or more servers").help( "Sends a command to the console of one or more servers on the network.", "", "Examples:", " /command Server1 version", " /command Server1 op Notch", " /command Server1 say Hello World!" ).register("cmd", "command"); new Command(host.info) { @Override public void command(CommandSender sender, String handle, String[] args) { if (canRun()) { if (args.length > 2) { if (args.length > 4 && !Try.all.run(() -> Integer.parseInt(args[4]))) { sender.sendMessage("Invalid port number"); } else { ((SubDataClient) SubAPI.getInstance().getSubDataNetwork()[0]).sendPacket(new PacketCreateServer(null, args[0], args[1], args[2], (args.length > 3)?new Version(args[3]):null, (args.length > 4)?Integer.parseInt(args[4]):null, data -> { switch (data.getInt(0x0001)) { case 3: sender.sendMessage("Server names cannot include spaces"); break; case 4: sender.sendMessage("There is already a subserver with that name"); break; case 5: sender.sendMessage("There is no host with that name"); break; case 6: sender.sendMessage("That host is not available"); break; case 7: sender.sendMessage("That host is not enabled"); break; case 8: sender.sendMessage("There is no template with that name"); break; case 9: sender.sendMessage("That template is not enabled"); break; case 10: sender.sendMessage("That template requires a Minecraft version to be specified"); break; case 11: sender.sendMessage("Invalid port number"); break; case 0: sender.sendMessage("Creating subserver " + args[0]); break; } })); } } else { sender.sendMessage("Usage: /" + handle + "