mirror of
https://github.com/PlaceholderAPI/PlaceholderAPI.git
synced 2024-11-22 10:36:14 +01:00
2.8.5
This commit is contained in:
commit
fbe0a03a8f
71
pom.xml
Normal file
71
pom.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
|
||||
<version>2.8.5</version>
|
||||
<name>PlaceholderAPI</name>
|
||||
<description>An awesome placeholder plugin</description>
|
||||
<url>http://extendedclip.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype</id>
|
||||
<url> https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
297
src/main/java/me/clip/placeholderapi/PlaceholderAPI.java
Normal file
297
src/main/java/me/clip/placeholderapi/PlaceholderAPI.java
Normal file
@ -0,0 +1,297 @@
|
||||
package me.clip.placeholderapi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import me.clip.placeholderapi.events.PlaceholderHookUnloadEvent;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.expansion.Relational;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class PlaceholderAPI {
|
||||
|
||||
private PlaceholderAPI() {
|
||||
}
|
||||
|
||||
private final static Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]");
|
||||
private final static Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[{]([^{}]+)[}]");
|
||||
private final static Pattern RELATIONAL_PLACEHOLDER_PATTERN = Pattern.compile("[%](rel_)([^%]+)[%]");
|
||||
private final static Map<String, PlaceholderHook> placeholders = new HashMap<>();
|
||||
|
||||
/**
|
||||
* unregister ALL placeholder hooks that are currently registered
|
||||
*/
|
||||
protected static void unregisterAll() {
|
||||
unregisterAllExpansions();
|
||||
placeholders.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister all expansions
|
||||
*/
|
||||
public static void unregisterAllExpansions() {
|
||||
if (placeholders.isEmpty()) return;
|
||||
getPlaceholders().forEach((key, value) -> {
|
||||
if (value instanceof PlaceholderExpansion) {
|
||||
Bukkit.getPluginManager().callEvent(new PlaceholderHookUnloadEvent(key, value));
|
||||
unregisterPlaceholderHook(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a specific placeholder identifier is currently registered
|
||||
* @param identifier to check
|
||||
* @return true if identifier is already registered
|
||||
*/
|
||||
public static boolean isRegistered(String identifier) {
|
||||
return !placeholders.isEmpty() && getRegisteredIdentifiers().stream().filter(id -> id.equalsIgnoreCase(identifier)).findFirst().orElse(null) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new placeholder hook
|
||||
* @param identifier Identifier of the placeholder -> "%(identifier)_(args...)%
|
||||
*
|
||||
* @param placeholderHook implementing class that contains the onPlaceholderRequest method which is called when a value is needed for the specific placeholder
|
||||
* @return true if the hook was successfully registered, false if there is already a hook 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;
|
||||
//test
|
||||
placeholders.put(identifier.toLowerCase(), placeholderHook);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister a placeholder hook by identifier
|
||||
* @param identifier the identifier for the placeholder hook to unregister
|
||||
* @return true if the placeholder hook was successfully unregistered, false if there was no 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all registered placeholder identifiers
|
||||
* @return all registered placeholder identifiers
|
||||
*/
|
||||
public static Set<String> getRegisteredIdentifiers() {
|
||||
if (placeholders.isEmpty()) return new HashSet<>();
|
||||
return new HashSet<>(placeholders.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map of registered placeholders
|
||||
* @return copy of the internal placeholder map
|
||||
*/
|
||||
public static Map<String, PlaceholderHook> getPlaceholders() {
|
||||
return new HashMap<>(placeholders);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a String contains any PlaceholderAPI placeholders
|
||||
* @param text String to check
|
||||
* @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();
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a String contains any PlaceholderAPI bracket placeholders
|
||||
* @param text String to check
|
||||
* @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();
|
||||
}
|
||||
|
||||
/**
|
||||
* set placeholders in the list<String> text provided
|
||||
* placeholders are matched with the pattern {<placeholder>} when set with this method
|
||||
* @param p Player to parse the placeholders for
|
||||
* @param text text to set the placeholder values in
|
||||
* @return modified list with all placeholders set to the corresponding values
|
||||
*/
|
||||
public static List<String> setBracketPlaceholders(Player p, List<String> text) {
|
||||
if (text == null) return null;
|
||||
List<String> temp = new ArrayList<>();
|
||||
text.forEach(line -> {
|
||||
temp.add(setBracketPlaceholders(p, line));
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* set placeholders in the text specified
|
||||
* placeholders are matched with the pattern {<placeholder>} when set with this method
|
||||
* @param player Player to parse the placeholders for
|
||||
* @param text text to parse the placeholder values to
|
||||
* @return modified text with all placeholders set to the corresponding values
|
||||
*/
|
||||
public static String setBracketPlaceholders(Player player, String text) {
|
||||
if (text == null) return null;
|
||||
if (placeholders.isEmpty()) return colorize(text);
|
||||
Matcher placeholderMatcher = BRACKET_PLACEHOLDER_PATTERN.matcher(text);
|
||||
Map<String, PlaceholderHook> hooks = getPlaceholders();
|
||||
while (placeholderMatcher.find()) {
|
||||
String format = placeholderMatcher.group(1);
|
||||
int index = format.indexOf("_");
|
||||
if (index == -1 || index >= format.length()) continue;
|
||||
String identifier = format.substring(0, index).toLowerCase();
|
||||
String params = format.substring(index+1);
|
||||
if (hooks.containsKey(identifier)) {
|
||||
String value = hooks.get(identifier).onPlaceholderRequest(player, params);
|
||||
if (value != null) {
|
||||
text = text.replaceAll("\\{"+format+"\\}", Matcher.quoteReplacement(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return colorize(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* set placeholders in the list<String> text provided
|
||||
* placeholders are matched with the pattern %(identifier)_(params)>% when set with this method
|
||||
* @param p Player to parse the placeholders for
|
||||
* @param text text to parse the placeholder values in
|
||||
* @return modified list with all placeholders set to the corresponding values
|
||||
*/
|
||||
public static List<String> setPlaceholders(Player p, List<String> text) {
|
||||
if (text == null) return null;
|
||||
List<String> temp = new ArrayList<>();
|
||||
text.forEach(line -> {
|
||||
temp.add(setPlaceholders(p, line));
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* set placeholders in the text specified
|
||||
* placeholders are matched with the pattern %<(identifier)_(params)>% when set with this method
|
||||
* @param player Player to parse the placeholders for
|
||||
* @param text text to parse the placeholder values to
|
||||
* @return text with all placeholders set to the corresponding values
|
||||
*/
|
||||
public static String setPlaceholders(Player player, String text) {
|
||||
if (text == null) return null;
|
||||
if (placeholders.isEmpty()) return colorize(text);
|
||||
Matcher m = PLACEHOLDER_PATTERN.matcher(text);
|
||||
Map<String, PlaceholderHook> hooks = getPlaceholders();
|
||||
while (m.find()) {
|
||||
String format = m.group(1);
|
||||
int index = format.indexOf("_");
|
||||
if (index <= 0 || index >= format.length()) continue;
|
||||
String identifier = format.substring(0, index).toLowerCase();
|
||||
String params = format.substring(index+1);
|
||||
if (hooks.containsKey(identifier)) {
|
||||
String value = hooks.get(identifier).onPlaceholderRequest(player, params);
|
||||
if (value != null) {
|
||||
text = text.replace("%"+format+"%", Matcher.quoteReplacement(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ChatColor.translateAlternateColorCodes('&', text);
|
||||
}
|
||||
|
||||
/**
|
||||
* set relational placeholders in the text specified
|
||||
* placeholders are matched with the pattern %<rel_(identifier)_(params)>% when set with this method
|
||||
* @param one Player to compare
|
||||
* @param two Player to compare
|
||||
* @param text text to parse the placeholder values to
|
||||
* @return text with all relational placeholders set to the corresponding values
|
||||
*/
|
||||
public static List<String> setRelationalPlaceholders(Player one, Player two, List<String> text) {
|
||||
if (text == null) return null;
|
||||
List<String> temp = new ArrayList<>();
|
||||
text.forEach(line -> {
|
||||
temp.add(setRelationalPlaceholders(one, two, line));
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* set relational placeholders in the text specified
|
||||
* placeholders are matched with the pattern %<rel_(identifier)_(params)>% when set with this method
|
||||
* @param one Player to compare
|
||||
* @param two Player to compare
|
||||
* @param text text to parse the placeholder values to
|
||||
* @return text with all relational placeholders set to the corresponding values
|
||||
*/
|
||||
public static String setRelationalPlaceholders(Player one, Player two, String text) {
|
||||
if (text == null) return null;
|
||||
if (placeholders.isEmpty()) return colorize(text);
|
||||
Matcher m = RELATIONAL_PLACEHOLDER_PATTERN.matcher(text);
|
||||
Map<String, PlaceholderHook> hooks = getPlaceholders();
|
||||
while (m.find()) {
|
||||
String format = m.group(2);
|
||||
int index = format.indexOf("_");
|
||||
if (index <= 0 || index >= format.length()) continue;
|
||||
String identifier = format.substring(0, index).toLowerCase();
|
||||
String params = format.substring(index+1);
|
||||
|
||||
if (hooks.containsKey(identifier)) {
|
||||
|
||||
if (!(hooks.get(identifier) instanceof Relational)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Relational rel = (Relational) hooks.get(identifier);
|
||||
String value = rel.onPlaceholderRequest(one, two, params);
|
||||
|
||||
if (value != null) {
|
||||
text = text.replace("%rel_"+format+"%", Matcher.quoteReplacement(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ChatColor.translateAlternateColorCodes('&', text);
|
||||
}
|
||||
|
||||
public static Pattern getPlaceholderPattern() {
|
||||
return PLACEHOLDER_PATTERN;
|
||||
}
|
||||
|
||||
public static Pattern getBracketPlaceholderPattern() {
|
||||
return BRACKET_PLACEHOLDER_PATTERN;
|
||||
}
|
||||
|
||||
public static Pattern getRelationalPlaceholderPattern() {
|
||||
return RELATIONAL_PLACEHOLDER_PATTERN;
|
||||
}
|
||||
|
||||
public static String colorize(String text) {
|
||||
return ChatColor.translateAlternateColorCodes('&', text);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Set<String> getRegisteredPlaceholderPlugins() {
|
||||
return getRegisteredIdentifiers();
|
||||
}
|
||||
@Deprecated
|
||||
public static Set<String> getExternalPlaceholderPlugins() {
|
||||
return null;
|
||||
}
|
||||
@Deprecated
|
||||
public static boolean registerPlaceholderHook(Plugin plugin, PlaceholderHook placeholderHook) {
|
||||
return plugin != null && registerPlaceholderHook(plugin.getName(), placeholderHook);
|
||||
}
|
||||
@Deprecated
|
||||
public static boolean unregisterPlaceholderHook(Plugin plugin) {
|
||||
return plugin != null && unregisterPlaceholderHook(plugin.getName());
|
||||
}
|
||||
}
|
258
src/main/java/me/clip/placeholderapi/PlaceholderAPIPlugin.java
Normal file
258
src/main/java/me/clip/placeholderapi/PlaceholderAPIPlugin.java
Normal file
@ -0,0 +1,258 @@
|
||||
package me.clip.placeholderapi;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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.updatechecker.UpdateChecker;
|
||||
import me.clip.placeholderapi.util.TimeUtil;
|
||||
import me.clip.placeholderapi.metrics.Metrics;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
|
||||
/**
|
||||
* Yes I have a shit load of work to do...
|
||||
*
|
||||
* @author Ryan McCarthy
|
||||
*
|
||||
*/
|
||||
public class PlaceholderAPIPlugin extends JavaPlugin {
|
||||
|
||||
private static PlaceholderAPIPlugin instance;
|
||||
|
||||
private PlaceholderAPIConfig config;
|
||||
|
||||
private ExpansionManager expansionManager;
|
||||
|
||||
private ExpansionCloudManager expansionCloud;
|
||||
|
||||
private static SimpleDateFormat dateFormat;
|
||||
|
||||
private static String booleanTrue;
|
||||
|
||||
private static String booleanFalse;
|
||||
|
||||
private static Version serverVersion;
|
||||
|
||||
private long startTime;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
startTime = System.currentTimeMillis();
|
||||
instance = this;
|
||||
serverVersion = getVersion();
|
||||
config = new PlaceholderAPIConfig(this);
|
||||
expansionManager = new ExpansionManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
config.loadDefConfig();
|
||||
setupOptions();
|
||||
setupCommands();
|
||||
new PlaceholderListener(this);
|
||||
getLogger().info("Placeholder expansion registration initializing...");
|
||||
expansionManager.registerAllExpansions();
|
||||
if (config.checkUpdates()) {
|
||||
new UpdateChecker(this);
|
||||
}
|
||||
if (config.isCloudEnabled()) {
|
||||
enableCloud();
|
||||
}
|
||||
setupMetrics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
disableCloud();
|
||||
PlaceholderAPI.unregisterAll();
|
||||
expansionManager.clean();
|
||||
expansionManager = null;
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
serverVersion = null;
|
||||
instance = null;
|
||||
}
|
||||
|
||||
public void reloadConf(CommandSender s) {
|
||||
boolean cloudEnabled = this.expansionCloud != null;
|
||||
expansionManager.clean();
|
||||
PlaceholderAPI.unregisterAllExpansions();
|
||||
reloadConfig();
|
||||
saveConfig();
|
||||
setupOptions();
|
||||
expansionManager.registerAllExpansions();
|
||||
if (!config.isCloudEnabled()) {
|
||||
disableCloud();
|
||||
} else if (!cloudEnabled) {
|
||||
enableCloud();
|
||||
}
|
||||
s.sendMessage(ChatColor.translateAlternateColorCodes('&', PlaceholderAPI.getRegisteredIdentifiers().size() + " &aplaceholder hooks successfully registered!"));
|
||||
}
|
||||
|
||||
private void setupCommands() {
|
||||
if (serverVersion != null && serverVersion.isSpigot()) {
|
||||
getCommand("placeholderapi").setExecutor(new me.clip.placeholderapi.commands.spigot.PlaceholderAPICommands(this));
|
||||
} else {
|
||||
getCommand("placeholderapi").setExecutor(new me.clip.placeholderapi.commands.bukkit.PlaceholderAPICommands(this));
|
||||
}
|
||||
}
|
||||
|
||||
private void setupOptions() {
|
||||
booleanTrue = config.booleanTrue();
|
||||
if (booleanTrue == null) {
|
||||
booleanTrue = "true";
|
||||
}
|
||||
booleanFalse = config.booleanFalse();
|
||||
if (booleanFalse == null) {
|
||||
booleanFalse = "false";
|
||||
}
|
||||
try {
|
||||
dateFormat = new SimpleDateFormat(config.dateFormat());
|
||||
} catch (Exception e) {
|
||||
dateFormat = new SimpleDateFormat("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"));
|
||||
|
||||
m.addCustomChart(new Metrics.SimplePie("using_spigot", () -> getServerVersion().isSpigot() ? "yes" : "no"));
|
||||
|
||||
m.addCustomChart(new Metrics.AdvancedPie("expansions_used", () -> {
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
Map<String, PlaceholderHook> p = PlaceholderAPI.getPlaceholders();
|
||||
|
||||
if (!p.isEmpty()) {
|
||||
|
||||
for (PlaceholderHook hook : p.values()) {
|
||||
if (hook instanceof PlaceholderExpansion) {
|
||||
PlaceholderExpansion ex = (PlaceholderExpansion) hook;
|
||||
map.put(ex.getPlugin() == null ? ex.getIdentifier()
|
||||
: ex.getPlugin(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
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 exception) {
|
||||
}
|
||||
return new Version(v, spigot);
|
||||
}
|
||||
|
||||
public void enableCloud() {
|
||||
if (expansionCloud == null) {
|
||||
expansionCloud = new ExpansionCloudManager(this);
|
||||
expansionCloud.fetch();
|
||||
} else {
|
||||
expansionCloud.clean();
|
||||
expansionCloud.fetch();
|
||||
}
|
||||
}
|
||||
|
||||
public void disableCloud() {
|
||||
if (expansionCloud != null) {
|
||||
expansionCloud.clean();
|
||||
expansionCloud = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 available from the
|
||||
* class: {@link PlaceholderAPI}
|
||||
*
|
||||
* @return PlaceholderAPIPlugin instance
|
||||
*/
|
||||
public static PlaceholderAPIPlugin getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configurable {@linkplain SimpleDateFormat} object that is used to
|
||||
* parse time for generic time based placeholders
|
||||
*
|
||||
* @return date format
|
||||
*/
|
||||
public static SimpleDateFormat getDateFormat() {
|
||||
return dateFormat != null ? dateFormat : new SimpleDateFormat(
|
||||
"MM/dd/yy HH:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configurable {@linkplain String} value that should be returned
|
||||
* when a boolean is true
|
||||
*
|
||||
* @return string value of true
|
||||
*/
|
||||
public static String booleanTrue() {
|
||||
return booleanTrue != null ? booleanTrue : "true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configurable {@linkplain String} value that should be returned
|
||||
* when a boolean is false
|
||||
*
|
||||
* @return string value of false
|
||||
*/
|
||||
public static String booleanFalse() {
|
||||
return booleanFalse != null ? booleanFalse : "false";
|
||||
}
|
||||
|
||||
public static Version getServerVersion() {
|
||||
return serverVersion != null ? serverVersion : getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the configuration class for PlaceholderAPI.
|
||||
*
|
||||
* @return PlaceholderAPIConfig instance
|
||||
*/
|
||||
public PlaceholderAPIConfig getPlaceholderAPIConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public ExpansionManager getExpansionManager() {
|
||||
return expansionManager;
|
||||
}
|
||||
|
||||
public ExpansionCloudManager getExpansionCloud() {
|
||||
return expansionCloud;
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return TimeUtil.getTime((int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - startTime));
|
||||
}
|
||||
|
||||
public long getUptimeMillis() {
|
||||
return (System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
14
src/main/java/me/clip/placeholderapi/PlaceholderHook.java
Normal file
14
src/main/java/me/clip/placeholderapi/PlaceholderHook.java
Normal file
@ -0,0 +1,14 @@
|
||||
package me.clip.placeholderapi;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public abstract class PlaceholderHook {
|
||||
|
||||
/**
|
||||
* called when a placeholder is requested from this PlaceholderHook
|
||||
* @param p Player requesting the placeholder value for, null if not needed for a player
|
||||
* @param params String passed for the placeholder hook to determine what value to return
|
||||
* @return value for the requested player and params
|
||||
*/
|
||||
public abstract String onPlaceholderRequest(Player p, String params);
|
||||
}
|
138
src/main/java/me/clip/placeholderapi/PlaceholderListener.java
Normal file
138
src/main/java/me/clip/placeholderapi/PlaceholderListener.java
Normal file
@ -0,0 +1,138 @@
|
||||
package me.clip.placeholderapi;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.clip.placeholderapi.events.PlaceholderHookUnloadEvent;
|
||||
import me.clip.placeholderapi.expansion.Cacheable;
|
||||
import me.clip.placeholderapi.expansion.Cleanable;
|
||||
import me.clip.placeholderapi.expansion.ExpansionManager;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.expansion.Taskable;
|
||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||
import me.clip.placeholderapi.external.EZPlaceholderHook;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PlaceholderListener implements Listener {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
public PlaceholderListener(PlaceholderAPIPlugin instance) {
|
||||
plugin = instance;
|
||||
Bukkit.getPluginManager().registerEvents(this, instance);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInternalUnload(PlaceholderHookUnloadEvent event) {
|
||||
|
||||
if (event.getHook() instanceof Listener) {
|
||||
HandlerList.unregisterAll((Listener)event.getHook());
|
||||
plugin.getLogger().info("Unregistered event listener for placeholder expansion: " + event.getHookName());
|
||||
}
|
||||
|
||||
if (event.getHook() instanceof Taskable) {
|
||||
plugin.getLogger().info("Cancelling scheduled task for placeholder expansion: " + event.getHookName());
|
||||
((Taskable) event.getHook()).stop();
|
||||
}
|
||||
|
||||
if (event.getHook() instanceof Cacheable) {
|
||||
((Cacheable) event.getHook()).clear();
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud() != null) {
|
||||
|
||||
CloudExpansion ex = plugin.getExpansionCloud().getCloudExpansion(event.getHookName());
|
||||
|
||||
if (ex != null) {
|
||||
ex.setHasExpansion(false);
|
||||
ex.setShouldUpdate(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEnable(PluginEnableEvent event) {
|
||||
ExpansionManager m = plugin.getExpansionManager();
|
||||
PlaceholderExpansion e = m.getCachedExpansion(event.getPlugin().getName().toLowerCase());
|
||||
if (e != null && e.canRegister()) {
|
||||
if (e.isRegistered() || m.registerExpansion(e)) {
|
||||
m.removeCachedExpansion(e.getPlugin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPluginUnload(PluginDisableEvent e) {
|
||||
|
||||
String n = e.getPlugin().getName();
|
||||
|
||||
if (n == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n.equals(plugin.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, PlaceholderHook> hooks = PlaceholderAPI.getPlaceholders();
|
||||
|
||||
for (Entry<String, PlaceholderHook> hook : hooks.entrySet()) {
|
||||
|
||||
PlaceholderHook i = hook.getValue();
|
||||
|
||||
if (i instanceof EZPlaceholderHook) {
|
||||
|
||||
EZPlaceholderHook h = (EZPlaceholderHook) i;
|
||||
|
||||
if (h.getPluginName() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (h.getPluginName().equalsIgnoreCase(n)) {
|
||||
if (PlaceholderAPI.unregisterPlaceholderHook(hook.getKey())) {
|
||||
plugin.getLogger().info("Unregistered placeholder hook for placeholder: " + h.getPlaceholderName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (i instanceof PlaceholderExpansion) {
|
||||
|
||||
PlaceholderExpansion ex = (PlaceholderExpansion) i;
|
||||
|
||||
if (ex.getPlugin() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ex.getPlugin().equalsIgnoreCase(n)) {
|
||||
if (PlaceholderAPI.unregisterPlaceholderHook(hook.getKey())) {
|
||||
plugin.getLogger().info("Unregistered placeholder expansion: " + ex.getIdentifier());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent e) {
|
||||
|
||||
Map<String, PlaceholderHook> placeholders = PlaceholderAPI.getPlaceholders();
|
||||
|
||||
if (placeholders.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (PlaceholderHook hooks : placeholders.values()) {
|
||||
if (hooks instanceof Cleanable) {
|
||||
((Cleanable) hooks).cleanup(e.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
package me.clip.placeholderapi.commands.bukkit;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||
import me.clip.placeholderapi.util.Msg;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ExpansionCloudCommands implements CommandExecutor {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
public ExpansionCloudCommands(PlaceholderAPIPlugin instance) {
|
||||
plugin = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender s, Command c, String label, String[] args) {
|
||||
|
||||
if (args.length == 1) {
|
||||
Msg.msg(s, "&bExpansion cloud commands");
|
||||
Msg.msg(s, " ");
|
||||
Msg.msg(s, "&b/papi ecloud status");
|
||||
Msg.msg(s, "&fView status of the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud list <all/author> (page)");
|
||||
Msg.msg(s, "&fList all/author specific available expansions");
|
||||
Msg.msg(s, "&b/papi ecloud info <expansion name>");
|
||||
Msg.msg(s, "&fView information about a specific expansion available on the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud download <expansion name>");
|
||||
Msg.msg(s, "&fDownload a specific expansion from the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud refresh");
|
||||
Msg.msg(s, "&fFetch the most up to date list of expansions available.");
|
||||
Msg.msg(s, "&b/papi ecloud clear");
|
||||
Msg.msg(s, "&fClear the expansion cloud cache.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("refresh")) {
|
||||
Msg.msg(s, "&aRefresh task started. Use &7/papi ecloud list all &fin a few!!");
|
||||
plugin.getExpansionCloud().clean();
|
||||
plugin.getExpansionCloud().fetch();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud().getCloudExpansions().isEmpty()) {
|
||||
Msg.msg(s, "&7No cloud expansions are available at this time.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("clear")) {
|
||||
plugin.getExpansionCloud().clean();
|
||||
Msg.msg(s, "&aThe cloud cache has been cleared!!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("download")) {
|
||||
|
||||
if (args.length < 3) {
|
||||
Msg.msg(s, "&cAn expansion name must be specified!");
|
||||
return true;
|
||||
}
|
||||
|
||||
CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(args[2]);
|
||||
|
||||
if (expansion == null) {
|
||||
Msg.msg(s, "&cNo expansion found with the name: &f" + args[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
PlaceholderExpansion loaded = plugin.getExpansionManager().getRegisteredExpansion(args[2]);
|
||||
|
||||
if (loaded != null && loaded.isRegistered()) {
|
||||
PlaceholderAPI.unregisterPlaceholderHook(loaded.getIdentifier());
|
||||
}
|
||||
|
||||
Msg.msg(s, "&aAttempting download of expansion &f" + expansion.getName());
|
||||
|
||||
String player = ((s instanceof Player) ? s.getName() : null);
|
||||
|
||||
plugin.getExpansionCloud().downloadExpansion(player, expansion);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("status")) {
|
||||
|
||||
Msg.msg(s, "&bThere are &f" + plugin.getExpansionCloud().getCloudExpansions().size()
|
||||
+ " &bcloud expansions available to download on demand.");
|
||||
Msg.msg(s, "&bA total of &f" + plugin.getExpansionCloud().getCloudAuthorCount()
|
||||
+ " &bauthors have contributed to the expansion cloud.");
|
||||
|
||||
return true;
|
||||
} else if (args[1].equalsIgnoreCase("info")) {
|
||||
|
||||
if (args.length < 3) {
|
||||
Msg.msg(s, "&cAn expansion name must be specified!");
|
||||
return true;
|
||||
}
|
||||
|
||||
CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(args[2]);
|
||||
|
||||
if (expansion == null) {
|
||||
Msg.msg(s, "&cNo expansion found with the name: &f" + args[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
PlaceholderExpansion exp = plugin.getExpansionManager().getRegisteredExpansion(args[2]);
|
||||
|
||||
boolean enabled = false;
|
||||
String version = null;
|
||||
|
||||
if (exp != null) {
|
||||
enabled = exp.isRegistered();
|
||||
version = exp.getVersion();
|
||||
}
|
||||
|
||||
Msg.msg(s, "&aExpansion: &f" + expansion.getName());
|
||||
if (enabled) {
|
||||
Msg.msg(s, "&aThis expansion is currently enabled!");
|
||||
Msg.msg(s, "&bYour version&7: &f" + version);
|
||||
}
|
||||
|
||||
Msg.msg(s, "&bCloud version&7: &f" + expansion.getVersion());
|
||||
Msg.msg(s, "&bAuthor&7: &f" + expansion.getAuthor());
|
||||
|
||||
String desc = expansion.getVersion();
|
||||
|
||||
if (desc.indexOf("\n") > 0) {
|
||||
for (String line : desc.split("\n")) {
|
||||
Msg.msg(s, line);
|
||||
}
|
||||
} else {
|
||||
Msg.msg(s, desc);
|
||||
}
|
||||
|
||||
Msg.msg(s, "&bDownload with &7/papi ecloud download " + expansion.getName());
|
||||
return true;
|
||||
|
||||
} else if (args[1].equalsIgnoreCase("list")) {
|
||||
|
||||
int page = 1;
|
||||
|
||||
String author;
|
||||
|
||||
if (args.length < 3) {
|
||||
Msg.msg(s, "&cIncorrect usage! &7/papi ecloud list <all/author> (page)");
|
||||
return true;
|
||||
}
|
||||
|
||||
author = args[2];
|
||||
|
||||
if (author.equalsIgnoreCase("all")) {
|
||||
author = null;
|
||||
}
|
||||
|
||||
if (args.length >= 4) {
|
||||
try {
|
||||
page = Integer.parseInt(args[3]);
|
||||
} catch (NumberFormatException ex) {
|
||||
Msg.msg(s, "&cPage number must be an integer!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (page < 1) {
|
||||
Msg.msg(s, "&cPage must be greater than or equal to 1!");
|
||||
return true;
|
||||
}
|
||||
|
||||
int avail;
|
||||
|
||||
Map<Integer, CloudExpansion> ex;
|
||||
|
||||
if (author == null) {
|
||||
ex = plugin.getExpansionCloud().getCloudExpansions();
|
||||
} else {
|
||||
ex = plugin.getExpansionCloud().getAllByAuthor(author);
|
||||
}
|
||||
|
||||
if (ex == null) {
|
||||
Msg.msg(s, "&cNo expansions available" + (author != null ? " for author &f" + author : ""));
|
||||
return true;
|
||||
}
|
||||
|
||||
avail = plugin.getExpansionCloud().getPagesAvailable(ex, 10);
|
||||
|
||||
if (page > avail) {
|
||||
Msg.msg(s, "&cThere " + ((avail == 1) ? " is only &f" + avail + " &cpage available!" : "are only &f" + avail + " &cpages available!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Msg.msg(s, "&bExpansion cloud for &f" + (author != null ? author : "all available")+ " &8&m-- &r&bamount&7: &f" + ex.size() + " &bpage&7: &f" + page + "&7/&f" + avail);
|
||||
|
||||
ex = plugin.getExpansionCloud().getPage(ex, page);
|
||||
|
||||
for (Entry<Integer, CloudExpansion> expansion : ex.entrySet()) {
|
||||
Msg.msg(s, "&b" + (expansion.getKey()+1) + "&7: &f" + expansion.getValue().getName() + " &8&m-- &r" + expansion.getValue().getLink());
|
||||
}
|
||||
Msg.msg(s, "&bDownload an expansion with &7/papi ecloud download <name>");
|
||||
Msg.msg(s, "&bView more info on an expansion with &7/papi ecloud info <expansion>");
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
package me.clip.placeholderapi.commands.bukkit;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.util.Msg;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlaceholderAPICommands implements CommandExecutor {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
private ExpansionCloudCommands eCloud;
|
||||
|
||||
|
||||
public PlaceholderAPICommands(PlaceholderAPIPlugin i) {
|
||||
plugin = i;
|
||||
eCloud = new ExpansionCloudCommands(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender s, Command c, String label, String[] args) {
|
||||
|
||||
if (args.length == 0) {
|
||||
Msg.msg(s, "PlaceholderAPI &7version &b&o"+plugin.getDescription().getVersion());
|
||||
Msg.msg(s, "&fCreated by&7: &bextended_clip");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
if (args[0].equalsIgnoreCase("help")) {
|
||||
Msg.msg(s, "PlaceholderAPI &aHelp &e(&f" + plugin.getDescription().getVersion() + "&e)");
|
||||
Msg.msg(s, "&b/papi");
|
||||
Msg.msg(s, "&fView plugin info/version info");
|
||||
Msg.msg(s, "&b/papi list");
|
||||
Msg.msg(s, "&fList all placeholder expansions that are currently active");
|
||||
Msg.msg(s, "&b/papi info <placeholder name>");
|
||||
Msg.msg(s, "&fView information for a specific expansion");
|
||||
Msg.msg(s, "&b/papi parse <...args>");
|
||||
Msg.msg(s, "&fParse a String with placeholders");
|
||||
Msg.msg(s, "&b/papi reload");
|
||||
Msg.msg(s, "&fReload the config settings");
|
||||
|
||||
boolean enabled = plugin.getExpansionCloud() != null;
|
||||
|
||||
|
||||
if (s.isOp()) {
|
||||
if (!enabled) {
|
||||
Msg.msg(s, "&b/papi enablecloud");
|
||||
Msg.msg(s, "&fEnable the expansion cloud");
|
||||
} else {
|
||||
Msg.msg(s, "&b/papi disablecloud");
|
||||
Msg.msg(s, "&fDisable the expansion cloud");
|
||||
Msg.msg(s, "&b/papi ecloud");
|
||||
Msg.msg(s, "&fView information about the PlaceholderAPI expansion cloud");
|
||||
Msg.msg(s, "&b/papi ecloud status");
|
||||
Msg.msg(s, "&fView status of the PlaceholderAPI expansion cloud");
|
||||
Msg.msg(s, "&b/papi ecloud list <all/author> <page>");
|
||||
Msg.msg(s, "&fList all available expansions");
|
||||
Msg.msg(s, "&b/papi ecloud info <expansion name>");
|
||||
Msg.msg(s, "&fView information about a specific expansion on the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud download <expansion name>");
|
||||
Msg.msg(s, "&fDownload a specific expansion from the cloud");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("ecloud")) {
|
||||
if (!s.isOp()) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud() == null) {
|
||||
Msg.msg(s, "&7The expansion cloud is not enabled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
return eCloud.onCommand(s, c, label, args);
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("enablecloud")) {
|
||||
|
||||
if (!s.isOp()) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud() != null) {
|
||||
Msg.msg(s, "&7The cloud is already enabled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.enableCloud();
|
||||
plugin.getPlaceholderAPIConfig().setCloudEnabled(true);
|
||||
Msg.msg(s, "&aThe cloud has been enabled!");
|
||||
return true;
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("disablecloud")) {
|
||||
|
||||
if (!s.isOp()) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud() == null) {
|
||||
Msg.msg(s, "&7The cloud is already disabled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.disableCloud();
|
||||
plugin.getPlaceholderAPIConfig().setCloudEnabled(false);
|
||||
Msg.msg(s, "&aThe cloud has been disabled!");
|
||||
return true;
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("info")) {
|
||||
|
||||
if (!s.hasPermission("placeholderapi.info")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
PlaceholderExpansion ex = plugin.getExpansionManager().getRegisteredExpansion(args[1]);
|
||||
|
||||
if (ex == null) {
|
||||
Msg.msg(s, "&cThere is no expansion loaded with the identifier: &f" + args[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
Msg.msg(s, "&7Placeholder expansion info for: &f%" + ex.getIdentifier() + "_<identifier>%");
|
||||
|
||||
Msg.msg(s, "&7Status: " + (ex.isRegistered() ? "&aRegistered" : "&cNot registered"));
|
||||
|
||||
if (ex.getAuthor() != null) {
|
||||
Msg.msg(s, "&7Created by: &f" + ex.getAuthor());
|
||||
}
|
||||
|
||||
if (ex.getVersion() != null) {
|
||||
Msg.msg(s, "&7Version: &f" + ex.getVersion());
|
||||
}
|
||||
|
||||
if (ex.getDescription() != null) {
|
||||
Msg.msg(s, ex.getDescription());
|
||||
}
|
||||
|
||||
if (ex.getLink() != null) {
|
||||
Msg.msg(s, "&7Link: &f" + ex.getLink());
|
||||
}
|
||||
|
||||
if (ex.getPlugin() != null) {
|
||||
Msg.msg(s, "&7Requires plugin: &f" + ex.getPlugin());
|
||||
}
|
||||
|
||||
if (ex.getPlaceholders() != null) {
|
||||
Msg.msg(s, "&8&m-- &r&7Placeholders &8&m--");
|
||||
for (String placeholder : ex.getPlaceholders()) {
|
||||
Msg.msg(s, placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (args[0].equalsIgnoreCase("parse")) {
|
||||
|
||||
if (!(s instanceof Player)) {
|
||||
Msg.msg(s, "&cThis command can only be used in game!");
|
||||
return true;
|
||||
} else {
|
||||
if (!s.hasPermission("placeholderapi.parse")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Player p = (Player) s;
|
||||
|
||||
String parse = StringUtils.join(args, " ", 1, args.length);
|
||||
|
||||
Msg.msg(s, "&r" + PlaceholderAPI.setPlaceholders(p, parse));
|
||||
|
||||
return true;
|
||||
} else if (args[0].equalsIgnoreCase("reload")) {
|
||||
|
||||
if (s instanceof Player) {
|
||||
if (!s.hasPermission("placeholderapi.reload")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Msg.msg(s, "&cClips &fPlaceholder&7API &bconfiguration reloaded!");
|
||||
|
||||
plugin.reloadConf(s);
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("list")) {
|
||||
|
||||
if (s instanceof Player) {
|
||||
if (!s.hasPermission("placeholderapi.list")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> registered = PlaceholderAPI.getRegisteredIdentifiers();
|
||||
|
||||
if (registered.isEmpty()) {
|
||||
Msg.msg(s, "&7There are no placeholder hooks currently registered!");
|
||||
return true;
|
||||
}
|
||||
Msg.msg(s, registered.size()+" &7Placeholder hooks registered:");
|
||||
Msg.msg(s, registered.toString());
|
||||
} else {
|
||||
Msg.msg(s, "&cIncorrect usage! &7/papi help");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,301 @@
|
||||
package me.clip.placeholderapi.commands.spigot;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||
import me.clip.placeholderapi.util.Msg;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ExpansionCloudCommands implements CommandExecutor {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
public ExpansionCloudCommands(PlaceholderAPIPlugin instance) {
|
||||
plugin = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender s, Command c, String label, String[] args) {
|
||||
|
||||
if (args.length == 1) {
|
||||
Msg.msg(s, "&bExpansion cloud commands");
|
||||
Msg.msg(s, " ");
|
||||
Msg.msg(s, "&b/papi ecloud status");
|
||||
Msg.msg(s, "&fView status of the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud list <all/author> (page)");
|
||||
Msg.msg(s, "&fList all/author specific available expansions");
|
||||
Msg.msg(s, "&b/papi ecloud info <expansion name>");
|
||||
Msg.msg(s, "&fView information about a specific expansion available on the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud download <expansion name>");
|
||||
Msg.msg(s, "&fDownload a specific expansion from the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud refresh");
|
||||
Msg.msg(s, "&fFetch the most up to date list of expansions available.");
|
||||
Msg.msg(s, "&b/papi ecloud clear");
|
||||
Msg.msg(s, "&fClear the expansion cloud cache.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("refresh") || args[1].equalsIgnoreCase("update") || args[1].equalsIgnoreCase("fetch")) {
|
||||
Msg.msg(s, "&aRefresh task started. Use &f/papi ecloud list all &ain a few!!");
|
||||
plugin.getExpansionCloud().clean();
|
||||
plugin.getExpansionCloud().fetch();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud().getCloudExpansions().isEmpty()) {
|
||||
Msg.msg(s, "&7No cloud expansions are available at this time.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("clear")) {
|
||||
plugin.getExpansionCloud().clean();
|
||||
Msg.msg(s, "&aThe cloud cache has been cleared!!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("status")) {
|
||||
|
||||
Msg.msg(s, "&bThere are &f" + plugin.getExpansionCloud().getCloudExpansions().size() + " &bexpansions available on the cloud.");
|
||||
Msg.msg(s, "&7A total of &f" + plugin.getExpansionCloud().getCloudAuthorCount()
|
||||
+ " &7authors have contributed to the expansion cloud.");
|
||||
if (plugin.getExpansionCloud().getToUpdateCount() > 0) {
|
||||
Msg.msg(s, "&eYou have &f" + plugin.getExpansionCloud().getToUpdateCount()
|
||||
+ " &eexpansions installed that have updates available.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("info")) {
|
||||
|
||||
if (args.length < 3) {
|
||||
Msg.msg(s, "&cAn expansion name must be specified!");
|
||||
return true;
|
||||
}
|
||||
|
||||
CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(args[2]);
|
||||
|
||||
if (expansion == null) {
|
||||
Msg.msg(s, "&cNo expansion found with the name: &f" + args[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(s instanceof Player)) {
|
||||
Msg.msg(s, (expansion.shouldUpdate() ? "&e" : "") + expansion.getName() + " &8&m-- &r" + expansion.getLink());
|
||||
return true;
|
||||
}
|
||||
|
||||
Player p = (Player) s;
|
||||
|
||||
Msg.msg(s, "&bCloud expansion info for&7:" + (expansion.shouldUpdate() ? "&6" : (expansion.hasExpansion() ? "&e" : "")) + expansion.getName());
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(expansion.getDescription());
|
||||
|
||||
if (expansion.getReleaseNotes() != null) {
|
||||
sb.append("\n\n" + expansion.getReleaseNotes());
|
||||
}
|
||||
|
||||
String hover = ChatColor.translateAlternateColorCodes('&', sb.toString());
|
||||
|
||||
if (expansion.hasExpansion()) {
|
||||
if (expansion.shouldUpdate()) {
|
||||
Msg.msg(s, "&6You have this expansion but there is a newer version available.");
|
||||
} else {
|
||||
Msg.msg(s, "&aYou have the latest version of this expansion!");
|
||||
}
|
||||
} else {
|
||||
Msg.msg(s, "&7You do not have this expansion installed");
|
||||
}
|
||||
|
||||
sms(p, "&bAuthor&7: &f" + expansion.getAuthor(), hover, null);
|
||||
sms(p, "&bVersion&7: &f" + expansion.getVersion(), hover, null);
|
||||
if (expansion.getLastUpdate() > 1) {
|
||||
sb.append("&bLast updated&7: &f" + expansion.getTimeSinceLastUpdate() + " ago");
|
||||
}
|
||||
sms(p, "&aClick here to download!", hover, expansion.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args[1].equalsIgnoreCase("list")) {
|
||||
|
||||
int page = 1;
|
||||
|
||||
String author;
|
||||
boolean installed = false;
|
||||
|
||||
if (args.length < 3) {
|
||||
Msg.msg(s, "&cIncorrect usage! &7/papi ecloud list <all/author/installed> (page)");
|
||||
return true;
|
||||
}
|
||||
|
||||
author = args[2];
|
||||
|
||||
if (author.equalsIgnoreCase("all")) {
|
||||
author = null;
|
||||
} else if (author.equalsIgnoreCase("installed")) {
|
||||
author = null;
|
||||
installed = true;
|
||||
}
|
||||
|
||||
if (args.length >= 4) {
|
||||
try {
|
||||
page = Integer.parseInt(args[3]);
|
||||
} catch (NumberFormatException ex) {
|
||||
Msg.msg(s, "&cPage number must be an integer!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (page < 1) {
|
||||
Msg.msg(s, "&cPage must be greater than or equal to 1!");
|
||||
return true;
|
||||
}
|
||||
|
||||
int avail;
|
||||
|
||||
Map<Integer, CloudExpansion> ex;
|
||||
|
||||
if (installed) {
|
||||
ex = plugin.getExpansionCloud().getAllInstalled();
|
||||
} else if (author == null) {
|
||||
ex = plugin.getExpansionCloud().getCloudExpansions();
|
||||
} else {
|
||||
ex = plugin.getExpansionCloud().getAllByAuthor(author);
|
||||
}
|
||||
|
||||
if (ex == null || ex.isEmpty()) {
|
||||
Msg.msg(s, "&cNo expansions available" + (author != null ? " for author &f" + author : ""));
|
||||
return true;
|
||||
}
|
||||
|
||||
avail = plugin.getExpansionCloud().getPagesAvailable(ex, 10);
|
||||
|
||||
if (page > avail) {
|
||||
Msg.msg(s, "&cThere " + ((avail == 1) ? " is only &f" + avail + " &cpage available!" : "are only &f" + avail + " &cpages available!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Msg.msg(s, "&bShowing expansions for&7: &f" + (author != null ? author : (installed ? "all installed" : "all available"))+ " &8&m--&r &bamount&7: &f" + ex.size() + " &bpage&7: &f" + page + "&7/&f" + avail);
|
||||
|
||||
ex = plugin.getExpansionCloud().getPage(ex, page);
|
||||
|
||||
if (ex == null) {
|
||||
Msg.msg(s, "&cThere was a problem getting the requested page...");
|
||||
return true;
|
||||
}
|
||||
|
||||
Msg.msg(s, "&aGreen = Expansions you have");
|
||||
Msg.msg(s, "&6Gold = Expansions which need updated");
|
||||
|
||||
if (!(s instanceof Player)) {
|
||||
|
||||
for (Entry<Integer, CloudExpansion> expansion : ex.entrySet()) {
|
||||
if (expansion == null || expansion.getKey() == null || expansion.getValue() == null) continue;
|
||||
Msg.msg(s, "&b" + (expansion.getKey()+1) + "&7: " + (expansion.getValue().shouldUpdate() ? "&6" : (expansion.getValue().hasExpansion() ? "&a" : "&7")) + expansion.getValue().getName() + " &8&m-- &r" + expansion.getValue().getLink());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Player p = (Player) s;
|
||||
|
||||
for (Entry<Integer, CloudExpansion> expansion : ex.entrySet()) {
|
||||
|
||||
if (expansion == null || expansion.getValue() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (expansion.getValue().shouldUpdate()) {
|
||||
sb.append("&6Click to update to the latest version of this expansion\n\n");
|
||||
} else if (!expansion.getValue().hasExpansion()) {
|
||||
sb.append("&bClick to download this expansion\n\n");
|
||||
} else {
|
||||
sb.append("&aYou have the latest version of this expansion\n\n");
|
||||
}
|
||||
sb.append("&bAuthor&7: &f" + expansion.getValue().getAuthor() + "\n");
|
||||
sb.append("&bVersion&7: &f" + expansion.getValue().getVersion() + "\n");
|
||||
if (expansion.getValue().getLastUpdate() > 1) {
|
||||
sb.append("&bLast updated&7: &f" + expansion.getValue().getTimeSinceLastUpdate() + " ago\n");
|
||||
}
|
||||
if (expansion.getValue().getReleaseNotes() != null) {
|
||||
sb.append("&bRelease Notes&7: &f" + expansion.getValue().getReleaseNotes() + "\n");
|
||||
}
|
||||
sb.append("\n" + expansion.getValue().getDescription());
|
||||
|
||||
String msg = ChatColor.translateAlternateColorCodes('&', "&b" + (expansion.getKey()+1) + "&7: " + (expansion.getValue().shouldUpdate() ? "&6" : (expansion.getValue().hasExpansion() ? "&a" : "")) + expansion.getValue().getName());
|
||||
|
||||
String hover = ChatColor.translateAlternateColorCodes('&', sb.toString());
|
||||
|
||||
sms(p, msg, hover, expansion.getValue().getName());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (args[1].equalsIgnoreCase("download")) {
|
||||
|
||||
if (args.length < 3) {
|
||||
Msg.msg(s, "&cAn expansion name must be specified!");
|
||||
return true;
|
||||
}
|
||||
|
||||
CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(args[2]);
|
||||
|
||||
if (expansion == null) {
|
||||
Msg.msg(s, "&cNo expansion found with the name: &f" + args[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expansion.hasExpansion() && !expansion.shouldUpdate()) {
|
||||
Msg.msg(s, "&aYou already have this expansion installed and your version is up to date!");
|
||||
return true;
|
||||
}
|
||||
|
||||
PlaceholderExpansion loaded = plugin.getExpansionManager().getRegisteredExpansion(args[2]);
|
||||
|
||||
if (loaded != null && loaded.isRegistered()) {
|
||||
PlaceholderAPI.unregisterPlaceholderHook(loaded.getIdentifier());
|
||||
}
|
||||
|
||||
Msg.msg(s, "&aAttempting download of expansion &f" + expansion.getName());
|
||||
|
||||
String player = ((s instanceof Player) ? s.getName() : null);
|
||||
|
||||
plugin.getExpansionCloud().downloadExpansion(player, expansion);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Msg.msg(s, "&cIncorrect usage! &b/papi ecloud");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sms(Player p, String text, String hover, String link) {
|
||||
TextComponent message = new TextComponent( ChatColor.translateAlternateColorCodes('&', text) );
|
||||
if (hover != null) {
|
||||
message.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(ChatColor.translateAlternateColorCodes('&', hover)).create() ) );
|
||||
}
|
||||
if (link != null) {
|
||||
message.setClickEvent( new ClickEvent( ClickEvent.Action.SUGGEST_COMMAND, "/papi ecloud download " + link) );
|
||||
}
|
||||
p.spigot().sendMessage( message );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,258 @@
|
||||
package me.clip.placeholderapi.commands.spigot;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.util.Msg;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlaceholderAPICommands implements CommandExecutor {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
private ExpansionCloudCommands eCloud;
|
||||
|
||||
public PlaceholderAPICommands(PlaceholderAPIPlugin i) {
|
||||
plugin = i;
|
||||
eCloud = new ExpansionCloudCommands(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender s, Command c, String label, String[] args) {
|
||||
|
||||
if (args.length == 0) {
|
||||
Msg.msg(s, "PlaceholderAPI &7version &b&o"+plugin.getDescription().getVersion());
|
||||
Msg.msg(s, "&fCreated by&7: &bextended_clip");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
if (args[0].equalsIgnoreCase("help")) {
|
||||
Msg.msg(s, "PlaceholderAPI &aHelp &e(&f" + plugin.getDescription().getVersion() + "&e)");
|
||||
Msg.msg(s, "&b/papi");
|
||||
Msg.msg(s, "&fView plugin info/version info");
|
||||
Msg.msg(s, "&b/papi list");
|
||||
Msg.msg(s, "&fList all placeholder expansions that are currently active");
|
||||
Msg.msg(s, "&b/papi info <placeholder name>");
|
||||
Msg.msg(s, "&fView information for a specific expansion");
|
||||
Msg.msg(s, "&b/papi parse <...args>");
|
||||
Msg.msg(s, "&fParse a String with placeholders");
|
||||
Msg.msg(s, "&b/papi parserel <player one> <player two> <...args>");
|
||||
Msg.msg(s, "&fParse a String with relational placeholders");
|
||||
Msg.msg(s, "&b/papi reload");
|
||||
Msg.msg(s, "&fReload the config settings");
|
||||
|
||||
boolean enabled = plugin.getExpansionCloud() != null;
|
||||
|
||||
|
||||
if (s.isOp()) {
|
||||
if (!enabled) {
|
||||
Msg.msg(s, "&b/papi enablecloud");
|
||||
Msg.msg(s, "&fEnable the expansion cloud");
|
||||
} else {
|
||||
Msg.msg(s, "&b/papi disablecloud");
|
||||
Msg.msg(s, "&fDisable the expansion cloud");
|
||||
Msg.msg(s, "&b/papi ecloud");
|
||||
Msg.msg(s, "&fView information about the PlaceholderAPI expansion cloud");
|
||||
Msg.msg(s, "&b/papi ecloud status");
|
||||
Msg.msg(s, "&fView status of the PlaceholderAPI expansion cloud");
|
||||
Msg.msg(s, "&b/papi ecloud list <all/author> <page>");
|
||||
Msg.msg(s, "&fList all available expansions");
|
||||
Msg.msg(s, "&b/papi ecloud info <expansion name>");
|
||||
Msg.msg(s, "&fView information about a specific expansion on the cloud");
|
||||
Msg.msg(s, "&b/papi ecloud download <expansion name>");
|
||||
Msg.msg(s, "&fDownload a specific expansion from the cloud");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("ecloud")) {
|
||||
if (!s.isOp()) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud() == null) {
|
||||
Msg.msg(s, "&7The expansion cloud is not enabled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
return eCloud.onCommand(s, c, label, args);
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("enablecloud")) {
|
||||
|
||||
if (!s.isOp()) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud() != null) {
|
||||
Msg.msg(s, "&7The cloud is already enabled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.enableCloud();
|
||||
plugin.getPlaceholderAPIConfig().setCloudEnabled(true);
|
||||
Msg.msg(s, "&aThe cloud has been enabled!");
|
||||
return true;
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("disablecloud")) {
|
||||
|
||||
if (!s.isOp()) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin.getExpansionCloud() == null) {
|
||||
Msg.msg(s, "&7The cloud is already disabled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.disableCloud();
|
||||
plugin.getPlaceholderAPIConfig().setCloudEnabled(false);
|
||||
Msg.msg(s, "&aThe cloud has been disabled!");
|
||||
return true;
|
||||
|
||||
} else if (args.length > 1 && args[0].equalsIgnoreCase("info")) {
|
||||
|
||||
if (!s.hasPermission("placeholderapi.info")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
PlaceholderExpansion ex = plugin.getExpansionManager().getRegisteredExpansion(args[1]);
|
||||
|
||||
if (ex == null) {
|
||||
Msg.msg(s, "&cThere is no expansion loaded with the identifier: &f" + args[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
Msg.msg(s, "&7Placeholder expansion info for: &f%" + ex.getIdentifier() + "_<identifier>%");
|
||||
|
||||
Msg.msg(s, "&7Status: " + (ex.isRegistered() ? "&aRegistered" : "&cNot registered"));
|
||||
|
||||
if (ex.getAuthor() != null) {
|
||||
Msg.msg(s, "&7Created by: &f" + ex.getAuthor());
|
||||
}
|
||||
|
||||
if (ex.getVersion() != null) {
|
||||
Msg.msg(s, "&7Version: &f" + ex.getVersion());
|
||||
}
|
||||
|
||||
if (ex.getDescription() != null) {
|
||||
Msg.msg(s, ex.getDescription());
|
||||
}
|
||||
|
||||
if (ex.getLink() != null) {
|
||||
Msg.msg(s, "&7Link: &f" + ex.getLink());
|
||||
}
|
||||
|
||||
if (ex.getPlugin() != null) {
|
||||
Msg.msg(s, "&7Requires plugin: &f" + ex.getPlugin());
|
||||
}
|
||||
|
||||
if (ex.getPlaceholders() != null) {
|
||||
Msg.msg(s, "&8&m-- &r&7Placeholders &8&m--");
|
||||
for (String placeholder : ex.getPlaceholders()) {
|
||||
Msg.msg(s, placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (args.length > 1 && args[0].equalsIgnoreCase("parse")) {
|
||||
|
||||
if (!(s instanceof Player)) {
|
||||
Msg.msg(s, "&cThis command can only be used in game!");
|
||||
return true;
|
||||
} else {
|
||||
if (!s.hasPermission("placeholderapi.parse")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Player p = (Player) s;
|
||||
|
||||
String parse = StringUtils.join(args, " ", 1, args.length);
|
||||
|
||||
Msg.msg(s, "&r" + PlaceholderAPI.setPlaceholders(p, parse));
|
||||
|
||||
return true;
|
||||
} else if (args.length > 3 && args[0].equalsIgnoreCase("parserel")) {
|
||||
|
||||
if (!(s instanceof Player)) {
|
||||
Msg.msg(s, "&cThis command can only be used in game!");
|
||||
return true;
|
||||
} else {
|
||||
if (!s.hasPermission("placeholderapi.parse")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Player one = Bukkit.getPlayer(args[1]);
|
||||
if (one == null) {
|
||||
Msg.msg(s, args[1] + " &cis not online!");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player two = Bukkit.getPlayer(args[2]);
|
||||
|
||||
if (two == null) {
|
||||
Msg.msg(s, args[2] + " &cis not online!");
|
||||
return true;
|
||||
}
|
||||
|
||||
String parse = StringUtils.join(args, " ", 3, args.length);
|
||||
|
||||
Msg.msg(s, "&r" + PlaceholderAPI.setRelationalPlaceholders(one, two, parse));
|
||||
|
||||
return true;
|
||||
} else if (args[0].equalsIgnoreCase("reload")) {
|
||||
|
||||
if (s instanceof Player) {
|
||||
if (!s.hasPermission("placeholderapi.reload")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Msg.msg(s, "&fPlaceholder&7API &bconfiguration reloaded!");
|
||||
|
||||
plugin.reloadConf(s);
|
||||
|
||||
} else if (args[0].equalsIgnoreCase("list")) {
|
||||
|
||||
if (s instanceof Player) {
|
||||
if (!s.hasPermission("placeholderapi.list")) {
|
||||
Msg.msg(s, "&cYou don't have permission to do that!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> registered = PlaceholderAPI.getRegisteredIdentifiers();
|
||||
|
||||
if (registered.isEmpty()) {
|
||||
Msg.msg(s, "&7There are no placeholder hooks currently registered!");
|
||||
return true;
|
||||
}
|
||||
Msg.msg(s, registered.size()+" &7Placeholder hooks registered:");
|
||||
Msg.msg(s, registered.toString());
|
||||
} else {
|
||||
Msg.msg(s, "&cIncorrect usage! &7/papi help");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package me.clip.placeholderapi.configuration;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class PlaceholderAPIConfig {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
public PlaceholderAPIConfig(PlaceholderAPIPlugin i) {
|
||||
plugin = i;
|
||||
}
|
||||
|
||||
public void loadDefConfig() {
|
||||
|
||||
FileConfiguration c = plugin.getConfig();
|
||||
|
||||
c.options().header("PlaceholderAPI version "+plugin.getDescription().getVersion()+""
|
||||
+ "\nCreated by extended_clip"
|
||||
+ "\n"
|
||||
+ "\nNo placeholders are provided with this plugin."
|
||||
+ "\nDownload placeholders with /papi ecloud"
|
||||
+ "\nExample:"
|
||||
+ "\n/papi ecloud refresh"
|
||||
+ "\n/papi ecloud list all"
|
||||
+ "\n/papi ecloud list all 2"
|
||||
+ "\n/papi ecloud download Player"
|
||||
+ "\n/papi ecloud download Vault"
|
||||
+ "\n/papi reload");
|
||||
|
||||
c.set("auto_install_expansions", null);
|
||||
c.set("cloud_enable_unverified_expansions", null);
|
||||
c.addDefault("check_updates", true);
|
||||
c.addDefault("cloud_enabled", true);
|
||||
c.addDefault("cloud_allow_unverified_expansions", false);
|
||||
c.addDefault("boolean.true", "yes");
|
||||
c.addDefault("boolean.false", "no");
|
||||
c.addDefault("date_format", "MM/dd/yy HH:mm:ss");
|
||||
c.options().copyDefaults(true);
|
||||
plugin.saveConfig();
|
||||
plugin.reloadConfig();
|
||||
}
|
||||
|
||||
public boolean checkUpdates() {
|
||||
return plugin.getConfig().getBoolean("check_updates");
|
||||
}
|
||||
|
||||
public boolean cloudAllowUnverifiedExpansions() {
|
||||
return plugin.getConfig().getBoolean("cloud_allow_unverified_expansions");
|
||||
}
|
||||
|
||||
public boolean isCloudEnabled() {
|
||||
return plugin.getConfig().getBoolean("cloud_enabled");
|
||||
}
|
||||
|
||||
public void setCloudEnabled(boolean b) {
|
||||
plugin.getConfig().set("cloud_enabled", b);
|
||||
plugin.saveConfig();
|
||||
plugin.reloadConfig();
|
||||
}
|
||||
|
||||
public String booleanTrue() {
|
||||
return plugin.getConfig().getString("boolean.true");
|
||||
}
|
||||
|
||||
public String booleanFalse() {
|
||||
return plugin.getConfig().getString("boolean.false");
|
||||
}
|
||||
|
||||
public String dateFormat() {
|
||||
return plugin.getConfig().getString("date_format");
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package me.clip.placeholderapi.events;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderHook;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class PlaceholderHookUnloadEvent extends Event {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private String plugin;
|
||||
private PlaceholderHook hook;
|
||||
|
||||
public PlaceholderHookUnloadEvent(String plugin, PlaceholderHook placeholderHook) {
|
||||
this.plugin = plugin;
|
||||
this.hook = placeholderHook;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public String getHookName() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public PlaceholderHook getHook() {
|
||||
return hook;
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
/**
|
||||
* This interface allows a class which extends a {@link PlaceholderExpansion}
|
||||
* to have the clear method called when the implementing expansion is unregistered
|
||||
* from PlaceholderAPI.
|
||||
* This is useful if we want to do things when the implementing hook is unregistered
|
||||
* @author Ryan McCarthy
|
||||
*
|
||||
*/
|
||||
public interface Cacheable {
|
||||
|
||||
/**
|
||||
* Called when the implementing class is unregistered from PlaceholderAPI
|
||||
*/
|
||||
void clear();
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* This interface allows a class which extends a {@link PlaceholderExpansion}
|
||||
* to have the cleanup method called every time a player leaves the server.
|
||||
* This is useful if we want to clean up after the player
|
||||
* @author Ryan McCarthy
|
||||
*
|
||||
*/
|
||||
public interface Cleanable {
|
||||
|
||||
/**
|
||||
* Called when a player leaves the server
|
||||
* @param p (@link Player} who left the server
|
||||
*/
|
||||
void cleanup(Player p);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Any {@link PlaceholderExpansion} class which implements configurable will
|
||||
* have any options listed in the getDefaults map automatically added to the PlaceholderAPI config.yml file
|
||||
* @author Ryan McCarthy
|
||||
*
|
||||
*/
|
||||
public interface Configurable {
|
||||
|
||||
/**
|
||||
* This method will be called before the implementing class is registered
|
||||
* to obtain a map of configuration options that the implementing class needs
|
||||
* These paths and values will be added to the PlaceholderAPI config.yml in the configuration section
|
||||
* expansions.(placeholder identifier).(your key): (your value)
|
||||
* @return Map of config path / values which need to be added / removed from the PlaceholderAPI config.yml file
|
||||
*/
|
||||
Map<String, Object> getDefaults();
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderHook;
|
||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||
import me.clip.placeholderapi.util.FileUtil;
|
||||
|
||||
public final class ExpansionManager {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
private final Map<String, PlaceholderExpansion> cache = new HashMap<>();
|
||||
|
||||
public ExpansionManager(PlaceholderAPIPlugin instance) {
|
||||
plugin = instance;
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public PlaceholderExpansion getCachedExpansion(String plugin) {
|
||||
return cache.getOrDefault(plugin, null);
|
||||
}
|
||||
|
||||
public boolean removeCachedExpansion(String identifier) {
|
||||
return cache.remove(identifier) != null;
|
||||
}
|
||||
|
||||
public PlaceholderExpansion getRegisteredExpansion(String name) {
|
||||
for (Entry<String, PlaceholderHook> hook : PlaceholderAPI.getPlaceholders().entrySet()) {
|
||||
if (hook.getValue() instanceof PlaceholderExpansion) {
|
||||
if (name.equalsIgnoreCase(hook.getKey())) {
|
||||
return (PlaceholderExpansion) hook.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean registerExpansion(PlaceholderExpansion c) {
|
||||
|
||||
if (c == null || c.getIdentifier() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c instanceof Configurable) {
|
||||
|
||||
Map<String, Object> defaults = ((Configurable) c).getDefaults();
|
||||
|
||||
String pre = "expansions." + c.getIdentifier() + ".";
|
||||
|
||||
if (defaults != null && !defaults.isEmpty()) {
|
||||
|
||||
FileConfiguration cfg = plugin.getConfig();
|
||||
|
||||
boolean save = false;
|
||||
|
||||
for (Entry<String, Object> entries : defaults.entrySet()) {
|
||||
if (entries.getKey() == null || entries.getKey().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entries.getValue() == null) {
|
||||
if (cfg.contains(pre + entries.getKey())) {
|
||||
save = true;
|
||||
cfg.set(pre + entries.getKey(), null);
|
||||
}
|
||||
} else {
|
||||
if (!cfg.contains(pre + entries.getKey())) {
|
||||
save = true;
|
||||
cfg.set(pre + entries.getKey(), entries.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (save) {
|
||||
plugin.saveConfig();
|
||||
plugin.reloadConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c instanceof VersionSpecific) {
|
||||
VersionSpecific nms = (VersionSpecific) c;
|
||||
if (!nms.isCompatibleWith(PlaceholderAPIPlugin.getServerVersion())) {
|
||||
plugin.getLogger().info("Your server version is not compatible with expansion: " + c.getIdentifier()
|
||||
+ " version: " + c.getVersion());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!c.canRegister()) {
|
||||
if (c.getPlugin() != null) {
|
||||
cache.put(c.getPlugin().toLowerCase(), c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!c.register()) {
|
||||
if (c.getPlugin() != null) {
|
||||
cache.put(c.getPlugin().toLowerCase(), c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c instanceof Listener) {
|
||||
Listener l = (Listener) c;
|
||||
Bukkit.getPluginManager().registerEvents(l, plugin);
|
||||
plugin.getLogger().info("Registered event listener for expansion: " + c.getIdentifier());
|
||||
}
|
||||
|
||||
plugin.getLogger().info("Successfully registered expansion: " + c.getIdentifier());
|
||||
|
||||
if (c instanceof Taskable) {
|
||||
((Taskable) c).start();
|
||||
plugin.getLogger().info("Started scheduled task for expansion: " + c.getIdentifier());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void registerAllExpansions() {
|
||||
|
||||
if (plugin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Class<?>> subs = FileUtil.getClasses("expansions", PlaceholderExpansion.class);
|
||||
|
||||
if (subs == null || subs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Class<?> klass : subs) {
|
||||
|
||||
if (klass == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
PlaceholderExpansion ex = null;
|
||||
|
||||
Constructor<?>[] c = klass.getConstructors();
|
||||
|
||||
if (c.length == 0) {
|
||||
ex = (PlaceholderExpansion) klass.newInstance();
|
||||
} else {
|
||||
for (Constructor<?> con : c) {
|
||||
if (con.getParameterTypes().length == 0) {
|
||||
ex = (PlaceholderExpansion) klass.newInstance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ex == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (registerExpansion(ex)) {
|
||||
if (plugin.getExpansionCloud() != null) {
|
||||
CloudExpansion ce = plugin.getExpansionCloud().getCloudExpansion(ex.getIdentifier());
|
||||
if (ce != null) {
|
||||
ce.setHasExpansion(true);
|
||||
if (!ce.getVersion().equals(ex.getVersion())) {
|
||||
ce.setShouldUpdate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
plugin.getLogger().severe("Failed to load placeholder expansion from class: " + klass.getName());
|
||||
plugin.getLogger().severe(t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
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");
|
||||
|
||||
private String version;
|
||||
|
||||
NMSVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public static NMSVersion getVersion(String version) {
|
||||
for (NMSVersion v : values()) {
|
||||
if (v.getVersion().equalsIgnoreCase(version)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return NMSVersion.UNKNOWN;
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.PlaceholderHook;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
public abstract class PlaceholderExpansion extends PlaceholderHook {
|
||||
|
||||
/**
|
||||
* The name of this expansion
|
||||
* @return identifier used for expansion if no name present
|
||||
*/
|
||||
public String getName() {
|
||||
return getIdentifier();
|
||||
}
|
||||
/**
|
||||
* Get the identifier that this placeholder expansion uses to be passed placeholder requests
|
||||
* @return placeholder identifier that is associated with this class
|
||||
*/
|
||||
public abstract String getIdentifier();
|
||||
|
||||
/**
|
||||
* Get the plugin that this expansion hooks into.
|
||||
* This will ensure the expansion is added to a cache if canRegister() returns false
|
||||
* get.
|
||||
* The expansion will be removed from the cache
|
||||
* once a plugin loads with the name that is here and the expansion is registered
|
||||
* @return placeholder identifier that is associated with this class
|
||||
*/
|
||||
public abstract String getPlugin();
|
||||
|
||||
/**
|
||||
* Get the author of this PlaceholderExpansion
|
||||
* @return name of the author for this expansion
|
||||
*/
|
||||
public abstract String getAuthor();
|
||||
|
||||
/**
|
||||
* Get the version of this PlaceholderExpansion
|
||||
* @return current version of this expansion
|
||||
*/
|
||||
public abstract String getVersion();
|
||||
|
||||
/**
|
||||
* Check if a placeholder has already been registered with this identifier
|
||||
* @return true if the identifier for this expansion has already been registered
|
||||
*/
|
||||
public boolean isRegistered() {
|
||||
Validate.notNull(getIdentifier(), "Placeholder identifier can not be null!");
|
||||
return PlaceholderAPI.getRegisteredIdentifiers().contains(getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* If any requirements are required to be checked before this hook can register, add them here
|
||||
* @return true if this hook meets all the requirements to register
|
||||
*/
|
||||
public boolean canRegister() {
|
||||
return getPlugin() == null || Bukkit.getPluginManager().getPlugin(getPlugin()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to register this PlaceholderExpansion with PlaceholderAPI
|
||||
* @return true if this class and identifier have been successfully registered with PlaceholderAPI
|
||||
*/
|
||||
public boolean register() {
|
||||
Validate.notNull(getIdentifier(), "Placeholder identifier can not be null!");
|
||||
return PlaceholderAPI.registerPlaceholderHook(getIdentifier(), this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Quick getter for the {@link PlaceholderAPIPlugin} instance
|
||||
* @return {@link PlaceholderAPIPlugin} instance
|
||||
*/
|
||||
public PlaceholderAPIPlugin getPlaceholderAPI() {
|
||||
return PlaceholderAPIPlugin.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* A short description of this expansion
|
||||
* @return null if no description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The url link to this expansion page
|
||||
* @return null if no link
|
||||
*/
|
||||
public String getLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of all valid placeholders
|
||||
* @return null if you dont care
|
||||
*/
|
||||
public List<String> getPlaceholders() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getString(String path, String def) {
|
||||
return getPlaceholderAPI().getConfig().getString("expansions." + getIdentifier() + "." + path, def);
|
||||
}
|
||||
|
||||
public int getInt(String path, int def) {
|
||||
return getPlaceholderAPI().getConfig().getInt("expansions." + getIdentifier() + "." + path, def);
|
||||
}
|
||||
|
||||
public long getLong(String path, long def) {
|
||||
return getPlaceholderAPI().getConfig().getLong("expansions." + getIdentifier() + "." + path, def);
|
||||
}
|
||||
|
||||
public double getDouble(String path, double def) {
|
||||
return getPlaceholderAPI().getConfig().getDouble("expansions." + getIdentifier() + "." + path, def);
|
||||
}
|
||||
|
||||
public List<String> getStringList(String path) {
|
||||
return getPlaceholderAPI().getConfig().getStringList("expansions." + getIdentifier() + "." + path);
|
||||
}
|
||||
|
||||
public Object get(String path, Object def) {
|
||||
return getPlaceholderAPI().getConfig().get("expansions." + getIdentifier() + "." + path, def);
|
||||
}
|
||||
|
||||
public ConfigurationSection getConfigSection(String path) {
|
||||
return getPlaceholderAPI().getConfig().getConfigurationSection("expansions." + getIdentifier() + "." + path);
|
||||
}
|
||||
|
||||
public ConfigurationSection getConfigSection() {
|
||||
return getPlaceholderAPI().getConfig().getConfigurationSection("expansions." + getIdentifier());
|
||||
}
|
||||
|
||||
public boolean configurationContains(String path) {
|
||||
return getPlaceholderAPI().getConfig().contains("expansions." + getIdentifier() + "." + path);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface Relational {
|
||||
String onPlaceholderRequest(Player one, Player two, String identifier);
|
||||
}
|
17
src/main/java/me/clip/placeholderapi/expansion/Taskable.java
Normal file
17
src/main/java/me/clip/placeholderapi/expansion/Taskable.java
Normal file
@ -0,0 +1,17 @@
|
||||
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
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Called when the implementing class has been unregistered from PlaceholderAPI
|
||||
* Tasks that need to be performed when this expansion has unregistered should go here
|
||||
*/
|
||||
void stop();
|
||||
}
|
21
src/main/java/me/clip/placeholderapi/expansion/Version.java
Normal file
21
src/main/java/me/clip/placeholderapi/expansion/Version.java
Normal file
@ -0,0 +1,21 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
public class Version {
|
||||
|
||||
private boolean isSpigot;
|
||||
|
||||
private String version;
|
||||
|
||||
public Version(String version, boolean isSpigot) {
|
||||
this.version = version;
|
||||
this.isSpigot = isSpigot;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version == null ? "unknown" : version;
|
||||
}
|
||||
|
||||
public boolean isSpigot() {
|
||||
return isSpigot;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package me.clip.placeholderapi.expansion;
|
||||
|
||||
/**
|
||||
* Placeholder expansions which use NMS code should be version specific.
|
||||
* Implementing this class allows you to perform checks based on the version the server is running.
|
||||
* The isCompatibleWith method will be passed the server version and allow you to return if your expansion is compatible with that version.
|
||||
* @author Ryan McCarthy
|
||||
*
|
||||
*/
|
||||
public interface VersionSpecific {
|
||||
|
||||
/**
|
||||
* This method is called before the expansion is attempted to be registered
|
||||
* The server version will be passed to this method so you know what version the server is currently running.
|
||||
*
|
||||
* @return true if your expansion is compatible with the version the server is running.
|
||||
*/
|
||||
boolean isCompatibleWith(Version v);
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package me.clip.placeholderapi.expansion.cloud;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import me.clip.placeholderapi.util.TimeUtil;
|
||||
|
||||
|
||||
public class CloudExpansion {
|
||||
|
||||
private String name, author, version, description, link, releaseNotes;
|
||||
|
||||
private boolean hasExpansion, shouldUpdate;
|
||||
|
||||
private long lastUpdate;
|
||||
|
||||
public CloudExpansion(String name, String author, String version, String description, String link) {
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
this.version = version;
|
||||
this.description = description;
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public boolean hasExpansion() {
|
||||
return hasExpansion;
|
||||
}
|
||||
|
||||
public void setHasExpansion(boolean hasExpansion) {
|
||||
this.hasExpansion = hasExpansion;
|
||||
}
|
||||
|
||||
public boolean shouldUpdate() {
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
public void setShouldUpdate(boolean shouldUpdate) {
|
||||
this.shouldUpdate = shouldUpdate;
|
||||
}
|
||||
|
||||
public long getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
|
||||
public void setLastUpdate(long lastUpdate) {
|
||||
this.lastUpdate = lastUpdate;
|
||||
}
|
||||
|
||||
public String getReleaseNotes() {
|
||||
return releaseNotes;
|
||||
}
|
||||
|
||||
public void setReleaseNotes(String releaseNotes) {
|
||||
this.releaseNotes = releaseNotes;
|
||||
}
|
||||
|
||||
public String getTimeSinceLastUpdate() {
|
||||
int time = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - getLastUpdate());
|
||||
return TimeUtil.getTime(time);
|
||||
}
|
||||
}
|
@ -0,0 +1,422 @@
|
||||
package me.clip.placeholderapi.expansion.cloud;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.util.Msg;
|
||||
|
||||
public class ExpansionCloudManager {
|
||||
|
||||
private final File dir;
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
private final TreeMap<Integer, CloudExpansion> remote = new TreeMap<>();
|
||||
|
||||
private final List<String> downloading = new ArrayList<>();
|
||||
|
||||
private int toUpdate = 0;
|
||||
|
||||
public ExpansionCloudManager(PlaceholderAPIPlugin instance) {
|
||||
|
||||
plugin = instance;
|
||||
dir = new File(instance.getDataFolder() + File.separator + "expansions");
|
||||
|
||||
if (!dir.exists()) {
|
||||
try {
|
||||
dir.mkdirs();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
remote.clear();
|
||||
toUpdate = 0;
|
||||
downloading.clear();
|
||||
}
|
||||
|
||||
public boolean isDownloading(String expansion) {
|
||||
return downloading.contains(expansion);
|
||||
}
|
||||
|
||||
public Map<Integer, CloudExpansion> getCloudExpansions() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public CloudExpansion getCloudExpansion(String name) {
|
||||
|
||||
for (CloudExpansion ex : remote.values()) {
|
||||
if (ex.getName().equalsIgnoreCase(name)) {
|
||||
return ex;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getCloudAuthorCount() {
|
||||
|
||||
if (remote == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<String> temp = new ArrayList<>();
|
||||
|
||||
for (CloudExpansion ex : remote.values()) {
|
||||
if (!temp.contains(ex.getAuthor())) {
|
||||
temp.add(ex.getAuthor());
|
||||
}
|
||||
}
|
||||
return temp.size();
|
||||
}
|
||||
|
||||
public int getToUpdateCount() {
|
||||
return toUpdate;
|
||||
}
|
||||
|
||||
public void decrementToUpdateCount() {
|
||||
if (toUpdate > 0) {
|
||||
toUpdate--;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Integer, CloudExpansion> getAllByAuthor(String author) {
|
||||
|
||||
if (remote.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TreeMap<Integer, CloudExpansion> byAuthor = new TreeMap<>();
|
||||
boolean first = true;
|
||||
|
||||
for (CloudExpansion ex : remote.values()) {
|
||||
if (ex.getAuthor().equalsIgnoreCase(author)) {
|
||||
if (first) {
|
||||
first = false;
|
||||
byAuthor.put(0, ex);
|
||||
} else {
|
||||
byAuthor.put(byAuthor.lastKey()+1, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (byAuthor.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return byAuthor;
|
||||
}
|
||||
|
||||
public Map<Integer, CloudExpansion> getAllInstalled() {
|
||||
|
||||
if (remote.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TreeMap<Integer, CloudExpansion> has = new TreeMap<>();
|
||||
|
||||
boolean first = true;
|
||||
|
||||
for (CloudExpansion ex : remote.values()) {
|
||||
if (ex.hasExpansion()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
has.put(0, ex);
|
||||
} else {
|
||||
has.put(has.lastKey()+1, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return has;
|
||||
}
|
||||
|
||||
public int getPagesAvailable(Map<Integer, CloudExpansion> map, int amount) {
|
||||
|
||||
if (map == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pages = map.size() > 0 ? 1 : 0;
|
||||
|
||||
if (pages == 0) {
|
||||
return pages;
|
||||
}
|
||||
|
||||
if (map.size() > amount) {
|
||||
|
||||
pages = map.size()/amount;
|
||||
|
||||
if (map.size() % amount > 0) {
|
||||
pages = pages+1;
|
||||
}
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
public Map<Integer, CloudExpansion> getPage(Map<Integer, CloudExpansion> map, int page) {
|
||||
|
||||
if (map == null || map.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (page > getPagesAvailable(map, 10)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int end = 10*page;
|
||||
|
||||
int start = end-10;
|
||||
|
||||
end = end-1;
|
||||
|
||||
int size = map.size();
|
||||
|
||||
if (end > size) {
|
||||
end = size-1;
|
||||
}
|
||||
|
||||
TreeMap<Integer, CloudExpansion> ex = new TreeMap<>();
|
||||
|
||||
for (int i = start ; i <= end ; i++) {
|
||||
ex.put(i, map.get(i));
|
||||
}
|
||||
return ex.isEmpty() ? null : ex;
|
||||
}
|
||||
|
||||
public void fetch() {
|
||||
|
||||
plugin.getLogger().info("Fetching available expansion list...");
|
||||
|
||||
toUpdate = 0;
|
||||
|
||||
new BukkitRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
StringBuilder sb;
|
||||
|
||||
try {
|
||||
|
||||
URL api = new URL("http://api.extendedclip.com/");
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) api.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
|
||||
connection.connect();
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
|
||||
sb = new StringBuilder();
|
||||
|
||||
String line;
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
|
||||
br.close();
|
||||
connection.disconnect();
|
||||
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
String json = sb.toString();
|
||||
JSONParser parser = new JSONParser();
|
||||
Object obj = null;
|
||||
|
||||
try {
|
||||
obj = parser.parse(json);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<CloudExpansion> unsorted = new ArrayList<>();
|
||||
|
||||
if (obj instanceof JSONObject) {
|
||||
|
||||
JSONObject jo = (JSONObject) obj;
|
||||
|
||||
for (Object o : jo.keySet()) {
|
||||
|
||||
JSONObject sub = (JSONObject) jo.get(o);
|
||||
String name = o.toString();
|
||||
String author = (String) sub.get("author");
|
||||
String version = (String) sub.get("version");
|
||||
String link = (String) sub.get("link");
|
||||
String description = (String) sub.get("description");
|
||||
String notes = "";
|
||||
long update = -1;
|
||||
|
||||
if (sub.get("release_notes") != null) {
|
||||
notes = (String) sub.get("release_notes");
|
||||
}
|
||||
|
||||
if (sub.get("last_update") != null) {
|
||||
|
||||
Object u = sub.get("last_update");
|
||||
|
||||
if (u instanceof Long) {
|
||||
update = (long) sub.get("last_update");
|
||||
}
|
||||
}
|
||||
|
||||
CloudExpansion ce = new CloudExpansion(name, author, version, description, link);
|
||||
|
||||
ce.setReleaseNotes(notes);
|
||||
|
||||
ce.setLastUpdate(update);
|
||||
|
||||
PlaceholderExpansion ex = plugin.getExpansionManager().getRegisteredExpansion(name);
|
||||
|
||||
if (ex != null && ex.isRegistered()) {
|
||||
ce.setHasExpansion(true);
|
||||
if (!ex.getVersion().equals(version)) {
|
||||
ce.setShouldUpdate(true);
|
||||
toUpdate++;
|
||||
}
|
||||
}
|
||||
|
||||
unsorted.add(ce);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
unsorted.sort(Comparator.comparing(CloudExpansion::getLastUpdate).reversed());
|
||||
|
||||
for (CloudExpansion e : unsorted) {
|
||||
remote.put(count, e);
|
||||
count++;
|
||||
}
|
||||
|
||||
plugin.getLogger().info(count + " placeholder expansions are available on the cloud.");
|
||||
plugin.getLogger().info(toUpdate + " expansions you use have updates.");
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(plugin);
|
||||
}
|
||||
|
||||
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(dir.getAbsolutePath() + File.separator + "Expansion-" + name + ".jar");
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
int l;
|
||||
|
||||
while ((l = is.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, l);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadExpansion(final String player, final CloudExpansion ex) {
|
||||
|
||||
if (downloading.contains(ex.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ex.getLink() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
downloading.add(ex.getName());
|
||||
|
||||
plugin.getLogger().info("Attempting download of expansion: " + ex.getName() + (player != null ? " by user: " + player : "") + " from url: " + ex.getLink());
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
|
||||
try {
|
||||
|
||||
download(new URL(ex.getLink()), ex.getName());
|
||||
|
||||
plugin.getLogger().info("Download of expansion: " + ex.getName() + " complete!");
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
plugin.getLogger().warning("Failed to download expansion: " + ex.getName() + " from: " + ex.getLink());
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
|
||||
downloading.remove(ex.getName());
|
||||
|
||||
if (player != null) {
|
||||
Player p = Bukkit.getPlayer(player);
|
||||
|
||||
if (p != null) {
|
||||
Msg.msg(p, "&cThere was a problem downloading expansion: &f" + ex.getName());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
|
||||
downloading.remove(ex.getName());
|
||||
|
||||
if (player != null) {
|
||||
|
||||
Player p = Bukkit.getPlayer(player);
|
||||
|
||||
if (p != null) {
|
||||
Msg.msg(p, "&aExpansion &f" + ex.getName() + " &adownload complete!");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package me.clip.placeholderapi.expansion.cloud;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ExpansionComparator implements Comparator<CloudExpansion> {
|
||||
|
||||
private static final int AUTHOR = 0;
|
||||
private static final int LAST = 1;
|
||||
private static final int RATING = 2;
|
||||
private static final int TO_UPDATE = 3;
|
||||
private int compare_mode = LAST;
|
||||
|
||||
public ExpansionComparator() { }
|
||||
|
||||
public ExpansionComparator(int compare_mode) {
|
||||
this.compare_mode = compare_mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(CloudExpansion o1, CloudExpansion o2) {
|
||||
switch (compare_mode) {
|
||||
case LAST:
|
||||
return (int) (o2.getLastUpdate() - o1.getLastUpdate());
|
||||
default:
|
||||
return o1.getAuthor().compareTo(o2.getAuthor());
|
||||
}
|
||||
}
|
||||
}
|
38
src/main/java/me/clip/placeholderapi/external/EZPlaceholderHook.java
vendored
Normal file
38
src/main/java/me/clip/placeholderapi/external/EZPlaceholderHook.java
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package me.clip.placeholderapi.external;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderHook;
|
||||
|
||||
@Deprecated
|
||||
public abstract class EZPlaceholderHook extends PlaceholderHook {
|
||||
|
||||
private String identifier;
|
||||
|
||||
private 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!");
|
||||
this.identifier = identifier;
|
||||
this.plugin = plugin.getName();
|
||||
}
|
||||
|
||||
public boolean isHooked() {
|
||||
return PlaceholderAPI.getRegisteredPlaceholderPlugins().contains(identifier);
|
||||
}
|
||||
|
||||
public boolean hook() {
|
||||
return PlaceholderAPI.registerPlaceholderHook(identifier, this);
|
||||
}
|
||||
|
||||
public String getPlaceholderName() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public String getPluginName() {
|
||||
return plugin;
|
||||
}
|
||||
}
|
666
src/main/java/me/clip/placeholderapi/metrics/Metrics.java
Normal file
666
src/main/java/me/clip/placeholderapi/metrics/Metrics.java
Normal file
@ -0,0 +1,666 @@
|
||||
package me.clip.placeholderapi.metrics;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* bStats collects some data for plugin authors.
|
||||
* Check out https://bStats.org/ to learn more about bStats!
|
||||
*/
|
||||
public class Metrics {
|
||||
|
||||
static {
|
||||
// You can use the property to disable the check in your test environment
|
||||
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
|
||||
// Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
|
||||
final String defaultPackage = new String(
|
||||
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
|
||||
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
|
||||
// We want to make sure nobody just copy & pastes the example and use the wrong package names
|
||||
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
|
||||
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The version of this bStats class
|
||||
public static final int B_STATS_VERSION = 1;
|
||||
|
||||
// The url to which the data is sent
|
||||
private static final String URL = "https://bStats.org/submitData/bukkit";
|
||||
|
||||
// Should failed requests be logged?
|
||||
private static boolean logFailedRequests;
|
||||
|
||||
// The uuid of the server
|
||||
private static String serverUUID;
|
||||
|
||||
// The plugin
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
// A list with all custom charts
|
||||
private final List<CustomChart> charts = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param plugin The plugin which stats should be submitted.
|
||||
*/
|
||||
public Metrics(JavaPlugin plugin) {
|
||||
if (plugin == null) {
|
||||
throw new IllegalArgumentException("Plugin cannot be null!");
|
||||
}
|
||||
this.plugin = plugin;
|
||||
|
||||
// Get the config file
|
||||
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
|
||||
File configFile = new File(bStatsFolder, "config.yml");
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
|
||||
|
||||
// Check if the config file exists
|
||||
if (!config.isSet("serverUuid")) {
|
||||
|
||||
// Add default values
|
||||
config.addDefault("enabled", true);
|
||||
// Every server gets it's unique random id.
|
||||
config.addDefault("serverUuid", UUID.randomUUID().toString());
|
||||
// Should failed request be logged?
|
||||
config.addDefault("logFailedRequests", false);
|
||||
|
||||
// Inform the server owners about bStats
|
||||
config.options().header(
|
||||
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
|
||||
"To honor their work, you should not disable it.\n" +
|
||||
"This has nearly no effect on the server performance!\n" +
|
||||
"Check out https://bStats.org/ to learn more :)"
|
||||
).copyDefaults(true);
|
||||
try {
|
||||
config.save(configFile);
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
|
||||
// Load the data
|
||||
serverUUID = config.getString("serverUuid");
|
||||
logFailedRequests = config.getBoolean("logFailedRequests", false);
|
||||
if (config.getBoolean("enabled", true)) {
|
||||
boolean found = false;
|
||||
// Search for all other bStats Metrics classes to see if we are the first one
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
found = true; // We aren't the first
|
||||
break;
|
||||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
// Register our service
|
||||
Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
|
||||
if (!found) {
|
||||
// We are the first!
|
||||
startSubmitting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom chart.
|
||||
*
|
||||
* @param chart The chart to add.
|
||||
*/
|
||||
public void addCustomChart(CustomChart chart) {
|
||||
if (chart == null) {
|
||||
throw new IllegalArgumentException("Chart cannot be null!");
|
||||
}
|
||||
charts.add(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the Scheduler which submits our data every 30 minutes.
|
||||
*/
|
||||
private void startSubmitting() {
|
||||
final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!plugin.isEnabled()) { // Plugin was disabled
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
|
||||
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
submitData();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1000*60*5, 1000*60*30);
|
||||
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
|
||||
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
|
||||
// WARNING: Just don't do it!
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin specific data.
|
||||
* This method is called using Reflection.
|
||||
*
|
||||
* @return The plugin specific data.
|
||||
*/
|
||||
public JSONObject getPluginData() {
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
String pluginName = plugin.getDescription().getName();
|
||||
String pluginVersion = plugin.getDescription().getVersion();
|
||||
|
||||
data.put("pluginName", pluginName); // Append the name of the plugin
|
||||
data.put("pluginVersion", pluginVersion); // Append the version of the plugin
|
||||
JSONArray customCharts = new JSONArray();
|
||||
for (CustomChart customChart : charts) {
|
||||
// Add the data of the custom charts
|
||||
JSONObject chart = customChart.getRequestJsonObject();
|
||||
if (chart == null) { // If the chart is null, we skip it
|
||||
continue;
|
||||
}
|
||||
customCharts.add(chart);
|
||||
}
|
||||
data.put("customCharts", customCharts);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server specific data.
|
||||
*
|
||||
* @return The server specific data.
|
||||
*/
|
||||
private JSONObject getServerData() {
|
||||
// Minecraft specific data
|
||||
int playerAmount;
|
||||
try {
|
||||
// Around MC 1.8 the return type was changed to a collection from an array,
|
||||
// This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
|
||||
Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
|
||||
playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
|
||||
? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
|
||||
: ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
|
||||
} catch (Exception e) {
|
||||
playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
|
||||
}
|
||||
int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
|
||||
String bukkitVersion = org.bukkit.Bukkit.getVersion();
|
||||
bukkitVersion = bukkitVersion.substring(bukkitVersion.indexOf("MC: ") + 4, bukkitVersion.length() - 1);
|
||||
|
||||
// OS/Java specific data
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
String osName = System.getProperty("os.name");
|
||||
String osArch = System.getProperty("os.arch");
|
||||
String osVersion = System.getProperty("os.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
JSONObject data = new JSONObject();
|
||||
|
||||
data.put("serverUUID", serverUUID);
|
||||
|
||||
data.put("playerAmount", playerAmount);
|
||||
data.put("onlineMode", onlineMode);
|
||||
data.put("bukkitVersion", bukkitVersion);
|
||||
|
||||
data.put("javaVersion", javaVersion);
|
||||
data.put("osName", osName);
|
||||
data.put("osArch", osArch);
|
||||
data.put("osVersion", osVersion);
|
||||
data.put("coreCount", coreCount);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the data and sends it afterwards.
|
||||
*/
|
||||
private void submitData() {
|
||||
final JSONObject data = getServerData();
|
||||
|
||||
JSONArray pluginData = new JSONArray();
|
||||
// Search for all other bStats Metrics classes to get their plugin data
|
||||
for (Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
|
||||
try {
|
||||
service.getField("B_STATS_VERSION"); // Our identifier :)
|
||||
|
||||
for (RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
|
||||
try {
|
||||
pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider()));
|
||||
} catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
|
||||
}
|
||||
} catch (NoSuchFieldException ignored) { }
|
||||
}
|
||||
|
||||
data.put("plugins", pluginData);
|
||||
|
||||
// Create a new thread for the connection to the bStats server
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Send the data
|
||||
sendData(data);
|
||||
} catch (Exception e) {
|
||||
// Something went wrong! :(
|
||||
if (logFailedRequests) {
|
||||
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the data to the bStats server.
|
||||
*
|
||||
* @param data The data to send.
|
||||
* @throws Exception If the request failed.
|
||||
*/
|
||||
private static void sendData(JSONObject data) throws Exception {
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Data cannot be null!");
|
||||
}
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
throw new IllegalAccessException("This method must not be called from the main thread!");
|
||||
}
|
||||
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
|
||||
|
||||
// Compress the data to save bandwidth
|
||||
byte[] compressedData = compress(data.toString());
|
||||
|
||||
// Add headers
|
||||
connection.setRequestMethod("POST");
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
|
||||
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
|
||||
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
|
||||
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
|
||||
|
||||
// Send data
|
||||
connection.setDoOutput(true);
|
||||
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
|
||||
outputStream.write(compressedData);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
connection.getInputStream().close(); // We don't care about the response - Just send our data :)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gzips the given String.
|
||||
*
|
||||
* @param str The string to gzip.
|
||||
* @return The gzipped String.
|
||||
* @throws IOException If the compression failed.
|
||||
*/
|
||||
private static byte[] compress(final String str) throws IOException {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
|
||||
gzip.write(str.getBytes("UTF-8"));
|
||||
gzip.close();
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom chart.
|
||||
*/
|
||||
public static abstract class CustomChart {
|
||||
|
||||
// The id of the chart
|
||||
final String chartId;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
*/
|
||||
CustomChart(String chartId) {
|
||||
if (chartId == null || chartId.isEmpty()) {
|
||||
throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
||||
}
|
||||
this.chartId = chartId;
|
||||
}
|
||||
|
||||
private JSONObject getRequestJsonObject() {
|
||||
JSONObject chart = new JSONObject();
|
||||
chart.put("chartId", chartId);
|
||||
try {
|
||||
JSONObject data = getChartData();
|
||||
if (data == null) {
|
||||
// If the data is null we don't send the chart.
|
||||
return null;
|
||||
}
|
||||
chart.put("data", data);
|
||||
} catch (Throwable t) {
|
||||
if (logFailedRequests) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
protected abstract JSONObject getChartData() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom simple pie.
|
||||
*/
|
||||
public static class SimplePie extends CustomChart {
|
||||
|
||||
private final Callable<String> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public SimplePie(String chartId, Callable<String> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
String value = callable.call();
|
||||
if (value == null || value.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom advanced pie.
|
||||
*/
|
||||
public static class AdvancedPie extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Integer>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom drilldown pie.
|
||||
*/
|
||||
public static class DrilldownPie extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Map<String, Integer>>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Map<String, Integer>> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean reallyAllSkipped = true;
|
||||
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
|
||||
JSONObject value = new JSONObject();
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
|
||||
value.put(valueEntry.getKey(), valueEntry.getValue());
|
||||
allSkipped = false;
|
||||
}
|
||||
if (!allSkipped) {
|
||||
reallyAllSkipped = false;
|
||||
values.put(entryValues.getKey(), value);
|
||||
}
|
||||
}
|
||||
if (reallyAllSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom single line chart.
|
||||
*/
|
||||
public static class SingleLineChart extends CustomChart {
|
||||
|
||||
private final Callable<Integer> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public SingleLineChart(String chartId, Callable<Integer> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
int value = callable.call();
|
||||
if (value == 0) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom multi line chart.
|
||||
*/
|
||||
public static class MultiLineChart extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Integer>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
if (entry.getValue() == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom simple bar chart.
|
||||
*/
|
||||
public static class SimpleBarChart extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, Integer>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, Integer> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
JSONArray categoryValues = new JSONArray();
|
||||
categoryValues.add(entry.getValue());
|
||||
values.put(entry.getKey(), categoryValues);
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom advanced bar chart.
|
||||
*/
|
||||
public static class AdvancedBarChart extends CustomChart {
|
||||
|
||||
private final Callable<Map<String, int[]>> callable;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param chartId The id of the chart.
|
||||
* @param callable The callable which is used to request the chart data.
|
||||
*/
|
||||
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
|
||||
super(chartId);
|
||||
this.callable = callable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONObject getChartData() throws Exception {
|
||||
JSONObject data = new JSONObject();
|
||||
JSONObject values = new JSONObject();
|
||||
Map<String, int[]> map = callable.call();
|
||||
if (map == null || map.isEmpty()) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
boolean allSkipped = true;
|
||||
for (Map.Entry<String, int[]> entry : map.entrySet()) {
|
||||
if (entry.getValue().length == 0) {
|
||||
continue; // Skip this invalid
|
||||
}
|
||||
allSkipped = false;
|
||||
JSONArray categoryValues = new JSONArray();
|
||||
for (int categoryValue : entry.getValue()) {
|
||||
categoryValues.add(categoryValue);
|
||||
}
|
||||
values.put(entry.getKey(), categoryValues);
|
||||
}
|
||||
if (allSkipped) {
|
||||
// Null = skip the chart
|
||||
return null;
|
||||
}
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package me.clip.placeholderapi.updatechecker;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
/**
|
||||
* thanks maxim
|
||||
*/
|
||||
public class UpdateChecker implements Listener {
|
||||
|
||||
private PlaceholderAPIPlugin plugin;
|
||||
|
||||
private final int resourceId = 6245;
|
||||
|
||||
private static String latestVersion = "";
|
||||
|
||||
private static boolean updateAvailable = false;
|
||||
|
||||
public UpdateChecker(PlaceholderAPIPlugin i) {
|
||||
plugin = i;
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
if (checkForUpdate()) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
plugin.getLogger().info("An update for PlaceholderAPI (v" + getLatestVersion() + ") is available at:");
|
||||
plugin.getLogger().info("https://www.spigotmc.org/resources/placeholderapi." + resourceId + "/");
|
||||
register();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
if (e.getPlayer().isOp()) {
|
||||
e.getPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', "&bAn update for &fPlaceholder&7API &e(&fPlaceholder&7API &fv" + getLatestVersion() + "&e)"));
|
||||
e.getPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', "&bis available at &ehttps://www.spigotmc.org/resources/placeholderapi." + resourceId + "/"));
|
||||
}
|
||||
}
|
||||
|
||||
private String getSpigotVersion() {
|
||||
try {
|
||||
HttpsURLConnection con = (HttpsURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=" + resourceId).openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
String version = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine();
|
||||
if (version.length() <= 7) {
|
||||
return version;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
plugin.getLogger().info("Failed to check for a update on spigot.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean checkHigher(String currentVersion, String newVersion) {
|
||||
String current = toReadable(currentVersion);
|
||||
String newVers = toReadable(newVersion);
|
||||
return current.compareTo(newVers) < 0;
|
||||
}
|
||||
|
||||
public boolean checkForUpdate() {
|
||||
String version = getSpigotVersion();
|
||||
if (version != null) {
|
||||
if (checkHigher(plugin.getDescription().getVersion(), version)) {
|
||||
latestVersion = version;
|
||||
updateAvailable = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean updateAvailable() {
|
||||
return updateAvailable;
|
||||
}
|
||||
|
||||
public static String getLatestVersion() {
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
private String toReadable(String version) {
|
||||
String[] split = Pattern.compile(".", Pattern.LITERAL).split(version.replace("v", ""));
|
||||
version = "";
|
||||
for (String s : split) {
|
||||
version += String.format("%4s", s);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
}
|
73
src/main/java/me/clip/placeholderapi/util/FileUtil.java
Normal file
73
src/main/java/me/clip/placeholderapi/util/FileUtil.java
Normal file
@ -0,0 +1,73 @@
|
||||
package me.clip.placeholderapi.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarInputStream;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
|
||||
public class FileUtil {
|
||||
|
||||
public static List<Class<?>> getClasses(String folder, Class<?> type) {
|
||||
List<Class<?>> list = new ArrayList<>();
|
||||
try {
|
||||
File f = new File(PlaceholderAPIPlugin.getInstance().getDataFolder(), folder);
|
||||
if (!f.exists()) {
|
||||
if (!f.mkdir()) {
|
||||
PlaceholderAPIPlugin.getInstance().getLogger().severe("Failed to create " + folder + " folder!");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
FilenameFilter fileNameFilter = (dir, name) -> {
|
||||
int i = name.lastIndexOf('.');
|
||||
return i > 0 && name.substring(i).equals(".jar");
|
||||
};
|
||||
File[] jars = f.listFiles(fileNameFilter);
|
||||
if (jars == null) {
|
||||
return list;
|
||||
}
|
||||
for (File file : jars) {
|
||||
list = gather(file.toURI().toURL(), list, type);
|
||||
}
|
||||
return list;
|
||||
} catch (Throwable t) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<Class<?>> gather(URL jar, List<Class<?>> list, Class<?> clazz) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (name.endsWith(".class")) {
|
||||
name = name.replace("/", ".");
|
||||
String cname = name.substring(0, name.lastIndexOf(".class"));
|
||||
Class<?> c = cl.loadClass(cname);
|
||||
if (clazz.isAssignableFrom(c)) {
|
||||
list.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
cl.close();
|
||||
jis.close();
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
12
src/main/java/me/clip/placeholderapi/util/Msg.java
Normal file
12
src/main/java/me/clip/placeholderapi/util/Msg.java
Normal file
@ -0,0 +1,12 @@
|
||||
package me.clip.placeholderapi.util;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class Msg {
|
||||
|
||||
public static void msg(CommandSender s, String msg) {
|
||||
s.sendMessage(ChatColor.translateAlternateColorCodes('&', msg));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package me.clip.placeholderapi.util;
|
||||
|
||||
public enum TimeFormat {
|
||||
|
||||
DAYS,
|
||||
HOURS,
|
||||
MINUTES,
|
||||
SECONDS
|
||||
}
|
183
src/main/java/me/clip/placeholderapi/util/TimeUtil.java
Normal file
183
src/main/java/me/clip/placeholderapi/util/TimeUtil.java
Normal file
@ -0,0 +1,183 @@
|
||||
package me.clip.placeholderapi.util;
|
||||
|
||||
public class TimeUtil {
|
||||
|
||||
public static String getRemaining(int seconds, TimeFormat type) {
|
||||
|
||||
if (seconds < 60) {
|
||||
switch(type) {
|
||||
case DAYS:
|
||||
return "0";
|
||||
case HOURS:
|
||||
return "0";
|
||||
case MINUTES:
|
||||
return "0";
|
||||
case SECONDS:
|
||||
return String.valueOf(seconds);
|
||||
}
|
||||
return String.valueOf(seconds);
|
||||
}
|
||||
|
||||
int minutes = seconds / 60;
|
||||
|
||||
int s = 60 * minutes;
|
||||
|
||||
int secondsLeft = seconds - s;
|
||||
|
||||
if (minutes < 60) {
|
||||
switch(type) {
|
||||
case DAYS:
|
||||
return "0";
|
||||
case HOURS:
|
||||
return "0";
|
||||
case MINUTES:
|
||||
return String.valueOf(minutes);
|
||||
case SECONDS:
|
||||
return String.valueOf(secondsLeft);
|
||||
}
|
||||
return String.valueOf(seconds);
|
||||
}
|
||||
|
||||
if (minutes < 1440) {
|
||||
|
||||
int hours = minutes / 60;
|
||||
|
||||
int inMins = 60 * hours;
|
||||
|
||||
int leftOver = minutes - inMins;
|
||||
|
||||
switch(type) {
|
||||
case DAYS:
|
||||
return "0";
|
||||
case HOURS:
|
||||
return String.valueOf(hours);
|
||||
case MINUTES:
|
||||
return String.valueOf(leftOver);
|
||||
case SECONDS:
|
||||
return String.valueOf(secondsLeft);
|
||||
}
|
||||
return String.valueOf(seconds);
|
||||
}
|
||||
|
||||
int days = minutes / 1440;
|
||||
|
||||
int inMins = 1440 * days;
|
||||
|
||||
int leftOver = minutes - inMins;
|
||||
|
||||
|
||||
if (leftOver < 60) {
|
||||
|
||||
switch (type) {
|
||||
case DAYS:
|
||||
return String.valueOf(days);
|
||||
case HOURS:
|
||||
return String.valueOf(0);
|
||||
case MINUTES:
|
||||
return String.valueOf(leftOver);
|
||||
case SECONDS:
|
||||
return String.valueOf(secondsLeft);
|
||||
}
|
||||
return String.valueOf(seconds);
|
||||
|
||||
} else {
|
||||
|
||||
int hours = leftOver / 60;
|
||||
|
||||
int hoursInMins = 60 * hours;
|
||||
|
||||
int minsLeft = leftOver - hoursInMins;
|
||||
|
||||
switch (type) {
|
||||
case DAYS:
|
||||
return String.valueOf(days);
|
||||
case HOURS:
|
||||
return String.valueOf(hours);
|
||||
case MINUTES:
|
||||
return String.valueOf(minsLeft);
|
||||
case SECONDS:
|
||||
return String.valueOf(secondsLeft);
|
||||
}
|
||||
return String.valueOf(seconds);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTime(int seconds) {
|
||||
|
||||
if (seconds < 60) {
|
||||
return seconds+"s";
|
||||
}
|
||||
|
||||
int minutes = seconds / 60;
|
||||
|
||||
int s = 60 * minutes;
|
||||
|
||||
int secondsLeft = seconds - s;
|
||||
|
||||
if (minutes < 60) {
|
||||
if (secondsLeft > 0) {
|
||||
return String.valueOf(minutes+"m "+secondsLeft+"s");
|
||||
} else {
|
||||
return String.valueOf(minutes+"m");
|
||||
}
|
||||
}
|
||||
|
||||
if (minutes < 1440) {
|
||||
|
||||
String time;
|
||||
|
||||
int hours = minutes / 60;
|
||||
|
||||
time = hours+"h";
|
||||
|
||||
int inMins = 60 * hours;
|
||||
|
||||
int leftOver = minutes - inMins;
|
||||
|
||||
if (leftOver >= 1) {
|
||||
time = time+" "+leftOver+"m";
|
||||
}
|
||||
|
||||
if (secondsLeft > 0) {
|
||||
time = time+" "+secondsLeft+"s";
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
String time;
|
||||
|
||||
int days = minutes / 1440;
|
||||
|
||||
time = days+"d";
|
||||
|
||||
int inMins = 1440 * days;
|
||||
|
||||
int leftOver = minutes - inMins;
|
||||
|
||||
if (leftOver >= 1) {
|
||||
|
||||
if (leftOver < 60) {
|
||||
|
||||
time = time+" "+leftOver+"m";
|
||||
} else {
|
||||
|
||||
int hours = leftOver / 60;
|
||||
|
||||
time = time+" "+hours+"h";
|
||||
|
||||
int hoursInMins = 60 * hours;
|
||||
|
||||
int minsLeft = leftOver - hoursInMins;
|
||||
|
||||
time = time+" "+minsLeft+"m";
|
||||
}
|
||||
}
|
||||
|
||||
if (secondsLeft > 0) {
|
||||
time = time+" "+secondsLeft+"s";
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
}
|
32
src/main/resources/plugin.yml
Normal file
32
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,32 @@
|
||||
name: PlaceholderAPI
|
||||
main: me.clip.placeholderapi.PlaceholderAPIPlugin
|
||||
version: ${pom.version}
|
||||
author: [extended_clip]
|
||||
description: A placeholder provider
|
||||
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.parse: true
|
||||
placeholderapi.injector.chat.bypass: true
|
||||
placeholderapi.injector.signs.bypass: true
|
||||
placeholderapi.injector.anvil.bypass: 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
|
||||
commands:
|
||||
placeholderapi:
|
||||
description: PlaceholderAPI command
|
||||
aliases: [clipsplaceholderapi, papi]
|
Loading…
Reference in New Issue
Block a user