diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java deleted file mode 100644 index 0032ed5cf..000000000 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ /dev/null @@ -1,618 +0,0 @@ -package codechicken.core.launch; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import cpw.mods.fml.common.versioning.ComparableVersion; -import cpw.mods.fml.relauncher.FMLInjectionData; -import cpw.mods.fml.relauncher.FMLLaunchHandler; -import cpw.mods.fml.relauncher.IFMLCallHook; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import net.minecraft.launchwrapper.LaunchClassLoader; -import sun.misc.URLClassPath; -import sun.net.util.URLUtil; - -import javax.swing.*; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; -import java.awt.*; -import java.awt.Dialog.ModalityType; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.*; -import java.lang.reflect.Field; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * For autodownloading stuff. - * This is really unoriginal, mostly ripped off FML, credits to cpw. - */ -public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { - private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); - private static final String owner = "CB's DepLoader"; - private static DepLoadInst inst; - - public interface IDownloadDisplay { - void resetProgress(int sizeGuess); - - void setPokeThread(Thread currentThread); - - void updateProgress(int fullLength); - - boolean shouldStopIt(); - - void updateProgressString(String string, Object... data); - - Object makeDialog(); - - void showErrorDialog(String name, String url); - } - - @SuppressWarnings("serial") - public static class Downloader extends JOptionPane implements IDownloadDisplay { - private JDialog container; - private JLabel currentActivity; - private JProgressBar progress; - boolean stopIt; - Thread pokeThread; - - private Box makeProgressPanel() { - Box box = Box.createVerticalBox(); - box.add(Box.createRigidArea(new Dimension(0, 10))); - JLabel welcomeLabel = new JLabel("" + owner + " is setting up your minecraft environment"); - box.add(welcomeLabel); - welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); - welcomeLabel = new JLabel("Please wait, " + owner + " has some tasks to do before you can play"); - welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); - box.add(welcomeLabel); - box.add(Box.createRigidArea(new Dimension(0, 10))); - currentActivity = new JLabel("Currently doing ..."); - box.add(currentActivity); - box.add(Box.createRigidArea(new Dimension(0, 10))); - progress = new JProgressBar(0, 100); - progress.setStringPainted(true); - box.add(progress); - box.add(Box.createRigidArea(new Dimension(0, 30))); - return box; - } - - @Override - public JDialog makeDialog() { - if (container != null) - return container; - - setMessageType(JOptionPane.INFORMATION_MESSAGE); - setMessage(makeProgressPanel()); - setOptions(new Object[]{"Stop"}); - addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getSource() == Downloader.this && evt.getPropertyName() == VALUE_PROPERTY) { - requestClose("This will stop minecraft from launching\nAre you sure you want to do this?"); - } - } - }); - container = new JDialog(null, "Hello", ModalityType.MODELESS); - container.setResizable(false); - container.setLocationRelativeTo(null); - container.add(this); - this.updateUI(); - container.pack(); - container.setMinimumSize(container.getPreferredSize()); - container.setVisible(true); - container.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - container.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - requestClose("Closing this window will stop minecraft from launching\nAre you sure you wish to do this?"); - } - }); - return container; - } - - protected void requestClose(String message) { - int shouldClose = JOptionPane.showConfirmDialog(container, message, "Are you sure you want to stop?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); - if (shouldClose == JOptionPane.YES_OPTION) - container.dispose(); - - stopIt = true; - if (pokeThread != null) - pokeThread.interrupt(); - } - - @Override - public void updateProgressString(String progressUpdate, Object... data) { - //FMLLog.finest(progressUpdate, data); - if (currentActivity != null) - currentActivity.setText(String.format(progressUpdate, data)); - } - - @Override - public void resetProgress(int sizeGuess) { - if (progress != null) - progress.getModel().setRangeProperties(0, 0, 0, sizeGuess, false); - } - - @Override - public void updateProgress(int fullLength) { - if (progress != null) - progress.getModel().setValue(fullLength); - } - - @Override - public void setPokeThread(Thread currentThread) { - this.pokeThread = currentThread; - } - - @Override - public boolean shouldStopIt() { - return stopIt; - } - - @Override - public void showErrorDialog(String name, String url) { - JEditorPane ep = new JEditorPane("text/html", - "" + - owner + " was unable to download required library " + name + - "
Check your internet connection and try restarting or download it manually from" + - "
" + url + " and put it in your mods folder" + - ""); - - ep.setEditable(false); - ep.setOpaque(false); - ep.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent event) { - try { - if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) - Desktop.getDesktop().browse(event.getURL().toURI()); - } catch (Exception e) { - } - } - }); - - JOptionPane.showMessageDialog(null, ep, "A download error has occured", JOptionPane.ERROR_MESSAGE); - } - } - - public static class DummyDownloader implements IDownloadDisplay { - @Override - public void resetProgress(int sizeGuess) { - } - - @Override - public void setPokeThread(Thread currentThread) { - } - - @Override - public void updateProgress(int fullLength) { - } - - @Override - public boolean shouldStopIt() { - return false; - } - - @Override - public void updateProgressString(String string, Object... data) { - } - - @Override - public Object makeDialog() { - return null; - } - - @Override - public void showErrorDialog(String name, String url) { - } - } - - public static class VersionedFile - { - public final Pattern pattern; - public final String filename; - public final ComparableVersion version; - public final String name; - - public VersionedFile(String filename, Pattern pattern) { - this.pattern = pattern; - this.filename = filename; - Matcher m = pattern.matcher(filename); - if(m.matches()) { - name = m.group(1); - version = new ComparableVersion(m.group(2)); - } - else { - name = null; - version = null; - } - } - - public boolean matches() { - return name != null; - } - } - - public static class Dependency - { - public String url; - public VersionedFile file; - - public String existing; - /** - * Flag set to add this dep to the classpath immediately because it is required for a coremod. - */ - public boolean coreLib; - - public Dependency(String url, VersionedFile file, boolean coreLib) { - this.url = url; - this.file = file; - this.coreLib = coreLib; - } - } - - public static class DepLoadInst { - private File modsDir; - private File v_modsDir; - private IDownloadDisplay downloadMonitor; - private JDialog popupWindow; - - private Map depMap = new HashMap(); - private HashSet depSet = new HashSet(); - - public DepLoadInst() { - String mcVer = (String) FMLInjectionData.data()[4]; - File mcDir = (File) FMLInjectionData.data()[6]; - - modsDir = new File(mcDir, "mods"); - v_modsDir = new File(mcDir, "mods/" + mcVer); - if (!v_modsDir.exists()) - v_modsDir.mkdirs(); - } - - private void addClasspath(String name) { - try { - ((LaunchClassLoader) DepLoader.class.getClassLoader()).addURL(new File(v_modsDir, name).toURI().toURL()); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - - private void deleteMod(File mod) { - if (mod.delete()) - return; - - try { - ClassLoader cl = DepLoader.class.getClassLoader(); - URL url = mod.toURI().toURL(); - Field f_ucp = URLClassLoader.class.getDeclaredField("ucp"); - Field f_loaders = URLClassPath.class.getDeclaredField("loaders"); - Field f_lmap = URLClassPath.class.getDeclaredField("lmap"); - f_ucp.setAccessible(true); - f_loaders.setAccessible(true); - f_lmap.setAccessible(true); - - URLClassPath ucp = (URLClassPath) f_ucp.get(cl); - Closeable loader = ((Map) f_lmap.get(ucp)).remove(URLUtil.urlNoFragString(url)); - if (loader != null) { - loader.close(); - ((List) f_loaders.get(ucp)).remove(loader); - } - } catch (Exception e) { - e.printStackTrace(); - } - - if (!mod.delete()) { - mod.deleteOnExit(); - String msg = owner + " was unable to delete file " + mod.getPath() + " the game will now try to delete it on exit. If this dialog appears again, delete it manually."; - System.err.println(msg); - if (!GraphicsEnvironment.isHeadless()) - JOptionPane.showMessageDialog(null, msg, "An update error has occured", JOptionPane.ERROR_MESSAGE); - - System.exit(1); - } - } - - private void download(Dependency dep) { - popupWindow = (JDialog) downloadMonitor.makeDialog(); - File libFile = new File(v_modsDir, dep.file.filename); - try { - URL libDownload = new URL(dep.url + '/' + dep.file.filename); - downloadMonitor.updateProgressString("Downloading file %s", libDownload.toString()); - System.out.format("Downloading file %s\n", libDownload.toString()); - URLConnection connection = libDownload.openConnection(); - connection.setConnectTimeout(5000); - connection.setReadTimeout(5000); - connection.setRequestProperty("User-Agent", "" + owner + " Downloader"); - int sizeGuess = connection.getContentLength(); - download(connection.getInputStream(), sizeGuess, libFile); - downloadMonitor.updateProgressString("Download complete"); - System.out.println("Download complete"); - - scanDepInfo(libFile); - } catch (Exception e) { - libFile.delete(); - if (downloadMonitor.shouldStopIt()) { - System.err.println("You have stopped the downloading operation before it could complete"); - System.exit(1); - return; - } - downloadMonitor.showErrorDialog(dep.file.filename, dep.url + '/' + dep.file.filename); - throw new RuntimeException("A download error occured", e); - } - } - - private void download(InputStream is, int sizeGuess, File target) throws Exception { - if (sizeGuess > downloadBuffer.capacity()) - throw new Exception(String.format("The file %s is too large to be downloaded by " + owner + " - the download is invalid", target.getName())); - - downloadBuffer.clear(); - - int bytesRead, fullLength = 0; - - downloadMonitor.resetProgress(sizeGuess); - try { - downloadMonitor.setPokeThread(Thread.currentThread()); - byte[] smallBuffer = new byte[1024]; - while ((bytesRead = is.read(smallBuffer)) >= 0) { - downloadBuffer.put(smallBuffer, 0, bytesRead); - fullLength += bytesRead; - if (downloadMonitor.shouldStopIt()) { - break; - } - downloadMonitor.updateProgress(fullLength); - } - is.close(); - downloadMonitor.setPokeThread(null); - downloadBuffer.limit(fullLength); - downloadBuffer.position(0); - } catch (InterruptedIOException e) { - // We were interrupted by the stop button. We're stopping now.. clear interruption flag. - Thread.interrupted(); - throw new Exception("Stop"); - } catch (IOException e) { - throw e; - } - - try { - /*String cksum = generateChecksum(downloadBuffer); - if (cksum.equals(validationHash)) - {*/ - if (!target.exists()) - target.createNewFile(); - - - downloadBuffer.position(0); - FileOutputStream fos = new FileOutputStream(target); - fos.getChannel().write(downloadBuffer); - fos.close(); - /*} - else - { - throw new RuntimeException(String.format("The downloaded file %s has an invalid checksum %s (expecting %s). The download did not succeed correctly and the file has been deleted. Please try launching again.", target.getName(), cksum, validationHash)); - }*/ - } catch (Exception e) { - throw e; - } - } - - private String checkExisting(Dependency dep) { - for (File f : modsDir.listFiles()) { - VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); - if (!vfile.matches() || !vfile.name.equals(dep.file.name)) - continue; - - if (f.renameTo(new File(v_modsDir, f.getName()))) - continue; - - deleteMod(f); - } - - for (File f : v_modsDir.listFiles()) { - VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); - if (!vfile.matches() || !vfile.name.equals(dep.file.name)) - continue; - - int cmp = vfile.version.compareTo(dep.file.version); - if (cmp < 0) { - System.out.println("Deleted old version " + f.getName()); - deleteMod(f); - return null; - } - if (cmp > 0) { - System.err.println("Warning: version of " + dep.file.name + ", " + vfile.version + " is newer than request " + dep.file.version); - return f.getName(); - } - return f.getName();//found dependency - } - return null; - } - - public void load() { - scanDepInfos(); - if (depMap.isEmpty()) - return; - - loadDeps(); - activateDeps(); - } - - private void activateDeps() { - for (Dependency dep : depMap.values()) - if (dep.coreLib) - addClasspath(dep.existing); - } - - private void loadDeps() { - downloadMonitor = FMLLaunchHandler.side().isClient() ? new Downloader() : new DummyDownloader(); - try { - while (!depSet.isEmpty()) { - Iterator it = depSet.iterator(); - Dependency dep = depMap.get(it.next()); - it.remove(); - load(dep); - } - } finally { - if (popupWindow != null) { - popupWindow.setVisible(false); - popupWindow.dispose(); - } - } - } - - private void load(Dependency dep) { - dep.existing = checkExisting(dep); - if (dep.existing == null)//download dep - { - download(dep); - dep.existing = dep.file.filename; - } - } - - private List modFiles() { - List list = new LinkedList(); - list.addAll(Arrays.asList(modsDir.listFiles())); - list.addAll(Arrays.asList(v_modsDir.listFiles())); - return list; - } - - private void scanDepInfos() { - for (File file : modFiles()) { - if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) - continue; - - scanDepInfo(file); - } - } - - private void scanDepInfo(File file) { - try { - ZipFile zip = new ZipFile(file); - ZipEntry e = zip.getEntry("dependancies.info"); - if (e == null) e = zip.getEntry("dependencies.info"); - if (e != null) - loadJSon(zip.getInputStream(e)); - zip.close(); - } catch (Exception e) { - System.err.println("Failed to load dependencies.info from " + file.getName() + " as JSON"); - e.printStackTrace(); - } - } - - private void loadJSon(InputStream input) throws IOException { - InputStreamReader reader = new InputStreamReader(input); - JsonElement root = new JsonParser().parse(reader); - if (root.isJsonArray()) - loadJSonArr(root); - else - loadJson(root.getAsJsonObject()); - reader.close(); - } - - private void loadJSonArr(JsonElement root) throws IOException { - for (JsonElement node : root.getAsJsonArray()) - loadJson(node.getAsJsonObject()); - } - - private void loadJson(JsonObject node) throws IOException { - boolean obfuscated = ((LaunchClassLoader) DepLoader.class.getClassLoader()) - .getClassBytes("net.minecraft.world.World") == null; - - String testClass = node.get("class").getAsString(); - if (DepLoader.class.getResource("/" + testClass.replace('.', '/') + ".class") != null) - return; - - String repo = node.get("repo").getAsString(); - String filename = node.get("file").getAsString(); - if (!obfuscated && node.has("dev")) - filename = node.get("dev").getAsString(); - - boolean coreLib = node.has("coreLib") && node.get("coreLib").getAsBoolean(); - - Pattern pattern = null; - try { - if(node.has("pattern")) - pattern = Pattern.compile(node.get("pattern").getAsString()); - } catch (PatternSyntaxException e) { - System.err.println("Invalid filename pattern: "+node.get("pattern")); - e.printStackTrace(); - } - if(pattern == null) - pattern = Pattern.compile("(\\w+).*?([\\d\\.]+)[-\\w]*\\.[^\\d]+"); - - VersionedFile file = new VersionedFile(filename, pattern); - if (!file.matches()) - throw new RuntimeException("Invalid filename format for dependency: " + filename); - - addDep(new Dependency(repo, file, coreLib)); - } - - private void addDep(Dependency newDep) { - if (mergeNew(depMap.get(newDep.file.name), newDep)) { - depMap.put(newDep.file.name, newDep); - depSet.add(newDep.file.name); - } - } - - private boolean mergeNew(Dependency oldDep, Dependency newDep) { - if (oldDep == null) - return true; - - Dependency newest = newDep.file.version.compareTo(oldDep.file.version) > 0 ? newDep : oldDep; - newest.coreLib = newDep.coreLib || oldDep.coreLib; - - return newest == newDep; - } - } - - public static void load() { - if (inst == null) { - inst = new DepLoadInst(); - inst.load(); - } - } - - @Override - public String[] getASMTransformerClass() { - return null; - } - - @Override - public String getModContainerClass() { - return null; - } - - @Override - public String getSetupClass() { - return getClass().getName(); - } - - @Override - public void injectData(Map data) { - } - - @Override - public Void call() { - load(); - - return null; - } - - @Override - public String getAccessTransformerClass() { - return null; - } -}