mirror of
				https://github.com/PlaceholderAPI/PlaceholderAPI
				synced 2025-10-31 06:12:28 +01:00 
			
		
		
		
	Performance Improvements (#340)
* Performance Improvements * More Optimizations * Even More Optimizations & Cleanups * Almost a recode I guess
This commit is contained in:
		
							
								
								
									
										22
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -5,8 +5,8 @@ | |||||||
|  |  | ||||||
|     <groupId>me.clip</groupId> |     <groupId>me.clip</groupId> | ||||||
|     <artifactId>placeholderapi</artifactId> |     <artifactId>placeholderapi</artifactId> | ||||||
|  |  | ||||||
|     <version>2.10.7-DEV-${BUILD_NUMBER}</version> |     <version>2.10.7-DEV-${BUILD_NUMBER}</version> | ||||||
|  |  | ||||||
|     <name>PlaceholderAPI</name> |     <name>PlaceholderAPI</name> | ||||||
|     <description>An awesome placeholder provider!</description> |     <description>An awesome placeholder provider!</description> | ||||||
|     <url>http://extendedclip.com</url> |     <url>http://extendedclip.com</url> | ||||||
| @@ -33,7 +33,7 @@ | |||||||
|     <dependencies> |     <dependencies> | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>org.spigotmc</groupId> |             <groupId>org.spigotmc</groupId> | ||||||
|             <artifactId>spigot-api</artifactId> |             <artifactId>spigot</artifactId> | ||||||
|             <version>1.16.1-R0.1-SNAPSHOT</version> |             <version>1.16.1-R0.1-SNAPSHOT</version> | ||||||
|             <scope>provided</scope> |             <scope>provided</scope> | ||||||
|         </dependency> |         </dependency> | ||||||
| @@ -45,7 +45,7 @@ | |||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>org.bstats</groupId> |             <groupId>org.bstats</groupId> | ||||||
|             <artifactId>bstats-bukkit</artifactId> |             <artifactId>bstats-bukkit</artifactId> | ||||||
|             <version>1.5</version> |             <version>1.7</version> | ||||||
|         </dependency> |         </dependency> | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>me.rayzr522</groupId> |             <groupId>me.rayzr522</groupId> | ||||||
| @@ -84,20 +84,14 @@ | |||||||
|             <plugin> |             <plugin> | ||||||
|                 <groupId>org.apache.maven.plugins</groupId> |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
|                 <artifactId>maven-shade-plugin</artifactId> |                 <artifactId>maven-shade-plugin</artifactId> | ||||||
|                 <version>3.1.0</version> |                 <version>3.2.4</version> | ||||||
|                 <executions> |  | ||||||
|                     <execution> |  | ||||||
|                         <phase>package</phase> |  | ||||||
|                         <goals> |  | ||||||
|                             <goal>shade</goal> |  | ||||||
|                         </goals> |  | ||||||
|                 <configuration> |                 <configuration> | ||||||
|                     <minimizeJar>false</minimizeJar> |                     <minimizeJar>false</minimizeJar> | ||||||
|                     <createDependencyReducedPom>false</createDependencyReducedPom> |                     <createDependencyReducedPom>false</createDependencyReducedPom> | ||||||
|                     <relocations> |                     <relocations> | ||||||
|                         <relocation> |                         <relocation> | ||||||
|                             <pattern>org.bstats</pattern> |                             <pattern>org.bstats</pattern> | ||||||
|                                     <shadedPattern>me.clip.placeholderapi.metrics</shadedPattern> |                             <shadedPattern>me.clip.placeholderapi.util</shadedPattern> | ||||||
|                         </relocation> |                         </relocation> | ||||||
|                         <relocation> |                         <relocation> | ||||||
|                             <pattern>com.google.code.gson</pattern> |                             <pattern>com.google.code.gson</pattern> | ||||||
| @@ -105,6 +99,12 @@ | |||||||
|                         </relocation> |                         </relocation> | ||||||
|                     </relocations> |                     </relocations> | ||||||
|                 </configuration> |                 </configuration> | ||||||
|  |                 <executions> | ||||||
|  |                     <execution> | ||||||
|  |                         <phase>package</phase> | ||||||
|  |                         <goals> | ||||||
|  |                             <goal>shade</goal> | ||||||
|  |                         </goals> | ||||||
|                     </execution> |                     </execution> | ||||||
|                 </executions> |                 </executions> | ||||||
|             </plugin> |             </plugin> | ||||||
|   | |||||||
| @@ -20,14 +20,13 @@ | |||||||
|  */ |  */ | ||||||
| package me.clip.placeholderapi; | package me.clip.placeholderapi; | ||||||
|  |  | ||||||
|  | import com.google.common.base.Strings; | ||||||
| import com.google.common.collect.ImmutableMap; | import com.google.common.collect.ImmutableMap; | ||||||
| import com.google.common.collect.ImmutableSet; | import com.google.common.collect.ImmutableSet; | ||||||
| import me.clip.placeholderapi.events.ExpansionRegisterEvent; | import me.clip.placeholderapi.events.ExpansionRegisterEvent; | ||||||
| import me.clip.placeholderapi.events.ExpansionUnregisterEvent; | import me.clip.placeholderapi.events.ExpansionUnregisterEvent; | ||||||
| import me.clip.placeholderapi.expansion.Cacheable; |  | ||||||
| import me.clip.placeholderapi.expansion.PlaceholderExpansion; | import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||||
| import me.clip.placeholderapi.expansion.Relational; | import me.clip.placeholderapi.expansion.Relational; | ||||||
| import me.clip.placeholderapi.util.Msg; |  | ||||||
| import org.apache.commons.lang.Validate; | import org.apache.commons.lang.Validate; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.OfflinePlayer; | import org.bukkit.OfflinePlayer; | ||||||
| @@ -35,18 +34,17 @@ import org.bukkit.entity.Player; | |||||||
| import org.bukkit.plugin.Plugin; | import org.bukkit.plugin.Plugin; | ||||||
|  |  | ||||||
| import java.util.*; | import java.util.*; | ||||||
|  | import java.util.concurrent.ConcurrentHashMap; | ||||||
| import java.util.regex.Matcher; | import java.util.regex.Matcher; | ||||||
| import java.util.regex.Pattern; | import java.util.regex.Pattern; | ||||||
| import java.util.stream.Collectors; |  | ||||||
|  |  | ||||||
| import static me.clip.placeholderapi.util.Msg.color; | import static me.clip.placeholderapi.util.Msg.color; | ||||||
|  |  | ||||||
| public class PlaceholderAPI { | public class PlaceholderAPI { | ||||||
|  |     protected static final Map<String, PlaceholderHook> PLACEHOLDERS = new ConcurrentHashMap<>(); | ||||||
|     private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]"); |     private static final Pattern PERCENT_PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]"); | ||||||
|     private static final Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[{]([^{}]+)[}]"); |     private static final Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[{]([^{}]+)[}]"); | ||||||
|     private static final Pattern RELATIONAL_PLACEHOLDER_PATTERN = Pattern.compile("[%](rel_)([^%]+)[%]"); |     private static final Pattern RELATIONAL_PLACEHOLDER_PATTERN = Pattern.compile("[%](rel_)([^%]+)[%]"); | ||||||
|     private static final Map<String, PlaceholderHook> placeholders = new HashMap<>(); |  | ||||||
|  |  | ||||||
|     private PlaceholderAPI() { |     private PlaceholderAPI() { | ||||||
|     } |     } | ||||||
| @@ -58,9 +56,7 @@ public class PlaceholderAPI { | |||||||
|      * @return true if identifier is already registered |      * @return true if identifier is already registered | ||||||
|      */ |      */ | ||||||
|     public static boolean isRegistered(String identifier) { |     public static boolean isRegistered(String identifier) { | ||||||
|         return getRegisteredIdentifiers().stream() |         return PLACEHOLDERS.containsKey(identifier.toLowerCase(Locale.ENGLISH)); | ||||||
|                 .filter(id -> id.equalsIgnoreCase(identifier)) |  | ||||||
|                 .findFirst().orElse(null) != null; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -73,15 +69,11 @@ public class PlaceholderAPI { | |||||||
|      * registered for the specified identifier |      * registered for the specified identifier | ||||||
|      */ |      */ | ||||||
|     public static boolean registerPlaceholderHook(String identifier, PlaceholderHook placeholderHook) { |     public static boolean registerPlaceholderHook(String identifier, PlaceholderHook placeholderHook) { | ||||||
|         Validate.notNull(identifier, "Identifier can not be null"); |         Validate.notEmpty(identifier, "Placeholder identifier cannot be null or empty"); | ||||||
|         Validate.notNull(placeholderHook, "Placeholderhook can not be null"); |         Objects.requireNonNull(placeholderHook, "Placeholder hook cannot be null"); | ||||||
|  |  | ||||||
|         if (isRegistered(identifier)) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         placeholders.put(identifier.toLowerCase(), placeholderHook); |  | ||||||
|  |  | ||||||
|  |         if (isRegistered(identifier)) return false; | ||||||
|  |         PLACEHOLDERS.put(identifier.toLowerCase(Locale.ENGLISH), placeholderHook); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -93,8 +85,8 @@ public class PlaceholderAPI { | |||||||
|      * placeholder hook registered for the identifier specified |      * placeholder hook registered for the identifier specified | ||||||
|      */ |      */ | ||||||
|     public static boolean unregisterPlaceholderHook(String identifier) { |     public static boolean unregisterPlaceholderHook(String identifier) { | ||||||
|         Validate.notNull(identifier, "Identifier can not be null"); |         Validate.notEmpty(identifier, "Identifier cannot be null"); | ||||||
|         return placeholders.remove(identifier.toLowerCase()) != null; |         return PLACEHOLDERS.remove(identifier.toLowerCase(Locale.ENGLISH)) != null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -103,7 +95,7 @@ public class PlaceholderAPI { | |||||||
|      * @return All registered placeholder identifiers |      * @return All registered placeholder identifiers | ||||||
|      */ |      */ | ||||||
|     public static Set<String> getRegisteredIdentifiers() { |     public static Set<String> getRegisteredIdentifiers() { | ||||||
|         return ImmutableSet.copyOf(placeholders.keySet()); |         return ImmutableSet.copyOf(PLACEHOLDERS.keySet()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -112,15 +104,16 @@ public class PlaceholderAPI { | |||||||
|      * @return Copy of the internal placeholder map |      * @return Copy of the internal placeholder map | ||||||
|      */ |      */ | ||||||
|     public static Map<String, PlaceholderHook> getPlaceholders() { |     public static Map<String, PlaceholderHook> getPlaceholders() { | ||||||
|         return ImmutableMap.copyOf(placeholders); |         return ImmutableMap.copyOf(PLACEHOLDERS); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static Set<PlaceholderExpansion> getExpansions() { |     public static Set<PlaceholderExpansion> getExpansions() { | ||||||
|         Set<PlaceholderExpansion> set = getPlaceholders().values().stream() |         Set<PlaceholderExpansion> expansions = new HashSet<>(); | ||||||
|                 .filter(PlaceholderExpansion.class::isInstance).map(PlaceholderExpansion.class::cast) |         for (PlaceholderHook expansion : PLACEHOLDERS.values()) { | ||||||
|                 .collect(Collectors.toCollection(HashSet::new)); |             if (expansion.isExpansion()) expansions.add((PlaceholderExpansion) expansion); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         return ImmutableSet.copyOf(set); |         return ImmutableSet.copyOf(expansions); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -130,7 +123,7 @@ public class PlaceholderAPI { | |||||||
|      * @return true if String contains any registered placeholder identifiers, false otherwise |      * @return true if String contains any registered placeholder identifiers, false otherwise | ||||||
|      */ |      */ | ||||||
|     public static boolean containsPlaceholders(String text) { |     public static boolean containsPlaceholders(String text) { | ||||||
|         return text != null && PLACEHOLDER_PATTERN.matcher(text).find(); |         return !Strings.isNullOrEmpty(text) && PERCENT_PLACEHOLDER_PATTERN.matcher(text).find(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -140,7 +133,7 @@ public class PlaceholderAPI { | |||||||
|      * @return true if String contains any registered placeholder identifiers, false otherwise |      * @return true if String contains any registered placeholder identifiers, false otherwise | ||||||
|      */ |      */ | ||||||
|     public static boolean containsBracketPlaceholders(String text) { |     public static boolean containsBracketPlaceholders(String text) { | ||||||
|         return text != null && BRACKET_PLACEHOLDER_PATTERN.matcher(text).find(); |         return !Strings.isNullOrEmpty(text) && BRACKET_PLACEHOLDER_PATTERN.matcher(text).find(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -177,7 +170,7 @@ public class PlaceholderAPI { | |||||||
|      * @return String containing all translated placeholders |      * @return String containing all translated placeholders | ||||||
|      */ |      */ | ||||||
|     public static List<String> setPlaceholders(OfflinePlayer player, List<String> text) { |     public static List<String> setPlaceholders(OfflinePlayer player, List<String> text) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, true); |         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -190,7 +183,7 @@ public class PlaceholderAPI { | |||||||
|      * @return String containing all translated placeholders |      * @return String containing all translated placeholders | ||||||
|      */ |      */ | ||||||
|     public static List<String> setPlaceholders(OfflinePlayer player, List<String> text, boolean colorize) { |     public static List<String> setPlaceholders(OfflinePlayer player, List<String> text, boolean colorize) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, colorize); |         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, colorize); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -219,13 +212,13 @@ public class PlaceholderAPI { | |||||||
|      * @return String containing all translated placeholders |      * @return String containing all translated placeholders | ||||||
|      */ |      */ | ||||||
|     public static List<String> setPlaceholders(OfflinePlayer player, List<String> text, Pattern pattern, boolean colorize) { |     public static List<String> setPlaceholders(OfflinePlayer player, List<String> text, Pattern pattern, boolean colorize) { | ||||||
|         if (text == null) { |         if (text == null) return null; | ||||||
|             return null; |         List<String> lines = new ArrayList<>(); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return text.stream() |         for (String line : text) { | ||||||
|                 .map(line -> setPlaceholders(player, line, pattern, colorize)) |             lines.add(setPlaceholders(player, line, pattern, colorize)); | ||||||
|                 .collect(Collectors.toList()); |         } | ||||||
|  |         return lines; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -262,7 +255,7 @@ public class PlaceholderAPI { | |||||||
|      * @return String containing all translated placeholders |      * @return String containing all translated placeholders | ||||||
|      */ |      */ | ||||||
|     public static String setPlaceholders(OfflinePlayer player, String text) { |     public static String setPlaceholders(OfflinePlayer player, String text) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN); |         return PlaceholderReplacer.evaluatePlaceholders(player, text, PlaceholderReplacer.Closure.PERCENT, false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -275,7 +268,7 @@ public class PlaceholderAPI { | |||||||
|      * @return The text containing the parsed placeholders |      * @return The text containing the parsed placeholders | ||||||
|      */ |      */ | ||||||
|     public static String setPlaceholders(OfflinePlayer player, String text, boolean colorize) { |     public static String setPlaceholders(OfflinePlayer player, String text, boolean colorize) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, colorize); |         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, colorize); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -304,43 +297,51 @@ public class PlaceholderAPI { | |||||||
|      * @return The text containing the parsed placeholders |      * @return The text containing the parsed placeholders | ||||||
|      */ |      */ | ||||||
|     public static String setPlaceholders(OfflinePlayer player, String text, Pattern pattern, boolean colorize) { |     public static String setPlaceholders(OfflinePlayer player, String text, Pattern pattern, boolean colorize) { | ||||||
|         if (text == null) { |         if (text == null) return null; | ||||||
|             return null; |         if (PLACEHOLDERS.isEmpty()) return colorize ? color(text) : text; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (placeholders.isEmpty()) { |  | ||||||
|             return colorize ? color(text) : text; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         final Matcher matcher = pattern.matcher(text); |  | ||||||
|         final Map<String, PlaceholderHook> hooks = getPlaceholders(); |  | ||||||
|  |  | ||||||
|  |         Matcher matcher = pattern.matcher(text); | ||||||
|         while (matcher.find()) { |         while (matcher.find()) { | ||||||
|             final String format = matcher.group(1); |             String format = matcher.group(1); | ||||||
|             final int index = format.indexOf("_"); |             int index = format.indexOf('_'); | ||||||
|  |             if (index <= 0 || index >= format.length()) continue; | ||||||
|  |  | ||||||
|             if (index <= 0 || index >= format.length()) { |             // We don't need to use getPlaceholders() because we know what we're doing and we won't modify the map. | ||||||
|                 continue; |             // And instead of looking for the element twice using contains() and get() we only get it and check if it's null. | ||||||
|             } |             String identifier = format.substring(0, index).toLowerCase(Locale.ENGLISH); | ||||||
|  |             PlaceholderHook handler = PLACEHOLDERS.get(identifier); | ||||||
|  |  | ||||||
|             final String identifier = format.substring(0, index).toLowerCase(); |             if (handler != null) { | ||||||
|             final String params = format.substring(index + 1); |                 String params = format.substring(index + 1); | ||||||
|             final PlaceholderHook hook = hooks.get(identifier); |                 String value = handler.onRequest(player, params); | ||||||
|  |  | ||||||
|             if (hook == null) { |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             final String value = hook.onRequest(player, params); |  | ||||||
|  |  | ||||||
|                 if (value != null) { |                 if (value != null) { | ||||||
|                     text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value)); |                     text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         return colorize ? color(text) : text; |         return colorize ? color(text) : text; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Optimized version of {@link #setPlaceholders(OfflinePlayer, String, Pattern, boolean)} | ||||||
|  |      * | ||||||
|  |      * @param player   player to parse the placeholders against. | ||||||
|  |      * @param text     the text to translate. | ||||||
|  |      * @param closure  the closing points of a placeholder. %, {, [ etc... | ||||||
|  |      * @param colorize if we should colorize this text using the common & symbol. | ||||||
|  |      * @return the translated text. | ||||||
|  |      */ | ||||||
|  |     public static String setPlaceholders(OfflinePlayer player, String text, PlaceholderReplacer.Closure closure, boolean colorize) { | ||||||
|  |         if (text == null) return null; | ||||||
|  |         if (text.isEmpty()) return ""; | ||||||
|  |         if (PLACEHOLDERS.isEmpty()) return colorize ? color(text) : text; | ||||||
|  |  | ||||||
|  |         // We don't want to dirty our class. | ||||||
|  |         return PlaceholderReplacer.evaluatePlaceholders(player, text, closure, colorize); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Translate placeholders in the provided List based on the relation of the two provided players. |      * Translate placeholders in the provided List based on the relation of the two provided players. | ||||||
|      * <br>The pattern of a valid placeholder is {@literal %rel_<identifier>_<param>%}. |      * <br>The pattern of a valid placeholder is {@literal %rel_<identifier>_<param>%}. | ||||||
| @@ -365,13 +366,12 @@ public class PlaceholderAPI { | |||||||
|      * @return The text containing the parsed relational placeholders |      * @return The text containing the parsed relational placeholders | ||||||
|      */ |      */ | ||||||
|     public static List<String> setRelationalPlaceholders(Player one, Player two, List<String> text, boolean colorize) { |     public static List<String> setRelationalPlaceholders(Player one, Player two, List<String> text, boolean colorize) { | ||||||
|         if (text == null) { |         if (text == null) return null; | ||||||
|             return null; |         List<String> lines = new ArrayList<>(); | ||||||
|  |         for (String line : text) { | ||||||
|  |             lines.add(setRelationalPlaceholders(one, two, line, colorize)); | ||||||
|         } |         } | ||||||
|  |         return lines; | ||||||
|         return text.stream() |  | ||||||
|                 .map(line -> setRelationalPlaceholders(one, two, line, colorize)) |  | ||||||
|                 .collect(Collectors.toList()); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -397,43 +397,31 @@ public class PlaceholderAPI { | |||||||
|      * @param colorize If color codes (&[0-1a-fk-o]) should be translated |      * @param colorize If color codes (&[0-1a-fk-o]) should be translated | ||||||
|      * @return The text containing the parsed relational placeholders |      * @return The text containing the parsed relational placeholders | ||||||
|      */ |      */ | ||||||
|     @SuppressWarnings("DuplicatedCode") |  | ||||||
|     public static String setRelationalPlaceholders(Player one, Player two, String text, boolean colorize) { |     public static String setRelationalPlaceholders(Player one, Player two, String text, boolean colorize) { | ||||||
|         if (text == null) { |         if (text == null) return null; | ||||||
|             return null; |         if (PLACEHOLDERS.isEmpty()) return colorize ? color(text) : text; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (placeholders.isEmpty()) { |  | ||||||
|             return colorize ? Msg.color(text) : text; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         final Matcher matcher = RELATIONAL_PLACEHOLDER_PATTERN.matcher(text); |  | ||||||
|         final Map<String, PlaceholderHook> hooks = getPlaceholders(); |  | ||||||
|  |  | ||||||
|  |         Matcher matcher = RELATIONAL_PLACEHOLDER_PATTERN.matcher(text); | ||||||
|         while (matcher.find()) { |         while (matcher.find()) { | ||||||
|             final String format = matcher.group(2); |             String format = matcher.group(2); | ||||||
|             final int index = format.indexOf("_"); |             int index = format.indexOf('_'); | ||||||
|  |             if (index <= 0 || index >= format.length()) continue; | ||||||
|  |  | ||||||
|             if (index <= 0 || index >= format.length()) { |             String identifier = format.substring(0, index).toLowerCase(Locale.ENGLISH); | ||||||
|                 continue; |             PlaceholderHook handler = PLACEHOLDERS.get(identifier); | ||||||
|             } |  | ||||||
|  |  | ||||||
|             String identifier = format.substring(0, index).toLowerCase(); |             if (handler.isRelational()) { | ||||||
|  |                 Relational relational = (Relational) handler; | ||||||
|                 String params = format.substring(index + 1); |                 String params = format.substring(index + 1); | ||||||
|             final PlaceholderHook hook = hooks.get(identifier); |                 String value = relational.onPlaceholderRequest(one, two, params); | ||||||
|  |  | ||||||
|             if (!(hook instanceof Relational)) { |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             final String value = ((Relational) hook).onPlaceholderRequest(one, two, params); |  | ||||||
|  |  | ||||||
|                 if (value != null) { |                 if (value != null) { | ||||||
|                     text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value)); |                     text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         return colorize ? Msg.color(text) : text; |         return colorize ? color(text) : text; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -441,43 +429,34 @@ public class PlaceholderAPI { | |||||||
|      */ |      */ | ||||||
|     protected static void unregisterAll() { |     protected static void unregisterAll() { | ||||||
|         unregisterAllProvidedExpansions(); |         unregisterAllProvidedExpansions(); | ||||||
|         placeholders.clear(); |         PLACEHOLDERS.clear(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Unregister all expansions provided by PlaceholderAPI |      * Unregister all expansions provided by PlaceholderAPI | ||||||
|      */ |      */ | ||||||
|     public static void unregisterAllProvidedExpansions() { |     public static void unregisterAllProvidedExpansions() { | ||||||
|         final Set<PlaceholderHook> set = new HashSet<>(placeholders.values()); |         if (PLACEHOLDERS.isEmpty()) return; | ||||||
|  |  | ||||||
|         for (PlaceholderHook hook : set) { |         for (PlaceholderHook handler : PLACEHOLDERS.values()) { | ||||||
|             if (hook instanceof PlaceholderExpansion) { |             if (handler.isExpansion()) { | ||||||
|                 final PlaceholderExpansion expansion = (PlaceholderExpansion) hook; |                 PlaceholderExpansion expansion = (PlaceholderExpansion) handler; | ||||||
|  |                 if (!expansion.persist()) unregisterExpansion(expansion); | ||||||
|                 if (!expansion.persist()) { |  | ||||||
|                     unregisterExpansion(expansion); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (hook instanceof Cacheable) { |  | ||||||
|                 ((Cacheable) hook).clear(); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static boolean registerExpansion(PlaceholderExpansion ex) { |     public static boolean registerExpansion(PlaceholderExpansion expansion) { | ||||||
|         ExpansionRegisterEvent ev = new ExpansionRegisterEvent(ex); |         ExpansionRegisterEvent event = new ExpansionRegisterEvent(expansion); | ||||||
|         Bukkit.getPluginManager().callEvent(ev); |         Bukkit.getPluginManager().callEvent(event); | ||||||
|         if (ev.isCancelled()) { |         if (event.isCancelled()) return false; | ||||||
|             return false; |  | ||||||
|  |         return registerPlaceholderHook(expansion.getIdentifier(), expansion); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         return registerPlaceholderHook(ex.getIdentifier(), ex); |     public static boolean unregisterExpansion(PlaceholderExpansion expansion) { | ||||||
|     } |         if (unregisterPlaceholderHook(expansion.getIdentifier())) { | ||||||
|  |             Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(expansion)); | ||||||
|     public static boolean unregisterExpansion(PlaceholderExpansion ex) { |  | ||||||
|         if (unregisterPlaceholderHook(ex.getIdentifier())) { |  | ||||||
|             Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(ex)); |  | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -490,7 +469,7 @@ public class PlaceholderAPI { | |||||||
|      * @return The pattern for {@literal %<identifier>_<params>%} |      * @return The pattern for {@literal %<identifier>_<params>%} | ||||||
|      */ |      */ | ||||||
|     public static Pattern getPlaceholderPattern() { |     public static Pattern getPlaceholderPattern() { | ||||||
|         return PLACEHOLDER_PATTERN; |         return PERCENT_PLACEHOLDER_PATTERN; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -532,19 +511,19 @@ public class PlaceholderAPI { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String setPlaceholders(Player player, String text) { |     public static String setPlaceholders(Player player, String text) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, true); |         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String setPlaceholders(Player player, String text, boolean colorize) { |     public static String setPlaceholders(Player player, String text, boolean colorize) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, colorize); |         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, colorize); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static List<String> setPlaceholders(Player player, List<String> text) { |     public static List<String> setPlaceholders(Player player, List<String> text) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, true); |         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static List<String> setPlaceholders(Player player, List<String> text, boolean colorize) { |     public static List<String> setPlaceholders(Player player, List<String> text, boolean colorize) { | ||||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, colorize); |         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, colorize); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String setBracketPlaceholders(Player player, String text) { |     public static String setBracketPlaceholders(Player player, String text) { | ||||||
|   | |||||||
| @@ -21,66 +21,63 @@ | |||||||
| package me.clip.placeholderapi; | package me.clip.placeholderapi; | ||||||
|  |  | ||||||
| import me.clip.placeholderapi.commands.CommandHandler; | import me.clip.placeholderapi.commands.CommandHandler; | ||||||
|  | import me.clip.placeholderapi.commands.CompletionHandler; | ||||||
| import me.clip.placeholderapi.configuration.PlaceholderAPIConfig; | import me.clip.placeholderapi.configuration.PlaceholderAPIConfig; | ||||||
| import me.clip.placeholderapi.expansion.ExpansionManager; | import me.clip.placeholderapi.expansion.ExpansionManager; | ||||||
| import me.clip.placeholderapi.expansion.PlaceholderExpansion; | import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||||
| import me.clip.placeholderapi.expansion.Version; | import me.clip.placeholderapi.expansion.Version; | ||||||
| import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; | import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; | ||||||
| import me.clip.placeholderapi.external.EZPlaceholderHook; | import me.clip.placeholderapi.external.EZPlaceholderHook; | ||||||
|  | import me.clip.placeholderapi.listeners.ApacheListener; | ||||||
| import me.clip.placeholderapi.listeners.PlaceholderListener; | import me.clip.placeholderapi.listeners.PlaceholderListener; | ||||||
| import me.clip.placeholderapi.listeners.ServerLoadEventListener; | import me.clip.placeholderapi.listeners.ServerLoadEventListener; | ||||||
| import me.clip.placeholderapi.updatechecker.UpdateChecker; |  | ||||||
| import me.clip.placeholderapi.util.TimeUtil; | import me.clip.placeholderapi.util.TimeUtil; | ||||||
|  | import me.clip.placeholderapi.util.UpdateChecker; | ||||||
| import org.bstats.bukkit.Metrics; | import org.bstats.bukkit.Metrics; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.ChatColor; | import org.bukkit.ChatColor; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
|  | import org.bukkit.command.PluginCommand; | ||||||
| import org.bukkit.plugin.java.JavaPlugin; | import org.bukkit.plugin.java.JavaPlugin; | ||||||
|  |  | ||||||
| import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||||
|  | import java.time.format.DateTimeFormatter; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Objects; |  | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Yes I have a shit load of work to do... |  * Yes I have a shit load of work to do... | ||||||
|  * |  * | ||||||
|  * @author Ryan McCarthy |  * @author Ryan McCarthy | ||||||
|  */ |  */ | ||||||
| public class PlaceholderAPIPlugin extends JavaPlugin { | public class PlaceholderAPIPlugin extends JavaPlugin { | ||||||
|  |     private static final Version serverVersion; | ||||||
|     private static PlaceholderAPIPlugin instance; |     private static PlaceholderAPIPlugin instance; | ||||||
|     private static SimpleDateFormat dateFormat; |     private static DateTimeFormatter dateFormat; | ||||||
|     private static String booleanTrue; |     private static String booleanTrue; | ||||||
|     private static String booleanFalse; |     private static String booleanFalse; | ||||||
|     private static Version serverVersion; |  | ||||||
|  |     static { | ||||||
|  |         // It's not possible to be null or throw an index exception unless it's a bug. | ||||||
|  |         String nmsVersion = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; | ||||||
|  |         boolean spigot; | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             Class.forName("org.spigotmc.SpigotConfig"); | ||||||
|  |             spigot = true; | ||||||
|  |         } catch (ExceptionInInitializerError | ClassNotFoundException ignored) { | ||||||
|  |             spigot = false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         serverVersion = new Version(nmsVersion, spigot); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private PlaceholderAPIConfig config; |     private PlaceholderAPIConfig config; | ||||||
|     private ExpansionManager expansionManager; |     private ExpansionManager expansionManager; | ||||||
|     private ExpansionCloudManager expansionCloud; |     private ExpansionCloudManager expansionCloud; | ||||||
|     private long startTime; |     private long startTime; | ||||||
|  |  | ||||||
|     private static Version getVersion() { |  | ||||||
|         String v = "unknown"; |  | ||||||
|         boolean spigot = false; |  | ||||||
|  |  | ||||||
|         try { |  | ||||||
|             v = Bukkit.getServer().getClass().getPackage().getName() |  | ||||||
|                     .split("\\.")[3]; |  | ||||||
|         } catch (ArrayIndexOutOfBoundsException ex) { |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         try { |  | ||||||
|             Class.forName("org.spigotmc.SpigotConfig"); |  | ||||||
|             Class.forName("net.md_5.bungee.api.chat.BaseComponent"); |  | ||||||
|             spigot = true; |  | ||||||
|         } catch (ExceptionInInitializerError | ClassNotFoundException ignored) { |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return new Version(v, spigot); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Gets the static instance of the main class for PlaceholderAPI. This class is not the actual API |      * Gets the static instance of the main class for PlaceholderAPI. This class is not the actual API | ||||||
|      * class, this is the main class that extends JavaPlugin. For most API methods, use static methods |      * class, this is the main class that extends JavaPlugin. For most API methods, use static methods | ||||||
| @@ -98,9 +95,8 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|      * |      * | ||||||
|      * @return date format |      * @return date format | ||||||
|      */ |      */ | ||||||
|     public static SimpleDateFormat getDateFormat() { |     public static DateTimeFormatter getDateFormat() { | ||||||
|         return dateFormat != null ? dateFormat : new SimpleDateFormat( |         return dateFormat != null ? dateFormat : DateTimeFormatter.ofPattern("MM/dd/yy HH:mm:ss"); | ||||||
|                 "MM/dd/yy HH:mm:ss"); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -122,26 +118,26 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static Version getServerVersion() { |     public static Version getServerVersion() { | ||||||
|         return serverVersion != null ? serverVersion : getVersion(); |         return serverVersion; | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void onLoad() { |  | ||||||
|         startTime = System.currentTimeMillis(); |  | ||||||
|         instance = this; |  | ||||||
|         serverVersion = getVersion(); |  | ||||||
|         config = new PlaceholderAPIConfig(this); |  | ||||||
|         expansionManager = new ExpansionManager(this); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onEnable() { |     public void onEnable() { | ||||||
|  |         startTime = System.currentTimeMillis(); | ||||||
|  |         instance = this; | ||||||
|  |  | ||||||
|  |         config = new PlaceholderAPIConfig(this); | ||||||
|         config.loadDefConfig(); |         config.loadDefConfig(); | ||||||
|         setupOptions(); |         setupOptions(); | ||||||
|  |  | ||||||
|         Objects.requireNonNull(getCommand("placeholderapi")).setExecutor(new CommandHandler()); |         expansionManager = new ExpansionManager(this); | ||||||
|         new PlaceholderListener(this); |         new PlaceholderListener(this); | ||||||
|  |  | ||||||
|  |         PluginCommand command = getCommand("placeholderapi"); | ||||||
|  |         command.setExecutor(new CommandHandler()); | ||||||
|  |         command.setTabCompleter(new CompletionHandler()); | ||||||
|  |  | ||||||
|  |         new ApacheListener(this); | ||||||
|         try { |         try { | ||||||
|             Class.forName("org.bukkit.event.server.ServerLoadEvent"); |             Class.forName("org.bukkit.event.server.ServerLoadEvent"); | ||||||
|             new ServerLoadEventListener(this); |             new ServerLoadEventListener(this); | ||||||
| @@ -150,7 +146,7 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|                 getLogger().info("Placeholder expansion registration initializing..."); |                 getLogger().info("Placeholder expansion registration initializing..."); | ||||||
|  |  | ||||||
|                 //fetch any hooks that may have registered externally onEnable first otherwise they will be lost |                 //fetch any hooks that may have registered externally onEnable first otherwise they will be lost | ||||||
|                 final Map<String, PlaceholderHook> alreadyRegistered = PlaceholderAPI.getPlaceholders(); |                 Map<String, PlaceholderHook> alreadyRegistered = PlaceholderAPI.PLACEHOLDERS; | ||||||
|                 getExpansionManager().registerAllExpansions(); |                 getExpansionManager().registerAllExpansions(); | ||||||
|  |  | ||||||
|                 if (alreadyRegistered != null && !alreadyRegistered.isEmpty()) { |                 if (alreadyRegistered != null && !alreadyRegistered.isEmpty()) { | ||||||
| @@ -159,13 +155,8 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|             }, 1); |             }, 1); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (config.checkUpdates()) { |         if (config.checkUpdates()) new UpdateChecker(this).fetch(); | ||||||
|             new UpdateChecker(this).fetch(); |         if (config.isCloudEnabled()) enableCloud(); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (config.isCloudEnabled()) { |  | ||||||
|             enableCloud(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         setupMetrics(); |         setupMetrics(); | ||||||
|         getServer().getScheduler().runTaskLater(this, this::checkHook, 40); |         getServer().getScheduler().runTaskLater(this, this::checkHook, 40); | ||||||
| @@ -175,14 +166,13 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|     public void onDisable() { |     public void onDisable() { | ||||||
|         disableCloud(); |         disableCloud(); | ||||||
|         PlaceholderAPI.unregisterAll(); |         PlaceholderAPI.unregisterAll(); | ||||||
|         expansionManager = null; |  | ||||||
|         Bukkit.getScheduler().cancelTasks(this); |         Bukkit.getScheduler().cancelTasks(this); | ||||||
|         serverVersion = null; |  | ||||||
|  |         expansionManager = null; | ||||||
|         instance = null; |         instance = null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void reloadConf(CommandSender s) { |     public void reloadConf(CommandSender s) { | ||||||
|         boolean cloudEnabled = this.expansionCloud != null; |  | ||||||
|         PlaceholderAPI.unregisterAllProvidedExpansions(); |         PlaceholderAPI.unregisterAllProvidedExpansions(); | ||||||
|         reloadConfig(); |         reloadConfig(); | ||||||
|         setupOptions(); |         setupOptions(); | ||||||
| @@ -190,79 +180,70 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|  |  | ||||||
|         if (!config.isCloudEnabled()) { |         if (!config.isCloudEnabled()) { | ||||||
|             disableCloud(); |             disableCloud(); | ||||||
|         } else if (!cloudEnabled) { |         } else if (this.expansionCloud != null) { | ||||||
|             enableCloud(); |             enableCloud(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         s.sendMessage(ChatColor.translateAlternateColorCodes('&', |         s.sendMessage(ChatColor.translateAlternateColorCodes('&', PlaceholderAPI.PLACEHOLDERS.size() + " &aplaceholder hooks successfully registered!")); | ||||||
|                 PlaceholderAPI.getRegisteredIdentifiers().size() |  | ||||||
|                         + " &aplaceholder hooks successfully registered!")); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @SuppressWarnings("deprecation") | ||||||
|     private void checkHook() { |     private void checkHook() { | ||||||
|         Map<String, PlaceholderHook> loaded = PlaceholderAPI.getPlaceholders(); |         for (PlaceholderHook hook : PlaceholderAPI.PLACEHOLDERS.values()) { | ||||||
|  |             if (hook instanceof EZPlaceholderHook) { | ||||||
|         loaded.values().forEach(h -> { |                 String pluginName = ((EZPlaceholderHook) hook).getPluginName(); | ||||||
|             if (h instanceof EZPlaceholderHook) { |  | ||||||
|                 String author; |                 String author; | ||||||
|  |  | ||||||
|                 try { |                 try { | ||||||
|                     author = Bukkit.getPluginManager().getPlugin(((EZPlaceholderHook) h).getPluginName()).getDescription().getAuthors().toString(); |                     author = Bukkit.getPluginManager().getPlugin(pluginName).getDescription().getAuthors().toString(); | ||||||
|                 } catch (Exception ex) { |                 } catch (Exception ex) { | ||||||
|                     author = "the author of the hook's plugin"; |                     author = "the author of the hook's plugin"; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 getLogger().severe(((EZPlaceholderHook) h).getPluginName() + |                 getLogger().severe(pluginName + | ||||||
|                         " is currently using a deprecated method to hook into PlaceholderAPI. Placeholders for that plugin no longer work. " + |                         " is currently using a deprecated method to hook into PlaceholderAPI. Placeholders for that plugin no longer work. " + | ||||||
|                         "Please consult {author} and urge them to update it ASAP.".replace("{author}", author)); |                         "Please consult " + author + " and urge them to update it ASAP."); | ||||||
|  |  | ||||||
|                 // disable the hook on startup |                 // disable the hook on startup | ||||||
|                 PlaceholderAPI.unregisterPlaceholderHook(((EZPlaceholderHook) h).getPlaceholderName()); |                 PlaceholderAPI.unregisterPlaceholderHook(((EZPlaceholderHook) hook).getPlaceholderName()); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void setupOptions() { |     private void setupOptions() { | ||||||
|         booleanTrue = config.booleanTrue(); |         booleanTrue = config.booleanTrue(); | ||||||
|  |         if (booleanTrue == null) booleanTrue = "true"; | ||||||
|         if (booleanTrue == null) { |  | ||||||
|             booleanTrue = "true"; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         booleanFalse = config.booleanFalse(); |         booleanFalse = config.booleanFalse(); | ||||||
|  |         if (booleanFalse == null) booleanFalse = "false"; | ||||||
|         if (booleanFalse == null) { |  | ||||||
|             booleanFalse = "false"; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             dateFormat = new SimpleDateFormat(config.dateFormat()); |             dateFormat = DateTimeFormatter.ofPattern(config.dateFormat()); | ||||||
|         } catch (Exception e) { |         } catch (Exception ignored) { | ||||||
|             dateFormat = new SimpleDateFormat("MM/dd/yy HH:mm:ss"); |             dateFormat = DateTimeFormatter.ofPattern("MM/dd/yy HH:mm:ss"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void setupMetrics() { |     private void setupMetrics() { | ||||||
|         Metrics m = new Metrics(this); |         // This is NOT the plugin resource ID. it's the bStats ID. | ||||||
|         m.addCustomChart(new Metrics.SimplePie("using_expansion_cloud", () -> getExpansionCloud() != null ? "yes" : "no")); |         Metrics metrics = new Metrics(this, 438); | ||||||
|  |         metrics.addCustomChart(new Metrics.SimplePie("using_expansion_cloud", | ||||||
|  |                 () -> getExpansionCloud() != null ? "yes" : "no")); | ||||||
|  |  | ||||||
|         m.addCustomChart(new Metrics.SimplePie("using_spigot", () -> getServerVersion().isSpigot() ? "yes" : "no")); |         metrics.addCustomChart(new Metrics.SimplePie("using_spigot", | ||||||
|  |                 () -> getServerVersion().isSpigot() ? "yes" : "no")); | ||||||
|  |  | ||||||
|         m.addCustomChart(new Metrics.AdvancedPie("expansions_used", () -> { |         metrics.addCustomChart(new Metrics.AdvancedPie("expansions_used", () -> { | ||||||
|             Map<String, Integer> map = new HashMap<>(); |             Map<String, Integer> map = new HashMap<>(); | ||||||
|             Map<String, PlaceholderHook> hooks = PlaceholderAPI.getPlaceholders(); |             for (PlaceholderHook hook : PlaceholderAPI.PLACEHOLDERS.values()) { | ||||||
|  |                 if (hook.isExpansion()) { | ||||||
|  |                     PlaceholderExpansion ex = (PlaceholderExpansion) hook; | ||||||
|  |                     map.put(ex.getRequiredPlugin() == null ? ex.getIdentifier() | ||||||
|  |                             : ex.getRequiredPlugin(), 1); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|             if (!hooks.isEmpty()) { |  | ||||||
|  |  | ||||||
|                 for (PlaceholderHook hook : hooks.values()) { |  | ||||||
|                     if (hook instanceof PlaceholderExpansion) { |  | ||||||
|                         PlaceholderExpansion expansion = (PlaceholderExpansion) hook; |  | ||||||
|                         map.put(expansion.getRequiredPlugin() == null ? expansion.getIdentifier() : expansion.getRequiredPlugin(), 1); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return map; |             return map; | ||||||
|  |  | ||||||
|         })); |         })); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -276,10 +257,7 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void disableCloud() { |     public void disableCloud() { | ||||||
|         if (expansionCloud != null) { |         if (expansionCloud != null) expansionCloud = null; | ||||||
|             expansionCloud.clean(); |  | ||||||
|             expansionCloud = null; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -305,6 +283,6 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public long getUptimeMillis() { |     public long getUptimeMillis() { | ||||||
|         return (System.currentTimeMillis() - startTime); |         return System.currentTimeMillis() - startTime; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,13 +20,14 @@ | |||||||
|  */ |  */ | ||||||
| package me.clip.placeholderapi; | package me.clip.placeholderapi; | ||||||
|  |  | ||||||
|  | import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||||
|  | import me.clip.placeholderapi.expansion.Relational; | ||||||
| import org.bukkit.OfflinePlayer; | import org.bukkit.OfflinePlayer; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
|  |  | ||||||
| public abstract class PlaceholderHook { | public abstract class PlaceholderHook { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * called when a placeholder value is requested from this hook |      * Called when a placeholder value is requested from this hook. | ||||||
|      * |      * | ||||||
|      * @param player {@link OfflinePlayer} to request the placeholder value for, null if not needed for a |      * @param player {@link OfflinePlayer} to request the placeholder value for, null if not needed for a | ||||||
|      *               player |      *               player | ||||||
| @@ -41,8 +42,12 @@ public abstract class PlaceholderHook { | |||||||
|         return onPlaceholderRequest(null, params); |         return onPlaceholderRequest(null, params); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public PlaceholderAPIPlugin getPlaceholderAPI() { | ||||||
|  |         return PlaceholderAPIPlugin.getInstance(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * called when a placeholder is requested from this hook |      * Called when a placeholder is requested from this hook. | ||||||
|      * |      * | ||||||
|      * @param player {@link Player} to request the placeholder value for, null if not needed for a player |      * @param player {@link Player} to request the placeholder value for, null if not needed for a player | ||||||
|      * @param params String passed to the hook to determine what value to return |      * @param params String passed to the hook to determine what value to return | ||||||
| @@ -51,4 +56,12 @@ public abstract class PlaceholderHook { | |||||||
|     public String onPlaceholderRequest(Player player, String params) { |     public String onPlaceholderRequest(Player player, String params) { | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public boolean isExpansion() { | ||||||
|  |         return this instanceof PlaceholderExpansion; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public boolean isRelational() { | ||||||
|  |         return this instanceof Relational; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										150
									
								
								src/main/java/me/clip/placeholderapi/PlaceholderReplacer.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								src/main/java/me/clip/placeholderapi/PlaceholderReplacer.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | |||||||
|  | /* | ||||||
|  |  * PlaceholderAPI | ||||||
|  |  * Copyright (C) 2019 Ryan McCarthy | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  | package me.clip.placeholderapi; | ||||||
|  |  | ||||||
|  | import com.google.common.collect.ImmutableSet; | ||||||
|  | import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||||
|  | import org.bukkit.ChatColor; | ||||||
|  | import org.bukkit.OfflinePlayer; | ||||||
|  |  | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This is certainly hard to understand and maintain, but it's fully optimized. | ||||||
|  |  * It's almost x5 times faster than the RegEx method for normal sized strings. This performance gap gets smaller | ||||||
|  |  * for smaller strings. | ||||||
|  |  * | ||||||
|  |  * @author Crypto Morin | ||||||
|  |  */ | ||||||
|  | public class PlaceholderReplacer { | ||||||
|  |     /** | ||||||
|  |      * Cached available color codes. Technically the uppercase of each letter can be used too, but no one really uses the uppercase ones. | ||||||
|  |      */ | ||||||
|  |     private static final Set<Character> COLOR_CODES = ImmutableSet.of('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | ||||||
|  |             'a', 'b', 'c', 'd', 'e', 'f', 'k', 'l', 'm', 'o', 'r', 'x'); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Translates placeholders for a string using pure character loops. | ||||||
|  |      * Might cause problems in really rare conditions. | ||||||
|  |      * | ||||||
|  |      * @param player   the player to translate the string for. | ||||||
|  |      * @param str      the string to translate. | ||||||
|  |      * @param closure  the type of the placeholder closing points. | ||||||
|  |      * @param colorize if this message should be colorized as well. | ||||||
|  |      * @return a translated string. | ||||||
|  |      */ | ||||||
|  |     public static String evaluatePlaceholders(OfflinePlayer player, String str, Closure closure, boolean colorize) { | ||||||
|  |         char[] chars = str.toCharArray(); | ||||||
|  |         StringBuilder builder = new StringBuilder(chars.length); | ||||||
|  |  | ||||||
|  |         // This won't cause memory leaks. It's inside a method. And we want to use setLength instead of | ||||||
|  |         // creating a new string builder to use the maximum capacity and avoid initializing new objects. | ||||||
|  |         StringBuilder identifier = new StringBuilder(50); | ||||||
|  |         PlaceholderHook handler = null; | ||||||
|  |  | ||||||
|  |         // Stages: | ||||||
|  |         //   Stage -1: Look for the color code in the next character. | ||||||
|  |         //   Stage 0: No closures detected, or the detected identifier is invalid. We're going forward while appending the characters normally. | ||||||
|  |         //   Stage 1: The closure has been detected, looking for the placeholder identifier... | ||||||
|  |         //   Stage 2: Detected the identifier and the parameter. Translating the placeholder... | ||||||
|  |         int stage = 0; | ||||||
|  |  | ||||||
|  |         for (char ch : chars) { | ||||||
|  |             if (stage == -1 && COLOR_CODES.contains(ch)) { | ||||||
|  |                 builder.append(ChatColor.COLOR_CHAR).append(ch); | ||||||
|  |                 stage = 0; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Check if the placeholder starts or ends. | ||||||
|  |             if (ch == closure.start || ch == closure.end) { | ||||||
|  |                 // If the placeholder ends. | ||||||
|  |                 if (stage == 2) { | ||||||
|  |                     String parameter = identifier.toString(); | ||||||
|  |                     String translated = handler.onRequest(player, parameter); | ||||||
|  |  | ||||||
|  |                     if (translated == null) { | ||||||
|  |                         String name = handler.isExpansion() ? ((PlaceholderExpansion) handler).getIdentifier() : ""; | ||||||
|  |                         builder.append(closure.start).append(name).append('_').append(parameter).append(closure.end); | ||||||
|  |                     } else builder.append(translated); | ||||||
|  |  | ||||||
|  |                     identifier.setLength(0); | ||||||
|  |                     stage = 0; | ||||||
|  |                     continue; | ||||||
|  |                 } else if (stage == 1) { // If it just started | Double closures | If it's still hasn't detected the indentifier, reset. | ||||||
|  |                     builder.append(closure.start).append(identifier); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 identifier.setLength(0); | ||||||
|  |                 stage = 1; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Placeholder identifier started. | ||||||
|  |             if (stage == 1) { | ||||||
|  |                 // Compare the current character with the idenfitier's. | ||||||
|  |                 // We reached the end of our identifier. | ||||||
|  |                 if (ch == '_') { | ||||||
|  |                     handler = PlaceholderAPI.PLACEHOLDERS.get(identifier.toString()); | ||||||
|  |                     if (handler == null) { | ||||||
|  |                         builder.append(closure.start).append(identifier).append('_'); | ||||||
|  |                         stage = 0; | ||||||
|  |                     } else { | ||||||
|  |                         identifier.setLength(0); | ||||||
|  |                         stage = 2; | ||||||
|  |                     } | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // Keep building the identifier name. | ||||||
|  |                 identifier.append(ch); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Building the placeholder parameter. | ||||||
|  |             if (stage == 2) { | ||||||
|  |                 identifier.append(ch); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Nothing placeholder related was found. | ||||||
|  |             if (colorize && ch == '&') { | ||||||
|  |                 stage = -1; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             builder.append(ch); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (identifier != null) { | ||||||
|  |             if (stage > 0) builder.append(closure.end); | ||||||
|  |             builder.append(identifier); | ||||||
|  |         } | ||||||
|  |         return builder.toString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public enum Closure { | ||||||
|  |         PERCENT('%', '%'), BRACKETS('[', ']'), BRACES('{', '}'); | ||||||
|  |  | ||||||
|  |         public char start, end; | ||||||
|  |  | ||||||
|  |         Closure(char start, char end) { | ||||||
|  |             this.start = start; | ||||||
|  |             this.end = end; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,52 +1,42 @@ | |||||||
| package me.clip.placeholderapi.commands; | package me.clip.placeholderapi.commands; | ||||||
|  |  | ||||||
| import com.google.common.collect.ImmutableSet; |  | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
| import org.jetbrains.annotations.Nullable; |  | ||||||
|  |  | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
| public abstract class Command { | public abstract class Command { | ||||||
|     private static final Options EMPTY_OPTIONS = new Options(null, 0, null); |     private static final Options EMPTY_OPTIONS = new Options(null, 0); | ||||||
|  |  | ||||||
|     private final String match; |     private final String match; | ||||||
|     private final String usage; |     private final String usage; | ||||||
|     private final int minimumArguments; |     private final int minimumArguments; | ||||||
|     private final Set<String> permissions; |     /** | ||||||
|  |      * Commands should not have multiple permissions. This can lead to a lot of confusions. | ||||||
|  |      * This is also a lot more appropriate for maintainability, I saw a lot of commands regitered with wrong permissions. | ||||||
|  |      * We will use the main command name to parse our permission. | ||||||
|  |      */ | ||||||
|  |     private final String permission; | ||||||
|  |  | ||||||
|     protected Command(@NotNull final String match) { |     protected Command(String match) { | ||||||
|         this(match, EMPTY_OPTIONS); |         this(match, EMPTY_OPTIONS); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected Command(@NotNull final String match, @NotNull final Options options) { |     protected Command(String match, Options options) { | ||||||
|         this.match = match; |         this.match = match; | ||||||
|         this.usage = options.usage == null ? "/papi " + match + " <required args> [optional args]" : options.usage; |         this.usage = options.usage == null ? "/papi " + match + " <required args> [optional args]" : options.usage; | ||||||
|         this.permissions = options.permissions == null ? Collections.emptySet() : ImmutableSet.copyOf(options.permissions); |         this.permission = "placeholderapi." + match.replace(' ', '.'); | ||||||
|         this.minimumArguments = options.minimumArguments; |         this.minimumArguments = options.minimumArguments; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected static Options usage(@NotNull final String usage, final int minimumArguments) { |     protected static Options options(String usage, int minimumArguments) { | ||||||
|         return new Options(usage, minimumArguments, null); |         return new Options(usage, minimumArguments); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected static Options permissions(@NotNull final String... permissions) { |  | ||||||
|         return new Options(null, 0, permissions); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     protected static Options options(@NotNull final String usage, final int minimumArguments, |  | ||||||
|                                      @NotNull final String... permissions) { |  | ||||||
|         return new Options(usage, minimumArguments, permissions); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @NotNull |  | ||||||
|     public String getMatch() { |     public String getMatch() { | ||||||
|         return match; |         return match; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NotNull |  | ||||||
|     public String getUsage() { |     public String getUsage() { | ||||||
|         return usage; |         return usage; | ||||||
|     } |     } | ||||||
| @@ -55,28 +45,23 @@ public abstract class Command { | |||||||
|         return minimumArguments; |         return minimumArguments; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NotNull |     public String getPermission() { | ||||||
|     public Set<String> getPermissions() { |         return permission; | ||||||
|         return permissions; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public abstract void execute(@NotNull final CommandSender sender, @NotNull final String[] args); |     public abstract void execute(CommandSender sender, String[] args); | ||||||
|  |  | ||||||
|     @NotNull |     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|     public List<String> handleCompletion(@NotNull final CommandSender sender, @NotNull final String[] args) { |  | ||||||
|         return Collections.emptyList(); |         return Collections.emptyList(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static class Options { |     private static class Options { | ||||||
|         private final String usage; |         private final String usage; | ||||||
|         private final int minimumArguments; |         private final int minimumArguments; | ||||||
|         private final String[] permissions; |  | ||||||
|  |  | ||||||
|         private Options(@Nullable final String usage, final int minimumArguments, |         private Options(String usage, int minimumArguments) { | ||||||
|                         @Nullable final String[] permissions) { |  | ||||||
|             this.usage = usage; |             this.usage = usage; | ||||||
|             this.minimumArguments = minimumArguments; |             this.minimumArguments = minimumArguments; | ||||||
|             this.permissions = permissions; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,25 +1,33 @@ | |||||||
| package me.clip.placeholderapi.commands; | package me.clip.placeholderapi.commands; | ||||||
|  |  | ||||||
| import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||||
| import me.clip.placeholderapi.PlaceholderAPIPlugin; |  | ||||||
| import me.clip.placeholderapi.commands.command.*; | import me.clip.placeholderapi.commands.command.*; | ||||||
| import me.clip.placeholderapi.commands.command.ecloud.EcloudInfoCommand; |  | ||||||
| import me.clip.placeholderapi.commands.command.ecloud.EcloudListCommand; |  | ||||||
| import me.clip.placeholderapi.commands.command.ecloud.*; | import me.clip.placeholderapi.commands.command.ecloud.*; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
|  | import org.apache.commons.lang.StringUtils; | ||||||
| import org.bukkit.command.CommandExecutor; | import org.bukkit.command.CommandExecutor; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Objects; |  | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
| import java.util.regex.Pattern; |  | ||||||
|  |  | ||||||
| public final class CommandHandler implements CommandExecutor { | public final class CommandHandler implements CommandExecutor { | ||||||
|     private static final Command DEFAULT = new VersionCommand(); |     private static final Command DEFAULT = new VersionCommand(); | ||||||
|  |  | ||||||
|     private static final List<Command> COMMANDS = Lists.newArrayList( |     protected static final List<Command> COMMANDS = Lists.newArrayList( | ||||||
|  |             DEFAULT, | ||||||
|  |             new HelpCommand(), | ||||||
|  |             new InfoCommand(), | ||||||
|  |             new ListCommand(), | ||||||
|  |             new RegisterCommand(), | ||||||
|  |             new UnregisterCommand(), | ||||||
|  |             new ReloadCommand(), | ||||||
|  |             new BcParseCommand(), | ||||||
|  |             new ParseCommand(), | ||||||
|  |             new ParseRelCommand(), | ||||||
|  |  | ||||||
|  |             new EcloudCommand(), | ||||||
|             new EcloudClearCommand(), |             new EcloudClearCommand(), | ||||||
|             new EcloudDownloadCommand(), |             new EcloudDownloadCommand(), | ||||||
|             new EcloudInfoCommand(), |             new EcloudInfoCommand(), | ||||||
| @@ -28,74 +36,57 @@ public final class CommandHandler implements CommandExecutor { | |||||||
|             new EcloudRefreshCommand(), |             new EcloudRefreshCommand(), | ||||||
|             new EcloudStatusCommand(), |             new EcloudStatusCommand(), | ||||||
|             new EcloudVersionInfoCommand(), |             new EcloudVersionInfoCommand(), | ||||||
|             new EcloudCommand(), |             new EcloudDisableCommand(), | ||||||
|             new BcParseCommand(), |             new EcloudEnableCommand() | ||||||
|             new ParseCommand(), |  | ||||||
|             new ParseRelCommand(), |  | ||||||
|             new DisableEcloudCommand(), |  | ||||||
|             new EnableCloudCommand(), |  | ||||||
|             new HelpCommand(), |  | ||||||
|             new InfoCommand(), |  | ||||||
|             new ListCommand(), |  | ||||||
|             new RegisterCommand(), |  | ||||||
|             new ReloadCommand(), |  | ||||||
|             DEFAULT, |  | ||||||
|             new UnregisterCommand() |  | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     static { |     static { | ||||||
|         COMMANDS.sort((command1, command2) -> { |         COMMANDS.sort((command1, command2) -> { | ||||||
|             final int comparison = Integer.compare(command1.getMatch().length(), command2.getMatch().length()); |             int comparison = Integer.compare(command1.getMatch().length(), command2.getMatch().length()); | ||||||
|  |  | ||||||
|             if (comparison == 1) return -1; |             if (comparison == 1) return -1; | ||||||
|             if (comparison == -1) return 1; |             if (comparison == -1) return 1; | ||||||
|             return 0; |             return 0; | ||||||
|         }); |         }); | ||||||
|         Objects.requireNonNull(PlaceholderAPIPlugin.getInstance().getCommand("placeholderapi")) |  | ||||||
|             .setTabCompleter(new CompletionHandler(COMMANDS)); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static final Pattern SPACE_PATTERN = Pattern.compile(" "); |     private static String[] splitArguments(String joinedArguments, String command) { | ||||||
|  |         joinedArguments = StringUtils.remove(joinedArguments, command).trim(); | ||||||
|  |         String[] args = StringUtils.split(joinedArguments); | ||||||
|  |         return args.length == 1 && args[0].isEmpty() ? new String[0] : args; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean onCommand(@NotNull final CommandSender sender, @NotNull final org.bukkit.command.Command bukkitCommand, |     public boolean onCommand(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command bukkitCommand, @NotNull String name, String[] args) { | ||||||
|                              @NotNull final String name, @NotNull String[] args) { |  | ||||||
|         if (args.length == 0) { |         if (args.length == 0) { | ||||||
|             DEFAULT.execute(sender, args); |             DEFAULT.execute(sender, args); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final String joined = String.join(" ", args).toLowerCase(); |         String joined = String.join(" ", args).toLowerCase(); | ||||||
|         final Optional<Command> optional = COMMANDS.stream() |         Optional<Command> optional = COMMANDS.stream() | ||||||
|                 .filter(command -> joined.startsWith(command.getMatch())) |                 .filter(command -> joined.startsWith(command.getMatch())) | ||||||
|                 .findFirst(); |                 .findFirst(); | ||||||
|  |  | ||||||
|         if (!optional.isPresent()) { |         if (!optional.isPresent()) { | ||||||
|             sender.sendMessage("Specified command is not valid."); |             Msg.msg(sender, "&cUnknown command."); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final Command command = optional.get(); |         Command command = optional.get(); | ||||||
|  |         String permission = command.getPermission(); | ||||||
|         if (!command.getPermissions().isEmpty() && command.getPermissions().stream().noneMatch(sender::hasPermission)) { |         if (!sender.hasPermission(permission)) { | ||||||
|             sender.sendMessage("You do not have the permission to execute specified command."); |             Msg.msg(sender, "&cYou do not have the permission to use this command."); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         args = splitArguments(joined, command.getMatch()); |         args = splitArguments(joined, command.getMatch()); | ||||||
|  |  | ||||||
|         if (args.length < command.getMinimumArguments()) { |         if (args.length < command.getMinimumArguments()) { | ||||||
|             Msg.msg(sender, command.getUsage()); |             Msg.msg(sender, command.getUsage()); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         command.execute(sender, args); |         command.execute(sender, args); | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static String[] splitArguments(@NotNull final String joinedArguments, @NotNull final String command) { |  | ||||||
|         final String[] args = SPACE_PATTERN.split(joinedArguments.replace(command, "").trim()); |  | ||||||
|         return args.length == 1 && args[0].isEmpty() ? new String[]{} : args; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,32 +1,37 @@ | |||||||
| package me.clip.placeholderapi.commands; | package me.clip.placeholderapi.commands; | ||||||
|  |  | ||||||
|  | import org.apache.commons.lang.StringUtils; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.command.TabCompleter; | import org.bukkit.command.TabCompleter; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
|  |  | ||||||
|  | import java.util.Arrays; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Optional; | import java.util.Locale; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| public final class CompletionHandler implements TabCompleter { | public final class CompletionHandler implements TabCompleter { | ||||||
|     private final List<Command> commands; |     private static String[] splitArguments(String[] args, String command) { | ||||||
|  |         int skip = StringUtils.split(command).length; | ||||||
|     CompletionHandler(@NotNull final List<Command> commands) { |         return Arrays.stream(args).skip(skip).toArray(String[]::new); | ||||||
|         this.commands = commands; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // it makes me physically cringe trying to understand why bukkit uses a list instead of a set for this |     // it makes me physically cringe trying to understand why bukkit uses a list instead of a set for this | ||||||
|     @NotNull |     // It's because of the list order. Even if they wanted to change that, they couldn't for the sake of backward compatibility. ~Crypto | ||||||
|     @Override |     @Override | ||||||
|     public List<String> onTabComplete(@NotNull final CommandSender sender, @NotNull final org.bukkit.command.Command bukkitCommand, |     public List<String> onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command bukkitCommand, @NotNull String name, String[] args) { | ||||||
|                                       @NotNull final String name, @NotNull final String[] args) { |         String joined = String.join(" ", args).toLowerCase(Locale.ENGLISH); | ||||||
|         final String joined = String.join(" ", args).toLowerCase(); |  | ||||||
|         final Optional<Command> optional = commands.stream() |  | ||||||
|                 .filter(command -> joined.startsWith(command.getMatch())) |  | ||||||
|                 .findAny(); |  | ||||||
|  |  | ||||||
|         return optional |         if (args.length > 1) { | ||||||
|                 .map(command -> command.handleCompletion(sender, CommandHandler.splitArguments(joined, command.getMatch()))) |             return CommandHandler.COMMANDS.stream() | ||||||
|  |                     .filter(command -> sender.hasPermission(command.getPermission()) && joined.startsWith(command.getMatch())) | ||||||
|  |                     .findFirst() | ||||||
|  |                     .map(command -> command.handleCompletion(sender, splitArguments(args, command.getMatch()))) | ||||||
|                     .orElse(Collections.emptyList()); |                     .orElse(Collections.emptyList()); | ||||||
|         } |         } | ||||||
|  |         return CommandHandler.COMMANDS.stream() | ||||||
|  |                 .filter(command -> sender.hasPermission(command.getPermission()) && (args[0].isEmpty() || command.getMatch().startsWith(joined))) | ||||||
|  |                 .map(Command::getMatch).collect(Collectors.toList()); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,40 +8,34 @@ import org.bukkit.Bukkit; | |||||||
| import org.bukkit.OfflinePlayer; | import org.bukkit.OfflinePlayer; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class BcParseCommand extends Command { | public final class BcParseCommand extends Command { | ||||||
|     public BcParseCommand() { |     public BcParseCommand() { | ||||||
|         super("bcparse", options("&cYou must specify a player.", 1, "placeholderapi.parse")); |         super("bcparse", options("&cYou must specify a player.", 1)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final OfflinePlayer player; |         OfflinePlayer player; | ||||||
|         final String input = args[0]; |         String input = args[0]; | ||||||
|  |  | ||||||
|         if (input.equalsIgnoreCase("me")) { |         if (input.equalsIgnoreCase("me")) { | ||||||
|             if (sender instanceof Player) { |             if (sender instanceof Player) { | ||||||
|                 player = (Player) sender; |                 player = (Player) sender; | ||||||
|             } else { |             } else { | ||||||
|                 Msg.msg(sender, "&cThis command must target a player when used by console"); |                 Msg.msg(sender, "&cThis command must target a player when used by console"); | ||||||
|  |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             if (Bukkit.getPlayer(input) != null) { |  | ||||||
|             player = Bukkit.getPlayer(input); |             player = Bukkit.getPlayer(input); | ||||||
|             } else { |             if (player == null) player = Bukkit.getOfflinePlayer(input); | ||||||
|                 player = Bukkit.getOfflinePlayer(input); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|             if (player == null || !player.hasPlayedBefore()) { |             if (player == null || !player.hasPlayedBefore()) { | ||||||
|             Msg.msg(sender, "&cFailed to find player: &f" + input); |                 Msg.msg(sender, "&cCould not find player&8: &f" + input); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         final String parse = StringUtils.join(args, " ", 2, args.length); |         String parse = StringUtils.join(args, " ", 2, args.length); | ||||||
|         Msg.broadcast("&r" + PlaceholderAPI.setPlaceholders(player, parse)); |         Msg.broadcast("&r" + PlaceholderAPI.setPlaceholders(player, parse)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ import me.clip.placeholderapi.commands.Command; | |||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.util.StringUtil; | import org.bukkit.util.StringUtil; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @@ -22,16 +21,18 @@ public final class EcloudCommand extends Command { | |||||||
|             "placeholders", |             "placeholders", | ||||||
|             "refresh", |             "refresh", | ||||||
|             "status", |             "status", | ||||||
|             "versioninfo" |             "versioninfo", | ||||||
|  |             "enable", | ||||||
|  |             "disable" | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     public EcloudCommand() { |     public EcloudCommand() { | ||||||
|         super("ecloud", permissions("placeholderapi.ecloud")); |         super("ecloud"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|  |  | ||||||
|         if (args.length == 0) { |         if (args.length == 0) { | ||||||
|             Msg.msg(sender, "&bExpansion cloud commands", |             Msg.msg(sender, "&bExpansion cloud commands", | ||||||
| @@ -57,7 +58,6 @@ public final class EcloudCommand extends Command { | |||||||
|  |  | ||||||
|         if (plugin.getExpansionCloud() == null) { |         if (plugin.getExpansionCloud() == null) { | ||||||
|             Msg.msg(sender, "&7The expansion cloud is not enabled!"); |             Msg.msg(sender, "&7The expansion cloud is not enabled!"); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -69,9 +69,9 @@ public final class EcloudCommand extends Command { | |||||||
|         sender.sendMessage("Specified command is not valid."); |         sender.sendMessage("Specified command is not valid."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NotNull |  | ||||||
|     @Override |     @Override | ||||||
|     public List<String> handleCompletion(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|         if (args.length == MAXIMUM_ARGUMENTS) { |         if (args.length == MAXIMUM_ARGUMENTS) { | ||||||
|             return StringUtil.copyPartialMatches(args[0], COMPLETIONS, new ArrayList<>(COMPLETIONS.size())); |             return StringUtil.copyPartialMatches(args[0], COMPLETIONS, new ArrayList<>(COMPLETIONS.size())); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -4,15 +4,14 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | |||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class HelpCommand extends Command { | public final class HelpCommand extends Command { | ||||||
|     public HelpCommand() { |     public HelpCommand() { | ||||||
|         super("help", permissions("placeholderapi.ecloud")); |         super("help"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         Msg.msg(sender, "PlaceholderAPI &aHelp &e(&f" + PlaceholderAPIPlugin.getInstance().getDescription().getVersion() + "&e)", |         Msg.msg(sender, "PlaceholderAPI &aHelp &e(&f" + PlaceholderAPIPlugin.getInstance().getDescription().getVersion() + "&e)", | ||||||
|                 "&b/papi", |                 "&b/papi", | ||||||
|                 "&fView plugin info/version info", |                 "&fView plugin info/version info", | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ import me.clip.placeholderapi.expansion.PlaceholderExpansion; | |||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.util.StringUtil; | import org.bukkit.util.StringUtil; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @@ -17,13 +16,13 @@ public final class InfoCommand extends Command { | |||||||
|     private static final int MINIMUM_ARGUMENTS = 1; |     private static final int MINIMUM_ARGUMENTS = 1; | ||||||
|  |  | ||||||
|     public InfoCommand() { |     public InfoCommand() { | ||||||
|         super("info", options("&cIncorrect usage! &7/papi info <expansion>", MINIMUM_ARGUMENTS, "placeholderapi.info")); |         super("info", options("&cIncorrect usage! &7/papi info <expansion>", MINIMUM_ARGUMENTS)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final String requestedExpansion = args[0]; |         String requestedExpansion = args[0]; | ||||||
|         final PlaceholderExpansion ex = PlaceholderAPIPlugin.getInstance().getExpansionManager().getRegisteredExpansion(requestedExpansion); |         PlaceholderExpansion ex = PlaceholderAPIPlugin.getInstance().getExpansionManager().getRegisteredExpansion(requestedExpansion); | ||||||
|         if (ex == null) { |         if (ex == null) { | ||||||
|             Msg.msg(sender, "&cThere is no expansion loaded with the identifier: &f" + requestedExpansion); |             Msg.msg(sender, "&cThere is no expansion loaded with the identifier: &f" + requestedExpansion); | ||||||
|  |  | ||||||
| @@ -54,11 +53,11 @@ public final class InfoCommand extends Command { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NotNull |  | ||||||
|     @Override |     @Override | ||||||
|     public List<String> handleCompletion(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|         if (args.length == MINIMUM_ARGUMENTS) { |         if (args.length == MINIMUM_ARGUMENTS) { | ||||||
|             final Set<String> completions = PlaceholderAPI.getRegisteredIdentifiers(); |             Set<String> completions = PlaceholderAPI.getRegisteredIdentifiers(); | ||||||
|  |  | ||||||
|             return StringUtil.copyPartialMatches(args[0], completions, new ArrayList<>(completions.size())); |             return StringUtil.copyPartialMatches(args[0], completions, new ArrayList<>(completions.size())); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -4,19 +4,18 @@ import me.clip.placeholderapi.PlaceholderAPI; | |||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| public final class ListCommand extends Command { | public final class ListCommand extends Command { | ||||||
|     public ListCommand() { |     public ListCommand() { | ||||||
|         super("list", permissions("placeholderapi.list")); |         super("list"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final Set<String> registered = PlaceholderAPI.getRegisteredIdentifiers(); |         Set<String> registered = PlaceholderAPI.getRegisteredIdentifiers(); | ||||||
|         if (registered.isEmpty()) { |         if (registered.isEmpty()) { | ||||||
|             Msg.msg(sender, "&7There are no placeholder hooks currently registered!"); |             Msg.msg(sender, "&7There are no placeholder hooks currently registered!"); | ||||||
|             return; |             return; | ||||||
|   | |||||||
| @@ -7,41 +7,53 @@ import org.apache.commons.lang.StringUtils; | |||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.OfflinePlayer; | import org.bukkit.OfflinePlayer; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
|  | import org.bukkit.entity.HumanEntity; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| public final class ParseCommand extends Command { | public final class ParseCommand extends Command { | ||||||
|     public ParseCommand() { |     public ParseCommand() { | ||||||
|         super("parse", options("&cYou must specify a player.", 1, "placeholderapi.parse")); |         super("parse", options("&cYou must specify a player.", 1)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final OfflinePlayer player; |         OfflinePlayer player; | ||||||
|         final String input = args[0]; |         String input = args[0]; | ||||||
|  |  | ||||||
|         if (input.equalsIgnoreCase("me")) { |         if (input.equalsIgnoreCase("me")) { | ||||||
|             if (sender instanceof Player) { |             if (sender instanceof Player) { | ||||||
|                 player = (Player) sender; |                 player = (Player) sender; | ||||||
|             } else { |             } else { | ||||||
|                 Msg.msg(sender, "&cThis command must target a player when used by console"); |                 Msg.msg(sender, "&cThis command must target a player when used by console"); | ||||||
|  |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             if (Bukkit.getPlayer(input) != null) { |  | ||||||
|             player = Bukkit.getPlayer(input); |             player = Bukkit.getPlayer(input); | ||||||
|             } else { |             if (player == null) player = Bukkit.getOfflinePlayer(input); | ||||||
|                 player = Bukkit.getOfflinePlayer(input); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|             if (player == null || !player.hasPlayedBefore()) { |             if (player == null || !player.hasPlayedBefore()) { | ||||||
|             Msg.msg(sender, "&cFailed to find player: &f" + input); |                 Msg.msg(sender, "&cCould not find player&8: &f" + input); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         final String parse = StringUtils.join(args, " ", 1, args.length); |         String parse = StringUtils.join(args, " ", 1, args.length); | ||||||
|         Msg.msg(sender, "&r" + PlaceholderAPI.setPlaceholders(player, parse)); |         Msg.msg(sender, "&r" + PlaceholderAPI.setPlaceholders(player, parse)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|  |         if (args.length == 1) { | ||||||
|  |             List<String> players = Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).collect(Collectors.toList()); | ||||||
|  |             players.add("me"); | ||||||
|  |             if (args[0].isEmpty()) return players; | ||||||
|  |             else return players.stream().filter(name -> name.startsWith(args[0])).collect(Collectors.toList()); | ||||||
|  |         } | ||||||
|  |         if (args.length == 2) return Collections.singletonList("<message>"); | ||||||
|  |         return new ArrayList<>(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,30 +7,27 @@ import org.apache.commons.lang.StringUtils; | |||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class ParseRelCommand extends Command { | public final class ParseRelCommand extends Command { | ||||||
|     public ParseRelCommand() { |     public ParseRelCommand() { | ||||||
|         super("parserel", options("&cYou must specify at least two players.", 2, "placeholderapi.parse")); |         super("parserel", options("&cYou must specify at least two players.", 2)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final Player one = Bukkit.getPlayer(args[0]); |         Player one = Bukkit.getPlayer(args[0]); | ||||||
|         if (one == null) { |         if (one == null) { | ||||||
|             Msg.msg(sender, args[0] + " &cis not online!"); |             Msg.msg(sender, args[0] + " &cis not online!"); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final Player two = Bukkit.getPlayer(args[1]); |         Player two = Bukkit.getPlayer(args[1]); | ||||||
|         if (two == null) { |         if (two == null) { | ||||||
|             Msg.msg(sender, args[1] + " &cis not online!"); |             Msg.msg(sender, args[1] + " &cis not online!"); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final String parse = StringUtils.join(args, " ", 1, args.length); |         String parse = StringUtils.join(args, " ", 1, args.length); | ||||||
|         Msg.msg(sender, "&r" + PlaceholderAPI.setRelationalPlaceholders(one, two, parse)); |         Msg.msg(sender, "&r" + PlaceholderAPI.setRelationalPlaceholders(one, two, parse)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,22 +4,21 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | |||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.expansion.PlaceholderExpansion; | import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
|  | import org.apache.commons.lang.StringUtils; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class RegisterCommand extends Command { | public final class RegisterCommand extends Command { | ||||||
|     public RegisterCommand() { |     public RegisterCommand() { | ||||||
|         super("register", options("&cAn expansion file name must be specified!", 1,"placeholderapi.register")); |         super("register", options("&cAn expansion file name must be specified!", 1)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final String fileName = args[0].replace(".jar", ""); |         String fileName = StringUtils.remove(args[0], ".jar"); | ||||||
|         final PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager().registerExpansion(fileName); |         PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager().registerExpansion(fileName); | ||||||
|  |  | ||||||
|         if (expansion == null) { |         if (expansion == null) { | ||||||
|             Msg.msg(sender, "&cFailed to register expansion from " + fileName); |             Msg.msg(sender, "&cFailed to register expansion from " + fileName); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,15 +4,14 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | |||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class ReloadCommand extends Command { | public final class ReloadCommand extends Command { | ||||||
|     public ReloadCommand() { |     public ReloadCommand() { | ||||||
|         super("reload", permissions("placeholderapi.reload")); |         super("reload"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         Msg.msg(sender, "&fPlaceholder&7API &bconfiguration reloaded!"); |         Msg.msg(sender, "&fPlaceholder&7API &bconfiguration reloaded!"); | ||||||
|         PlaceholderAPIPlugin.getInstance().reloadConf(sender); |         PlaceholderAPIPlugin.getInstance().reloadConf(sender); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ import me.clip.placeholderapi.expansion.PlaceholderExpansion; | |||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.util.StringUtil; | import org.bukkit.util.StringUtil; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @@ -17,18 +16,17 @@ public final class UnregisterCommand extends Command { | |||||||
|     private static final int MINIMUM_ARGUMENTS = 1; |     private static final int MINIMUM_ARGUMENTS = 1; | ||||||
|  |  | ||||||
|     public UnregisterCommand() { |     public UnregisterCommand() { | ||||||
|         super("unregister", options("&cAn expansion name must be specified!", MINIMUM_ARGUMENTS, "placeholderapi.register")); |         super("unregister", options("&cAn expansion name must be specified!", MINIMUM_ARGUMENTS)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final String requestedExpansion = args[0]; |         String requestedExpansion = args[0]; | ||||||
|         final PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager() |         PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager() | ||||||
|                 .getRegisteredExpansion(requestedExpansion); |                 .getRegisteredExpansion(requestedExpansion); | ||||||
|  |  | ||||||
|         if (expansion == null) { |         if (expansion == null) { | ||||||
|             Msg.msg(sender, "&cFailed to find expansion: &f" + requestedExpansion); |             Msg.msg(sender, "&cFailed to find expansion: &f" + requestedExpansion); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -39,12 +37,11 @@ public final class UnregisterCommand extends Command { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NotNull |  | ||||||
|     @Override |  | ||||||
|     public List<String> handleCompletion(@NotNull final CommandSender sender, @NotNull final String[] args) { |  | ||||||
|         if (args.length == MINIMUM_ARGUMENTS) { |  | ||||||
|             final Set<String> completions = PlaceholderAPI.getRegisteredIdentifiers(); |  | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|  |         if (args.length == MINIMUM_ARGUMENTS) { | ||||||
|  |             Set<String> completions = PlaceholderAPI.getRegisteredIdentifiers(); | ||||||
|             return StringUtil.copyPartialMatches(args[0], completions, new ArrayList<>(completions.size())); |             return StringUtil.copyPartialMatches(args[0], completions, new ArrayList<>(completions.size())); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ import me.clip.placeholderapi.util.Msg; | |||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.plugin.PluginDescriptionFile; | import org.bukkit.plugin.PluginDescriptionFile; | ||||||
| import org.bukkit.util.StringUtil; | import org.bukkit.util.StringUtil; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @@ -34,8 +33,8 @@ public final class VersionCommand extends Command { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PluginDescriptionFile description = PlaceholderAPIPlugin.getInstance().getDescription(); |         PluginDescriptionFile description = PlaceholderAPIPlugin.getInstance().getDescription(); | ||||||
|  |  | ||||||
|         Msg.msg(sender, "PlaceholderAPI &7version &b&o" + description.getVersion(), |         Msg.msg(sender, "PlaceholderAPI &7version &b&o" + description.getVersion(), | ||||||
|                 "&fCreated by&7: &b" + description.getAuthors(), |                 "&fCreated by&7: &b" + description.getAuthors(), | ||||||
| @@ -43,9 +42,9 @@ public final class VersionCommand extends Command { | |||||||
|                 "&fEcloud commands: &b/papi ecloud"); |                 "&fEcloud commands: &b/papi ecloud"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NotNull |  | ||||||
|     @Override |     @Override | ||||||
|     public List<String> handleCompletion(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|         if (args.length == 1) { |         if (args.length == 1) { | ||||||
|             return StringUtil.copyPartialMatches(args[0], COMPLETIONS, new ArrayList<>(COMPLETIONS.size())); |             return StringUtil.copyPartialMatches(args[0], COMPLETIONS, new ArrayList<>(COMPLETIONS.size())); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -4,15 +4,14 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | |||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class EcloudClearCommand extends Command { | public final class EcloudClearCommand extends Command { | ||||||
|     public EcloudClearCommand() { |     public EcloudClearCommand() { | ||||||
|         super("ecloud clear", permissions("placeholderapi.ecloud")); |         super("ecloud clear"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         PlaceholderAPIPlugin.getInstance().getExpansionCloud().clean(); |         PlaceholderAPIPlugin.getInstance().getExpansionCloud().clean(); | ||||||
|         Msg.msg(sender, "&aThe cache has been cleared!!"); |         Msg.msg(sender, "&aThe cache has been cleared!!"); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,29 +1,25 @@ | |||||||
| package me.clip.placeholderapi.commands.command; | package me.clip.placeholderapi.commands.command.ecloud; | ||||||
| 
 | 
 | ||||||
| import me.clip.placeholderapi.PlaceholderAPIPlugin; | import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
| 
 | 
 | ||||||
| public final class DisableEcloudCommand extends Command { | public final class EcloudDisableCommand extends Command { | ||||||
|     public DisableEcloudCommand() { |     public EcloudDisableCommand() { | ||||||
|         super("disablecloud", permissions("placeholderapi.ecloud")); |         super("ecloud disable"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|         if (plugin.getExpansionCloud() == null) { |         if (plugin.getExpansionCloud() == null) { | ||||||
|             Msg.msg(sender, "&7The cloud is already disabled!"); |             Msg.msg(sender, "&7The cloud is already disabled!"); | ||||||
| 
 |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         plugin.disableCloud(); |         plugin.disableCloud(); | ||||||
|         plugin.getPlaceholderAPIConfig().setCloudEnabled(false); |         plugin.getPlaceholderAPIConfig().setCloudEnabled(false); | ||||||
|         Msg.msg(sender, "&aThe cloud has been disabled!"); |         Msg.msg(sender, "&aThe cloud has been disabled!"); | ||||||
| 
 |  | ||||||
|         return; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -9,25 +9,24 @@ import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; | |||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class EcloudDownloadCommand extends Command { | public final class EcloudDownloadCommand extends Command { | ||||||
|     public EcloudDownloadCommand() { |     public EcloudDownloadCommand() { | ||||||
|         super("ecloud download", options("&cAn expansion name must be specified!", 1, "placeholderapi.ecloud")); |         super("ecloud download", options("&cAn expansion name must be specified!", 1)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|         final String input = args[0]; |         String input = args[0]; | ||||||
|         final CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); |         CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); | ||||||
|  |  | ||||||
|         if (expansion == null) { |         if (expansion == null) { | ||||||
|             Msg.msg(sender, "&cNo expansion found with the name: &f" + input); |             Msg.msg(sender, "&cNo expansion found with the name: &f" + input); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final PlaceholderExpansion loaded = plugin.getExpansionManager().getRegisteredExpansion(input); |         PlaceholderExpansion loaded = plugin.getExpansionManager().getRegisteredExpansion(input); | ||||||
|         if (loaded != null && loaded.isRegistered()) { |         if (loaded != null && loaded.isRegistered()) { | ||||||
|             PlaceholderAPI.unregisterPlaceholderHook(loaded.getIdentifier()); |             PlaceholderAPI.unregisterPlaceholderHook(loaded.getIdentifier()); | ||||||
|         } |         } | ||||||
| @@ -46,10 +45,23 @@ public final class EcloudDownloadCommand extends Command { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         Msg.msg(sender, "&aDownload starting for expansion: &f" + expansion.getName() + " &aversion: &f" + version); |         Msg.msg(sender, "&aDownload starting for expansion: &f" + expansion.getName() + " &aversion: &f" + version); | ||||||
|         final String player = ((sender instanceof Player) ? sender.getName() : null); |         String player = ((sender instanceof Player) ? sender.getName() : null); | ||||||
|         final ExpansionCloudManager cloud = plugin.getExpansionCloud(); |         ExpansionCloudManager cloud = plugin.getExpansionCloud(); | ||||||
|         cloud.downloadExpansion(player, expansion, version); |         cloud.downloadExpansion(player, expansion, version); | ||||||
|         cloud.clean(); |         cloud.clean(); | ||||||
|         cloud.fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); |         cloud.fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | //    @Override | ||||||
|  | //    public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|  | //        List<String> downloads = new ArrayList<>(); | ||||||
|  | //        if (!PlaceholderAPI.isRegistered("player")) downloads.add("player"); | ||||||
|  | // | ||||||
|  | //        for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { | ||||||
|  | //            String identifier = plugin.getName(); | ||||||
|  | //            if (!PlaceholderAPI.isRegistered(identifier)) downloads.add(identifier); | ||||||
|  | //        } | ||||||
|  | // | ||||||
|  | //        return downloads; | ||||||
|  | //    } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,22 +1,20 @@ | |||||||
| package me.clip.placeholderapi.commands.command; | package me.clip.placeholderapi.commands.command.ecloud; | ||||||
| 
 | 
 | ||||||
| import me.clip.placeholderapi.PlaceholderAPIPlugin; | import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
| 
 | 
 | ||||||
| public final class EnableCloudCommand extends Command { | public final class EcloudEnableCommand extends Command { | ||||||
|     public EnableCloudCommand() { |     public EcloudEnableCommand() { | ||||||
|         super("enablecloud", permissions("placeholderapi.ecloud")); |         super("ecloud enable"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|         if (plugin.getExpansionCloud() != null) { |         if (plugin.getExpansionCloud() != null) { | ||||||
|             Msg.msg(sender, "&7The cloud is already enabled!"); |             Msg.msg(sender, "&7The cloud is already enabled!"); | ||||||
| 
 |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -7,19 +7,18 @@ import me.clip.placeholderapi.util.Msg; | |||||||
| import me.rayzr522.jsonmessage.JSONMessage; | import me.rayzr522.jsonmessage.JSONMessage; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import static me.clip.placeholderapi.util.Msg.color; | import static me.clip.placeholderapi.util.Msg.color; | ||||||
|  |  | ||||||
| public final class EcloudInfoCommand extends Command { | public final class EcloudInfoCommand extends Command { | ||||||
|     public EcloudInfoCommand() { |     public EcloudInfoCommand() { | ||||||
|         super("ecloud info", options("&cAn expansion name must be specified!", 1, "placeholderapi.ecloud")); |         super("ecloud info", options("&cAn expansion name must be specified!", 1)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final String input = args[0]; |         String input = args[0]; | ||||||
|         final CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); |         CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); | ||||||
|  |  | ||||||
|         if (expansion == null) { |         if (expansion == null) { | ||||||
|             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); |             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); | ||||||
| @@ -35,7 +34,7 @@ public final class EcloudInfoCommand extends Command { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final Player p = (Player) sender; |         Player p = (Player) sender; | ||||||
|  |  | ||||||
|         Msg.msg(sender, "&bExpansion&7: &f" + expansion.getName(), |         Msg.msg(sender, "&bExpansion&7: &f" + expansion.getName(), | ||||||
|                 "&bAuthor: &f" + expansion.getAuthor(), |                 "&bAuthor: &f" + expansion.getAuthor(), | ||||||
| @@ -43,7 +42,7 @@ public final class EcloudInfoCommand extends Command { | |||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         // latest version |         // latest version | ||||||
|         final JSONMessage latestVersion = JSONMessage |         JSONMessage latestVersion = JSONMessage | ||||||
|                 .create(color("&bLatest version: &f" + expansion.getLatestVersion())); |                 .create(color("&bLatest version: &f" + expansion.getLatestVersion())); | ||||||
|         latestVersion.tooltip(color("&bReleased: &f" + expansion.getTimeSinceLastUpdate() |         latestVersion.tooltip(color("&bReleased: &f" + expansion.getTimeSinceLastUpdate() | ||||||
|                 + "\n&bUpdate information: &f" + expansion.getVersion().getReleaseNotes() |                 + "\n&bUpdate information: &f" + expansion.getVersion().getReleaseNotes() | ||||||
| @@ -51,7 +50,7 @@ public final class EcloudInfoCommand extends Command { | |||||||
|         latestVersion.send(p); |         latestVersion.send(p); | ||||||
|  |  | ||||||
|         // versions |         // versions | ||||||
|         final JSONMessage versions = JSONMessage |         JSONMessage versions = JSONMessage | ||||||
|                 .create(color("&bVersions available: &f" + expansion.getVersions().size())); |                 .create(color("&bVersions available: &f" + expansion.getVersions().size())); | ||||||
|         versions.tooltip(color(String.join("&b, &f", expansion.getAvailableVersions()))); |         versions.tooltip(color(String.join("&b, &f", expansion.getAvailableVersions()))); | ||||||
|         versions.suggestCommand( |         versions.suggestCommand( | ||||||
| @@ -60,7 +59,7 @@ public final class EcloudInfoCommand extends Command { | |||||||
|  |  | ||||||
|         // placeholders |         // placeholders | ||||||
|         if (expansion.getPlaceholders() != null) { |         if (expansion.getPlaceholders() != null) { | ||||||
|             final JSONMessage placeholders = JSONMessage |             JSONMessage placeholders = JSONMessage | ||||||
|                     .create(color("&bPlaceholders: &f" + expansion.getPlaceholders().size())); |                     .create(color("&bPlaceholders: &f" + expansion.getPlaceholders().size())); | ||||||
|             placeholders.tooltip(color(String.join("&b, &f", expansion.getPlaceholders()))); |             placeholders.tooltip(color(String.join("&b, &f", expansion.getPlaceholders()))); | ||||||
|             placeholders.suggestCommand("/papi ecloud placeholders " + expansion.getName()); |             placeholders.suggestCommand("/papi ecloud placeholders " + expansion.getName()); | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ import me.rayzr522.jsonmessage.JSONMessage; | |||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.bukkit.util.StringUtil; | import org.bukkit.util.StringUtil; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import java.util.*; | import java.util.*; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| @@ -25,13 +24,12 @@ public final class EcloudListCommand extends Command { | |||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     public EcloudListCommand() { |     public EcloudListCommand() { | ||||||
|         super("ecloud list", options("&cIncorrect usage! &7/papi ecloud list <all/author/installed> (page)", |         super("ecloud list", options("&cIncorrect usage! &7/papi ecloud list <all/author/installed> (page)", MINIMUM_ARGUMENTS)); | ||||||
|                 MINIMUM_ARGUMENTS, "placeholderapi.ecloud")); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|         int page = 1; |         int page = 1; | ||||||
|  |  | ||||||
|         String author; |         String author; | ||||||
| @@ -103,7 +101,7 @@ public final class EcloudListCommand extends Command { | |||||||
|         Msg.msg(sender, "&6Gold = Expansions which need updated"); |         Msg.msg(sender, "&6Gold = Expansions which need updated"); | ||||||
|  |  | ||||||
|         if (!(sender instanceof Player)) { |         if (!(sender instanceof Player)) { | ||||||
|             final Map<String, CloudExpansion> expansions = new HashMap<>(); |             Map<String, CloudExpansion> expansions = new HashMap<>(); | ||||||
|  |  | ||||||
|             for (CloudExpansion exp : ex.values()) { |             for (CloudExpansion exp : ex.values()) { | ||||||
|                 if (exp == null || exp.getName() == null) { |                 if (exp == null || exp.getName() == null) { | ||||||
| @@ -113,7 +111,7 @@ public final class EcloudListCommand extends Command { | |||||||
|                 expansions.put(exp.getName(), exp); |                 expansions.put(exp.getName(), exp); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             final List<String> ce = expansions.keySet().stream().sorted().collect(Collectors.toList()); |             List<String> ce = expansions.keySet().stream().sorted().collect(Collectors.toList()); | ||||||
|  |  | ||||||
|             int i = (int) ex.keySet().toArray()[0]; |             int i = (int) ex.keySet().toArray()[0]; | ||||||
|  |  | ||||||
| @@ -122,7 +120,7 @@ public final class EcloudListCommand extends Command { | |||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 final CloudExpansion expansion = expansions.get(name); |                 CloudExpansion expansion = expansions.get(name); | ||||||
|  |  | ||||||
|                 Msg.msg(sender, |                 Msg.msg(sender, | ||||||
|                         "&b" + i + "&7: " + (expansion.shouldUpdate() ? "&6" |                         "&b" + i + "&7: " + (expansion.shouldUpdate() ? "&6" | ||||||
| @@ -134,11 +132,11 @@ public final class EcloudListCommand extends Command { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final Player p = (Player) sender; |         Player p = (Player) sender; | ||||||
|  |  | ||||||
|         final Map<String, CloudExpansion> expansions = new HashMap<>(); |         Map<String, CloudExpansion> expansions = new HashMap<>(); | ||||||
|  |  | ||||||
|         for (final CloudExpansion exp : ex.values()) { |         for (CloudExpansion exp : ex.values()) { | ||||||
|             if (exp == null || exp.getName() == null) { |             if (exp == null || exp.getName() == null) { | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| @@ -146,7 +144,7 @@ public final class EcloudListCommand extends Command { | |||||||
|             expansions.put(exp.getName(), exp); |             expansions.put(exp.getName(), exp); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final List<String> ce = expansions.keySet().stream().sorted().collect(Collectors.toList()); |         List<String> ce = expansions.keySet().stream().sorted().collect(Collectors.toList()); | ||||||
|  |  | ||||||
|         int i = page > 1 ? page * 10 : 0; |         int i = page > 1 ? page * 10 : 0; | ||||||
|  |  | ||||||
| @@ -155,8 +153,8 @@ public final class EcloudListCommand extends Command { | |||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             final CloudExpansion expansion = expansions.get(name); |             CloudExpansion expansion = expansions.get(name); | ||||||
|             final StringBuilder sb = new StringBuilder(); |             StringBuilder sb = new StringBuilder(); | ||||||
|  |  | ||||||
|             if (expansion.shouldUpdate()) { |             if (expansion.shouldUpdate()) { | ||||||
|                 sb.append("&6Click to update to the latest version of this expansion\n\n"); |                 sb.append("&6Click to update to the latest version of this expansion\n\n"); | ||||||
| @@ -172,13 +170,13 @@ public final class EcloudListCommand extends Command { | |||||||
|             sb.append("&bLast updated&7: &f").append(expansion.getTimeSinceLastUpdate()).append(" ago\n"); |             sb.append("&bLast updated&7: &f").append(expansion.getTimeSinceLastUpdate()).append(" ago\n"); | ||||||
|             sb.append("\n").append(expansion.getDescription()); |             sb.append("\n").append(expansion.getDescription()); | ||||||
|  |  | ||||||
|             final String msg = color( |             String msg = color( | ||||||
|                     "&b" + (i + 1) + "&7: " + (expansion.shouldUpdate() ? "&6" |                     "&b" + (i + 1) + "&7: " + (expansion.shouldUpdate() ? "&6" | ||||||
|                             : (expansion.hasExpansion() ? "&a" : "")) + expansion.getName()); |                             : (expansion.hasExpansion() ? "&a" : "")) + expansion.getName()); | ||||||
|  |  | ||||||
|             final String hover = color(sb.toString()); |             String hover = color(sb.toString()); | ||||||
|  |  | ||||||
|             final JSONMessage line = JSONMessage.create(msg); |             JSONMessage line = JSONMessage.create(msg); | ||||||
|             line.tooltip(hover); |             line.tooltip(hover); | ||||||
|  |  | ||||||
|             if (expansion.shouldUpdate() || !expansion.hasExpansion()) { |             if (expansion.shouldUpdate() || !expansion.hasExpansion()) { | ||||||
| @@ -192,9 +190,9 @@ public final class EcloudListCommand extends Command { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NotNull |  | ||||||
|     @Override |     @Override | ||||||
|     public List<String> handleCompletion(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||||
|         if (args.length == MINIMUM_ARGUMENTS) { |         if (args.length == MINIMUM_ARGUMENTS) { | ||||||
|             return StringUtil.copyPartialMatches(args[0], COMPLETIONS, new ArrayList<>(COMPLETIONS.size())); |             return StringUtil.copyPartialMatches(args[0], COMPLETIONS, new ArrayList<>(COMPLETIONS.size())); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -8,27 +8,26 @@ import me.clip.placeholderapi.util.Msg; | |||||||
| import me.rayzr522.jsonmessage.JSONMessage; | import me.rayzr522.jsonmessage.JSONMessage; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| public final class EcloudPlaceholdersCommand extends Command { | public final class EcloudPlaceholdersCommand extends Command { | ||||||
|     public EcloudPlaceholdersCommand() { |     public EcloudPlaceholdersCommand() { | ||||||
|         super("ecloud placeholders", options("&cAn expansion name must be specified!", 1, "placeholderapi.ecloud")); |         super("ecloud placeholders", options("&cAn expansion name must be specified!", 1)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|         final String input = args[0]; |         String input = args[0]; | ||||||
|         final CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); |         CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); | ||||||
|         if (expansion == null) { |         if (expansion == null) { | ||||||
|             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); |             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); | ||||||
|  |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final List<String> placeholders = expansion.getPlaceholders(); |         List<String> placeholders = expansion.getPlaceholders(); | ||||||
|         if (placeholders == null) { |         if (placeholders == null) { | ||||||
|             Msg.msg(sender, "&cThe expansion: &f" + expansion.getName() |             Msg.msg(sender, "&cThe expansion: &f" + expansion.getName() | ||||||
|                             + " &cdoes not have any placeholders listed.", |                             + " &cdoes not have any placeholders listed.", | ||||||
| @@ -45,15 +44,15 @@ public final class EcloudPlaceholdersCommand extends Command { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final Player p = (Player) sender; |         Player p = (Player) sender; | ||||||
|         final JSONMessage message = JSONMessage.create(Msg.color("&bPlaceholders: &f" + placeholders.size())); |         JSONMessage message = JSONMessage.create(Msg.color("&bPlaceholders: &f" + placeholders.size())); | ||||||
|         message.then("\n"); |         message.then("\n"); | ||||||
|  |  | ||||||
|         for (int i = 0; i < placeholders.size(); i++) { |         for (int i = 0; i < placeholders.size(); i++) { | ||||||
|             message.then(i == placeholders.size() - 1 ? placeholders.get(i) : Msg.color(placeholders.get(i) + "&b, &f")); |             message.then(i == placeholders.size() - 1 ? placeholders.get(i) : Msg.color(placeholders.get(i) + "&b, &f")); | ||||||
|             try { |             try { | ||||||
|                 message.tooltip(PlaceholderAPI.setPlaceholders(p, placeholders.get(i))); |                 message.tooltip(PlaceholderAPI.setPlaceholders(p, placeholders.get(i))); | ||||||
|             } catch (final Exception ignored) { |             } catch (Exception ignored) { | ||||||
|                 // Ignored exception |                 // Ignored exception | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -5,17 +5,16 @@ import me.clip.placeholderapi.commands.Command; | |||||||
| import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; | import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class EcloudRefreshCommand extends Command { | public final class EcloudRefreshCommand extends Command { | ||||||
|     public EcloudRefreshCommand() { |     public EcloudRefreshCommand() { | ||||||
|         super("ecloud refresh", permissions("placeholderapi.ecloud")); |         super("ecloud refresh"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|         final ExpansionCloudManager cloud = plugin.getExpansionCloud(); |         ExpansionCloudManager cloud = plugin.getExpansionCloud(); | ||||||
|         Msg.msg(sender, "&aRefresh task started. Use &f/papi ecloud list all &ain a few!!"); |         Msg.msg(sender, "&aRefresh task started. Use &f/papi ecloud list all &ain a few!!"); | ||||||
|         cloud.clean(); |         cloud.clean(); | ||||||
|         cloud.fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); |         cloud.fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); | ||||||
|   | |||||||
| @@ -4,16 +4,15 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | |||||||
| import me.clip.placeholderapi.commands.Command; | import me.clip.placeholderapi.commands.Command; | ||||||
| import me.clip.placeholderapi.util.Msg; | import me.clip.placeholderapi.util.Msg; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class EcloudStatusCommand extends Command { | public final class EcloudStatusCommand extends Command { | ||||||
|     public EcloudStatusCommand() { |     public EcloudStatusCommand() { | ||||||
|         super("ecloud status", permissions("placeholderapi.ecloud")); |         super("ecloud status"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); |         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||||
|         Msg.msg(sender, "&bThere are &f" + plugin.getExpansionCloud().getCloudExpansions().size() |         Msg.msg(sender, "&bThere are &f" + plugin.getExpansionCloud().getCloudExpansions().size() | ||||||
|                         + " &bexpansions available on the cloud.", |                         + " &bexpansions available on the cloud.", | ||||||
|                 "&7A total of &f" + plugin.getExpansionCloud().getCloudAuthorCount() |                 "&7A total of &f" + plugin.getExpansionCloud().getCloudAuthorCount() | ||||||
|   | |||||||
| @@ -7,24 +7,22 @@ import me.clip.placeholderapi.util.Msg; | |||||||
| import me.rayzr522.jsonmessage.JSONMessage; | import me.rayzr522.jsonmessage.JSONMessage; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
| import org.jetbrains.annotations.NotNull; |  | ||||||
|  |  | ||||||
| public final class EcloudVersionInfoCommand extends Command { | public final class EcloudVersionInfoCommand extends Command { | ||||||
|     public EcloudVersionInfoCommand() { |     public EcloudVersionInfoCommand() { | ||||||
|         super("ecloud versioninfo", options("&cIncorrect usage! &7/papi ecloud versioninfo <name> <version>", |         super("ecloud versioninfo", options("&cIncorrect usage! &7/papi ecloud versioninfo <name> <version>", 2)); | ||||||
|                 2, "placeholderapi.ecloud")); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { |     public void execute(CommandSender sender, String[] args) { | ||||||
|         final String input = args[0]; |         String input = args[0]; | ||||||
|         final CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); |         CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); | ||||||
|         if (expansion == null) { |         if (expansion == null) { | ||||||
|             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); |             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final CloudExpansion.Version version = expansion.getVersion(args[1]); |         CloudExpansion.Version version = expansion.getVersion(args[1]); | ||||||
|         if (version == null) { |         if (version == null) { | ||||||
|             Msg.msg(sender, "&cThe version specified does not exist for expansion: &f" + expansion.getName()); |             Msg.msg(sender, "&cThe version specified does not exist for expansion: &f" + expansion.getName()); | ||||||
|             return; |             return; | ||||||
| @@ -39,10 +37,10 @@ public final class EcloudVersionInfoCommand extends Command { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final Player p = (Player) sender; |         Player p = (Player) sender; | ||||||
|         final JSONMessage download = JSONMessage.create(Msg.color("&7Click to download this version")); |         JSONMessage download = JSONMessage.create(Msg.color("&7Click to download this version")); | ||||||
|         download.suggestCommand( |         download.suggestCommand( | ||||||
|                 "/papi ecloud download " + expansion.getName() + " " + version.getVersion()); |                 "/papi ecloud download " + expansion.getName() + ' ' + version.getVersion()); | ||||||
|         download.send(p); |         download.send(p); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,8 +0,0 @@ | |||||||
| package me.clip.placeholderapi.exceptions; |  | ||||||
|  |  | ||||||
| public final class NoDefaultCommandException extends RuntimeException { |  | ||||||
|     public NoDefaultCommandException(final String message) { |  | ||||||
|         super(message); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @@ -28,7 +28,6 @@ package me.clip.placeholderapi.expansion; | |||||||
|  * @author Ryan McCarthy |  * @author Ryan McCarthy | ||||||
|  */ |  */ | ||||||
| public interface Cacheable { | public interface Cacheable { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Called when the implementing class is unregistered from PlaceholderAPI |      * Called when the implementing class is unregistered from PlaceholderAPI | ||||||
|      */ |      */ | ||||||
|   | |||||||
| @@ -30,11 +30,10 @@ import org.bukkit.entity.Player; | |||||||
|  * @author Ryan McCarthy |  * @author Ryan McCarthy | ||||||
|  */ |  */ | ||||||
| public interface Cleanable { | public interface Cleanable { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Called when a player leaves the server |      * Called when a player leaves the server | ||||||
|      * |      * | ||||||
|      * @param p (@link Player} who left the server |      * @param player (@link Player} who left the server | ||||||
|      */ |      */ | ||||||
|     void cleanup(Player p); |     void cleanup(Player player); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ | |||||||
|  */ |  */ | ||||||
| package me.clip.placeholderapi.expansion; | package me.clip.placeholderapi.expansion; | ||||||
|  |  | ||||||
|  | import com.google.common.base.Strings; | ||||||
| import me.clip.placeholderapi.PlaceholderAPI; | import me.clip.placeholderapi.PlaceholderAPI; | ||||||
| import me.clip.placeholderapi.PlaceholderAPIPlugin; | import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||||
| import me.clip.placeholderapi.PlaceholderHook; | import me.clip.placeholderapi.PlaceholderHook; | ||||||
| @@ -41,15 +42,13 @@ public final class ExpansionManager { | |||||||
|     public ExpansionManager(PlaceholderAPIPlugin instance) { |     public ExpansionManager(PlaceholderAPIPlugin instance) { | ||||||
|         plugin = instance; |         plugin = instance; | ||||||
|  |  | ||||||
|         File f = new File(PlaceholderAPIPlugin.getInstance().getDataFolder(), "expansions"); |         File f = new File(plugin.getDataFolder(), "expansions"); | ||||||
|         if (!f.exists()) { |         if (!f.exists()) f.mkdirs(); | ||||||
|             f.mkdirs(); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public PlaceholderExpansion getRegisteredExpansion(String name) { |     public PlaceholderExpansion getRegisteredExpansion(String name) { | ||||||
|         for (Entry<String, PlaceholderHook> hook : PlaceholderAPI.getPlaceholders().entrySet()) { |         for (Entry<String, PlaceholderHook> hook : PlaceholderAPI.getPlaceholders().entrySet()) { | ||||||
|             if (hook.getValue() instanceof PlaceholderExpansion) { |             if (hook.getValue().isExpansion()) { | ||||||
|                 if (name.equalsIgnoreCase(hook.getKey())) { |                 if (name.equalsIgnoreCase(hook.getKey())) { | ||||||
|                     return (PlaceholderExpansion) hook.getValue(); |                     return (PlaceholderExpansion) hook.getValue(); | ||||||
|                 } |                 } | ||||||
| @@ -60,31 +59,28 @@ public final class ExpansionManager { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean registerExpansion(PlaceholderExpansion expansion) { |     public boolean registerExpansion(PlaceholderExpansion expansion) { | ||||||
|         if (expansion == null || expansion.getIdentifier() == null) { |         if (expansion == null || expansion.getIdentifier() == null) return false; | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (expansion instanceof Configurable) { |         if (expansion instanceof Configurable) { | ||||||
|             Map<String, Object> defaults = ((Configurable) expansion).getDefaults(); |             Map<String, Object> defaults = ((Configurable) expansion).getDefaults(); | ||||||
|             String pre = "expansions." + expansion.getIdentifier() + "."; |             String pre = expansion.getPathStarter(); | ||||||
|             FileConfiguration cfg = plugin.getConfig(); |             FileConfiguration cfg = plugin.getConfig(); | ||||||
|             boolean save = false; |             boolean save = false; | ||||||
|  |  | ||||||
|             if (defaults != null) { |             if (defaults != null) { | ||||||
|                 for (Entry<String, Object> entries : defaults.entrySet()) { |                 for (Entry<String, Object> entry : defaults.entrySet()) { | ||||||
|                     if (entries.getKey() == null || entries.getKey().isEmpty()) { |                     String key = entry.getKey(); | ||||||
|                         continue; |                     if (Strings.isNullOrEmpty(key)) continue; | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     if (entries.getValue() == null) { |                     if (entry.getValue() == null) { | ||||||
|                         if (cfg.contains(pre + entries.getKey())) { |                         if (cfg.contains(pre + key)) { | ||||||
|                             save = true; |                             save = true; | ||||||
|                             cfg.set(pre + entries.getKey(), null); |                             cfg.set(pre + key, null); | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         if (!cfg.contains(pre + entries.getKey())) { |                         if (!cfg.contains(pre + key)) { | ||||||
|                             save = true; |                             save = true; | ||||||
|                             cfg.set(pre + entries.getKey(), entries.getValue()); |                             cfg.set(pre + key, entry.getValue()); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @@ -107,17 +103,11 @@ public final class ExpansionManager { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!expansion.canRegister()) { |         if (!expansion.canRegister()) return false; | ||||||
|             return false; |         if (!expansion.register()) return false; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (!expansion.register()) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (expansion instanceof Listener) { |         if (expansion instanceof Listener) { | ||||||
|             Listener l = (Listener) expansion; |             Bukkit.getPluginManager().registerEvents((Listener) expansion, plugin); | ||||||
|             Bukkit.getPluginManager().registerEvents(l, plugin); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         plugin.getLogger().info("Successfully registered expansion: " + expansion.getIdentifier()); |         plugin.getLogger().info("Successfully registered expansion: " + expansion.getIdentifier()); | ||||||
| @@ -143,29 +133,18 @@ public final class ExpansionManager { | |||||||
|  |  | ||||||
|     public PlaceholderExpansion registerExpansion(String fileName) { |     public PlaceholderExpansion registerExpansion(String fileName) { | ||||||
|         List<Class<?>> subs = FileUtil.getClasses("expansions", fileName, PlaceholderExpansion.class); |         List<Class<?>> subs = FileUtil.getClasses("expansions", fileName, PlaceholderExpansion.class); | ||||||
|         if (subs == null || subs.isEmpty()) { |         if (subs == null || subs.isEmpty()) return null; | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // only register the first instance found as an expansion jar should only have 1 class |         // Only register the first instance found as an expansion JAR should only have 1 class | ||||||
|         // extending PlaceholderExpansion |         // extending PlaceholderExpansion | ||||||
|         PlaceholderExpansion ex = createInstance(subs.get(0)); |         PlaceholderExpansion ex = createInstance(subs.get(0)); | ||||||
|         if (registerExpansion(ex)) { |         if (registerExpansion(ex)) return ex; | ||||||
|             return ex; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void registerAllExpansions() { |     public void registerAllExpansions() { | ||||||
|         if (plugin == null) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         List<Class<?>> subs = FileUtil.getClasses("expansions", null, PlaceholderExpansion.class); |         List<Class<?>> subs = FileUtil.getClasses("expansions", null, PlaceholderExpansion.class); | ||||||
|         if (subs == null || subs.isEmpty()) { |         if (subs == null || subs.isEmpty()) return; | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         for (Class<?> klass : subs) { |         for (Class<?> klass : subs) { | ||||||
|             PlaceholderExpansion ex = createInstance(klass); |             PlaceholderExpansion ex = createInstance(klass); | ||||||
| @@ -180,34 +159,29 @@ public final class ExpansionManager { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private PlaceholderExpansion createInstance(Class<?> klass) { |     private PlaceholderExpansion createInstance(Class<?> clazz) { | ||||||
|         if (klass == null) { |         if (clazz == null) return null; | ||||||
|             return null; |         if (!PlaceholderExpansion.class.isAssignableFrom(clazz)) return null; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         PlaceholderExpansion ex = null; |  | ||||||
|         if (!PlaceholderExpansion.class.isAssignableFrom(klass)) { |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |         PlaceholderExpansion expansion = null; | ||||||
|         try { |         try { | ||||||
|             Constructor<?>[] c = klass.getConstructors(); |             Constructor<?>[] constructors = clazz.getConstructors(); | ||||||
|             if (c.length == 0) { |             if (constructors.length == 0) { | ||||||
|                 ex = (PlaceholderExpansion) klass.newInstance(); |                 expansion = (PlaceholderExpansion) clazz.newInstance(); | ||||||
|             } else { |             } else { | ||||||
|                 for (Constructor<?> con : c) { |                 for (Constructor<?> ctor : constructors) { | ||||||
|                     if (con.getParameterTypes().length == 0) { |                     if (ctor.getParameterTypes().length == 0) { | ||||||
|                         ex = (PlaceholderExpansion) klass.newInstance(); |                         expansion = (PlaceholderExpansion) ctor.newInstance(); | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } catch (Throwable t) { |         } catch (Throwable t) { | ||||||
|             plugin.getLogger() |             plugin.getLogger() | ||||||
|                     .severe("Failed to init placeholder expansion from class: " + klass.getName()); |                     .severe("Failed to init placeholder expansion from class: " + clazz.getName()); | ||||||
|             plugin.getLogger().severe(t.getMessage()); |             plugin.getLogger().severe(t.getMessage()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return ex; |         return expansion; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,8 +20,11 @@ | |||||||
|  */ |  */ | ||||||
| package me.clip.placeholderapi.expansion; | package me.clip.placeholderapi.expansion; | ||||||
|  |  | ||||||
| public enum NMSVersion { | import com.google.common.base.Enums; | ||||||
|  |  | ||||||
|  | import java.util.Optional; | ||||||
|  |  | ||||||
|  | public enum NMSVersion { | ||||||
|     UNKNOWN("unknown"), |     UNKNOWN("unknown"), | ||||||
|     SPIGOT_1_7_R1("v1_7_R1"), |     SPIGOT_1_7_R1("v1_7_R1"), | ||||||
|     SPIGOT_1_7_R2("v1_7_R2"), |     SPIGOT_1_7_R2("v1_7_R2"), | ||||||
| @@ -38,8 +41,7 @@ public enum NMSVersion { | |||||||
|     SPIGOT_1_13_R1("v1_13_R1"), |     SPIGOT_1_13_R1("v1_13_R1"), | ||||||
|     SPIGOT_1_13_R2("v1_13_R2"), |     SPIGOT_1_13_R2("v1_13_R2"), | ||||||
|     SPIGOT_1_14_R1("v1_14_R1"), |     SPIGOT_1_14_R1("v1_14_R1"), | ||||||
|   SPIGOT_1_15_R1("v1_15_R1"), |     SPIGOT_1_15_R1("v1_15_R1"); | ||||||
|   SPIGOT_1_16_R1("v1_16_R1"); |  | ||||||
|  |  | ||||||
|     private final String version; |     private final String version; | ||||||
|  |  | ||||||
| @@ -48,17 +50,12 @@ public enum NMSVersion { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static NMSVersion getVersion(String version) { |     public static NMSVersion getVersion(String version) { | ||||||
|         for (NMSVersion v : values()) { |         // Guava caches values() as well. | ||||||
|             if (v.getVersion().equalsIgnoreCase(version)) { |         Optional<NMSVersion> opt = Enums.getIfPresent(NMSVersion.class, version).toJavaUtil(); | ||||||
|                 return v; |         return opt.orElse(NMSVersion.UNKNOWN); | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return NMSVersion.UNKNOWN; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public String getVersion() { |     public String getVersion() { | ||||||
|         return version; |         return version; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,11 +26,11 @@ import me.clip.placeholderapi.PlaceholderHook; | |||||||
| import org.apache.commons.lang.Validate; | import org.apache.commons.lang.Validate; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.configuration.ConfigurationSection; | import org.bukkit.configuration.ConfigurationSection; | ||||||
|  | import org.bukkit.configuration.file.FileConfiguration; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| public abstract class PlaceholderExpansion extends PlaceholderHook { | public abstract class PlaceholderExpansion extends PlaceholderHook { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * The name of this expansion |      * The name of this expansion | ||||||
|      * |      * | ||||||
| @@ -123,60 +123,58 @@ public abstract class PlaceholderExpansion extends PlaceholderHook { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Quick getter for the {@link PlaceholderAPIPlugin} instance |      * Quick getter for the {@link PlaceholderAPIPlugin} config. | ||||||
|      * |      * | ||||||
|      * @return {@link PlaceholderAPIPlugin} instance |      * @return {@link PlaceholderAPIPlugin} config instance. | ||||||
|      */ |      */ | ||||||
|     public PlaceholderAPIPlugin getPlaceholderAPI() { |     public FileConfiguration getConfig() { | ||||||
|         return PlaceholderAPIPlugin.getInstance(); |         return PlaceholderAPIPlugin.getInstance().getConfig(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public String getString(String path, String def) { |     public String getString(String path, String def) { | ||||||
|         return getPlaceholderAPI().getConfig() |         return getConfig().getString(getPathStarter() + path, def); | ||||||
|                 .getString("expansions." + getIdentifier() + "." + path, def); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public int getInt(String path, int def) { |     public int getInt(String path, int def) { | ||||||
|         return getPlaceholderAPI().getConfig() |         return getConfig().getInt(getPathStarter() + path, def); | ||||||
|                 .getInt("expansions." + getIdentifier() + "." + path, def); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public long getLong(String path, long def) { |     public long getLong(String path, long def) { | ||||||
|         return getPlaceholderAPI().getConfig() |         return getConfig().getLong(getPathStarter() + path, def); | ||||||
|                 .getLong("expansions." + getIdentifier() + "." + path, def); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public double getDouble(String path, double def) { |     public double getDouble(String path, double def) { | ||||||
|         return getPlaceholderAPI().getConfig() |         return getConfig().getDouble(getPathStarter() + path, def); | ||||||
|                 .getDouble("expansions." + getIdentifier() + "." + path, def); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public List<String> getStringList(String path) { |     public List<String> getStringList(String path) { | ||||||
|         return getPlaceholderAPI().getConfig() |         return getConfig().getStringList(getPathStarter() + path); | ||||||
|                 .getStringList("expansions." + getIdentifier() + "." + path); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Object get(String path, Object def) { |     public Object get(String path, Object def) { | ||||||
|         return getPlaceholderAPI().getConfig().get("expansions." + getIdentifier() + "." + path, def); |         return getConfig().get(getPathStarter() + path, def); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public ConfigurationSection getConfigSection(String path) { |     public ConfigurationSection getConfigSection(String path) { | ||||||
|         return getPlaceholderAPI().getConfig() |         return getConfig().getConfigurationSection(getPathStarter() + path); | ||||||
|                 .getConfigurationSection("expansions." + getIdentifier() + "." + path); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public ConfigurationSection getConfigSection() { |     public ConfigurationSection getConfigSection() { | ||||||
|         return getPlaceholderAPI().getConfig().getConfigurationSection("expansions." + getIdentifier()); |         return getConfig().getConfigurationSection("expansions." + getIdentifier()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean configurationContains(String path) { |     public boolean configurationContains(String path) { | ||||||
|         return getPlaceholderAPI().getConfig().contains("expansions." + getIdentifier() + "." + path); |         return getConfig().contains(getPathStarter() + path); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     protected String getPathStarter() { | ||||||
|  |         return "expansions." + getIdentifier() + '.'; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @deprecated As of versions greater than 2.8.7, use {@link #getRequiredPlugin()} |      * @deprecated As of versions greater than 2.8.7, use {@link #getRequiredPlugin()} | ||||||
|      */ |      */ | ||||||
|  |     @SuppressWarnings("DeprecatedIsStillUsed") | ||||||
|     @Deprecated |     @Deprecated | ||||||
|     public String getPlugin() { |     public String getPlugin() { | ||||||
|         return null; |         return null; | ||||||
|   | |||||||
| @@ -23,6 +23,5 @@ package me.clip.placeholderapi.expansion; | |||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
|  |  | ||||||
| public interface Relational { | public interface Relational { | ||||||
|  |  | ||||||
|     String onPlaceholderRequest(Player one, Player two, String identifier); |     String onPlaceholderRequest(Player one, Player two, String identifier); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,9 +20,7 @@ | |||||||
|  */ |  */ | ||||||
| package me.clip.placeholderapi.expansion; | package me.clip.placeholderapi.expansion; | ||||||
|  |  | ||||||
|  |  | ||||||
| public interface Taskable { | public interface Taskable { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Called when the implementing class has successfully been registered to the placeholder map |      * Called when the implementing class has successfully been registered to the placeholder map | ||||||
|      * Tasks that need to be performed when this expansion is registered should go here |      * Tasks that need to be performed when this expansion is registered should go here | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ | |||||||
| package me.clip.placeholderapi.expansion; | package me.clip.placeholderapi.expansion; | ||||||
|  |  | ||||||
| public final class Version { | public final class Version { | ||||||
|  |  | ||||||
|     private final boolean isSpigot; |     private final boolean isSpigot; | ||||||
|     private final String version; |     private final String version; | ||||||
|  |  | ||||||
| @@ -41,5 +40,4 @@ public final class Version { | |||||||
|     public boolean compareTo(String version) { |     public boolean compareTo(String version) { | ||||||
|         return getVersion().equalsIgnoreCase(version); |         return getVersion().equalsIgnoreCase(version); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,5 +36,5 @@ public interface VersionSpecific { | |||||||
|      * |      * | ||||||
|      * @return true if your expansion is compatible with the version the server is running. |      * @return true if your expansion is compatible with the version the server is running. | ||||||
|      */ |      */ | ||||||
|     boolean isCompatibleWith(Version v); |     boolean isCompatibleWith(Version version); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,11 +26,8 @@ import java.util.List; | |||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
|  |  | ||||||
| public class CloudExpansion { | public class CloudExpansion { | ||||||
|  |     private String name, author, | ||||||
|     private String name, |  | ||||||
|             author, |  | ||||||
|             latest_version, |             latest_version, | ||||||
|             description, |             description, | ||||||
|             source_url, |             source_url, | ||||||
| @@ -74,14 +71,12 @@ public class CloudExpansion { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Version getVersion() { |     public Version getVersion() { | ||||||
|         return getLatestVersion() == null ? null : getVersion(getLatestVersion()); |         return latest_version == null ? null : getVersion(latest_version); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Version getVersion(String version) { |     public Version getVersion(String version) { | ||||||
|         return versions == null ? null : versions.stream() |         return versions == null ? null : versions.stream() | ||||||
|                 .filter(v -> v.getVersion().equals(version)) |                 .filter(v -> v.getVersion().equals(version)).findFirst().orElse(null); | ||||||
|                 .findFirst() |  | ||||||
|                 .orElse(null); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public List<String> getAvailableVersions() { |     public List<String> getAvailableVersions() { | ||||||
| @@ -140,6 +135,10 @@ public class CloudExpansion { | |||||||
|         return verified; |         return verified; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public void setVerified(boolean verified) { | ||||||
|  |         this.verified = verified; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public long getLastUpdate() { |     public long getLastUpdate() { | ||||||
|         return last_update; |         return last_update; | ||||||
|     } |     } | ||||||
| @@ -156,6 +155,10 @@ public class CloudExpansion { | |||||||
|         return average_rating; |         return average_rating; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public void setAverage_rating(double average_rating) { | ||||||
|  |         this.average_rating = average_rating; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public List<String> getPlaceholders() { |     public List<String> getPlaceholders() { | ||||||
|         return placeholders; |         return placeholders; | ||||||
|     } |     } | ||||||
| @@ -172,7 +175,11 @@ public class CloudExpansion { | |||||||
|         this.versions = versions; |         this.versions = versions; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public class Version { |     public void setRatings_count(long ratings_count) { | ||||||
|  |         this.ratings_count = ratings_count; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static class Version { | ||||||
|         private String url, version, release_notes; |         private String url, version, release_notes; | ||||||
|  |  | ||||||
|         public String getUrl() { |         public String getUrl() { | ||||||
|   | |||||||
| @@ -37,37 +37,29 @@ import java.util.stream.Collectors; | |||||||
| import java.util.stream.IntStream; | import java.util.stream.IntStream; | ||||||
|  |  | ||||||
| public class ExpansionCloudManager { | public class ExpansionCloudManager { | ||||||
|  |  | ||||||
|     private static final String API_URL = "http://api.extendedclip.com/v2/"; |     private static final String API_URL = "http://api.extendedclip.com/v2/"; | ||||||
|     private static final Gson GSON = new Gson(); |     private static final Gson GSON = new Gson(); | ||||||
|  |  | ||||||
|  |  | ||||||
|     private final PlaceholderAPIPlugin plugin; |     private final PlaceholderAPIPlugin plugin; | ||||||
|     private final File expansionsDir; |     private final File expansionsDir; | ||||||
|  |  | ||||||
|     private final List<String> downloading = new ArrayList<>(); |     private final Set<String> downloading = new HashSet<>(); | ||||||
|     private final Map<Integer, CloudExpansion> remote = new TreeMap<>(); |     private final Map<Integer, CloudExpansion> remote = new TreeMap<>(); | ||||||
|  |  | ||||||
|  |  | ||||||
|     public ExpansionCloudManager(PlaceholderAPIPlugin plugin) { |     public ExpansionCloudManager(PlaceholderAPIPlugin plugin) { | ||||||
|         this.plugin = plugin; |         this.plugin = plugin; | ||||||
|  |  | ||||||
|         expansionsDir = new File(plugin.getDataFolder(), "expansions"); |         expansionsDir = new File(plugin.getDataFolder(), "expansions"); | ||||||
|  |  | ||||||
|         final boolean result = expansionsDir.mkdirs(); |         if (expansionsDir.mkdirs()) { | ||||||
|         if (result) { |  | ||||||
|             plugin.getLogger().info("Created Expansions Directory"); |             plugin.getLogger().info("Created Expansions Directory"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     public void clean() { |     public void clean() { | ||||||
|         remote.clear(); |         remote.clear(); | ||||||
|         downloading.clear(); |         downloading.clear(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     public Map<Integer, CloudExpansion> getCloudExpansions() { |     public Map<Integer, CloudExpansion> getCloudExpansions() { | ||||||
|         return remote; |         return remote; | ||||||
|     } |     } | ||||||
| @@ -80,7 +72,6 @@ public class ExpansionCloudManager { | |||||||
|                 .orElse(null); |                 .orElse(null); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     public int getCloudAuthorCount() { |     public int getCloudAuthorCount() { | ||||||
|         return remote.values() |         return remote.values() | ||||||
|                 .stream() |                 .stream() | ||||||
| @@ -126,14 +117,10 @@ public class ExpansionCloudManager { | |||||||
|  |  | ||||||
|  |  | ||||||
|     public int getPagesAvailable(Map<Integer, CloudExpansion> map, int amount) { |     public int getPagesAvailable(Map<Integer, CloudExpansion> map, int amount) { | ||||||
|         if (map == null) { |         if (map == null) return 0; | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         int pages = map.size() > 0 ? 1 : 0; |         int pages = map.size() > 0 ? 1 : 0; | ||||||
|         if (pages == 0) { |         if (pages == 0) return 0; | ||||||
|             return pages; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (map.size() > amount) { |         if (map.size() > amount) { | ||||||
|             pages = map.size() / amount; |             pages = map.size() / amount; | ||||||
| @@ -159,12 +146,11 @@ public class ExpansionCloudManager { | |||||||
|         return ex; |         return ex; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     public void fetch(boolean allowUnverified) { |     public void fetch(boolean allowUnverified) { | ||||||
|         plugin.getLogger().info("Fetching available expansion information..."); |         plugin.getLogger().info("Fetching available expansion information..."); | ||||||
|  |  | ||||||
|         plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { |         plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { | ||||||
|             final Map<String, CloudExpansion> data = new HashMap<>(); |             Map<String, CloudExpansion> data = new HashMap<>(); | ||||||
|  |  | ||||||
|             try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(API_URL).openStream()))) { |             try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(API_URL).openStream()))) { | ||||||
|                 data.putAll(GSON.fromJson(reader, new TypeToken<Map<String, CloudExpansion>>() { |                 data.putAll(GSON.fromJson(reader, new TypeToken<Map<String, CloudExpansion>>() { | ||||||
| @@ -173,11 +159,12 @@ public class ExpansionCloudManager { | |||||||
|                 if (plugin.getPlaceholderAPIConfig().isDebugMode()) { |                 if (plugin.getPlaceholderAPIConfig().isDebugMode()) { | ||||||
|                     ex.printStackTrace(); |                     ex.printStackTrace(); | ||||||
|                 } else { |                 } else { | ||||||
|                     plugin.getLogger().warning("Unable to fetch expansions!\nThere was an error with the server host connecting to the PlaceholderAPI eCloud (https://api.extendedclip.com/v2/)"); |                     plugin.getLogger().warning("Unable to fetch expansions!\nThere was an error with the server host connecting to the PlaceholderAPI eCloud (https://api" + | ||||||
|  |                             ".extendedclip.com/v2/)"); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             final List<CloudExpansion> unsorted = new ArrayList<>(); |             List<CloudExpansion> unsorted = new ArrayList<>(); | ||||||
|  |  | ||||||
|             data.forEach((name, cexp) -> { |             data.forEach((name, cexp) -> { | ||||||
|                 if ((allowUnverified || cexp.isVerified()) && cexp.getLatestVersion() != null && cexp.getVersion(cexp.getLatestVersion()) != null) { |                 if ((allowUnverified || cexp.isVerified()) && cexp.getLatestVersion() != null && cexp.getVersion(cexp.getLatestVersion()) != null) { | ||||||
| @@ -204,7 +191,6 @@ public class ExpansionCloudManager { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             plugin.getLogger().info(count + " placeholder expansions are available on the cloud."); |             plugin.getLogger().info(count + " placeholder expansions are available on the cloud."); | ||||||
|  |  | ||||||
|             long updates = getToUpdateCount(); |             long updates = getToUpdateCount(); | ||||||
|  |  | ||||||
|             if (updates > 0) { |             if (updates > 0) { | ||||||
| @@ -220,19 +206,15 @@ public class ExpansionCloudManager { | |||||||
|  |  | ||||||
|     private void download(URL url, String name) throws IOException { |     private void download(URL url, String name) throws IOException { | ||||||
|         InputStream is = null; |         InputStream is = null; | ||||||
|  |  | ||||||
|         FileOutputStream fos = null; |         FileOutputStream fos = null; | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             URLConnection urlConn = url.openConnection(); |             URLConnection urlConn = url.openConnection(); | ||||||
|  |  | ||||||
|             is = urlConn.getInputStream(); |             is = urlConn.getInputStream(); | ||||||
|  |  | ||||||
|             fos = new FileOutputStream( |             fos = new FileOutputStream( | ||||||
|                     expansionsDir.getAbsolutePath() + File.separator + "Expansion-" + name + ".jar"); |                     expansionsDir.getAbsolutePath() + File.separator + "Expansion-" + name + ".jar"); | ||||||
|  |  | ||||||
|             byte[] buffer = new byte[is.available()]; |             byte[] buffer = new byte[is.available()]; | ||||||
|  |  | ||||||
|             int l; |             int l; | ||||||
|  |  | ||||||
|             while ((l = is.read(buffer)) > 0) { |             while ((l = is.read(buffer)) > 0) { | ||||||
| @@ -252,42 +234,35 @@ public class ExpansionCloudManager { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     public void downloadExpansion(final String player, final CloudExpansion ex) { |     public void downloadExpansion(String player, CloudExpansion ex) { | ||||||
|         downloadExpansion(player, ex, ex.getLatestVersion()); |         downloadExpansion(player, ex, ex.getLatestVersion()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void downloadExpansion(final String player, final CloudExpansion ex, final String version) { |     public void downloadExpansion(String player, CloudExpansion ex, String version) { | ||||||
|         if (downloading.contains(ex.getName())) { |         if (downloading.contains(ex.getName())) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final CloudExpansion.Version ver = ex.getVersions() |         CloudExpansion.Version ver = ex.getVersions() | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(v -> v.getVersion().equals(version)) |                 .filter(v -> v.getVersion().equals(version)) | ||||||
|                 .findFirst() |                 .findFirst() | ||||||
|                 .orElse(null); |                 .orElse(null); | ||||||
|  |  | ||||||
|         if (ver == null) { |         if (ver == null) return; | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         downloading.add(ex.getName()); |         downloading.add(ex.getName()); | ||||||
|  |  | ||||||
|         plugin.getLogger().info("Attempting download of expansion: " + ex.getName() + (player != null ? " by user: " + player : "") + " from url: " + ver.getUrl()); |         plugin.getLogger().info("Attempting download of expansion: " + ex.getName() + (player != null ? " by user: " + player : "") + " from url: " + ver.getUrl()); | ||||||
|  |  | ||||||
|         Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { |         Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { | ||||||
|  |  | ||||||
|             try { |             try { | ||||||
|                 download(new URL(ver.getUrl()), ex.getName()); |                 download(new URL(ver.getUrl()), ex.getName()); | ||||||
|  |  | ||||||
|                 plugin.getLogger().info("Download of expansion: " + ex.getName() + " complete!"); |                 plugin.getLogger().info("Download of expansion: " + ex.getName() + " complete!"); | ||||||
|  |  | ||||||
|             } catch (Exception e) { |             } catch (Exception e) { | ||||||
|                 plugin.getLogger() |                 plugin.getLogger() | ||||||
|                         .warning("Failed to download expansion: " + ex.getName() + " from: " + ver.getUrl()); |                         .warning("Failed to download expansion: " + ex.getName() + " from: " + ver.getUrl()); | ||||||
|  |  | ||||||
|                 Bukkit.getScheduler().runTask(plugin, () -> { |                 Bukkit.getScheduler().runTask(plugin, () -> { | ||||||
|  |  | ||||||
|                     downloading.remove(ex.getName()); |                     downloading.remove(ex.getName()); | ||||||
|  |  | ||||||
|                     if (player != null) { |                     if (player != null) { | ||||||
| @@ -314,7 +289,6 @@ public class ExpansionCloudManager { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,9 +25,7 @@ import me.clip.placeholderapi.PlaceholderHook; | |||||||
| import org.apache.commons.lang.Validate; | import org.apache.commons.lang.Validate; | ||||||
| import org.bukkit.plugin.Plugin; | import org.bukkit.plugin.Plugin; | ||||||
|  |  | ||||||
| /** | @SuppressWarnings("DeprecatedIsStillUsed") | ||||||
|  * Use {@link me.clip.placeholderapi.expansion.PlaceholderExpansion} instead |  | ||||||
|  */ |  | ||||||
| @Deprecated | @Deprecated | ||||||
| public abstract class EZPlaceholderHook extends PlaceholderHook { | public abstract class EZPlaceholderHook extends PlaceholderHook { | ||||||
|  |  | ||||||
| @@ -35,8 +33,8 @@ public abstract class EZPlaceholderHook extends PlaceholderHook { | |||||||
|     private final String plugin; |     private final String plugin; | ||||||
|  |  | ||||||
|     public EZPlaceholderHook(Plugin plugin, String identifier) { |     public EZPlaceholderHook(Plugin plugin, String identifier) { | ||||||
|         Validate.notNull(plugin, "Plugin can not be null!"); |         Validate.notNull(plugin, "Plugin cannot be null"); | ||||||
|         Validate.notNull(identifier, "Placeholder name can not be null!"); |         Validate.notNull(identifier, "Placeholder name cannot be null"); | ||||||
|         this.identifier = identifier; |         this.identifier = identifier; | ||||||
|         this.plugin = plugin.getName(); |         this.plugin = plugin.getName(); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -0,0 +1,39 @@ | |||||||
|  | package me.clip.placeholderapi.listeners; | ||||||
|  |  | ||||||
|  | import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||||
|  | import org.apache.logging.log4j.Level; | ||||||
|  | import org.apache.logging.log4j.LogManager; | ||||||
|  | import org.apache.logging.log4j.core.LogEvent; | ||||||
|  | import org.apache.logging.log4j.core.filter.AbstractFilter; | ||||||
|  | import org.bukkit.Bukkit; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The purpose of this class is to filter the console warning messages when the plugin | ||||||
|  |  * tries to load placeholder expansions from other jars in the plugins folder. | ||||||
|  |  */ | ||||||
|  | public class ApacheListener extends AbstractFilter { | ||||||
|  |     private boolean cancelled = false; | ||||||
|  |  | ||||||
|  |     public ApacheListener(PlaceholderAPIPlugin plugin) { | ||||||
|  |         org.apache.logging.log4j.core.Logger logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger(); | ||||||
|  |         logger.addFilter(this); | ||||||
|  |  | ||||||
|  |         // 3 second should be more than enough. I have no idea how to unregister a filter. | ||||||
|  |         Bukkit.getScheduler().runTaskLater(plugin, () -> cancelled = true, 3 * 20L); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Result filter(LogEvent event) { | ||||||
|  |         if (cancelled) return Result.NEUTRAL; | ||||||
|  |         if (event.getLevel() != Level.WARN) return Result.NEUTRAL; | ||||||
|  |         if (!event.getLoggerName().equals("PlaceholderAPI")) return Result.NEUTRAL; | ||||||
|  |  | ||||||
|  |         // Format: | ||||||
|  |         // Loaded class {CLASS} from {PLUGIN} {VERSION} which is not a depend, softdepend or loadbefore of this plugin. | ||||||
|  |         // E.g. | ||||||
|  |         // Loaded class com.earth2me.essentials.Essentials from PlaceholderAPI v2.10.5-DEV-84 which is not a depend, softdepend or loadbefore of this plugin. | ||||||
|  |         String message = event.getMessage().getFormattedMessage(); | ||||||
|  |         if (message.startsWith("Loaded class") && message.endsWith("which is not a depend, softdepend or loadbefore of this plugin.")) return Result.DENY; | ||||||
|  |         return Result.NEUTRAL; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -37,13 +37,8 @@ import org.bukkit.event.Listener; | |||||||
| import org.bukkit.event.player.PlayerQuitEvent; | import org.bukkit.event.player.PlayerQuitEvent; | ||||||
| import org.bukkit.event.server.PluginDisableEvent; | import org.bukkit.event.server.PluginDisableEvent; | ||||||
|  |  | ||||||
| import java.util.Map; |  | ||||||
| import java.util.Map.Entry; |  | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| public class PlaceholderListener implements Listener { | public class PlaceholderListener implements Listener { | ||||||
|  |  | ||||||
|     private final PlaceholderAPIPlugin plugin; |     private final PlaceholderAPIPlugin plugin; | ||||||
|  |  | ||||||
|     public PlaceholderListener(PlaceholderAPIPlugin instance) { |     public PlaceholderListener(PlaceholderAPIPlugin instance) { | ||||||
| @@ -53,22 +48,23 @@ public class PlaceholderListener implements Listener { | |||||||
|  |  | ||||||
|     @EventHandler |     @EventHandler | ||||||
|     public void onExpansionUnregister(ExpansionUnregisterEvent event) { |     public void onExpansionUnregister(ExpansionUnregisterEvent event) { | ||||||
|         if (event.getExpansion() instanceof Listener) { |         PlaceholderExpansion expansion = event.getExpansion(); | ||||||
|             HandlerList.unregisterAll((Listener) event.getExpansion()); |         if (expansion instanceof Listener) { | ||||||
|  |             HandlerList.unregisterAll((Listener) expansion); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (event.getExpansion() instanceof Taskable) { |         if (expansion instanceof Taskable) { | ||||||
|             ((Taskable) event.getExpansion()).stop(); |             ((Taskable) expansion).stop(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (event.getExpansion() instanceof Cacheable) { |         if (expansion instanceof Cacheable) { | ||||||
|             ((Cacheable) event.getExpansion()).clear(); |             ((Cacheable) expansion).clear(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (plugin.getExpansionCloud() != null) { |         if (plugin.getExpansionCloud() != null) { | ||||||
|  |  | ||||||
|             CloudExpansion ex = plugin.getExpansionCloud() |             CloudExpansion ex = plugin.getExpansionCloud() | ||||||
|                     .getCloudExpansion(event.getExpansion().getName()); |                     .getCloudExpansion(expansion.getName()); | ||||||
|  |  | ||||||
|             if (ex != null) { |             if (ex != null) { | ||||||
|                 ex.setHasExpansion(false); |                 ex.setHasExpansion(false); | ||||||
| @@ -78,28 +74,20 @@ public class PlaceholderListener implements Listener { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @EventHandler(priority = EventPriority.HIGH) |     @EventHandler(priority = EventPriority.HIGH) | ||||||
|     public void onPluginUnload(PluginDisableEvent e) { |     public void onPluginUnload(PluginDisableEvent event) { | ||||||
|         String n = e.getPlugin().getName(); |         // A plugin name cannot be null. | ||||||
|  |         String name = event.getPlugin().getName(); | ||||||
|  |         if (name.equals(plugin.getName())) return; | ||||||
|  |  | ||||||
|         if (n.equals(plugin.getName())) { |         for (PlaceholderHook hook : PlaceholderAPI.getPlaceholders().values()) { | ||||||
|             return; |             if (hook.isExpansion()) { | ||||||
|         } |                 PlaceholderExpansion ex = (PlaceholderExpansion) hook; | ||||||
|  |  | ||||||
|         Map<String, PlaceholderHook> hooks = PlaceholderAPI.getPlaceholders(); |                 if (ex.getRequiredPlugin() == null) continue; | ||||||
|  |  | ||||||
|         for (Entry<String, PlaceholderHook> entry : hooks.entrySet()) { |                 if (ex.getRequiredPlugin().equalsIgnoreCase(name)) { | ||||||
|             PlaceholderHook hook = entry.getValue(); |                     if (PlaceholderAPI.unregisterExpansion(ex)) { | ||||||
|  |                         plugin.getLogger().info("Unregistered placeholder expansion: " + ex.getIdentifier()); | ||||||
|             if (hook instanceof PlaceholderExpansion) { |  | ||||||
|                 PlaceholderExpansion expansion = (PlaceholderExpansion) hook; |  | ||||||
|  |  | ||||||
|                 if (expansion.getRequiredPlugin() == null) { |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 if (expansion.getRequiredPlugin().equalsIgnoreCase(n)) { |  | ||||||
|                     if (PlaceholderAPI.unregisterExpansion(expansion)) { |  | ||||||
|                         plugin.getLogger().info("Unregistered placeholder expansion: " + expansion.getIdentifier()); |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -107,16 +95,10 @@ public class PlaceholderListener implements Listener { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @EventHandler |     @EventHandler | ||||||
|     public void onQuit(PlayerQuitEvent e) { |     public void onQuit(PlayerQuitEvent event) { | ||||||
|         Set<PlaceholderExpansion> expansions = PlaceholderAPI.getExpansions(); |         for (PlaceholderHook hook : PlaceholderAPI.getPlaceholders().values()) { | ||||||
|  |             if (hook instanceof Cleanable) { | ||||||
|         if (expansions.isEmpty()) { |                 ((Cleanable) hook).cleanup(event.getPlayer()); | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         for (PlaceholderExpansion ex : expansions) { |  | ||||||
|             if (ex instanceof Cleanable) { |  | ||||||
|                 ((Cleanable) ex).cleanup(e.getPlayer()); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -31,7 +31,6 @@ import org.bukkit.event.server.ServerLoadEvent; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  |  | ||||||
| public class ServerLoadEventListener implements Listener { | public class ServerLoadEventListener implements Listener { | ||||||
|  |  | ||||||
|     private final PlaceholderAPIPlugin plugin; |     private final PlaceholderAPIPlugin plugin; | ||||||
|  |  | ||||||
|     public ServerLoadEventListener(PlaceholderAPIPlugin instance) { |     public ServerLoadEventListener(PlaceholderAPIPlugin instance) { | ||||||
| @@ -40,19 +39,19 @@ public class ServerLoadEventListener implements Listener { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * This method will be called when the server is first loaded |      * This method will be called when the server is first loaded. | ||||||
|      * <p> |      * <p> | ||||||
|      * The goal of the method is to register all the expansions as soon as possible |      * The goal of the method is to register all the expansions as soon as possible | ||||||
|      * especially before players can join |      * especially before players can join. | ||||||
|      * <p> |      * <p> | ||||||
|      * This will ensure no issues with expanions and hooks. |      * This will ensure no issues with expanions and hooks. | ||||||
|      * |      * | ||||||
|      * @param e the server load event |      * @param event the server load event. | ||||||
|      */ |      */ | ||||||
|     @EventHandler |     @EventHandler | ||||||
|     public void onServerLoad(ServerLoadEvent e) { |     public void onServerLoad(ServerLoadEvent event) { | ||||||
|         plugin.getLogger().info("Placeholder expansion registration initializing..."); |         plugin.getLogger().info("Placeholder expansion registration initializing..."); | ||||||
|         final Map<String, PlaceholderHook> alreadyRegistered = PlaceholderAPI.getPlaceholders(); |         Map<String, PlaceholderHook> alreadyRegistered = PlaceholderAPI.getPlaceholders(); | ||||||
|         plugin.getExpansionManager().registerAllExpansions(); |         plugin.getExpansionManager().registerAllExpansions(); | ||||||
|  |  | ||||||
|         if (alreadyRegistered != null && !alreadyRegistered.isEmpty()) { |         if (alreadyRegistered != null && !alreadyRegistered.isEmpty()) { | ||||||
|   | |||||||
| @@ -1,9 +0,0 @@ | |||||||
| package me.clip.placeholderapi.util; |  | ||||||
|  |  | ||||||
| public class Constants { |  | ||||||
|     public static final String ADMIN_PERMISSION = "placeholderapi.admin"; |  | ||||||
|     public static final String ECLOUD_PERMISSION = "placeholderapi.ecloud"; |  | ||||||
|     public static final String INFO_PERMISSION = "placeholderapi.info"; |  | ||||||
|     public static final String LIST_PERMISSION = "placeholderapi.list"; |  | ||||||
|     public static final String RELOAD_PERMISSION = "placeholderapi.reload"; |  | ||||||
| } |  | ||||||
| @@ -42,65 +42,50 @@ public class FileUtil { | |||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             File f = new File(PlaceholderAPIPlugin.getInstance().getDataFolder(), folder); |             File f = new File(PlaceholderAPIPlugin.getInstance().getDataFolder(), folder); | ||||||
|             if (!f.exists()) { |             if (!f.exists()) return list; | ||||||
|                 return list; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             FilenameFilter fileNameFilter = (dir, name) -> { |             FilenameFilter fileNameFilter = (dir, name) -> { | ||||||
|  |                 boolean isJar = name.endsWith(".jar"); | ||||||
|                 if (fileName != null) { |                 if (fileName != null) { | ||||||
|                     return name.endsWith(".jar") && name.replace(".jar", "") |                     return isJar && name.substring(0, name.length() - 4) | ||||||
|                             .equalsIgnoreCase(fileName.replace(".jar", "")); |                             .equalsIgnoreCase(fileName.substring(0, fileName.length() - 4)); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 return name.endsWith(".jar"); |                 return isJar; | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             File[] jars = f.listFiles(fileNameFilter); |             File[] jars = f.listFiles(fileNameFilter); | ||||||
|             if (jars == null) { |             if (jars == null) return list; | ||||||
|                 return list; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             for (File file : jars) { |             for (File file : jars) { | ||||||
|                 list = gather(file.toURI().toURL(), list, type); |                 list = gather(file.toURI().toURL(), list, type); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return list; |             return list; | ||||||
|         } catch (Throwable t) { |         } catch (Throwable ignored) { | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static List<Class<?>> gather(URL jar, List<Class<?>> list, Class<?> clazz) { |     private static List<Class<?>> gather(URL jar, List<Class<?>> list, Class<?> clazz) { | ||||||
|         if (list == null) { |         // list cannot be null. | ||||||
|             list = new ArrayList<>(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         try (URLClassLoader cl = new URLClassLoader(new URL[]{jar}, clazz.getClassLoader()); |         try (URLClassLoader cl = new URLClassLoader(new URL[]{jar}, clazz.getClassLoader()); | ||||||
|              JarInputStream jis = new JarInputStream(jar.openStream())) { |              JarInputStream jis = new JarInputStream(jar.openStream())) { | ||||||
|  |  | ||||||
|             while (true) { |             JarEntry entry; | ||||||
|                 JarEntry j = jis.getNextJarEntry(); |             while ((entry = jis.getNextJarEntry()) != null) { | ||||||
|                 if (j == null) { |                 String name = entry.getName(); | ||||||
|                     break; |                 if (name == null || name.isEmpty()) continue; | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 String name = j.getName(); |  | ||||||
|                 if (name == null || name.isEmpty()) { |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 if (name.endsWith(".class")) { |                 if (name.endsWith(".class")) { | ||||||
|                     name = name.replace("/", "."); |                     name = name.substring(0, name.length() - 6).replace('/', '.'); | ||||||
|                     String cname = name.substring(0, name.lastIndexOf(".class")); |  | ||||||
|  |  | ||||||
|                     Class<?> c = cl.loadClass(cname); |                     Class<?> loaded = cl.loadClass(name); | ||||||
|                     if (clazz.isAssignableFrom(c)) { |                     if (clazz.isAssignableFrom(loaded)) list.add(loaded); | ||||||
|                         list.add(c); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             } |         } catch (Throwable ignored) { | ||||||
|         } catch (Throwable t) { |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return list; |         return list; | ||||||
|   | |||||||
| @@ -24,17 +24,20 @@ import org.bukkit.Bukkit; | |||||||
| import org.bukkit.ChatColor; | import org.bukkit.ChatColor; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
|  |  | ||||||
| import java.util.Arrays; | public class Msg { | ||||||
| import java.util.Objects; |     public static void msg(CommandSender sender, String... messages) { | ||||||
| import java.util.stream.Collectors; |         for (String message : messages) { | ||||||
|  |             String msg = color(message); | ||||||
| public final class Msg { |             sender.sendMessage(msg); | ||||||
|     public static void msg(CommandSender s, String... msg) { |         } | ||||||
|         s.sendMessage(Arrays.stream(msg).filter(Objects::nonNull).map(Msg::color).collect(Collectors.joining("\n"))); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static void broadcast(String... msg) { |     public static void broadcast(String... messages) { | ||||||
|         Arrays.stream(msg).filter(Objects::nonNull).map(Msg::color).forEach(Bukkit::broadcastMessage); |         CommandSender sender = Bukkit.getConsoleSender(); | ||||||
|  |         for (String message : messages) { | ||||||
|  |             String msg = color(message); | ||||||
|  |             sender.sendMessage(msg); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String color(String text) { |     public static String color(String text) { | ||||||
|   | |||||||
| @@ -1,28 +0,0 @@ | |||||||
| /* |  | ||||||
|  * |  | ||||||
|  * PlaceholderAPI |  | ||||||
|  * Copyright (C) 2019 Ryan McCarthy |  | ||||||
|  * |  | ||||||
|  * This program is free software: you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program. If not, see <http://www.gnu.org/licenses/>. |  | ||||||
|  * |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| package me.clip.placeholderapi.util; |  | ||||||
|  |  | ||||||
| public enum TimeFormat { |  | ||||||
|     DAYS, |  | ||||||
|     HOURS, |  | ||||||
|     MINUTES, |  | ||||||
|     SECONDS |  | ||||||
| } |  | ||||||
| @@ -22,10 +22,10 @@ package me.clip.placeholderapi.util; | |||||||
|  |  | ||||||
| import java.time.Duration; | import java.time.Duration; | ||||||
| import java.time.temporal.ChronoUnit; | import java.time.temporal.ChronoUnit; | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
| public class TimeUtil { | public class TimeUtil { | ||||||
|  |     public static String getRemaining(int seconds, TimeUnit type) { | ||||||
|     public static String getRemaining(int seconds, TimeFormat type) { |  | ||||||
|         if (seconds < 60) { |         if (seconds < 60) { | ||||||
|             switch (type) { |             switch (type) { | ||||||
|                 case DAYS: |                 case DAYS: | ||||||
| @@ -124,8 +124,8 @@ public class TimeUtil { | |||||||
|      * @param duration {@link Duration} (eg, Duration.of(20, {@link ChronoUnit#SECONDS}) for 20 seconds) |      * @param duration {@link Duration} (eg, Duration.of(20, {@link ChronoUnit#SECONDS}) for 20 seconds) | ||||||
|      * @return formatted time |      * @return formatted time | ||||||
|      */ |      */ | ||||||
|     public static String getTime(final Duration duration) { |     public static String getTime(Duration duration) { | ||||||
|         final StringBuilder builder = new StringBuilder(); |         StringBuilder builder = new StringBuilder(); | ||||||
|  |  | ||||||
|         long seconds = duration.getSeconds(); |         long seconds = duration.getSeconds(); | ||||||
|         long minutes = seconds / 60; |         long minutes = seconds / 60; | ||||||
|   | |||||||
| @@ -18,13 +18,13 @@ | |||||||
|  * |  * | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| package me.clip.placeholderapi.updatechecker; | package me.clip.placeholderapi.util; | ||||||
| 
 | 
 | ||||||
| import me.clip.placeholderapi.PlaceholderAPIPlugin; | import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||||
| import me.clip.placeholderapi.util.Msg; | import org.apache.commons.lang.StringUtils; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
|  | import org.bukkit.entity.Player; | ||||||
| import org.bukkit.event.EventHandler; | import org.bukkit.event.EventHandler; | ||||||
| import org.bukkit.event.EventPriority; |  | ||||||
| import org.bukkit.event.Listener; | import org.bukkit.event.Listener; | ||||||
| import org.bukkit.event.player.PlayerJoinEvent; | import org.bukkit.event.player.PlayerJoinEvent; | ||||||
| 
 | 
 | ||||||
| @@ -32,10 +32,11 @@ import javax.net.ssl.HttpsURLConnection; | |||||||
| import java.io.BufferedReader; | import java.io.BufferedReader; | ||||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
| 
 | 
 | ||||||
| public class UpdateChecker implements Listener { | public class UpdateChecker implements Listener { | ||||||
| 
 |     private static final int RESOURCE_ID = 6245; | ||||||
|     private final int RESOURCE_ID = 6245; |     private static final String SPIGOT_API = "https://api.spigotmc.org/legacy/update.php?resource=" + RESOURCE_ID; | ||||||
|     private final PlaceholderAPIPlugin plugin; |     private final PlaceholderAPIPlugin plugin; | ||||||
|     private final String pluginVersion; |     private final String pluginVersion; | ||||||
|     private String spigotVersion; |     private String spigotVersion; | ||||||
| @@ -57,39 +58,35 @@ public class UpdateChecker implements Listener { | |||||||
|     public void fetch() { |     public void fetch() { | ||||||
|         Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { |         Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { | ||||||
|             try { |             try { | ||||||
|                 HttpsURLConnection con = (HttpsURLConnection) new URL( |                 HttpsURLConnection con = (HttpsURLConnection) new URL(SPIGOT_API).openConnection(); | ||||||
|                         "https://api.spigotmc.org/legacy/update.php?resource=" + RESOURCE_ID).openConnection(); | 
 | ||||||
|  |                 // Prevents the server from freezing with bad internet connection. | ||||||
|                 con.setRequestMethod("GET"); |                 con.setRequestMethod("GET"); | ||||||
|                 spigotVersion = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine(); |                 con.setConnectTimeout(2000); | ||||||
|  |                 con.setReadTimeout(2000); | ||||||
|  | 
 | ||||||
|  |                 spigotVersion = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)).readLine(); | ||||||
|             } catch (Exception ex) { |             } catch (Exception ex) { | ||||||
|                 plugin.getLogger().info("Failed to check for updates on spigot."); |                 plugin.getLogger().warning("Failed to check for updates on spigot."); | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (spigotVersion == null || spigotVersion.isEmpty()) { |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             if (spigotVersion == null || spigotVersion.isEmpty()) return; | ||||||
|             updateAvailable = spigotIsNewer(); |             updateAvailable = spigotIsNewer(); | ||||||
| 
 |             if (!updateAvailable) return; | ||||||
|             if (!updateAvailable) { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             Bukkit.getScheduler().runTask(plugin, () -> { |             Bukkit.getScheduler().runTask(plugin, () -> { | ||||||
|                 plugin.getLogger() |                 plugin.getLogger() | ||||||
|                         .info("An update for PlaceholderAPI (v" + getSpigotVersion() + ") is available at:"); |                         .info("An update for PlaceholderAPI (v" + spigotVersion + ") is available at:"); | ||||||
|                 plugin.getLogger() |                 plugin.getLogger() | ||||||
|                         .info("https://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID + "/"); |                         .info("https://www.spigotmc.org/resources/" + RESOURCE_ID + '/'); | ||||||
|                 Bukkit.getPluginManager().registerEvents(this, plugin); |                 Bukkit.getPluginManager().registerEvents(this, plugin); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean spigotIsNewer() { |     private boolean spigotIsNewer() { | ||||||
|         if (spigotVersion == null || spigotVersion.isEmpty()) { |         if (spigotVersion == null || spigotVersion.isEmpty()) return false; | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         String plV = toReadable(pluginVersion); |         String plV = toReadable(pluginVersion); | ||||||
|         String spV = toReadable(spigotVersion); |         String spV = toReadable(spigotVersion); | ||||||
| @@ -97,21 +94,17 @@ public class UpdateChecker implements Listener { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private String toReadable(String version) { |     private String toReadable(String version) { | ||||||
|         if (version.contains("-DEV-")) { |         if (version.contains("-DEV-")) version = StringUtils.split(version, "-DEV-")[0]; | ||||||
|             version = version.split("-DEV-")[0]; |         return StringUtils.remove(version, '.'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|         return version.replaceAll("\\.", ""); |     @EventHandler | ||||||
|     } |     public void onJoin(PlayerJoinEvent event) { | ||||||
| 
 |         Player player = event.getPlayer(); | ||||||
|     @EventHandler(priority = EventPriority.MONITOR) |         if (player.hasPermission("placeholderapi.updatenotify")) { | ||||||
|     public void onJoin(PlayerJoinEvent e) { |             Msg.msg(player, | ||||||
|         if (e.getPlayer().hasPermission("placeholderapi.updatenotify")) { |                     "&bAn update for &fPlaceholder&7API &e(&fPlaceholder&7API &fv" + getSpigotVersion() + "&e)", | ||||||
|             Msg.msg(e.getPlayer(), |                     "&bis available at &ehttps://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID + '/'); | ||||||
|                     "&bAn update for &fPlaceholder&7API &e(&fPlaceholder&7API &fv" + getSpigotVersion() |  | ||||||
|                             + "&e)" |  | ||||||
|                     , "&bis available at &ehttps://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID |  | ||||||
|                             + "/"); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -4,6 +4,12 @@ version: ${project.version} | |||||||
| api-version: '1.13' | api-version: '1.13' | ||||||
| authors: [extended_clip, Glare] | authors: [extended_clip, Glare] | ||||||
| description: ${project.description} | description: ${project.description} | ||||||
|  |  | ||||||
|  | commands: | ||||||
|  |   placeholderapi: | ||||||
|  |     description: PlaceholderAPI command | ||||||
|  |     aliases: [papi] | ||||||
|  |  | ||||||
| permissions: | permissions: | ||||||
|   placeholderapi.*: |   placeholderapi.*: | ||||||
|     description: ability to use all commands |     description: ability to use all commands | ||||||
| @@ -33,10 +39,16 @@ permissions: | |||||||
|   placeholderapi.ecloud: |   placeholderapi.ecloud: | ||||||
|     description: allows the usage of ecloud commands |     description: allows the usage of ecloud commands | ||||||
|     default: op |     default: op | ||||||
|  |     children: | ||||||
|  |       placeholderapi.ecloud.enable: true | ||||||
|  |       placeholderapi.ecloud.disable: true | ||||||
|  |       placeholderapi.ecloud.list: true | ||||||
|  |       placeholderapi.ecloud.info: true | ||||||
|  |       placeholderapi.ecloud.clear: true | ||||||
|  |       placeholderapi.ecloud.status: true | ||||||
|  |       placeholderapi.ecloud.refresh: true | ||||||
|  |       placeholderapi.ecloud.download: true | ||||||
|  |       placeholderapi.ecloud.versioninfo: true | ||||||
|   placeholderapi.updatenotify: |   placeholderapi.updatenotify: | ||||||
|     description: notifies you when there is a PAPI update |     description: notifies you when there is a PAPI update | ||||||
|     default: op |     default: op | ||||||
| commands: |  | ||||||
|    placeholderapi: |  | ||||||
|      description: PlaceholderAPI command |  | ||||||
|      aliases: [papi] |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user