package com.kokakiwi.mclauncher.core.updater;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import com.kokakiwi.mclauncher.api.LauncherAPI;
import com.kokakiwi.mclauncher.core.Updater.State;
import com.kokakiwi.mclauncher.utils.SystemUtils;
public class UpdaterWorker
{
public static void update(LauncherAPI api)
{
for (final GameFile file : api.getUpdater().getGameFiles())
{
try
{
file.init();
api.getUpdater().incrementTotalSize(file.getSize());
}
catch (final Exception e)
{
e.printStackTrace();
}
}
// Downloading packages
api.getUpdater().setState(State.DOWNLOADING);
api.getUpdater().setPercentage(10);
for (final GameFile file : api.getUpdater().getGameFiles())
{
api.getUpdater().setCurrentFile(file);
try
{
file.download(api);
}
catch (final Exception e)
{
e.printStackTrace();
}
}
api.getUpdater().setCurrentFile(null);
// Extracting packages
api.getUpdater().setState(State.EXTRACTING_PACKAGES);
api.getUpdater().setPercentage(55);
final int percentageStep = 20 / api.getUpdater().getGameFiles().size();
for (int i = 0; i < api.getUpdater().getGameFiles().size(); i++)
{
final GameFile file = api.getUpdater().getGameFiles().get(i);
api.getUpdater().setCurrentFile(file);
final int min = 55 + i * percentageStep;
final int max = 55 + (i + 1) * percentageStep;
file.extract(api, min, max);
}
api.getUpdater().setCurrentFile(null);
}
public static void determinePackages(LauncherAPI api)
{
api.getUpdater().setState(State.DETERMINING_PACKAGES);
api.getUpdater().setPercentage(5);
api.getUpdater().getGameFiles().clear();
File dest = null;
Type type = null;
try
{
// Load libraries URLs
dest = new File(api.getMinecraftDirectory(), "bin");
type = Type.LIBRARY;
for (final String librariesFile : api.getConfig().getStringList(
"updater.libraries"))
{
final URL url = new URL(librariesFile);
final GameFile file = new GameFile(url, dest, type);
api.getUpdater().getGameFiles().add(file);
}
// Load native URL
dest = new File(dest, "natives");
{
final URL url = new URL(api.getConfig().getString(
"updater.natives." + SystemUtils.getSystemOS().name()));
type = Type.NATIVE;
final GameFile file = new GameFile(url, dest, type);
api.getUpdater().getGameFiles().add(file);
}
// Load additionnals URLs
dest = new File(api.getMinecraftDirectory(), "bin");
type = Type.ADDITIONNAL;
for (final String additionnalFile : api.getConfig().getStringList(
"updater.additionnals"))
{
final URL url = new URL(additionnalFile);
final GameFile file = new GameFile(url, dest, type);
api.getUpdater().getGameFiles().add(file);
}
}
catch (final Exception e)
{
e.printStackTrace();
}
}
public static class GameFile
{
private final URL url;
private final File dest;
private final Type type;
private HttpURLConnection connection = null;
private float speed = 0;
private long downloaded = 0;
private long total = 0;
private int percentage = 0;
public GameFile(URL url, File dest, Type type) throws Exception
{
this.url = url;
this.dest = dest;
this.type = type;
dest.mkdirs();
}
public void init() throws Exception
{
connection = (HttpURLConnection) url.openConnection();
connection.setDefaultUseCaches(false);
total = connection.getContentLength();
}
public void download(LauncherAPI api) throws Exception
{
System.out.println("Downloading '" + getFileName() + "'...");
long lastTime = System.currentTimeMillis();
final InputStream in = connection.getInputStream();
final OutputStream out = new FileOutputStream(new File(dest,
getFileName()));
int instantDownload = 0;
int bufferSize;
final byte[] buffer = new byte[65536];
while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1)
{
out.write(buffer, 0, bufferSize);
downloaded += bufferSize;
api.getUpdater().incrementDownloaded(bufferSize);
instantDownload += bufferSize;
final long diff = System.currentTimeMillis() - lastTime;
if (diff >= 1000L)
{
speed = (int) (instantDownload / diff * 100.0f) / 100.0f;
instantDownload = 0;
lastTime += diff;
}
percentage = (int) (downloaded * 100 / total);
api.getUpdater().setPercentage(
(int) (10 + api.getUpdater().getDownloaded() * 45
/ api.getUpdater().getTotalSize()));
}
in.close();
out.close();
}
public void extract(LauncherAPI api, int min, int max)
{
System.out.println("Extracting '" + getFileName() + "'...");
if (type == Type.NATIVE || type == Type.ADDITIONNAL)
{
File dest = this.dest;
boolean recursive = true;
if (type == Type.ADDITIONNAL)
{
dest = api.getMinecraftDirectory();
recursive = false;
}
try
{
if (FileExtractor.extract(api, this, dest, min, max,
recursive))
{
}
}
catch (final Exception e)
{
e.printStackTrace();
}
}
}
public URL getUrl()
{
return url;
}
public File getDest()
{
return dest;
}
public Type getType()
{
return type;
}
public String getFileName()
{
return url.getPath().substring(url.getPath().lastIndexOf('/') + 1);
}
public float getSpeed()
{
return speed;
}
public long getSize()
{
return total;
}
public HttpURLConnection getConnection()
{
return connection;
}
public long getDownloaded()
{
return downloaded;
}
public long getTotal()
{
return total;
}
public int getPercentage()
{
return percentage;
}
public void setPercentage(int percentage)
{
this.percentage = percentage;
}
public File getFile()
{
return new File(dest, getFileName());
}
public String toString()
{
return getFileName();
}
}
public static enum Type
{
LIBRARY, NATIVE, ADDITIONNAL;
}
}