    001package net.minecraft.util;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.io.DataInputStream;
    006import java.io.DataOutputStream;
    007import java.io.File;
    008import java.io.FileOutputStream;
    009import java.io.IOException;
    010import java.net.URL;
    011import java.net.URLConnection;
    012
    013import javax.xml.parsers.DocumentBuilder;
    014import javax.xml.parsers.DocumentBuilderFactory;
    015import net.minecraft.client.Minecraft;
    016import org.w3c.dom.Document;
    017import org.w3c.dom.Element;
    018import org.w3c.dom.Node;
    019import org.w3c.dom.NodeList;
    020
    021@SideOnly(Side.CLIENT)
    022public class ThreadDownloadResources extends Thread
    023{
    024    /** The folder to store the resources in. */
    025    public File resourcesFolder;
    026
    027    /** A reference to the Minecraft object. */
    028    private Minecraft mc;
    029
    030    /** Set to true when Minecraft is closing down. */
    031    private boolean closing = false;
    032
    033    public ThreadDownloadResources(File par1File, Minecraft par2Minecraft)
    034    {
    035        this.mc = par2Minecraft;
    036        this.setName("Resource download thread");
    037        this.setDaemon(true);
    038        this.resourcesFolder = new File(par1File, "resources/");
    039
    040        if (!this.resourcesFolder.exists() && !this.resourcesFolder.mkdirs())
    041        {
    042            throw new RuntimeException("The working directory could not be created: " + this.resourcesFolder);
    043        }
    044    }
    045
    046    public void run()
    047    {
    048        try
    049        {
    050            URL var1 = new URL("http://s3.amazonaws.com/MinecraftResources/");
    051            DocumentBuilderFactory var2 = DocumentBuilderFactory.newInstance();
    052            DocumentBuilder var3 = var2.newDocumentBuilder();
    053            //Add a timeout of 60 seconds to getting the list, MC stalls without sound for some users.
    054            URLConnection con = var1.openConnection();
    055            con.setConnectTimeout(60000);
    056            con.setReadTimeout(60000);
    057            Document var4 = var3.parse(con.getInputStream());
    058            NodeList var5 = var4.getElementsByTagName("Contents");
    059
    060            for (int var6 = 0; var6 < 2; ++var6)
    061            {
    062                for (int var7 = 0; var7 < var5.getLength(); ++var7)
    063                {
    064                    Node var8 = var5.item(var7);
    065
    066                    if (var8.getNodeType() == 1)
    067                    {
    068                        Element var9 = (Element)var8;
    069                        String var10 = var9.getElementsByTagName("Key").item(0).getChildNodes().item(0).getNodeValue();
    070                        long var11 = Long.parseLong(var9.getElementsByTagName("Size").item(0).getChildNodes().item(0).getNodeValue());
    071
    072                        if (var11 > 0L)
    073                        {
    074                            this.downloadAndInstallResource(var1, var10, var11, var6);
    075
    076                            if (this.closing)
    077                            {
    078                                return;
    079                            }
    080                        }
    081                    }
    082                }
    083            }
    084        }
    085        catch (Exception var13)
    086        {
    087            this.loadResource(this.resourcesFolder, "");
    088            var13.printStackTrace();
    089        }
    090    }
    091
    092    /**
    093     * Reloads the resource folder and passes the resources to Minecraft to install.
    094     */
    095    public void reloadResources()
    096    {
    097        this.loadResource(this.resourcesFolder, "");
    098    }
    099
    100    /**
    101     * Loads a resource and passes it to Minecraft to install.
    102     */
    103    private void loadResource(File par1File, String par2Str)
    104    {
    105        File[] var3 = par1File.listFiles();
    106
    107        for (int var4 = 0; var4 < var3.length; ++var4)
    108        {
    109            if (var3[var4].isDirectory())
    110            {
    111                this.loadResource(var3[var4], par2Str + var3[var4].getName() + "/");
    112            }
    113            else
    114            {
    115                try
    116                {
    117                    this.mc.installResource(par2Str + var3[var4].getName(), var3[var4]);
    118                }
    119                catch (Exception var6)
    120                {
    121                    System.out.println("Failed to add " + par2Str + var3[var4].getName());
    122                }
    123            }
    124        }
    125    }
    126
    127    /**
    128     * Downloads the resource and saves it to disk then installs it.
    129     */
    130    private void downloadAndInstallResource(URL par1URL, String par2Str, long par3, int par5)
    131    {
    132        try
    133        {
    134            int var6 = par2Str.indexOf("/");
    135            String var7 = par2Str.substring(0, var6);
    136
    137            if (var7.equalsIgnoreCase("sound3"))
    138            {
    139                if (par5 != 0)
    140                {
    141                    return;
    142                }
    143            }
    144            else if (par5 != 1)
    145            {
    146                return;
    147            }
    148
    149            File var8 = new File(this.resourcesFolder, par2Str);
    150
    151            if (!var8.exists() || var8.length() != par3)
    152            {
    153                var8.getParentFile().mkdirs();
    154                String var9 = par2Str.replaceAll(" ", "%20");
    155                this.downloadResource(new URL(par1URL, var9), var8, par3);
    156
    157                if (this.closing)
    158                {
    159                    return;
    160                }
    161            }
    162
    163            this.mc.installResource(par2Str, var8);
    164        }
    165        catch (Exception var10)
    166        {
    167            var10.printStackTrace();
    168        }
    169    }
    170
    171    /**
    172     * Downloads the resource and saves it to disk.
    173     */
    174    private void downloadResource(URL par1URL, File par2File, long par3) throws IOException
    175    {
    176        byte[] var5 = new byte[4096];
    177        //Add a timeout of 60 seconds to getting the list, MC stalls without sound for some users.
    178        URLConnection con = par1URL.openConnection();
    179        con.setConnectTimeout(60000);
    180        con.setReadTimeout(60000);
    181        DataInputStream var6 = new DataInputStream(con.getInputStream());
    182        DataOutputStream var7 = new DataOutputStream(new FileOutputStream(par2File));
    183        boolean var8 = false;
    184
    185        do
    186        {
    187            int var9;
    188
    189            if ((var9 = var6.read(var5)) < 0)
    190            {
    191                var6.close();
    192                var7.close();
    193                return;
    194            }
    195
    196            var7.write(var5, 0, var9);
    197        }
    198        while (!this.closing);
    199    }
    200
    201    /**
    202     * Called when Minecraft is closing down.
    203     */
    204    public void closeMinecraft()
    205    {
    206        this.closing = true;
    207    }
    208}