package sk.tomsik68.mclauncher.impl.versions.mcdownload;
import java.io.File;
import java.io.FileReader;
import net.minidev.json.JSONObject;
import net.minidev.json.JSONValue;
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.util.FilePathBuilder;
import sk.tomsik68.mclauncher.util.FileUtils;
final class MCDResourcesInstaller {
private final File assetsDir, indexesDir, objectsDir, virtualDir;
private static final String RESOURCES_INDEX_URL = "https://s3.amazonaws.com/Minecraft.Download/indexes/";
MCDResourcesInstaller(MinecraftInstance mc) {
assetsDir = new File(mc.getLocation(), "assets");
indexesDir = new File(assetsDir, "indexes");
objectsDir = new File(assetsDir, "objects");
virtualDir = new File(assetsDir, "virtual");
}
/**
* Installs resources for given version
* @param version Version to install resources for
* @param progress ProgressMonitor
* @throws Exception Connection and I/O errors
*/
void installAssetsForVersion(MCDownloadVersion version, IProgressMonitor progress) throws Exception {
// let's see which asset index is needed by this version
String index = version.getAssetsIndexName();
MCLauncherAPI.log.fine("Installing asset index ".concat(index));
File indexDest = new File(indexesDir, index + ".json");
String indexDownloadURL = RESOURCES_INDEX_URL + index + ".json";
// download this asset index
if (!indexDest.exists() || indexDest.length() == 0)
FileUtils.downloadFileWithProgress(indexDownloadURL, indexDest, progress);
// parse it from JSON
FileReader fileReader = new FileReader(indexDest);
JSONObject jsonAssets = (JSONObject) JSONValue.parse(fileReader);
fileReader.close();
AssetIndex assets = new AssetIndex(index, jsonAssets);
// and download individual assets inside it
downloadAssetList(assets, progress);
MCLauncherAPI.log.fine("Finished installing asset index ".concat(index));
}
File getAssetsDirectory(){ return assetsDir; }
/**
* Download all the {@link Asset} objects inside this index
* @param index AssetIndex to download from
* @param progress
* @throws Exception
*/
private void downloadAssetList(AssetIndex index, IProgressMonitor progress) throws Exception {
for(Asset asset : index.getAssets()){
MCLauncherAPI.log.info("Updating asset file: ".concat(asset.getKey()).concat(" (size:").concat(""+asset.getSize()).concat("B)"));
if(progress != null)
progress.setStatus("Updating asset file: " + asset.getKey());
File dest = getDestFile(index, asset);
dest.getParentFile().mkdirs();
if (!dest.exists() || dest.length() != asset.getSize()) {
MCLauncherAPI.log.finest("Downloading ".concat(asset.getKey()));
FileUtils.downloadFileWithProgress(asset.getUrl(), dest, progress);
} else {
MCLauncherAPI.log.finest("No need to update ".concat(asset.getKey()));
}
}
}
/**
*
* @param index AssetIndex where the asset belongs to
* @param asset Asset which is going to be downloaded
* @return Path to file where the asset in given index should be located
*/
private File getDestFile(AssetIndex index, Asset asset){
File result;
// the difference is, that some indexes are virtual.
// virtual indexes have their assets downloaded to assets/virtual/1.7.3 etc
if(index.isVirtual()){
File assetsDir = new File(virtualDir, index.getName());
assetsDir.mkdirs();
String path = asset.getKey().replace('/', File.separatorChar);
result = new File(assetsDir, path);
} else {
// while non-virtual indexes download them into 'objects' folder and name them after their hash
FilePathBuilder pathBuilder = new FilePathBuilder(objectsDir);
pathBuilder.append(asset.getPreHash()).append(asset.getHash());
result = pathBuilder.getResult();
}
return result;
}
}