Commit 71a589d154d1d55211a943d2de87b2720c2f697c

Authored by Mumfrey
1 parent 53881326

Enable checking for and notifying of new snapshot builds, with option

src/client/java/com/mumfrey/liteloader/client/LiteLoaderPanelManager.java
... ... @@ -9,6 +9,7 @@ import org.lwjgl.input.Keyboard;
9 9  
10 10 import com.mumfrey.liteloader.client.gui.GuiLiteLoaderPanel;
11 11 import com.mumfrey.liteloader.common.GameEngine;
  12 +import com.mumfrey.liteloader.core.LiteLoader;
12 13 import com.mumfrey.liteloader.core.LiteLoaderMods;
13 14 import com.mumfrey.liteloader.core.LiteLoaderUpdateSite;
14 15 import com.mumfrey.liteloader.core.LiteLoaderVersion;
... ... @@ -32,6 +33,13 @@ import net.minecraft.client.resources.I18n;
32 33 */
33 34 public class LiteLoaderPanelManager implements PanelManager<GuiScreen>
34 35 {
  36 + /**
  37 + * Number of launches required before an update check is forced when the
  38 + * "force update check" option is enabled. For snapshot versions this is
  39 + * ignored and an update check is always performed.
  40 + */
  41 + private static final int UPDATE_CHECK_INTERVAL = 10;
  42 +
35 43 private final LoaderEnvironment environment;
36 44  
37 45 /**
... ... @@ -87,14 +95,14 @@ public class LiteLoaderPanelManager implements PanelManager&lt;GuiScreen&gt;
87 95 this.displayModInfoScreenTab = this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_MOD_INFO_SCREEN, true);
88 96 this.tabAlwaysExpanded = this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_NO_HIDE_TAB, false);
89 97  
90   - if (this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_FORCE_UPDATE, false))
  98 + if (this.shouldCheckForUpdates())
91 99 {
92 100 int updateCheckInterval = this.properties.getIntegerProperty(LoaderProperties.OPTION_UPDATE_CHECK_INTR) + 1;
93   - LiteLoaderLogger.debug("Force update is TRUE, updateCheckInterval = %d", updateCheckInterval);
  101 + LiteLoaderLogger.debug("Regular update check enabled, updateCheckInterval = %d", updateCheckInterval);
94 102  
95   - if (updateCheckInterval > 10)
  103 + if (LiteLoader.isSnapshot() || updateCheckInterval > LiteLoaderPanelManager.UPDATE_CHECK_INTERVAL)
96 104 {
97   - LiteLoaderLogger.debug("Forcing update check!");
  105 + LiteLoaderLogger.debug("Checking for updates...");
98 106 this.checkForUpdate = true;
99 107 updateCheckInterval = 0;
100 108 }
... ... @@ -104,6 +112,16 @@ public class LiteLoaderPanelManager implements PanelManager&lt;GuiScreen&gt;
104 112 }
105 113 }
106 114  
  115 + private boolean shouldCheckForUpdates()
  116 + {
  117 + if (LiteLoader.isSnapshot() && this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_CHECK_SNAPSHOTS, true))
  118 + {
  119 + return true;
  120 + }
  121 +
  122 + return this.properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_FORCE_UPDATE, false);
  123 + }
  124 +
107 125 @Override
108 126 public void init(LiteLoaderMods mods, ConfigManager configManager)
109 127 {
... ... @@ -141,7 +159,8 @@ public class LiteLoaderPanelManager implements PanelManager&lt;GuiScreen&gt;
141 159 this.checkForUpdate = false;
142 160 if (updateSite.isCheckSucceess() && updateSite.isUpdateAvailable())
143 161 {
144   - this.setNotification(I18n.format("gui.notifications.updateavailable"));
  162 + this.setNotification(I18n.format("gui.notifications." + (LiteLoader.isSnapshot() ? "newsnapshotavailable" : "updateavailable"),
  163 + updateSite.getAvailableVersion(), updateSite.getAvailableVersionDate()));
145 164 }
146 165 }
147 166 }
... ... @@ -251,6 +270,19 @@ public class LiteLoaderPanelManager implements PanelManager&lt;GuiScreen&gt;
251 270 {
252 271 return this.properties.getBooleanProperty(LoaderProperties.OPTION_FORCE_UPDATE);
253 272 }
  273 +
  274 + @Override
  275 + public void setCheckForSnapshotsEnabled(boolean checkForSnapshots)
  276 + {
  277 + this.properties.setBooleanProperty(LoaderProperties.OPTION_CHECK_SNAPSHOTS, checkForSnapshots);
  278 + this.properties.writeProperties();
  279 + }
  280 +
  281 + @Override
  282 + public boolean isCheckForSnapshotsEnabled()
  283 + {
  284 + return this.properties.getBooleanProperty(LoaderProperties.OPTION_CHECK_SNAPSHOTS);
  285 + }
254 286  
255 287 /**
256 288 * Display the liteloader panel over the specified GUI
... ...
src/client/java/com/mumfrey/liteloader/client/gui/GuiLiteLoaderPanel.java
... ... @@ -177,11 +177,10 @@ public class GuiLiteLoaderPanel extends GuiScreen
177 177 this.startupErrorCount = mods.getStartupErrorCount();
178 178 this.criticalErrorCount = mods.getCriticalErrorCount();
179 179  
180   - String branding = LiteLoader.getBranding();
181   - if (branding != null && branding.contains("SNAPSHOT"))
  180 + this.isSnapshot = LiteLoader.isSnapshot();
  181 + if (this.isSnapshot)
182 182 {
183   - this.isSnapshot = true;
184   - this.versionText = "\247c" + branding;
  183 + this.versionText = "\247c" + LiteLoader.getBranding();
185 184 }
186 185 }
187 186  
... ... @@ -524,6 +523,7 @@ public class GuiLiteLoaderPanel extends GuiScreen
524 523  
525 524 if (annoyingTip)
526 525 {
  526 + GuiLiteLoaderPanel.displayErrorToolTip = false;
527 527 this.drawNotificationTooltip(mouseX, mouseY - 13);
528 528 }
529 529 }
... ... @@ -542,8 +542,11 @@ public class GuiLiteLoaderPanel extends GuiScreen
542 542 }
543 543 else if (this.notification != null)
544 544 {
545   - GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, this.notification, left, top, this.width, this.height,
546   - GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_FOREGROUND, GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_BACKGROUND);
  545 + boolean isCritical = this.notification.startsWith("!!");
  546 + String text = isCritical ? this.notification.substring(2) : this.notification;
  547 + int bgColour = isCritical ? GuiLiteLoaderPanel.ERROR_TOOLTIP_BACKGROUND : GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_BACKGROUND;
  548 + GuiLiteLoaderPanel.drawTooltip(this.fontRendererObj, text, left, top, this.width, this.height,
  549 + GuiLiteLoaderPanel.NOTIFICATION_TOOLTIP_FOREGROUND, bgColour);
547 550 }
548 551 }
549 552  
... ... @@ -739,21 +742,32 @@ public class GuiLiteLoaderPanel extends GuiScreen
739 742 *
740 743 * @param fontRenderer
741 744 * @param tooltipText
742   - * @param mouseX
743   - * @param mouseY
  745 + * @param left
  746 + * @param top
744 747 * @param screenWidth
745 748 * @param screenHeight
746 749 * @param colour
747 750 * @param backgroundColour
748 751 */
749   - public static void drawTooltip(FontRenderer fontRenderer, String tooltipText, int mouseX, int mouseY, int screenWidth, int screenHeight,
  752 + public static void drawTooltip(FontRenderer fontRenderer, String text, int left, int top, int screenWidth, int screenHeight,
750 753 int colour, int backgroundColour)
751 754 {
752   - int textSize = fontRenderer.getStringWidth(tooltipText);
753   - mouseX = Math.max(0, Math.min(screenWidth - 4, mouseX - 4));
754   - mouseY = Math.max(0, Math.min(screenHeight - 16, mouseY));
755   - drawRect(mouseX - textSize - 2, mouseY, mouseX + 2, mouseY + 12, backgroundColour);
756   - fontRenderer.drawStringWithShadow(tooltipText, mouseX - textSize, mouseY + 2, colour);
  755 + String[] lines = text.trim().split("\\r?\\n");
  756 + int textWidth = 0;
  757 + int textHeight = 9 * lines.length;
  758 + for (String line : lines)
  759 + {
  760 + textWidth = Math.max(textWidth, fontRenderer.getStringWidth(line));
  761 + top -= 9;
  762 + }
  763 +
  764 + left = Math.max(0, Math.min(screenWidth - 4, left - 4));
  765 + top = Math.max(0, Math.min(screenHeight - 16, top + 9));
  766 + drawRect(left - textWidth - 2, top, left + 2, top + textHeight + 2, backgroundColour);
  767 + for (String line : lines)
  768 + {
  769 + fontRenderer.drawStringWithShadow(line, left - textWidth, (top += 9) - 7, colour);
  770 + }
757 771 }
758 772  
759 773  
... ...
src/client/java/com/mumfrey/liteloader/client/gui/GuiPanelSettings.java
... ... @@ -17,25 +17,29 @@ import net.minecraft.client.resources.I18n;
17 17  
18 18 class GuiPanelSettings extends GuiPanel
19 19 {
20   - private GuiLiteLoaderPanel parentScreen;
  20 + private final GuiLiteLoaderPanel parentScreen;
  21 +
  22 + private final boolean isSnapshot;
21 23  
22   - private GuiCheckbox chkShowTab, chkNoHide, chkForceUpdate;
  24 + private GuiCheckbox chkShowTab, chkNoHide, chkForceUpdate, chkCheckForSnapshots;
23 25  
24 26 private boolean hide;
25 27  
26 28 private String[] helpText = new String[5];
27   -
  29 +
28 30 GuiPanelSettings(GuiLiteLoaderPanel parentScreen, Minecraft minecraft)
29 31 {
30 32 super(minecraft);
31 33  
32 34 this.parentScreen = parentScreen;
  35 + this.isSnapshot = LiteLoader.isSnapshot();
33 36  
  37 + String helpKey = this.isSnapshot ? "checkforsnapshots" : "forceupdate";
34 38 this.helpText[0] = I18n.format("gui.settings.showtab.help1");
35 39 this.helpText[1] = I18n.format("gui.settings.showtab.help2");
36 40 this.helpText[2] = I18n.format("gui.settings.notabhide.help1");
37   - this.helpText[3] = I18n.format("gui.settings.forceupdate.help1");
38   - this.helpText[4] = I18n.format("gui.settings.forceupdate.help2");
  41 + this.helpText[3] = I18n.format("gui.settings." + helpKey + ".help1");
  42 + this.helpText[4] = I18n.format("gui.settings." + helpKey + ".help2");
39 43 }
40 44  
41 45 @Override
... ... @@ -61,6 +65,10 @@ class GuiPanelSettings extends GuiPanel
61 65 this.controls.add(this.chkShowTab = new GuiCheckbox(0, 34, 90, I18n.format("gui.settings.showtab.label")));
62 66 this.controls.add(this.chkNoHide = new GuiCheckbox(1, 34, 128, I18n.format("gui.settings.notabhide.label")));
63 67 this.controls.add(this.chkForceUpdate = new GuiCheckbox(2, 34, 158, I18n.format("gui.settings.forceupdate.label")));
  68 + this.controls.add(this.chkCheckForSnapshots = new GuiCheckbox(2, 34, 158, I18n.format("gui.settings.checkforsnapshots.label")));
  69 +
  70 + this.chkForceUpdate.visible = !this.isSnapshot;
  71 + this.chkCheckForSnapshots.visible = this.isSnapshot;
64 72  
65 73 this.updateCheckBoxes();
66 74 }
... ... @@ -72,6 +80,7 @@ class GuiPanelSettings extends GuiPanel
72 80 this.chkShowTab.checked = panelManager.isTabVisible();
73 81 this.chkNoHide.checked = panelManager.isTabAlwaysExpanded();
74 82 this.chkForceUpdate.checked = panelManager.isForceUpdateEnabled();
  83 + this.chkCheckForSnapshots.checked = panelManager.isCheckForSnapshotsEnabled();
75 84 }
76 85  
77 86 private void updateSettings()
... ... @@ -81,6 +90,7 @@ class GuiPanelSettings extends GuiPanel
81 90 panelManager.setTabVisible(this.chkShowTab.checked);
82 91 panelManager.setTabAlwaysExpanded(this.chkNoHide.checked);
83 92 panelManager.setForceUpdateEnabled(this.chkForceUpdate.checked);
  93 + panelManager.setCheckForSnapshotsEnabled(this.chkCheckForSnapshots.checked);
84 94 }
85 95  
86 96 @Override
... ...
src/main/java/com/mumfrey/liteloader/core/LiteLoader.java
... ... @@ -532,6 +532,15 @@ public final class LiteLoader
532 532 {
533 533 return "true".equals(System.getProperty("mcpenv"));
534 534 }
  535 +
  536 + /**
  537 + * Get whether the current running version is a snapshot build
  538 + */
  539 + public static boolean isSnapshot()
  540 + {
  541 + String branding = LiteLoader.getBranding();
  542 + return branding != null && branding.contains("SNAPSHOT");
  543 + }
