Search in sources :

Example 1 with Status

use of net.minecraftforge.fml.VersionChecker.Status in project MinecraftForge by MinecraftForge.

the class VersionChecker method startVersionCheck.

public static void startVersionCheck() {
    new Thread("Forge Version Check") {

        private HttpClient client;

        @Override
        public void run() {
            if (!FMLConfig.runVersionCheck()) {
                LOGGER.info("Global Forge version check system disabled, no further processing.");
                return;
            }
            client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(HTTP_TIMEOUT_SECS)).build();
            gatherMods().forEach(this::process);
        }

        /**
         * Returns the response body as a String for the given URL while following redirects
         */
        private String openUrlString(URL url) throws IOException, URISyntaxException, InterruptedException {
            URL currentUrl = url;
            for (int redirects = 0; redirects < MAX_HTTP_REDIRECTS; redirects++) {
                var request = HttpRequest.newBuilder().uri(currentUrl.toURI()).timeout(Duration.ofSeconds(HTTP_TIMEOUT_SECS)).setHeader("Accept-Encoding", "gzip").GET().build();
                final HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
                int responseCode = response.statusCode();
                if (responseCode >= 300 && responseCode <= 399) {
                    String newLocation = response.headers().firstValue("Location").orElseThrow(() -> new IOException("Got a 3xx response code but Location header was null while trying to fetch " + url));
                    currentUrl = new URL(currentUrl, newLocation);
                    continue;
                }
                final boolean isGzipEncoded = response.headers().firstValue("Content-Encoding").orElse("").equals("gzip");
                final String bodyStr;
                try (InputStream inStream = isGzipEncoded ? new GZIPInputStream(response.body()) : response.body()) {
                    try (var bufferedReader = new BufferedReader(new InputStreamReader(inStream))) {
                        bodyStr = bufferedReader.lines().collect(Collectors.joining("\n"));
                    }
                }
                return bodyStr;
            }
            throw new IOException("Too many redirects while trying to fetch " + url);
        }

        private void process(IModInfo mod) {
            Status status = PENDING;
            ComparableVersion target = null;
            Map<ComparableVersion, String> changes = null;
            String display_url = null;
            try {
                if (mod.getUpdateURL().isEmpty())
                    return;
                URL url = mod.getUpdateURL().get();
                LOGGER.info("[{}] Starting version check at {}", mod.getModId(), url.toString());
                String data = openUrlString(url);
                LOGGER.debug("[{}] Received version check data:\n{}", mod.getModId(), data);
                @SuppressWarnings("unchecked") Map<String, Object> json = new Gson().fromJson(data, Map.class);
                @SuppressWarnings("unchecked") Map<String, String> promos = (Map<String, String>) json.get("promos");
                display_url = (String) json.get("homepage");
                var mcVersion = FMLLoader.versionInfo().mcVersion();
                String rec = promos.get(mcVersion + "-recommended");
                String lat = promos.get(mcVersion + "-latest");
                ComparableVersion current = new ComparableVersion(mod.getVersion().toString());
                if (rec != null) {
                    ComparableVersion recommended = new ComparableVersion(rec);
                    int diff = recommended.compareTo(current);
                    if (diff == 0)
                        status = UP_TO_DATE;
                    else if (diff < 0) {
                        status = AHEAD;
                        if (lat != null) {
                            ComparableVersion latest = new ComparableVersion(lat);
                            if (current.compareTo(latest) < 0) {
                                status = OUTDATED;
                                target = latest;
                            }
                        }
                    } else {
                        status = OUTDATED;
                        target = recommended;
                    }
                } else if (lat != null) {
                    ComparableVersion latest = new ComparableVersion(lat);
                    if (current.compareTo(latest) < 0)
                        status = BETA_OUTDATED;
                    else
                        status = BETA;
                    target = latest;
                } else
                    status = BETA;
                LOGGER.info("[{}] Found status: {} Current: {} Target: {}", mod.getModId(), status, current, target);
                changes = new LinkedHashMap<>();
                @SuppressWarnings("unchecked") Map<String, String> tmp = (Map<String, String>) json.get(mcVersion);
                if (tmp != null) {
                    List<ComparableVersion> ordered = new ArrayList<>();
                    for (String key : tmp.keySet()) {
                        ComparableVersion ver = new ComparableVersion(key);
                        if (ver.compareTo(current) > 0 && (target == null || ver.compareTo(target) < 1)) {
                            ordered.add(ver);
                        }
                    }
                    Collections.sort(ordered);
                    for (ComparableVersion ver : ordered) {
                        changes.put(ver, tmp.get(ver.toString()));
                    }
                }
            } catch (Exception e) {
                LOGGER.warn("Failed to process update information", e);
                status = FAILED;
            }
            results.put(mod, new CheckResult(status, target, changes, display_url));
        }
    }.start();
}
Also used : Status(net.minecraftforge.fml.VersionChecker.Status) InputStreamReader(java.io.InputStreamReader) IModInfo(net.minecraftforge.forgespi.language.IModInfo) GZIPInputStream(java.util.zip.GZIPInputStream) InputStream(java.io.InputStream) HttpResponse(java.net.http.HttpResponse) Gson(com.google.gson.Gson) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) ComparableVersion(org.apache.maven.artifact.versioning.ComparableVersion) URL(java.net.URL) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) LinkedHashMap(java.util.LinkedHashMap) GZIPInputStream(java.util.zip.GZIPInputStream) HttpClient(java.net.http.HttpClient) BufferedReader(java.io.BufferedReader) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Aggregations

Gson (com.google.gson.Gson)1 BufferedReader (java.io.BufferedReader)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 URISyntaxException (java.net.URISyntaxException)1 URL (java.net.URL)1 HttpClient (java.net.http.HttpClient)1 HttpResponse (java.net.http.HttpResponse)1 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 GZIPInputStream (java.util.zip.GZIPInputStream)1 Status (net.minecraftforge.fml.VersionChecker.Status)1 IModInfo (net.minecraftforge.forgespi.language.IModInfo)1 ComparableVersion (org.apache.maven.artifact.versioning.ComparableVersion)1