mirror of
				https://github.com/PlaceholderAPI/PlaceholderAPI
				synced 2025-10-31 06:12:28 +01:00 
			
		
		
		
	updated managers to make more sense, removed old
This commit is contained in:
		| @@ -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<String, PlaceholderHook> 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<String> 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<String, PlaceholderHook> 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<PlaceholderHook> 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); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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<String, Integer>         map   = new HashMap<>(); | ||||
| 							Map<String, PlaceholderHook> hooks = PlaceholderAPI.getPlaceholders(); | ||||
|  | ||||
| 			Map<String, Integer>         map   = new HashMap<>(); | ||||
| 			Map<String, PlaceholderHook> 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; | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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<String> params) | ||||
| 	{ | ||||
| 		plugin.getExpansionCloud().clean(); | ||||
| 		plugin.getCloudExpansionManager().clean(); | ||||
| 		Msg.msg(sender, | ||||
| 				"&aThe eCloud cache has been cleared!"); | ||||
| 	} | ||||
|   | ||||
| @@ -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<String> names = plugin.getExpansionCloud().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); | ||||
| 			final Stream<String> 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<CloudExpansion> expansion = plugin.getExpansionCloud().getCloudExpansion(params.get(0)); | ||||
| 		final Optional<CloudExpansion> expansion = plugin.getCloudExpansionManager().findCloudExpansionByName(params.get(0)); | ||||
| 		if (!expansion.isPresent()) | ||||
| 		{ | ||||
| 			return; | ||||
|   | ||||
| @@ -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<String> names = plugin.getExpansionCloud().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); | ||||
| 			final Stream<String> 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<CloudExpansion> expansion = plugin.getExpansionCloud().getCloudExpansion(params.get(0)); | ||||
| 		final Optional<CloudExpansion> expansion = plugin.getCloudExpansionManager().findCloudExpansionByName(params.get(0)); | ||||
| 		if (!expansion.isPresent()) | ||||
| 		{ | ||||
| 			return; | ||||
|   | ||||
| @@ -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<CloudExpansion> getPage(@NotNull final List<CloudExpansion> 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<CloudExpansion> 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<CloudExpansion> 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<String> params) | ||||
| @@ -45,8 +135,7 @@ public final class CommandECloudExpansionList extends PlaceholderCommand | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		@Unmodifiable final Map<Integer, CloudExpansion> expansions = getExpansions(params.get(0), plugin); | ||||
| 		final List<CloudExpansion> 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<CloudExpansion> 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<Integer, CloudExpansion> 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<CloudExpansion> getPage(@NotNull final Map<Integer, CloudExpansion> 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<Integer, CloudExpansion> 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)); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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<String> names = plugin.getExpansionCloud().getCloudExpansions().values().stream().map(CloudExpansion::getName).map(name -> name.replace(' ', '_')); | ||||
| 		final Stream<String> names = plugin.getCloudExpansionManager() | ||||
| 										   .getCloudExpansions() | ||||
| 										   .values() | ||||
| 										   .stream() | ||||
| 										   .map(CloudExpansion::getName) | ||||
| 										   .map(name -> name.replace(' ', '_')); | ||||
|  | ||||
| 		suggestByParameter(names, suggestions, params.isEmpty() ? null : params.get(0)); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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<String> 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!"); | ||||
|   | ||||
| @@ -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<String> 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(); | ||||
|   | ||||
| @@ -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<String> 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")); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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<PlaceholderExpansion> 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; | ||||
|   | ||||
| @@ -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<PlaceholderExpansion> 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 | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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 <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
| 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<String, PlaceholderHook> registered = PlaceholderAPI.getPlaceholders(); | ||||
| 		registerAllExpansions(); | ||||
|  | ||||
| 		if (!registered.isEmpty()) { | ||||
| 			registered.forEach(PlaceholderAPI::registerPlaceholderHook); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| 	public PlaceholderExpansion getRegisteredExpansion(String name) | ||||
| 	{ | ||||
| 		for (Entry<String, PlaceholderHook> hook : PlaceholderAPI.getPlaceholders().entrySet()) | ||||
| 		{ | ||||
| 			if (hook.getValue() instanceof PlaceholderExpansion) | ||||
| 			{ | ||||
| 				if (name.equalsIgnoreCase(hook.getKey())) | ||||
| 				{ | ||||
| 					return (PlaceholderExpansion) hook.getValue(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return null; | ||||
| 	} | ||||
|  | ||||
| 	public boolean registerExpansion(@NotNull final PlaceholderExpansion expansion) | ||||
| 	{ | ||||
| 		if (expansion.getIdentifier() == null) | ||||
| 		{ | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (expansion instanceof Configurable) | ||||
| 		{ | ||||
| 			Map<String, Object> defaults = ((Configurable) expansion).getDefaults(); | ||||
| 			String              pre      = "expansions." + expansion.getIdentifier() + "."; | ||||
| 			FileConfiguration   cfg      = plugin.getConfig(); | ||||
| 			boolean             save     = false; | ||||
|  | ||||
| 			if (defaults != null) | ||||
| 			{ | ||||
| 				for (Entry<String, Object> entries : defaults.entrySet()) | ||||
| 				{ | ||||
| 					if (entries.getKey() == null || entries.getKey().isEmpty()) | ||||
| 					{ | ||||
| 						continue; | ||||
| 					} | ||||
|  | ||||
| 					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<Class<? extends PlaceholderExpansion>> 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<? extends PlaceholderExpansion>> subs = FileUtil.getClasses(folder, PlaceholderExpansion.class); | ||||
| 		if (subs.isEmpty()) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		for (final Class<? extends PlaceholderExpansion> 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<? extends PlaceholderExpansion> 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; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -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); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -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 <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
| 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<Integer, CloudExpansion>                 expansions  = new TreeMap<>(); | ||||
| 	@NotNull | ||||
| 	private final Map<CloudExpansion, CompletableFuture<File>> 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<Integer, CloudExpansion> getCloudExpansions() | ||||
| 	{ | ||||
| 		return ImmutableMap.copyOf(expansions); | ||||
| 	} | ||||
|  | ||||
| 	@NotNull | ||||
| 	@Unmodifiable | ||||
| 	public Set<String> 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<CloudExpansion> 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<Integer, CloudExpansion> 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<Integer, CloudExpansion> 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<String, CloudExpansion> data = new HashMap<>(); | ||||
|  | ||||
| 			try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(API_URL).openStream()))) | ||||
| 			{ | ||||
| 				data.putAll(GSON.fromJson(reader, new TypeToken<Map<String, CloudExpansion>>() | ||||
| 				{ | ||||
| 				}.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<CloudExpansion> 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<File> previous = downloading.get(expansion); | ||||
| 		if (previous != null) | ||||
| 		{ | ||||
| 			return previous; | ||||
| 		} | ||||
|  | ||||
| 		final File file = new File(folder, "Expansion-" + expansion.getName() + ".jar"); | ||||
|  | ||||
| 		final CompletableFuture<File> 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; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -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<Map<String, CloudExpansion>>() {}.getType(); | ||||
|  | ||||
| 	@NotNull | ||||
| 	private final Collector<CloudExpansion, ?, Map<String, CloudExpansion>> INDEXED_NAME_COLLECTOR = Collectors.toMap(CloudExpansionManager::toIndexName, Function.identity()); | ||||
|  | ||||
|  | ||||
| 	@NotNull | ||||
| 	private final PlaceholderAPIPlugin plugin; | ||||
|  | ||||
| 	@NotNull | ||||
| 	private final Map<String, CloudExpansion>          cache = new HashMap<>(); | ||||
| 	@NotNull | ||||
| 	private final Map<String, CompletableFuture<File>> 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<String, CloudExpansion> getCloudExpansions() | ||||
| 	{ | ||||
| 		return ImmutableMap.copyOf(cache); | ||||
| 	} | ||||
|  | ||||
| 	@NotNull | ||||
| 	@Unmodifiable | ||||
| 	public Map<String, CloudExpansion> getCloudExpansionsInstalled() | ||||
| 	{ | ||||
| 		if (cache.isEmpty()) | ||||
| 		{ | ||||
| 			return Collections.emptyMap(); | ||||
| 		} | ||||
|  | ||||
| 		return cache.values() | ||||
| 					.stream() | ||||
| 					.filter(CloudExpansion::hasExpansion) | ||||
| 					.collect(INDEXED_NAME_COLLECTOR); | ||||
| 	} | ||||
|  | ||||
| 	@NotNull | ||||
| 	@Unmodifiable | ||||
| 	public Map<String, CloudExpansion> 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<String> 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<CloudExpansion> 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<Map<String, CloudExpansion>> future = CompletableFuture.supplyAsync(() -> { | ||||
| 			final Map<String, CloudExpansion> 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<PlaceholderExpansion> 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<File> downloadExpansion(@NotNull final CloudExpansion expansion, @NotNull final CloudExpansion.Version version) | ||||
| 	{ | ||||
| 		final CompletableFuture<File> previous = await.get(toIndexName(expansion)); | ||||
| 		if (previous != null) | ||||
| 		{ | ||||
| 			return previous; | ||||
| 		} | ||||
|  | ||||
| 		final File file = new File(plugin.getLocalExpansionManager().getExpansionsFolder(), "Expansion-" + toIndexName(expansion) + ".jar"); | ||||
|  | ||||
| 		final CompletableFuture<File> 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()); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -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<String, PlaceholderExpansion> 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<String> getIdentifiers() | ||||
| 	{ | ||||
| 		return ImmutableSet.copyOf(expansions.keySet()); | ||||
| 	} | ||||
|  | ||||
| 	@NotNull | ||||
| 	@Unmodifiable | ||||
| 	public Collection<PlaceholderExpansion> getExpansions() | ||||
| 	{ | ||||
| 		return ImmutableSet.copyOf(expansions.values()); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	@Nullable | ||||
| 	public PlaceholderExpansion getExpansion(@NotNull final String identifier) | ||||
| 	{ | ||||
| 		return expansions.get(identifier.toLowerCase()); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	@NotNull | ||||
| 	public Optional<PlaceholderExpansion> findExpansionByName(@NotNull final String name) | ||||
| 	{ | ||||
| 		return expansions.values().stream().filter(expansion -> name.equalsIgnoreCase(expansion.getName())).findFirst(); | ||||
| 	} | ||||
|  | ||||
| 	@NotNull | ||||
| 	public Optional<PlaceholderExpansion> 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<String, Object> defaults = ((Configurable) expansion).getDefaults(); | ||||
| 			String              pre      = "expansions." + expansion.getIdentifier() + "."; | ||||
| 			FileConfiguration   cfg      = plugin.getConfig(); | ||||
| 			boolean             save     = false; | ||||
|  | ||||
| 			if (defaults != null) | ||||
| 			{ | ||||
| 				for (Map.Entry<String, Object> entries : defaults.entrySet()) | ||||
| 				{ | ||||
| 					if (entries.getKey() == null || entries.getKey().isEmpty()) | ||||
| 					{ | ||||
| 						continue; | ||||
| 					} | ||||
|  | ||||
| 					if (entries.getValue() == null) | ||||
| 					{ | ||||
| 						if (cfg.contains(pre + entries.getKey())) | ||||
| 						{ | ||||
| 							save = true; | ||||
| 							cfg.set(pre + entries.getKey(), null); | ||||
| 						} | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						if (!cfg.contains(pre + entries.getKey())) | ||||
| 						{ | ||||
| 							save = true; | ||||
| 							cfg.set(pre + entries.getKey(), entries.getValue()); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (save) | ||||
| 			{ | ||||
| 				plugin.saveConfig(); | ||||
| 				plugin.reloadConfig(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (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> 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<PlaceholderExpansion> register(@NotNull final Class<? extends PlaceholderExpansion> 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<List<Class<? extends PlaceholderExpansion>>> findExpansionsOnDisk() | ||||
| 	{ | ||||
| 		return CompletableFuture.supplyAsync(() -> { | ||||
| 			try | ||||
| 			{ | ||||
| 				return FileUtil.getClasses(getExpansionsFolder(), PlaceholderExpansion.class); | ||||
| 			} | ||||
| 			catch (final IOException | ClassNotFoundException ex) | ||||
| 			{ | ||||
| 				throw new CompletionException(ex); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	@NotNull | ||||
| 	public CompletableFuture<List<Class<? extends PlaceholderExpansion>>> findExpansionsInFile(@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; | ||||
| 			} | ||||
| 			catch (final Exception ex) | ||||
| 			{ | ||||
| 				throw new CompletionException(ex); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	@Nullable | ||||
| 	public PlaceholderExpansion createExpansionInstance(@NotNull final Class<? extends PlaceholderExpansion> 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()); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -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 <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
| 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<String, PlaceholderHook> hooks = PlaceholderAPI.getPlaceholders(); | ||||
|  | ||||
|         for (Entry<String, PlaceholderHook> entry : hooks.entrySet()) { | ||||
|             PlaceholderHook hook = entry.getValue(); | ||||
|  | ||||
|             if (hook instanceof PlaceholderExpansion) { | ||||
|                 PlaceholderExpansion expansion = (PlaceholderExpansion) hook; | ||||
|  | ||||
|                 if (expansion.getRequiredPlugin() == null) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (expansion.getRequiredPlugin().equalsIgnoreCase(n)) { | ||||
|                     if (PlaceholderAPI.unregisterExpansion(expansion)) { | ||||
|                         plugin.getLogger().info("Unregistered placeholder expansion: " + expansion.getIdentifier()); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @EventHandler | ||||
|     public void onQuit(PlayerQuitEvent e) { | ||||
|         Set<PlaceholderExpansion> expansions = PlaceholderAPI.getExpansions(); | ||||
|  | ||||
|         if (expansions.isEmpty()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         for (PlaceholderExpansion ex : expansions) { | ||||
|             if (ex instanceof Cleanable) { | ||||
|                 ((Cleanable) ex).cleanup(e.getPlayer()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -38,45 +38,33 @@ public class FileUtil | ||||
| { | ||||
|  | ||||
| 	@NotNull | ||||
| 	public static <T> List<@NotNull Class<? extends T>> getClasses(@NotNull final File folder, @NotNull final Class<T> clazz) | ||||
| 	public static <T> List<@NotNull Class<? extends T>> getClasses(@NotNull final File folder, @NotNull final Class<T> clazz) throws IOException, ClassNotFoundException | ||||
| 	{ | ||||
| 		return getClasses(folder, clazz, null); | ||||
| 	} | ||||
|  | ||||
| 	@NotNull | ||||
| 	public static <T> List<@NotNull Class<? extends T>> getClasses(@NotNull final File folder, @NotNull final Class<T> clazz, @Nullable final String target) | ||||
| 	public static <T> List<@NotNull Class<? extends T>> getClasses(@NotNull final File folder, @NotNull final Class<T> 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<? extends T>> 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<? extends T>> list = new ArrayList<>(); | ||||
|  | ||||
| 		for (final File file : jars) | ||||
| 		{ | ||||
| 			gather(file.toURI().toURL(), clazz, list); | ||||
| 		} | ||||
|  | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	private static <T> void gather(@NotNull final URL jar, @NotNull final Class<T> clazz, @NotNull final List<@NotNull Class<? extends T>> list) throws IOException, ClassNotFoundException | ||||
| @@ -101,7 +89,8 @@ public class FileUtil | ||||
| 					} | ||||
| 				} | ||||
| 				catch (final NoClassDefFoundError ignored) | ||||
| 				{ } | ||||
| 				{ | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user