From 45fa5b0dce06327b2d9ef2bb7190504926b53ff2 Mon Sep 17 00:00:00 2001 From: Sky Swimmer Date: Fri, 15 Mar 2024 20:31:53 +0100 Subject: [PATCH] Launcher improvements --- .../launcher/feraltweaks/LauncherMain.java | 186 ++++++++---- .../launcher/updater/LauncherUpdaterMain.java | 278 +++++++++++++----- 2 files changed, 336 insertions(+), 128 deletions(-) diff --git a/launcher/feraltweaks-launcher/src/main/java/org/asf/centuria/launcher/feraltweaks/LauncherMain.java b/launcher/feraltweaks-launcher/src/main/java/org/asf/centuria/launcher/feraltweaks/LauncherMain.java index 19b51d9..152efe6 100644 --- a/launcher/feraltweaks-launcher/src/main/java/org/asf/centuria/launcher/feraltweaks/LauncherMain.java +++ b/launcher/feraltweaks-launcher/src/main/java/org/asf/centuria/launcher/feraltweaks/LauncherMain.java @@ -53,6 +53,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; import java.util.Enumeration; import java.util.HashMap; @@ -230,6 +232,7 @@ public void mouseExited(MouseEvent e) { JsonObject client; JsonObject modloader; String manifest; + boolean useWineMethodOSX; try { // Read server info String url; @@ -243,6 +246,10 @@ public void mouseExited(MouseEvent e) { System.exit(1); return; } + ArrayList arguments = new ArrayList(Arrays.asList(args)); + arguments.remove(0); + arguments.remove(0); + args = arguments.toArray(t -> new String[t]); frmCenturiaLauncher.setTitle(srvName + " Launcher"); lblNewLabel_1.setText(srvName + " Launcher"); @@ -259,6 +266,7 @@ public void mouseExited(MouseEvent e) { ports = serverInfo.get("ports").getAsJsonObject(); client = launcher.get("client").getAsJsonObject(); JsonObject loader = launcher.get("modloader").getAsJsonObject(); + useWineMethodOSX = launcher.has("osxUseWineMethod") && launcher.get("osxUseWineMethod").getAsBoolean(); // Handle relative paths for banner if (!banner.startsWith("http://") && !banner.startsWith("https://")) { @@ -287,16 +295,29 @@ public void mouseExited(MouseEvent e) { } else if (System.getProperty("os.name").toLowerCase().contains("darwin") || System.getProperty("os.name").toLowerCase().contains("mac")) { // MacOS os = "osx"; - feralPlat = "osx"; - if (!loader.has(os)) { - JOptionPane.showMessageDialog(null, - "Unsupported platform!\nThe launcher cannot load on your device due to there being no modloader for your platform in the server configuration. Please wait until your device is supported.\n\nOS Name: " - + System.getProperty("os.name"), - "Launcher Error", JOptionPane.ERROR_MESSAGE); - System.exit(1); - return; + if (useWineMethodOSX) { + feralPlat = "win64"; + if (!loader.has("win64")) { + JOptionPane.showMessageDialog(null, + "Unsupported platform!\nThe launcher cannot load on your device due to there being no modloader for your platform in the server configuration. Please wait until your device is supported.\n\nOS Name: " + + System.getProperty("os.name"), + "Launcher Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + manifest = client.get("win64").getAsString(); + } else { + feralPlat = "osx"; + if (!loader.has(os)) { + JOptionPane.showMessageDialog(null, + "Unsupported platform!\nThe launcher cannot load on your device due to there being no modloader for your platform in the server configuration. Please wait until your device is supported.\n\nOS Name: " + + System.getProperty("os.name"), + "Launcher Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + manifest = client.get(os).getAsString(); } - manifest = client.get(os).getAsString(); } else if (System.getProperty("os.name").toLowerCase().contains("linux")) {// Linux os = "linux"; feralPlat = "win64"; @@ -324,7 +345,7 @@ public void mouseExited(MouseEvent e) { panel_1.setImage(img); } catch (Exception e) { JOptionPane.showMessageDialog(null, - "Could not connect with the launcher servers, please check your internet connection. If you are connected, please wait a few minutes and try again.\n\nIf the issue remains and you are connected to the internet, please submit a support ticket.", + "Could not connect with the launcher servers, please check your internet connection. If you are connected, please wait a few minutes and try again.\n\nIf the issue remains and you are connected to the internet, please contact support.", "Launcher Error", JOptionPane.ERROR_MESSAGE); System.exit(1); return; @@ -333,7 +354,6 @@ public void mouseExited(MouseEvent e) { Thread th = new Thread(() -> { // Set progress bar status try { - // Set label SwingUtilities.invokeAndWait(() -> { log("Preparing..."); @@ -441,8 +461,7 @@ public void mouseExited(MouseEvent e) { if (!api.endsWith("/")) api += "/"; String apiData = api + "data/"; - if (hosts.has("launcherDataSource")) - { + if (hosts.has("launcherDataSource")) { apiData = hosts.get("launcherDataSource").getAsString(); if (!apiData.endsWith("/")) apiData += "/"; @@ -478,9 +497,8 @@ public void mouseExited(MouseEvent e) { System.exit(1); return; } else if (resp.has("errorMessage")) { - JOptionPane.showMessageDialog(frmCenturiaLauncher, - resp.get("errorMessage").getAsString(), "Launcher Error", - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(frmCenturiaLauncher, resp.get("errorMessage").getAsString(), + "Launcher Error", JOptionPane.ERROR_MESSAGE); System.exit(1); return; } @@ -500,6 +518,41 @@ public void mouseExited(MouseEvent e) { String currentClient = ""; if (new File("clientversion.info").exists()) { currentClient = Files.readString(Path.of("clientversion.info")); + + // Verify method switch + if (!useWineMethodOSX) { + // Check if last time was wine method + if (new File("macosusewine").exists()) { + // Clean up + if (new File("client").exists()) + deleteDir(new File("client")); + if (new File("clientversion.info").exists()) + new File("clientversion.info").delete(); + if (new File("loaderversion.info").exists()) + new File("loaderversion.info").delete(); + if (new File("modversion.info").exists()) + new File("modversion.info").delete(); + if (new File("assetversion.info").exists()) + new File("assetversion.info").delete(); + new File("macosusewine").delete(); + } + } else if (os.equals("osx")) { + // Check if last time was non-wine method + if (!new File("macosusewine").exists()) { + // Clean up + if (new File("client").exists()) + deleteDir(new File("client")); + if (new File("clientversion.info").exists()) + new File("clientversion.info").delete(); + if (new File("loaderversion.info").exists()) + new File("loaderversion.info").delete(); + if (new File("modversion.info").exists()) + new File("modversion.info").delete(); + if (new File("assetversion.info").exists()) + new File("assetversion.info").delete(); + new File("macosusewine").createNewFile(); + } + } } // Download manifest @@ -682,7 +735,7 @@ public void mouseExited(MouseEvent e) { }); // OSX stuff - if (os.equals("osx")) { + if (feralPlat.equals("osx")) { resetAttrs = true; } } @@ -725,7 +778,7 @@ public void mouseExited(MouseEvent e) { Files.writeString(Path.of("loaderversion.info"), modloader.get("version").getAsString()); // OSX stuff - if (os.equals("osx")) { + if (feralPlat.equals("osx")) { resetAttrs = true; } @@ -793,8 +846,8 @@ public void mouseExited(MouseEvent e) { }); // Download manifest - updateMods("assets/index.json", apiData, modloader.get("assetBaseDir").getAsString(), hosts, authToken, - progressBar, panel_1); + updateMods("assets/index.json", apiData, modloader.get("assetBaseDir").getAsString(), hosts, + authToken, progressBar, panel_1); // Save version Files.writeString(Path.of("assetversion.info"), serverInfo.get("assetVersion").getAsString()); @@ -875,16 +928,37 @@ public void mouseExited(MouseEvent e) { } try { - // Check OS - if (os.equals("win64")) - builder = new ProcessBuilder(clientFile.getAbsolutePath(), "--launcher-handoff", - Integer.toString(port)); // Windows - else if (os.equals("osx")) { - builder = new ProcessBuilder("sh", clientFile.getAbsolutePath(), "--launcher-handoff", - Integer.toString(port)); // MacOS - } else if (os.equals("linux")) { - builder = new ProcessBuilder("wine", clientFile.getAbsolutePath(), "--launcher-handoff", - Integer.toString(port)); // Linux, need wine + // Build startup command + ArrayList arguments = new ArrayList(); + + // Start command + if (os.equals("win64")) { + // Windows + arguments.add(clientFile.getAbsolutePath()); + } else if (os.equals("osx") && !useWineMethodOSX) { + // MacOS + arguments.add("sh"); + arguments.add(clientFile.getAbsolutePath()); + } else if (os.equals("linux") || useWineMethodOSX) { + // Linux or wine-method-macos + arguments.add("wine"); + arguments.add(clientFile.getAbsolutePath()); + } + + // Handoff + arguments.add("--launcher-handoff"); + arguments.add(Integer.toString(port)); + + // User arguments + for (String arg : args) + arguments.add(arg); + + // Builder + builder = new ProcessBuilder(arguments.toArray(t -> new String[t])); + + // Wine + if (os.equals("linux") || (useWineMethodOSX && os.equals("osx"))) { + // Check prefix File prefix = new File("wineprefix"); if (!new File(prefix, "completed").exists()) { prefix.mkdirs(); @@ -944,7 +1018,9 @@ else if (os.equals("osx")) { panel_5.setVisible(true); panel_1.repaint(); }); - String man = downloadString("https://api.github.com/repos/doitsujin/dxvk/releases/latest"); + String man = downloadString(os.equalsIgnoreCase("linux") + ? "https://api.github.com/repos/doitsujin/dxvk/releases/latest" + : "https://api.github.com/repos/Gcenx/DXVK-macOS/releases/latest"); JsonArray assets = JsonParser.parseString(man).getAsJsonObject().get("assets") .getAsJsonArray(); String dxvk = null; @@ -1039,7 +1115,7 @@ else if (os.equals("osx")) { SwingUtilities.invokeAndWait(() -> { JOptionPane.showMessageDialog(frmCenturiaLauncher, "Client process exited before the launch was completed!\nExit code: " - + proc.exitValue() + "\n\nPlease open a support ticket!", + + proc.exitValue() + "\n\nPlease contact support!", "Launcher Error", JOptionPane.ERROR_MESSAGE); System.exit(proc.exitValue()); }); @@ -1066,8 +1142,8 @@ else if (os.equals("osx")) { progressBar.setValue(0); panel_1.repaint(); }); - launcherHandoff(cl, authTokenF, hosts.get("api").getAsString(), apiDataF, serverInfo, hosts, ports, - completedTutorial); + launcherHandoff(cl, authTokenF, hosts.get("api").getAsString(), apiDataF, serverInfo, hosts, + ports, completedTutorial); cl.close(); SwingUtilities.invokeAndWait(() -> { log("Finished startup!"); @@ -1136,8 +1212,8 @@ else if (os.equals("osx")) { th.start(); } - private void launcherHandoff(Socket cl, String authToken, String api, String apiData, JsonObject serverInfo, JsonObject hosts, - JsonObject ports, boolean completedTutorial) throws Exception { + private void launcherHandoff(Socket cl, String authToken, String api, String apiData, JsonObject serverInfo, + JsonObject hosts, JsonObject ports, boolean completedTutorial) throws Exception { if (!api.endsWith("/")) api += "/"; if (!apiData.endsWith("/")) @@ -1232,8 +1308,8 @@ private void deleteDir(File dir) { dir.delete(); } - private void updateMods(String pth, String apiData, String baseOut, JsonObject hosts, String authToken, JProgressBar progressBar, - JPanel panel_1) throws Exception { + private void updateMods(String pth, String apiData, String baseOut, JsonObject hosts, String authToken, + JProgressBar progressBar, JPanel panel_1) throws Exception { String api = hosts.get("api").getAsString(); if (!api.endsWith("/")) api += "/"; @@ -1250,27 +1326,25 @@ private void updateMods(String pth, String apiData, String baseOut, JsonObject h // Handle error String err = resp.get("error").getAsString(); switch (err) { - case "invalid_credential": { - throw new IOException("Credentials invalid"); - } - case "feraltweaks_not_enabled": { - JOptionPane.showMessageDialog(frmCenturiaLauncher, - "Client modding is not enabled on your account, unable to launch the game.", - "Launcher Error", - JOptionPane.ERROR_MESSAGE); + case "invalid_credential": { + throw new IOException("Credentials invalid"); + } + case "feraltweaks_not_enabled": { + JOptionPane.showMessageDialog(frmCenturiaLauncher, + "Client modding is not enabled on your account, unable to launch the game.", "Launcher Error", + JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + default: { + if (resp.has("errorMessage")) { + JOptionPane.showMessageDialog(frmCenturiaLauncher, resp.get("errorMessage").getAsString(), + "Launcher Error", JOptionPane.ERROR_MESSAGE); System.exit(1); return; } - default: { - if (resp.has("errorMessage")) { - JOptionPane.showMessageDialog(frmCenturiaLauncher, - resp.get("errorMessage").getAsString(), "Launcher Error", - JOptionPane.ERROR_MESSAGE); - System.exit(1); - return; - } - throw new Exception("Unknown server error: " + err); - } + throw new Exception("Unknown server error: " + err); + } } } diff --git a/launcher/launcher-updater/src/main/java/org/asf/centuria/launcher/updater/LauncherUpdaterMain.java b/launcher/launcher-updater/src/main/java/org/asf/centuria/launcher/updater/LauncherUpdaterMain.java index 9b93d16..3d9efb3 100644 --- a/launcher/launcher-updater/src/main/java/org/asf/centuria/launcher/updater/LauncherUpdaterMain.java +++ b/launcher/launcher-updater/src/main/java/org/asf/centuria/launcher/updater/LauncherUpdaterMain.java @@ -44,6 +44,9 @@ public class LauncherUpdaterMain { private static JFrame frmCenturiaLauncher; private static JLabel lblNewLabel; + private static BackgroundPanel panel_1; + + private static String[] args; /** * Launch the application. @@ -52,6 +55,7 @@ public class LauncherUpdaterMain { * @throws JsonSyntaxException */ public static void main(String[] args) throws JsonSyntaxException, IOException { + LauncherUpdaterMain.args = args; if (new File("installerdata").exists()) { installerMode = true; @@ -131,11 +135,11 @@ public static void main(String[] args) throws JsonSyntaxException, IOException { // Perform installer operation if needed if (operation != -1) { // Contact server - String launcherVersion; - String launcherDir; - String launcherURL; - String dataUrl; - String srvName; + String launcherVersion = null; + String launcherDir = null; + String launcherURL = null; + String dataUrl = null; + String srvName = null; File instDir; try { // Read server info @@ -148,6 +152,7 @@ public static void main(String[] args) throws JsonSyntaxException, IOException { dirName = conf.get("launcherDirName").getAsString(); url = conf.get("serverConfig").getAsString(); dataUrl = url; + launcherDir = dirName; } catch (Exception e) { JOptionPane.showMessageDialog(null, "Invalid " + (installerMode ? "installer" : "launcher") + " configuration.", @@ -164,12 +169,13 @@ public static void main(String[] args) throws JsonSyntaxException, IOException { JsonObject launcher = info.get("launcher").getAsJsonObject(); url = launcher.get("url").getAsString(); launcherVersion = launcher.get("version").getAsString(); - launcherDir = dirName; launcherURL = url; } catch (Exception e) { - System.err.println("Error: failed to contact launcher servers."); - System.exit(1); - return; + if (operation == 0) { + System.err.println("Error: failed to contact launcher servers."); + System.exit(1); + return; + } } // Build folder path @@ -219,7 +225,7 @@ public static void main(String[] args) throws JsonSyntaxException, IOException { installDirFile); } else if (operation == 1) { // Uninstall - uninstallLauncher(instDir, null, launcherVersion, srvName, launcherURL, dataUrl, launcherDir); + uninstallLauncher(instDir, null, srvName, launcherDir); } // Exit @@ -271,6 +277,10 @@ private void initialize() { strmi.close(); } catch (IOException e1) { } + try { + frmCenturiaLauncher.setIconImage(ImageIO.read(new File("icon.png"))); + } catch (IOException e1) { + } JPanel panel = new JPanel(); frmCenturiaLauncher.getContentPane().add(panel, BorderLayout.SOUTH); @@ -280,7 +290,7 @@ private void initialize() { progressBar.setPreferredSize(new Dimension(146, 10)); panel.add(progressBar, BorderLayout.NORTH); - BackgroundPanel panel_1 = new BackgroundPanel(); + panel_1 = new BackgroundPanel(); panel_1.setForeground(Color.WHITE); frmCenturiaLauncher.getContentPane().add(panel_1, BorderLayout.CENTER); panel_1.setLayout(new BorderLayout(0, 0)); @@ -289,23 +299,20 @@ private void initialize() { lblNewLabel.setPreferredSize(new Dimension(46, 20)); panel_1.add(lblNewLabel, BorderLayout.SOUTH); - // Contact server - String launcherVersion; - String launcherDir; - String launcherURL; - String dataUrl; - String srvName; - File instDir; try { // Read server info String dirName; String url; + String launcherDir; + String dataUrl; + String srvName; try { JsonObject conf = JsonParser.parseString(Files.readString(Path.of("server.json"))).getAsJsonObject(); srvName = conf.get("serverName").getAsString(); dirName = conf.get("launcherDirName").getAsString(); url = conf.get("serverConfig").getAsString(); dataUrl = url; + launcherDir = dirName; } catch (Exception e) { JOptionPane.showMessageDialog(null, "Invalid " + (installerMode ? "installer" : "launcher") + " configuration.", @@ -314,50 +321,8 @@ private void initialize() { return; } - // Download data - InputStream strm = new URL(url).openStream(); - String data = new String(strm.readAllBytes(), "UTF-8"); - strm.close(); - JsonObject info = JsonParser.parseString(data).getAsJsonObject(); - JsonObject launcher = info.get("launcher").getAsJsonObject(); - String splash = launcher.get("splash").getAsString(); - url = launcher.get("url").getAsString(); - String version = launcher.get("version").getAsString(); - - // Handle relative paths for banner - if (!splash.startsWith("http://") && !splash.startsWith("https://")) { - JsonObject serverInfo = info.get("server").getAsJsonObject(); - JsonObject hosts = serverInfo.get("hosts").getAsJsonObject(); - String api = hosts.get("api").getAsString(); - if (!api.endsWith("/")) - api += "/"; - while (splash.startsWith("/")) - splash = splash.substring(1); - splash = api + splash; - } - - // Download splash and set image - BufferedImage img = ImageIO.read(new URL(splash)); - panel_1.setImage(img); - launcherVersion = version; - launcherDir = dirName; - launcherURL = url; - - // Set title - if (!installerMode) - frmCenturiaLauncher.setTitle(srvName + " Launcher"); - else - frmCenturiaLauncher.setTitle(srvName + " Installer"); - } catch (Exception e) { - JOptionPane.showMessageDialog(null, - "Could not connect with the launcher servers, please check your internet connection. If you are connected, please wait a few minutes and try again.\n\nIf the issue remains and you are connected to the internet, please submit a support ticket.", - (installerMode ? "Installer" : "Launcher") + " Error", JOptionPane.ERROR_MESSAGE); - System.exit(1); - return; - } - - try { // Build folder path + File instDir; boolean inHome = false; if (System.getenv("LOCALAPPDATA") == null) { instDir = new File(System.getProperty("user.home") + "/.local/share"); @@ -394,13 +359,78 @@ private void initialize() { JsonParser.parseString(Files.readString(new File(instDir, "installation.json").toPath())) .getAsJsonObject().get("installationDirectory").getAsString()); + // Set title + if (!installerMode) + frmCenturiaLauncher.setTitle(srvName + " Launcher"); + else + frmCenturiaLauncher.setTitle(srvName + " Installer"); + + // Contact server + String launcherVersion = null; + String launcherURL = null; + boolean connection = false; + try { + // Download data + InputStream strm = new URL(url).openStream(); + String data = new String(strm.readAllBytes(), "UTF-8"); + strm.close(); + JsonObject info = JsonParser.parseString(data).getAsJsonObject(); + JsonObject launcher = info.get("launcher").getAsJsonObject(); + String splash = launcher.get("splash").getAsString(); + url = launcher.get("url").getAsString(); + String version = launcher.get("version").getAsString(); + + // Handle relative paths for banner + if (!splash.startsWith("http://") && !splash.startsWith("https://")) { + JsonObject serverInfo = info.get("server").getAsJsonObject(); + JsonObject hosts = serverInfo.get("hosts").getAsJsonObject(); + String api = hosts.get("api").getAsString(); + if (!api.endsWith("/")) + api += "/"; + while (splash.startsWith("/")) + splash = splash.substring(1); + splash = api + splash; + } + + // Download splash and set image + try { + InputStream strmi = new URL(splash).openStream(); + FileOutputStream bannerO = new FileOutputStream(new File(instDir, "banner.image")); + strmi.transferTo(bannerO); + strmi.close(); + bannerO.close(); + } catch (IOException e) { + } + BufferedImage img = ImageIO.read(new File(instDir, "banner.image")); + panel_1.setImage(img); + launcherVersion = version; + launcherURL = url; + connection = true; + } catch (Exception e) { + if (!installerMode || !new File(instDir, "banner.image").exists()) { + JOptionPane.showMessageDialog(null, + "Could not connect with the launcher servers, please check your internet connection. If you are connected, please wait a few minutes and try again.\n\nIf the issue remains and you are connected to the internet, please contact support.", + (installerMode ? "Installer" : "Launcher") + " Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } else { + // Download splash and set image + BufferedImage img = ImageIO.read(new File(instDir, "banner.image")); + panel_1.setImage(img); + launcherURL = url; + } + } + // Start launcher if (!installerMode) - startLauncher(instDir, progressBar, launcherVersion, srvName, launcherURL, dataUrl); + startLauncher(instDir, progressBar, launcherVersion, srvName, launcherURL, dataUrl, args); else { File dir = instDir; // Installer mode, ask which operation to perform + boolean connectionF = connection; + String launcherVersionF = launcherVersion; + String launcherURLF = launcherURL; Thread th = new Thread(() -> { log("Waiting for user to select installer operation..."); SwingUtilities.invokeLater(() -> { @@ -443,10 +473,18 @@ private void initialize() { }); // Run operation - if (selected == 0) - installLauncher(dir, progressBar, launcherVersion, srvName, launcherURL, dataUrl, + if (selected == 0) { + if (!connectionF) { + JOptionPane.showMessageDialog(null, + "Could not connect with the launcher servers, please check your internet connection. If you are connected, please wait a few minutes and try again.\n\nIf the issue remains and you are connected to the internet, please contact support.", + (installerMode ? "Installer" : "Launcher") + " Error", + JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + installLauncher(dir, progressBar, launcherVersionF, srvName, launcherURLF, dataUrl, launcherDir); - else { + } else { SwingUtilities.invokeAndWait(() -> { if (JOptionPane.showConfirmDialog(frmCenturiaLauncher, "Are you sure you wish to uninstall the " + srvName @@ -456,8 +494,7 @@ private void initialize() { System.exit(1); } }); - uninstallLauncher(dir, progressBar, launcherVersion, srvName, launcherURL, dataUrl, - launcherDir); + uninstallLauncher(dir, progressBar, srvName, launcherDir); } } catch (Exception e) { try { @@ -703,6 +740,9 @@ private static void performInstallLauncher(File instDir, JProgressBar progressBa installDirFile.getParentFile().mkdirs(); Files.writeString(installDirFile.toPath(), infoJson.toString()); + // TODO: support URL protocols + // TODO: register uninstall stuff for windows + // Windows and linux only, macos already has the app installed now if (os != 0) { log("Creating shortcuts..."); @@ -785,7 +825,8 @@ private static void performInstallLauncher(File instDir, JProgressBar progressBa System.exit(proc.exitValue()); } else { // Start OSX launcher - ProcessBuilder builder = new ProcessBuilder("open", "-n", new File("/Applications/" + srvName + ".app").getAbsolutePath()); + ProcessBuilder builder = new ProcessBuilder("open", "-n", + new File("/Applications/" + srvName + ".app").getAbsolutePath()); builder.inheritIO(); Process proc = builder.start(); try { @@ -827,8 +868,7 @@ private static void createWindowsShortcut(File lnk, File executable, String args vbs.delete(); } - private static void uninstallLauncher(File instDir, JProgressBar progressBar, String launcherVersion, - String srvName, String launcherURL, String dataUrl, String launcherDir) { + private static void uninstallLauncher(File instDir, JProgressBar progressBar, String srvName, String launcherDir) { log("Preparing to uninstall..."); // Check for installation data @@ -1087,7 +1127,7 @@ private static int countDir(File dir) { } private void startLauncher(File instDir, JProgressBar progressBar, String launcherVersion, String srvName, - String launcherURL, String dataUrl) { + String launcherURL, String dataUrl, String[] args) { File dir = instDir; Thread th = new Thread(() -> { // Set progress bar status @@ -1167,6 +1207,8 @@ private void startLauncher(File instDir, JProgressBar progressBar, String launch .replace("$", ProcessHandle.current().info().command().get()) .replace("$", File.pathSeparator).replace("$", srvName) .replace("$", dataUrl)); + for (String arg : args) + cmd.add(arg); // Detect OS int os; @@ -1184,6 +1226,8 @@ else if (System.getProperty("os.name").toLowerCase().contains("win")) builder.environment().put("CENTURIA_LAUNCHER_PATH", (os == 0 || os == 2 ? new File("launcher.sh").getAbsolutePath() : new File("launcher.bat").getAbsolutePath())); + if (os == 0) + builder.environment().put("PATH", System.getenv("PATH") + ":/usr/local/bin"); builder.inheritIO(); Process proc = builder.start(); @@ -1191,9 +1235,99 @@ else if (System.getProperty("os.name").toLowerCase().contains("win")) if (!currentVersion.equals(launcherVersion)) Files.writeString(verFile.toPath(), launcherVersion); SwingUtilities.invokeAndWait(() -> { - frmCenturiaLauncher.dispose(); + frmCenturiaLauncher.setVisible(false); }); proc.waitFor(); + int exitCode = proc.waitFor(); + if (exitCode == 237) { + // Reset + log("Checking launcher files..."); + SwingUtilities.invokeAndWait(() -> { + progressBar.setMaximum(100); + progressBar.setValue(0); + }); + + // Read server info + String url; + String dataUrl2; + String srvName2; + try { + JsonObject conf = JsonParser.parseString(Files.readString(Path.of("server.json"))) + .getAsJsonObject(); + srvName2 = conf.get("serverName").getAsString(); + url = conf.get("serverConfig").getAsString(); + dataUrl2 = url; + } catch (Exception e) { + JOptionPane.showMessageDialog(null, + "Invalid " + (installerMode ? "installer" : "launcher") + " configuration.", + (installerMode ? "Installer" : "Launcher") + " Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + + // Set title + if (!installerMode) + frmCenturiaLauncher.setTitle(srvName + " Launcher"); + else + frmCenturiaLauncher.setTitle(srvName + " Installer"); + + // Contact server + String launcherVersion2; + String launcherURL2; + try { + // Download data + InputStream strm = new URL(url).openStream(); + String data = new String(strm.readAllBytes(), "UTF-8"); + strm.close(); + JsonObject info = JsonParser.parseString(data).getAsJsonObject(); + JsonObject launcher = info.get("launcher").getAsJsonObject(); + String splash = launcher.get("splash").getAsString(); + url = launcher.get("url").getAsString(); + String version = launcher.get("version").getAsString(); + + // Handle relative paths for banner + if (!splash.startsWith("http://") && !splash.startsWith("https://")) { + JsonObject serverInfo = info.get("server").getAsJsonObject(); + JsonObject hosts = serverInfo.get("hosts").getAsJsonObject(); + String api = hosts.get("api").getAsString(); + if (!api.endsWith("/")) + api += "/"; + while (splash.startsWith("/")) + splash = splash.substring(1); + splash = api + splash; + } + + // Download splash and set image + try { + InputStream strmi = new URL(splash).openStream(); + FileOutputStream bannerO = new FileOutputStream(new File(instDir, "banner.image")); + strmi.transferTo(bannerO); + strmi.close(); + bannerO.close(); + } catch (IOException e) { + } + BufferedImage img = ImageIO.read(new File(instDir, "banner.image")); + panel_1.setImage(img); + launcherVersion2 = version; + launcherURL2 = url; + + // Launch again + SwingUtilities.invokeAndWait(() -> { + frmCenturiaLauncher.setVisible(true); + }); + startLauncher(instDir, progressBar, launcherVersion2, srvName2, launcherURL2, dataUrl2, args); + } catch (Exception e) { + JOptionPane.showMessageDialog(null, + "Could not connect with the launcher servers, please check your internet connection. If you are connected, please wait a few minutes and try again.\n\nIf the issue remains and you are connected to the internet, please contact support.", + (installerMode ? "Installer" : "Launcher") + " Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + return; + } + SwingUtilities.invokeAndWait(() -> { + frmCenturiaLauncher.dispose(); + }); System.exit(proc.exitValue()); } catch (Exception e) { try {