package sk.tomsik68.mclauncher.impl.versions.mcdownload; import net.minidev.json.JSONStyle; import sk.tomsik68.mclauncher.api.common.MCLauncherAPI; import sk.tomsik68.mclauncher.api.common.mc.MinecraftInstance; import sk.tomsik68.mclauncher.api.ui.IProgressMonitor; import sk.tomsik68.mclauncher.api.versions.IVersion; import sk.tomsik68.mclauncher.api.versions.IVersionInstallListener; import sk.tomsik68.mclauncher.api.versions.IVersionInstaller; import sk.tomsik68.mclauncher.impl.common.Platform; import sk.tomsik68.mclauncher.util.ExtractUtils; import sk.tomsik68.mclauncher.util.FileUtils; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; final class MCDownloadVersionInstaller implements IVersionInstaller { private final ArrayList<IVersionInstallListener> listeners = new ArrayList<IVersionInstallListener>(); private static final String JAR_DOWNLOAD_URL = "https://s3.amazonaws.com/Minecraft.Download/versions/<VERSION>/<VERSION>.jar"; public MCDownloadVersionInstaller(){ } @Override public void addVersionInstallListener(IVersionInstallListener listener) { listeners.add(listener); } @Override public void install(IVersion v, MinecraftInstance mc, IProgressMonitor progress) throws Exception { MCDownloadVersionList versionList = new MCDownloadVersionList(mc); final boolean haveProgress = (progress != null); // create jar manager and library provider as we'll need them MCDJarManager jarManager = new MCDJarManager(mc); LibraryProvider libraryProvider = new LibraryProvider(mc); Logger log = MCLauncherAPI.log; log.fine("Checking compatibility..."); MCDownloadVersion version = (MCDownloadVersion) v; // check compatibility of this version if (!version.isCompatible()) throw new VersionIncompatibleException(v); // check if inheritance was completed if(version.needsInheritance()) throw new VersionInheritanceException(v); // if we're inheriting from a version if(version.getInheritsFrom() != null && version.getInheritsFrom().length() > 0){ MCLauncherAPI.log.fine("Looks like we're inheriting a version. Checking parent version..."); // download the parent version information IVersion parent = versionList.retrieveVersionInfo(version.getInheritsFrom()); // and the parent version isn't installed File jsonFile = jarManager.getInfoFile(parent); MCLauncherAPI.log.fine("Looking for ".concat(jsonFile.getAbsolutePath())); if (!jsonFile.exists()) { MCLauncherAPI.log.info("Installing parent version..."); parent.getInstaller().install(parent, mc, progress); } } log.fine("Version compatible"); List<Library> toInstall = version.getLibraries(); List<Library> toExtract = new ArrayList<Library>(); log.fine("Fetching libraries..."); if(haveProgress) progress.setStatus("Fetching Libraries..."); log.fine("Platform: " + Platform.getCurrentPlatform().getDisplayName()); // install all libraries that are needed for (Library lib : toInstall) { if (lib.isCompatible()) { if (!libraryProvider.isInstalled(lib)) { log.finest("Installing " + lib.getName()); if(haveProgress) progress.setStatus("Installing " + lib.getName()); try { downloadLibrary(lib.getDownloadURL(), libraryProvider.getLibraryFile(lib), progress); } catch (Exception e) { e.printStackTrace(); log.finest("Failed to install " + lib.getName()); } } // if library has natives, it needs to be extracted... if (lib.hasNatives()) { toExtract.add(lib); } } else { log.finest(lib.getName() + " is not compatible."); } } log.fine("Extracting natives..."); if(haveProgress) progress.setStatus("Extracting natives..."); File nativesDir = new File(jarManager.getVersionFolder(version), "natives"); // purge old natives if they are present if (nativesDir.exists()) { File[] contains = nativesDir.listFiles(); for (File f : contains) { f.delete(); } } log.fine("Extracting libraries..."); if(haveProgress) progress.setStatus("Extracting Libraries..."); // extract the new natives for (Library lib : toExtract) { File libFile = libraryProvider.getLibraryFile(lib); ExtractUtils.extractZipWithRules(libFile, nativesDir, lib.getExtractRules()); } log.fine("Updating resources..."); if(haveProgress) progress.setStatus("Updating Resource..."); updateResources(mc, version, progress); File jarDest = jarManager.getVersionJAR(version); File jsonDest = jarManager.getInfoFile(version); log.fine("Writing version info JSON file..."); // always overwrite json file FileUtils.writeFile(jsonDest, version.toJSON().toJSONString(JSONStyle.LT_COMPRESS)); // and jar file log.fine("Downloading game JAR..."); // if this version uses its own jar if(version.getJarVersion().equals(version.getId())) { // download it if(haveProgress) progress.setStatus("Downloading Game Jar..."); try { FileUtils.downloadFileWithProgress(JAR_DOWNLOAD_URL.replace("<VERSION>", version.getId()), jarDest, progress); } catch (Exception e) { e.printStackTrace(); } } // notify listeners that installation is finished notifyListeners(version); } private void updateResources(MinecraftInstance mc, MCDownloadVersion version, IProgressMonitor progress) throws Exception { MCDResourcesInstaller resInstaller = new MCDResourcesInstaller(mc); resInstaller.installAssetsForVersion(version, progress); } private void downloadLibrary(String url, File dest, IProgressMonitor p) throws Exception { FileUtils.downloadFileWithProgress(url, dest, p); } private void notifyListeners(IVersion version) { for (IVersionInstallListener listener : listeners) { listener.versionInstalled(version); } } }