From f3ba9d588e153874817c83114ac8c58f4dc17834 Mon Sep 17 00:00:00 2001 From: Sxtanna Date: Fri, 24 Jul 2020 14:30:57 -0400 Subject: [PATCH] updated managers to make more sense, removed old --- .../clip/placeholderapi/PlaceholderAPI.java | 124 +----- .../placeholderapi/PlaceholderAPIPlugin.java | 192 +++++---- .../impl/cloud/CommandECloudClear.java | 2 +- .../impl/cloud/CommandECloudDownload.java | 12 +- .../cloud/CommandECloudExpansionInfo.java | 6 +- .../cloud/CommandECloudExpansionList.java | 205 +++++++--- .../CommandECloudExpansionPlaceholders.java | 10 +- .../impl/cloud/CommandECloudRefresh.java | 4 +- .../impl/cloud/CommandECloudStatus.java | 6 +- .../impl/cloud/CommandECloudToggle.java | 11 +- .../impl/local/CommandExpansionRegister.java | 45 +- .../local/CommandExpansionUnregister.java | 9 +- .../commands/impl/local/CommandInfo.java | 3 +- .../expansion/ExpansionManager.java | 255 ------------ .../expansion/PlaceholderExpansion.java | 5 +- .../cloud/ExpansionCloudManager.java | 283 ------------- .../manager/CloudExpansionManager.java | 266 ++++++++++++ .../manager/LocalExpansionManager.java | 385 ++++++++++++++++++ .../listeners/PlaceholderListener.java | 120 ------ .../listeners/ServerLoadEventListener.java | 2 +- .../me/clip/placeholderapi/util/FileUtil.java | 41 +- 21 files changed, 996 insertions(+), 990 deletions(-) delete mode 100644 src/main/java/me/clip/placeholderapi/expansion/ExpansionManager.java delete mode 100644 src/main/java/me/clip/placeholderapi/expansion/cloud/ExpansionCloudManager.java create mode 100644 src/main/java/me/clip/placeholderapi/expansion/manager/CloudExpansionManager.java create mode 100644 src/main/java/me/clip/placeholderapi/expansion/manager/LocalExpansionManager.java delete mode 100644 src/main/java/me/clip/placeholderapi/listeners/PlaceholderListener.java diff --git a/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java b/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java index e15145d..30be162 100644 --- a/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java +++ b/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java @@ -20,25 +20,18 @@ */ package me.clip.placeholderapi; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import me.clip.placeholderapi.events.ExpansionRegisterEvent; -import me.clip.placeholderapi.events.ExpansionUnregisterEvent; -import me.clip.placeholderapi.expansion.Cacheable; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import me.clip.placeholderapi.expansion.Relational; import me.clip.placeholderapi.replacer.CharsReplacer; import me.clip.placeholderapi.replacer.Replacer; import me.clip.placeholderapi.replacer.Replacer.Closure; import me.clip.placeholderapi.util.Msg; -import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -53,8 +46,6 @@ public final class PlaceholderAPI private static final Replacer REPLACER_PERCENT = new CharsReplacer(Closure.PERCENT); private static final Replacer REPLACER_BRACKET = new CharsReplacer(Closure.BRACKET); - private static final Map PLACEHOLDERS = new HashMap<>(); - @Deprecated private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]"); @@ -82,7 +73,7 @@ public final class PlaceholderAPI @NotNull public static String setPlaceholders(@Nullable final OfflinePlayer player, @NotNull final String text) { - return REPLACER_PERCENT.apply(text, player, PLACEHOLDERS::get); + return REPLACER_PERCENT.apply(text, player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion); } /** @@ -105,13 +96,12 @@ public final class PlaceholderAPI * * @param player Player to parse the placeholders against * @param text Text to set the placeholder values in - * * @return String containing all translated placeholders */ @NotNull public static String setBracketPlaceholders(@Nullable final OfflinePlayer player, @NotNull final String text) { - return REPLACER_BRACKET.apply(text, player, PLACEHOLDERS::get); + return REPLACER_BRACKET.apply(text, player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion); } /** @@ -120,7 +110,6 @@ public final class PlaceholderAPI * * @param player Player to parse the placeholders against * @param text List of Strings to set the placeholder values in - * * @return String containing all translated placeholders */ @NotNull @@ -138,43 +127,7 @@ public final class PlaceholderAPI */ public static boolean isRegistered(@NotNull final String identifier) { - return PLACEHOLDERS.containsKey(identifier.toLowerCase()); - } - - /** - * 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(@NotNull final String identifier, @NotNull final PlaceholderHook placeholderHook) - { - return PLACEHOLDERS.putIfAbsent(identifier.toLowerCase(), placeholderHook) == null; - } - - public static boolean registerPlaceholderHook(@NotNull final Plugin plugin, @NotNull final PlaceholderHook placeholderHook) - { - return registerPlaceholderHook(plugin.getName(), placeholderHook); - } - - /** - * 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(@NotNull final String identifier) - { - return PLACEHOLDERS.remove(identifier.toLowerCase()) != null; - } - - public static boolean unregisterPlaceholderHook(@NotNull final Plugin plugin) - { - return unregisterPlaceholderHook(plugin.getName()); + return PlaceholderAPIPlugin.getInstance().getLocalExpansionManager().findExpansionByIdentifier(identifier).isPresent(); } @@ -186,7 +139,7 @@ public final class PlaceholderAPI @NotNull public static Set getRegisteredIdentifiers() { - return ImmutableSet.copyOf(PLACEHOLDERS.keySet()); + return ImmutableSet.copyOf(PlaceholderAPIPlugin.getInstance().getLocalExpansionManager().getIdentifiers()); } /** @@ -195,69 +148,11 @@ public final class PlaceholderAPI * @return Copy of the internal placeholder map */ @NotNull + @Deprecated public static Map getPlaceholders() { - return ImmutableMap.copyOf(PLACEHOLDERS); - } - - - /** - * Unregister ALL placeholder hooks that are currently registered - */ - protected static void unregisterAll() - { - unregisterAllProvidedExpansions(); - PLACEHOLDERS.clear(); - } - - /** - * Unregister all expansions provided by PlaceholderAPI - */ - public static void unregisterAllProvidedExpansions() - { - final Set set = new HashSet<>(PLACEHOLDERS.values()); - - for (PlaceholderHook hook : set) - { - if (hook instanceof PlaceholderExpansion) - { - final PlaceholderExpansion expansion = (PlaceholderExpansion) hook; - - if (!expansion.persist()) - { - unregisterExpansion(expansion); - } - } - - if (hook instanceof Cacheable) - { - ((Cacheable) hook).clear(); - } - } - } - - public static boolean registerExpansion(@NotNull final PlaceholderExpansion expansion) - { - final ExpansionRegisterEvent event = new ExpansionRegisterEvent(expansion); - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) - { - return false; - } - - return registerPlaceholderHook(expansion.getIdentifier(), expansion); - } - - public static boolean unregisterExpansion(@NotNull final PlaceholderExpansion expansion) - { - if (unregisterPlaceholderHook(expansion.getIdentifier())) - { - Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(expansion)); - return true; - } - - return false; + throw new UnsupportedOperationException("PlaceholderAPI no longer provides a view of the placeholder's map!\n" + + "Use: PlaceholderAPIPlugin.getInstance().getLocalExpansionManager().findExpansionByIdentifier(String)"); } @@ -512,7 +407,7 @@ public final class PlaceholderAPI return null; } - if (PLACEHOLDERS.isEmpty()) + if (PlaceholderAPIPlugin.getInstance().getLocalExpansionManager().getExpansionsCount() == 0) { return colorize ? Msg.color(text) : text; } @@ -608,7 +503,8 @@ public final class PlaceholderAPI * @deprecated Will be removed in a future release. */ @Deprecated - public static String setPlaceholders(Player player, String text) { + public static String setPlaceholders(Player player, String text) + { return setPlaceholders(((OfflinePlayer) player), text); } diff --git a/src/main/java/me/clip/placeholderapi/PlaceholderAPIPlugin.java b/src/main/java/me/clip/placeholderapi/PlaceholderAPIPlugin.java index fd9e9f4..12474ce 100644 --- a/src/main/java/me/clip/placeholderapi/PlaceholderAPIPlugin.java +++ b/src/main/java/me/clip/placeholderapi/PlaceholderAPIPlugin.java @@ -22,11 +22,10 @@ package me.clip.placeholderapi; import me.clip.placeholderapi.commands.PlaceholderCommandRouter; 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.listeners.PlaceholderListener; +import me.clip.placeholderapi.expansion.manager.CloudExpansionManager; +import me.clip.placeholderapi.expansion.manager.LocalExpansionManager; import me.clip.placeholderapi.listeners.ServerLoadEventListener; import me.clip.placeholderapi.updatechecker.UpdateChecker; import me.clip.placeholderapi.util.Msg; @@ -52,18 +51,35 @@ public final class PlaceholderAPIPlugin extends JavaPlugin { @NotNull - private static final Version version = resolveServerVersion(); + private static final Version VERSION; + static + { + final String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + + boolean isSpigot; + try + { + Class.forName("org.spigotmc.SpigotConfig"); + isSpigot = true; + } + catch (final ExceptionInInitializerError | ClassNotFoundException ignored) + { + isSpigot = false; + } + + VERSION = new Version(version, isSpigot); + } private static PlaceholderAPIPlugin instance; + @NotNull + private final PlaceholderAPIConfig config = new PlaceholderAPIConfig(this); @NotNull - private final PlaceholderAPIConfig config = new PlaceholderAPIConfig(this); + private final LocalExpansionManager localExpansionManager = new LocalExpansionManager(this); @NotNull - private final ExpansionCloudManager cloud = new ExpansionCloudManager(this); - @NotNull - private final ExpansionManager manager = new ExpansionManager(this); + private final CloudExpansionManager cloudExpansionManager = new CloudExpansionManager(this); @Override @@ -81,11 +97,9 @@ public final class PlaceholderAPIPlugin extends JavaPlugin setupMetrics(); setupExpansions(); - new PlaceholderListener(this); - if (config.isCloudEnabled()) { - enableCloud(); + getCloudExpansionManager().load(); } if (config.checkUpdates()) @@ -97,11 +111,11 @@ public final class PlaceholderAPIPlugin extends JavaPlugin @Override public void onDisable() { - disableCloud(); - - PlaceholderAPI.unregisterAll(); + getCloudExpansionManager().kill(); + getLocalExpansionManager().kill(); HandlerList.unregisterAll(this); + Bukkit.getScheduler().cancelTasks(this); instance = null; @@ -110,34 +124,36 @@ public final class PlaceholderAPIPlugin extends JavaPlugin public void reloadConf(@NotNull final CommandSender sender) { - PlaceholderAPI.unregisterAllProvidedExpansions(); + getLocalExpansionManager().kill(); reloadConfig(); - manager.registerAllExpansions(); + getLocalExpansionManager().load(); if (config.isCloudEnabled()) { - enableCloud(); + getCloudExpansionManager().load(); } else { - disableCloud(); + getCloudExpansionManager().kill(); } Msg.msg(sender, - PlaceholderAPI.getRegisteredIdentifiers().size() + " &aplaceholder hooks successfully registered!"); + getLocalExpansionManager().getIdentifiers().size() + " &aplaceholder hooks successfully registered!"); } - public void enableCloud() + + @NotNull + public LocalExpansionManager getLocalExpansionManager() { - disableCloud(); - cloud.fetch(config.cloudAllowUnverifiedExpansions()); + return localExpansionManager; } - public void disableCloud() + @NotNull + public CloudExpansionManager getCloudExpansionManager() { - cloud.clean(); + return cloudExpansionManager; } @@ -152,18 +168,6 @@ public final class PlaceholderAPIPlugin extends JavaPlugin return config; } - @NotNull - public ExpansionManager getExpansionManager() - { - return manager; - } - - @NotNull - public ExpansionCloudManager getExpansionCloud() - { - return cloud; - } - private void setupCommand() { @@ -181,42 +185,54 @@ public final class PlaceholderAPIPlugin extends JavaPlugin private void setupMetrics() { final Metrics metrics = new Metrics(this); - metrics.addCustomChart(new Metrics.SimplePie("using_expansion_cloud", () -> getPlaceholderAPIConfig().isCloudEnabled() ? "yes" : "no")); + metrics.addCustomChart( + new Metrics.SimplePie( + "using_expansion_cloud", + () -> getPlaceholderAPIConfig().isCloudEnabled() ? "yes" : "no")); - metrics.addCustomChart(new Metrics.SimplePie("using_spigot", () -> getServerVersion().isSpigot() ? "yes" : "no")); + metrics.addCustomChart( + new Metrics.SimplePie("using_spigot", () -> getServerVersion().isSpigot() ? "yes" : "no")); - metrics.addCustomChart(new Metrics.AdvancedPie("expansions_used", () -> { + metrics.addCustomChart( + new Metrics.AdvancedPie( + "expansions_used", + () -> { + Map map = new HashMap<>(); + Map hooks = PlaceholderAPI.getPlaceholders(); - Map map = new HashMap<>(); - Map hooks = PlaceholderAPI.getPlaceholders(); + if (!hooks.isEmpty()) + { - if (!hooks.isEmpty()) - { + for (PlaceholderHook hook : hooks.values()) + { + if (hook instanceof PlaceholderExpansion) + { + PlaceholderExpansion expansion = (PlaceholderExpansion) hook; + map.put( + expansion.getRequiredPlugin() == null + ? expansion.getIdentifier() + : expansion.getRequiredPlugin(), + 1); + } + } + } - for (PlaceholderHook hook : hooks.values()) - { - if (hook instanceof PlaceholderExpansion) - { - PlaceholderExpansion expansion = (PlaceholderExpansion) hook; - map.put(expansion.getRequiredPlugin() == null ? expansion.getIdentifier() : expansion.getRequiredPlugin(), 1); - } - } - } - - return map; - })); + return map; + })); } private void setupExpansions() { + Bukkit.getPluginManager().registerEvents(getLocalExpansionManager(), this); + try { Class.forName("org.bukkit.event.server.ServerLoadEvent"); new ServerLoadEventListener(this); } - catch (final ExceptionInInitializerError | ClassNotFoundException exception) + catch (final ExceptionInInitializerError | ClassNotFoundException ignored) { - Bukkit.getScheduler().runTaskLater(this, getExpansionManager()::initializeExpansions, 1); + Bukkit.getScheduler().runTaskLater(this, getLocalExpansionManager()::load, 1); } } @@ -235,28 +251,6 @@ public final class PlaceholderAPIPlugin extends JavaPlugin } - /** - * Get the configurable {@linkplain SimpleDateFormat} object that is used to parse time for - * generic time based placeholders - * - * @return date format - */ - @NotNull - public static SimpleDateFormat getDateFormat() - { - try - { - return new SimpleDateFormat(getInstance().getPlaceholderAPIConfig().dateFormat()); - } - catch (final IllegalArgumentException ex) - { - - getInstance().getLogger().log(Level.WARNING, "configured date format is invalid", ex); - - return new SimpleDateFormat("MM/dd/yy HH:mm:ss"); - } - } - /** * Get the configurable {@linkplain String} value that should be returned when a boolean is true * @@ -279,28 +273,30 @@ public final class PlaceholderAPIPlugin extends JavaPlugin return getInstance().getPlaceholderAPIConfig().booleanFalse(); } + /** + * Get the configurable {@linkplain SimpleDateFormat} object that is used to parse time for + * generic time based placeholders + * + * @return date format + */ + @NotNull + public static SimpleDateFormat getDateFormat() + { + try + { + return new SimpleDateFormat(getInstance().getPlaceholderAPIConfig().dateFormat()); + } + catch (final IllegalArgumentException ex) + { + getInstance().getLogger().log(Level.WARNING, "configured date format is invalid", ex); + return new SimpleDateFormat("MM/dd/yy HH:mm:ss"); + } + } + public static Version getServerVersion() { - return version; - } - - private static Version resolveServerVersion() - { - final String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; - - boolean isSpigot; - try - { - Class.forName("org.spigotmc.SpigotConfig"); - isSpigot = true; - } - catch (final ExceptionInInitializerError | ClassNotFoundException ignored) - { - isSpigot = false; - } - - return new Version(version, isSpigot); + return VERSION; } } diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudClear.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudClear.java index 247c89e..db5ed51 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudClear.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudClear.java @@ -20,7 +20,7 @@ public final class CommandECloudClear extends PlaceholderCommand @Override public void evaluate(@NotNull final PlaceholderAPIPlugin plugin, @NotNull final CommandSender sender, @NotNull final String alias, @NotNull @Unmodifiable final List params) { - plugin.getExpansionCloud().clean(); + plugin.getCloudExpansionManager().clean(); Msg.msg(sender, "&aThe eCloud cache has been cleared!"); } diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudDownload.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudDownload.java index f830446..5196858 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudDownload.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudDownload.java @@ -30,7 +30,7 @@ public final class CommandECloudDownload extends PlaceholderCommand return; } - final CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(params.get(0)).orElse(null); + final CloudExpansion expansion = plugin.getCloudExpansionManager().findCloudExpansionByName(params.get(0)).orElse(null); if (expansion == null) { Msg.msg(sender, @@ -61,7 +61,7 @@ public final class CommandECloudDownload extends PlaceholderCommand } } - plugin.getExpansionCloud().downloadExpansion(expansion, version).whenComplete((file, exception) -> { + plugin.getCloudExpansionManager().downloadExpansion(expansion, version).whenComplete((file, exception) -> { if (exception != null) { Msg.msg(sender, @@ -72,8 +72,8 @@ public final class CommandECloudDownload extends PlaceholderCommand Msg.msg(sender, "&aSuccessfully downloaded expansion to file: &e" + file.getName()); - plugin.getExpansionCloud().clean(); - plugin.getExpansionCloud().fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); + plugin.getCloudExpansionManager().clean(); + plugin.getCloudExpansionManager().fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); }); } @@ -87,12 +87,12 @@ public final class CommandECloudDownload extends PlaceholderCommand if (params.size() <= 1) { - final Stream names = plugin.getExpansionCloud().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); + final Stream names = plugin.getCloudExpansionManager().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); suggestByParameter(names, suggestions, params.isEmpty() ? null : params.get(0)); return; } - final Optional expansion = plugin.getExpansionCloud().getCloudExpansion(params.get(0)); + final Optional expansion = plugin.getCloudExpansionManager().findCloudExpansionByName(params.get(0)); if (!expansion.isPresent()) { return; diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionInfo.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionInfo.java index 91514f3..d0faa8f 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionInfo.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionInfo.java @@ -30,7 +30,7 @@ public final class CommandECloudExpansionInfo extends PlaceholderCommand return; } - final CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(params.get(0)).orElse(null); + final CloudExpansion expansion = plugin.getCloudExpansionManager().findCloudExpansionByName(params.get(0)).orElse(null); if (expansion == null) { Msg.msg(sender, @@ -99,12 +99,12 @@ public final class CommandECloudExpansionInfo extends PlaceholderCommand if (params.size() <= 1) { - final Stream names = plugin.getExpansionCloud().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); + final Stream names = plugin.getCloudExpansionManager().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); suggestByParameter(names, suggestions, params.isEmpty() ? null : params.get(0)); return; } - final Optional expansion = plugin.getExpansionCloud().getCloudExpansion(params.get(0)); + final Optional expansion = plugin.getCloudExpansionManager().findCloudExpansionByName(params.get(0)); if (!expansion.isPresent()) { return; diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionList.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionList.java index 4e4a8d5..7abc52b 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionList.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionList.java @@ -1,19 +1,25 @@ package me.clip.placeholderapi.commands.impl.cloud; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.primitives.Ints; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.commands.PlaceholderCommand; import me.clip.placeholderapi.expansion.cloud.CloudExpansion; import me.clip.placeholderapi.util.Msg; +import me.rayzr522.jsonmessage.JSONMessage; +import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; +import java.text.SimpleDateFormat; +import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -22,7 +28,7 @@ import java.util.stream.IntStream; public final class CommandECloudExpansionList extends PlaceholderCommand { - private static final int PAGE_SIZE = 3; + private static final int PAGE_SIZE = 10; @Unmodifiable @@ -34,6 +40,90 @@ public final class CommandECloudExpansionList extends PlaceholderCommand super("list"); } + @NotNull + private static List getPage(@NotNull final List expansions, final int page, final int pageSize) + { + if (expansions.isEmpty()) + { + return Collections.emptyList(); + } + + final int head = (page * pageSize); + final int tail = Math.min(expansions.size(), head + pageSize); + + if (expansions.size() < head) + { + return Collections.emptyList(); + } + + return IntStream.range(head, tail).mapToObj(expansions::get).filter(Objects::nonNull).collect(Collectors.toList()); + } + + @NotNull + private static Collection getExpansions(@NotNull final String target, @NotNull final PlaceholderAPIPlugin plugin) + { + switch (target.toLowerCase()) + { + case "all": + return plugin.getCloudExpansionManager().getCloudExpansions().values(); + case "installed": + return plugin.getCloudExpansionManager().getCloudExpansionsInstalled().values(); + default: + return plugin.getCloudExpansionManager().getCloudExpansionsByAuthor(target).values(); + } + } + + @NotNull + private static JSONMessage getMessage(@NotNull final List expansions, final int page) + { + final SimpleDateFormat format = PlaceholderAPIPlugin.getDateFormat(); + + final StringBuilder tooltip = new StringBuilder(); + final JSONMessage message = JSONMessage.create(); + + int index = ((page - 1) * PAGE_SIZE) + 1; + for (int i = 0; i < expansions.size(); i++) + { + final CloudExpansion expansion = expansions.get(i); + tooltip.append("&bClick to download this expansion!") + .append('\n') + .append('\n') + .append("&bAuthor: &f") + .append(expansion.getAuthor()) + .append('\n') + .append("&bVerified: ") + .append(expansion.isVerified() ? "&a&l✔&r" : "&c&l❌&r") + .append('\n') + .append("&bLatest Version: &f") + .append(expansion.getLatestVersion()) + .append('\n') + .append("&bReleased: &f") + .append(format.format(expansion.getLastUpdate())); + + final String description = expansion.getDescription(); + if (description != null && !description.isEmpty()) + { + tooltip.append('\n') + .append('\n') + .append("&f") + .append(description.replace("\r", "").trim()); + } + + message.then(Msg.color("&8" + (index++) + ".&r " + (expansion.shouldUpdate() ? "&6" : expansion.hasExpansion() ? "&a" : "&7") + expansion.getName())); + + message.tooltip(Msg.color(tooltip.toString())); + message.suggestCommand("/papi ecloud download " + expansion.getName()); + + if (i < expansions.size() - 1) + { + message.newline(); + } + + tooltip.setLength(0); + } + + return message; + } @Override public void evaluate(@NotNull final PlaceholderAPIPlugin plugin, @NotNull final CommandSender sender, @NotNull final String alias, @NotNull @Unmodifiable final List params) @@ -45,8 +135,7 @@ public final class CommandECloudExpansionList extends PlaceholderCommand return; } - - @Unmodifiable final Map expansions = getExpansions(params.get(0), plugin); + final List expansions = Lists.newArrayList(getExpansions(params.get(0), plugin)); final int page; @@ -77,6 +166,7 @@ public final class CommandECloudExpansionList extends PlaceholderCommand page = parsed; } + expansions.sort(Comparator.comparing(CloudExpansion::getLastUpdate).reversed()); final StringBuilder builder = new StringBuilder(); final List values = getPage(expansions, page - 1, PAGE_SIZE); @@ -100,27 +190,63 @@ public final class CommandECloudExpansionList extends PlaceholderCommand .append(page) .append('\n'); - int index = ((page - 1) * PAGE_SIZE) + 1; - for (final CloudExpansion expansion : values) + + if (sender instanceof Player) { - builder.append("&8") - .append(index++) - .append(". ") - .append(expansion.shouldUpdate() ? "&e" : "&a") - .append(expansion.getName()) - .append('\n') - .append(" &bAuthor: &f") - .append(expansion.getAuthor()) - .append('\n') - .append(" &bVerified: ") - .append(expansion.isVerified() ? "&a&l✔&r" : "&c&l❌&r") - .append('\n') - .append(" &bLatest Version: &f") - .append(expansion.getLatestVersion()) - .append('\n'); + Msg.msg(sender, builder.toString()); + + final int limit = (int) Math.ceil((double) expansions.size() / PAGE_SIZE); + + final JSONMessage message = getMessage(values, page); + + if (limit > 1) + { + message.newline(); + + message.then("◀") + .color(page <= 1 ? ChatColor.GRAY : ChatColor.DARK_GRAY); + if (page > 1) + { + message.runCommand("/papi ecloud list " + params.get(0) + " " + (page - 1)); + } + + message.then(" " + page + " ").color(ChatColor.GREEN); + + message.then("▶") + .color(page >= limit ? ChatColor.GRAY : ChatColor.DARK_GRAY); + if (page < limit) + { + message.runCommand("/papi ecloud list " + params.get(0) + " " + (page + 1)); + } + } + + message.send(((Player) sender)); + } + else + { + int index = ((page - 1) * PAGE_SIZE) + 1; + for (final CloudExpansion expansion : values) + { + builder.append("&8") + .append(index++) + .append(". ") + .append((expansion.shouldUpdate() ? "&6" : expansion.hasExpansion() ? "&a" : "&7")) + .append(expansion.getName()) + .append('\n') + .append(" &bAuthor: &f") + .append(expansion.getAuthor()) + .append('\n') + .append(" &bVerified: ") + .append(expansion.isVerified() ? "&a&l✔&r" : "&c&l❌&r") + .append('\n') + .append(" &bLatest Version: &f") + .append(expansion.getLatestVersion()) + .append('\n'); + } + + Msg.msg(sender, builder.toString()); } - Msg.msg(sender, builder.toString()); } @Override @@ -133,42 +259,11 @@ public final class CommandECloudExpansionList extends PlaceholderCommand if (params.size() <= 1) { - suggestByParameter(Sets.union(OPTIONS, plugin.getExpansionCloud().getCloudAuthorNames()).stream(), suggestions, params.isEmpty() ? null : params.get(0)); + suggestByParameter(Sets.union(OPTIONS, plugin.getCloudExpansionManager().getCloudExpansionAuthors()).stream(), suggestions, params.isEmpty() ? null : params.get(0)); return; } - final Map expansions = getExpansions(params.get(0), plugin); - - suggestByParameter(IntStream.rangeClosed(1, (int) Math.ceil((double) expansions.size() / PAGE_SIZE)).mapToObj(Objects::toString), suggestions, params.get(1)); - } - - - @NotNull - private static List getPage(@NotNull final Map expansions, final int page, final int pageSize) - { - if (expansions.isEmpty()) - { - return Collections.emptyList(); - } - - final int head = (page * pageSize); - final int tail = (head + pageSize); - - return IntStream.range(head, tail).mapToObj(expansions::get).filter(Objects::nonNull).collect(Collectors.toList()); - } - - @NotNull - private static Map getExpansions(@NotNull final String target, @NotNull final PlaceholderAPIPlugin plugin) - { - switch (target.toLowerCase()) - { - case "all": - return plugin.getExpansionCloud().getCloudExpansions(); - case "installed": - return plugin.getExpansionCloud().getAllInstalled(); - default: - return plugin.getExpansionCloud().getAllByAuthor(target); - } + suggestByParameter(IntStream.rangeClosed(1, (int) Math.ceil((double) getExpansions(params.get(0), plugin).size() / PAGE_SIZE)).mapToObj(Objects::toString), suggestions, params.get(1)); } } diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionPlaceholders.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionPlaceholders.java index 9f6a3ac..2b93215 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionPlaceholders.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudExpansionPlaceholders.java @@ -31,7 +31,7 @@ public final class CommandECloudExpansionPlaceholders extends PlaceholderCommand return; } - final CloudExpansion expansion = plugin.getExpansionCloud().getCloudExpansion(params.get(0)).orElse(null); + final CloudExpansion expansion = plugin.getCloudExpansionManager().findCloudExpansionByName(params.get(0)).orElse(null); if (expansion == null) { Msg.msg(sender, @@ -63,7 +63,13 @@ public final class CommandECloudExpansionPlaceholders extends PlaceholderCommand return; } - final Stream names = plugin.getExpansionCloud().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); + final Stream names = plugin.getCloudExpansionManager() + .getCloudExpansions() + .values() + .stream() + .map(CloudExpansion::getName) + .map(name -> name.replace(' ', '_')); + suggestByParameter(names, suggestions, params.isEmpty() ? null : params.get(0)); } diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudRefresh.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudRefresh.java index 5cea281..4192192 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudRefresh.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudRefresh.java @@ -20,8 +20,8 @@ public final class CommandECloudRefresh extends PlaceholderCommand @Override public void evaluate(@NotNull final PlaceholderAPIPlugin plugin, @NotNull final CommandSender sender, @NotNull final String alias, @NotNull @Unmodifiable final List params) { - plugin.getExpansionCloud().clean(); - plugin.getExpansionCloud().fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); + plugin.getCloudExpansionManager().clean(); + plugin.getCloudExpansionManager().fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); Msg.msg(sender, "&aThe eCloud Manager has been refreshed!"); diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudStatus.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudStatus.java index 86474cd..a6dce58 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudStatus.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudStatus.java @@ -2,7 +2,7 @@ package me.clip.placeholderapi.commands.impl.cloud; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.commands.PlaceholderCommand; -import me.clip.placeholderapi.expansion.cloud.ExpansionCloudManager; +import me.clip.placeholderapi.expansion.manager.CloudExpansionManager; import me.clip.placeholderapi.util.Msg; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -21,10 +21,10 @@ public final class CommandECloudStatus extends PlaceholderCommand @Override public void evaluate(@NotNull final PlaceholderAPIPlugin plugin, @NotNull final CommandSender sender, @NotNull final String alias, @NotNull @Unmodifiable final List params) { - final ExpansionCloudManager manager = plugin.getExpansionCloud(); + final CloudExpansionManager manager = plugin.getCloudExpansionManager(); final int updateCount = manager.getCloudUpdateCount(); - final int authorCount = manager.getCloudAuthorCount(); + final int authorCount = manager.getCloudExpansionAuthorCount(); final int expansionCount = manager.getCloudExpansions().size(); final StringBuilder builder = new StringBuilder(); diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudToggle.java b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudToggle.java index 4a8d04d..dd56d04 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudToggle.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/cloud/CommandECloudToggle.java @@ -17,7 +17,6 @@ public final class CommandECloudToggle extends PlaceholderCommand super("toggle", "enable", "disable"); } - @Override public void evaluate(@NotNull final PlaceholderAPIPlugin plugin, @NotNull final CommandSender sender, @NotNull final String alias, @NotNull @Unmodifiable final List params) { @@ -39,8 +38,7 @@ public final class CommandECloudToggle extends PlaceholderCommand if (desiredState == currentState) { - Msg.msg(sender, - "&7The eCloud Manager is already " + (desiredState ? "enabled" : "disabled")); + Msg.msg(sender, "&7The eCloud Manager is already " + (desiredState ? "enabled" : "disabled")); return; } @@ -48,15 +46,14 @@ public final class CommandECloudToggle extends PlaceholderCommand if (desiredState) { - plugin.enableCloud(); + plugin.getCloudExpansionManager().load(); } else { - plugin.disableCloud(); + plugin.getCloudExpansionManager().kill(); } - Msg.msg(sender, - "&aThe eCloud Manager has been " + (desiredState ? "enabled" : "disabled")); + Msg.msg(sender, "&aThe eCloud Manager has been " + (desiredState ? "enabled" : "disabled")); } } diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionRegister.java b/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionRegister.java index 1f7c740..44c2bdd 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionRegister.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionRegister.java @@ -3,13 +3,17 @@ package me.clip.placeholderapi.commands.impl.local; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.commands.PlaceholderCommand; import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import me.clip.placeholderapi.expansion.manager.LocalExpansionManager; import me.clip.placeholderapi.util.Msg; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; +import java.io.File; import java.util.Arrays; import java.util.List; +import java.util.Optional; +import java.util.logging.Level; public final class CommandExpansionRegister extends PlaceholderCommand { @@ -29,16 +33,45 @@ public final class CommandExpansionRegister extends PlaceholderCommand return; } - final PlaceholderExpansion expansion = plugin.getExpansionManager().registerExpansion(params.get(0)); - if (expansion == null) + + final LocalExpansionManager manager = plugin.getLocalExpansionManager(); + + final File file = new File(manager.getExpansionsFolder(), params.get(0)); + if (!file.exists()) { Msg.msg(sender, - "&cFailed to register expansion from &f" + params.get(0)); + "&cThe file &f" + file.getName() + "&c doesn't exist!"); return; } - Msg.msg(sender, - "&aSuccessfully registered expansion: &f" + expansion.getName()); + manager.findExpansionsInFile(file).whenCompleteAsync((classes, exception) -> { + if (exception != null) + { + Msg.msg(sender, + "&cFailed to find expansion in file: &f" + file); + + plugin.getLogger().log(Level.WARNING, "failed to find expansion in file: " + file, exception); + return; + } + + if (classes.isEmpty()) + { + Msg.msg(sender, + "&cNo expansion class found in file: &f" + file); + return; + } + + final Optional expansion = manager.register(classes.get(0)); + if (!expansion.isPresent()) + { + Msg.msg(sender, + "&cFailed to register expansion from &f" + params.get(0)); + return; + } + + Msg.msg(sender, + "&aSuccessfully registered expansion: &f" + expansion.get().getName()); + }); } @Override @@ -49,7 +82,7 @@ public final class CommandExpansionRegister extends PlaceholderCommand return; } - final String[] fileNames = plugin.getExpansionManager().getFolder().list((dir, name) -> name.endsWith(".jar")); + final String[] fileNames = plugin.getLocalExpansionManager().getExpansionsFolder().list((dir, name) -> name.endsWith(".jar")); if (fileNames == null || fileNames.length == 0) { return; diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionUnregister.java b/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionUnregister.java index 6d08056..ccc0d2f 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionUnregister.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandExpansionUnregister.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import java.util.List; +import java.util.Optional; public final class CommandExpansionUnregister extends PlaceholderCommand { @@ -29,8 +30,8 @@ public final class CommandExpansionUnregister extends PlaceholderCommand return; } - final PlaceholderExpansion expansion = plugin.getExpansionManager().getRegisteredExpansion(params.get(0)); - if (expansion == null) + final Optional expansion = plugin.getLocalExpansionManager().findExpansionByName(params.get(0)); + if (!expansion.isPresent()) { Msg.msg(sender, "&cThere is no expansion loaded with the identifier: &f" + params.get(0)); @@ -38,11 +39,11 @@ public final class CommandExpansionUnregister extends PlaceholderCommand } - final String message = !PlaceholderAPI.unregisterExpansion(expansion) ? + final String message = !plugin.getLocalExpansionManager().unregister(expansion.get()) ? "&cFailed to unregister expansion: &f" : "&aSuccessfully unregistered expansion: &f"; - Msg.msg(sender, message + expansion.getName()); + Msg.msg(sender, message + expansion.get().getName()); } @Override diff --git a/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandInfo.java b/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandInfo.java index e142305..f017a30 100644 --- a/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandInfo.java +++ b/src/main/java/me/clip/placeholderapi/commands/impl/local/CommandInfo.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import java.util.List; +import java.util.Optional; public final class CommandInfo extends PlaceholderCommand { @@ -29,7 +30,7 @@ public final class CommandInfo extends PlaceholderCommand return; } - final PlaceholderExpansion expansion = plugin.getExpansionManager().getRegisteredExpansion(params.get(0)); + final PlaceholderExpansion expansion = plugin.getLocalExpansionManager().findExpansionByName(params.get(0)).orElse(null); if (expansion == null) { Msg.msg(sender, diff --git a/src/main/java/me/clip/placeholderapi/expansion/ExpansionManager.java b/src/main/java/me/clip/placeholderapi/expansion/ExpansionManager.java deleted file mode 100644 index 63358ab..0000000 --- a/src/main/java/me/clip/placeholderapi/expansion/ExpansionManager.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * - * PlaceholderAPI - * Copyright (C) 2019 Ryan McCarthy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - */ -package me.clip.placeholderapi.expansion; - -import me.clip.placeholderapi.PlaceholderAPI; -import me.clip.placeholderapi.PlaceholderAPIPlugin; -import me.clip.placeholderapi.PlaceholderHook; -import me.clip.placeholderapi.expansion.cloud.CloudExpansion; -import me.clip.placeholderapi.util.FileUtil; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.event.Listener; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.logging.Level; - -public final class ExpansionManager -{ - - @NotNull - private final File folder; - @NotNull - private final PlaceholderAPIPlugin plugin; - - public ExpansionManager(@NotNull final PlaceholderAPIPlugin plugin) - { - this.plugin = plugin; - this.folder = new File(plugin.getDataFolder(), "expansions"); - - if (!this.folder.exists() && !folder.mkdirs()) - { - plugin.getLogger().log(Level.WARNING, "failed to create expansions folder!"); - } - } - - - @NotNull - public File getFolder() - { - return folder; - } - - public void initializeExpansions() - { - plugin.getLogger().info("Placeholder expansion registration initializing..."); - - final Map registered = PlaceholderAPI.getPlaceholders(); - registerAllExpansions(); - - if (!registered.isEmpty()) { - registered.forEach(PlaceholderAPI::registerPlaceholderHook); - } - } - - - - public PlaceholderExpansion getRegisteredExpansion(String name) - { - for (Entry hook : PlaceholderAPI.getPlaceholders().entrySet()) - { - if (hook.getValue() instanceof PlaceholderExpansion) - { - if (name.equalsIgnoreCase(hook.getKey())) - { - return (PlaceholderExpansion) hook.getValue(); - } - } - } - - return null; - } - - public boolean registerExpansion(@NotNull final PlaceholderExpansion expansion) - { - if (expansion.getIdentifier() == null) - { - return false; - } - - if (expansion instanceof Configurable) - { - Map defaults = ((Configurable) expansion).getDefaults(); - String pre = "expansions." + expansion.getIdentifier() + "."; - FileConfiguration cfg = plugin.getConfig(); - boolean save = false; - - if (defaults != null) - { - for (Entry 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 (expansion instanceof VersionSpecific) - { - VersionSpecific nms = (VersionSpecific) expansion; - if (!nms.isCompatibleWith(PlaceholderAPIPlugin.getServerVersion())) - { - plugin.getLogger() - .info( - "Your server version is not compatible with expansion: " + expansion.getIdentifier() - + " version: " + expansion.getVersion()); - return false; - } - } - - if (!expansion.canRegister() || !expansion.register()) - { - return false; - } - - if (expansion instanceof Listener) - { - Bukkit.getPluginManager().registerEvents(((Listener) expansion), plugin); - } - - plugin.getLogger().info("Successfully registered expansion: " + expansion.getIdentifier()); - - if (expansion instanceof Taskable) - { - ((Taskable) expansion).start(); - } - - if (plugin.getPlaceholderAPIConfig().isCloudEnabled()) - { - final CloudExpansion cloudExpansion = plugin.getExpansionCloud().getCloudExpansion(expansion.getIdentifier()).orElse(null); - - if (cloudExpansion != null) - { - cloudExpansion.setHasExpansion(true); - if (!cloudExpansion.getLatestVersion().equals(expansion.getVersion())) - { - cloudExpansion.setShouldUpdate(true); - } - } - } - - return true; - } - - - @Nullable - public PlaceholderExpansion registerExpansion(@NotNull final String fileName) - { - final List> subs = FileUtil.getClasses(folder, PlaceholderExpansion.class, fileName); - if (subs.isEmpty()) - { - return null; - } - - // only register the first instance found as an expansion jar should only have 1 class - // extending PlaceholderExpansion - final PlaceholderExpansion expansion = createInstance(subs.get(0)); - if (expansion != null && registerExpansion(expansion)) - { - return expansion; - } - - return null; - } - - public void registerAllExpansions() - { - final List<@NotNull Class> subs = FileUtil.getClasses(folder, PlaceholderExpansion.class); - if (subs.isEmpty()) - { - return; - } - - for (final Class clazz : subs) - { - final PlaceholderExpansion expansion = createInstance(clazz); - if (expansion == null) - { - continue; - } - - try - { - registerExpansion(expansion); - } - catch (final Exception ex) - { - plugin.getLogger().log(Level.WARNING, "Couldn't register " + expansion.getIdentifier() + " expansion", ex); - } - } - } - - @Nullable - private PlaceholderExpansion createInstance(@NotNull final Class clazz) - { - try - { - return clazz.getDeclaredConstructor().newInstance(); - } - catch (final Throwable ex) - { - plugin.getLogger().log(Level.SEVERE, "Failed to load placeholder expansion from class: " + clazz.getName(), ex); - } - - return null; - } - -} diff --git a/src/main/java/me/clip/placeholderapi/expansion/PlaceholderExpansion.java b/src/main/java/me/clip/placeholderapi/expansion/PlaceholderExpansion.java index 4ebdb51..8cad404 100644 --- a/src/main/java/me/clip/placeholderapi/expansion/PlaceholderExpansion.java +++ b/src/main/java/me/clip/placeholderapi/expansion/PlaceholderExpansion.java @@ -108,8 +108,7 @@ public abstract class PlaceholderExpansion extends PlaceholderHook { * @return true if this hook meets all the requirements to register */ public boolean canRegister() { - return getRequiredPlugin() == null - || Bukkit.getPluginManager().getPlugin(getRequiredPlugin()) != null; + return getRequiredPlugin() == null || Bukkit.getPluginManager().getPlugin(getRequiredPlugin()) != null; } /** @@ -119,7 +118,7 @@ public abstract class PlaceholderExpansion extends PlaceholderHook { */ public boolean register() { Validate.notNull(getIdentifier(), "Placeholder identifier can not be null!"); - return PlaceholderAPI.registerExpansion(this); + return canRegister() && getPlaceholderAPI().getLocalExpansionManager().register(this); } /** diff --git a/src/main/java/me/clip/placeholderapi/expansion/cloud/ExpansionCloudManager.java b/src/main/java/me/clip/placeholderapi/expansion/cloud/ExpansionCloudManager.java deleted file mode 100644 index 86fa45c..0000000 --- a/src/main/java/me/clip/placeholderapi/expansion/cloud/ExpansionCloudManager.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * - * PlaceholderAPI - * Copyright (C) 2019 Ryan McCarthy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - */ -package me.clip.placeholderapi.expansion.cloud; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import me.clip.placeholderapi.PlaceholderAPI; -import me.clip.placeholderapi.PlaceholderAPIPlugin; -import me.clip.placeholderapi.expansion.PlaceholderExpansion; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Unmodifiable; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; -import java.util.logging.Level; -import java.util.stream.Collectors; - -public final class ExpansionCloudManager -{ - - private static final String API_URL = "http://api.extendedclip.com/v2/"; - private static final Gson GSON = new Gson(); - - - @NotNull - private final File folder; - @NotNull - private final PlaceholderAPIPlugin plugin; - - - @NotNull - private final Map expansions = new TreeMap<>(); - @NotNull - private final Map> downloading = new HashMap<>(); - - - public ExpansionCloudManager(@NotNull final PlaceholderAPIPlugin plugin) - { - this.plugin = plugin; - this.folder = new File(plugin.getDataFolder(), "expansions"); - - if (!this.folder.exists() && !this.folder.mkdirs()) - { - plugin.getLogger().severe("Failed to create expansions directory!"); - } - } - - - @NotNull - @Unmodifiable - public Map getCloudExpansions() - { - return ImmutableMap.copyOf(expansions); - } - - @NotNull - @Unmodifiable - public Set getCloudAuthorNames() - { - return ImmutableSet.copyOf(expansions.values().stream().map(CloudExpansion::getAuthor).collect(Collectors.toSet())); - } - - public int getCloudAuthorCount() - { - return expansions.values() - .stream() - .collect(Collectors.groupingBy(CloudExpansion::getAuthor, Collectors.counting())) - .size(); - } - - @NotNull - public Optional getCloudExpansion(String name) - { - return expansions.values() - .stream() - .filter(ex -> ex.getName().replace(' ', '_').equalsIgnoreCase(name.replace(' ', '_'))) - .findFirst(); - } - - - public int getCloudUpdateCount() - { - return ((int) PlaceholderAPI.getExpansions() - .stream() - .filter(ex -> getCloudExpansion(ex.getName()).map(CloudExpansion::shouldUpdate).isPresent()) - .count()); - } - - @NotNull - @Unmodifiable - public Map getAllByAuthor(@NotNull final String author) - { - if (expansions.isEmpty()) - { - return Collections.emptyMap(); - } - - final AtomicInteger index = new AtomicInteger(); - - return expansions.values() - .stream() - .filter(expansion -> author.equalsIgnoreCase(expansion.getAuthor())) - .collect(Collectors.toMap(($) -> index.incrementAndGet(), Function.identity())); - } - - @NotNull - @Unmodifiable - public Map getAllInstalled() - { - if (expansions.isEmpty()) - { - return Collections.emptyMap(); - } - - final AtomicInteger index = new AtomicInteger(); - - return expansions.values() - .stream() - .filter(CloudExpansion::hasExpansion) - .collect(Collectors.toMap(($) -> index.incrementAndGet(), Function.identity())); - } - - - public void clean() - { - expansions.clear(); - - downloading.values().forEach(future -> future.cancel(true)); - downloading.clear(); - } - - public void fetch(boolean allowUnverified) - { - plugin.getLogger().info("Fetching available expansion information..."); - - plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { - final Map data = new HashMap<>(); - - try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(API_URL).openStream()))) - { - data.putAll(GSON.fromJson(reader, new TypeToken>() - { - }.getType())); - } - catch (Exception ex) - { - if (plugin.getPlaceholderAPIConfig().isDebugMode()) - { - ex.printStackTrace(); - } - else - { - plugin.getLogger().warning("Unable to fetch expansions!\nThere was an error with the server host connecting to the PlaceholderAPI eCloud (https://api.extendedclip.com/v2/)"); - } - } - - final List unsorted = new ArrayList<>(); - - data.forEach((name, cexp) -> { - if ((allowUnverified || cexp.isVerified()) && cexp.getLatestVersion() != null && cexp.getVersion(cexp.getLatestVersion()) != null) - { - cexp.setName(name); - - PlaceholderExpansion ex = plugin.getExpansionManager().getRegisteredExpansion(cexp.getName()); - - if (ex != null && ex.isRegistered()) - { - cexp.setHasExpansion(true); - if (!ex.getVersion().equals(cexp.getLatestVersion())) - { - cexp.setShouldUpdate(true); - } - } - - unsorted.add(cexp); - } - }); - - unsorted.sort(Comparator.comparing(CloudExpansion::getLastUpdate).reversed()); - - int count = 0; - for (CloudExpansion e : unsorted) - { - expansions.put(count++, e); - } - - plugin.getLogger().info(count + " placeholder expansions are available on the cloud."); - - long updates = getCloudUpdateCount(); - - if (updates > 0) - { - plugin.getLogger().info(updates + " installed expansions have updates available."); - } - }); - } - - - public boolean isDownloading(@NotNull final CloudExpansion expansion) - { - return downloading.containsKey(expansion); - } - - - @NotNull - public CompletableFuture<@NotNull File> downloadExpansion(@NotNull final CloudExpansion expansion, @NotNull final CloudExpansion.Version version) - { - final CompletableFuture previous = downloading.get(expansion); - if (previous != null) - { - return previous; - } - - final File file = new File(folder, "Expansion-" + expansion.getName() + ".jar"); - - final CompletableFuture download = CompletableFuture.supplyAsync(() -> { - - try (final ReadableByteChannel source = Channels.newChannel(new URL(version.getUrl()).openStream()); final FileOutputStream target = new FileOutputStream(file)) - { - target.getChannel().transferFrom(source, 0, Long.MAX_VALUE); - } - catch (final IOException ex) - { - throw new CompletionException(ex); - } - - return file; - }); - - download.whenCompleteAsync((value, exception) -> { - downloading.remove(expansion); - - if (exception != null) - { - plugin.getLogger().log(Level.SEVERE, "failed to download " + expansion.getName() + ":" + version.getVersion(), exception); - } - }); - - downloading.put(expansion, download); - - return download; - } - -} diff --git a/src/main/java/me/clip/placeholderapi/expansion/manager/CloudExpansionManager.java b/src/main/java/me/clip/placeholderapi/expansion/manager/CloudExpansionManager.java new file mode 100644 index 0000000..f12c293 --- /dev/null +++ b/src/main/java/me/clip/placeholderapi/expansion/manager/CloudExpansionManager.java @@ -0,0 +1,266 @@ +package me.clip.placeholderapi.expansion.manager; + +import com.google.common.collect.ImmutableMap; +import com.google.common.io.Resources; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import me.clip.placeholderapi.PlaceholderAPIPlugin; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import me.clip.placeholderapi.expansion.cloud.CloudExpansion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Type; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +public final class CloudExpansionManager +{ + + @NotNull + private static final String API_URL = "http://api.extendedclip.com/v2/"; + + @NotNull + private static final Gson GSON = new Gson(); + @NotNull + private static final Type TYPE = new TypeToken>() {}.getType(); + + @NotNull + private final Collector> INDEXED_NAME_COLLECTOR = Collectors.toMap(CloudExpansionManager::toIndexName, Function.identity()); + + + @NotNull + private final PlaceholderAPIPlugin plugin; + + @NotNull + private final Map cache = new HashMap<>(); + @NotNull + private final Map> await = new ConcurrentHashMap<>(); + + + public CloudExpansionManager(@NotNull final PlaceholderAPIPlugin plugin) + { + this.plugin = plugin; + } + + + public void load() + { + clean(); + fetch(plugin.getPlaceholderAPIConfig().cloudAllowUnverifiedExpansions()); + } + + public void kill() + { + clean(); + } + + @NotNull + @Unmodifiable + public Map getCloudExpansions() + { + return ImmutableMap.copyOf(cache); + } + + @NotNull + @Unmodifiable + public Map getCloudExpansionsInstalled() + { + if (cache.isEmpty()) + { + return Collections.emptyMap(); + } + + return cache.values() + .stream() + .filter(CloudExpansion::hasExpansion) + .collect(INDEXED_NAME_COLLECTOR); + } + + @NotNull + @Unmodifiable + public Map getCloudExpansionsByAuthor(@NotNull final String author) + { + if (cache.isEmpty()) + { + return Collections.emptyMap(); + } + + return cache.values() + .stream() + .filter(expansion -> author.equalsIgnoreCase(expansion.getAuthor())) + .collect(INDEXED_NAME_COLLECTOR); + } + + @NotNull + @Unmodifiable + public Set getCloudExpansionAuthors() + { + return cache.values().stream().map(CloudExpansion::getAuthor).collect(Collectors.toSet()); + } + + + public int getCloudExpansionAuthorCount() + { + return getCloudExpansionAuthors().size(); + } + + public int getCloudUpdateCount() + { + return ((int) plugin.getLocalExpansionManager() + .getExpansions() + .stream() + .filter(expansion -> findCloudExpansionByName(expansion.getName()).map(CloudExpansion::shouldUpdate).orElse(false)) + .count()); + } + + + @NotNull + public Optional findCloudExpansionByName(@NotNull final String name) + { + return Optional.ofNullable(cache.get(toIndexName(name))); + } + + + public void clean() + { + cache.clear(); + + await.values().forEach(future -> future.cancel(true)); + await.clear(); + } + + public void fetch(final boolean allowUnverified) + { + plugin.getLogger().info("Fetching available expansion information..."); + + CompletableFuture> future = CompletableFuture.supplyAsync(() -> { + final Map values = new HashMap<>(); + + try + { + //noinspection UnstableApiUsage + final String json = Resources.toString(new URL(API_URL), StandardCharsets.UTF_8); + values.putAll(GSON.fromJson(json, TYPE)); + } + catch (final IOException ex) + { + throw new CompletionException(ex); + } + + values.values().removeIf(value -> value.getLatestVersion() == null || value.getVersion(value.getLatestVersion()) == null); + + return values; + }); + + + if (!allowUnverified) + { + future = future.thenApplyAsync((values) -> { + values.values().removeIf(expansion -> !expansion.isVerified()); + return values; + }); + } + + + future = future.thenApplyAsync((values) -> { + + values.forEach((name, expansion) -> { + expansion.setName(name); + + final Optional local = plugin.getLocalExpansionManager().findExpansionByName(name); + if (local.isPresent() && local.get().isRegistered()) + { + expansion.setHasExpansion(true); + expansion.setShouldUpdate(!local.get().getVersion().equals(expansion.getLatestVersion())); + } + }); + + return values; + }); + + future.whenComplete((expansions, exception) -> { + + if (exception != null) + { + plugin.getLogger().log(Level.WARNING, "failed to download expansion information", exception); + return; + } + + this.cache.putAll(expansions); + }); + } + + public boolean isDownloading(@NotNull final CloudExpansion expansion) + { + return await.containsKey(toIndexName(expansion)); + } + + @NotNull + public CompletableFuture downloadExpansion(@NotNull final CloudExpansion expansion, @NotNull final CloudExpansion.Version version) + { + final CompletableFuture previous = await.get(toIndexName(expansion)); + if (previous != null) + { + return previous; + } + + final File file = new File(plugin.getLocalExpansionManager().getExpansionsFolder(), "Expansion-" + toIndexName(expansion) + ".jar"); + + final CompletableFuture download = CompletableFuture.supplyAsync(() -> { + try (final ReadableByteChannel source = Channels.newChannel(new URL(version.getUrl()).openStream()); final FileOutputStream target = new FileOutputStream(file)) + { + target.getChannel().transferFrom(source, 0, Long.MAX_VALUE); + } + catch (final IOException ex) + { + throw new CompletionException(ex); + } + return file; + }); + + download.whenCompleteAsync((value, exception) -> { + await.remove(toIndexName(expansion)); + + if (exception != null) + { + plugin.getLogger().log(Level.SEVERE, "failed to download " + expansion.getName() + ":" + version.getVersion(), exception); + } + }); + + await.put(toIndexName(expansion), download); + + return download; + } + + + @NotNull + private static String toIndexName(@NotNull final String name) + { + return name.toLowerCase().replace(' ', '_'); + } + + @NotNull + private static String toIndexName(@NotNull final CloudExpansion expansion) + { + return toIndexName(expansion.getName()); + } + +} diff --git a/src/main/java/me/clip/placeholderapi/expansion/manager/LocalExpansionManager.java b/src/main/java/me/clip/placeholderapi/expansion/manager/LocalExpansionManager.java new file mode 100644 index 0000000..c05982a --- /dev/null +++ b/src/main/java/me/clip/placeholderapi/expansion/manager/LocalExpansionManager.java @@ -0,0 +1,385 @@ +package me.clip.placeholderapi.expansion.manager; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import me.clip.placeholderapi.PlaceholderAPIPlugin; +import me.clip.placeholderapi.events.ExpansionRegisterEvent; +import me.clip.placeholderapi.events.ExpansionUnregisterEvent; +import me.clip.placeholderapi.expansion.Cacheable; +import me.clip.placeholderapi.expansion.Cleanable; +import me.clip.placeholderapi.expansion.Configurable; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import me.clip.placeholderapi.expansion.Taskable; +import me.clip.placeholderapi.expansion.VersionSpecific; +import me.clip.placeholderapi.expansion.cloud.CloudExpansion; +import me.clip.placeholderapi.util.FileUtil; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +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.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +import java.io.File; +import java.io.IOException; +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; + +public final class LocalExpansionManager implements Listener +{ + + @NotNull + private static final String EXPANSIONS_FOLDER_NAME = "expansions"; + + + @NotNull + private final File folder; + @NotNull + private final PlaceholderAPIPlugin plugin; + + @NotNull + private final Map expansions = new HashMap<>(); + + + public LocalExpansionManager(@NotNull final PlaceholderAPIPlugin plugin) + { + this.plugin = plugin; + this.folder = new File(plugin.getDataFolder(), EXPANSIONS_FOLDER_NAME); + + if (!this.folder.exists() && !folder.mkdirs()) + { + plugin.getLogger().log(Level.WARNING, "failed to create expansions folder!"); + } + } + + public void load() + { + registerAll(); + } + + public void kill() + { + unregisterAll(); + } + + + @NotNull + public File getExpansionsFolder() + { + return folder; + } + + public int getExpansionsCount() + { + return expansions.size(); + } + + + @NotNull + @Unmodifiable + public Collection getIdentifiers() + { + return ImmutableSet.copyOf(expansions.keySet()); + } + + @NotNull + @Unmodifiable + public Collection getExpansions() + { + return ImmutableSet.copyOf(expansions.values()); + } + + + @Nullable + public PlaceholderExpansion getExpansion(@NotNull final String identifier) + { + return expansions.get(identifier.toLowerCase()); + } + + + @NotNull + public Optional findExpansionByName(@NotNull final String name) + { + return expansions.values().stream().filter(expansion -> name.equalsIgnoreCase(expansion.getName())).findFirst(); + } + + @NotNull + public Optional findExpansionByIdentifier(@NotNull final String identifier) + { + return Optional.ofNullable(getExpansion(identifier)); + } + + + /** + * Do not call this method yourself, use {@link PlaceholderExpansion#register()} + */ + public boolean register(@NotNull final PlaceholderExpansion expansion) + { + final String identifier = expansion.getIdentifier(); + if (identifier == null) + { + return false; + } + + if (expansion instanceof Configurable) + { + Map defaults = ((Configurable) expansion).getDefaults(); + String pre = "expansions." + expansion.getIdentifier() + "."; + FileConfiguration cfg = plugin.getConfig(); + boolean save = false; + + if (defaults != null) + { + for (Map.Entry 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 (expansion instanceof VersionSpecific) + { + VersionSpecific nms = (VersionSpecific) expansion; + if (!nms.isCompatibleWith(PlaceholderAPIPlugin.getServerVersion())) + { + plugin.getLogger().info("Your server version is not compatible with expansion: " + expansion.getIdentifier() + " version: " + expansion.getVersion()); + return false; + } + } + + final ExpansionRegisterEvent event = new ExpansionRegisterEvent(expansion); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled() || expansions.put(expansion.getIdentifier(), expansion) != null) + { + return false; + } + + if (expansion instanceof Listener) + { + Bukkit.getPluginManager().registerEvents(((Listener) expansion), plugin); + } + + plugin.getLogger().info("Successfully registered expansion: " + expansion.getIdentifier()); + + if (expansion instanceof Taskable) + { + ((Taskable) expansion).start(); + } + + if (plugin.getPlaceholderAPIConfig().isCloudEnabled()) + { + final Optional cloudExpansion = plugin.getCloudExpansionManager().findCloudExpansionByName(identifier); + if (cloudExpansion.isPresent()) + { + cloudExpansion.get().setHasExpansion(true); + cloudExpansion.get().setShouldUpdate(!cloudExpansion.get().getLatestVersion().equals(expansion.getVersion())); + } + } + + return true; + } + + public Optional register(@NotNull final Class clazz) + { + final PlaceholderExpansion expansion = createExpansionInstance(clazz); + if (expansion == null || !expansion.register()) + { + return Optional.empty(); + } + + return Optional.of(expansion); + } + + public boolean unregister(@NotNull final PlaceholderExpansion expansion) + { + if (expansions.remove(expansion.getIdentifier()) == null) + { + return false; + } + + + Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(expansion)); + + + if (expansion instanceof Listener) + { + HandlerList.unregisterAll((Listener) expansion); + } + + if (expansion instanceof Taskable) + { + ((Taskable) expansion).stop(); + } + + if (expansion instanceof Cacheable) + { + ((Cacheable) expansion).clear(); + } + + if (plugin.getPlaceholderAPIConfig().isCloudEnabled()) + { + plugin.getCloudExpansionManager().findCloudExpansionByName(expansion.getName()).ifPresent(cloud -> { + cloud.setHasExpansion(false); + cloud.setShouldUpdate(false); + }); + } + + return true; + } + + + private void registerAll() + { + plugin.getLogger().info("Placeholder expansion registration initializing..."); + + findExpansionsOnDisk().whenCompleteAsync((classes, exception) -> { + if (exception != null) + { + plugin.getLogger().log(Level.SEVERE, "failed to load class files of expansions", exception); + return; + } + + Bukkit.getScheduler().runTask(plugin, () -> classes.forEach(this::register)); + }); + } + + private void unregisterAll() + { + for (final PlaceholderExpansion expansion : Sets.newHashSet(expansions.values())) + { + if (expansion.persist()) + { + continue; + } + + unregister(expansion); + } + } + + + @NotNull + public CompletableFuture>> findExpansionsOnDisk() + { + return CompletableFuture.supplyAsync(() -> { + try + { + return FileUtil.getClasses(getExpansionsFolder(), PlaceholderExpansion.class); + } + catch (final IOException | ClassNotFoundException ex) + { + throw new CompletionException(ex); + } + }); + } + + @NotNull + public CompletableFuture>> findExpansionsInFile(@NotNull final File file) + { + return CompletableFuture.supplyAsync(() -> { + try + { + final List<@NotNull Class> classes = FileUtil.getClasses(getExpansionsFolder(), PlaceholderExpansion.class, file.getName()); + if (classes.size() > 1) + { + throw new IllegalStateException("multiple expansion classes in one file!"); + } + + return classes; + } + catch (final Exception ex) + { + throw new CompletionException(ex); + } + }); + } + + + @Nullable + public PlaceholderExpansion createExpansionInstance(@NotNull final Class clazz) + { + try + { + return clazz.getDeclaredConstructor().newInstance(); + } + catch (final Throwable ex) + { + plugin.getLogger().log(Level.SEVERE, "Failed to load placeholder expansion from class: " + clazz.getName(), ex); + return null; + } + } + + + @EventHandler + public void onQuit(@NotNull final PlayerQuitEvent event) + { + for (final PlaceholderExpansion expansion : getExpansions()) + { + if (!(expansion instanceof Cleanable)) + { + continue; + } + + ((Cleanable) expansion).cleanup(event.getPlayer()); + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPluginDisable(@NotNull final PluginDisableEvent event) + { + final String name = event.getPlugin().getName(); + if (name.equals(plugin.getName())) + { + return; + } + + for (final PlaceholderExpansion expansion : getExpansions()) + { + if (!name.equalsIgnoreCase(expansion.getRequiredPlugin())) + { + continue; + } + + unregister(expansion); + plugin.getLogger().info("Unregistered placeholder expansion: " + expansion.getName()); + } + } + +} diff --git a/src/main/java/me/clip/placeholderapi/listeners/PlaceholderListener.java b/src/main/java/me/clip/placeholderapi/listeners/PlaceholderListener.java deleted file mode 100644 index 875c5a1..0000000 --- a/src/main/java/me/clip/placeholderapi/listeners/PlaceholderListener.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * PlaceholderAPI - * Copyright (C) 2019 Ryan McCarthy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - */ -package me.clip.placeholderapi.listeners; - -import me.clip.placeholderapi.PlaceholderAPI; -import me.clip.placeholderapi.PlaceholderAPIPlugin; -import me.clip.placeholderapi.PlaceholderHook; -import me.clip.placeholderapi.events.ExpansionUnregisterEvent; -import me.clip.placeholderapi.expansion.Cacheable; -import me.clip.placeholderapi.expansion.Cleanable; -import me.clip.placeholderapi.expansion.PlaceholderExpansion; -import me.clip.placeholderapi.expansion.Taskable; -import me.clip.placeholderapi.expansion.cloud.CloudExpansion; -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 java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - - -public class PlaceholderListener implements Listener { - - private final PlaceholderAPIPlugin plugin; - - public PlaceholderListener(PlaceholderAPIPlugin instance) { - plugin = instance; - Bukkit.getPluginManager().registerEvents(this, instance); - } - - @EventHandler - public void onExpansionUnregister(ExpansionUnregisterEvent event) { - if (event.getExpansion() instanceof Listener) { - HandlerList.unregisterAll((Listener) event.getExpansion()); - } - - if (event.getExpansion() instanceof Taskable) { - ((Taskable) event.getExpansion()).stop(); - } - - if (event.getExpansion() instanceof Cacheable) { - ((Cacheable) event.getExpansion()).clear(); - } - - if (plugin.getPlaceholderAPIConfig().isCloudEnabled()) { - CloudExpansion ex = plugin.getExpansionCloud().getCloudExpansion(event.getExpansion().getName()).orElse(null); - if (ex != null) { - ex.setHasExpansion(false); - ex.setShouldUpdate(false); - } - } - } - - @EventHandler(priority = EventPriority.HIGH) - public void onPluginUnload(PluginDisableEvent e) { - String n = e.getPlugin().getName(); - - if (n.equals(plugin.getName())) { - return; - } - - Map hooks = PlaceholderAPI.getPlaceholders(); - - for (Entry entry : hooks.entrySet()) { - PlaceholderHook hook = entry.getValue(); - - if (hook instanceof PlaceholderExpansion) { - PlaceholderExpansion expansion = (PlaceholderExpansion) hook; - - if (expansion.getRequiredPlugin() == null) { - continue; - } - - if (expansion.getRequiredPlugin().equalsIgnoreCase(n)) { - if (PlaceholderAPI.unregisterExpansion(expansion)) { - plugin.getLogger().info("Unregistered placeholder expansion: " + expansion.getIdentifier()); - } - } - } - } - } - - @EventHandler - public void onQuit(PlayerQuitEvent e) { - Set expansions = PlaceholderAPI.getExpansions(); - - if (expansions.isEmpty()) { - return; - } - - for (PlaceholderExpansion ex : expansions) { - if (ex instanceof Cleanable) { - ((Cleanable) ex).cleanup(e.getPlayer()); - } - } - } -} diff --git a/src/main/java/me/clip/placeholderapi/listeners/ServerLoadEventListener.java b/src/main/java/me/clip/placeholderapi/listeners/ServerLoadEventListener.java index 018e452..c916214 100644 --- a/src/main/java/me/clip/placeholderapi/listeners/ServerLoadEventListener.java +++ b/src/main/java/me/clip/placeholderapi/listeners/ServerLoadEventListener.java @@ -55,7 +55,7 @@ public final class ServerLoadEventListener implements Listener public void onServerLoad(@NotNull final ServerLoadEvent event) { HandlerList.unregisterAll(this); - plugin.getExpansionManager().initializeExpansions(); + plugin.getLocalExpansionManager().load(); } } diff --git a/src/main/java/me/clip/placeholderapi/util/FileUtil.java b/src/main/java/me/clip/placeholderapi/util/FileUtil.java index 70cf792..3510715 100644 --- a/src/main/java/me/clip/placeholderapi/util/FileUtil.java +++ b/src/main/java/me/clip/placeholderapi/util/FileUtil.java @@ -38,45 +38,33 @@ public class FileUtil { @NotNull - public static List<@NotNull Class> getClasses(@NotNull final File folder, @NotNull final Class clazz) + public static List<@NotNull Class> getClasses(@NotNull final File folder, @NotNull final Class clazz) throws IOException, ClassNotFoundException { return getClasses(folder, clazz, null); } @NotNull - public static List<@NotNull Class> getClasses(@NotNull final File folder, @NotNull final Class clazz, @Nullable final String target) + public static List<@NotNull Class> getClasses(@NotNull final File folder, @NotNull final Class clazz, @Nullable final String target) throws IOException, ClassNotFoundException { if (!folder.exists()) { return Collections.emptyList(); } - try + final File[] jars = folder.listFiles((dir, name) -> name.endsWith(".jar") && (target == null || name.replace(".jar", "").equalsIgnoreCase(target.replace(".jar", "")))); + if (jars == null) { - final FilenameFilter filter = - (dir, name) -> name.endsWith(".jar") && (target == null || name.replace(".jar", "").equalsIgnoreCase(target.replace(".jar", ""))); - - final File[] jars = folder.listFiles(filter); - if (jars == null) - { - return Collections.emptyList(); - } - - final List<@NotNull Class> list = new ArrayList<>(); - - for (File file : jars) - { - gather(file.toURI().toURL(), clazz, list); - } - - return list; - } - catch (final Throwable ex) - { - ex.printStackTrace(); + return Collections.emptyList(); } - return Collections.emptyList(); + final List<@NotNull Class> list = new ArrayList<>(); + + for (final File file : jars) + { + gather(file.toURI().toURL(), clazz, list); + } + + return list; } private static void gather(@NotNull final URL jar, @NotNull final Class clazz, @NotNull final List<@NotNull Class> list) throws IOException, ClassNotFoundException @@ -101,7 +89,8 @@ public class FileUtil } } catch (final NoClassDefFoundError ignored) - { } + { + } } } }