Explorar o código

Update Checker (#25)

* WIP Update Checker (Not working)

* Pushed this for testing

* Working as intended
Daniel She %!s(int64=6) %!d(string=hai) anos
pai
achega
555a4979f4

+ 1 - 1
build.gradle

@@ -6,7 +6,7 @@ sourceCompatibility = 1.8
 targetCompatibility = 1.8
 
 archivesBaseName = "RoughlyEnoughItems"
-version = "2.2.0.47"
+version = "2.2.0.48"
 
 def minecraftVersion = "19w04b"
 def yarnVersion = "19w04b.5"

+ 5 - 0
src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java

@@ -7,6 +7,7 @@ import me.shedaniel.rei.client.ConfigHelper;
 import me.shedaniel.rei.client.GuiHelper;
 import me.shedaniel.rei.client.RecipeHelper;
 import me.shedaniel.rei.plugin.DefaultPlugin;
+import me.shedaniel.rei.update.UpdateChecker;
 import net.fabricmc.api.ClientModInitializer;
 import net.fabricmc.api.ModInitializer;
 import net.fabricmc.api.loader.Loader;
@@ -75,6 +76,10 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer, ModInitiali
         configHelper = new ConfigHelper();
         
         ClientTickEvent.CLIENT.register(GuiHelper::onTick);
+        if (getConfigHelper().checkUpdates())
+            ClientTickEvent.CLIENT.register(UpdateChecker::onTick);
+        
+        new UpdateChecker().onInitializeClient();
     }
     
     @Override

+ 4 - 0
src/main/java/me/shedaniel/rei/client/ConfigHelper.java

@@ -103,4 +103,8 @@ public class ConfigHelper {
         config.sideSearchField = sideSearchField;
     }
     
+    public boolean checkUpdates() {
+        return config.checkUpdates;
+    }
+    
 }

+ 1 - 0
src/main/java/me/shedaniel/rei/client/REIConfig.java

@@ -12,5 +12,6 @@ public class REIConfig {
     public boolean enableCraftableOnlyButton = true;
     public boolean sideSearchField = false;
     public String giveCommandPrefix = "/give";
+    public boolean checkUpdates = true;
     
 }

+ 202 - 0
src/main/java/me/shedaniel/rei/update/UpdateChecker.java

