Performance Improvements (#340)

* Performance Improvements

* More Optimizations

* Even More Optimizations & Cleanups

* Almost a recode I guess
This commit is contained in:
Crypto Morin 2020-07-16 09:32:22 -07:00 committed by GitHub
parent f9f59f1f96
commit 54d5757d0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 876 additions and 875 deletions

36
pom.xml
View File

@ -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>

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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;
}
}

View 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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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));
}
}

View File

@ -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()));
}

View File

@ -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",

View File

@ -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()));
}

View File

@ -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;

View File

@ -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<>();
}
}

View File

@ -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));
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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()));
}

View File

@ -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()));
}

View File

@ -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!!");
}

View File

@ -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;
}
}

View File

@ -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;
// }
}

View File

@ -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;
}

View File

@ -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());

View File

@ -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()));
}

View File

@ -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
}
}

View File

@ -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());

View File

@ -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()

View File

@ -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);
}
}

View File

@ -1,8 +0,0 @@
package me.clip.placeholderapi.exceptions;
public final class NoDefaultCommandException extends RuntimeException {
public NoDefaultCommandException(final String message) {
super(message);
}
}

View File

@ -28,7 +28,6 @@ package me.clip.placeholderapi.expansion;
* @author Ryan McCarthy
*/
public interface Cacheable {
/**
* Called when the implementing class is unregistered from PlaceholderAPI
*/

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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() {

View File

@ -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 {
}
}
});
});
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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());
}
}
}

View File

@ -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()) {

View File

@ -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";
}

View File

@ -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;

View File

@ -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) {

View File

@ -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
}

View File

@ -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;

View File

@ -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 + '/');
}
}
}

View File

@ -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