Initial commit
This commit is contained in:
commit
8f0c028bb5
113
.gitignore
vendored
Normal file
113
.gitignore
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# User-specific stuff
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
target/
|
||||||
|
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
.flattened-pom.xml
|
||||||
|
|
||||||
|
# Common working directory
|
||||||
|
run/
|
74
pom.xml
Normal file
74
pom.xml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>net.knarcraft</groupId>
|
||||||
|
<artifactId>KnarLib</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>KnarLib</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>16</java.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spigotmc-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>sonatype</id>
|
||||||
|
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.19.2-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user