From 03f20c7c6c53bf03c67479270d13089c919e42e9 Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 9 Jan 2014 10:18:34 -0800 Subject: [PATCH] Added more detection of broken instances. --- .../java/com/skcraft/launcher/AssetsRoot.java | 8 +++- .../launcher/dialog/LauncherFrame.java | 1 + .../launcher/install/HttpDownloader.java | 2 +- .../com/skcraft/launcher/launch/Runner.java | 42 ++++++++++++++++--- .../skcraft/launcher/update/BaseUpdater.java | 15 +++---- .../skcraft/launcher/lang/Launcher.properties | 8 +++- .../com/skcraft/launcher/launcher.properties | 2 +- 7 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/skcraft/launcher/AssetsRoot.java b/src/main/java/com/skcraft/launcher/AssetsRoot.java index a96003c..16f7d16 100644 --- a/src/main/java/com/skcraft/launcher/AssetsRoot.java +++ b/src/main/java/com/skcraft/launcher/AssetsRoot.java @@ -42,9 +42,13 @@ public class AssetsRoot { return new File(dir, "objects/" + hash.substring(0, 2) + "/" + hash); } - public AssetsTreeBuilder createAssetsBuilder(@NonNull VersionManifest versionManifest) { + public AssetsTreeBuilder createAssetsBuilder(@NonNull VersionManifest versionManifest) throws LauncherException { String indexId = versionManifest.getAssetsIndex(); - AssetsIndex index = Persistence.read(getIndexPath(versionManifest), AssetsIndex.class); + File path = getIndexPath(versionManifest); + AssetsIndex index = Persistence.read(path, AssetsIndex.class, true); + if (index == null || index.getObjects() == null) { + throw new LauncherException("Missing index at " + path, _("assets.missingIndex", path.getAbsolutePath())); + } File treeDir = new File(dir, "virtual/" + indexId); treeDir.mkdirs(); return new AssetsTreeBuilder(index, treeDir); diff --git a/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java b/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java index 92fe0da..f40b40c 100644 --- a/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java +++ b/src/main/java/com/skcraft/launcher/dialog/LauncherFrame.java @@ -505,6 +505,7 @@ public class LauncherFrame extends JFrame { } catch (IOException e) { log.log(Level.WARNING, "Failed to clean up " + extractDir.getAbsolutePath(), e); } + instancesModel.update(); } }, sameThreadExecutor()); } diff --git a/src/main/java/com/skcraft/launcher/install/HttpDownloader.java b/src/main/java/com/skcraft/launcher/install/HttpDownloader.java index 71b0060..840ede4 100644 --- a/src/main/java/com/skcraft/launcher/install/HttpDownloader.java +++ b/src/main/java/com/skcraft/launcher/install/HttpDownloader.java @@ -135,7 +135,7 @@ public class HttpDownloader implements Downloader { synchronized (this) { if (failed.size() > 0) { - throw new IOException(failed.size() + " files could not be downloaded"); + throw new IOException(failed.size() + " file(s) could not be downloaded"); } } } finally { diff --git a/src/main/java/com/skcraft/launcher/launch/Runner.java b/src/main/java/com/skcraft/launcher/launch/Runner.java index a3237cb..56757d9 100644 --- a/src/main/java/com/skcraft/launcher/launch/Runner.java +++ b/src/main/java/com/skcraft/launcher/launch/Runner.java @@ -18,6 +18,7 @@ import com.skcraft.launcher.install.ZipExtract; import com.skcraft.launcher.model.minecraft.AssetsIndex; import com.skcraft.launcher.model.minecraft.Library; import com.skcraft.launcher.model.minecraft.VersionManifest; +import com.skcraft.launcher.persistence.Persistence; import com.skcraft.launcher.util.Environment; import com.skcraft.launcher.util.Platform; import lombok.Getter; @@ -27,6 +28,7 @@ import lombok.extern.java.Log; import org.apache.commons.lang.text.StrSubstitutor; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.List; @@ -99,12 +101,33 @@ public class Runner implements Callable, ProgressObservable { // Load versionManifest and assets index versionManifest = mapper.readValue(instance.getVersionPath(), VersionManifest.class); - assetsIndex = mapper.readValue(assetsRoot.getIndexPath(versionManifest), AssetsIndex.class); + + // Load assets index + File assetsFile = assetsRoot.getIndexPath(versionManifest); + try { + assetsIndex = mapper.readValue(assetsFile, AssetsIndex.class); + } catch (FileNotFoundException e) { + instance.setInstalled(false); + Persistence.commitAndForget(instance); + throw new LauncherException("Missing assets index " + assetsFile.getAbsolutePath(), + _("runner.missingAssetsIndex", instance.getTitle(), assetsFile.getAbsolutePath())); + } catch (IOException e) { + instance.setInstalled(false); + Persistence.commitAndForget(instance); + throw new LauncherException("Corrupt assets index " + assetsFile.getAbsolutePath(), + _("runner.corruptAssetsIndex", instance.getTitle(), assetsFile.getAbsolutePath())); + } // Copy over assets to the tree - AssetsRoot.AssetsTreeBuilder assetsBuilder = assetsRoot.createAssetsBuilder(versionManifest); - progress = assetsBuilder; - virtualAssetsDir = assetsBuilder.build(); + try { + AssetsRoot.AssetsTreeBuilder assetsBuilder = assetsRoot.createAssetsBuilder(versionManifest); + progress = assetsBuilder; + virtualAssetsDir = assetsBuilder.build(); + } catch (LauncherException e) { + instance.setInstalled(false); + Persistence.commitAndForget(instance); + throw e; + } progress = new DefaultProgress(0.9, _("runner.collectingArgs")); @@ -150,9 +173,13 @@ public class Runner implements Callable, ProgressObservable { /** * Add libraries. */ - private void addLibraries() { + private void addLibraries() throws LauncherException { // Add libraries to classpath or extract the libraries as necessary for (Library library : versionManifest.getLibraries()) { + if (!library.matches(environment)) { + continue; + } + File path = new File(launcher.getLibrariesDir(), library.getPath(environment)); if (path.exists()) { @@ -164,6 +191,11 @@ public class Runner implements Callable, ProgressObservable { } else { builder.classPath(path); } + } else { + instance.setInstalled(false); + Persistence.commitAndForget(instance); + throw new LauncherException("Missing library " + library.getName(), + _("runner.missingLibrary", instance.getTitle(), library.getName())); } } diff --git a/src/main/java/com/skcraft/launcher/update/BaseUpdater.java b/src/main/java/com/skcraft/launcher/update/BaseUpdater.java index 4f611ea..014160a 100644 --- a/src/main/java/com/skcraft/launcher/update/BaseUpdater.java +++ b/src/main/java/com/skcraft/launcher/update/BaseUpdater.java @@ -29,10 +29,7 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.logging.Level; import static com.skcraft.launcher.LauncherUtils.checkInterrupted; @@ -139,6 +136,9 @@ public abstract class BaseUpdater { .saveContent(assetsRoot.getIndexPath(versionManifest)) .asJson(AssetsIndex.class); + // Keep track of duplicates + Set downloading = new HashSet(); + for (Map.Entry entry : index.getObjects().entrySet()) { checkInterrupted(); @@ -146,7 +146,7 @@ public abstract class BaseUpdater { String path = String.format("%s/%s", hash.subSequence(0, 2), hash); File targetFile = assetsRoot.getObjectPath(entry.getValue()); - if (!targetFile.exists()) { + if (!targetFile.exists() && !downloading.contains(path)) { List urls = new ArrayList(); for (URL sourceUrl : sources) { try { @@ -157,9 +157,10 @@ public abstract class BaseUpdater { } File tempFile = installer.getDownloader().download( - sources, "", entry.getValue().getSize(), entry.getKey()); + urls, "", entry.getValue().getSize(), entry.getKey()); installer.queue(new FileMover(tempFile, targetFile)); log.info("Fetching " + path + " from " + urls); + downloading.add(path); } } } @@ -186,7 +187,7 @@ public abstract class BaseUpdater { } } - File tempFile = installer.getDownloader().download(sources, "", LIBRARY_SIZE_ESTIMATE, + File tempFile = installer.getDownloader().download(urls, "", LIBRARY_SIZE_ESTIMATE, library.getName() + ".jar"); installer.queue(new FileMover( tempFile, targetFile)); log.info("Fetching " + path + " from " + urls); diff --git a/src/main/resources/com/skcraft/launcher/lang/Launcher.properties b/src/main/resources/com/skcraft/launcher/lang/Launcher.properties index 0353364..6f8b443 100644 --- a/src/main/resources/com/skcraft/launcher/lang/Launcher.properties +++ b/src/main/resources/com/skcraft/launcher/lang/Launcher.properties @@ -161,10 +161,14 @@ instanceLoader.loadingLocal=Loading local instances from disk... instanceLoader.checkingRemote=Checking for new modpacks... runner.preparing=Preparing for launch... -runner.collectingArgs=Collecting arguments... +runner.collectingArgs=Collecting process arguments... runner.startingJava=Starting java... runner.updateRequired=This instance must be updated before it can be run. +runner.missingLibrary={0} needs to be relaunched and updated because the library ''{1}'' is missing. +runner.missingAssetsIndex={0} needs to be relaunched and updated because its asset index is missing. +runner.corruptAssetsIndex={0} needs to be relaunched and updated because its asset index is corrupt. assets.expanding1=Expanding {0} asset... ({1} remaining) assets.expandingN=Expanding {0} assets... ({1} remaining) -assets.missingObject=You need to force update this instance because the file at ''{0}'' is missing. \ No newline at end of file +assets.missingIndex=You need to update this instance because its index file at ''{0}'' is missing. +assets.missingObject=You need to update this instance because the file at ''{0}'' is missing. \ No newline at end of file diff --git a/src/main/resources/com/skcraft/launcher/launcher.properties b/src/main/resources/com/skcraft/launcher/launcher.properties index d16a0cd..f85e7bf 100644 --- a/src/main/resources/com/skcraft/launcher/launcher.properties +++ b/src/main/resources/com/skcraft/launcher/launcher.properties @@ -12,7 +12,7 @@ versionManifestUrl=https://s3.amazonaws.com/Minecraft.Download/versions/%1$s/%1$ librariesSource=https://libraries.minecraft.net/ jarUrl=http://s3.amazonaws.com/Minecraft.Download/versions/%1$s/%1$s.jar assetsIndexUrl=https://s3.amazonaws.com/Minecraft.Download/indexes/%s.json -assetsSource=http://resources.download.minecraft.net/%s/%s +assetsSource=http://resources.download.minecraft.net/ yggdrasilAuthUrl=https://authserver.mojang.com/authenticate resetPasswordUrl=https://minecraft.net/resetpassword