diff --git a/.classpath b/.classpath index b9ad5b8a..c81123b9 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,7 @@ + diff --git a/src-devtools/amidst/devtools/MinecraftJarDownloadAvailabilityChecker.java b/src-devtools/amidst/devtools/MinecraftJarDownloadAvailabilityChecker.java new file mode 100644 index 00000000..03e0718b --- /dev/null +++ b/src-devtools/amidst/devtools/MinecraftJarDownloadAvailabilityChecker.java @@ -0,0 +1,33 @@ +package amidst.devtools; + +import java.io.IOException; + +import amidst.devtools.mojangapi.Version; +import amidst.devtools.mojangapi.Versions; +import amidst.devtools.utils.VersionStateRenderer; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; + +public class MinecraftJarDownloadAvailabilityChecker { + public static void main(String[] args) throws JsonSyntaxException, + JsonIOException, IOException { + new MinecraftJarDownloadAvailabilityChecker(Versions.retrieve()) + .displayDownloadAvailability(); + } + + private VersionStateRenderer renderer = new VersionStateRenderer(); + private Versions versions; + + public MinecraftJarDownloadAvailabilityChecker(Versions versions) { + this.versions = versions; + } + + public void displayDownloadAvailability() { + for (Version version : versions.getVersions()) { + boolean hasServer = version.hasServer(); + boolean hasClient = version.hasClient(); + System.out.println(renderer.render(version, hasServer, hasClient)); + } + } +} diff --git a/src-devtools/amidst/devtools/MinecraftJarDownloader.java b/src-devtools/amidst/devtools/MinecraftJarDownloader.java new file mode 100644 index 00000000..ee87e326 --- /dev/null +++ b/src-devtools/amidst/devtools/MinecraftJarDownloader.java @@ -0,0 +1,37 @@ +package amidst.devtools; + +import java.io.IOException; + +import amidst.devtools.mojangapi.Version; +import amidst.devtools.mojangapi.Versions; +import amidst.devtools.settings.DevToolsSettings; +import amidst.devtools.utils.VersionStateRenderer; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; + +public class MinecraftJarDownloader { + public static void main(String[] args) throws JsonSyntaxException, + JsonIOException, IOException { + new MinecraftJarDownloader( + DevToolsSettings.INSTANCE.getMinecraftVersionsDirectory(), + Versions.retrieve()).downloadAll(); + } + + private VersionStateRenderer renderer = new VersionStateRenderer(); + private String basePath; + private Versions versions; + + public MinecraftJarDownloader(String basePath, Versions versions) { + this.basePath = basePath; + this.versions = versions; + } + + public void downloadAll() { + for (Version version : versions.getVersions()) { + boolean hasServer = version.tryDownloadServer(basePath); + boolean hasClient = version.tryDownloadClient(basePath); + System.out.println(renderer.render(version, hasServer, hasClient)); + } + } +} diff --git a/src-devtools/amidst/devtools/MinecraftVersionCompatibilityChecker.java b/src-devtools/amidst/devtools/MinecraftVersionCompatibilityChecker.java new file mode 100644 index 00000000..0df9045a --- /dev/null +++ b/src-devtools/amidst/devtools/MinecraftVersionCompatibilityChecker.java @@ -0,0 +1,78 @@ +package amidst.devtools; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import amidst.Util; +import amidst.clazz.Classes; +import amidst.clazz.translator.ClassTranslator; +import amidst.devtools.mojangapi.Version; +import amidst.devtools.mojangapi.Versions; +import amidst.devtools.settings.DevToolsSettings; +import amidst.minecraft.local.LocalMinecraftInterfaceBuilder; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; + +public class MinecraftVersionCompatibilityChecker { + public static void main(String[] args) throws JsonSyntaxException, + JsonIOException, IOException { + new MinecraftVersionCompatibilityChecker( + DevToolsSettings.INSTANCE.getMinecraftVersionsDirectory(), + Versions.retrieve()).checkAll(); + } + + private String basePath; + private Versions versions; + + public MinecraftVersionCompatibilityChecker(String basePath, + Versions versions) { + this.basePath = basePath; + this.versions = versions; + } + + public void checkAll() { + initCreepyStuff(); + List successful = new ArrayList(); + List failed = new ArrayList(); + for (Version version : versions.getVersions()) { + if (checkOne(version)) { + successful.add(version); + } else { + failed.add(version); + } + } + displayVersionList(successful, + "================ SUCCESSFUL VERSIONS ============"); + displayVersionList(failed, + "================ FAILED VERSIONS ================"); + } + + private void initCreepyStuff() { + Util.setMinecraftDirectory(); + Util.setMinecraftLibraries(); + } + + private boolean checkOne(Version version) { + if (version.tryDownloadClient(basePath)) { + try { + File jarFile = version.getLocalClientJarPath(basePath).toFile(); + ClassTranslator translator = LocalMinecraftInterfaceBuilder.StatelessResources.INSTANCE.classTranslator; + return Classes.ensureExactlyOneMatches(jarFile, translator); + } catch (Exception e) { + e.printStackTrace(); + } + } + return false; + } + + private void displayVersionList(List versionList, String message) { + System.out.println(); + System.out.println(message); + for (Version version : versionList) { + System.out.println(version.getId()); + } + } +} diff --git a/src-devtools/amidst/devtools/mojangapi/Latest.java b/src-devtools/amidst/devtools/mojangapi/Latest.java new file mode 100644 index 00000000..6e1d6a3e --- /dev/null +++ b/src-devtools/amidst/devtools/mojangapi/Latest.java @@ -0,0 +1,14 @@ +package amidst.devtools.mojangapi; + +public class Latest { + private String snapshot; + private String release; + + public String getSnapshot() { + return snapshot; + } + + public String getRelease() { + return release; + } +} diff --git a/src-devtools/amidst/devtools/mojangapi/Version.java b/src-devtools/amidst/devtools/mojangapi/Version.java new file mode 100644 index 00000000..a1613979 --- /dev/null +++ b/src-devtools/amidst/devtools/mojangapi/Version.java @@ -0,0 +1,156 @@ +package amidst.devtools.mojangapi; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import amidst.utilties.URIUtils; + +public class Version { + private static enum StatelessResources { + INSTANCE; + + private char defaultTypeChar = 'N'; + private Map typeCharMap = createTypeCharMap(); + + private Map createTypeCharMap() { + HashMap result = new HashMap(); + result.put("snapshot", 'S'); + result.put("release", 'R'); + result.put("old_beta", 'B'); + result.put("old_alpha", 'A'); + return result; + } + + private char getTypeChar(String type) { + if (typeCharMap.containsKey(type)) { + return typeCharMap.get(type); + } else { + return defaultTypeChar; + } + } + } + + private static final String DOWNLOAD_URL_PREFIX = "https://s3.amazonaws.com/Minecraft.Download/versions/"; + private static final String DOWNLOAD_URL_MIDDLE_SERVER = "/minecraft_server."; + private static final String DOWNLOAD_URL_MIDDLE_CLIENT = "/"; + private static final String JAR_FILE_EXTENSION = ".jar"; + private static final String JSON_FILE_EXTENSION = ".json"; + + private String id; + private String type; + + public String getId() { + return id; + } + + public String getType() { + return type; + } + + public char getTypeChar() { + return StatelessResources.INSTANCE.getTypeChar(type); + } + + private String getServerLocation(String fileExtension) { + return DOWNLOAD_URL_PREFIX + id + DOWNLOAD_URL_MIDDLE_SERVER + id + + fileExtension; + } + + private String getClientLocation(String fileExtension) { + return DOWNLOAD_URL_PREFIX + id + DOWNLOAD_URL_MIDDLE_CLIENT + id + + fileExtension; + } + + public String getServerJarLocation() { + return getServerLocation(JAR_FILE_EXTENSION); + } + + public String getClientJarLocation() { + return getClientLocation(JAR_FILE_EXTENSION); + } + + public URI getServerJarURI() { + return URIUtils.newURI(getServerJarLocation()); + } + + public URI getClientJarURI() { + return URIUtils.newURI(getClientJarLocation()); + } + + public URL getServerJarURL() throws MalformedURLException { + return URIUtils.newURL(getServerJarLocation()); + } + + public URL getClientJarURL() throws MalformedURLException { + return URIUtils.newURL(getClientJarLocation()); + } + + public String getClientJsonLocation() { + return getClientLocation(JSON_FILE_EXTENSION); + } + + public URI getClientJsonURI() { + return URIUtils.newURI(getClientJsonLocation()); + } + + public URL getClientJsonURL() throws MalformedURLException { + return URIUtils.newURL(getClientJsonLocation()); + } + + public boolean hasServer() { + return URIUtils.exists(getServerJarLocation()); + } + + public boolean hasClient() { + return URIUtils.exists(getClientJarLocation()); + } + + public void downloadServer(String basePath) throws MalformedURLException, + IOException { + URIUtils.download(getServerJarURL(), getLocalServerJarPath(basePath)); + } + + public void downloadClient(String basePath) throws MalformedURLException, + IOException { + URIUtils.download(getClientJarURL(), getLocalClientJarPath(basePath)); + URIUtils.download(getClientJsonURL(), getLocalClientJsonPath(basePath)); + } + + public boolean tryDownloadServer(String basePath) { + try { + downloadServer(basePath); + return true; + } catch (MalformedURLException e) { + } catch (IOException e) { + } + return false; + } + + public boolean tryDownloadClient(String basePath) { + try { + downloadClient(basePath); + return true; + } catch (MalformedURLException e) { + } catch (IOException e) { + } + return false; + } + + public Path getLocalServerJarPath(String basePath) { + return Paths.get(basePath, "server", id + JAR_FILE_EXTENSION); + } + + public Path getLocalClientJarPath(String basePath) { + return Paths.get(basePath, "client", id + JAR_FILE_EXTENSION); + } + + public Path getLocalClientJsonPath(String basePath) { + return Paths.get(basePath, "client", id + JSON_FILE_EXTENSION); + } +} diff --git a/src-devtools/amidst/devtools/mojangapi/Versions.java b/src-devtools/amidst/devtools/mojangapi/Versions.java new file mode 100644 index 00000000..664d4a64 --- /dev/null +++ b/src-devtools/amidst/devtools/mojangapi/Versions.java @@ -0,0 +1,31 @@ +package amidst.devtools.mojangapi; + +import java.io.IOException; +import java.util.List; + +import amidst.utilties.URIUtils; + +import com.google.gson.Gson; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; + +public class Versions { + private static final Gson GSON = new Gson(); + private static final String VERSIONS_URL = "https://s3.amazonaws.com/Minecraft.Download/versions/versions.json"; + + public static Versions retrieve() throws JsonSyntaxException, + JsonIOException, IOException { + return GSON.fromJson(URIUtils.newReader(VERSIONS_URL), Versions.class); + } + + private Latest latest; + private List versions; + + public Latest getLatest() { + return latest; + } + + public List getVersions() { + return versions; + } +} diff --git a/src-devtools/amidst/devtools/settings/DevToolsSettings.java b/src-devtools/amidst/devtools/settings/DevToolsSettings.java new file mode 100644 index 00000000..41a5a9fe --- /dev/null +++ b/src-devtools/amidst/devtools/settings/DevToolsSettings.java @@ -0,0 +1,11 @@ +package amidst.devtools.settings; + +public enum DevToolsSettings { + INSTANCE; + + private String minecraftVersionsDirectory = "/tmp/mc/"; + + public String getMinecraftVersionsDirectory() { + return minecraftVersionsDirectory; + } +} diff --git a/src-devtools/amidst/devtools/utils/VersionStateRenderer.java b/src-devtools/amidst/devtools/utils/VersionStateRenderer.java new file mode 100644 index 00000000..a29959af --- /dev/null +++ b/src-devtools/amidst/devtools/utils/VersionStateRenderer.java @@ -0,0 +1,18 @@ +package amidst.devtools.utils; + +import amidst.devtools.mojangapi.Version; + +public class VersionStateRenderer { + public String render(Version version, boolean hasServer, boolean hasClient) { + return toBox(hasServer, 'S') + " " + toBox(hasClient, 'C') + " " + + version.getTypeChar() + " " + version.getId(); + } + + private String toBox(boolean value, char c) { + if (value) { + return "[" + c + "]"; + } else { + return "[ ]"; + } + } +} diff --git a/src/amidst/utilties/URIUtils.java b/src/amidst/utilties/URIUtils.java new file mode 100644 index 00000000..6d0a41df --- /dev/null +++ b/src/amidst/utilties/URIUtils.java @@ -0,0 +1,64 @@ +package amidst.utilties; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +public enum URIUtils { + ; + + public static URI newURI(String location) { + return URI.create(location); + } + + public static URL newURL(String location) throws MalformedURLException { + return URI.create(location).toURL(); + } + + public static BufferedReader newReader(String location) throws IOException { + return newReader(newURL(location)); + } + + public static BufferedReader newReader(URL url) throws IOException { + return new BufferedReader(new InputStreamReader(url.openStream())); + } + + public static boolean exists(String location) { + try { + return exists(newURL(location)); + } catch (MalformedURLException e) { + return false; + } + } + + public static boolean exists(URL url) { + try { + HttpURLConnection connection = (HttpURLConnection) url + .openConnection(); + connection.setRequestMethod("HEAD"); + return connection.getResponseCode() == HttpURLConnection.HTTP_OK; + } catch (IOException e) { + return false; + } + } + + public static void download(URL from, Path to) throws IOException { + to.getParent().toFile().mkdirs(); + if (to.toFile().exists()) { + return; + } + Path part = Paths.get(to.toString() + ".part"); + InputStream in = from.openStream(); + Files.copy(in, part, StandardCopyOption.REPLACE_EXISTING); + Files.move(part, to, StandardCopyOption.REPLACE_EXISTING); + } +}