Initial commit
This commit is contained in:
		
							
								
								
									
										31
									
								
								src/main/java/net/knarcraft/knarlib/KnarLib.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/java/net/knarcraft/knarlib/KnarLib.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
package net.knarcraft.knarlib;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.plugin.java.JavaPlugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * KnarLib's main class
 | 
			
		||||
 */
 | 
			
		||||
public final class KnarLib {
 | 
			
		||||
 | 
			
		||||
    private static JavaPlugin plugin;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a plugin instance for use with the bukkit scheduler or similar
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>A plugin instance</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static JavaPlugin getPlugin() {
 | 
			
		||||
        return plugin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets an instance of the plugin used with KnarLib
 | 
			
		||||
     *
 | 
			
		||||
     * @param plugin <p>The plugin instance to use</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void setPlugin(final JavaPlugin plugin) {
 | 
			
		||||
        KnarLib.plugin = plugin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,95 @@
 | 
			
		||||
package net.knarcraft.knarlib.formatting;
 | 
			
		||||
 | 
			
		||||
import net.knarcraft.knarlib.KnarLib;
 | 
			
		||||
import net.md_5.bungee.api.ChatColor;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A formatter for formatting displayed messages
 | 
			
		||||
 */
 | 
			
		||||
public final class StringFormatter {
 | 
			
		||||
 | 
			
		||||
    private final static String pluginName = KnarLib.getPlugin().getDescription().getName();
 | 
			
		||||
 | 
			
		||||
    private StringFormatter() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a message signifying a successful action
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender  <p>The command sender to display the message to</p>
 | 
			
		||||
     * @param message <p>The translatable message to display</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void displaySuccessMessage(CommandSender sender, TranslatableTimeUnit message) {
 | 
			
		||||
        sender.sendMessage(ChatColor.GREEN + getFormattedMessage(Translator.getTranslatedMessage(message)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a message signifying a successful action
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender  <p>The command sender to display the message to</p>
 | 
			
		||||
     * @param message <p>The raw message to display</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void displaySuccessMessage(CommandSender sender, String message) {
 | 
			
		||||
        sender.sendMessage(ChatColor.GREEN + getFormattedMessage(message));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays a message signifying an unsuccessful action
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender  <p>The command sender to display the message to</p>
 | 
			
		||||
     * @param message <p>The translatable message to display</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void displayErrorMessage(CommandSender sender, TranslatableTimeUnit message) {
 | 
			
		||||
        sender.sendMessage(ChatColor.DARK_RED + getFormattedMessage(Translator.getTranslatedMessage(message)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the formatted version of any chat message
 | 
			
		||||
     *
 | 
			
		||||
     * @param message <p>The message to format</p>
 | 
			
		||||
     * @return <p>The formatted message</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static String getFormattedMessage(String message) {
 | 
			
		||||
        return "[" + pluginName + "] " + ChatColor.RESET + translateColors(message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Translates & color codes to proper colors
 | 
			
		||||
     *
 | 
			
		||||
     * @param input <p>The input string to translate colors for</p>
 | 
			
		||||
     * @return <p>The input with color codes translated</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static String translateColors(String input) {
 | 
			
		||||
        return ChatColor.translateAlternateColorCodes('&', input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Replaces a placeholder in a string
 | 
			
		||||
     *
 | 
			
		||||
     * @param input       <p>The input string to replace in</p>
 | 
			
		||||
     * @param placeholder <p>The placeholder to replace</p>
 | 
			
		||||
     * @param replacement <p>The replacement value</p>
 | 
			
		||||
     * @return <p>The input string with the placeholder replaced</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String replacePlaceholder(String input, String placeholder, String replacement) {
 | 
			
		||||
        return input.replace(placeholder, replacement);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Replaces placeholders in a string
 | 
			
		||||
     *
 | 
			
		||||
     * @param input        <p>The input string to replace in</p>
 | 
			
		||||
     * @param placeholders <p>The placeholders to replace</p>
 | 
			
		||||
     * @param replacements <p>The replacement values</p>
 | 
			
		||||
     * @return <p>The input string with placeholders replaced</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
 | 
			
		||||
        for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
 | 
			
		||||
            input = replacePlaceholder(input, placeholders[i], replacements[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return input;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,99 @@
 | 
			
		||||
package net.knarcraft.knarlib.formatting;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static net.knarcraft.knarlib.formatting.StringFormatter.replacePlaceholder;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A utility for formatting a string specifying an amount of time
 | 
			
		||||
 */
 | 
			
		||||
public final class TimeFormatter {
 | 
			
		||||
 | 
			
		||||
    private static Map<Double, TranslatableTimeUnit[]> timeUnits;
 | 
			
		||||
    private static List<Double> sortedUnits;
 | 
			
		||||
 | 
			
		||||
    private TimeFormatter() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the string used for displaying this sign's duration
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The string used for displaying this sign's duration</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String getDurationString(int duration) {
 | 
			
		||||
        if (duration == 0) {
 | 
			
		||||
            return Translator.getTranslatedMessage(TranslatableTimeUnit.UNIT_NOW);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (sortedUnits == null) {
 | 
			
		||||
                initializeUnits();
 | 
			
		||||
            }
 | 
			
		||||
            for (Double unit : sortedUnits) {
 | 
			
		||||
                if (duration / unit >= 1) {
 | 
			
		||||
                    double units = round(duration / unit);
 | 
			
		||||
                    return formatDurationString(units, timeUnits.get(unit)[units == 1 ? 0 : 1],
 | 
			
		||||
                            (units * 10) % 10 == 0);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return formatDurationString(duration, TranslatableTimeUnit.UNIT_SECONDS, false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Rounds a number to its last two digits
 | 
			
		||||
     *
 | 
			
		||||
     * @param number <p>The number to round</p>
 | 
			
		||||
     * @return <p>The rounded number</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static double round(double number) {
 | 
			
		||||
        return Math.round(number * 100.0) / 100.0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Formats a duration string
 | 
			
		||||
     *
 | 
			
		||||
     * @param duration            <p>The duration to display</p>
 | 
			
		||||
     * @param translatableMessage <p>The time unit to display</p>
 | 
			
		||||
     * @param castToInt           <p>Whether to cast the duration to an int</p>
 | 
			
		||||
     * @return <p>The formatted duration string</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static String formatDurationString(double duration, TranslatableTimeUnit translatableMessage, boolean castToInt) {
 | 
			
		||||
        String durationFormat = Translator.getTranslatedMessage(TranslatableTimeUnit.DURATION_FORMAT);
 | 
			
		||||
        durationFormat = replacePlaceholder(durationFormat, "{unit}",
 | 
			
		||||
                Translator.getTranslatedMessage(translatableMessage));
 | 
			
		||||
        return replacePlaceholder(durationFormat, "{time}", castToInt ? String.valueOf((int) duration) :
 | 
			
		||||
                String.valueOf(duration));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the mapping of available time units for formatting permission sign duration
 | 
			
		||||
     */
 | 
			
		||||
    private static void initializeUnits() {
 | 
			
		||||
        double minute = 60;
 | 
			
		||||
        double hour = 60 * minute;
 | 
			
		||||
        double day = 24 * hour;
 | 
			
		||||
        double week = 7 * day;
 | 
			
		||||
        double month = 4 * week;
 | 
			
		||||
        double year = 365 * day;
 | 
			
		||||
        double decade = 10 * year;
 | 
			
		||||
 | 
			
		||||
        timeUnits = new HashMap<>();
 | 
			
		||||
        timeUnits.put(decade, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_DECADE, TranslatableTimeUnit.UNIT_DECADES});
 | 
			
		||||
        timeUnits.put(year, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_YEAR, TranslatableTimeUnit.UNIT_YEARS});
 | 
			
		||||
        timeUnits.put(month, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_MONTH, TranslatableTimeUnit.UNIT_MONTHS});
 | 
			
		||||
        timeUnits.put(week, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_WEEK, TranslatableTimeUnit.UNIT_WEEKS});
 | 
			
		||||
        timeUnits.put(day, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_DAY, TranslatableTimeUnit.UNIT_DAYS});
 | 
			
		||||
        timeUnits.put(hour, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_HOUR, TranslatableTimeUnit.UNIT_HOURS});
 | 
			
		||||
        timeUnits.put(minute, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_MINUTE, TranslatableTimeUnit.UNIT_MINUTES});
 | 
			
		||||
        timeUnits.put(1D, new TranslatableTimeUnit[]{TranslatableTimeUnit.UNIT_SECOND, TranslatableTimeUnit.UNIT_SECONDS});
 | 
			
		||||
 | 
			
		||||
        sortedUnits = new ArrayList<>(timeUnits.keySet());
 | 
			
		||||
        Collections.sort(sortedUnits);
 | 
			
		||||
        Collections.reverse(sortedUnits);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,26 @@
 | 
			
		||||
package net.knarcraft.knarlib.formatting;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A message which can be translated
 | 
			
		||||
 */
 | 
			
		||||
public interface TranslatableMessage {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the name of this translatable message
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This is automatically overridden by enums. This should not be overridden manually!</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The name of this translatable message</p>
 | 
			
		||||
     */
 | 
			
		||||
    String name();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets all translatable messages
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This should return Enum.values() for the class. This is basically a workaround to get all enum values.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>All translatable messages</p>
 | 
			
		||||
     */
 | 
			
		||||
    TranslatableMessage[] getAllMessages();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,106 @@
 | 
			
		||||
package net.knarcraft.knarlib.formatting;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An enum containing all translatable time units
 | 
			
		||||
 *
 | 
			
		||||
 * <p>These time units must have a translatable message to use the time formatter</p>
 | 
			
		||||
 */
 | 
			
		||||
public enum TranslatableTimeUnit implements TranslatableMessage {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The format for displaying the exact duration of a blacksmith's cool-down or delay
 | 
			
		||||
     */
 | 
			
		||||
    DURATION_FORMAT,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 0 seconds
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_NOW,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 second
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_SECOND,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of seconds
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_SECONDS,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 minute
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_MINUTE,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of minutes
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_MINUTES,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 hour
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_HOUR,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of hours
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_HOURS,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 day
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_DAY,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of days
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_DAYS,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 week
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_WEEK,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of weeks
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_WEEKS,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 month
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_MONTH,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of months
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_MONTHS,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 year
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_YEAR,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of years
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_YEARS,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for 1 decade
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_DECADE,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The text to display for a number of decades
 | 
			
		||||
     */
 | 
			
		||||
    UNIT_DECADES,
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TranslatableMessage[] getAllMessages() {
 | 
			
		||||
        return TranslatableTimeUnit.values();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										139
									
								
								src/main/java/net/knarcraft/knarlib/formatting/Translator.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/main/java/net/knarcraft/knarlib/formatting/Translator.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,139 @@
 | 
			
		||||
package net.knarcraft.knarlib.formatting;
 | 
			
		||||
 | 
			
		||||
import net.knarcraft.knarlib.KnarLib;
 | 
			
		||||
import net.knarcraft.knarlib.property.ColorConversion;
 | 
			
		||||
import net.knarcraft.knarlib.util.ColorHelper;
 | 
			
		||||
import net.knarcraft.knarlib.util.FileHelper;
 | 
			
		||||
import org.bukkit.configuration.file.YamlConfiguration;
 | 
			
		||||
import org.bukkit.plugin.java.JavaPlugin;
 | 
			
		||||
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.FileNotFoundException;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A tool to get strings translated to the correct language
 | 
			
		||||
 */
 | 
			
		||||
public final class Translator {
 | 
			
		||||
 | 
			
		||||
    private static List<TranslatableMessage> messageCategories;
 | 
			
		||||
    private static Map<TranslatableMessage, String> translatedMessages;
 | 
			
		||||
    private static Map<TranslatableMessage, String> backupTranslatedMessages;
 | 
			
		||||
 | 
			
		||||
    private Translator() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers all translatable messages in the given message category
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This should be run for one enum of every class extending TranslatableMessage. This allows the translator to
 | 
			
		||||
     * look for translations for any enum in the category.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param translatableMessage <p>A translatable message in the category to register</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void registerMessageCategory(TranslatableMessage translatableMessage) {
 | 
			
		||||
        messageCategories.add(translatableMessage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads the languages used by this translator
 | 
			
		||||
     */
 | 
			
		||||
    public static void loadLanguages(String selectedLanguage) {
 | 
			
		||||
        backupTranslatedMessages = loadTranslatedMessages("en");
 | 
			
		||||
        translatedMessages = loadCustomTranslatedMessages(selectedLanguage);
 | 
			
		||||
        if (translatedMessages == null) {
 | 
			
		||||
            translatedMessages = loadTranslatedMessages(selectedLanguage);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a translated version of the given translatable message
 | 
			
		||||
     *
 | 
			
		||||
     * @param translatableMessage <p>The message to translate</p>
 | 
			
		||||
     * @return <p>The translated message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String getTranslatedMessage(TranslatableMessage translatableMessage) {
 | 
			
		||||
        if (translatedMessages == null) {
 | 
			
		||||
            return "Translated strings not loaded";
 | 
			
		||||
        }
 | 
			
		||||
        String translatedMessage;
 | 
			
		||||
        if (translatedMessages.containsKey(translatableMessage)) {
 | 
			
		||||
            translatedMessage = translatedMessages.get(translatableMessage);
 | 
			
		||||
        } else if (backupTranslatedMessages.containsKey(translatableMessage)) {
 | 
			
		||||
            translatedMessage = backupTranslatedMessages.get(translatableMessage);
 | 
			
		||||
        } else {
 | 
			
		||||
            translatedMessage = translatableMessage.toString();
 | 
			
		||||
        }
 | 
			
		||||
        return ColorHelper.translateColorCodes(translatedMessage, ColorConversion.RGB);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads all translated messages for the given language
 | 
			
		||||
     *
 | 
			
		||||
     * @param language <p>The language chosen by the user</p>
 | 
			
		||||
     * @return <p>A mapping of all strings for the given language</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static Map<TranslatableMessage, String> loadTranslatedMessages(String language) {
 | 
			
		||||
        try {
 | 
			
		||||
            BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
 | 
			
		||||
            return loadTranslatableMessages(language, reader);
 | 
			
		||||
        } catch (FileNotFoundException e) {
 | 
			
		||||
            KnarLib.getPlugin().getLogger().log(Level.SEVERE, "Unable to load translated messages");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tries to load translated messages from a custom strings.yml file
 | 
			
		||||
     *
 | 
			
		||||
     * @param language <p>The selected language</p>
 | 
			
		||||
     * @return <p>The loaded translated strings, or null if no custom language file exists</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static Map<TranslatableMessage, String> loadCustomTranslatedMessages(String language) {
 | 
			
		||||
        JavaPlugin instance = KnarLib.getPlugin();
 | 
			
		||||
 | 
			
		||||
        File strings = new File(instance.getDataFolder(), "strings.yml");
 | 
			
		||||
        if (!strings.exists()) {
 | 
			
		||||
            instance.getLogger().log(Level.FINEST, "Strings file not found");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            instance.getLogger().log(Level.INFO, "Loading custom strings...");
 | 
			
		||||
            return loadTranslatableMessages(language, new BufferedReader(new InputStreamReader(new FileInputStream(strings))));
 | 
			
		||||
        } catch (FileNotFoundException e) {
 | 
			
		||||
            instance.getLogger().log(Level.WARNING, "Unable to load custom messages");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads translatable messages from the given reader
 | 
			
		||||
     *
 | 
			
		||||
     * @param language <p>The selected language</p>
 | 
			
		||||
     * @param reader   <p>The buffered reader to read from</p>
 | 
			
		||||
     * @return <p>The loaded translated strings</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static Map<TranslatableMessage, String> loadTranslatableMessages(String language, BufferedReader reader) {
 | 
			
		||||
        Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
 | 
			
		||||
        YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
 | 
			
		||||
 | 
			
		||||
        for (TranslatableMessage translatableMessageCategories : messageCategories) {
 | 
			
		||||
            for (TranslatableMessage translatableMessage : translatableMessageCategories.getAllMessages()) {
 | 
			
		||||
                String translated = configuration.getString(language + "." + translatableMessage.name());
 | 
			
		||||
                if (translated != null) {
 | 
			
		||||
                    translatedMessages.put(translatableMessage, translated);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return translatedMessages;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
package net.knarcraft.knarlib.property;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An enum representing the different types of color conversions available
 | 
			
		||||
 */
 | 
			
		||||
public enum ColorConversion {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * No conversion of colors
 | 
			
		||||
     */
 | 
			
		||||
    NONE,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Ampersand color codes are converted into colors
 | 
			
		||||
     */
 | 
			
		||||
    NORMAL,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Ampersand color codes, and hexadecimal color codes are converted into colors
 | 
			
		||||
     */
 | 
			
		||||
    RGB
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										89
									
								
								src/main/java/net/knarcraft/knarlib/util/ColorHelper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/main/java/net/knarcraft/knarlib/util/ColorHelper.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
package net.knarcraft.knarlib.util;
 | 
			
		||||
 | 
			
		||||
import net.knarcraft.knarlib.property.ColorConversion;
 | 
			
		||||
import net.md_5.bungee.api.ChatColor;
 | 
			
		||||
import org.bukkit.Color;
 | 
			
		||||
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A helper class for dealing with colors
 | 
			
		||||
 */
 | 
			
		||||
public final class ColorHelper {
 | 
			
		||||
 | 
			
		||||
    private static boolean requireAmpersandInHexColors = false;
 | 
			
		||||
 | 
			
		||||
    private ColorHelper() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Inverts the given color
 | 
			
		||||
     *
 | 
			
		||||
     * @param color <p>The color to invert</p>
 | 
			
		||||
     * @return <p>The inverted color</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static Color invert(Color color) {
 | 
			
		||||
        return color.setRed(255 - color.getRed()).setGreen(255 - color.getGreen()).setBlue(255 - color.getBlue());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the chat color corresponding to the given color
 | 
			
		||||
     *
 | 
			
		||||
     * @param color <p>The color to convert into a chat color</p>
 | 
			
		||||
     * @return <p>The resulting chat color</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static ChatColor fromColor(Color color) {
 | 
			
		||||
        return ChatColor.of(String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets whether to require ampersand in hex color
 | 
			
		||||
     *
 | 
			
		||||
     * <p>If set to true, &#f35336 will be treated as a color code, but #f35336 won't. By default, this is set to false,
 | 
			
		||||
     * meaning that both are treated as color codes.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param requireAmpersandInHexColors <p>True if hex colors should require an ampersand</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void setRequireAmpersandInHexColors(boolean requireAmpersandInHexColors) {
 | 
			
		||||
        ColorHelper.requireAmpersandInHexColors = requireAmpersandInHexColors;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Translates color codes according to the given color conversion setting
 | 
			
		||||
     *
 | 
			
		||||
     * @param message         <p>The message to translate color codes for</p>
 | 
			
		||||
     * @param colorConversion <p>The type of color conversion to apply</p>
 | 
			
		||||
     * @return <p>The string with color codes applied</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String translateColorCodes(String message, ColorConversion colorConversion) {
 | 
			
		||||
        return switch (colorConversion) {
 | 
			
		||||
            case NONE -> message;
 | 
			
		||||
            case NORMAL -> ChatColor.translateAlternateColorCodes('&', message);
 | 
			
		||||
            case RGB -> translateAllColorCodes(message);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Translates all found color codes to formatting in a string
 | 
			
		||||
     *
 | 
			
		||||
     * @param message <p>The string to search for color codes</p>
 | 
			
		||||
     * @return <p>The message with color codes translated</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static String translateAllColorCodes(String message) {
 | 
			
		||||
        message = ChatColor.translateAlternateColorCodes('&', message);
 | 
			
		||||
        Pattern pattern;
 | 
			
		||||
        if (requireAmpersandInHexColors) {
 | 
			
		||||
            pattern = Pattern.compile("(&#[a-fA-F0-9]{6})");
 | 
			
		||||
        } else {
 | 
			
		||||
            pattern = Pattern.compile("(&?#[a-fA-F0-9]{6})");
 | 
			
		||||
        }
 | 
			
		||||
        Matcher matcher = pattern.matcher(message);
 | 
			
		||||
        while (matcher.find()) {
 | 
			
		||||
            message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group()));
 | 
			
		||||
        }
 | 
			
		||||
        return message;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										141
									
								
								src/main/java/net/knarcraft/knarlib/util/FileHelper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/main/java/net/knarcraft/knarlib/util/FileHelper.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
package net.knarcraft.knarlib.util;
 | 
			
		||||
 | 
			
		||||
import net.md_5.bungee.api.ChatColor;
 | 
			
		||||
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.io.BufferedWriter;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.FileNotFoundException;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.io.OutputStreamWriter;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A helper class for dealing with files
 | 
			
		||||
 */
 | 
			
		||||
public final class FileHelper {
 | 
			
		||||
 | 
			
		||||
    private FileHelper() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a buffered reader for
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>A buffered read for reading the file</p>
 | 
			
		||||
     * @throws FileNotFoundException <p>If unable to get an input stream for the given file</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static BufferedReader getBufferedReaderForInternalFile(String file) throws FileNotFoundException {
 | 
			
		||||
        InputStream inputStream = getInputStreamForInternalFile(file);
 | 
			
		||||
        if (inputStream == null) {
 | 
			
		||||
            throw new FileNotFoundException("Unable to read the given file");
 | 
			
		||||
        }
 | 
			
		||||
        return getBufferedReaderFromInputStream(inputStream);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets an input stream from a string pointing to an internal file
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This is used for getting an input stream for reading a file contained within the compiled .jar file. The file
 | 
			
		||||
     * should be in the resources directory, and the file path should start with a forward slash ("/") character.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param file <p>The file to read</p>
 | 
			
		||||
     * @return <p>An input stream for the file</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static InputStream getInputStreamForInternalFile(String file) {
 | 
			
		||||
        return FileHelper.class.getResourceAsStream(file);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a buffered reader from a string pointing to a file
 | 
			
		||||
     *
 | 
			
		||||
     * @param file <p>The file to read</p>
 | 
			
		||||
     * @return <p>A buffered reader reading the file</p>
 | 
			
		||||
     * @throws FileNotFoundException <p>If the given file does not exist</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static BufferedReader getBufferedReaderFromString(String file) throws FileNotFoundException {
 | 
			
		||||
        FileInputStream fileInputStream = new FileInputStream(file);
 | 
			
		||||
        return getBufferedReaderFromInputStream(fileInputStream);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a buffered reader given an input stream
 | 
			
		||||
     *
 | 
			
		||||
     * @param inputStream <p>The input stream to read</p>
 | 
			
		||||
     * @return <p>A buffered reader reading the input stream</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static BufferedReader getBufferedReaderFromInputStream(InputStream inputStream) {
 | 
			
		||||
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
 | 
			
		||||
        return new BufferedReader(inputStreamReader);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a buffered writer from a string pointing to a file
 | 
			
		||||
     *
 | 
			
		||||
     * @param file <p>The file to write to</p>
 | 
			
		||||
     * @return <p>A buffered writer writing to the file</p>
 | 
			
		||||
     * @throws FileNotFoundException <p>If the file does not exist</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static BufferedWriter getBufferedWriterFromString(String file) throws FileNotFoundException {
 | 
			
		||||
        FileOutputStream fileOutputStream = new FileOutputStream(file);
 | 
			
		||||
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
 | 
			
		||||
        return new BufferedWriter(outputStreamWriter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reads key/value pairs from an input stream
 | 
			
		||||
     *
 | 
			
		||||
     * @param bufferedReader <p>The buffered reader to read</p>
 | 
			
		||||
     * @return <p>A map containing the read pairs</p>
 | 
			
		||||
     * @throws IOException <p>If unable to read from the stream</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static Map<String, String> readKeyValuePairs(BufferedReader bufferedReader, String separator, boolean translateColorCodes) throws IOException {
 | 
			
		||||
        Map<String, String> readPairs = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
        String line = bufferedReader.readLine();
 | 
			
		||||
        boolean firstLine = true;
 | 
			
		||||
        while (line != null) {
 | 
			
		||||
            //Strip UTF BOM from the first line
 | 
			
		||||
            if (firstLine) {
 | 
			
		||||
                line = removeUTF8BOM(line);
 | 
			
		||||
                firstLine = false;
 | 
			
		||||
            }
 | 
			
		||||
            //Split at first separator
 | 
			
		||||
            int separatorIndex = line.indexOf(separator);
 | 
			
		||||
            if (separatorIndex == -1) {
 | 
			
		||||
                line = bufferedReader.readLine();
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //Read the line
 | 
			
		||||
            String key = line.substring(0, separatorIndex);
 | 
			
		||||
            String value = ChatColor.translateAlternateColorCodes('&', line.substring(separatorIndex + 1));
 | 
			
		||||
            readPairs.put(key, value);
 | 
			
		||||
 | 
			
		||||
            line = bufferedReader.readLine();
 | 
			
		||||
        }
 | 
			
		||||
        bufferedReader.close();
 | 
			
		||||
 | 
			
		||||
        return readPairs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Removes the UTF-8 Byte Order Mark if present
 | 
			
		||||
     *
 | 
			
		||||
     * @param string <p>The string to remove the BOM from</p>
 | 
			
		||||
     * @return <p>A string guaranteed without a BOM</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static String removeUTF8BOM(String string) {
 | 
			
		||||
        String UTF8_BOM = "\uFEFF";
 | 
			
		||||
        if (string.startsWith(UTF8_BOM)) {
 | 
			
		||||
            string = string.substring(1);
 | 
			
		||||
        }
 | 
			
		||||
        return string;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,48 @@
 | 
			
		||||
package net.knarcraft.knarlib.util;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper class for getting string lists required for auto-completion
 | 
			
		||||
 */
 | 
			
		||||
public final class TabCompletionHelper {
 | 
			
		||||
 | 
			
		||||
    private TabCompletionHelper() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds tab complete values that contain the typed text
 | 
			
		||||
     *
 | 
			
		||||
     * @param values    <p>The values to filter</p>
 | 
			
		||||
     * @param typedText <p>The text the player has started typing</p>
 | 
			
		||||
     * @return <p>The given string values that contain the player's typed text</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static List<String> filterMatchingContains(List<String> values, String typedText) {
 | 
			
		||||
        List<String> configValues = new ArrayList<>();
 | 
			
		||||
        for (String value : values) {
 | 
			
		||||
            if (value.toLowerCase().contains(typedText.toLowerCase())) {
 | 
			
		||||
                configValues.add(value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return configValues;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds tab complete values that match the start of the typed text
 | 
			
		||||
     *
 | 
			
		||||
     * @param values    <p>The values to filter</p>
 | 
			
		||||
     * @param typedText <p>The text the player has started typing</p>
 | 
			
		||||
     * @return <p>The given string values that start with the player's typed text</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static List<String> filterMatchingStartsWith(List<String> values, String typedText) {
 | 
			
		||||
        List<String> configValues = new ArrayList<>();
 | 
			
		||||
        for (String value : values) {
 | 
			
		||||
            if (value.toLowerCase().startsWith(typedText.toLowerCase())) {
 | 
			
		||||
                configValues.add(value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return configValues;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										102
									
								
								src/main/java/net/knarcraft/knarlib/util/UpdateChecker.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/main/java/net/knarcraft/knarlib/util/UpdateChecker.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
package net.knarcraft.knarlib.util;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.plugin.Plugin;
 | 
			
		||||
import org.bukkit.scheduler.BukkitScheduler;
 | 
			
		||||
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
import java.util.function.Supplier;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The update checker is responsible for looking for new updates
 | 
			
		||||
 */
 | 
			
		||||
public final class UpdateChecker {
 | 
			
		||||
 | 
			
		||||
    private final static String updateNotice = "A new update is available: %s (You are still on %s)";
 | 
			
		||||
 | 
			
		||||
    private UpdateChecker() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if there's a new update available, and alerts the user if necessary
 | 
			
		||||
     *
 | 
			
		||||
     * @param plugin             <p>The plugin to check for updates for</p>
 | 
			
		||||
     * @param apiResourceURL     <p>The spigot URL to check for updates. Example: https://api.spigotmc.org/legacy/update.php?resource={resourceId}</p>
 | 
			
		||||
     * @param getVersionSupplier <p>The supplier used to get the current plugin version</p>
 | 
			
		||||
     * @param setVersionMethod   <p>A method to call with the new version as an argument. Can be used to alert admins about an available update or similar.</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void checkForUpdate(Plugin plugin, String apiResourceURL, Supplier<String> getVersionSupplier,
 | 
			
		||||
                                      Consumer<String> setVersionMethod) {
 | 
			
		||||
        BukkitScheduler scheduler = plugin.getServer().getScheduler();
 | 
			
		||||
        scheduler.runTaskAsynchronously(plugin, () -> UpdateChecker.queryAPI(plugin, apiResourceURL, getVersionSupplier,
 | 
			
		||||
                setVersionMethod));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Queries the spigot API to check for a newer version, and prints to the console if found
 | 
			
		||||
     *
 | 
			
		||||
     * @param plugin           <p>The plugin to check for updates for</p>
 | 
			
		||||
     * @param APIResourceURL   <p>The spigot URL to check for updates</p>
 | 
			
		||||
     * @param getVersionMethod <p>The supplier used to get the current plugin version</p>
 | 
			
		||||
     * @param setVersionMethod <p>A method to call with the new version as an argument. Can be used to alert admins about an available update or similar.</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static void queryAPI(Plugin plugin, String APIResourceURL, Supplier<String> getVersionMethod,
 | 
			
		||||
                                 Consumer<String> setVersionMethod) {
 | 
			
		||||
        try {
 | 
			
		||||
            InputStream inputStream = new URL(APIResourceURL).openStream();
 | 
			
		||||
            BufferedReader reader = FileHelper.getBufferedReaderFromInputStream(inputStream);
 | 
			
		||||
            //There should only be one line of output
 | 
			
		||||
            String newVersion = reader.readLine();
 | 
			
		||||
            reader.close();
 | 
			
		||||
 | 
			
		||||
            String oldVersion = getVersionMethod.get();
 | 
			
		||||
            //If there is a newer version, notify the user
 | 
			
		||||
            if (isVersionHigher(oldVersion, newVersion)) {
 | 
			
		||||
                plugin.getLogger().log(Level.INFO, getUpdateAvailableString(newVersion, oldVersion));
 | 
			
		||||
                if (setVersionMethod != null) {
 | 
			
		||||
                    setVersionMethod.accept(newVersion);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            plugin.getLogger().log(Level.WARNING, "Unable to get newest version.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the string to display to a user to alert about a new update
 | 
			
		||||
     *
 | 
			
		||||
     * @param newVersion <p>The new available plugin version</p>
 | 
			
		||||
     * @param oldVersion <p>The old (current) plugin version</p>
 | 
			
		||||
     * @return <p>The string to display</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String getUpdateAvailableString(String newVersion, String oldVersion) {
 | 
			
		||||
        return String.format(updateNotice, newVersion, oldVersion);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Decides whether one version number is higher than another
 | 
			
		||||
     *
 | 
			
		||||
     * @param oldVersion <p>The old version to check</p>
 | 
			
		||||
     * @param newVersion <p>The new version to check</p>
 | 
			
		||||
     * @return <p>True if the new version is higher than the old one</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isVersionHigher(String oldVersion, String newVersion) {
 | 
			
		||||
        String[] oldVersionParts = oldVersion.split("\\.");
 | 
			
		||||
        String[] newVersionParts = newVersion.split("\\.");
 | 
			
		||||
        int versionLength = Math.max(oldVersionParts.length, newVersionParts.length);
 | 
			
		||||
        for (int i = 0; i < versionLength; i++) {
 | 
			
		||||
            int oldVersionNumber = oldVersionParts.length > i ? Integer.parseInt(oldVersionParts[i]) : 0;
 | 
			
		||||
            int newVersionNumber = newVersionParts.length > i ? Integer.parseInt(newVersionParts[i]) : 0;
 | 
			
		||||
            if (newVersionNumber != oldVersionNumber) {
 | 
			
		||||
                return newVersionNumber > oldVersionNumber;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user