diff --git a/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/FileDownloader.java b/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/FileDownloader.java index b627c03a..f377921f 100644 --- a/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/FileDownloader.java +++ b/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/FileDownloader.java @@ -35,24 +35,27 @@ public record FileDownloader(String url, String target, String hash) implements if (Files.isDirectory(path)) { throw new FileAlreadyExistsException(target); } else { - if (Util.hash(path).equals(hash)) return path; + if (Util.hash(path).equalsIgnoreCase(hash)) return path; else Files.delete(path); } } if (!Files.exists(path) && path.getParent() != null) { Files.createDirectories(path.getParent()); } + var tmp = new File(target + ".tmp").toPath(); URL url = new URL(this.url); try (InputStream stream = redirect(url)) { - Files.copy(stream, path, StandardCopyOption.REPLACE_EXISTING); + Files.copy(stream, tmp, StandardCopyOption.REPLACE_EXISTING); } catch (SocketTimeoutException | SSLException e) { throw new RuntimeException("Timeout " + url); } - if (Files.exists(path)) { - String hash = Util.hash(path); - if (hash.equalsIgnoreCase(this.hash)) return path; - else { - Files.delete(path); + if (Files.exists(tmp)) { + String hash = Util.hash(tmp); + if (hash.equalsIgnoreCase(this.hash)) { + Files.move(tmp, path, StandardCopyOption.REPLACE_EXISTING); + return path; + } else { + Files.delete(tmp); throw new RuntimeException("Hash not match, expect %s found %s in %s".formatted(this.hash, hash, url)); } } else { diff --git a/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/ForgeInstaller.java b/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/ForgeInstaller.java index f27d9f2e..c4f0e8a7 100644 --- a/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/ForgeInstaller.java +++ b/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/ForgeInstaller.java @@ -82,11 +82,12 @@ public class ForgeInstaller { List> suppliers = checkMavenNoSource(installInfo.libraries); var sysType = File.pathSeparatorChar == ';' ? "win" : "unix"; Path path = Paths.get("libraries", "net", "minecraftforge", "forge", installInfo.installer.minecraft + "-" + installInfo.installer.forge, sysType + "_args.txt"); - if (!suppliers.isEmpty() || !Files.exists(path)) { + var installForge = !Files.exists(path) || forgeClasspathMissing(path); + if (!suppliers.isEmpty() || installForge) { System.out.println("Downloading missing libraries ..."); ExecutorService pool = Executors.newFixedThreadPool(8); CompletableFuture[] array = suppliers.stream().map(reportSupply(pool, System.out::println)).toArray(CompletableFuture[]::new); - if (!Files.exists(path)) { + if (installForge) { CompletableFuture[] futures = installForge(installInfo, pool, System.out::println); handleFutures(System.out::println, futures); System.out.println("Forge installation is starting, please wait... "); @@ -151,8 +152,10 @@ public class ForgeInstaller { future.join(); } catch (CompletionException e) { logger.accept(e.getCause().toString()); + Unsafe.throwException(e.getCause()); } catch (Exception e) { e.printStackTrace(); + Unsafe.throwException(e); } } } @@ -202,6 +205,23 @@ public class ForgeInstaller { return incomplete; } + private static boolean forgeClasspathMissing(Path path) throws Exception { + for (String arg : Files.lines(path).collect(Collectors.toList())) { + if (arg.startsWith("-p ")) { + var modules = arg.substring(2).trim(); + if (!Arrays.stream(modules.split(File.pathSeparator)).map(Paths::get).allMatch(Files::exists)) { + return true; + } + } else if (arg.startsWith("-DlegacyClassPath")) { + var classpath = arg.substring("-DlegacyClassPath=".length()).trim(); + if (!Arrays.stream(classpath.split(File.pathSeparator)).map(Paths::get).allMatch(Files::exists)) { + return true; + } + } + } + return false; + } + private static Map.Entry> classpath(Path path, InstallInfo installInfo) throws Throwable { boolean jvmArgs = true; String mainClass = null; @@ -340,6 +360,7 @@ public class ForgeInstaller { this.packages = packages; this.target = target; } + } private static void addExtra(List extras, MethodHandle implAddExtraMH, MethodHandle implAddExtraToAllUnnamedMH) {