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:
		
							
								
								
									
										36
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -5,8 +5,8 @@ | ||||
|  | ||||
|     <groupId>me.clip</groupId> | ||||
|     <artifactId>placeholderapi</artifactId> | ||||
|  | ||||
|     <version>2.10.7-DEV-${BUILD_NUMBER}</version> | ||||
|  | ||||
|     <name>PlaceholderAPI</name> | ||||
|     <description>An awesome placeholder provider!</description> | ||||
|     <url>http://extendedclip.com</url> | ||||
| @@ -33,7 +33,7 @@ | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>org.spigotmc</groupId> | ||||
|             <artifactId>spigot-api</artifactId> | ||||
|             <artifactId>spigot</artifactId> | ||||
|             <version>1.16.1-R0.1-SNAPSHOT</version> | ||||
|             <scope>provided</scope> | ||||
|         </dependency> | ||||
| @@ -45,7 +45,7 @@ | ||||
|         <dependency> | ||||
|             <groupId>org.bstats</groupId> | ||||
|             <artifactId>bstats-bukkit</artifactId> | ||||
|             <version>1.5</version> | ||||
|             <version>1.7</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>me.rayzr522</groupId> | ||||
| @@ -84,27 +84,27 @@ | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-shade-plugin</artifactId> | ||||
|                 <version>3.1.0</version> | ||||
|                 <version>3.2.4</version> | ||||
|                 <configuration> | ||||
|                     <minimizeJar>false</minimizeJar> | ||||
|                     <createDependencyReducedPom>false</createDependencyReducedPom> | ||||
|                     <relocations> | ||||
|                         <relocation> | ||||
|                             <pattern>org.bstats</pattern> | ||||
|                             <shadedPattern>me.clip.placeholderapi.util</shadedPattern> | ||||
|                         </relocation> | ||||
|                         <relocation> | ||||
|                             <pattern>com.google.code.gson</pattern> | ||||
|                             <shadedPattern>me.clip.placeholderapi.libs.gson</shadedPattern> | ||||
|                         </relocation> | ||||
|                     </relocations> | ||||
|                 </configuration> | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <phase>package</phase> | ||||
|                         <goals> | ||||
|                             <goal>shade</goal> | ||||
|                         </goals> | ||||
|                         <configuration> | ||||
|                             <minimizeJar>false</minimizeJar> | ||||
|                             <createDependencyReducedPom>false</createDependencyReducedPom> | ||||
|                             <relocations> | ||||
|                                 <relocation> | ||||
|                                     <pattern>org.bstats</pattern> | ||||
|                                     <shadedPattern>me.clip.placeholderapi.metrics</shadedPattern> | ||||
|                                 </relocation> | ||||
|                                 <relocation> | ||||
|                                     <pattern>com.google.code.gson</pattern> | ||||
|                                     <shadedPattern>me.clip.placeholderapi.libs.gson</shadedPattern> | ||||
|                                 </relocation> | ||||
|                             </relocations> | ||||
|                         </configuration> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|             </plugin> | ||||
|   | ||||
| @@ -20,14 +20,13 @@ | ||||
|  */ | ||||
| package me.clip.placeholderapi; | ||||
|  | ||||
| import com.google.common.base.Strings; | ||||
| import com.google.common.collect.ImmutableMap; | ||||
| import com.google.common.collect.ImmutableSet; | ||||
| import me.clip.placeholderapi.events.ExpansionRegisterEvent; | ||||
| import me.clip.placeholderapi.events.ExpansionUnregisterEvent; | ||||
| import me.clip.placeholderapi.expansion.Cacheable; | ||||
| import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||
| import me.clip.placeholderapi.expansion.Relational; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.apache.commons.lang.Validate; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.OfflinePlayer; | ||||
| @@ -35,18 +34,17 @@ import org.bukkit.entity.Player; | ||||
| import org.bukkit.plugin.Plugin; | ||||
|  | ||||
| import java.util.*; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| import static me.clip.placeholderapi.util.Msg.color; | ||||
|  | ||||
| public class PlaceholderAPI { | ||||
|  | ||||
|     private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]"); | ||||
|     protected static final Map<String, PlaceholderHook> PLACEHOLDERS = new ConcurrentHashMap<>(); | ||||
|     private static final Pattern PERCENT_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 Map<String, PlaceholderHook> placeholders = new HashMap<>(); | ||||
|  | ||||
|     private PlaceholderAPI() { | ||||
|     } | ||||
| @@ -58,9 +56,7 @@ public class PlaceholderAPI { | ||||
|      * @return true if identifier is already registered | ||||
|      */ | ||||
|     public static boolean isRegistered(String identifier) { | ||||
|         return getRegisteredIdentifiers().stream() | ||||
|                 .filter(id -> id.equalsIgnoreCase(identifier)) | ||||
|                 .findFirst().orElse(null) != null; | ||||
|         return PLACEHOLDERS.containsKey(identifier.toLowerCase(Locale.ENGLISH)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -73,15 +69,11 @@ public class PlaceholderAPI { | ||||
|      * registered for the specified identifier | ||||
|      */ | ||||
|     public static boolean registerPlaceholderHook(String identifier, PlaceholderHook placeholderHook) { | ||||
|         Validate.notNull(identifier, "Identifier can not be null"); | ||||
|         Validate.notNull(placeholderHook, "Placeholderhook can not be null"); | ||||
|  | ||||
|         if (isRegistered(identifier)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         placeholders.put(identifier.toLowerCase(), placeholderHook); | ||||
|         Validate.notEmpty(identifier, "Placeholder identifier cannot be null or empty"); | ||||
|         Objects.requireNonNull(placeholderHook, "Placeholder hook cannot be null"); | ||||
|  | ||||
|         if (isRegistered(identifier)) return false; | ||||
|         PLACEHOLDERS.put(identifier.toLowerCase(Locale.ENGLISH), placeholderHook); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -93,8 +85,8 @@ public class PlaceholderAPI { | ||||
|      * placeholder hook registered for the identifier specified | ||||
|      */ | ||||
|     public static boolean unregisterPlaceholderHook(String identifier) { | ||||
|         Validate.notNull(identifier, "Identifier can not be null"); | ||||
|         return placeholders.remove(identifier.toLowerCase()) != null; | ||||
|         Validate.notEmpty(identifier, "Identifier cannot be null"); | ||||
|         return PLACEHOLDERS.remove(identifier.toLowerCase(Locale.ENGLISH)) != null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -103,7 +95,7 @@ public class PlaceholderAPI { | ||||
|      * @return All registered placeholder identifiers | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     public static Map<String, PlaceholderHook> getPlaceholders() { | ||||
|         return ImmutableMap.copyOf(placeholders); | ||||
|         return ImmutableMap.copyOf(PLACEHOLDERS); | ||||
|     } | ||||
|  | ||||
|     public static Set<PlaceholderExpansion> getExpansions() { | ||||
|         Set<PlaceholderExpansion> set = getPlaceholders().values().stream() | ||||
|                 .filter(PlaceholderExpansion.class::isInstance).map(PlaceholderExpansion.class::cast) | ||||
|                 .collect(Collectors.toCollection(HashSet::new)); | ||||
|         Set<PlaceholderExpansion> expansions = new HashSet<>(); | ||||
|         for (PlaceholderHook expansion : PLACEHOLDERS.values()) { | ||||
|             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 | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     public static List<String> setPlaceholders(OfflinePlayer player, List<String> text, Pattern pattern, boolean colorize) { | ||||
|         if (text == null) { | ||||
|             return null; | ||||
|         } | ||||
|         if (text == null) return null; | ||||
|         List<String> lines = new ArrayList<>(); | ||||
|  | ||||
|         return text.stream() | ||||
|                 .map(line -> setPlaceholders(player, line, pattern, colorize)) | ||||
|                 .collect(Collectors.toList()); | ||||
|         for (String line : text) { | ||||
|             lines.add(setPlaceholders(player, line, pattern, colorize)); | ||||
|         } | ||||
|         return lines; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -262,7 +255,7 @@ public class PlaceholderAPI { | ||||
|      * @return String containing all translated placeholders | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     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 | ||||
|      */ | ||||
|     public static String setPlaceholders(OfflinePlayer player, String text, Pattern pattern, boolean colorize) { | ||||
|         if (text == null) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         if (placeholders.isEmpty()) { | ||||
|             return colorize ? color(text) : text; | ||||
|         } | ||||
|  | ||||
|         final Matcher matcher = pattern.matcher(text); | ||||
|         final Map<String, PlaceholderHook> hooks = getPlaceholders(); | ||||
|         if (text == null) return null; | ||||
|         if (PLACEHOLDERS.isEmpty()) return colorize ? color(text) : text; | ||||
|  | ||||
|         Matcher matcher = pattern.matcher(text); | ||||
|         while (matcher.find()) { | ||||
|             final String format = matcher.group(1); | ||||
|             final int index = format.indexOf("_"); | ||||
|             String format = matcher.group(1); | ||||
|             int index = format.indexOf('_'); | ||||
|             if (index <= 0 || index >= format.length()) continue; | ||||
|  | ||||
|             if (index <= 0 || index >= format.length()) { | ||||
|                 continue; | ||||
|             } | ||||
|             // We don't need to use getPlaceholders() because we know what we're doing and we won't modify the map. | ||||
|             // 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(); | ||||
|             final String params = format.substring(index + 1); | ||||
|             final PlaceholderHook hook = hooks.get(identifier); | ||||
|             if (handler != null) { | ||||
|                 String params = format.substring(index + 1); | ||||
|                 String value = handler.onRequest(player, params); | ||||
|  | ||||
|             if (hook == null) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             final String value = hook.onRequest(player, params); | ||||
|  | ||||
|             if (value != null) { | ||||
|                 text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value)); | ||||
|                 if (value != null) { | ||||
|                     text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         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. | ||||
|      * <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 | ||||
|      */ | ||||
|     public static List<String> setRelationalPlaceholders(Player one, Player two, List<String> text, boolean colorize) { | ||||
|         if (text == null) { | ||||
|             return null; | ||||
|         if (text == null) return null; | ||||
|         List<String> lines = new ArrayList<>(); | ||||
|         for (String line : text) { | ||||
|             lines.add(setRelationalPlaceholders(one, two, line, colorize)); | ||||
|         } | ||||
|  | ||||
|         return text.stream() | ||||
|                 .map(line -> setRelationalPlaceholders(one, two, line, colorize)) | ||||
|                 .collect(Collectors.toList()); | ||||
|         return lines; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -397,43 +397,31 @@ public class PlaceholderAPI { | ||||
|      * @param colorize If color codes (&[0-1a-fk-o]) should be translated | ||||
|      * @return The text containing the parsed relational placeholders | ||||
|      */ | ||||
|     @SuppressWarnings("DuplicatedCode") | ||||
|     public static String setRelationalPlaceholders(Player one, Player two, String text, boolean colorize) { | ||||
|         if (text == null) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         if (placeholders.isEmpty()) { | ||||
|             return colorize ? Msg.color(text) : text; | ||||
|         } | ||||
|  | ||||
|         final Matcher matcher = RELATIONAL_PLACEHOLDER_PATTERN.matcher(text); | ||||
|         final Map<String, PlaceholderHook> hooks = getPlaceholders(); | ||||
|         if (text == null) return null; | ||||
|         if (PLACEHOLDERS.isEmpty()) return colorize ? color(text) : text; | ||||
|  | ||||
|         Matcher matcher = RELATIONAL_PLACEHOLDER_PATTERN.matcher(text); | ||||
|         while (matcher.find()) { | ||||
|             final String format = matcher.group(2); | ||||
|             final int index = format.indexOf("_"); | ||||
|             String format = matcher.group(2); | ||||
|             int index = format.indexOf('_'); | ||||
|             if (index <= 0 || index >= format.length()) continue; | ||||
|  | ||||
|             if (index <= 0 || index >= format.length()) { | ||||
|                 continue; | ||||
|             } | ||||
|             String identifier = format.substring(0, index).toLowerCase(Locale.ENGLISH); | ||||
|             PlaceholderHook handler = PLACEHOLDERS.get(identifier); | ||||
|  | ||||
|             String identifier = format.substring(0, index).toLowerCase(); | ||||
|             String params = format.substring(index + 1); | ||||
|             final PlaceholderHook hook = hooks.get(identifier); | ||||
|             if (handler.isRelational()) { | ||||
|                 Relational relational = (Relational) handler; | ||||
|                 String params = format.substring(index + 1); | ||||
|                 String value = relational.onPlaceholderRequest(one, two, params); | ||||
|  | ||||
|             if (!(hook instanceof Relational)) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             final String value = ((Relational) hook).onPlaceholderRequest(one, two, params); | ||||
|  | ||||
|             if (value != null) { | ||||
|                 text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value)); | ||||
|                 if (value != null) { | ||||
|                     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() { | ||||
|         unregisterAllProvidedExpansions(); | ||||
|         placeholders.clear(); | ||||
|         PLACEHOLDERS.clear(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Unregister all expansions provided by PlaceholderAPI | ||||
|      */ | ||||
|     public static void unregisterAllProvidedExpansions() { | ||||
|         final Set<PlaceholderHook> set = new HashSet<>(placeholders.values()); | ||||
|         if (PLACEHOLDERS.isEmpty()) return; | ||||
|  | ||||
|         for (PlaceholderHook hook : set) { | ||||
|             if (hook instanceof PlaceholderExpansion) { | ||||
|                 final PlaceholderExpansion expansion = (PlaceholderExpansion) hook; | ||||
|  | ||||
|                 if (!expansion.persist()) { | ||||
|                     unregisterExpansion(expansion); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (hook instanceof Cacheable) { | ||||
|                 ((Cacheable) hook).clear(); | ||||
|         for (PlaceholderHook handler : PLACEHOLDERS.values()) { | ||||
|             if (handler.isExpansion()) { | ||||
|                 PlaceholderExpansion expansion = (PlaceholderExpansion) handler; | ||||
|                 if (!expansion.persist()) unregisterExpansion(expansion); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static boolean registerExpansion(PlaceholderExpansion ex) { | ||||
|         ExpansionRegisterEvent ev = new ExpansionRegisterEvent(ex); | ||||
|         Bukkit.getPluginManager().callEvent(ev); | ||||
|         if (ev.isCancelled()) { | ||||
|             return false; | ||||
|         } | ||||
|     public static boolean registerExpansion(PlaceholderExpansion expansion) { | ||||
|         ExpansionRegisterEvent event = new ExpansionRegisterEvent(expansion); | ||||
|         Bukkit.getPluginManager().callEvent(event); | ||||
|         if (event.isCancelled()) return false; | ||||
|  | ||||
|         return registerPlaceholderHook(ex.getIdentifier(), ex); | ||||
|         return registerPlaceholderHook(expansion.getIdentifier(), expansion); | ||||
|     } | ||||
|  | ||||
|     public static boolean unregisterExpansion(PlaceholderExpansion ex) { | ||||
|         if (unregisterPlaceholderHook(ex.getIdentifier())) { | ||||
|             Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(ex)); | ||||
|     public static boolean unregisterExpansion(PlaceholderExpansion expansion) { | ||||
|         if (unregisterPlaceholderHook(expansion.getIdentifier())) { | ||||
|             Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(expansion)); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
| @@ -490,7 +469,7 @@ public class PlaceholderAPI { | ||||
|      * @return The pattern for {@literal %<identifier>_<params>%} | ||||
|      */ | ||||
|     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) { | ||||
|         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) { | ||||
|         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) { | ||||
|         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) { | ||||
|         return setPlaceholders(player, text, PLACEHOLDER_PATTERN, colorize); | ||||
|         return setPlaceholders(player, text, PERCENT_PLACEHOLDER_PATTERN, colorize); | ||||
|     } | ||||
|  | ||||
|     public static String setBracketPlaceholders(Player player, String text) { | ||||
|   | ||||
| @@ -21,66 +21,63 @@ | ||||
| package me.clip.placeholderapi; | ||||
|  | ||||
| import me.clip.placeholderapi.commands.CommandHandler; | ||||
| import me.clip.placeholderapi.commands.CompletionHandler; | ||||
| import me.clip.placeholderapi.configuration.PlaceholderAPIConfig; | ||||
| import me.clip.placeholderapi.expansion.ExpansionManager; | ||||
| import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||
| import me.clip.placeholderapi.expansion.Version; | ||||
| import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; | ||||
| import me.clip.placeholderapi.external.EZPlaceholderHook; | ||||
| import me.clip.placeholderapi.listeners.ApacheListener; | ||||
| import me.clip.placeholderapi.listeners.PlaceholderListener; | ||||
| import me.clip.placeholderapi.listeners.ServerLoadEventListener; | ||||
| import me.clip.placeholderapi.updatechecker.UpdateChecker; | ||||
| import me.clip.placeholderapi.util.TimeUtil; | ||||
| import me.clip.placeholderapi.util.UpdateChecker; | ||||
| import org.bstats.bukkit.Metrics; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.ChatColor; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.command.PluginCommand; | ||||
| import org.bukkit.plugin.java.JavaPlugin; | ||||
|  | ||||
| import java.text.SimpleDateFormat; | ||||
| import java.time.format.DateTimeFormatter; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Yes I have a shit load of work to do... | ||||
|  * | ||||
|  * @author Ryan McCarthy | ||||
|  */ | ||||
| public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|  | ||||
|     private static final Version serverVersion; | ||||
|     private static PlaceholderAPIPlugin instance; | ||||
|     private static SimpleDateFormat dateFormat; | ||||
|     private static DateTimeFormatter dateFormat; | ||||
|     private static String booleanTrue; | ||||
|     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 ExpansionManager expansionManager; | ||||
|     private ExpansionCloudManager expansionCloud; | ||||
|     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 | ||||
|      * 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 | ||||
|      */ | ||||
|     public static SimpleDateFormat getDateFormat() { | ||||
|         return dateFormat != null ? dateFormat : new SimpleDateFormat( | ||||
|                 "MM/dd/yy HH:mm:ss"); | ||||
|     public static DateTimeFormatter getDateFormat() { | ||||
|         return dateFormat != null ? dateFormat : DateTimeFormatter.ofPattern("MM/dd/yy HH:mm:ss"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -122,26 +118,26 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|     } | ||||
|  | ||||
|     public static Version getServerVersion() { | ||||
|         return serverVersion != null ? serverVersion : getVersion(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onLoad() { | ||||
|         startTime = System.currentTimeMillis(); | ||||
|         instance = this; | ||||
|         serverVersion = getVersion(); | ||||
|         config = new PlaceholderAPIConfig(this); | ||||
|         expansionManager = new ExpansionManager(this); | ||||
|         return serverVersion; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onEnable() { | ||||
|         startTime = System.currentTimeMillis(); | ||||
|         instance = this; | ||||
|  | ||||
|         config = new PlaceholderAPIConfig(this); | ||||
|         config.loadDefConfig(); | ||||
|         setupOptions(); | ||||
|  | ||||
|         Objects.requireNonNull(getCommand("placeholderapi")).setExecutor(new CommandHandler()); | ||||
|         expansionManager = new ExpansionManager(this); | ||||
|         new PlaceholderListener(this); | ||||
|  | ||||
|         PluginCommand command = getCommand("placeholderapi"); | ||||
|         command.setExecutor(new CommandHandler()); | ||||
|         command.setTabCompleter(new CompletionHandler()); | ||||
|  | ||||
|         new ApacheListener(this); | ||||
|         try { | ||||
|             Class.forName("org.bukkit.event.server.ServerLoadEvent"); | ||||
|             new ServerLoadEventListener(this); | ||||
| @@ -150,7 +146,7 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|                 getLogger().info("Placeholder expansion registration initializing..."); | ||||
|  | ||||
|                 //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(); | ||||
|  | ||||
|                 if (alreadyRegistered != null && !alreadyRegistered.isEmpty()) { | ||||
| @@ -159,13 +155,8 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|             }, 1); | ||||
|         } | ||||
|  | ||||
|         if (config.checkUpdates()) { | ||||
|             new UpdateChecker(this).fetch(); | ||||
|         } | ||||
|  | ||||
|         if (config.isCloudEnabled()) { | ||||
|             enableCloud(); | ||||
|         } | ||||
|         if (config.checkUpdates()) new UpdateChecker(this).fetch(); | ||||
|         if (config.isCloudEnabled()) enableCloud(); | ||||
|  | ||||
|         setupMetrics(); | ||||
|         getServer().getScheduler().runTaskLater(this, this::checkHook, 40); | ||||
| @@ -175,14 +166,13 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|     public void onDisable() { | ||||
|         disableCloud(); | ||||
|         PlaceholderAPI.unregisterAll(); | ||||
|         expansionManager = null; | ||||
|         Bukkit.getScheduler().cancelTasks(this); | ||||
|         serverVersion = null; | ||||
|  | ||||
|         expansionManager = null; | ||||
|         instance = null; | ||||
|     } | ||||
|  | ||||
|     public void reloadConf(CommandSender s) { | ||||
|         boolean cloudEnabled = this.expansionCloud != null; | ||||
|         PlaceholderAPI.unregisterAllProvidedExpansions(); | ||||
|         reloadConfig(); | ||||
|         setupOptions(); | ||||
| @@ -190,79 +180,70 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|  | ||||
|         if (!config.isCloudEnabled()) { | ||||
|             disableCloud(); | ||||
|         } else if (!cloudEnabled) { | ||||
|         } else if (this.expansionCloud != null) { | ||||
|             enableCloud(); | ||||
|         } | ||||
|  | ||||
|         s.sendMessage(ChatColor.translateAlternateColorCodes('&', | ||||
|                 PlaceholderAPI.getRegisteredIdentifiers().size() | ||||
|                         + " &aplaceholder hooks successfully registered!")); | ||||
|         s.sendMessage(ChatColor.translateAlternateColorCodes('&', PlaceholderAPI.PLACEHOLDERS.size() + " &aplaceholder hooks successfully registered!")); | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings("deprecation") | ||||
|     private void checkHook() { | ||||
|         Map<String, PlaceholderHook> loaded = PlaceholderAPI.getPlaceholders(); | ||||
|  | ||||
|         loaded.values().forEach(h -> { | ||||
|             if (h instanceof EZPlaceholderHook) { | ||||
|         for (PlaceholderHook hook : PlaceholderAPI.PLACEHOLDERS.values()) { | ||||
|             if (hook instanceof EZPlaceholderHook) { | ||||
|                 String pluginName = ((EZPlaceholderHook) hook).getPluginName(); | ||||
|                 String author; | ||||
|  | ||||
|                 try { | ||||
|                     author = Bukkit.getPluginManager().getPlugin(((EZPlaceholderHook) h).getPluginName()).getDescription().getAuthors().toString(); | ||||
|                     author = Bukkit.getPluginManager().getPlugin(pluginName).getDescription().getAuthors().toString(); | ||||
|                 } catch (Exception ex) { | ||||
|                     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. " + | ||||
|                         "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 | ||||
|                 PlaceholderAPI.unregisterPlaceholderHook(((EZPlaceholderHook) h).getPlaceholderName()); | ||||
|                 PlaceholderAPI.unregisterPlaceholderHook(((EZPlaceholderHook) hook).getPlaceholderName()); | ||||
|             } | ||||
|         }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void setupOptions() { | ||||
|         booleanTrue = config.booleanTrue(); | ||||
|  | ||||
|         if (booleanTrue == null) { | ||||
|             booleanTrue = "true"; | ||||
|         } | ||||
|         if (booleanTrue == null) booleanTrue = "true"; | ||||
|  | ||||
|         booleanFalse = config.booleanFalse(); | ||||
|  | ||||
|         if (booleanFalse == null) { | ||||
|             booleanFalse = "false"; | ||||
|         } | ||||
|         if (booleanFalse == null) booleanFalse = "false"; | ||||
|  | ||||
|         try { | ||||
|             dateFormat = new SimpleDateFormat(config.dateFormat()); | ||||
|         } catch (Exception e) { | ||||
|             dateFormat = new SimpleDateFormat("MM/dd/yy HH:mm:ss"); | ||||
|             dateFormat = DateTimeFormatter.ofPattern(config.dateFormat()); | ||||
|         } catch (Exception ignored) { | ||||
|             dateFormat = DateTimeFormatter.ofPattern("MM/dd/yy HH:mm:ss"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void setupMetrics() { | ||||
|         Metrics m = new Metrics(this); | ||||
|         m.addCustomChart(new Metrics.SimplePie("using_expansion_cloud", () -> getExpansionCloud() != null ? "yes" : "no")); | ||||
|         // This is NOT the plugin resource ID. it's the bStats ID. | ||||
|         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, PlaceholderHook> hooks = PlaceholderAPI.getPlaceholders(); | ||||
|  | ||||
|             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); | ||||
|                     } | ||||
|             for (PlaceholderHook hook : PlaceholderAPI.PLACEHOLDERS.values()) { | ||||
|                 if (hook.isExpansion()) { | ||||
|                     PlaceholderExpansion ex = (PlaceholderExpansion) hook; | ||||
|                     map.put(ex.getRequiredPlugin() == null ? ex.getIdentifier() | ||||
|                             : ex.getRequiredPlugin(), 1); | ||||
|                 } | ||||
|             } | ||||
|             return map; | ||||
|  | ||||
|             return map; | ||||
|         })); | ||||
|     } | ||||
|  | ||||
| @@ -276,10 +257,7 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|     } | ||||
|  | ||||
|     public void disableCloud() { | ||||
|         if (expansionCloud != null) { | ||||
|             expansionCloud.clean(); | ||||
|             expansionCloud = null; | ||||
|         } | ||||
|         if (expansionCloud != null) expansionCloud = null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -305,6 +283,6 @@ public class PlaceholderAPIPlugin extends JavaPlugin { | ||||
|     } | ||||
|  | ||||
|     public long getUptimeMillis() { | ||||
|         return (System.currentTimeMillis() - startTime); | ||||
|         return System.currentTimeMillis() - startTime; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,13 +20,14 @@ | ||||
|  */ | ||||
| package me.clip.placeholderapi; | ||||
|  | ||||
| import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||
| import me.clip.placeholderapi.expansion.Relational; | ||||
| import org.bukkit.OfflinePlayer; | ||||
| import org.bukkit.entity.Player; | ||||
|  | ||||
| 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 | ||||
|      *               player | ||||
| @@ -41,8 +42,12 @@ public abstract class PlaceholderHook { | ||||
|         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 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) { | ||||
|         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; | ||||
|  | ||||
| import com.google.common.collect.ImmutableSet; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
|  | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| 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 usage; | ||||
|     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); | ||||
|     } | ||||
|  | ||||
|     protected Command(@NotNull final String match, @NotNull final Options options) { | ||||
|     protected Command(String match, Options options) { | ||||
|         this.match = match; | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|     protected static Options usage(@NotNull final String usage, final int minimumArguments) { | ||||
|         return new Options(usage, minimumArguments, null); | ||||
|     protected static Options options(String usage, int minimumArguments) { | ||||
|         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() { | ||||
|         return match; | ||||
|     } | ||||
|  | ||||
|     @NotNull | ||||
|     public String getUsage() { | ||||
|         return usage; | ||||
|     } | ||||
| @@ -55,28 +45,23 @@ public abstract class Command { | ||||
|         return minimumArguments; | ||||
|     } | ||||
|  | ||||
|     @NotNull | ||||
|     public Set<String> getPermissions() { | ||||
|         return permissions; | ||||
|     public String getPermission() { | ||||
|         return permission; | ||||
|     } | ||||
|  | ||||
|     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(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|     public List<String> handleCompletion(CommandSender sender, String[] args) { | ||||
|         return Collections.emptyList(); | ||||
|     } | ||||
|  | ||||
|     private static class Options { | ||||
|         private final String usage; | ||||
|         private final int minimumArguments; | ||||
|         private final String[] permissions; | ||||
|  | ||||
|         private Options(@Nullable final String usage, final int minimumArguments, | ||||
|                         @Nullable final String[] permissions) { | ||||
|         private Options(String usage, int minimumArguments) { | ||||
|             this.usage = usage; | ||||
|             this.minimumArguments = minimumArguments; | ||||
|             this.permissions = permissions; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,25 +1,33 @@ | ||||
| package me.clip.placeholderapi.commands; | ||||
|  | ||||
| import com.google.common.collect.Lists; | ||||
| import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||
| 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.util.Msg; | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.bukkit.command.CommandExecutor; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.Optional; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| public final class CommandHandler implements CommandExecutor { | ||||
|     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 EcloudDownloadCommand(), | ||||
|             new EcloudInfoCommand(), | ||||
| @@ -28,74 +36,57 @@ public final class CommandHandler implements CommandExecutor { | ||||
|             new EcloudRefreshCommand(), | ||||
|             new EcloudStatusCommand(), | ||||
|             new EcloudVersionInfoCommand(), | ||||
|             new EcloudCommand(), | ||||
|             new BcParseCommand(), | ||||
|             new ParseCommand(), | ||||
|             new ParseRelCommand(), | ||||
|             new DisableEcloudCommand(), | ||||
|             new EnableCloudCommand(), | ||||
|             new HelpCommand(), | ||||
|             new InfoCommand(), | ||||
|             new ListCommand(), | ||||
|             new RegisterCommand(), | ||||
|             new ReloadCommand(), | ||||
|             DEFAULT, | ||||
|             new UnregisterCommand() | ||||
|             new EcloudDisableCommand(), | ||||
|             new EcloudEnableCommand() | ||||
|     ); | ||||
|  | ||||
|     static { | ||||
|         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; | ||||
|             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 | ||||
|     public boolean onCommand(@NotNull final CommandSender sender, @NotNull final org.bukkit.command.Command bukkitCommand, | ||||
|                              @NotNull final String name, @NotNull String[] args) { | ||||
|     public boolean onCommand(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command bukkitCommand, @NotNull String name, String[] args) { | ||||
|         if (args.length == 0) { | ||||
|             DEFAULT.execute(sender, args); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         final String joined = String.join(" ", args).toLowerCase(); | ||||
|         final Optional<Command> optional = COMMANDS.stream() | ||||
|         String joined = String.join(" ", args).toLowerCase(); | ||||
|         Optional<Command> optional = COMMANDS.stream() | ||||
|                 .filter(command -> joined.startsWith(command.getMatch())) | ||||
|                 .findFirst(); | ||||
|  | ||||
|         if (!optional.isPresent()) { | ||||
|             sender.sendMessage("Specified command is not valid."); | ||||
|             Msg.msg(sender, "&cUnknown command."); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         final Command command = optional.get(); | ||||
|  | ||||
|         if (!command.getPermissions().isEmpty() && command.getPermissions().stream().noneMatch(sender::hasPermission)) { | ||||
|             sender.sendMessage("You do not have the permission to execute specified command."); | ||||
|         Command command = optional.get(); | ||||
|         String permission = command.getPermission(); | ||||
|         if (!sender.hasPermission(permission)) { | ||||
|             Msg.msg(sender, "&cYou do not have the permission to use this command."); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         args = splitArguments(joined, command.getMatch()); | ||||
|  | ||||
|         if (args.length < command.getMinimumArguments()) { | ||||
|             Msg.msg(sender, command.getUsage()); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         command.execute(sender, args); | ||||
|  | ||||
|         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; | ||||
|  | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.command.TabCompleter; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| import java.util.Locale; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| public final class CompletionHandler implements TabCompleter { | ||||
|     private final List<Command> commands; | ||||
|  | ||||
|     CompletionHandler(@NotNull final List<Command> commands) { | ||||
|         this.commands = commands; | ||||
|     private static String[] splitArguments(String[] args, String command) { | ||||
|         int skip = StringUtils.split(command).length; | ||||
|         return Arrays.stream(args).skip(skip).toArray(String[]::new); | ||||
|     } | ||||
|  | ||||
|     // 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 | ||||
|     public List<String> onTabComplete(@NotNull final CommandSender sender, @NotNull final org.bukkit.command.Command bukkitCommand, | ||||
|                                       @NotNull final String name, @NotNull final String[] args) { | ||||
|         final String joined = String.join(" ", args).toLowerCase(); | ||||
|         final Optional<Command> optional = commands.stream() | ||||
|                 .filter(command -> joined.startsWith(command.getMatch())) | ||||
|                 .findAny(); | ||||
|     public List<String> onTabComplete(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command bukkitCommand, @NotNull String name, String[] args) { | ||||
|         String joined = String.join(" ", args).toLowerCase(Locale.ENGLISH); | ||||
|  | ||||
|         return optional | ||||
|                 .map(command -> command.handleCompletion(sender, CommandHandler.splitArguments(joined, command.getMatch()))) | ||||
|                 .orElse(Collections.emptyList()); | ||||
|         if (args.length > 1) { | ||||
|             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()); | ||||
|         } | ||||
|         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.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class BcParseCommand extends Command { | ||||
|     public BcParseCommand() { | ||||
|         super("bcparse", options("&cYou must specify a player.", 1, "placeholderapi.parse")); | ||||
|         super("bcparse", options("&cYou must specify a player.", 1)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final OfflinePlayer player; | ||||
|         final String input = args[0]; | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         OfflinePlayer player; | ||||
|         String input = args[0]; | ||||
|  | ||||
|         if (input.equalsIgnoreCase("me")) { | ||||
|             if (sender instanceof Player) { | ||||
|                 player = (Player) sender; | ||||
|             } else { | ||||
|                 Msg.msg(sender, "&cThis command must target a player when used by console"); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|         } else { | ||||
|             if (Bukkit.getPlayer(input) != null) { | ||||
|                 player = Bukkit.getPlayer(input); | ||||
|             } else { | ||||
|                 player = Bukkit.getOfflinePlayer(input); | ||||
|             player = Bukkit.getPlayer(input); | ||||
|             if (player == null) player = Bukkit.getOfflinePlayer(input); | ||||
|             if (player == null || !player.hasPlayedBefore()) { | ||||
|                 Msg.msg(sender, "&cCould not find player&8: &f" + input); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (player == null || !player.hasPlayedBefore()) { | ||||
|             Msg.msg(sender, "&cFailed to find player: &f" + input); | ||||
|             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)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,6 @@ import me.clip.placeholderapi.commands.Command; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.util.StringUtil; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| @@ -22,16 +21,18 @@ public final class EcloudCommand extends Command { | ||||
|             "placeholders", | ||||
|             "refresh", | ||||
|             "status", | ||||
|             "versioninfo" | ||||
|             "versioninfo", | ||||
|             "enable", | ||||
|             "disable" | ||||
|     ); | ||||
|  | ||||
|     public EcloudCommand() { | ||||
|         super("ecloud", permissions("placeholderapi.ecloud")); | ||||
|         super("ecloud"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|  | ||||
|         if (args.length == 0) { | ||||
|             Msg.msg(sender, "&bExpansion cloud commands", | ||||
| @@ -57,7 +58,6 @@ public final class EcloudCommand extends Command { | ||||
|  | ||||
|         if (plugin.getExpansionCloud() == null) { | ||||
|             Msg.msg(sender, "&7The expansion cloud is not enabled!"); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -69,9 +69,9 @@ public final class EcloudCommand extends Command { | ||||
|         sender.sendMessage("Specified command is not valid."); | ||||
|     } | ||||
|  | ||||
|     @NotNull | ||||
|  | ||||
|     @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) { | ||||
|             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.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class HelpCommand extends Command { | ||||
|     public HelpCommand() { | ||||
|         super("help", permissions("placeholderapi.ecloud")); | ||||
|         super("help"); | ||||
|     } | ||||
|  | ||||
|     @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)", | ||||
|                 "&b/papi", | ||||
|                 "&fView plugin info/version info", | ||||
|   | ||||
| @@ -7,7 +7,6 @@ import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.util.StringUtil; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| @@ -17,13 +16,13 @@ public final class InfoCommand extends Command { | ||||
|     private static final int MINIMUM_ARGUMENTS = 1; | ||||
|  | ||||
|     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 | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final String requestedExpansion = args[0]; | ||||
|         final PlaceholderExpansion ex = PlaceholderAPIPlugin.getInstance().getExpansionManager().getRegisteredExpansion(requestedExpansion); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         String requestedExpansion = args[0]; | ||||
|         PlaceholderExpansion ex = PlaceholderAPIPlugin.getInstance().getExpansionManager().getRegisteredExpansion(requestedExpansion); | ||||
|         if (ex == null) { | ||||
|             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 | ||||
|     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) { | ||||
|             final Set<String> completions = PlaceholderAPI.getRegisteredIdentifiers(); | ||||
|             Set<String> completions = PlaceholderAPI.getRegisteredIdentifiers(); | ||||
|  | ||||
|             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.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.Set; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| public final class ListCommand extends Command { | ||||
|     public ListCommand() { | ||||
|         super("list", permissions("placeholderapi.list")); | ||||
|         super("list"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final Set<String> registered = PlaceholderAPI.getRegisteredIdentifiers(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         Set<String> registered = PlaceholderAPI.getRegisteredIdentifiers(); | ||||
|         if (registered.isEmpty()) { | ||||
|             Msg.msg(sender, "&7There are no placeholder hooks currently registered!"); | ||||
|             return; | ||||
|   | ||||
| @@ -7,41 +7,53 @@ import org.apache.commons.lang.StringUtils; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.OfflinePlayer; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.HumanEntity; | ||||
| 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 ParseCommand() { | ||||
|         super("parse", options("&cYou must specify a player.", 1, "placeholderapi.parse")); | ||||
|         super("parse", options("&cYou must specify a player.", 1)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final OfflinePlayer player; | ||||
|         final String input = args[0]; | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         OfflinePlayer player; | ||||
|         String input = args[0]; | ||||
|  | ||||
|         if (input.equalsIgnoreCase("me")) { | ||||
|             if (sender instanceof Player) { | ||||
|                 player = (Player) sender; | ||||
|             } else { | ||||
|                 Msg.msg(sender, "&cThis command must target a player when used by console"); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|         } else { | ||||
|             if (Bukkit.getPlayer(input) != null) { | ||||
|                 player = Bukkit.getPlayer(input); | ||||
|             } else { | ||||
|                 player = Bukkit.getOfflinePlayer(input); | ||||
|             player = Bukkit.getPlayer(input); | ||||
|             if (player == null) player = Bukkit.getOfflinePlayer(input); | ||||
|             if (player == null || !player.hasPlayedBefore()) { | ||||
|                 Msg.msg(sender, "&cCould not find player&8: &f" + input); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (player == null || !player.hasPlayedBefore()) { | ||||
|             Msg.msg(sender, "&cFailed to find player: &f" + input); | ||||
|             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)); | ||||
|     } | ||||
|  | ||||
|     @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.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class ParseRelCommand extends Command { | ||||
|     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 | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final Player one = Bukkit.getPlayer(args[0]); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         Player one = Bukkit.getPlayer(args[0]); | ||||
|         if (one == null) { | ||||
|             Msg.msg(sender, args[0] + " &cis not online!"); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final Player two = Bukkit.getPlayer(args[1]); | ||||
|         Player two = Bukkit.getPlayer(args[1]); | ||||
|         if (two == null) { | ||||
|             Msg.msg(sender, args[1] + " &cis not online!"); | ||||
|  | ||||
|             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)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,22 +4,21 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||
| import me.clip.placeholderapi.commands.Command; | ||||
| import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class RegisterCommand extends Command { | ||||
|     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 | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final String fileName = args[0].replace(".jar", ""); | ||||
|         final PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager().registerExpansion(fileName); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         String fileName = StringUtils.remove(args[0], ".jar"); | ||||
|         PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager().registerExpansion(fileName); | ||||
|  | ||||
|         if (expansion == null) { | ||||
|             Msg.msg(sender, "&cFailed to register expansion from " + fileName); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -4,15 +4,14 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||
| import me.clip.placeholderapi.commands.Command; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class ReloadCommand extends Command { | ||||
|     public ReloadCommand() { | ||||
|         super("reload", permissions("placeholderapi.reload")); | ||||
|         super("reload"); | ||||
|     } | ||||
|  | ||||
|     @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!"); | ||||
|         PlaceholderAPIPlugin.getInstance().reloadConf(sender); | ||||
|     } | ||||
|   | ||||
| @@ -7,7 +7,6 @@ import me.clip.placeholderapi.expansion.PlaceholderExpansion; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.util.StringUtil; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| @@ -17,18 +16,17 @@ public final class UnregisterCommand extends Command { | ||||
|     private static final int MINIMUM_ARGUMENTS = 1; | ||||
|  | ||||
|     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 | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final String requestedExpansion = args[0]; | ||||
|         final PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager() | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         String requestedExpansion = args[0]; | ||||
|         PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionManager() | ||||
|                 .getRegisteredExpansion(requestedExpansion); | ||||
|  | ||||
|         if (expansion == null) { | ||||
|             Msg.msg(sender, "&cFailed to find expansion: &f" + requestedExpansion); | ||||
|  | ||||
|             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())); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,6 @@ import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.plugin.PluginDescriptionFile; | ||||
| import org.bukkit.util.StringUtil; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| @@ -34,8 +33,8 @@ public final class VersionCommand extends Command { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PluginDescriptionFile description = PlaceholderAPIPlugin.getInstance().getDescription(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PluginDescriptionFile description = PlaceholderAPIPlugin.getInstance().getDescription(); | ||||
|  | ||||
|         Msg.msg(sender, "PlaceholderAPI &7version &b&o" + description.getVersion(), | ||||
|                 "&fCreated by&7: &b" + description.getAuthors(), | ||||
| @@ -43,9 +42,9 @@ public final class VersionCommand extends Command { | ||||
|                 "&fEcloud commands: &b/papi ecloud"); | ||||
|     } | ||||
|  | ||||
|     @NotNull | ||||
|  | ||||
|     @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) { | ||||
|             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.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class EcloudClearCommand extends Command { | ||||
|     public EcloudClearCommand() { | ||||
|         super("ecloud clear", permissions("placeholderapi.ecloud")); | ||||
|         super("ecloud clear"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin.getInstance().getExpansionCloud().clean(); | ||||
|         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.commands.Command; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| 
 | ||||
| public final class DisableEcloudCommand extends Command { | ||||
|     public DisableEcloudCommand() { | ||||
|         super("disablecloud", permissions("placeholderapi.ecloud")); | ||||
| public final class EcloudDisableCommand extends Command { | ||||
|     public EcloudDisableCommand() { | ||||
|         super("ecloud disable"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         if (plugin.getExpansionCloud() == null) { | ||||
|             Msg.msg(sender, "&7The cloud is already disabled!"); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         plugin.disableCloud(); | ||||
|         plugin.getPlaceholderAPIConfig().setCloudEnabled(false); | ||||
|         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 org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class EcloudDownloadCommand extends Command { | ||||
|     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 | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         final String input = args[0]; | ||||
|         final CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         String input = args[0]; | ||||
|         CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); | ||||
|  | ||||
|         if (expansion == null) { | ||||
|             Msg.msg(sender, "&cNo expansion found with the name: &f" + input); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final PlaceholderExpansion loaded = plugin.getExpansionManager().getRegisteredExpansion(input); | ||||
|         PlaceholderExpansion loaded = plugin.getExpansionManager().getRegisteredExpansion(input); | ||||
|         if (loaded != null && loaded.isRegistered()) { | ||||
|             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); | ||||
|         final String player = ((sender instanceof Player) ? sender.getName() : null); | ||||
|         final ExpansionCloudManager cloud = plugin.getExpansionCloud(); | ||||
|         String player = ((sender instanceof Player) ? sender.getName() : null); | ||||
|         ExpansionCloudManager cloud = plugin.getExpansionCloud(); | ||||
|         cloud.downloadExpansion(player, expansion, version); | ||||
|         cloud.clean(); | ||||
|         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.commands.Command; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| 
 | ||||
| public final class EnableCloudCommand extends Command { | ||||
|     public EnableCloudCommand() { | ||||
|         super("enablecloud", permissions("placeholderapi.ecloud")); | ||||
| public final class EcloudEnableCommand extends Command { | ||||
|     public EcloudEnableCommand() { | ||||
|         super("ecloud enable"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         if (plugin.getExpansionCloud() != null) { | ||||
|             Msg.msg(sender, "&7The cloud is already enabled!"); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
| @@ -7,19 +7,18 @@ import me.clip.placeholderapi.util.Msg; | ||||
| import me.rayzr522.jsonmessage.JSONMessage; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import static me.clip.placeholderapi.util.Msg.color; | ||||
|  | ||||
| public final class EcloudInfoCommand extends Command { | ||||
|     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 | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final String input = args[0]; | ||||
|         final CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         String input = args[0]; | ||||
|         CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); | ||||
|  | ||||
|         if (expansion == null) { | ||||
|             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); | ||||
| @@ -35,7 +34,7 @@ public final class EcloudInfoCommand extends Command { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final Player p = (Player) sender; | ||||
|         Player p = (Player) sender; | ||||
|  | ||||
|         Msg.msg(sender, "&bExpansion&7: &f" + expansion.getName(), | ||||
|                 "&bAuthor: &f" + expansion.getAuthor(), | ||||
| @@ -43,7 +42,7 @@ public final class EcloudInfoCommand extends Command { | ||||
|         ); | ||||
|  | ||||
|         // latest version | ||||
|         final JSONMessage latestVersion = JSONMessage | ||||
|         JSONMessage latestVersion = JSONMessage | ||||
|                 .create(color("&bLatest version: &f" + expansion.getLatestVersion())); | ||||
|         latestVersion.tooltip(color("&bReleased: &f" + expansion.getTimeSinceLastUpdate() | ||||
|                 + "\n&bUpdate information: &f" + expansion.getVersion().getReleaseNotes() | ||||
| @@ -51,7 +50,7 @@ public final class EcloudInfoCommand extends Command { | ||||
|         latestVersion.send(p); | ||||
|  | ||||
|         // versions | ||||
|         final JSONMessage versions = JSONMessage | ||||
|         JSONMessage versions = JSONMessage | ||||
|                 .create(color("&bVersions available: &f" + expansion.getVersions().size())); | ||||
|         versions.tooltip(color(String.join("&b, &f", expansion.getAvailableVersions()))); | ||||
|         versions.suggestCommand( | ||||
| @@ -60,7 +59,7 @@ public final class EcloudInfoCommand extends Command { | ||||
|  | ||||
|         // placeholders | ||||
|         if (expansion.getPlaceholders() != null) { | ||||
|             final JSONMessage placeholders = JSONMessage | ||||
|             JSONMessage placeholders = JSONMessage | ||||
|                     .create(color("&bPlaceholders: &f" + expansion.getPlaceholders().size())); | ||||
|             placeholders.tooltip(color(String.join("&b, &f", expansion.getPlaceholders()))); | ||||
|             placeholders.suggestCommand("/papi ecloud placeholders " + expansion.getName()); | ||||
|   | ||||
| @@ -9,7 +9,6 @@ import me.rayzr522.jsonmessage.JSONMessage; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.bukkit.util.StringUtil; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.*; | ||||
| import java.util.stream.Collectors; | ||||
| @@ -25,13 +24,12 @@ public final class EcloudListCommand extends Command { | ||||
|     ); | ||||
|  | ||||
|     public EcloudListCommand() { | ||||
|         super("ecloud list", options("&cIncorrect usage! &7/papi ecloud list <all/author/installed> (page)", | ||||
|                 MINIMUM_ARGUMENTS, "placeholderapi.ecloud")); | ||||
|         super("ecloud list", options("&cIncorrect usage! &7/papi ecloud list <all/author/installed> (page)", MINIMUM_ARGUMENTS)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         int page = 1; | ||||
|  | ||||
|         String author; | ||||
| @@ -103,7 +101,7 @@ public final class EcloudListCommand extends Command { | ||||
|         Msg.msg(sender, "&6Gold = Expansions which need updated"); | ||||
|  | ||||
|         if (!(sender instanceof Player)) { | ||||
|             final Map<String, CloudExpansion> expansions = new HashMap<>(); | ||||
|             Map<String, CloudExpansion> expansions = new HashMap<>(); | ||||
|  | ||||
|             for (CloudExpansion exp : ex.values()) { | ||||
|                 if (exp == null || exp.getName() == null) { | ||||
| @@ -113,7 +111,7 @@ public final class EcloudListCommand extends Command { | ||||
|                 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]; | ||||
|  | ||||
| @@ -122,7 +120,7 @@ public final class EcloudListCommand extends Command { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 final CloudExpansion expansion = expansions.get(name); | ||||
|                 CloudExpansion expansion = expansions.get(name); | ||||
|  | ||||
|                 Msg.msg(sender, | ||||
|                         "&b" + i + "&7: " + (expansion.shouldUpdate() ? "&6" | ||||
| @@ -134,11 +132,11 @@ public final class EcloudListCommand extends Command { | ||||
|             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) { | ||||
|                 continue; | ||||
|             } | ||||
| @@ -146,7 +144,7 @@ public final class EcloudListCommand extends Command { | ||||
|             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; | ||||
|  | ||||
| @@ -155,8 +153,8 @@ public final class EcloudListCommand extends Command { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             final CloudExpansion expansion = expansions.get(name); | ||||
|             final StringBuilder sb = new StringBuilder(); | ||||
|             CloudExpansion expansion = expansions.get(name); | ||||
|             StringBuilder sb = new StringBuilder(); | ||||
|  | ||||
|             if (expansion.shouldUpdate()) { | ||||
|                 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("\n").append(expansion.getDescription()); | ||||
|  | ||||
|             final String msg = color( | ||||
|             String msg = color( | ||||
|                     "&b" + (i + 1) + "&7: " + (expansion.shouldUpdate() ? "&6" | ||||
|                             : (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); | ||||
|  | ||||
|             if (expansion.shouldUpdate() || !expansion.hasExpansion()) { | ||||
| @@ -192,9 +190,9 @@ public final class EcloudListCommand extends Command { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @NotNull | ||||
|  | ||||
|     @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) { | ||||
|             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 org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public final class EcloudPlaceholdersCommand extends Command { | ||||
|     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 | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         final String input = args[0]; | ||||
|         final CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         String input = args[0]; | ||||
|         CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(input); | ||||
|         if (expansion == null) { | ||||
|             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final List<String> placeholders = expansion.getPlaceholders(); | ||||
|         List<String> placeholders = expansion.getPlaceholders(); | ||||
|         if (placeholders == null) { | ||||
|             Msg.msg(sender, "&cThe expansion: &f" + expansion.getName() | ||||
|                             + " &cdoes not have any placeholders listed.", | ||||
| @@ -45,15 +44,15 @@ public final class EcloudPlaceholdersCommand extends Command { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final Player p = (Player) sender; | ||||
|         final JSONMessage message = JSONMessage.create(Msg.color("&bPlaceholders: &f" + placeholders.size())); | ||||
|         Player p = (Player) sender; | ||||
|         JSONMessage message = JSONMessage.create(Msg.color("&bPlaceholders: &f" + placeholders.size())); | ||||
|         message.then("\n"); | ||||
|  | ||||
|         for (int i = 0; i < placeholders.size(); i++) { | ||||
|             message.then(i == placeholders.size() - 1 ? placeholders.get(i) : Msg.color(placeholders.get(i) + "&b, &f")); | ||||
|             try { | ||||
|                 message.tooltip(PlaceholderAPI.setPlaceholders(p, placeholders.get(i))); | ||||
|             } catch (final Exception ignored) { | ||||
|             } catch (Exception ignored) { | ||||
|                 // Ignored exception | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -5,17 +5,16 @@ import me.clip.placeholderapi.commands.Command; | ||||
| import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class EcloudRefreshCommand extends Command { | ||||
|     public EcloudRefreshCommand() { | ||||
|         super("ecloud refresh", permissions("placeholderapi.ecloud")); | ||||
|         super("ecloud refresh"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         final ExpansionCloudManager cloud = plugin.getExpansionCloud(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         ExpansionCloudManager cloud = plugin.getExpansionCloud(); | ||||
|         Msg.msg(sender, "&aRefresh task started. Use &f/papi ecloud list all &ain a few!!"); | ||||
|         cloud.clean(); | ||||
|         cloud.fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); | ||||
|   | ||||
| @@ -4,16 +4,15 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||
| import me.clip.placeholderapi.commands.Command; | ||||
| import me.clip.placeholderapi.util.Msg; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class EcloudStatusCommand extends Command { | ||||
|     public EcloudStatusCommand() { | ||||
|         super("ecloud status", permissions("placeholderapi.ecloud")); | ||||
|         super("ecloud status"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         PlaceholderAPIPlugin plugin = PlaceholderAPIPlugin.getInstance(); | ||||
|         Msg.msg(sender, "&bThere are &f" + plugin.getExpansionCloud().getCloudExpansions().size() | ||||
|                         + " &bexpansions available on the cloud.", | ||||
|                 "&7A total of &f" + plugin.getExpansionCloud().getCloudAuthorCount() | ||||
|   | ||||
| @@ -7,24 +7,22 @@ import me.clip.placeholderapi.util.Msg; | ||||
| import me.rayzr522.jsonmessage.JSONMessage; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public final class EcloudVersionInfoCommand extends Command { | ||||
|     public EcloudVersionInfoCommand() { | ||||
|         super("ecloud versioninfo", options("&cIncorrect usage! &7/papi ecloud versioninfo <name> <version>", | ||||
|                 2, "placeholderapi.ecloud")); | ||||
|         super("ecloud versioninfo", options("&cIncorrect usage! &7/papi ecloud versioninfo <name> <version>", 2)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(@NotNull final CommandSender sender, @NotNull final String[] args) { | ||||
|         final String input = args[0]; | ||||
|         final CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); | ||||
|     public void execute(CommandSender sender, String[] args) { | ||||
|         String input = args[0]; | ||||
|         CloudExpansion expansion = PlaceholderAPIPlugin.getInstance().getExpansionCloud().getCloudExpansion(input); | ||||
|         if (expansion == null) { | ||||
|             Msg.msg(sender, "&cNo expansion found by the name: &f" + input); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final CloudExpansion.Version version = expansion.getVersion(args[1]); | ||||
|         CloudExpansion.Version version = expansion.getVersion(args[1]); | ||||
|         if (version == null) { | ||||
|             Msg.msg(sender, "&cThe version specified does not exist for expansion: &f" + expansion.getName()); | ||||
|             return; | ||||
| @@ -39,10 +37,10 @@ public final class EcloudVersionInfoCommand extends Command { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final Player p = (Player) sender; | ||||
|         final JSONMessage download = JSONMessage.create(Msg.color("&7Click to download this version")); | ||||
|         Player p = (Player) sender; | ||||
|         JSONMessage download = JSONMessage.create(Msg.color("&7Click to download this version")); | ||||
|         download.suggestCommand( | ||||
|                 "/papi ecloud download " + expansion.getName() + " " + version.getVersion()); | ||||
|                 "/papi ecloud download " + expansion.getName() + ' ' + version.getVersion()); | ||||
|         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 | ||||
|  */ | ||||
| public interface Cacheable { | ||||
|  | ||||
|     /** | ||||
|      * Called when the implementing class is unregistered from PlaceholderAPI | ||||
|      */ | ||||
|   | ||||
| @@ -30,11 +30,10 @@ import org.bukkit.entity.Player; | ||||
|  * @author Ryan McCarthy | ||||
|  */ | ||||
| public interface Cleanable { | ||||
|  | ||||
|     /** | ||||
|      * 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; | ||||
|  | ||||
| import com.google.common.base.Strings; | ||||
| import me.clip.placeholderapi.PlaceholderAPI; | ||||
| import me.clip.placeholderapi.PlaceholderAPIPlugin; | ||||
| import me.clip.placeholderapi.PlaceholderHook; | ||||
| @@ -41,15 +42,13 @@ public final class ExpansionManager { | ||||
|     public ExpansionManager(PlaceholderAPIPlugin instance) { | ||||
|         plugin = instance; | ||||
|  | ||||
|         File f = new File(PlaceholderAPIPlugin.getInstance().getDataFolder(), "expansions"); | ||||
|         if (!f.exists()) { | ||||
|             f.mkdirs(); | ||||
|         } | ||||
|         File f = new File(plugin.getDataFolder(), "expansions"); | ||||
|         if (!f.exists()) f.mkdirs(); | ||||
|     } | ||||
|  | ||||
|     public PlaceholderExpansion getRegisteredExpansion(String name) { | ||||
|         for (Entry<String, PlaceholderHook> hook : PlaceholderAPI.getPlaceholders().entrySet()) { | ||||
|             if (hook.getValue() instanceof PlaceholderExpansion) { | ||||
|             if (hook.getValue().isExpansion()) { | ||||
|                 if (name.equalsIgnoreCase(hook.getKey())) { | ||||
|                     return (PlaceholderExpansion) hook.getValue(); | ||||
|                 } | ||||
| @@ -60,31 +59,28 @@ public final class ExpansionManager { | ||||
|     } | ||||
|  | ||||
|     public boolean registerExpansion(PlaceholderExpansion expansion) { | ||||
|         if (expansion == null || expansion.getIdentifier() == null) { | ||||
|             return false; | ||||
|         } | ||||
|         if (expansion == null || expansion.getIdentifier() == null) return false; | ||||
|  | ||||
|         if (expansion instanceof Configurable) { | ||||
|             Map<String, Object> defaults = ((Configurable) expansion).getDefaults(); | ||||
|             String pre = "expansions." + expansion.getIdentifier() + "."; | ||||
|             String pre = expansion.getPathStarter(); | ||||
|             FileConfiguration cfg = plugin.getConfig(); | ||||
|             boolean save = false; | ||||
|  | ||||
|             if (defaults != null) { | ||||
|                 for (Entry<String, Object> entries : defaults.entrySet()) { | ||||
|                     if (entries.getKey() == null || entries.getKey().isEmpty()) { | ||||
|                         continue; | ||||
|                     } | ||||
|                 for (Entry<String, Object> entry : defaults.entrySet()) { | ||||
|                     String key = entry.getKey(); | ||||
|                     if (Strings.isNullOrEmpty(key)) continue; | ||||
|  | ||||
|                     if (entries.getValue() == null) { | ||||
|                         if (cfg.contains(pre + entries.getKey())) { | ||||
|                     if (entry.getValue() == null) { | ||||
|                         if (cfg.contains(pre + key)) { | ||||
|                             save = true; | ||||
|                             cfg.set(pre + entries.getKey(), null); | ||||
|                             cfg.set(pre + key, null); | ||||
|                         } | ||||
|                     } else { | ||||
|                         if (!cfg.contains(pre + entries.getKey())) { | ||||
|                         if (!cfg.contains(pre + key)) { | ||||
|                             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()) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (!expansion.register()) { | ||||
|             return false; | ||||
|         } | ||||
|         if (!expansion.canRegister()) return false; | ||||
|         if (!expansion.register()) return false; | ||||
|  | ||||
|         if (expansion instanceof Listener) { | ||||
|             Listener l = (Listener) expansion; | ||||
|             Bukkit.getPluginManager().registerEvents(l, plugin); | ||||
|             Bukkit.getPluginManager().registerEvents((Listener) expansion, plugin); | ||||
|         } | ||||
|  | ||||
|         plugin.getLogger().info("Successfully registered expansion: " + expansion.getIdentifier()); | ||||
| @@ -143,29 +133,18 @@ public final class ExpansionManager { | ||||
|  | ||||
|     public PlaceholderExpansion registerExpansion(String fileName) { | ||||
|         List<Class<?>> subs = FileUtil.getClasses("expansions", fileName, PlaceholderExpansion.class); | ||||
|         if (subs == null || subs.isEmpty()) { | ||||
|             return null; | ||||
|         } | ||||
|         if (subs == null || subs.isEmpty()) 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 | ||||
|         PlaceholderExpansion ex = createInstance(subs.get(0)); | ||||
|         if (registerExpansion(ex)) { | ||||
|             return ex; | ||||
|         } | ||||
|  | ||||
|         if (registerExpansion(ex)) return ex; | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public void registerAllExpansions() { | ||||
|         if (plugin == null) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         List<Class<?>> subs = FileUtil.getClasses("expansions", null, PlaceholderExpansion.class); | ||||
|         if (subs == null || subs.isEmpty()) { | ||||
|             return; | ||||
|         } | ||||
|         if (subs == null || subs.isEmpty()) return; | ||||
|  | ||||
|         for (Class<?> klass : subs) { | ||||
|             PlaceholderExpansion ex = createInstance(klass); | ||||
| @@ -180,34 +159,29 @@ public final class ExpansionManager { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private PlaceholderExpansion createInstance(Class<?> klass) { | ||||
|         if (klass == null) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         PlaceholderExpansion ex = null; | ||||
|         if (!PlaceholderExpansion.class.isAssignableFrom(klass)) { | ||||
|             return null; | ||||
|         } | ||||
|     private PlaceholderExpansion createInstance(Class<?> clazz) { | ||||
|         if (clazz == null) return null; | ||||
|         if (!PlaceholderExpansion.class.isAssignableFrom(clazz)) return null; | ||||
|  | ||||
|         PlaceholderExpansion expansion = null; | ||||
|         try { | ||||
|             Constructor<?>[] c = klass.getConstructors(); | ||||
|             if (c.length == 0) { | ||||
|                 ex = (PlaceholderExpansion) klass.newInstance(); | ||||
|             Constructor<?>[] constructors = clazz.getConstructors(); | ||||
|             if (constructors.length == 0) { | ||||
|                 expansion = (PlaceholderExpansion) clazz.newInstance(); | ||||
|             } else { | ||||
|                 for (Constructor<?> con : c) { | ||||
|                     if (con.getParameterTypes().length == 0) { | ||||
|                         ex = (PlaceholderExpansion) klass.newInstance(); | ||||
|                 for (Constructor<?> ctor : constructors) { | ||||
|                     if (ctor.getParameterTypes().length == 0) { | ||||
|                         expansion = (PlaceholderExpansion) ctor.newInstance(); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } catch (Throwable t) { | ||||
|             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()); | ||||
|         } | ||||
|  | ||||
|         return ex; | ||||
|         return expansion; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,26 +20,28 @@ | ||||
|  */ | ||||
| package me.clip.placeholderapi.expansion; | ||||
|  | ||||
| public enum NMSVersion { | ||||
| import com.google.common.base.Enums; | ||||
|  | ||||
|   UNKNOWN("unknown"), | ||||
|   SPIGOT_1_7_R1("v1_7_R1"), | ||||
|   SPIGOT_1_7_R2("v1_7_R2"), | ||||
|   SPIGOT_1_7_R3("v1_7_R3"), | ||||
|   SPIGOT_1_7_R4("v1_7_R4"), | ||||
|   SPIGOT_1_8_R1("v1_8_R1"), | ||||
|   SPIGOT_1_8_R2("v1_8_R2"), | ||||
|   SPIGOT_1_8_R3("v1_8_R3"), | ||||
|   SPIGOT_1_9_R1("v1_9_R1"), | ||||
|   SPIGOT_1_9_R2("v1_9_R2"), | ||||
|   SPIGOT_1_10_R1("v1_10_R1"), | ||||
|   SPIGOT_1_11_R1("v1_11_R1"), | ||||
|   SPIGOT_1_12_R1("v1_12_R1"), | ||||
|   SPIGOT_1_13_R1("v1_13_R1"), | ||||
|   SPIGOT_1_13_R2("v1_13_R2"), | ||||
|   SPIGOT_1_14_R1("v1_14_R1"), | ||||
|   SPIGOT_1_15_R1("v1_15_R1"), | ||||
|   SPIGOT_1_16_R1("v1_16_R1"); | ||||
| import java.util.Optional; | ||||
|  | ||||
| public enum NMSVersion { | ||||
|     UNKNOWN("unknown"), | ||||
|     SPIGOT_1_7_R1("v1_7_R1"), | ||||
|     SPIGOT_1_7_R2("v1_7_R2"), | ||||
|     SPIGOT_1_7_R3("v1_7_R3"), | ||||
|     SPIGOT_1_7_R4("v1_7_R4"), | ||||
|     SPIGOT_1_8_R1("v1_8_R1"), | ||||
|     SPIGOT_1_8_R2("v1_8_R2"), | ||||
|     SPIGOT_1_8_R3("v1_8_R3"), | ||||
|     SPIGOT_1_9_R1("v1_9_R1"), | ||||
|     SPIGOT_1_9_R2("v1_9_R2"), | ||||
|     SPIGOT_1_10_R1("v1_10_R1"), | ||||
|     SPIGOT_1_11_R1("v1_11_R1"), | ||||
|     SPIGOT_1_12_R1("v1_12_R1"), | ||||
|     SPIGOT_1_13_R1("v1_13_R1"), | ||||
|     SPIGOT_1_13_R2("v1_13_R2"), | ||||
|     SPIGOT_1_14_R1("v1_14_R1"), | ||||
|     SPIGOT_1_15_R1("v1_15_R1"); | ||||
|  | ||||
|     private final String version; | ||||
|  | ||||
| @@ -48,17 +50,12 @@ public enum NMSVersion { | ||||
|     } | ||||
|  | ||||
|     public static NMSVersion getVersion(String version) { | ||||
|         for (NMSVersion v : values()) { | ||||
|             if (v.getVersion().equalsIgnoreCase(version)) { | ||||
|                 return v; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return NMSVersion.UNKNOWN; | ||||
|         // Guava caches values() as well. | ||||
|         Optional<NMSVersion> opt = Enums.getIfPresent(NMSVersion.class, version).toJavaUtil(); | ||||
|         return opt.orElse(NMSVersion.UNKNOWN); | ||||
|     } | ||||
|  | ||||
|     public String getVersion() { | ||||
|         return version; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -26,11 +26,11 @@ import me.clip.placeholderapi.PlaceholderHook; | ||||
| import org.apache.commons.lang.Validate; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.configuration.ConfigurationSection; | ||||
| import org.bukkit.configuration.file.FileConfiguration; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public abstract class PlaceholderExpansion extends PlaceholderHook { | ||||
|  | ||||
|     /** | ||||
|      * 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() { | ||||
|         return PlaceholderAPIPlugin.getInstance(); | ||||
|     public FileConfiguration getConfig() { | ||||
|         return PlaceholderAPIPlugin.getInstance().getConfig(); | ||||
|     } | ||||
|  | ||||
|     public String getString(String path, String def) { | ||||
|         return getPlaceholderAPI().getConfig() | ||||
|                 .getString("expansions." + getIdentifier() + "." + path, def); | ||||
|         return getConfig().getString(getPathStarter() + path, def); | ||||
|     } | ||||
|  | ||||
|     public int getInt(String path, int def) { | ||||
|         return getPlaceholderAPI().getConfig() | ||||
|                 .getInt("expansions." + getIdentifier() + "." + path, def); | ||||
|         return getConfig().getInt(getPathStarter() + path, def); | ||||
|     } | ||||
|  | ||||
|     public long getLong(String path, long def) { | ||||
|         return getPlaceholderAPI().getConfig() | ||||
|                 .getLong("expansions." + getIdentifier() + "." + path, def); | ||||
|         return getConfig().getLong(getPathStarter() + path, def); | ||||
|     } | ||||
|  | ||||
|     public double getDouble(String path, double def) { | ||||
|         return getPlaceholderAPI().getConfig() | ||||
|                 .getDouble("expansions." + getIdentifier() + "." + path, def); | ||||
|         return getConfig().getDouble(getPathStarter() + path, def); | ||||
|     } | ||||
|  | ||||
|     public List<String> getStringList(String path) { | ||||
|         return getPlaceholderAPI().getConfig() | ||||
|                 .getStringList("expansions." + getIdentifier() + "." + path); | ||||
|         return getConfig().getStringList(getPathStarter() + path); | ||||
|     } | ||||
|  | ||||
|     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) { | ||||
|         return getPlaceholderAPI().getConfig() | ||||
|                 .getConfigurationSection("expansions." + getIdentifier() + "." + path); | ||||
|         return getConfig().getConfigurationSection(getPathStarter() + path); | ||||
|     } | ||||
|  | ||||
|     public ConfigurationSection getConfigSection() { | ||||
|         return getPlaceholderAPI().getConfig().getConfigurationSection("expansions." + getIdentifier()); | ||||
|         return getConfig().getConfigurationSection("expansions." + getIdentifier()); | ||||
|     } | ||||
|  | ||||
|     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()} | ||||
|      */ | ||||
|     @SuppressWarnings("DeprecatedIsStillUsed") | ||||
|     @Deprecated | ||||
|     public String getPlugin() { | ||||
|         return null; | ||||
|   | ||||
| @@ -23,6 +23,5 @@ package me.clip.placeholderapi.expansion; | ||||
| import org.bukkit.entity.Player; | ||||
|  | ||||
| public interface Relational { | ||||
|  | ||||
|     String onPlaceholderRequest(Player one, Player two, String identifier); | ||||
| } | ||||
|   | ||||
| @@ -20,9 +20,7 @@ | ||||
|  */ | ||||
| package me.clip.placeholderapi.expansion; | ||||
|  | ||||
|  | ||||
| public interface Taskable { | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|   | ||||
| @@ -21,7 +21,6 @@ | ||||
| package me.clip.placeholderapi.expansion; | ||||
|  | ||||
| public final class Version { | ||||
|  | ||||
|     private final boolean isSpigot; | ||||
|     private final String version; | ||||
|  | ||||
| @@ -41,5 +40,4 @@ public final class Version { | ||||
|     public boolean compareTo(String 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. | ||||
|      */ | ||||
|     boolean isCompatibleWith(Version v); | ||||
|     boolean isCompatibleWith(Version version); | ||||
| } | ||||
|   | ||||
| @@ -26,11 +26,8 @@ import java.util.List; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
|  | ||||
| public class CloudExpansion { | ||||
|  | ||||
|     private String name, | ||||
|             author, | ||||
|     private String name, author, | ||||
|             latest_version, | ||||
|             description, | ||||
|             source_url, | ||||
| @@ -74,14 +71,12 @@ public class CloudExpansion { | ||||
|     } | ||||
|  | ||||
|     public Version getVersion() { | ||||
|         return getLatestVersion() == null ? null : getVersion(getLatestVersion()); | ||||
|         return latest_version == null ? null : getVersion(latest_version); | ||||
|     } | ||||
|  | ||||
|     public Version getVersion(String version) { | ||||
|         return versions == null ? null : versions.stream() | ||||
|                 .filter(v -> v.getVersion().equals(version)) | ||||
|                 .findFirst() | ||||
|                 .orElse(null); | ||||
|                 .filter(v -> v.getVersion().equals(version)).findFirst().orElse(null); | ||||
|     } | ||||
|  | ||||
|     public List<String> getAvailableVersions() { | ||||
| @@ -140,6 +135,10 @@ public class CloudExpansion { | ||||
|         return verified; | ||||
|     } | ||||
|  | ||||
|     public void setVerified(boolean verified) { | ||||
|         this.verified = verified; | ||||
|     } | ||||
|  | ||||
|     public long getLastUpdate() { | ||||
|         return last_update; | ||||
|     } | ||||
| @@ -156,6 +155,10 @@ public class CloudExpansion { | ||||
|         return average_rating; | ||||
|     } | ||||
|  | ||||
|     public void setAverage_rating(double average_rating) { | ||||
|         this.average_rating = average_rating; | ||||
|     } | ||||
|  | ||||
|     public List<String> getPlaceholders() { | ||||
|         return placeholders; | ||||
|     } | ||||
| @@ -172,7 +175,11 @@ public class CloudExpansion { | ||||
|         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; | ||||
|  | ||||
|         public String getUrl() { | ||||
|   | ||||
| @@ -37,37 +37,29 @@ import java.util.stream.Collectors; | ||||
| import java.util.stream.IntStream; | ||||
|  | ||||
| public class ExpansionCloudManager { | ||||
|  | ||||
|     private static final String API_URL = "http://api.extendedclip.com/v2/"; | ||||
|     private static final Gson GSON = new Gson(); | ||||
|  | ||||
|  | ||||
|     private final PlaceholderAPIPlugin plugin; | ||||
|     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<>(); | ||||
|  | ||||
|  | ||||
|     public ExpansionCloudManager(PlaceholderAPIPlugin plugin) { | ||||
|         this.plugin = plugin; | ||||
|  | ||||
|         expansionsDir = new File(plugin.getDataFolder(), "expansions"); | ||||
|  | ||||
|         final boolean result = expansionsDir.mkdirs(); | ||||
|         if (result) { | ||||
|         if (expansionsDir.mkdirs()) { | ||||
|             plugin.getLogger().info("Created Expansions Directory"); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public void clean() { | ||||
|         remote.clear(); | ||||
|         downloading.clear(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public Map<Integer, CloudExpansion> getCloudExpansions() { | ||||
|         return remote; | ||||
|     } | ||||
| @@ -80,7 +72,6 @@ public class ExpansionCloudManager { | ||||
|                 .orElse(null); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public int getCloudAuthorCount() { | ||||
|         return remote.values() | ||||
|                 .stream() | ||||
| @@ -126,14 +117,10 @@ public class ExpansionCloudManager { | ||||
|  | ||||
|  | ||||
|     public int getPagesAvailable(Map<Integer, CloudExpansion> map, int amount) { | ||||
|         if (map == null) { | ||||
|             return 0; | ||||
|         } | ||||
|         if (map == null) return 0; | ||||
|  | ||||
|         int pages = map.size() > 0 ? 1 : 0; | ||||
|         if (pages == 0) { | ||||
|             return pages; | ||||
|         } | ||||
|         if (pages == 0) return 0; | ||||
|  | ||||
|         if (map.size() > amount) { | ||||
|             pages = map.size() / amount; | ||||
| @@ -159,12 +146,11 @@ public class ExpansionCloudManager { | ||||
|         return ex; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public void fetch(boolean allowUnverified) { | ||||
|         plugin.getLogger().info("Fetching available expansion information..."); | ||||
|  | ||||
|         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()))) { | ||||
|                 data.putAll(GSON.fromJson(reader, new TypeToken<Map<String, CloudExpansion>>() { | ||||
| @@ -173,11 +159,12 @@ public class ExpansionCloudManager { | ||||
|                 if (plugin.getPlaceholderAPIConfig().isDebugMode()) { | ||||
|                     ex.printStackTrace(); | ||||
|                 } 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) -> { | ||||
|                 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."); | ||||
|  | ||||
|             long updates = getToUpdateCount(); | ||||
|  | ||||
|             if (updates > 0) { | ||||
| @@ -220,19 +206,15 @@ public class ExpansionCloudManager { | ||||
|  | ||||
|     private void download(URL url, String name) throws IOException { | ||||
|         InputStream is = null; | ||||
|  | ||||
|         FileOutputStream fos = null; | ||||
|  | ||||
|         try { | ||||
|             URLConnection urlConn = url.openConnection(); | ||||
|  | ||||
|             is = urlConn.getInputStream(); | ||||
|  | ||||
|             fos = new FileOutputStream( | ||||
|                     expansionsDir.getAbsolutePath() + File.separator + "Expansion-" + name + ".jar"); | ||||
|  | ||||
|             byte[] buffer = new byte[is.available()]; | ||||
|  | ||||
|             int l; | ||||
|  | ||||
|             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()); | ||||
|     } | ||||
|  | ||||
|     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())) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final CloudExpansion.Version ver = ex.getVersions() | ||||
|         CloudExpansion.Version ver = ex.getVersions() | ||||
|                 .stream() | ||||
|                 .filter(v -> v.getVersion().equals(version)) | ||||
|                 .findFirst() | ||||
|                 .orElse(null); | ||||
|  | ||||
|         if (ver == null) { | ||||
|             return; | ||||
|         } | ||||
|         if (ver == null) return; | ||||
|  | ||||
|         downloading.add(ex.getName()); | ||||
|  | ||||
|         plugin.getLogger().info("Attempting download of expansion: " + ex.getName() + (player != null ? " by user: " + player : "") + " from url: " + ver.getUrl()); | ||||
|  | ||||
|         Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { | ||||
|  | ||||
|             try { | ||||
|                 download(new URL(ver.getUrl()), ex.getName()); | ||||
|  | ||||
|                 plugin.getLogger().info("Download of expansion: " + ex.getName() + " complete!"); | ||||
|  | ||||
|             } catch (Exception e) { | ||||
|                 plugin.getLogger() | ||||
|                         .warning("Failed to download expansion: " + ex.getName() + " from: " + ver.getUrl()); | ||||
|  | ||||
|                 Bukkit.getScheduler().runTask(plugin, () -> { | ||||
|  | ||||
|                     downloading.remove(ex.getName()); | ||||
|  | ||||
|                     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.bukkit.plugin.Plugin; | ||||
|  | ||||
| /** | ||||
|  * Use {@link me.clip.placeholderapi.expansion.PlaceholderExpansion} instead | ||||
|  */ | ||||
| @SuppressWarnings("DeprecatedIsStillUsed") | ||||
| @Deprecated | ||||
| public abstract class EZPlaceholderHook extends PlaceholderHook { | ||||
|  | ||||
| @@ -35,8 +33,8 @@ public abstract class EZPlaceholderHook extends PlaceholderHook { | ||||
|     private final String plugin; | ||||
|  | ||||
|     public EZPlaceholderHook(Plugin plugin, String identifier) { | ||||
|         Validate.notNull(plugin, "Plugin can not be null!"); | ||||
|         Validate.notNull(identifier, "Placeholder name can not be null!"); | ||||
|         Validate.notNull(plugin, "Plugin cannot be null"); | ||||
|         Validate.notNull(identifier, "Placeholder name cannot be null"); | ||||
|         this.identifier = identifier; | ||||
|         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.server.PluginDisableEvent; | ||||
|  | ||||
| import java.util.Map; | ||||
| import java.util.Map.Entry; | ||||
| import java.util.Set; | ||||
|  | ||||
|  | ||||
| public class PlaceholderListener implements Listener { | ||||
|  | ||||
|     private final PlaceholderAPIPlugin plugin; | ||||
|  | ||||
|     public PlaceholderListener(PlaceholderAPIPlugin instance) { | ||||
| @@ -53,22 +48,23 @@ public class PlaceholderListener implements Listener { | ||||
|  | ||||
|     @EventHandler | ||||
|     public void onExpansionUnregister(ExpansionUnregisterEvent event) { | ||||
|         if (event.getExpansion() instanceof Listener) { | ||||
|             HandlerList.unregisterAll((Listener) event.getExpansion()); | ||||
|         PlaceholderExpansion expansion = event.getExpansion(); | ||||
|         if (expansion instanceof Listener) { | ||||
|             HandlerList.unregisterAll((Listener) expansion); | ||||
|         } | ||||
|  | ||||
|         if (event.getExpansion() instanceof Taskable) { | ||||
|             ((Taskable) event.getExpansion()).stop(); | ||||
|         if (expansion instanceof Taskable) { | ||||
|             ((Taskable) expansion).stop(); | ||||
|         } | ||||
|  | ||||
|         if (event.getExpansion() instanceof Cacheable) { | ||||
|             ((Cacheable) event.getExpansion()).clear(); | ||||
|         if (expansion instanceof Cacheable) { | ||||
|             ((Cacheable) expansion).clear(); | ||||
|         } | ||||
|  | ||||
|         if (plugin.getExpansionCloud() != null) { | ||||
|  | ||||
|             CloudExpansion ex = plugin.getExpansionCloud() | ||||
|                     .getCloudExpansion(event.getExpansion().getName()); | ||||
|                     .getCloudExpansion(expansion.getName()); | ||||
|  | ||||
|             if (ex != null) { | ||||
|                 ex.setHasExpansion(false); | ||||
| @@ -78,28 +74,20 @@ public class PlaceholderListener implements Listener { | ||||
|     } | ||||
|  | ||||
|     @EventHandler(priority = EventPriority.HIGH) | ||||
|     public void onPluginUnload(PluginDisableEvent e) { | ||||
|         String n = e.getPlugin().getName(); | ||||
|     public void onPluginUnload(PluginDisableEvent event) { | ||||
|         // A plugin name cannot be null. | ||||
|         String name = event.getPlugin().getName(); | ||||
|         if (name.equals(plugin.getName())) return; | ||||
|  | ||||
|         if (n.equals(plugin.getName())) { | ||||
|             return; | ||||
|         } | ||||
|         for (PlaceholderHook hook : PlaceholderAPI.getPlaceholders().values()) { | ||||
|             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()) { | ||||
|             PlaceholderHook hook = entry.getValue(); | ||||
|  | ||||
|             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()); | ||||
|                 if (ex.getRequiredPlugin().equalsIgnoreCase(name)) { | ||||
|                     if (PlaceholderAPI.unregisterExpansion(ex)) { | ||||
|                         plugin.getLogger().info("Unregistered placeholder expansion: " + ex.getIdentifier()); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -107,16 +95,10 @@ public class PlaceholderListener implements Listener { | ||||
|     } | ||||
|  | ||||
|     @EventHandler | ||||
|     public void onQuit(PlayerQuitEvent e) { | ||||
|         Set<PlaceholderExpansion> expansions = PlaceholderAPI.getExpansions(); | ||||
|  | ||||
|         if (expansions.isEmpty()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         for (PlaceholderExpansion ex : expansions) { | ||||
|             if (ex instanceof Cleanable) { | ||||
|                 ((Cleanable) ex).cleanup(e.getPlayer()); | ||||
|     public void onQuit(PlayerQuitEvent event) { | ||||
|         for (PlaceholderHook hook : PlaceholderAPI.getPlaceholders().values()) { | ||||
|             if (hook instanceof Cleanable) { | ||||
|                 ((Cleanable) hook).cleanup(event.getPlayer()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -31,7 +31,6 @@ import org.bukkit.event.server.ServerLoadEvent; | ||||
| import java.util.Map; | ||||
|  | ||||
| public class ServerLoadEventListener implements Listener { | ||||
|  | ||||
|     private final PlaceholderAPIPlugin plugin; | ||||
|  | ||||
|     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> | ||||
|      * 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> | ||||
|      * This will ensure no issues with expanions and hooks. | ||||
|      * | ||||
|      * @param e the server load event | ||||
|      * @param event the server load event. | ||||
|      */ | ||||
|     @EventHandler | ||||
|     public void onServerLoad(ServerLoadEvent e) { | ||||
|     public void onServerLoad(ServerLoadEvent event) { | ||||
|         plugin.getLogger().info("Placeholder expansion registration initializing..."); | ||||
|         final Map<String, PlaceholderHook> alreadyRegistered = PlaceholderAPI.getPlaceholders(); | ||||
|         Map<String, PlaceholderHook> alreadyRegistered = PlaceholderAPI.getPlaceholders(); | ||||
|         plugin.getExpansionManager().registerAllExpansions(); | ||||
|  | ||||
|         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 { | ||||
|             File f = new File(PlaceholderAPIPlugin.getInstance().getDataFolder(), folder); | ||||
|             if (!f.exists()) { | ||||
|                 return list; | ||||
|             } | ||||
|             if (!f.exists()) return list; | ||||
|  | ||||
|             FilenameFilter fileNameFilter = (dir, name) -> { | ||||
|                 boolean isJar = name.endsWith(".jar"); | ||||
|                 if (fileName != null) { | ||||
|                     return name.endsWith(".jar") && name.replace(".jar", "") | ||||
|                             .equalsIgnoreCase(fileName.replace(".jar", "")); | ||||
|                     return isJar && name.substring(0, name.length() - 4) | ||||
|                             .equalsIgnoreCase(fileName.substring(0, fileName.length() - 4)); | ||||
|                 } | ||||
|  | ||||
|                 return name.endsWith(".jar"); | ||||
|                 return isJar; | ||||
|             }; | ||||
|  | ||||
|             File[] jars = f.listFiles(fileNameFilter); | ||||
|             if (jars == null) { | ||||
|                 return list; | ||||
|             } | ||||
|             if (jars == null) return list; | ||||
|  | ||||
|             for (File file : jars) { | ||||
|                 list = gather(file.toURI().toURL(), list, type); | ||||
|             } | ||||
|  | ||||
|             return list; | ||||
|         } catch (Throwable t) { | ||||
|         } catch (Throwable ignored) { | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private static List<Class<?>> gather(URL jar, List<Class<?>> list, Class<?> clazz) { | ||||
|         if (list == null) { | ||||
|             list = new ArrayList<>(); | ||||
|         } | ||||
|  | ||||
|         // list cannot be null. | ||||
|         try (URLClassLoader cl = new URLClassLoader(new URL[]{jar}, clazz.getClassLoader()); | ||||
|              JarInputStream jis = new JarInputStream(jar.openStream())) { | ||||
|  | ||||
|             while (true) { | ||||
|                 JarEntry j = jis.getNextJarEntry(); | ||||
|                 if (j == null) { | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 String name = j.getName(); | ||||
|                 if (name == null || name.isEmpty()) { | ||||
|                     continue; | ||||
|                 } | ||||
|             JarEntry entry; | ||||
|             while ((entry = jis.getNextJarEntry()) != null) { | ||||
|                 String name = entry.getName(); | ||||
|                 if (name == null || name.isEmpty()) continue; | ||||
|  | ||||
|                 if (name.endsWith(".class")) { | ||||
|                     name = name.replace("/", "."); | ||||
|                     String cname = name.substring(0, name.lastIndexOf(".class")); | ||||
|                     name = name.substring(0, name.length() - 6).replace('/', '.'); | ||||
|  | ||||
|                     Class<?> c = cl.loadClass(cname); | ||||
|                     if (clazz.isAssignableFrom(c)) { | ||||
|                         list.add(c); | ||||
|                     } | ||||
|                     Class<?> loaded = cl.loadClass(name); | ||||
|                     if (clazz.isAssignableFrom(loaded)) list.add(loaded); | ||||
|                 } | ||||
|             } | ||||
|         } catch (Throwable t) { | ||||
|         } catch (Throwable ignored) { | ||||
|         } | ||||
|  | ||||
|         return list; | ||||
|   | ||||
| @@ -24,17 +24,20 @@ import org.bukkit.Bukkit; | ||||
| import org.bukkit.ChatColor; | ||||
| import org.bukkit.command.CommandSender; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import java.util.Objects; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| public final class 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 class Msg { | ||||
|     public static void msg(CommandSender sender, String... messages) { | ||||
|         for (String message : messages) { | ||||
|             String msg = color(message); | ||||
|             sender.sendMessage(msg); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void broadcast(String... msg) { | ||||
|         Arrays.stream(msg).filter(Objects::nonNull).map(Msg::color).forEach(Bukkit::broadcastMessage); | ||||
|     public static void broadcast(String... messages) { | ||||
|         CommandSender sender = Bukkit.getConsoleSender(); | ||||
|         for (String message : messages) { | ||||
|             String msg = color(message); | ||||
|             sender.sendMessage(msg); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     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.temporal.ChronoUnit; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| public class TimeUtil { | ||||
|  | ||||
|     public static String getRemaining(int seconds, TimeFormat type) { | ||||
|     public static String getRemaining(int seconds, TimeUnit type) { | ||||
|         if (seconds < 60) { | ||||
|             switch (type) { | ||||
|                 case DAYS: | ||||
| @@ -124,8 +124,8 @@ public class TimeUtil { | ||||
|      * @param duration {@link Duration} (eg, Duration.of(20, {@link ChronoUnit#SECONDS}) for 20 seconds) | ||||
|      * @return formatted time | ||||
|      */ | ||||
|     public static String getTime(final Duration duration) { | ||||
|         final StringBuilder builder = new StringBuilder(); | ||||
|     public static String getTime(Duration duration) { | ||||
|         StringBuilder builder = new StringBuilder(); | ||||
|  | ||||
|         long seconds = duration.getSeconds(); | ||||
|         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.util.Msg; | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.bukkit.event.EventHandler; | ||||
| import org.bukkit.event.EventPriority; | ||||
| import org.bukkit.event.Listener; | ||||
| import org.bukkit.event.player.PlayerJoinEvent; | ||||
| 
 | ||||
| @@ -32,10 +32,11 @@ import javax.net.ssl.HttpsURLConnection; | ||||
| import java.io.BufferedReader; | ||||
| import java.io.InputStreamReader; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| 
 | ||||
| public class UpdateChecker implements Listener { | ||||
| 
 | ||||
|     private final int RESOURCE_ID = 6245; | ||||
|     private static 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 String pluginVersion; | ||||
|     private String spigotVersion; | ||||
| @@ -57,39 +58,35 @@ public class UpdateChecker implements Listener { | ||||
|     public void fetch() { | ||||
|         Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { | ||||
|             try { | ||||
|                 HttpsURLConnection con = (HttpsURLConnection) new URL( | ||||
|                         "https://api.spigotmc.org/legacy/update.php?resource=" + RESOURCE_ID).openConnection(); | ||||
|                 HttpsURLConnection con = (HttpsURLConnection) new URL(SPIGOT_API).openConnection(); | ||||
| 
 | ||||
|                 // Prevents the server from freezing with bad internet connection. | ||||
|                 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) { | ||||
|                 plugin.getLogger().info("Failed to check for updates on spigot."); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (spigotVersion == null || spigotVersion.isEmpty()) { | ||||
|                 plugin.getLogger().warning("Failed to check for updates on spigot."); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (spigotVersion == null || spigotVersion.isEmpty()) return; | ||||
|             updateAvailable = spigotIsNewer(); | ||||
| 
 | ||||
|             if (!updateAvailable) { | ||||
|                 return; | ||||
|             } | ||||
|             if (!updateAvailable) return; | ||||
| 
 | ||||
|             Bukkit.getScheduler().runTask(plugin, () -> { | ||||
|                 plugin.getLogger() | ||||
|                         .info("An update for PlaceholderAPI (v" + getSpigotVersion() + ") is available at:"); | ||||
|                         .info("An update for PlaceholderAPI (v" + spigotVersion + ") is available at:"); | ||||
|                 plugin.getLogger() | ||||
|                         .info("https://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID + "/"); | ||||
|                         .info("https://www.spigotmc.org/resources/" + RESOURCE_ID + '/'); | ||||
|                 Bukkit.getPluginManager().registerEvents(this, plugin); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private boolean spigotIsNewer() { | ||||
|         if (spigotVersion == null || spigotVersion.isEmpty()) { | ||||
|             return false; | ||||
|         } | ||||
|         if (spigotVersion == null || spigotVersion.isEmpty()) return false; | ||||
| 
 | ||||
|         String plV = toReadable(pluginVersion); | ||||
|         String spV = toReadable(spigotVersion); | ||||
| @@ -97,21 +94,17 @@ public class UpdateChecker implements Listener { | ||||
|     } | ||||
| 
 | ||||
|     private String toReadable(String version) { | ||||
|         if (version.contains("-DEV-")) { | ||||
|             version = version.split("-DEV-")[0]; | ||||
|         } | ||||
| 
 | ||||
|         return version.replaceAll("\\.", ""); | ||||
|         if (version.contains("-DEV-")) version = StringUtils.split(version, "-DEV-")[0]; | ||||
|         return StringUtils.remove(version, '.'); | ||||
|     } | ||||
| 
 | ||||
|     @EventHandler(priority = EventPriority.MONITOR) | ||||
|     public void onJoin(PlayerJoinEvent e) { | ||||
|         if (e.getPlayer().hasPermission("placeholderapi.updatenotify")) { | ||||
|             Msg.msg(e.getPlayer(), | ||||
|                     "&bAn update for &fPlaceholder&7API &e(&fPlaceholder&7API &fv" + getSpigotVersion() | ||||
|                             + "&e)" | ||||
|                     , "&bis available at &ehttps://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID | ||||
|                             + "/"); | ||||
|     @EventHandler | ||||
|     public void onJoin(PlayerJoinEvent event) { | ||||
|         Player player = event.getPlayer(); | ||||
|         if (player.hasPermission("placeholderapi.updatenotify")) { | ||||
|             Msg.msg(player, | ||||
|                     "&bAn update for &fPlaceholder&7API &e(&fPlaceholder&7API &fv" + getSpigotVersion() + "&e)", | ||||
|                     "&bis available at &ehttps://www.spigotmc.org/resources/placeholderapi." + RESOURCE_ID + '/'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -4,39 +4,51 @@ version: ${project.version} | ||||
| api-version: '1.13' | ||||
| authors: [extended_clip, Glare] | ||||
| description: ${project.description} | ||||
| permissions: | ||||
|     placeholderapi.*: | ||||
|         description: ability to use all commands | ||||
|         children: | ||||
|             placeholderapi.admin: true | ||||
|     placeholderapi.admin: | ||||
|         description: ability to use all commands | ||||
|         children: | ||||
|             placeholderapi.list: true | ||||
|             placeholderapi.reload: true | ||||
|             placeholderapi.ecloud: true | ||||
|             placeholderapi.parse: true | ||||
|             placeholderapi.register: true | ||||
|             placeholderapi.updatenotify: true | ||||
|     placeholderapi.list: | ||||
|         description: ability to use the list command | ||||
|         default: op | ||||
|     placeholderapi.reload: | ||||
|         description: ability to use the reload command | ||||
|         default: op | ||||
|     placeholderapi.parse: | ||||
|         description: ability to use parse command | ||||
|         default: op | ||||
|     placeholderapi.register: | ||||
|         description: ability to register or unregister placeholder expansions | ||||
|         default: op | ||||
|     placeholderapi.ecloud: | ||||
|         description: allows the usage of ecloud commands | ||||
|         default: op | ||||
|     placeholderapi.updatenotify: | ||||
|         description: notifies you when there is a PAPI update | ||||
|         default: op | ||||
|  | ||||
| commands: | ||||
|    placeholderapi: | ||||
|      description: PlaceholderAPI command | ||||
|      aliases: [papi] | ||||
|   placeholderapi: | ||||
|     description: PlaceholderAPI command | ||||
|     aliases: [papi] | ||||
|  | ||||
| permissions: | ||||
|   placeholderapi.*: | ||||
|     description: ability to use all commands | ||||
|     children: | ||||
|       placeholderapi.admin: true | ||||
|   placeholderapi.admin: | ||||
|     description: ability to use all commands | ||||
|     children: | ||||
|       placeholderapi.list: true | ||||
|       placeholderapi.reload: true | ||||
|       placeholderapi.ecloud: true | ||||
|       placeholderapi.parse: true | ||||
|       placeholderapi.register: true | ||||
|       placeholderapi.updatenotify: true | ||||
|   placeholderapi.list: | ||||
|     description: ability to use the list command | ||||
|     default: op | ||||
|   placeholderapi.reload: | ||||
|     description: ability to use the reload command | ||||
|     default: op | ||||
|   placeholderapi.parse: | ||||
|     description: ability to use parse command | ||||
|     default: op | ||||
|   placeholderapi.register: | ||||
|     description: ability to register or unregister placeholder expansions | ||||
|     default: op | ||||
|   placeholderapi.ecloud: | ||||
|     description: allows the usage of ecloud commands | ||||
|     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: | ||||
|     description: notifies you when there is a PAPI update | ||||
|     default: op | ||||
		Reference in New Issue
	
	Block a user