535 544  
536 545 /**
537 546 * Dump debugging information to the console
... ...
src/main/java/com/mumfrey/liteloader/core/LiteLoaderUpdateSite.java
... ... @@ -8,6 +8,10 @@ package com.mumfrey.liteloader.core;
8 8 import java.io.File;
9 9 import java.io.IOException;
10 10 import java.io.InputStream;
  11 +import java.util.Date;
  12 +import java.util.Map;
  13 +import java.util.regex.Matcher;
  14 +import java.util.regex.Pattern;
11 15  
12 16 import com.google.common.io.ByteSink;
13 17 import com.google.common.io.Files;
... ... @@ -21,6 +25,8 @@ public class LiteLoaderUpdateSite extends UpdateSite
21 25 private static final String UPDATE_SITE_URL = "http://dl.liteloader.com/versions/";
22 26 private static final String UPDATE_SITE_VERSIONS_JSON = "versions.json";
23 27 private static final String UPDATE_SITE_ARTEFACT_NAME = "com.mumfrey:liteloader";
  28 +
  29 + private static final Pattern SNAPSHOT_REGEX = Pattern.compile("^([0-9\\._]+)-SNAPSHOT-(r[0-9a-z]+)-(b([0-9]+))-(.*)$", Pattern.CASE_INSENSITIVE);
24 30  
25 31 private String mcVersion;
26 32  
... ... @@ -28,6 +34,10 @@ public class LiteLoaderUpdateSite extends UpdateSite
28 34 private File jarFile = null;
29 35  
30 36 private boolean updateForced = false;
  37 + private boolean isSnapshot = false;
  38 +
  39 + private int currentBuild, availableBuild;
  40 + private String snapshotDate = null;
31 41  
32 42 public LiteLoaderUpdateSite(String targetVersion, long currentTimeStamp)
33 43 {
... ... @@ -36,6 +46,64 @@ public class LiteLoaderUpdateSite extends UpdateSite
36 46  
37 47 this.mcVersion = targetVersion;
38 48 }
  49 +
  50 + @Override
  51 + public void beginUpdateCheck()
  52 + {
  53 + this.isSnapshot = LiteLoader.isSnapshot();
  54 + super.beginUpdateCheck();
  55 + }
  56 +
  57 + @Override
  58 + public boolean isSnapshot()
  59 + {
  60 + return this.isSnapshot;
  61 + }
  62 +
  63 + @Override
  64 + public String getAvailableVersion()
  65 + {
  66 + if (this.isSnapshot() && this.availableBuild > 0)
  67 + {
  68 + return String.valueOf(this.availableBuild);
  69 + }
  70 +
  71 + return super.getAvailableVersion();
  72 + }
  73 +
  74 + @Override
  75 + public String getAvailableVersionDate()
  76 + {
  77 + if (this.snapshotDate != null)
  78 + {
  79 + return this.snapshotDate;
  80 + }
  81 +
  82 + return super.getAvailableVersionDate();
  83 + }
  84 +
  85 + @Override
  86 + protected boolean compareArtefact(Map<?, ?> artefact, long bestTimeStamp, Long remoteTimeStamp)
  87 + {
  88 + if (this.isSnapshot())
  89 + {
  90 + String remoteBuild = artefact.get("build").toString();
  91 + String myBuild = LiteLoader.getBranding();
  92 +
  93 + Matcher remoteMatcher = LiteLoaderUpdateSite.SNAPSHOT_REGEX.matcher(remoteBuild);
  94 + Matcher myMatcher = LiteLoaderUpdateSite.SNAPSHOT_REGEX.matcher(myBuild);
  95 +
  96 + if (remoteMatcher.matches() && myMatcher.matches())
  97 + {
  98 + this.currentBuild = Integer.parseInt(myMatcher.group(4));
  99 + this.availableBuild = Integer.parseInt(remoteMatcher.group(4));
  100 + this.snapshotDate = String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM", new Date(remoteTimeStamp * 1000L));
  101 + return this.availableBuild > this.currentBuild;
  102 + }
  103 + }
  104 +
  105 + return super.compareArtefact(artefact, bestTimeStamp, remoteTimeStamp);
  106 + }
39 107  
40 108 public boolean canForceUpdate(LoaderProperties properties)
41 109 {
... ...
src/main/java/com/mumfrey/liteloader/interfaces/PanelManager.java
... ... @@ -88,4 +88,14 @@ public interface PanelManager&lt;TParentScreen&gt; extends TickObserver, PostRenderObs
88 88 * Get whether "force update" is enabled
89 89 */
90 90 public abstract boolean isForceUpdateEnabled();
  91 +
  92 + /**
  93 + * Set whether "check for new snapshots" is enabled
  94 + */
  95 + public abstract void setCheckForSnapshotsEnabled(boolean checkForSnapshots);
  96 +
  97 + /**
  98 + * Get whether "check for new snapshots" is enabled
  99 + */
  100 + public abstract boolean isCheckForSnapshotsEnabled();
