Merge remote-tracking branch 'origin/master'

This commit is contained in:
PiggyPiglet
2020-07-27 15:23:11 +08:00
22 changed files with 750 additions and 478 deletions

View File

@@ -20,180 +20,278 @@
package me.clip.placeholderapi.expansion;
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.OfflinePlayer;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public abstract class PlaceholderExpansion extends PlaceholderHook {
public abstract class PlaceholderExpansion extends PlaceholderHook
{
/**
* The name of this expansion
*
* @return {@link #getIdentifier()} by default, name of this expansion if specified
*/
public String getName() {
return getIdentifier();
}
/**
* The placeholder identifier of this expansion
*
* @return placeholder identifier that is associated with this expansion
*/
@NotNull
public abstract String getIdentifier();
/**
* The placeholder identifier of this expansion
*
* @return placeholder identifier that is associated with this expansion
*/
public abstract String getIdentifier();
/**
* The author of this expansion
*
* @return name of the author for this expansion
*/
@NotNull
public abstract String getAuthor();
/**
* The author of this expansion
*
* @return name of the author for this expansion
*/
public abstract String getAuthor();
/**
* The version of this expansion
*
* @return current version of this expansion
*/
@NotNull
public abstract String getVersion();
/**
* The version of this expansion
*
* @return current version of this expansion
*/
public abstract String getVersion();
/**
* The name of the plugin that this expansion hooks into. by default will return the deprecated
* {@link #getPlugin()} method
*
* @return plugin name that this expansion requires to function
*/
public String getRequiredPlugin() {
return getPlugin();
}
/**
* The placeholders associated with this expansion
*
* @return placeholder list that this expansion provides
*/
public List<String> getPlaceholders() {
return null;
}
/**
* Expansions that do not use the ecloud and instead register from the dependency should set this
* to true to ensure that your placeholder expansion is not unregistered when the papi reload
* command is used
*
* @return if this expansion should persist through placeholder reloads
*/
public boolean persist() {
return false;
}
/**
* Check if this placeholder identifier has already been registered
*
* @return true if the identifier for this expansion is already registered
*/
public boolean isRegistered() {
Validate.notNull(getIdentifier(), "Placeholder identifier can not be null!");
return PlaceholderAPI.isRegistered(getIdentifier());
}
/**
* If any requirements need to be checked before this expansion should register, you can check
* them here
*
* @return true if this hook meets all the requirements to register
*/
public boolean canRegister() {
return getRequiredPlugin() == null || Bukkit.getPluginManager().getPlugin(getRequiredPlugin()) != null;
}
/**
* Attempt to register this PlaceholderExpansion
*
* @return true if this expansion is now registered with PlaceholderAPI
*/
public boolean register() {
Validate.notNull(getIdentifier(), "Placeholder identifier can not be null!");
return canRegister() && getPlaceholderAPI().getLocalExpansionManager().register(this);
}
/**
* Quick getter for the {@link PlaceholderAPIPlugin} instance
*
* @return {@link PlaceholderAPIPlugin} instance
*/
public PlaceholderAPIPlugin getPlaceholderAPI() {
return PlaceholderAPIPlugin.getInstance();
}
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);
}
@Nullable
@Override /* override for now >:) */
public String onRequest(@Nullable final OfflinePlayer player, @NotNull final String params)
{
return super.onRequest(player, params);
}
/**
* @deprecated As of versions greater than 2.8.7, use {@link #getRequiredPlugin()}
*/
@Deprecated
public String getPlugin() {
return null;
}
/**
* The name of this expansion
*
* @return {@link #getIdentifier()} by default, name of this expansion if specified
*/
@NotNull
public String getName()
{
return getIdentifier();
}
/**
* @deprecated As of versions greater than 2.8.7, use the expansion cloud to show a description
*/
@Deprecated
public String getDescription() {
return null;
}
/**
* The name of the plugin that this expansion hooks into. by default will null
*
* @return plugin name that this expansion requires to function
*/
@Nullable
public String getRequiredPlugin()
{
return getPlugin();
}
/**
* The placeholders associated with this expansion
*
* @return placeholder list that this expansion provides
*/
@NotNull
public List<String> getPlaceholders()
{
return Collections.emptyList();
}
/**
* Expansions that do not use the ecloud and instead register from the dependency should set this
* to true to ensure that your placeholder expansion is not unregistered when the papi reload
* command is used
*
* @return if this expansion should persist through placeholder reloads
*/
public boolean persist()
{
return false;
}
/**
* Check if this placeholder identifier has already been registered
*
* @return true if the identifier for this expansion is already registered
*/
public final boolean isRegistered()
{
return getPlaceholderAPI().getLocalExpansionManager().findExpansionByIdentifier(getIdentifier()).map(it -> it.equals(this)).orElse(false);
}
/**
* If any requirements need to be checked before this expansion should register, you can check
* them here
*
* @return true if this hook meets all the requirements to register
*/
public boolean canRegister()
{
return getRequiredPlugin() == null || Bukkit.getPluginManager().getPlugin(getRequiredPlugin()) != null;
}
/**
* Attempt to register this PlaceholderExpansion
*
* @return true if this expansion is now registered with PlaceholderAPI
* @deprecated This is going to be final in the future, startup and shutdown logic will have their own methods soon.
*/
@Deprecated
public boolean register()
{
return canRegister() && getPlaceholderAPI().getLocalExpansionManager().register(this);
}
/**
* Attempt to unregister this PlaceholderExpansion
*
* @return true if this expansion is now unregistered with PlaceholderAPI
*/
public final boolean unregister()
{
return getPlaceholderAPI().getLocalExpansionManager().unregister(this);
}
/**
* Quick getter for the {@link PlaceholderAPIPlugin} instance
*
* @return {@link PlaceholderAPIPlugin} instance
*/
@NotNull
public final PlaceholderAPIPlugin getPlaceholderAPI()
{
return PlaceholderAPIPlugin.getInstance();
}
// === Configuration ===
@Nullable
public final ConfigurationSection getConfigSection()
{
return getPlaceholderAPI().getConfig().getConfigurationSection("expansions." + getIdentifier());
}
@Nullable
public final ConfigurationSection getConfigSection(@NotNull final String path)
{
final ConfigurationSection section = getConfigSection();
return section == null ? null : section.getConfigurationSection(path);
}
@Nullable
@Contract("_, !null -> !null")
public final Object get(@NotNull final String path, final Object def)
{
final ConfigurationSection section = getConfigSection();
return section == null ? def : section.get(path, def);
}
public final int getInt(@NotNull final String path, final int def)
{
final ConfigurationSection section = getConfigSection();
return section == null ? def : section.getInt(path, def);
}
public final long getLong(@NotNull final String path, final long def)
{
final ConfigurationSection section = getConfigSection();
return section == null ? def : section.getLong(path, def);
}
public final double getDouble(@NotNull final String path, final double def)
{
final ConfigurationSection section = getConfigSection();
return section == null ? def : section.getDouble(path, def);
}
@Nullable
@Contract("_, !null -> !null")
public final String getString(@NotNull final String path, @Nullable final String def)
{
final ConfigurationSection section = getConfigSection();
return section == null ? def : section.getString(path, def);
}
@NotNull
public final List<String> getStringList(@NotNull final String path)
{
final ConfigurationSection section = getConfigSection();
return section == null ? Collections.emptyList() : section.getStringList(path);
}
public final boolean configurationContains(@NotNull final String path)
{
final ConfigurationSection section = getConfigSection();
return section != null && section.contains(path);
}
@Override
public final boolean equals(final Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof PlaceholderExpansion))
{
return false;
}
final PlaceholderExpansion expansion = (PlaceholderExpansion) o;
return getIdentifier().equals(expansion.getIdentifier()) &&
getAuthor().equals(expansion.getAuthor()) &&
getVersion().equals(expansion.getVersion());
}
@Override
public final int hashCode()
{
return Objects.hash(getIdentifier(), getAuthor(), getVersion());
}
@Override
public final String toString()
{
return String.format("PlaceholderExpansion[name: '%s', author: '%s', version: '%s']", getName(), getAuthor(), getVersion());
}
// === Deprecated API ===
/**
* @deprecated As of versions greater than 2.8.7, use {@link #getRequiredPlugin()}
*/
@Deprecated
public String getPlugin()
{
return null;
}
/**
* @deprecated As of versions greater than 2.8.7, use the expansion cloud to show a description
*/
@Deprecated
public String getDescription()
{
return null;
}
/**
* @deprecated As of versions greater than 2.8.7, use the expansion cloud to display a link
*/
@Deprecated
public String getLink()
{
return null;
}
/**
* @deprecated As of versions greater than 2.8.7, use the expansion cloud to display a link
*/
@Deprecated
public String getLink() {
return null;
}
}

