package net.minecraft.util; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import net.minecraft.client.Minecraft; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @SideOnly(Side.CLIENT) public class ThreadDownloadResources extends Thread { /** The folder to store the resources in. */ public File resourcesFolder; /** A reference to the Minecraft object. */ private Minecraft mc; /** Set to true when Minecraft is closing down. */ private boolean closing = false; public ThreadDownloadResources(File par1File, Minecraft par2Minecraft) { this.mc = par2Minecraft; this.setName("Resource download thread"); this.setDaemon(true); this.resourcesFolder = new File(par1File, "resources/"); if (!this.resourcesFolder.exists() && !this.resourcesFolder.mkdirs()) { throw new RuntimeException("The working directory could not be created: " + this.resourcesFolder); } } public void run() { try { URL url = new URL("http://s3.amazonaws.com/MinecraftResources/"); DocumentBuilderFactory documentbuilderfactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentbuilder = documentbuilderfactory.newDocumentBuilder(); //Add a timeout of 60 seconds to getting the list, MC stalls without sound for some users. URLConnection con = url.openConnection(); con.setConnectTimeout(60000); con.setReadTimeout(60000); Document document = documentbuilder.parse(con.getInputStream()); NodeList nodelist = document.getElementsByTagName("Contents"); for (int i = 0; i < 2; ++i) { for (int j = 0; j < nodelist.getLength(); ++j) { Node node = nodelist.item(j); if (node.getNodeType() == 1) { Element element = (Element)node; String s = element.getElementsByTagName("Key").item(0).getChildNodes().item(0).getNodeValue(); long k = Long.parseLong(element.getElementsByTagName("Size").item(0).getChildNodes().item(0).getNodeValue()); if (k > 0L) { this.downloadAndInstallResource(url, s, k, i); if (this.closing) { return; } } } } } } catch (Exception exception) { this.loadResource(this.resourcesFolder, ""); exception.printStackTrace(); } } /** * Reloads the resource folder and passes the resources to Minecraft to install. */ public void reloadResources() { this.loadResource(this.resourcesFolder, ""); } /** * Loads a resource and passes it to Minecraft to install. */ private void loadResource(File par1File, String par2Str) { File[] afile = par1File.listFiles(); for (int i = 0; i < afile.length; ++i) { if (afile[i].isDirectory()) { this.loadResource(afile[i], par2Str + afile[i].getName() + "/"); } else { try { this.mc.installResource(par2Str + afile[i].getName(), afile[i]); } catch (Exception exception) { this.mc.getLogAgent().logWarning("Failed to add " + par2Str + afile[i].getName() + " in resources"); } } } } /** * Downloads the resource and saves it to disk then installs it. */ private void downloadAndInstallResource(URL par1URL, String par2Str, long par3, int par5) { try { int k = par2Str.indexOf("/"); String s1 = par2Str.substring(0, k); if (s1.equalsIgnoreCase("sound3")) { if (par5 != 0) { return; } } else if (par5 != 1) { return; } File file1 = new File(this.resourcesFolder, par2Str); if (!file1.exists() || file1.length() != par3) { file1.getParentFile().mkdirs(); String s2 = par2Str.replaceAll(" ", "%20"); this.downloadResource(new URL(par1URL, s2), file1, par3); if (this.closing) { return; } } this.mc.installResource(par2Str, file1); } catch (Exception exception) { exception.printStackTrace(); } } /** * Downloads the resource and saves it to disk. */ private void downloadResource(URL par1URL, File par2File, long par3) throws IOException { byte[] abyte = new byte[4096]; //Add a timeout of 60 seconds to getting the list, MC stalls without sound for some users. URLConnection con = par1URL.openConnection(); con.setConnectTimeout(60000); con.setReadTimeout(60000); DataInputStream datainputstream = new DataInputStream(con.getInputStream()); DataOutputStream dataoutputstream = new DataOutputStream(new FileOutputStream(par2File)); boolean flag = false; do { int j; if ((j = datainputstream.read(abyte)) < 0) { datainputstream.close(); dataoutputstream.close(); return; } dataoutputstream.write(abyte, 0, j); } while (!this.closing); } /** * Called when Minecraft is closing down. */ public void closeMinecraft() { this.closing = true; } }