@@ -0,0 +1,202 @@
+package me.shedaniel.rei.update;
+
+import com.google.common.collect.Lists;
+import com.google.gson.*;
+import com.google.gson.annotations.SerializedName;
+import me.shedaniel.rei.RoughlyEnoughItemsCore;
+import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.loader.FabricLoader;
+import net.fabricmc.loader.ModContainer;
+import net.minecraft.SharedConstants;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.resource.language.I18n;
+import net.minecraft.text.StringTextComponent;
+import net.minecraft.world.World;
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringBufferInputStream;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class UpdateChecker implements ClientModInitializer {
+    
+    private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
+    private static Version currentVersion = null, latestForGame = null;
+    private static JsonVersionElement element;
+    private static World lastWorld = null;
+    private static String VERSION_STRING = "https://raw.githubusercontent.com/shedaniel/RoughlyEnoughItems/1.14/version.json";
+    
+    public static boolean isOutdated() {
+        return latestForGame.compareTo(currentVersion) == 1 && currentVersion != null;
+    }
+    
+    public static UpdatePriority getUpdatePriority(List<Version> versions) {
+        UpdatePriority p = UpdatePriority.NONE;
+        List<UpdatePriority> priorities = Arrays.asList(UpdatePriority.values());
+        for(UpdatePriority priority : versions.stream().map(UpdateChecker::getUpdatePriority).collect(Collectors.toList()))
+            if (priority.compareTo(p) > 0)
+                p = priority;
+        return p;
+    }
+    
+    public static UpdatePriority getUpdatePriority(Version version) {
+        JsonArray array = element.getChangelogs().getFabric();
+        for(JsonElement element : array) {
+            JsonObject jsonObject = element.getAsJsonObject();
+            if (jsonObject.has("version") && jsonObject.get("version").getAsString().equals(version.toString()))
+                return UpdatePriority.fromString(jsonObject.get("level").getAsString());
+        }
+        return UpdatePriority.NONE;
+    }
+    
+    public static boolean checkUpdates() {
+        return RoughlyEnoughItemsCore.getConfigHelper().checkUpdates();
+    }
+    
+    public static List<String> getChangelog(Version currentVersion) {
+        List<String> changelogs = Lists.newLinkedList();
+        JsonArray array = element.getChangelogs().getFabric();
+        array.forEach(jsonElement -> {
+            JsonObject jsonObject = jsonElement.getAsJsonObject();
+            Version jsonVersion = new Version(jsonObject.get("version").getAsString());
+            if (jsonVersion.compareTo(currentVersion) > 0 && jsonVersion.compareTo(latestForGame) <= 0)
+                changelogs.add(I18n.translate("text.rei.update_changelog_line", jsonObject.get("text").getAsString()));
+        });
+        return changelogs;
+    }
+    
+    public static Version getCurrentVersion() {
+        return currentVersion;
+    }
+    
+    public static Version getLatestForGame() {
+        return latestForGame;
+    }
+    
+    public static void onTick(MinecraftClient client) {
+        if (client.world != lastWorld) {
+            lastWorld = client.world;
+            if (lastWorld != null) {
+                if (checkUpdates() && isOutdated()) {
+                    String currentVersionString = getCurrentVersion() == null ? "null" : getCurrentVersion().toString();
+                    List<Version> versions = getVersionsHigherThan(currentVersion);
+                    String t[] = I18n.translate("text.rei.update_outdated", currentVersionString, getLatestForGame(), getUpdatePriority(versions).name().toUpperCase()).split("\n");
+                    for(String s : t)
+                        client.player.addChatMessage(new StringTextComponent(s), false);
+                    getChangelog(currentVersion).forEach(s -> client.player.addChatMessage(new StringTextComponent(s), false));
+                }
+            }
+        }
+    }
+    
+    private static List<Version> getVersionsHigherThan(Version currentVersion) {
+        List<Version> versions = Lists.newLinkedList();
+        JsonArray array = element.getChangelogs().getFabric();
+        array.forEach(jsonElement -> {
+            Version jsonVersion = new Version(jsonElement.getAsJsonObject().get("version").getAsString());
+            if (jsonVersion.compareTo(currentVersion) > 0)
+                versions.add(jsonVersion);
+        });
+        return versions;
+    }
+    
+    @Override
+    public void onInitializeClient() {
+        if (!checkUpdates())
+            return;
+        FabricLoader.INSTANCE.getMods().stream().map(ModContainer::getInfo).forEach(modInfo -> {
+            if (modInfo.getId().equals("roughlyenoughitems"))
+                try {
+                    currentVersion = new Version(modInfo.getVersionString());
+                } catch (Exception e) {
+                }
+        });
+        InputStream downloadedStream = downloadVersionString();
+        String downloadedString = null;
+        try {
+            downloadedString = IOUtils.toString(downloadedStream, StandardCharsets.UTF_8);
+            element = GSON.fromJson(downloadedString, JsonVersionElement.class);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        if (downloadedString != null && !downloadedString.equalsIgnoreCase("{}"))
+            latestForGame = new Version(parseLatest(element, SharedConstants.getGameVersion().getName()));
+        else latestForGame = new Version("0.0.0");
+    }
+    
+    private InputStream downloadVersionString() {
+        try {
+            URL versionUrl = new URL(VERSION_STRING);
+            return versionUrl.openStream();
+        } catch (IOException e) {
+            return new StringBufferInputStream("{}");
+        }
+    }
+    
+    private String parseLatest(JsonVersionElement element, String gameVersion) {
+        List<LatestVersionObject> objects = new LinkedList<>(element.getLatestVersions());
+        for(int i = objects.size() - 1; i >= 0; i--)
+            if (objects.get(i).getGameVersion().equals(gameVersion))
+                return objects.get(i).getModVersion();
+        return objects.get(objects.size() - 1).getModVersion();
+    }
+    
+    private class JsonVersionElement {
+        @SerializedName("latest")
+        private List<LatestVersionObject> latestVersions;
+        private ChangelogObject changelogs;
+        
+        public JsonVersionElement() {
+            this.latestVersions = Lists.newArrayList();
+            changelogs = new ChangelogObject();
+        }
+        
+        public List<LatestVersionObject> getLatestVersions() {
+            return latestVersions;
+        }
+        
+        public ChangelogObject getChangelogs() {
+            return changelogs;
+        }
+    }
+    
+    private class LatestVersionObject {
+        @SerializedName("game")
+        private String gameVersion = "";
+        @SerializedName("mod")
+        private String modVersion = "";
+        
+        public String getGameVersion() {
+            return gameVersion;
+        }
+        
+        public String getModVersion() {
+            return modVersion;
+        }
+        
+        @Override
+        public String toString() {
+            return String.format("LatestVersion[%s] = %s", getGameVersion(), getModVersion());
+        }
+    }
+    
+    private class ChangelogObject {
+        private JsonArray fabric = new JsonArray();
+        private JsonArray rift = new JsonArray();
+        
+        public JsonArray getFabric() {
+            return fabric;
+        }
+        
+        public JsonArray getRift() {
+            return rift;
+        }
+    }
+    
+}

+ 13 - 0
src/main/java/me/shedaniel/rei/update/UpdatePriority.java

@@ -0,0 +1,13 @@
+package me.shedaniel.rei.update;
+
+import java.util.Arrays;
+
+public enum UpdatePriority {
+    
+    NONE, LIGHT, NORMAL, USEFUL, IMPORTANT;
+    
+    public static UpdatePriority fromString(String string) {
+        return Arrays.stream(values()).filter(updatePriority -> updatePriority.name().toLowerCase().equals(string)).findFirst().orElse(NONE);
+    }
+    
+}

+ 49 - 0
src/main/java/me/shedaniel/rei/update/Version.java

@@ -0,0 +1,49 @@
+package me.shedaniel.rei.update;
+
+public class Version implements Comparable<Version> {
+    
+    private String version;
+    
+    public Version(String version) {
+        if (version == null)
+            throw new IllegalArgumentException("Version can not be null");
+        if (!version.matches("[0-9]+(\\.[0-9]+)*"))
+            throw new IllegalArgumentException("Invalid version format");
+        this.version = version;
+    }
+    
+    @Override
+    public final String toString() {
+        return this.version;
+    }
+    
+    @Override
+    public int compareTo(Version other) {
+        if (other == null)
+            return 1;
+        String[] thisParts = this.toString().split("\\.");
+        String[] thatParts = other.toString().split("\\.");
+        int length = Math.max(thisParts.length, thatParts.length);
+        for(int i = 0; i < length; i++) {
+            int thisPart = i < thisParts.length ? Integer.parseInt(thisParts[i]) : 0;
+            int thatPart = i < thatParts.length ? Integer.parseInt(thatParts[i]) : 0;
+            if (thisPart < thatPart)
+                return -1;
+            if (thisPart > thatPart)
+                return 1;
+        }
+        return 0;
+    }
+    
+    @Override
+    public boolean equals(Object that) {
+        if (this == that)
+            return true;
+        if (that == null)
+            return false;
+        if (this.getClass() != that.getClass())
+            return false;
+        return this.compareTo((Version) that) == 0;
+    }
+    
+}

+ 3 - 1
src/main/resources/assets/roughlyenoughitems/lang/en_us.json

@@ -33,5 +33,7 @@
   "text.rei.enable_craftable_only": "Enable Craftable Only: ",
   "text.rei.showing_craftable": "Showing Craftable",
   "text.rei.showing_all": "Showing All",
-  "text.rei.delete_items": "§cDelete Item"
+  "text.rei.delete_items": "§cDelete Item",
+  "text.rei.update_outdated": "§6REI is outdated!\n§6Current: §a%s §6Latest: §a%s\n§6Update Priority: §a%s",
+  "text.rei.update_changelog_line": "§6- %s"
 }

+ 25 - 0
version.json

@@ -0,0 +1,25 @@
+{
+  "latest": [
+    {
+      "game": "19w04a",
+      "mod": "2.2.0.48"
+    },
+    {
+      "game": "19w04b",
+      "mod": "2.2.0.48"
+    },
+    {
+      "game": "19w05a",
+      "mod": "2.2.0.48"
+    }
+  ],
+  "changelogs": {
+    "fabric": [
+      {
+        "version": "2.2.0.28",
+        "text": "Added a version checker.",
+        "level": "light"
+      }
+    ]
+  }
+}