Skip to content

Instantly share code, notes, and snippets.

@Runemoro
Created June 26, 2019 11:24
Show Gist options
  • Save Runemoro/6890bcadae617ed91e8ee79680e9769a to your computer and use it in GitHub Desktop.
Save Runemoro/6890bcadae617ed91e8ee79680e9769a to your computer and use it in GitHub Desktop.
package downloader;
import downloader.mlp.LauncherJsonHelper;
import downloader.mlp.Version;
import downloader.mlp.VersionManifest;
import net.fabricmc.stitch.merge.JarMerger;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Downloader {
private static final String VERSION_MANIFEST = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
public static void main(String[] args) throws Exception {
VersionManifest versionManifest = readJson(new URL(VERSION_MANIFEST), VersionManifest.class);
for (Map.Entry<String, String> entry : versionManifest.latest.entrySet()) {
System.out.println("Latest '" + entry.getKey() + "' version is '" + entry.getValue() + "'");
}
String versionId = ask("Minecraft version", versionManifest.latest.get("snapshot"));
URL versionUrl = versionManifest.versions.stream()
.filter(version -> version.id.equals(versionId))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("version not found: " + versionId))
.url;
Version version = readJson(versionUrl, Version.class);
File clientJar = null;
File serverJar = null;
for (Map.Entry<String, Version.Download> entry : version.downloads.entrySet()) {
File file = new File("tmp", version.id + "_" + entry.getKey() + ".jar");
if (entry.getKey().equals("client")) {
clientJar = file;
} else if (entry.getKey().equals("server")) {
serverJar = file;
} else {
throw new IllegalStateException("unknown jar type " + entry);
}
System.out.println("Downloading " + entry.getKey());
downloadIfAbsent(entry.getValue().url, file, entry.getValue().sha1);
}
Set<File> libs = new LinkedHashSet<>();
for (Version.Library library : version.libraries) {
Version.Download artifact = library.downloads.artifact;
File file = new File("tmp/libs", artifact.path);
libs.add(file);
System.out.println("Downloading library " + library.name);
downloadIfAbsent(artifact.url, file, artifact.sha1);
}
System.out.println("Creating merged jar");
File mergedJar = new File("tmp", version.id + "_merged.jar");
try (JarMerger merger = new JarMerger(clientJar, serverJar, mergedJar)) {
merger.enableSnowmanRemoval();
merger.merge();
}
}
private static void downloadIfAbsent(URL url, File file, String sha1) throws IOException {
if (!file.exists() || !sha1(file).equals(sha1)) {
file.getParentFile().mkdirs();
try (InputStream in = url.openStream()) {
Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
}
private static String sha1(File file) throws IOException {
try {
byte[] hash = MessageDigest.getInstance("SHA1").digest(Files.readAllBytes(file.toPath()));
StringBuilder sb = new StringBuilder();
for (byte b : hash) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
private static <T> T readJson(URL url, Class<T> classOfT) throws IOException {
T t;
try (Reader reader = new InputStreamReader(url.openStream())) {
t = LauncherJsonHelper.GSON.fromJson(reader, classOfT);
}
return t;
}
private static String ask(String message, String fallback) {
System.out.print(message + (fallback == null ? "" : " (or blank for " + fallback + ")") + ": ");
String result = new Scanner(System.in).nextLine().trim();
return result.isEmpty() ? fallback : result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment