diff --git a/launcher/src/se/llbit/chunky/launcher/ChunkyLauncher.java b/launcher/src/se/llbit/chunky/launcher/ChunkyLauncher.java index 8d0f4cbf3..f217c083a 100644 --- a/launcher/src/se/llbit/chunky/launcher/ChunkyLauncher.java +++ b/launcher/src/se/llbit/chunky/launcher/ChunkyLauncher.java @@ -32,6 +32,7 @@ import java.net.*; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; +import java.util.List; import java.util.Scanner; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; @@ -89,15 +90,30 @@ public static Options cliOptionsPublic() { options.addOption(Option.builder() .longOpt("update") + .desc("Update Chunky to the latest release") + .build() + ); + + options.addOption(Option.builder() + .longOpt("releaseChannel") .argName("release channel") .optionalArg(true) - .desc("Update Chunky to the latest release") + .desc("Specify the release channel (for use with --update and --chunkyVersion latest)") + .build() + ); + + options.addOption(Option.builder() + .longOpt("updateSite") + .argName("update site") + .desc("Update site to use for updating") .build() ); options.addOption(Option.builder() - .longOpt("setup") - .desc("Runs the interactive command-line launcher setup") + .longOpt("chunkyVersion") + .argName("chunky version") + .numberOfArgs(1) + .desc("Chunky version to launch (latest for the latest installed version of the specified release channel)") .build() ); @@ -168,7 +184,10 @@ public static void main(String[] args) throws FileNotFoundException { CommandLine cmd = parseCli(args); if (cmd.hasOption("help")) { - String header = CliUtil.makeHelpHeader("Chunky Launcher", LAUNCHER_VERSION.toString(), ""); + String header = CliUtil.makeHelpHeader("Chunky Launcher", LAUNCHER_VERSION.toString(), "Commands:\n" + + " setup Runs the interactive command-line launcher setup\n" + + " update Download the latest version\n" + + " (none) Launch the latest version\n\nOptions:"); String footer = "\n" + "Command line options after -- are passed to Chunky.\n" + "For Chunky's command line help, run:\n" + @@ -176,7 +195,7 @@ public static void main(String[] args) throws FileNotFoundException { HelpFormatter help = new HelpFormatter(); help.setWidth(CliUtil.CLI_WIDTH); - help.printHelp("java -jar ChunkyLauncher.jar", header, cliOptionsPublic(), footer); + help.printHelp("java -jar ChunkyLauncher.jar [command] ", header, cliOptionsPublic(), footer); return; } @@ -197,19 +216,27 @@ public static void main(String[] args) throws FileNotFoundException { settings.forceGuiConsole = true; } - if (cmd.hasOption("update")) { - ReleaseChannel channel = settings.selectedChannel; + if (cmd.hasOption("updateSite")) { + settings.updateSite = cmd.getOptionValue("updateSite"); + reloadReleaseChannels(settings); + return; + } - String selected = cmd.getOptionValue("update"); + if (cmd.hasOption("releaseChannel")) { + String selected = cmd.getOptionValue("releaseChannel"); if (selected != null) { - channel = settings.releaseChannels.getOrDefault(selected, channel); + settings.selectedChannel = settings.releaseChannels.getOrDefault(selected, settings.selectedChannel); } + } - headlessUpdateChunky(settings, channel); - return; + if (cmd.hasOption("update") || args[0].equals("update")) { + headlessUpdateChunky(settings, settings.selectedChannel); + if (args[0].equals("update")) { + return; + } } - if (cmd.hasOption("setup")) { + if (args[0].equals("setup")) { doSetup(settings); settings.save(); return; @@ -245,6 +272,14 @@ public static void main(String[] args) throws FileNotFoundException { LauncherSettings.disableLibraryValidation = true; } + if (cmd.hasOption("chunkyVersion")) { + settings.version = cmd.getOptionValue("chunkyVersion"); + if ("latest".equals(cmd.getOptionValue("chunkyVersion"))) { + List versions = new UpdateChecker(settings, settings.selectedChannel).getVersions(); + settings.version = versions.stream().findAny().map(version -> version.name).orElse(settings.version); + } + } + headlessOptions = String.join(" ", cmd.getArgList()); if (forceLauncher) { @@ -330,7 +365,7 @@ public static void main(String[] args) throws FileNotFoundException { } e.printStackTrace(System.err); } catch (ParseException e) { - System.out.println(e.getMessage()); + System.out.println(e.getMessage()); } } diff --git a/launcher/src/se/llbit/chunky/launcher/UpdateChecker.java b/launcher/src/se/llbit/chunky/launcher/UpdateChecker.java index e6584aa6f..fa6d9f81f 100644 --- a/launcher/src/se/llbit/chunky/launcher/UpdateChecker.java +++ b/launcher/src/se/llbit/chunky/launcher/UpdateChecker.java @@ -17,18 +17,19 @@ */ package se.llbit.chunky.launcher; +import se.llbit.json.JsonParser; +import se.llbit.json.JsonParser.SyntaxError; + import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import se.llbit.json.JsonParser; -import se.llbit.json.JsonParser.SyntaxError; - /** * Check for update and run update dialog (or just update in headless mode). * @@ -37,12 +38,31 @@ public class UpdateChecker extends Thread { private final LauncherSettings settings; private final UpdateListener listener; - private final String path; + private final ReleaseChannel channel; public UpdateChecker(LauncherSettings settings, ReleaseChannel channel, UpdateListener listener) { this.settings = settings; this.listener = listener; - this.path = channel.path; + this.channel = channel; + } + + public UpdateChecker(LauncherSettings settings, ReleaseChannel channel) { + this(settings, channel, new UpdateListener() { + @Override + public void updateError(String message) { + // ignore + } + + @Override + public void updateAvailable(VersionInfo latest) { + // ignore + } + + @Override + public void noUpdateAvailable() { + // ignore + } + }); } @Override @@ -58,9 +78,7 @@ public void run() { } private boolean tryUpdate() { - List candidates = new LinkedList<>(); - - getVersion(candidates, settings.getResourceUrl(path)); + List candidates = getVersions(); // Filter out corrupt versions. Iterator iter = candidates.iterator(); @@ -98,6 +116,12 @@ private boolean tryUpdate() { return true; } + public List getVersions() { + List candidates = new LinkedList<>(); + getVersion(candidates, settings.getResourceUrl(channel.path)); + return Collections.unmodifiableList(candidates); + } + private void getVersion(List candidates, String url) { try { URL latestJson = new URL(url); diff --git a/lib/src/se/llbit/chunky/HelpCopyright.java b/lib/src/se/llbit/chunky/HelpCopyright.java index 2dd70a6e7..154a87b05 100644 --- a/lib/src/se/llbit/chunky/HelpCopyright.java +++ b/lib/src/se/llbit/chunky/HelpCopyright.java @@ -22,7 +22,7 @@ * This contains the proper copyright information for various messages */ public class HelpCopyright { - public static final String COPYRIGHT_LINE = "Copyright (c) 2010-2024 Jesper Öqvist and Chunky Contributors"; + public static final String COPYRIGHT_LINE = "Copyright (c) 2010-2026 Jesper Öqvist and Chunky Contributors"; public static final String COPYRIGHT_DISCLAIMER = "Chunky comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it " +