91 101 }
... ...
src/main/java/com/mumfrey/liteloader/launch/LoaderProperties.java
... ... @@ -99,6 +99,7 @@ public interface LoaderProperties
99 99 public static final String OPTION_FORCE_UPDATE = "allowForceUpdate";
100 100 public static final String OPTION_UPDATE_CHECK_INTR = "updateCheckInterval";
101 101 public static final String OPTION_JINPUT_DISABLE = "disableJInput";
  102 + public static final String OPTION_CHECK_SNAPSHOTS = "checkForNewSnapshots";
102 103  
103 104 // Enumerator properties
104 105 public static final String OPTION_SEARCH_MODS = "search.mods";
... ...
src/main/java/com/mumfrey/liteloader/update/UpdateSite.java
... ... @@ -160,6 +160,11 @@ public class UpdateSite implements Comparator&lt;Long&gt;
160 160 }
161 161 }
162 162 }
  163 +
  164 + public boolean isSnapshot()
  165 + {
  166 + return false;
  167 + }
163 168  
164 169 /**
165 170 * Gets whether a check is in progress
... ... @@ -319,7 +324,7 @@ public class UpdateSite implements Comparator&lt;Long&gt;
319 324 */
320 325 private void handleVersionData(Object key, Map<?, ?> value)
321 326 {
322   - if ("artefacts".equals(key))
  327 + if ((this.isSnapshot() && "snapshots".equals(key)) || (!this.isSnapshot() && "artefacts".equals(key)))
323 328 {
324 329 if (value.containsKey(this.artefact))
325 330 {
... ... @@ -387,7 +392,7 @@ public class UpdateSite implements Comparator&lt;Long&gt;
387 392 this.availableVersion = artefact.get("version").toString();
388 393 this.availableVersionDate = DateFormat.getDateTimeInstance().format(new Date(remoteTimeStamp * 1000L));
389 394 this.availableVersionURL = this.createArtefactURL(artefact.get("file").toString());
390   - this.updateAvailable = this.compareTimeStamps(bestTimeStamp, remoteTimeStamp);
  395 + this.updateAvailable = this.compareArtefact(artefact, bestTimeStamp, remoteTimeStamp);
391 396  
392 397 return true;
393 398 }
... ... @@ -395,6 +400,11 @@ public class UpdateSite implements Comparator&lt;Long&gt;
395 400 return false;
396 401 }
397 402  
  403 + protected boolean compareArtefact(Map<?, ?> artefact, long bestTimeStamp, Long remoteTimeStamp)
  404 + {
  405 + return this.compareTimeStamps(bestTimeStamp, remoteTimeStamp);
  406 + }
  407 +
398 408 /**
399 409 * @param bestTimeStamp
400 410 * @param remoteTimeStamp
... ...
src/main/resources/assets/liteloader/lang/en_us.lang
... ... @@ -16,6 +16,9 @@ gui.settings.notabhide.help1=Only applies if the above option is also checked
16 16 gui.settings.forceupdate.label=Periodically Check For Updates
17 17 gui.settings.forceupdate.help1=This option is §cexperimental§r and may not work properly
18 18 gui.settings.forceupdate.help2=yet, it also enables the "force update" capability.
  19 +gui.settings.checkforsnapshots.label=Check For New Snapshots
  20 +gui.settings.checkforsnapshots.help1=If this option is enabled, LiteLoader will check
  21 +gui.settings.checkforsnapshots.help2=for new SNAPSHOT releases each time it it launched
19 22  
20 23 gui.about.taboptions=§nLiteLoader Panel Options
21 24  
... ... @@ -86,4 +89,5 @@ gui.error.title=Startup errors for %s
86 89  
87 90 gui.error.tooltip=%d mod startup error(s) detected (%d critical)
88 91  
89   -gui.notifications.updateavailable=LiteLoader Update Available!
90 92 \ No newline at end of file
  93 +gui.notifications.updateavailable=LiteLoader Update Available!
  94 +gui.notifications.newsnapshotavailable=!!New Snapshot Available:%nBuild #%s (%s)
91 95 \ No newline at end of file
... ...