mirror of
https://github.com/filoghost/ChestCommands.git
synced 2024-11-22 10:05:17 +01:00
API improvements
This commit is contained in:
parent
f415e4afe2
commit
ec057ea2e7
@ -53,18 +53,24 @@ public class ChestCommandsAPI {
|
|||||||
* Menus loaded by Chest Commands from the menus folder always display placeholders, including those registered
|
* Menus loaded by Chest Commands from the menus folder always display placeholders, including those registered
|
||||||
* through this method.
|
* through this method.
|
||||||
* <p>
|
* <p>
|
||||||
* The identifier is automatically converted to the appropriate placeholder format. For example, given the
|
* The identifier is used to compute which placeholder formats will invoke the replacer callback. For example, given
|
||||||
* identifier "test", the callback would be invoked to replace the the following placeholders:
|
* the identifier "test", the callback would be invoked to replace the following placeholders (case insensitive):
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{test}
|
* <li>{test}
|
||||||
* <li>{test: 123}
|
* <li>{test: argument}
|
||||||
* <li>{test: hello world}
|
* <li>{pluginName/test}
|
||||||
|
* <li>{pluginName/test: argument}
|
||||||
* </ul>
|
* </ul>
|
||||||
|
* The plugin name is used as optional namespace, to distinguish two placeholders with the same identifier but
|
||||||
|
* registered by distinct plugins.
|
||||||
|
* <p>
|
||||||
|
* This replaces any currently registered placeholder with the same plugin and identifier.
|
||||||
*
|
*
|
||||||
* @param plugin the plugin registering the placeholder
|
* @param plugin the plugin registering the placeholder
|
||||||
* @param identifier the identifier of the placeholder, which can only contain letters, digits and
|
* @param identifier the identifier of the placeholder, which can only contain letters, digits and
|
||||||
* underscores
|
* underscores
|
||||||
* @param placeholderReplacer the callback that returns the displayed value
|
* @param placeholderReplacer the callback that returns the displayed value
|
||||||
|
* @throws IllegalArgumentException if the identifier contains invalid characters
|
||||||
* @see PlaceholderReplacer#getReplacement(Player, String)
|
* @see PlaceholderReplacer#getReplacement(Player, String)
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
@ -74,12 +80,11 @@ public class ChestCommandsAPI {
|
|||||||
BackendAPI.getImplementation().registerPlaceholder(plugin, identifier, placeholderReplacer);
|
BackendAPI.getImplementation().registerPlaceholder(plugin, identifier, placeholderReplacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if a menu with a given file name exists and was loaded successfully by Chest Commands from the menus
|
* Returns if a menu with a given file name exists and was loaded successfully by Chest Commands from the menus
|
||||||
* folder.
|
* folder.
|
||||||
*
|
*
|
||||||
* @param menuFileName the file name of the menu to check
|
* @param menuFileName the file name of the menu to check, including the {@code .yml} file extension
|
||||||
* @return true if the menu exists, false otherwise
|
* @return true if the menu exists, false otherwise
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
@ -94,7 +99,7 @@ public class ChestCommandsAPI {
|
|||||||
* <b>WARNING</b>: this method opens the menu without checking the permissions of the player.
|
* <b>WARNING</b>: this method opens the menu without checking the permissions of the player.
|
||||||
*
|
*
|
||||||
* @param player the player that will see the menu
|
* @param player the player that will see the menu
|
||||||
* @param menuFileName the file name of the menu to open
|
* @param menuFileName the file name of the menu to open, including the {@code .yml} file extension
|
||||||
* @return true if the menu was found and opened successfully, false otherwise
|
* @return true if the menu was found and opened successfully, false otherwise
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
|
@ -8,30 +8,34 @@ package me.filoghost.chestcommands.api;
|
|||||||
import me.filoghost.chestcommands.api.internal.BackendAPI;
|
import me.filoghost.chestcommands.api.internal.BackendAPI;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menus are containers of {@link Icon}s that can be displayed to players as unmodifiable inventories.
|
* Menus are containers of {@link Icon}s that can be displayed to players as unmodifiable inventories, organized as a
|
||||||
|
* grid with a number of rows and columns.
|
||||||
* <p>
|
* <p>
|
||||||
* It is not recommended to implement this interface, use the provided constructor {@link Menu#create(Plugin, String,
|
* This interface should not be implemented, use the provided constructor {@link Menu#create(Plugin, String, int)}. Any
|
||||||
* int)}.
|
* custom implementation will not be handled by Chest Commands' event listener, which relies on internal details. New
|
||||||
|
* methods may also be added, making existing custom implementations incompatible.
|
||||||
*
|
*
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
public interface Menu {
|
public interface Menu {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new menu.
|
* Creates a new menu.
|
||||||
*
|
*
|
||||||
* @param owner the plugin creating the menu
|
* @param plugin the plugin creating the menu
|
||||||
* @param title title of the menu that will be displayed in the inventory
|
* @param title title of the menu that appears in the displayed inventory
|
||||||
* @param rowCount number of rows in the menu (the number of columns is always 9, currently)
|
* @param rows number of rows in the menu (the number of columns is always 9, currently)
|
||||||
* @return the created menu
|
* @return the created menu
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
static @NotNull Menu create(@NotNull Plugin owner, @NotNull String title, int rowCount) {
|
static @NotNull Menu create(@NotNull Plugin plugin, @NotNull String title, int rows) {
|
||||||
return BackendAPI.getImplementation().createMenu(owner, title, rowCount);
|
return BackendAPI.getImplementation().createMenu(plugin, title, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,6 +44,8 @@ public interface Menu {
|
|||||||
* @param row the row position
|
* @param row the row position
|
||||||
* @param column the column position
|
* @param column the column position
|
||||||
* @param icon the new icon, null to remove the current one
|
* @param icon the new icon, null to remove the current one
|
||||||
|
* @throws IndexOutOfBoundsException if the row or the column is outside the limits ({@code row < 0 || row >=
|
||||||
|
* getRows() || column < 0 || column >= getColumns()})
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
void setIcon(int row, int column, @Nullable Icon icon);
|
void setIcon(int row, int column, @Nullable Icon icon);
|
||||||
@ -50,39 +56,17 @@ public interface Menu {
|
|||||||
* @param row the row position
|
* @param row the row position
|
||||||
* @param column the column position
|
* @param column the column position
|
||||||
* @return the icon at the give position, null if absent
|
* @return the icon at the give position, null if absent
|
||||||
|
* @throws IndexOutOfBoundsException if the row or the column is outside the limits ({@code row < 0 || row >=
|
||||||
|
* getRows() || column < 0 || column >= getColumns()})
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
@Nullable Icon getIcon(int row, int column);
|
@Nullable Icon getIcon(int row, int column);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the title of the displayed inventory.
|
|
||||||
*
|
|
||||||
* @return the title
|
|
||||||
* @since 1
|
|
||||||
*/
|
|
||||||
@NotNull String getTitle();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the amount of rows of the displayed inventory.
|
|
||||||
*
|
|
||||||
* @return the amount of rows
|
|
||||||
* @since 1
|
|
||||||
*/
|
|
||||||
int getRowCount();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the amount of columns of the displayed inventory.
|
|
||||||
*
|
|
||||||
* @return the amount of columns
|
|
||||||
* @since 1
|
|
||||||
*/
|
|
||||||
int getColumnCount();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the menu to a player, creating a rendering of this menu and its icons.
|
* Displays the menu to a player, creating a rendering of this menu and its icons.
|
||||||
* <p>
|
* <p>
|
||||||
* If icons are added, removed or changed after the menu is displayed to a player, the view is not updated
|
* If icons are added, removed or changed after the menu is displayed to a player, the view is not updated
|
||||||
* automatically and you may want to invoke {@link Menu#refreshOpenMenuViews()}.
|
* automatically and you may want to invoke {@link Menu#refreshOpenViews()}.
|
||||||
*
|
*
|
||||||
* @param player the player to which the menu will be displayed
|
* @param player the player to which the menu will be displayed
|
||||||
* @return the newly created view for the player
|
* @return the newly created view for the player
|
||||||
@ -97,10 +81,42 @@ public interface Menu {
|
|||||||
* This method should be called after adding, removing or changing one or more icons to update the open menu views
|
* This method should be called after adding, removing or changing one or more icons to update the open menu views
|
||||||
* of players.
|
* of players.
|
||||||
* <p>
|
* <p>
|
||||||
* This method invokes {@link MenuView#refresh()} on each open view created by this menu.
|
* This method invokes {@link MenuView#refresh()} on each currently open view created by this menu.
|
||||||
*
|
*
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
void refreshOpenMenuViews();
|
void refreshOpenViews();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of rows of the displayed inventory.
|
||||||
|
*
|
||||||
|
* @return the amount of rows
|
||||||
|
* @since 1
|
||||||
|
*/
|
||||||
|
int getRows();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of columns of the displayed inventory.
|
||||||
|
*
|
||||||
|
* @return the amount of columns
|
||||||
|
* @since 1
|
||||||
|
*/
|
||||||
|
int getColumns();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the title of the displayed inventory.
|
||||||
|
*
|
||||||
|
* @return the title
|
||||||
|
* @since 1
|
||||||
|
*/
|
||||||
|
@NotNull String getTitle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the plugin that created the menu.
|
||||||
|
*
|
||||||
|
* @return the plugin that created the menu
|
||||||
|
* @since 1
|
||||||
|
*/
|
||||||
|
Plugin getPlugin();
|
||||||
|
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ public interface MenuView {
|
|||||||
* player and you want to refresh the money placeholder instantly.
|
* player and you want to refresh the money placeholder instantly.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that {@link ClickHandler} exposes the menu view being interacted with, so you don't need to refresh all the
|
* Note that {@link ClickHandler} exposes the menu view being interacted with, so you don't need to refresh all the
|
||||||
* views of a menu through {@link Menu#refreshOpenMenuViews()}.
|
* views of a menu through {@link Menu#refreshOpenViews()}.
|
||||||
*
|
*
|
||||||
* @since 1
|
* @since 1
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +27,8 @@ public interface PlaceholderReplacer {
|
|||||||
* <p>
|
* <p>
|
||||||
* If this method returns null, the placeholder is not replaced. It is preferred to return a descriptive error
|
* If this method returns null, the placeholder is not replaced. It is preferred to return a descriptive error
|
||||||
* message rather than returning null.
|
* message rather than returning null.
|
||||||
|
* <p>
|
||||||
|
* <b>Warning</b>: this method should be performance efficient, as it may be invoked quite often.
|
||||||
*
|
*
|
||||||
* @param player the player viewing the placeholder
|
* @param player the player viewing the placeholder
|
||||||
* @param argument the argument inside the placeholder, if present
|
* @param argument the argument inside the placeholder, if present
|
||||||
|
@ -42,7 +42,7 @@ public abstract class BackendAPI {
|
|||||||
|
|
||||||
public abstract boolean openPluginMenu(@NotNull Player player, @NotNull String menuFileName);
|
public abstract boolean openPluginMenu(@NotNull Player player, @NotNull String menuFileName);
|
||||||
|
|
||||||
public abstract @NotNull Menu createMenu(@NotNull Plugin owner, @NotNull String title, int rows);
|
public abstract @NotNull Menu createMenu(@NotNull Plugin plugin, @NotNull String title, int rows);
|
||||||
|
|
||||||
public abstract @NotNull ConfigurableIcon createConfigurableIcon(@NotNull Material material);
|
public abstract @NotNull ConfigurableIcon createConfigurableIcon(@NotNull Material material);
|
||||||
|
|
||||||
|
@ -75,7 +75,6 @@
|
|||||||
<module name="EqualsAvoidNull"/>
|
<module name="EqualsAvoidNull"/>
|
||||||
<module name="EqualsHashCode"/>
|
<module name="EqualsHashCode"/>
|
||||||
<module name="FallThrough"/>
|
<module name="FallThrough"/>
|
||||||
<module name="IllegalCatch"/>
|
|
||||||
<module name="IllegalThrows"/>
|
<module name="IllegalThrows"/>
|
||||||
<module name="IllegalToken"/>
|
<module name="IllegalToken"/>
|
||||||
<module name="IllegalType"/>
|
<module name="IllegalType"/>
|
||||||
|
@ -184,7 +184,7 @@ public class ChestCommands extends BaseJavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Plugin getPluginInstance() {
|
public static Plugin getInstance() {
|
||||||
return pluginInstance;
|
return pluginInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ public class DefaultBackendAPI extends BackendAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Menu createMenu(@NotNull Plugin owner, @NotNull String title, int rows) {
|
public @NotNull Menu createMenu(@NotNull Plugin plugin, @NotNull String title, int rows) {
|
||||||
return new APIMenu(owner, title, rows);
|
return new APIMenu(plugin, title, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -63,7 +63,9 @@ public class DefaultBackendAPI extends BackendAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerPlaceholder(@NotNull Plugin plugin, @NotNull String identifier, @NotNull PlaceholderReplacer placeholderReplacer) {
|
public void registerPlaceholder(@NotNull Plugin plugin,
|
||||||
|
@NotNull String identifier,
|
||||||
|
@NotNull PlaceholderReplacer placeholderReplacer) {
|
||||||
PlaceholderManager.registerPluginPlaceholder(plugin, identifier, placeholderReplacer);
|
PlaceholderManager.registerPluginPlaceholder(plugin, identifier, placeholderReplacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public class OpenMenuAction implements Action {
|
|||||||
* Delay the task, since this action is executed in ClickInventoryEvent
|
* Delay the task, since this action is executed in ClickInventoryEvent
|
||||||
* and opening another inventory in the same moment is not a good idea.
|
* and opening another inventory in the same moment is not a good idea.
|
||||||
*/
|
*/
|
||||||
Bukkit.getScheduler().runTask(ChestCommands.getPluginInstance(), () -> {
|
Bukkit.getScheduler().runTask(ChestCommands.getInstance(), () -> {
|
||||||
menu.openCheckingPermission(player);
|
menu.openCheckingPermission(player);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class CommandHandler extends MultiCommandManager {
|
|||||||
@Override
|
@Override
|
||||||
protected void sendNoArgsMessage(CommandSender sender, String rootCommandLabel) {
|
protected void sendNoArgsMessage(CommandSender sender, String rootCommandLabel) {
|
||||||
sender.sendMessage(ChestCommands.CHAT_PREFIX);
|
sender.sendMessage(ChestCommands.CHAT_PREFIX);
|
||||||
sender.sendMessage(ChatColor.GREEN + "Version: " + ChatColor.GRAY + ChestCommands.getPluginInstance().getDescription().getVersion());
|
sender.sendMessage(ChatColor.GREEN + "Version: " + ChatColor.GRAY + ChestCommands.getInstance().getDescription().getVersion());
|
||||||
sender.sendMessage(ChatColor.GREEN + "Developer: " + ChatColor.GRAY + "filoghost");
|
sender.sendMessage(ChatColor.GREEN + "Developer: " + ChatColor.GRAY + "filoghost");
|
||||||
sender.sendMessage(ChatColor.GREEN + "Commands: " + ChatColor.GRAY + "/" + rootCommandLabel + " help");
|
sender.sendMessage(ChatColor.GREEN + "Commands: " + ChatColor.GRAY + "/" + rootCommandLabel + " help");
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ public enum BungeeCordHook implements PluginHook {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setup() {
|
public void setup() {
|
||||||
if (!Bukkit.getMessenger().isOutgoingChannelRegistered(ChestCommands.getPluginInstance(), BUNGEE_CORD_CHANNEL)) {
|
if (!Bukkit.getMessenger().isOutgoingChannelRegistered(ChestCommands.getInstance(), BUNGEE_CORD_CHANNEL)) {
|
||||||
Bukkit.getMessenger().registerOutgoingPluginChannel(ChestCommands.getPluginInstance(), BUNGEE_CORD_CHANNEL);
|
Bukkit.getMessenger().registerOutgoingPluginChannel(ChestCommands.getInstance(), BUNGEE_CORD_CHANNEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ public enum BungeeCordHook implements PluginHook {
|
|||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendPluginMessage(ChestCommands.getPluginInstance(), BUNGEE_CORD_CHANNEL, byteArrayOutputStream.toByteArray());
|
player.sendPluginMessage(ChestCommands.getInstance(), BUNGEE_CORD_CHANNEL, byteArrayOutputStream.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,6 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a particular view of a menu.
|
|
||||||
*/
|
|
||||||
public class DefaultMenuView implements MenuView {
|
public class DefaultMenuView implements MenuView {
|
||||||
|
|
||||||
private final BaseMenu menu;
|
private final BaseMenu menu;
|
||||||
@ -26,7 +23,7 @@ public class DefaultMenuView implements MenuView {
|
|||||||
public DefaultMenuView(@NotNull BaseMenu menu, @NotNull Player viewer) {
|
public DefaultMenuView(@NotNull BaseMenu menu, @NotNull Player viewer) {
|
||||||
this.menu = menu;
|
this.menu = menu;
|
||||||
this.viewer = viewer;
|
this.viewer = viewer;
|
||||||
this.bukkitInventory = new InventoryGrid(new MenuInventoryHolder(this), menu.getRowCount(), menu.getTitle());
|
this.bukkitInventory = new InventoryGrid(new MenuInventoryHolder(this), menu.getRows(), menu.getTitle());
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,13 @@ package me.filoghost.chestcommands.listener;
|
|||||||
import me.filoghost.chestcommands.ChestCommands;
|
import me.filoghost.chestcommands.ChestCommands;
|
||||||
import me.filoghost.chestcommands.api.ClickResult;
|
import me.filoghost.chestcommands.api.ClickResult;
|
||||||
import me.filoghost.chestcommands.api.Icon;
|
import me.filoghost.chestcommands.api.Icon;
|
||||||
|
import me.filoghost.chestcommands.api.Menu;
|
||||||
import me.filoghost.chestcommands.config.Settings;
|
import me.filoghost.chestcommands.config.Settings;
|
||||||
import me.filoghost.chestcommands.inventory.DefaultMenuView;
|
import me.filoghost.chestcommands.inventory.DefaultMenuView;
|
||||||
|
import me.filoghost.chestcommands.logging.Errors;
|
||||||
|
import me.filoghost.chestcommands.menu.InternalMenu;
|
||||||
import me.filoghost.chestcommands.menu.MenuManager;
|
import me.filoghost.chestcommands.menu.MenuManager;
|
||||||
|
import me.filoghost.fcommons.logging.Log;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -75,13 +79,28 @@ public class InventoryListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only handle the click AFTER the event has finished
|
// Only handle the click AFTER the event has finished
|
||||||
Bukkit.getScheduler().runTask(ChestCommands.getPluginInstance(), () -> {
|
Bukkit.getScheduler().runTask(ChestCommands.getInstance(), () -> {
|
||||||
|
try {
|
||||||
ClickResult result = icon.onClick(menuView, clicker);
|
ClickResult result = icon.onClick(menuView, clicker);
|
||||||
|
|
||||||
if (result == ClickResult.CLOSE) {
|
if (result == ClickResult.CLOSE) {
|
||||||
clicker.closeInventory();
|
clicker.closeInventory();
|
||||||
}
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
handleIconClickException(menuView.getMenu(), t);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleIconClickException(Menu menu, Throwable throwable) {
|
||||||
|
String menuDescription;
|
||||||
|
if (menu.getPlugin() == ChestCommands.getInstance()) {
|
||||||
|
menuDescription = "the menu \"" + Errors.formatPath(((InternalMenu) menu).getSourceFile()) + "\"";
|
||||||
|
} else {
|
||||||
|
menuDescription = "a menu created by the plugin \"" + menu.getPlugin().getName() + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.severe("Encountered exception while handling a click inside " + menuDescription, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ public class Errors {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatPath(Path path) {
|
public static String formatPath(Path path) {
|
||||||
return ConfigErrors.formatPath(ChestCommands.getDataFolderPath(), path);
|
return ConfigErrors.formatPath(ChestCommands.getDataFolderPath(), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,16 +11,17 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
public class APIMenu extends BaseMenu {
|
public class APIMenu extends BaseMenu {
|
||||||
|
|
||||||
private final Plugin owner;
|
private final Plugin plugin;
|
||||||
|
|
||||||
public APIMenu(@NotNull Plugin owner, @NotNull String title, int rows) {
|
public APIMenu(@NotNull Plugin plugin, @NotNull String title, int rows) {
|
||||||
super(title, rows);
|
super(title, rows);
|
||||||
Preconditions.notNull(owner, "owner");
|
Preconditions.notNull(plugin, "plugin");
|
||||||
this.owner = owner;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Plugin getOwner() {
|
@Override
|
||||||
return owner;
|
public Plugin getPlugin() {
|
||||||
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,12 +42,31 @@ public abstract class BaseMenu implements Menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
public @NotNull MenuView open(@NotNull Player player) {
|
||||||
|
Preconditions.notNull(player, "player");
|
||||||
|
|
||||||
|
DefaultMenuView menuView = new DefaultMenuView(this, player);
|
||||||
|
menuView.open();
|
||||||
|
return menuView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshOpenViews() {
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
DefaultMenuView menuView = MenuManager.getOpenMenuView(player);
|
||||||
|
if (menuView != null && menuView.getMenu() == this) {
|
||||||
|
menuView.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRows() {
|
||||||
return icons.getRows();
|
return icons.getRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColumnCount() {
|
public int getColumns() {
|
||||||
return icons.getColumns();
|
return icons.getColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,22 +79,4 @@ public abstract class BaseMenu implements Menu {
|
|||||||
return icons;
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull MenuView open(@NotNull Player player) {
|
|
||||||
Preconditions.notNull(player, "player");
|
|
||||||
|
|
||||||
DefaultMenuView menuView = new DefaultMenuView(this, player);
|
|
||||||
menuView.open();
|
|
||||||
return menuView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void refreshOpenMenuViews() {
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
||||||
DefaultMenuView menuView = MenuManager.getOpenMenuView(player);
|
|
||||||
if (menuView != null && menuView.getMenu() == this) {
|
|
||||||
menuView.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package me.filoghost.chestcommands.menu;
|
package me.filoghost.chestcommands.menu;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import me.filoghost.chestcommands.ChestCommands;
|
||||||
import me.filoghost.chestcommands.Permissions;
|
import me.filoghost.chestcommands.Permissions;
|
||||||
import me.filoghost.chestcommands.action.Action;
|
import me.filoghost.chestcommands.action.Action;
|
||||||
import me.filoghost.chestcommands.api.MenuView;
|
import me.filoghost.chestcommands.api.MenuView;
|
||||||
@ -13,6 +14,7 @@ import me.filoghost.chestcommands.config.Lang;
|
|||||||
import me.filoghost.fcommons.collection.CollectionUtils;
|
import me.filoghost.fcommons.collection.CollectionUtils;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -63,6 +65,11 @@ public class InternalMenu extends BaseMenu {
|
|||||||
return super.open(player);
|
return super.open(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Plugin getPlugin() {
|
||||||
|
return ChestCommands.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
public void openCheckingPermission(Player player) {
|
public void openCheckingPermission(Player player) {
|
||||||
if (player.hasPermission(openPermission)) {
|
if (player.hasPermission(openPermission)) {
|
||||||
open(player);
|
open(player);
|
||||||
|
@ -63,16 +63,16 @@ public class MenuParser {
|
|||||||
int row = positionY.getPosition() - 1;
|
int row = positionY.getPosition() - 1;
|
||||||
int column = positionX.getPosition() - 1;
|
int column = positionX.getPosition() - 1;
|
||||||
|
|
||||||
if (row < 0 || row >= menu.getRowCount()) {
|
if (row < 0 || row >= menu.getRows()) {
|
||||||
errorCollector.add(
|
errorCollector.add(
|
||||||
Errors.Menu.invalidAttribute(iconSettings, AttributeType.POSITION_Y),
|
Errors.Menu.invalidAttribute(iconSettings, AttributeType.POSITION_Y),
|
||||||
"it must be between 1 and " + menu.getRowCount());
|
"it must be between 1 and " + menu.getRows());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (column < 0 || column >= menu.getColumnCount()) {
|
if (column < 0 || column >= menu.getColumns()) {
|
||||||
errorCollector.add(
|
errorCollector.add(
|
||||||
Errors.Menu.invalidAttribute(iconSettings, AttributeType.POSITION_X),
|
Errors.Menu.invalidAttribute(iconSettings, AttributeType.POSITION_X),
|
||||||
"it must be between 1 and " + menu.getColumnCount());
|
"it must be between 1 and " + menu.getColumns());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) filoghost and contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
package me.filoghost.chestcommands.placeholder;
|
||||||
|
|
||||||
|
import me.filoghost.chestcommands.api.PlaceholderReplacer;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
public class Placeholder {
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final PlaceholderReplacer placeholderReplacer;
|
||||||
|
|
||||||
|
public Placeholder(Plugin plugin, PlaceholderReplacer placeholderReplacer) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.placeholderReplacer = placeholderReplacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plugin getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlaceholderReplacer getReplacer() {
|
||||||
|
return placeholderReplacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -10,6 +10,7 @@ import me.filoghost.chestcommands.hook.PlaceholderAPIHook;
|
|||||||
import me.filoghost.chestcommands.placeholder.scanner.PlaceholderMatch;
|
import me.filoghost.chestcommands.placeholder.scanner.PlaceholderMatch;
|
||||||
import me.filoghost.chestcommands.placeholder.scanner.PlaceholderScanner;
|
import me.filoghost.chestcommands.placeholder.scanner.PlaceholderScanner;
|
||||||
import me.filoghost.fcommons.Preconditions;
|
import me.filoghost.fcommons.Preconditions;
|
||||||
|
import me.filoghost.fcommons.logging.Log;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -21,14 +22,13 @@ public class PlaceholderManager {
|
|||||||
|
|
||||||
private static final List<StaticPlaceholder> staticPlaceholders = new ArrayList<>();
|
private static final List<StaticPlaceholder> staticPlaceholders = new ArrayList<>();
|
||||||
private static final PlaceholderRegistry relativePlaceholderRegistry = new PlaceholderRegistry();
|
private static final PlaceholderRegistry relativePlaceholderRegistry = new PlaceholderRegistry();
|
||||||
|
private static final PlaceholderCache placeholderCache = new PlaceholderCache();
|
||||||
static {
|
static {
|
||||||
for (DefaultPlaceholder placeholder : DefaultPlaceholder.values()) {
|
for (DefaultPlaceholder placeholder : DefaultPlaceholder.values()) {
|
||||||
relativePlaceholderRegistry.registerInternalPlaceholder(placeholder.getIdentifier(), placeholder.getReplacer());
|
relativePlaceholderRegistry.registerInternalPlaceholder(placeholder.getIdentifier(), placeholder.getReplacer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final PlaceholderCache placeholderCache = new PlaceholderCache();
|
|
||||||
|
|
||||||
public static boolean hasRelativePlaceholders(List<String> list) {
|
public static boolean hasRelativePlaceholders(List<String> list) {
|
||||||
for (String element : list) {
|
for (String element : list) {
|
||||||
if (hasRelativePlaceholders(element)) {
|
if (hasRelativePlaceholders(element)) {
|
||||||
@ -61,18 +61,24 @@ public class PlaceholderManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isValidPlaceholder(PlaceholderMatch placeholderMatch) {
|
private static boolean isValidPlaceholder(PlaceholderMatch placeholderMatch) {
|
||||||
return relativePlaceholderRegistry.getPlaceholderReplacer(placeholderMatch) != null;
|
return relativePlaceholderRegistry.getPlaceholder(placeholderMatch) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @Nullable String getReplacement(PlaceholderMatch placeholderMatch, Player player) {
|
private static @Nullable String getReplacement(PlaceholderMatch placeholderMatch, Player player) {
|
||||||
PlaceholderReplacer placeholderReplacer = relativePlaceholderRegistry.getPlaceholderReplacer(placeholderMatch);
|
Placeholder placeholder = relativePlaceholderRegistry.getPlaceholder(placeholderMatch);
|
||||||
|
|
||||||
if (placeholderReplacer == null) {
|
if (placeholder == null) {
|
||||||
return null; // Placeholder not found
|
return null; // Placeholder not found
|
||||||
}
|
}
|
||||||
|
|
||||||
return placeholderCache.computeIfAbsent(placeholderMatch, player, () -> {
|
return placeholderCache.computeIfAbsent(placeholderMatch, player, () -> {
|
||||||
return placeholderReplacer.getReplacement(player, placeholderMatch.getArgument());
|
try {
|
||||||
|
return placeholder.getReplacer().getReplacement(player, placeholderMatch.getArgument());
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.severe("Encountered exception while replacing the placeholder \"" + placeholderMatch
|
||||||
|
+ "\" registered by the plugin \"" + placeholder.getPlugin().getName() + "\"", t);
|
||||||
|
return "[ERROR]";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,47 +5,54 @@
|
|||||||
*/
|
*/
|
||||||
package me.filoghost.chestcommands.placeholder;
|
package me.filoghost.chestcommands.placeholder;
|
||||||
|
|
||||||
|
import me.filoghost.chestcommands.ChestCommands;
|
||||||
import me.filoghost.chestcommands.api.PlaceholderReplacer;
|
import me.filoghost.chestcommands.api.PlaceholderReplacer;
|
||||||
import me.filoghost.chestcommands.placeholder.scanner.PlaceholderMatch;
|
import me.filoghost.chestcommands.placeholder.scanner.PlaceholderMatch;
|
||||||
|
import me.filoghost.fcommons.collection.CaseInsensitiveMap;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class PlaceholderRegistry {
|
public class PlaceholderRegistry {
|
||||||
|
|
||||||
private final Map<String, PlaceholderReplacer> internalPlaceholders = new HashMap<>();
|
// <identifier, placeholder>
|
||||||
private final Map<String, Map<String, PlaceholderReplacer>> externalPlaceholders = new HashMap<>();
|
private final Map<String, Placeholder> internalPlaceholders = new CaseInsensitiveMap<>();
|
||||||
|
|
||||||
|
// <identifier, <pluginName, placeholder>>
|
||||||
|
private final Map<String, Map<String, Placeholder>> externalPlaceholders = new CaseInsensitiveMap<>();
|
||||||
|
|
||||||
public void registerInternalPlaceholder(String identifier, PlaceholderReplacer replacer) {
|
public void registerInternalPlaceholder(String identifier, PlaceholderReplacer replacer) {
|
||||||
internalPlaceholders.put(identifier, replacer);
|
internalPlaceholders.put(identifier, new Placeholder(ChestCommands.getInstance(), replacer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerExternalPlaceholder(Plugin plugin, String identifier, PlaceholderReplacer placeholderReplacer) {
|
public void registerExternalPlaceholder(Plugin plugin, String identifier, PlaceholderReplacer placeholderReplacer) {
|
||||||
externalPlaceholders
|
externalPlaceholders
|
||||||
.computeIfAbsent(identifier, key -> new LinkedHashMap<>())
|
.computeIfAbsent(identifier, key -> new CaseInsensitiveMap<>(new LinkedHashMap<>()))
|
||||||
.put(plugin.getName(), placeholderReplacer);
|
.put(plugin.getName(), new Placeholder(plugin, placeholderReplacer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable PlaceholderReplacer getPlaceholderReplacer(PlaceholderMatch placeholderMatch) {
|
public @Nullable Placeholder getPlaceholder(PlaceholderMatch placeholderMatch) {
|
||||||
|
String identifier = placeholderMatch.getIdentifier();
|
||||||
|
|
||||||
if (placeholderMatch.getPluginNamespace() == null) {
|
if (placeholderMatch.getPluginNamespace() == null) {
|
||||||
PlaceholderReplacer internalReplacer = internalPlaceholders.get(placeholderMatch.getIdentifier());
|
Placeholder internalPlaceholder = internalPlaceholders.get(identifier);
|
||||||
if (internalReplacer != null) {
|
if (internalPlaceholder != null) {
|
||||||
return internalReplacer;
|
return internalPlaceholder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, PlaceholderReplacer> externalReplacers = externalPlaceholders.get(placeholderMatch.getIdentifier());
|
Map<String, Placeholder> externalPlaceholdersByPlugin = externalPlaceholders.get(identifier);
|
||||||
|
|
||||||
// Find exact replacer if plugin name is specified
|
// Find exact replacer if plugin name is specified
|
||||||
if (placeholderMatch.getPluginNamespace() != null) {
|
if (placeholderMatch.getPluginNamespace() != null) {
|
||||||
return externalReplacers.get(placeholderMatch.getPluginNamespace());
|
return externalPlaceholdersByPlugin.get(placeholderMatch.getPluginNamespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (externalReplacers != null && !externalReplacers.isEmpty()) {
|
// Otherwise try find the first one registered
|
||||||
return externalReplacers.values().iterator().next();
|
if (externalPlaceholdersByPlugin != null && !externalPlaceholdersByPlugin.isEmpty()) {
|
||||||
|
return externalPlaceholdersByPlugin.values().iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -35,9 +35,10 @@ public class PlaceholderMatch {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Valid formats:
|
* Valid formats:
|
||||||
* {pluginName/placeholder: argument}
|
|
||||||
* {placeholder: argument}
|
|
||||||
* {placeholder}
|
* {placeholder}
|
||||||
|
* {placeholder: argument}
|
||||||
|
* {pluginName/identifier}
|
||||||
|
* {pluginName/identifier: argument}
|
||||||
*/
|
*/
|
||||||
public static PlaceholderMatch parse(String placeholderContent) {
|
public static PlaceholderMatch parse(String placeholderContent) {
|
||||||
String explicitPluginName = null;
|
String explicitPluginName = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user