aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/eu
diff options
context:
space:
mode:
authorCow <cow@volloeko.de>2020-03-08 00:12:57 +0100
committerCow <cow@volloeko.de>2020-03-08 00:12:57 +0100
commit0a105c807a3f8040ada76c4e4edac4a79fe32fe6 (patch)
treeb0631894c6547b2fe3daf73539fec6935dd9659d /src/main/java/eu
parent508f872ba076f4e767ff2c374656bc47637eb229 (diff)
downloadCowlection-0a105c807a3f8040ada76c4e4edac4a79fe32fe6.tar.gz
Cowlection-0a105c807a3f8040ada76c4e4edac4a79fe32fe6.tar.bz2
Cowlection-0a105c807a3f8040ada76c4e4edac4a79fe32fe6.zip
Added mod update notification (opt-out via /moo config)
Standardized versioning (now includes Minecraft version) Bug fixes: - Reduced greediness of login/logout notification detection
Diffstat (limited to 'src/main/java/eu')
-rw-r--r--src/main/java/eu/olli/cowmoonication/Cowmoonication.java26
-rw-r--r--src/main/java/eu/olli/cowmoonication/command/MooCommand.java86
-rw-r--r--src/main/java/eu/olli/cowmoonication/config/MooConfig.java7
-rw-r--r--src/main/java/eu/olli/cowmoonication/config/MooGuiConfig.java1
-rw-r--r--src/main/java/eu/olli/cowmoonication/listener/ChatListener.java7
-rw-r--r--src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java18
-rw-r--r--src/main/java/eu/olli/cowmoonication/util/Utils.java9
-rw-r--r--src/main/java/eu/olli/cowmoonication/util/VersionChecker.java140
8 files changed, 274 insertions, 20 deletions
diff --git a/src/main/java/eu/olli/cowmoonication/Cowmoonication.java b/src/main/java/eu/olli/cowmoonication/Cowmoonication.java
index 3a93fe6..78f1905 100644
--- a/src/main/java/eu/olli/cowmoonication/Cowmoonication.java
+++ b/src/main/java/eu/olli/cowmoonication/Cowmoonication.java
@@ -3,24 +3,32 @@ package eu.olli.cowmoonication;
import eu.olli.cowmoonication.command.MooCommand;
import eu.olli.cowmoonication.config.MooConfig;
import eu.olli.cowmoonication.listener.ChatListener;
+import eu.olli.cowmoonication.listener.PlayerListener;
import eu.olli.cowmoonication.util.Utils;
+import eu.olli.cowmoonication.util.VersionChecker;
import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger;
import java.io.File;
-@Mod(modid = Cowmoonication.MODID, version = Cowmoonication.VERSION, clientSideOnly = true, guiFactory = "eu.olli." + Cowmoonication.MODID + ".config.MooGuiFactory")
+@Mod(modid = Cowmoonication.MODID, name = Cowmoonication.MODNAME, version = Cowmoonication.VERSION,
+ clientSideOnly = true,
+ guiFactory = "eu.olli." + Cowmoonication.MODID + ".config.MooGuiFactory",
+ updateJSON = "https://raw.githubusercontent.com/cow-mc/Cowmoonication/master/update.json")
public class Cowmoonication {
public static final String MODID = "cowmoonication";
- public static final String VERSION = "1.0";
+ public static final String VERSION = "1.8.9-0.2.0";
+ public static final String MODNAME = "Cowmoonication";
private MooConfig config;
private Friends friends;
+ private VersionChecker versionChecker;
private Utils utils;
private Logger logger;
@@ -35,16 +43,23 @@ public class Cowmoonication {
friends = new Friends(this);
config = new MooConfig(new Configuration(new File(modDir, MODID + ".cfg")), this);
+
+ utils = new Utils(this, e.getSourceFile());
}
@EventHandler
public void init(FMLInitializationEvent e) {
- utils = new Utils(this);
MinecraftForge.EVENT_BUS.register(new ChatListener(this));
+ MinecraftForge.EVENT_BUS.register(new PlayerListener(this));
ClientCommandHandler.instance.registerCommand(new MooCommand(this));
}
+ @EventHandler
+ public void postInit(FMLPostInitializationEvent e) {
+ versionChecker = new VersionChecker(this);
+ }
+
public MooConfig getConfig() {
return config;
}
@@ -53,6 +68,10 @@ public class Cowmoonication {
return friends;
}
+ public VersionChecker getVersionChecker() {
+ return versionChecker;
+ }
+
public Utils getUtils() {
return utils;
}
@@ -60,5 +79,4 @@ public class Cowmoonication {
public Logger getLogger() {
return logger;
}
-
}
diff --git a/src/main/java/eu/olli/cowmoonication/command/MooCommand.java b/src/main/java/eu/olli/cowmoonication/command/MooCommand.java
index f3d234b..08c377d 100644
--- a/src/main/java/eu/olli/cowmoonication/command/MooCommand.java
+++ b/src/main/java/eu/olli/cowmoonication/command/MooCommand.java
@@ -8,13 +8,15 @@ import net.minecraft.client.Minecraft;
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
-import net.minecraft.util.BlockPos;
-import net.minecraft.util.ChatComponentTranslation;
-import net.minecraft.util.EnumChatFormatting;
-import net.minecraft.util.MathHelper;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.event.HoverEvent;
+import net.minecraft.util.*;
+import java.awt.*;
+import java.io.IOException;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
public class MooCommand extends CommandBase {
private final Cowmoonication main;
@@ -29,21 +31,55 @@ public class MooCommand extends CommandBase {
main.getUtils().sendMessage(new ChatComponentTranslation(getCommandUsage(sender)));
return;
}
- if (args[0].equalsIgnoreCase("friends") || args[0].equalsIgnoreCase("f")) {
+ if (args[0].equalsIgnoreCase("friends") || args[0].equalsIgnoreCase("config")) {
new TickDelay(() -> Minecraft.getMinecraft().displayGuiScreen(new MooGuiConfig(null)), 1); // delay by 1 tick, because the chat closing would close the new gui instantly as well.
} else if (args[0].equalsIgnoreCase("list")) {
handleListBestFriends();
} else if (args[0].equalsIgnoreCase("toggle")) {
main.getConfig().toggleNotifications();
- main.getUtils().sendMessage(EnumChatFormatting.GREEN + "Switched all non-best friend login/logout notifications " + (MooConfig.filterFriendNotifications ? EnumChatFormatting.DARK_GREEN + "off" : EnumChatFormatting.DARK_RED + "on"));
+ main.getUtils().sendMessage(EnumChatFormatting.GREEN + "\u2714 Switched all non-best friend login/logout notifications " + (MooConfig.filterFriendNotifications ? EnumChatFormatting.DARK_GREEN + "off" : EnumChatFormatting.DARK_RED + "on"));
} else if (args[0].equalsIgnoreCase("guiscale")) {
int currentGuiScale = (Minecraft.getMinecraft()).gameSettings.guiScale;
if (args.length == 1) {
- main.getUtils().sendMessage(EnumChatFormatting.GREEN + "Current GUI scale: " + EnumChatFormatting.DARK_GREEN + currentGuiScale);
+ main.getUtils().sendMessage(EnumChatFormatting.GREEN + "\u279C Current GUI scale: " + EnumChatFormatting.DARK_GREEN + currentGuiScale);
} else {
int scale = Math.min(10, MathHelper.parseIntWithDefault(args[1], 6));
Minecraft.getMinecraft().gameSettings.guiScale = scale;
- main.getUtils().sendMessage(EnumChatFormatting.GREEN + "New GUI scale: " + EnumChatFormatting.DARK_GREEN + scale + EnumChatFormatting.GREEN + " (previous: " + EnumChatFormatting.DARK_GREEN + currentGuiScale + EnumChatFormatting.GREEN + ")");
+ main.getUtils().sendMessage(EnumChatFormatting.GREEN + "\u2714 New GUI scale: " + EnumChatFormatting.DARK_GREEN + scale + EnumChatFormatting.GREEN + " (previous: " + EnumChatFormatting.DARK_GREEN + currentGuiScale + EnumChatFormatting.GREEN + ")");
+ }
+ } else if (args[0].equalsIgnoreCase("update")) {
+ boolean updateCheckStarted = main.getVersionChecker().runUpdateCheck(true);
+
+ if (updateCheckStarted) {
+ main.getUtils().sendMessage(EnumChatFormatting.GREEN + "\u279C Checking for a newer mod version...");
+ // VersionChecker#handleVersionStatus will run with a 5 seconds delay
+ } else {
+ long nextUpdate = main.getVersionChecker().getNextCheck();
+ String waitingTime = String.format("%02d:%02d",
+ TimeUnit.MILLISECONDS.toMinutes(nextUpdate),
+ TimeUnit.MILLISECONDS.toSeconds(nextUpdate) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(nextUpdate)));
+ main.getUtils().sendMessage(new ChatComponentText("\u26A0 Update checker is on cooldown. Please wait " + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + waitingTime + EnumChatFormatting.RESET + EnumChatFormatting.RED + " more minutes before checking again.").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)));
+ }
+ } else if (args[0].equalsIgnoreCase("updateHelp")) {
+ main.getUtils().sendMessage(new ChatComponentText("\u279C Update instructions:").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(true))
+ .appendSibling(new ChatComponentText("\n\u278A" + EnumChatFormatting.YELLOW + " download latest mod version").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(false)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, main.getVersionChecker().getDownloadUrl()))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Download the latest version of Cowmoonication\n\u279C Click to download latest mod file")))))
+ .appendSibling(new ChatComponentText("\n\u278B" + EnumChatFormatting.YELLOW + " exit Minecraft").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(false)
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.GOLD + "\u278B" + EnumChatFormatting.YELLOW + " Without closing Minecraft first,\n" + EnumChatFormatting.YELLOW + "you can't delete the old .jar file!")))))
+ .appendSibling(new ChatComponentText("\n\u278C" + EnumChatFormatting.YELLOW + " copy " + EnumChatFormatting.GOLD + "Cowmoonication-" + main.getVersionChecker().getNewVersion() + ".jar" + EnumChatFormatting.YELLOW + " into mods folder").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(false)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/moo folder"))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Open mods folder with command " + EnumChatFormatting.GOLD + "/moo folder\n\u279C Click to open mods folder")))))
+ .appendSibling(new ChatComponentText("\n\u278D" + EnumChatFormatting.YELLOW + " delete old mod file " + EnumChatFormatting.GOLD + "Cowmoonication-" + Cowmoonication.VERSION + ".jar ").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(false)))
+ .appendSibling(new ChatComponentText("\n\u278E" + EnumChatFormatting.YELLOW + " start Minecraft again").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(false))));
+ } else if (args[0].equalsIgnoreCase("version")) {
+ main.getVersionChecker().handleVersionStatus(true);
+ } else if (args[0].equalsIgnoreCase("folder")) {
+ try {
+ Desktop.getDesktop().open(main.getUtils().getModsFolder());
+ } catch (IOException e) {
+ main.getUtils().sendMessage(new ChatComponentText("\u2716 An error occurred trying to open the mod's folder. I guess you have to open it manually \u00af\\_(\u30c4)_/\u00af").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)));
+ e.printStackTrace();
}
} else {
main.getUtils().sendMessage(new ChatComponentTranslation(getCommandUsage(sender)));
@@ -54,7 +90,7 @@ public class MooCommand extends CommandBase {
Set<String> bestFriends = main.getFriends().getBestFriends();
// TODO show fancy gui with list of best friends (maybe just the mod's settings?)
- main.getUtils().sendMessage(EnumChatFormatting.GREEN + "Best friends: " + String.join(", ", bestFriends));
+ main.getUtils().sendMessage(EnumChatFormatting.GREEN + "\u279C Best friends: " + EnumChatFormatting.DARK_GREEN + String.join(EnumChatFormatting.GREEN + ", " + EnumChatFormatting.DARK_GREEN, bestFriends));
}
@Override
@@ -64,7 +100,35 @@ public class MooCommand extends CommandBase {
@Override
public String getCommandUsage(ICommandSender sender) {
- return Cowmoonication.MODID + ":command.moo.usage";
+ IChatComponent usage = new ChatComponentText("\u279C Cowmoonication commands:").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(true))
+ .appendSibling(createCmdHelpSection(1, "Login/Logout Notifications"))
+ .appendSibling(createCmdHelpEntry("friends", "Add/remove best friends"))
+ .appendSibling(createCmdHelpEntry("list", "View list of best friends"))
+ .appendSibling(createCmdHelpEntry("toggle", "Toggle show/hide all join/leave notifications"))
+ .appendSibling(createCmdHelpSection(2, "Miscellaneous"))
+ .appendSibling(createCmdHelpEntry("config", "Open configuration GUI"))
+ .appendSibling(createCmdHelpEntry("guiScale", "Change GUI scale"))
+ .appendSibling(createCmdHelpSection(3, "Update mod"))
+ .appendSibling(createCmdHelpEntry("update", "Check for new mod updates"))
+ .appendSibling(createCmdHelpEntry("updateHelp", "Show mod update instructions"))
+ .appendSibling(createCmdHelpEntry("version", "View results of last mod update check"))
+ .appendSibling(createCmdHelpEntry("folder", "Open Minecraft's mods folder"));
+ sender.addChatMessage(usage);
+ return "";
+ }
+
+ private IChatComponent createCmdHelpSection(int nr, String title) {
+ String prefix = Character.toString((char) (0x2789 + nr));
+ return new ChatComponentText("\n").appendSibling(new ChatComponentText(prefix + " " + title).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD).setBold(true)));
+ }
+
+ private IChatComponent createCmdHelpEntry(String cmd, String usage) {
+ String command = "/" + this.getCommandName() + " " + cmd;
+ ChatStyle clickableMsg = new ChatStyle()
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Run " + EnumChatFormatting.GOLD + command)))
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command));
+ return new ChatComponentText("\n").appendSibling(new ChatComponentText(command).setChatStyle(clickableMsg.createDeepCopy().setColor(EnumChatFormatting.GOLD)))
+ .appendSibling(new ChatComponentText(" \u27A1 " + usage).setChatStyle(clickableMsg.createDeepCopy().setColor(EnumChatFormatting.YELLOW)));
}
@Override
@@ -75,7 +139,7 @@ public class MooCommand extends CommandBase {
@Override
public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) {
if (args.length == 1) {
- return getListOfStringsMatchingLastWord(args, "friends", "list", "toggle", "guiscale");
+ return getListOfStringsMatchingLastWord(args, "config", "friends", "list", "toggle", "guiscale", "update", "updateHelp", "version", "folder", "help");
}
return null;
}
diff --git a/src/main/java/eu/olli/cowmoonication/config/MooConfig.java b/src/main/java/eu/olli/cowmoonication/config/MooConfig.java
index 97cea9b..e9b2146 100644
--- a/src/main/java/eu/olli/cowmoonication/config/MooConfig.java
+++ b/src/main/java/eu/olli/cowmoonication/config/MooConfig.java
@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.List;
public class MooConfig {
+ public static boolean doUpdateCheck;
public static boolean filterFriendNotifications;
private static String[] bestFriends;
private static Configuration cfg = null;
@@ -69,6 +70,9 @@ public class MooConfig {
cfg.load();
}
+ final boolean DO_UPDATE_CHECK = true;
+ Property propDoUpdateCheck = cfg.get(Configuration.CATEGORY_CLIENT, "doUpdateCheck", DO_UPDATE_CHECK, "Check for mod updates?");
+
final boolean FILTER_FRIEND_NOTIFICATIONS = true;
Property propFilterFriendNotify = cfg.get(Configuration.CATEGORY_CLIENT, "filterFriendNotifications", FILTER_FRIEND_NOTIFICATIONS, "Set to false to receive all login/logout messages, set to true to only get notifications of 'best friends' joining/leaving");
@@ -77,15 +81,18 @@ public class MooConfig {
propBestFriends.setValidationPattern(Utils.VALID_USERNAME);
List<String> propOrderGeneral = new ArrayList<>();
+ propOrderGeneral.add(propDoUpdateCheck.getName());
propOrderGeneral.add(propFilterFriendNotify.getName());
propOrderGeneral.add(propBestFriends.getName());
cfg.setCategoryPropertyOrder(Configuration.CATEGORY_CLIENT, propOrderGeneral);
if (readFieldsFromConfig) {
+ doUpdateCheck = propDoUpdateCheck.getBoolean(DO_UPDATE_CHECK);
filterFriendNotifications = propFilterFriendNotify.getBoolean(FILTER_FRIEND_NOTIFICATIONS);
bestFriends = propBestFriends.getStringList();
}
+ propDoUpdateCheck.set(doUpdateCheck);
propFilterFriendNotify.set(filterFriendNotifications);
propBestFriends.set(bestFriends);
diff --git a/src/main/java/eu/olli/cowmoonication/config/MooGuiConfig.java b/src/main/java/eu/olli/cowmoonication/config/MooGuiConfig.java
index e7b7862..c8c68c1 100644
--- a/src/main/java/eu/olli/cowmoonication/config/MooGuiConfig.java
+++ b/src/main/java/eu/olli/cowmoonication/config/MooGuiConfig.java
@@ -24,7 +24,6 @@ public class MooGuiConfig extends GuiConfig {
// optional: add buttons and initialize fields
}
-
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
super.drawScreen(mouseX, mouseY, partialTicks);
diff --git a/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java b/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java
index 83b3890..54f8025 100644
--- a/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java
+++ b/src/main/java/eu/olli/cowmoonication/listener/ChatListener.java
@@ -36,8 +36,9 @@ public class ChatListener {
public void onLogInOutMessage(ClientChatReceivedEvent e) {
if (e.type != 2 && MooConfig.filterFriendNotifications) { // normal chat or system msg
String text = e.message.getUnformattedText();
- if (text.endsWith(" joined.") || text.endsWith(" left.") // Hypixel
- || text.endsWith(" joined the game") || text.endsWith(" left the game.")) { // Spigot
+ if (text.length() < 42 && // to prevent the party disbanded message from being filtered: "The party was disbanded because all invites have expired and all members have left."
+ (text.endsWith(" joined.") || text.endsWith(" left.") // Hypixel
+ || text.endsWith(" joined the game") || text.endsWith(" left the game."))) { // Spigot
// TODO maybe check which server thePlayer is on and check for logout pattern accordingly
int nameEnd = text.indexOf(" joined");
if (nameEnd == -1) {
@@ -76,7 +77,7 @@ public class ChatListener {
if (lastTypedChars.equalsIgnoreCase("/r ")) {
// replace /r with /msg <last user>
main.getUtils().sendAboveChatMessage("Sending message to " + lastPMSender + "!");
- Minecraft.getMinecraft().displayGuiScreen(new GuiChat("/msg " + lastPMSender + " "));
+ Minecraft.getMinecraft().displayGuiScreen(new GuiChat("/w " + lastPMSender + " "));
}
} else if (Keyboard.getEventKey() == Keyboard.KEY_BACK) { // Backspace
lastTypedChars = lastTypedChars.substring(0, Math.max(lastTypedChars.length() - 1, 0));
diff --git a/src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java b/src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java
new file mode 100644
index 0000000..b817ed8
--- /dev/null
+++ b/src/main/java/eu/olli/cowmoonication/listener/PlayerListener.java
@@ -0,0 +1,18 @@
+package eu.olli.cowmoonication.listener;
+
+import eu.olli.cowmoonication.Cowmoonication;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.network.FMLNetworkEvent;
+
+public class PlayerListener {
+ private final Cowmoonication main;
+
+ public PlayerListener(Cowmoonication main) {
+ this.main = main;
+ }
+
+ @SubscribeEvent
+ public void onServerJoin(FMLNetworkEvent.ClientConnectedToServerEvent e) {
+ main.getVersionChecker().runUpdateCheck(false);
+ }
+}
diff --git a/src/main/java/eu/olli/cowmoonication/util/Utils.java b/src/main/java/eu/olli/cowmoonication/util/Utils.java
index d10c2ed..60e2ea3 100644
--- a/src/main/java/eu/olli/cowmoonication/util/Utils.java
+++ b/src/main/java/eu/olli/cowmoonication/util/Utils.java
@@ -7,6 +7,7 @@ import net.minecraft.util.IChatComponent;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.common.MinecraftForge;
+import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -14,11 +15,13 @@ public class Utils {
public static final Pattern VALID_USERNAME = Pattern.compile("^[\\w]{1,16}$");
private static final Pattern USELESS_JSON_CONTENT_PATTERN = Pattern.compile("\"[A-Za-z]+\":false,?");
private final Cowmoonication main;
+ private final File modsDir;
private String[] aboveChatMessage;
private long aboveChatMessageExpiration;
- public Utils(Cowmoonication main) {
+ public Utils(Cowmoonication main, File sourceFile) {
this.main = main;
+ modsDir = sourceFile.getParentFile();
}
public void sendMessage(String text) {
@@ -55,4 +58,8 @@ public class Utils {
Matcher jsonMatcher = USELESS_JSON_CONTENT_PATTERN.matcher(component);
return jsonMatcher.replaceAll("");
}
+
+ public File getModsFolder() {
+ return modsDir;
+ }
}
diff --git a/src/main/java/eu/olli/cowmoonication/util/VersionChecker.java b/src/main/java/eu/olli/cowmoonication/util/VersionChecker.java
new file mode 100644
index 0000000..5c29ae5
--- /dev/null
+++ b/src/main/java/eu/olli/cowmoonication/util/VersionChecker.java
@@ -0,0 +1,140 @@
+package eu.olli.cowmoonication.util;
+
+import eu.olli.cowmoonication.Cowmoonication;
+import eu.olli.cowmoonication.config.MooConfig;
+import net.minecraft.client.Minecraft;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.event.HoverEvent;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatStyle;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraftforge.common.ForgeModContainer;
+import net.minecraftforge.common.ForgeVersion;
+import net.minecraftforge.fml.common.Loader;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @see ForgeVersion
+ */
+public class VersionChecker {
+ /**
+ * Cooldown between to update checks in minutes
+ */
+ private static final int CHECK_COOLDOWN = 15;
+ private static final String CHANGELOG_URL = "https://github.com/cow-mc/Cowmoonication/blob/master/CHANGELOG.md";
+ private final Cowmoonication main;
+ private long lastCheck;
+ private String newVersion;
+ private String downloadUrl;
+
+ public VersionChecker(Cowmoonication main) {
+ this.main = main;
+ this.lastCheck = Minecraft.getSystemTime();
+ newVersion = "[newVersion]";
+ downloadUrl = "https://github.com/cow-mc/Cowmoonication/releases";
+ }
+
+ public boolean runUpdateCheck(boolean isCommandTriggered) {
+ if (isCommandTriggered || (!ForgeModContainer.disableVersionCheck && MooConfig.doUpdateCheck)) {
+ Runnable handleResults = () -> main.getVersionChecker().handleVersionStatus(isCommandTriggered);
+
+ long now = Minecraft.getSystemTime();
+
+ // only re-run if last check was >CHECK_COOLDOWN minutes ago#
+ if (getNextCheck() < 0) { // next allowed check is "in the past", so we're good to go
+ lastCheck = now;
+ ForgeVersion.startVersionCheck();
+
+ // check status after 5 seconds - hopefully that's enough to check
+ new TickDelay(handleResults, 5 * 20);
+ return true;
+ } else {
+ new TickDelay(handleResults, 1);
+ }
+ }
+ return false;
+ }
+
+ public void handleVersionStatus(boolean isCommandTriggered) {
+ ForgeVersion.CheckResult versionResult = ForgeVersion.getResult(Loader.instance().activeModContainer());
+ if (versionResult.target != null) {
+ newVersion = versionResult.target.toString();
+ downloadUrl = "https://github.com/cow-mc/Cowmoonication/releases/download/v" + newVersion + "/" + Cowmoonication.MODNAME + "-" + newVersion + ".jar";
+ }
+
+ IChatComponent statusMsg = null;
+
+ if (isCommandTriggered) {
+ if (versionResult.status == ForgeVersion.Status.UP_TO_DATE) {
+ // up to date
+ statusMsg = new ChatComponentText("\u2714 You're running the latest version (" + Cowmoonication.VERSION + ").").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GREEN));
+ } else if (versionResult.status == ForgeVersion.Status.PENDING) {
+ // pending
+ statusMsg = new ChatComponentText("\u279C " + "Version check either failed or is still running.").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.YELLOW))
+ .appendSibling(new ChatComponentText("\n \u278A Check for results again in a few seconds with " + EnumChatFormatting.GOLD + "/moo version").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.YELLOW)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/moo version"))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Run " + EnumChatFormatting.GOLD + "/moo version")))))
+ .appendSibling(new ChatComponentText("\n \u278B Re-run update check with " + EnumChatFormatting.GOLD + "/moo update").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.YELLOW)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/moo update"))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Run " + EnumChatFormatting.GOLD + "/moo update")))));
+ } else if (versionResult.status == ForgeVersion.Status.FAILED) {
+ // check failed
+ statusMsg = new ChatComponentText("\u2716 Version check failed for an unknown reason. Check again in a few seconds with ").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED))
+ .appendSibling(new ChatComponentText("/moo update").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.GOLD)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/moo update"))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Run " + EnumChatFormatting.GOLD + "/moo update")))));
+ }
+ }
+ if (versionResult.status == ForgeVersion.Status.OUTDATED || versionResult.status == ForgeVersion.Status.BETA_OUTDATED) {
+ // outdated
+ IChatComponent spacer = new ChatComponentText(" ").setChatStyle(new ChatStyle().setParentStyle(null));
+
+ IChatComponent text = new ChatComponentText("\u279C New version of " + EnumChatFormatting.DARK_GREEN + "Cowmoonication " + EnumChatFormatting.GREEN + "available (" + Cowmoonication.VERSION + " \u27A1 " + newVersion + ")\n").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GREEN));
+
+ IChatComponent download = new ChatComponentText("[Download]").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.DARK_GREEN).setBold(true)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, downloadUrl))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Download the latest version of Cowmoonication"))));
+
+ IChatComponent changelog = new ChatComponentText("[Changelog]").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.DARK_AQUA).setBold(true)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, CHANGELOG_URL))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "View changelog"))));
+
+ IChatComponent updateInstructions = new ChatComponentText("[Update instructions]").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.GOLD).setBold(true)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/moo updateHelp"))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Run " + EnumChatFormatting.GOLD + "/moo updateHelp"))));
+
+ IChatComponent openModsFolder = new ChatComponentText("\n[Open Mods folder]").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.GREEN).setBold(true)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/moo folder"))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "Open mods folder with command " + EnumChatFormatting.GOLD + "/moo folder\n\u279C Click to open mods folder"))));
+
+ statusMsg = text.appendSibling(download).appendSibling(spacer).appendSibling(changelog).appendSibling(spacer).appendSibling(updateInstructions).appendSibling(spacer).appendSibling(openModsFolder);
+ }
+
+ if (statusMsg != null) {
+ main.getUtils().sendMessage(statusMsg);
+ }
+ }
+
+ public long getNextCheck() {
+ long cooldown = TimeUnit.MINUTES.toMillis(CHECK_COOLDOWN);
+ long systemTime = Minecraft.getSystemTime();
+ return cooldown - (systemTime - lastCheck);
+ }
+
+ public String getNewVersion() {
+ return newVersion;
+ }
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+}