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.equalsIgnoreCase("sound3"))
142                {
143                    if (par5 != 0)
144                    {
145                        return;
146                    }
147                }
148                else if (par5 != 1)
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    }