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}