View File

@@ -28,6 +28,7 @@ import me.clip.placeholderapi.events.ExpansionUnregisterEvent;
import me.clip.placeholderapi.expansion.*;
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
import me.clip.placeholderapi.util.FileUtil;
import me.clip.placeholderapi.util.Futures;
import me.clip.placeholderapi.util.Msg;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -43,8 +44,12 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.logging.Level;
@@ -134,6 +139,27 @@ public final class LocalExpansionManager implements Listener
}
public Optional<PlaceholderExpansion> register(@NotNull final Class<? extends PlaceholderExpansion> clazz)
{
try
{
final PlaceholderExpansion expansion = createExpansionInstance(clazz);
if (expansion == null || !expansion.register())
{
return Optional.empty();
}
return Optional.of(expansion);
}
catch (final LinkageError ex)
{
plugin.getLogger().severe("expansion class " + clazz.getSimpleName() + " is outdated: \n" +
"Failed to load due to a [" + ex.getClass().getSimpleName() + "], attempted to use " + ex.getMessage());
}
return Optional.empty();
}
/**
* Do not call this method yourself, use {@link PlaceholderExpansion#register()}
*/
@@ -198,7 +224,7 @@ public final class LocalExpansionManager implements Listener
}
final PlaceholderExpansion removed = expansions.get(expansion.getIdentifier());
if (removed != null && !unregister(removed))
if (removed != null && !removed.unregister())
{
return false;
}
@@ -238,27 +264,9 @@ public final class LocalExpansionManager implements Listener
return true;
}
public Optional<PlaceholderExpansion> register(@NotNull final Class<? extends PlaceholderExpansion> clazz)
{
try
{
final PlaceholderExpansion expansion = createExpansionInstance(clazz);
if (expansion == null || !expansion.register())
{
return Optional.empty();
}
return Optional.of(expansion);
}
catch (final LinkageError ex)
{
plugin.getLogger().severe("expansion class " + clazz.getSimpleName() + " is outdated: \n" +
"Failed to load due to a [" + ex.getClass().getSimpleName() + "], attempted to use " + ex.getMessage());
}
return Optional.empty();
}
/**
* Do not call this method yourself, use {@link PlaceholderExpansion#unregister()}
*/
public boolean unregister(@NotNull final PlaceholderExpansion expansion)
{
if (expansions.remove(expansion.getIdentifier()) == null)
@@ -301,18 +309,17 @@ public final class LocalExpansionManager implements Listener
{
plugin.getLogger().info("Placeholder expansion registration initializing...");
findExpansionsOnDisk().whenCompleteAsync((classes, exception) -> {
Futures.onMainThread(plugin, findExpansionsOnDisk(), (classes, exception) -> {
if (exception != null)
{
plugin.getLogger().log(Level.SEVERE, "failed to load class files of expansions", exception);
return;
}
Bukkit.getScheduler().runTask(plugin, () -> {
final long registered = classes.stream().map(this::register).filter(Optional::isPresent).count();
Msg.msg(sender,
registered == 0 ? "&6No expansions were registered!" : registered + "&a placeholder hooks successfully registered!");
});
final long registered = classes.stream().map(this::register).filter(Optional::isPresent).count();
Msg.msg(sender,
registered == 0 ? "&6No expansions were registered!" : registered + "&a placeholder hooks successfully registered!");
});
}
@@ -325,39 +332,32 @@ public final class LocalExpansionManager implements Listener
continue;
}
unregister(expansion);
expansion.unregister();
}
}
@NotNull
public CompletableFuture<List<Class<? extends PlaceholderExpansion>>> findExpansionsOnDisk()
public CompletableFuture<@NotNull List<@NotNull Class<? extends PlaceholderExpansion>>> findExpansionsOnDisk()
{
return CompletableFuture.supplyAsync(() -> {
try
{
return FileUtil.getClasses(getExpansionsFolder(), PlaceholderExpansion.class);
}
catch (final IOException | ClassNotFoundException ex)
{
throw new CompletionException(ex);
}
});
return Arrays.stream(folder.listFiles((dir, name) -> name.endsWith(".jar")))
.map(this::findExpansionInFile)
.collect(Futures.collector());
}
@NotNull
public CompletableFuture<List<Class<? extends PlaceholderExpansion>>> findExpansionsInFile(@NotNull final File file)
public CompletableFuture<@Nullable Class<? extends PlaceholderExpansion>> findExpansionInFile(@NotNull final File file)
{
return CompletableFuture.supplyAsync(() -> {
try
{
final List<@NotNull Class<? extends PlaceholderExpansion>> classes = FileUtil.getClasses(getExpansionsFolder(), PlaceholderExpansion.class, file.getName());
if (classes.size() > 1)
{
throw new IllegalStateException("multiple expansion classes in one file!");
}
return classes;
return FileUtil.findClass(file, PlaceholderExpansion.class);
}
catch (final VerifyError ex)
{
plugin.getLogger().severe("expansion file " + file.getName() + " is outdated: \n" +
"Failed to load due to a [" + ex.getClass().getSimpleName() + "], attempted to use" + ex.getMessage().substring(ex.getMessage().lastIndexOf(' ')));
return null;
}
catch (final Exception ex)
{
@@ -376,6 +376,11 @@ public final class LocalExpansionManager implements Listener
}
catch (final Exception ex)
{
if (ex.getCause() instanceof LinkageError)
{
throw ((LinkageError) ex.getCause());
}
plugin.getLogger().log(Level.SEVERE, "Failed to load placeholder expansion from class: " + clazz.getName(), ex);
return null;
}
@@ -412,7 +417,7 @@ public final class LocalExpansionManager implements Listener
continue;
}
unregister(expansion);
expansion.unregister();
plugin.getLogger().info("Unregistered placeholder expansion: " + expansion.getName());
}
}