    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import java.io.DataInputStream;
    006    import java.io.DataOutputStream;
    007    import java.io.File;
    008    import java.io.FileOutputStream;
    009    import java.io.IOException;
    010    import java.net.URL;
    011    import java.net.URLConnection;
    012
    013    import javax.xml.parsers.DocumentBuilder;
    014    import javax.xml.parsers.DocumentBuilderFactory;
    015    import net.minecraft.client.Minecraft;
    016    import org.w3c.dom.Document;
    017    import org.w3c.dom.Element;
    018    import org.w3c.dom.Node;
    019    import org.w3c.dom.NodeList;
    020
    021    @SideOnly(Side.CLIENT)
    022    public 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            File[] var4 = var3;
    107            int var5 = var3.length;
    108
    109            for (int var6 = 0; var6 < var5; ++var6)
    110            {
    111                File var7 = var4[var6];
    112
    113                if (var7.isDirectory())
    114                {
    115                    this.loadResource(var7, par2Str + var7.getName() + "/");
    116                }
    117                else
    118                {
    119                    try
    120                    {
    121                        this.mc.installResource(par2Str + var7.getName(), var7);
    122                    }
    123                    catch (Exception var9)
    124                    {
    125                        System.out.println("Failed to add " + par2Str + var7.getName());
    126                    }
    127                }
    128            }
    129        }
    130
    131        /**
    132         * Downloads the resource and saves it to disk then installs it.
    133         */
    134        private void downloadAndInstallResource(URL par1URL, String par2Str, long par3, int par5)
    135        {
    136            try
    137            {
    138                int var6 = par2Str.indexOf("/");
    139                String var7 = par2Str.substring(0, var6);
    140
    141                if (!var7.equals("sound") && !var7.equals("newsound"))
    142                {
    143                    if (par5 != 1)
    144                    {
    145                        return;
    146                    }
    147                }
    148                else if (par5 != 0)
    149                {
    150                    return;
    151                }
    152
    153                File var8 = new File(this.resourcesFolder, par2Str);
    154
    155                if (!var8.exists() || var8.length() != par3)
    156                {
    157                    var8.getParentFile().mkdirs();
    158                    String var9 = par2Str.replaceAll(" ", "%20");
    159                    this.downloadResource(new URL(par1URL, var9), var8, par3);
    160
    161                    if (this.closing)
    162                    {
    163                        return;
    164                    }
    165                }
    166
    167                this.mc.installResource(par2Str, var8);
    168            }
    169            catch (Exception var10)
    170            {
    171                var10.printStackTrace();
    172            }
    173        }
    174
    175        /**
    176         * Downloads the resource and saves it to disk.
    177         */
    178        private void downloadResource(URL par1URL, File par2File, long par3) throws IOException
    179        {
    180            byte[] var5 = new byte[4096];
    181            //Add a timeout of 60 seconds to getting the list, MC stalls without sound for some users.
    182            URLConnection con = par1URL.openConnection();
    183            con.setConnectTimeout(60000);
    184            con.setReadTimeout(60000);
    185            DataInputStream var6 = new DataInputStream(con.getInputStream());
    186            DataOutputStream var7 = new DataOutputStream(new FileOutputStream(par2File));
    187            boolean var8 = false;
    188
    189            do
    190            {
    191                int var9;
    192
    193                if ((var9 = var6.read(var5)) < 0)
    194                {
    195                    var6.close();
    196                    var7.close();
    197                    return;
    198                }
    199
    200                var7.write(var5, 0, var9);
    201            }
    202            while (!this.closing);
    203        }
    204
    205        /**
    206         * Called when Minecraft is closing down.
    207         */
    208        public void closeMinecraft()
    209        {
    210            this.closing = true;
    211        }
    212    }