Commit 00d2ffc1cec6214f71b79dddee52e3acae80856a

Authored by Mumfrey
1 parent 34b8439f

mechanism to self-update the realms version in our local JSON

java/common/com/mumfrey/liteloader/core/LiteLoaderBootstrap.java
... ... @@ -27,9 +27,12 @@ import com.mumfrey.liteloader.api.manager.APIRegistry;
27 27 import com.mumfrey.liteloader.common.LoadingProgress;
28 28 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI;
29 29 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
  30 +import com.mumfrey.liteloader.launch.ClassPathUtilities;
  31 +import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
30 32 import com.mumfrey.liteloader.launch.LoaderBootstrap;
31 33 import com.mumfrey.liteloader.launch.LoaderEnvironment;
32 34 import com.mumfrey.liteloader.launch.LoaderProperties;
  35 +import com.mumfrey.liteloader.launch.RealmsJsonUpdateThread;
33 36 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
34 37  
35 38 /**
... ... @@ -138,6 +141,8 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
138 141 */
139 142 private EnabledModsList enabledModsList;
140 143  
  144 + private RealmsJsonUpdateThread realmsJsonUpdateThread;
  145 +
141 146 /**
142 147 * @param gameDirectory
143 148 * @param assetsDirectory
... ... @@ -172,6 +177,8 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
172 177 this.initAPIs(apisToLoad);
173 178 this.apiProvider = this.apiRegistry.getProvider();
174 179 this.apiAdapter = this.apiRegistry.getAdapter();
  180 +
  181 + this.setupRealmsVersionCheck(profile);
175 182 }
176 183  
177 184 /**
... ... @@ -321,6 +328,8 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
321 328 if (this.enumerator == null) return;
322 329  
323 330 LiteLoader.invokePostInit();
  331 +
  332 + this.runRealmsVersionCheck();
324 333 }
325 334  
326 335 /**
... ... @@ -679,4 +688,36 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
679 688 {
680 689 return this.apiAdapter.getPacketTransformers();
681 690 }
  691 +
  692 + private void setupRealmsVersionCheck(String profile)
  693 + {
  694 + if (!this.getAndStoreBooleanProperty(LoaderProperties.OPTION_UPDATE_REALMS, true))
  695 + {
  696 + return;
  697 + }
  698 +
  699 + try
  700 + {
  701 + File realmsContainer = ClassPathUtilities.getPathToResource(LiteLoaderTweaker.class, "/net/minecraft/realms/Realms.class");
  702 + if (realmsContainer == null) return;
  703 +
  704 + File versionsDir = realmsContainer.getParentFile().getParentFile();
  705 + if (versionsDir.exists() && "versions".equals(versionsDir.getName()))
  706 + {
  707 + this.realmsJsonUpdateThread = new RealmsJsonUpdateThread(versionsDir, profile, LiteLoaderTweaker.VERSION);
  708 + }
  709 + }
  710 + catch (Exception ex)
  711 + {
  712 + ex.printStackTrace();
  713 + }
  714 + }
  715 +
  716 + private void runRealmsVersionCheck()
  717 + {
  718 + if (this.realmsJsonUpdateThread != null)
  719 + {
  720 + this.realmsJsonUpdateThread.start();
  721 + }
  722 + }
682 723 }
... ...
java/common/com/mumfrey/liteloader/core/LiteLoaderVersion.java
... ... @@ -9,7 +9,7 @@ import com.mumfrey.liteloader.update.UpdateSite;
9 9 * LiteLoader version table
10 10 *
11 11 * @author Adam Mummery-Smith
12   - * @version 1.7.10_01
  12 + * @version 1.7.10_02
13 13 */
14 14 public enum LiteLoaderVersion
15 15 {
... ... @@ -36,12 +36,13 @@ public enum LiteLoaderVersion
36 36 MC_1_7_2_R5(25, 0, "1.7.2", "1.7.2_05", "1.7.2_02", "1.7.2_03", "1.7.2_04", "1.7.2_05"),
37 37 MC_1_7_2_R6(26, 0, "1.7.2", "1.7.2_06", "1.7.2_06"),
38 38 MC_1_7_10_R0(27, 1404330030, "1.7.10", "1.7.10", "1.7.10"),
39   - MC_1_7_10_R1(28, 1404673785, "1.7.10", "1.7.10_01", "1.7.10");
  39 + MC_1_7_10_R1(28, 1404673785, "1.7.10", "1.7.10_01", "1.7.10"),
  40 + MC_1_7_10_R2(29, 0, "1.7.10", "1.7.10_02", "1.7.10");
40 41  
41 42 /**
42 43 * Current loader version
43 44 */
44   - public static final LiteLoaderVersion CURRENT = LiteLoaderVersion.MC_1_7_10_R1;
  45 + public static final LiteLoaderVersion CURRENT = LiteLoaderVersion.MC_1_7_10_R2;
45 46  
46 47 private static final String UPDATE_SITE_URL = "http://dl.liteloader.com/versions/";
47 48 private static final String UPDATE_SITE_VERSIONS_JSON = "versions.json";
... ...
java/common/com/mumfrey/liteloader/launch/LoaderProperties.java
... ... @@ -69,6 +69,7 @@ public interface LoaderProperties
69 69 public static final String OPTION_NO_HIDE_TAB = "tabAlwaysExpanded";
70 70 public static final String OPTION_BRAND = "brand";
71 71 public static final String OPTION_LOADING_BAR = "loadingbar";
  72 + public static final String OPTION_UPDATE_REALMS = "realmsUpdateCheck";
72 73  
73 74 // Enumerator properties
74 75 public static final String OPTION_SEARCH_MODS = "search.mods";
... ...
java/common/com/mumfrey/liteloader/launch/RealmsJsonUpdateThread.java 0 โ†’ 100644
  1 +package com.mumfrey.liteloader.launch;
  2 +
  3 +import java.io.File;
  4 +import java.io.FileReader;
  5 +import java.io.FileWriter;
  6 +import java.net.URI;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +import java.util.Map.Entry;
  10 +
  11 +import org.apache.commons.io.IOUtils;
  12 +
  13 +import com.google.common.base.Strings;
  14 +import com.google.gson.Gson;
  15 +import com.google.gson.GsonBuilder;
  16 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
  17 +import com.mumfrey.liteloader.util.net.HttpStringRetriever;
  18 +
  19 +/**
  20 + * Attempt to keep the version JSON we were launched from in sync with the latest lib version for this version of MC
  21 + *
  22 + * @author Adam Mummery-Smith
  23 + */
  24 +public class RealmsJsonUpdateThread extends Thread
  25 +{
  26 + private static final String DOWNLOAD_BASE_URL = "http://s3.amazonaws.com/Minecraft.Download/";
  27 +
  28 + private static final String REALMS_LIB_PATH = "com.mojang:realms";
  29 +
  30 + private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
  31 +
  32 + private final File versionsDir;
  33 +
  34 + private final String version;
  35 +
  36 + private final URI uri;
  37 +
  38 + public RealmsJsonUpdateThread(File versionsDir, String version, String parentVersion)
  39 + {
  40 + this.versionsDir = versionsDir;
  41 + this.version = version;
  42 + this.uri = URI.create(String.format("%sversions/%2$s/%2$s.json", RealmsJsonUpdateThread.DOWNLOAD_BASE_URL, parentVersion));
  43 +
  44 + this.setName("Realms JSON update thread");
  45 + this.setDaemon(true);
  46 + }
  47 +
  48 + @Override
  49 + public void run()
  50 + {
  51 + if (this.isLocalJsonUpToDate())
  52 + {
  53 + LiteLoaderLogger.info("Realms JSON thread is skipping update check, version JSON file was recently modified");
  54 + return;
  55 + }
  56 +
  57 + Map<String, ?> localJson = this.getLocalVersionJson();
  58 + if (localJson == null)
  59 + {
  60 + LiteLoaderLogger.info("Realms JSON thread failed to locate the local version JSON for version %s. The realms library reference can not be updated", this.version);
  61 + return;
  62 + }
  63 +
  64 + Map<String, ?> remoteJson = this.getRemoteVersionJson();
  65 + if (remoteJson == null)
  66 + {
  67 + LiteLoaderLogger.info("Realms JSON thread failed to fetch the vanilla JSON. The realms library reference will not be updated");
  68 + return;
  69 + }
  70 +
  71 + String realmsVersionRemote = this.getLibraryVersion(remoteJson, RealmsJsonUpdateThread.REALMS_LIB_PATH);
  72 + if (realmsVersionRemote == null)
  73 + {
  74 + LiteLoaderLogger.info("Realms JSON thread failed to parse remote version JSON. The realms library reference can not be updated");
  75 + return;
  76 + }
  77 +
  78 + String realmsVersionLocal = this.getLibraryVersion(localJson, RealmsJsonUpdateThread.REALMS_LIB_PATH);
  79 + if (realmsVersionLocal == null)
  80 + {
  81 + LiteLoaderLogger.info("Realms JSON thread failed to parse local version JSON. The realms library reference can not be updated");
  82 + return;
  83 + }
  84 +
  85 + if (realmsVersionRemote.equals(realmsVersionLocal))
  86 + {
  87 + LiteLoaderLogger.info("Realms library reference is up-to-date. Current version is %s", realmsVersionRemote);
  88 + return;
  89 + }
  90 +
  91 + LiteLoaderLogger.info("Realms library reference is out of date. Current version %s, found remote version %s. Attempting to update version JSON.", realmsVersionLocal, realmsVersionRemote);
  92 + if (!this.setLibraryVersion(localJson, RealmsJsonUpdateThread.REALMS_LIB_PATH, realmsVersionRemote))
  93 + {
  94 + LiteLoaderLogger.warning("Could not update the realms library version in the version JSON");
  95 + return;
  96 + }
  97 +
  98 + if (!this.writeLocalVersionJson(localJson))
  99 + {
  100 + LiteLoaderLogger.warning("Could not write the updated version JSON");
  101 + return;
  102 + }
  103 +
  104 + LiteLoaderLogger.info("Realms library reference was successfully updated. Current version is now %s", realmsVersionRemote);
  105 + }
  106 +
  107 + private boolean writeLocalVersionJson(Map<String, ?> localJson)
  108 + {
  109 + File versionDir = new File(this.versionsDir, this.version);
  110 + if (!versionDir.exists() || !versionDir.isDirectory()) return false;
  111 +
  112 + File versionJsonFile = new File(versionDir, this.version + ".json");
  113 +
  114 + FileWriter writer = null;
  115 +
  116 + try
  117 + {
  118 + writer = new FileWriter(versionJsonFile);
  119 + this.gson.toJson(localJson, writer);
  120 + }
  121 + catch (Exception ex)
  122 + {
  123 + ex.printStackTrace();
  124 + }
  125 + finally
  126 + {
  127 + IOUtils.closeQuietly(writer);
  128 + }
  129 +
  130 + return true;
  131 + }
  132 +
  133 + @SuppressWarnings("unchecked")
  134 + private String getLibraryVersion(Map<String, ?> json, String libraryName)
  135 + {
  136 + for (Map<String, String> library : (List<Map<String, String>>)json.get("libraries"))
  137 + {
  138 + try
  139 + {
  140 + for (Entry<String, ?> entry : library.entrySet())
  141 + {
  142 + String keyName = entry.getKey();
  143 + if ("name".equals(keyName))
  144 + {
  145 + String libName = entry.getValue().toString();
  146 + if (libName.startsWith(libraryName))
  147 + {
  148 + return libName.substring(libraryName.length() + 1);
  149 + }
  150 + }
  151 + }
  152 + }
  153 + catch (Exception ex) {}
  154 + }
  155 +
  156 + return null;
  157 + }
  158 +
  159 + @SuppressWarnings("unchecked")
  160 + private boolean setLibraryVersion(Map<String, ?> json, String libraryName, String newVersion)
  161 + {
  162 + int libraryIndex = this.getLibraryIndex(json, libraryName);
  163 + if (libraryIndex > -1)
  164 + {
  165 + List<Map<String, Object>> libraries = (List<Map<String, Object>>)json.get("libraries");
  166 + Map<String, Object> library = libraries.get(libraryIndex);
  167 + library.put("name", String.format("%s:%s", libraryName, newVersion));
  168 + return true;
  169 + }
  170 +
  171 + return false;
  172 + }
  173 +
  174 + /**
  175 + * @param json
  176 + * @param libraryName
  177 + * @return
  178 + */
  179 + @SuppressWarnings("unchecked")
  180 + private int getLibraryIndex(Map<String, ?> json, String libraryName)
  181 + {
  182 + List<Map<String, ?>> libraries = (List<Map<String, ?>>)json.get("libraries");
  183 + for (int index = 0; index < libraries.size(); index++)
  184 + {
  185 + try
  186 + {
  187 + Map<String, ?> library = libraries.get(index);
  188 + for (Entry<String, ?> entry : library.entrySet())
  189 + {
  190 + String keyName = entry.getKey();
  191 + if ("name".equals(keyName))
  192 + {
  193 + String libName = entry.getValue().toString();
  194 + if (libName.startsWith(libraryName))
  195 + {
  196 + return index;
  197 + }
  198 + }
  199 + }
  200 + }
  201 + catch (Exception ex) {}
  202 + }
  203 +
  204 + return -1;
  205 + }
  206 +
  207 + @SuppressWarnings("unchecked")
  208 + private Map<String, ?> getRemoteVersionJson()
  209 + {
  210 + try
  211 + {
  212 + HttpStringRetriever http = new HttpStringRetriever();
  213 + String json = http.fetch(this.uri.toURL());
  214 + if (!Strings.isNullOrEmpty(json))
  215 + {
  216 + return this.gson.fromJson(json, Map.class);
  217 + }
  218 + }
  219 + catch (Exception ex)
  220 + {
  221 + ex.printStackTrace();
  222 + }
  223 +
  224 + return null;
  225 + }
  226 +
  227 + @SuppressWarnings("unchecked")
  228 + private Map<String, ?> getLocalVersionJson()
  229 + {
  230 + File versionDir = new File(this.versionsDir, this.version);
  231 + if (!versionDir.exists() || !versionDir.isDirectory()) return null;
  232 +
  233 + File versionJsonFile = new File(versionDir, this.version + ".json");
  234 + if (!versionJsonFile.exists()) return null;
  235 +
  236 + FileReader reader = null;
  237 +
  238 + try
  239 + {
  240 + reader = new FileReader(versionJsonFile);
  241 + return this.gson.fromJson(reader, Map.class);
  242 + }
  243 + catch (Exception ex)
  244 + {
  245 + ex.printStackTrace();
  246 + }
  247 + finally
  248 + {
  249 + IOUtils.closeQuietly(reader);
  250 + }
  251 +
  252 + return null;
  253 + }
  254 +
  255 + private boolean isLocalJsonUpToDate()
  256 + {
  257 + File versionDir = new File(this.versionsDir, this.version);
  258 + if (!versionDir.exists() || !versionDir.isDirectory()) return false;
  259 +
  260 + File versionJsonFile = new File(versionDir, this.version + ".json");
  261 + if (!versionJsonFile.exists()) return false;
  262 +
  263 + long deltaTime = System.currentTimeMillis() - versionJsonFile.lastModified();
  264 + return deltaTime < 86400000;
  265 + }
  266 +}
... ...
java/common/com/mumfrey/liteloader/transformers/ClassOverlayTransformer.java
... ... @@ -167,7 +167,7 @@ public abstract class ClassOverlayTransformer extends ClassTransformer
167 167 {
168 168 throw new RuntimeException(String.format("%s is an overlay class and cannot be referenced directly", this.overlayClassName));
169 169 }
170   - else if (this.remappingAgent && transformedName.endsWith("LiteModRenderDecorator"))
  170 + else if (this.remappingAgent)
171 171 {
172 172 return this.remapClass(transformedName, basicClass);
173 173 }
... ...
java/common/com/mumfrey/liteloader/util/net/HttpStringRetriever.java
... ... @@ -93,6 +93,16 @@ public class HttpStringRetriever extends Thread
93 93 }
94 94  
95 95 /**
  96 + * Create a new string retriever to be used synchronously
  97 + *
  98 + * @param url URL to download from
  99 + */
  100 + public HttpStringRetriever()
  101 + {
  102 + this(null, null);
  103 + }
  104 +
  105 + /**
96 106 * Get the string which was retrieved
97 107 */
98 108 public String getString()
... ...