package com.thebrokenrail.freshcoffee.util; import com.thebrokenrail.freshcoffee.config.HardcodedConfig; import net.fabricmc.loader.FabricLoader; import net.fabricmc.loader.game.MinecraftGameProvider; import net.fabricmc.loader.util.Arguments; import org.apache.logging.log4j.LogManager; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public final class ReLaunchUtil { private static boolean contains(File dir, File targetFile) { File[] files = dir.listFiles(); if (files != null) { for (File file : files) { try { if (file.toPath().toRealPath().equals(targetFile.toPath().toRealPath()) || contains(file, targetFile)) { return true; } } catch (IOException e) { throw new UncheckedIOException(e); } } } return false; } private static List getMainArgs() { boolean isMultiMC; try { Class.forName("org.multimc.EntryPoint"); isMultiMC = true; } catch (ClassNotFoundException e) { isMultiMC = false; } if (isMultiMC) { // Replace MultiMC's Entry-Point With Fabric's List mainArgs = new ArrayList<>(); // Set Entry-Point mainArgs.add(Util.getMainClass()); // Get Parameters String[] launchArgs; try { Field launchArgsField = MinecraftGameProvider.class.getDeclaredField("arguments"); launchArgsField.setAccessible(true); //noinspection deprecation launchArgs = ((Arguments) launchArgsField.get(FabricLoader.INSTANCE.getGameProvider())).toArray(); } catch (IllegalAccessException | NoSuchFieldException e) { throw new RuntimeException(e); } // Add Parameters mainArgs.addAll(Arrays.asList(launchArgs)); return mainArgs; } else { return Arrays.asList(System.getProperty("sun.java.command").split(" ")); } } private static void reLaunch(String javaBinary) { List vmArgs = new ArrayList<>(ManagementFactory.getRuntimeMXBean().getInputArguments()); // Remove Debugger vmArgs.removeIf(arg -> arg.startsWith("-agentlib") || arg.startsWith("-javaagent")); List mainArgs = getMainArgs(); String classpathStr = System.getProperty("java.class.path"); // Remove Built-In Java Libraries From Classpath List classpath = new ArrayList<>(Arrays.asList(classpathStr.split(File.pathSeparator))); classpath.removeIf(arg -> { File file = new File(arg); File javaHome = new File(System.getProperty("java.home")); return contains(javaHome, file); }); String newClasspathStr = String.join(File.pathSeparator, classpath); List args = new ArrayList<>(); args.add(javaBinary); args.addAll(vmArgs); args.add("-cp"); args.add(newClasspathStr); args.addAll(mainArgs); Util.getLogger().info("ReLaunching Minecraft..."); Util.getLogger().debug("Launching: " + String.join(" ", args)); // Release Lock On Log File LogManager.shutdown(); Process process; try { process = new ProcessBuilder(args).inheritIO().start(); } catch (IOException e) { throw new UncheckedIOException(e); } try { int status = process.waitFor(); System.exit(status); } catch (InterruptedException e) { process.destroy(); } } public static void reLaunch() { File[] files = HardcodedConfig.INSTALL_DIR.listFiles(); if (files != null) { List list = new ArrayList<>(); for (File file : files) { if (file.isDirectory()) { list.add(file.getName()); } } String newestVersion = JavaVersionUtil.getNewest(list.toArray(new String[0])); if (newestVersion != null) { File javaBinary = new File(new File(Util.getJavaDir(newestVersion), "bin"), "java" + PlatformUtil.getExecutableExtension()); if (javaBinary.exists() && javaBinary.canExecute()) { Util.getLogger().info("Using Java Executable: " + javaBinary.getAbsolutePath()); reLaunch(javaBinary.getAbsolutePath()); } } } } }