[FEATURE] Download assets from mojang

This commit is contained in:
Gravita 2022-07-30 16:15:35 +07:00
parent bbb962c624
commit 81b80a7938
4 changed files with 100 additions and 9 deletions

View file

@ -1,25 +1,39 @@
package pro.gravit.launchserver.command.hash;
import com.google.gson.JsonObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.AsyncDownloader;
import pro.gravit.launcher.Launcher;
import pro.gravit.launchserver.HttpRequester;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.command.Command;
import pro.gravit.utils.Downloader;
import pro.gravit.utils.helper.IOHelper;
import proguard.OutputWriter;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class DownloadAssetCommand extends Command {
private transient final Logger logger = LogManager.getLogger();
private static final String MINECRAFT_VERSIONS_URL = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
private static final String RESOURCES_DOWNLOAD_URL = "https://resources.download.minecraft.net/";
public DownloadAssetCommand(LaunchServer server) {
super(server);
}
@Override
public String getArgsDescription() {
return "[version] [dir]";
return "[version] [dir] (mojang/mirror)";
}
@Override
@ -32,20 +46,89 @@ public void invoke(String... args) throws Exception {
verifyArgs(args, 2);
//Version version = Version.byName(args[0]);
String versionName = args[0];
String type = args.length > 2 ? args[2] : "mojang";
String dirName = IOHelper.verifyFileName(args[1]);
Path assetDir = server.updatesDir.resolve(dirName);
// Create asset dir
if(Files.notExists(assetDir)) {
logger.info("Creating asset dir: '{}'", dirName);
Files.createDirectory(assetDir);
}
if(type.equals("mojang")) {
HttpRequester requester = new HttpRequester();
logger.info("Fetch versions from {}", MINECRAFT_VERSIONS_URL);
var versions = requester.send(requester.get(MINECRAFT_VERSIONS_URL, null), MinecraftVersions.class).getOrThrow();
String profileUrl = null;
for(var e : versions.versions) {
if(e.id.equals(versionName)) {
profileUrl = e.url;
break;
}
}
if(profileUrl == null) {
logger.error("Version {} not found", versionName);
return;
}
logger.info("Fetch profile {} from {}", versionName, profileUrl);
var profileInfo = requester.send(requester.get(profileUrl, null), MiniVersion.class).getOrThrow();
String assetsIndexUrl = profileInfo.assetIndex.url;
String assetIndex = profileInfo.assetIndex.id;
Path indexPath = assetDir.resolve("indexes").resolve(assetIndex+".json");
logger.info("Fetch asset index {} from {}", assetIndex, assetsIndexUrl);
JsonObject assets = requester.send(requester.get(assetsIndexUrl, null), JsonObject.class).getOrThrow();
JsonObject objects = assets.get("objects").getAsJsonObject();
try(Writer writer = IOHelper.newWriter(indexPath)) {
logger.info("Save {}", indexPath);
Launcher.gsonManager.configGson.toJson(assets, writer);
}
List<AsyncDownloader.SizedFile> toDownload = new ArrayList<>(128);
for(var e : objects.entrySet()) {
var value = e.getValue().getAsJsonObject();
var hash = value.get("hash").getAsString();
hash = hash.substring(0, 2) + "/" + hash;
var size = value.get("size").getAsLong();
var path = "objects/" + hash;
var target = assetDir.resolve(path);
if(Files.exists(target)) {
long fileSize = Files.size(target);
if(fileSize != size) {
logger.warn("File {} corrupted. Size {}, expected {}", target, size, fileSize);
} else {
continue;
}
}
toDownload.add(new AsyncDownloader.SizedFile(hash, path, size));
}
logger.info("Download {} files", toDownload.size());
Downloader downloader = downloadWithProgressBar(dirName, toDownload, RESOURCES_DOWNLOAD_URL, assetDir);
downloader.getFuture().get();
} else {
// Download required asset
logger.info("Downloading asset, it may take some time");
//HttpDownloader.downloadZip(server.mirrorManager.getDefaultMirror().getAssetsURL(version.name), assetDir);
server.mirrorManager.downloadZip(assetDir, "assets/%s.zip", versionName);
}
// Finished
server.syncUpdatesDir(Collections.singleton(dirName));
logger.info("Asset successfully downloaded: '{}'", dirName);
}
public record MiniVersionInfo(String id, String url) {
}
public record MinecraftVersions(List<MiniVersionInfo> versions) {
}
public record MinecraftAssetIndexInfo(String id, String url) {
}
public record MiniVersion(MinecraftAssetIndexInfo assetIndex) {
}
}

View file

@ -236,6 +236,9 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
if (Files.exists(dir.resolve("libraries/forge/launchwrapper-1.12-launcherfixed.jar.jar")) || Files.exists(dir.resolve("libraries/net/minecraft/launchwrapper"))) {
options.add(new MakeProfileOptionLaunchWrapper());
}
if(globalAssets) {
options.add(new MakeProfileOptionGlobalAssets());
}
return options.toArray(new MakeProfileOption[0]);
}

View file

@ -115,7 +115,9 @@ public static void main(String[] args) throws Throwable {
// Verify ClientLauncher sign and classpath
LogHelper.debug("Verifying ClientLauncher sign and classpath");
List<Path> classpath = resolveClassPath(clientDir, params.actions, params.profile).collect(Collectors.toList());
List<Path> classpath = resolveClassPath(clientDir, params.actions, params.profile)
.filter(x -> !profile.getModulePath().contains(clientDir.relativize(x).toString()))
.collect(Collectors.toList());
List<URL> classpathURLs = classpath.stream().map(IOHelper::toURL).collect(Collectors.toList());
// Start client with WatchService monitoring
RequestService service;

View file

@ -153,7 +153,10 @@ public void start(boolean pipeOutput) throws IOException, InterruptedException {
if (params.profile.getClassLoaderConfig() == ClientProfile.ClassLoaderConfig.AGENT) {
processArgs.add("-javaagent:".concat(IOHelper.getCodeSource(ClientLauncherEntryPoint.class).toAbsolutePath().toString()));
} else if (params.profile.getClassLoaderConfig() == ClientProfile.ClassLoaderConfig.SYSTEM_ARGS) {
systemClassPath.addAll(ClientLauncherEntryPoint.resolveClassPath(workDir, params.actions, params.profile).map(Path::toString).collect(Collectors.toList()));
systemClassPath.addAll(ClientLauncherEntryPoint.resolveClassPath(workDir, params.actions, params.profile)
.filter(x -> !params.profile.getModulePath().contains(workDir.relativize(x).toString()))
.map(Path::toString)
.collect(Collectors.toList()));
}
if(Launcher.getConfig().environment != LauncherConfig.LauncherEnvironment.PROD) {
processArgs.add(JVMHelper.jvmProperty(LogHelper.DEV_PROPERTY, String.valueOf(LogHelper.isDevEnabled())));