API refactoring

This commit is contained in:
filoghost 2020-07-04 17:19:57 +02:00
parent f0aa5347ee
commit 41fcd9540d
73 changed files with 1765 additions and 1670 deletions

View File

@ -1,28 +1,28 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.api;
import org.bukkit.entity.Player;
@FunctionalInterface
public interface ClickHandler {
/**
* @param player the player that clicked on the icon
* @return true if the menu should be closed right after, false otherwise
*/
ClickResult onClick(Player player);
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.api;
import org.bukkit.entity.Player;
@FunctionalInterface
public interface ClickHandler {
/**
* @param player the player that clicked on the inventory
* @return true if the inventory should be closed, false otherwise
*/
ClickResult onClick(Player player);
}

View File

@ -15,8 +15,7 @@
package me.filoghost.chestcommands.api;
public enum ClickResult {
DEFAULT,
KEEP_OPEN,
CLOSE

View File

@ -0,0 +1,20 @@
package me.filoghost.chestcommands.api;
import org.bukkit.entity.Player;
public interface ClickableIcon extends Icon {
void setClickHandler(ClickHandler clickHandler);
ClickHandler getClickHandler();
@Override
default ClickResult onClick(ItemInventory itemInventory, Player clicker) {
if (getClickHandler() != null) {
return getClickHandler().onClick(clicker);
} else {
return ClickResult.KEEP_OPEN;
}
}
}

View File

@ -14,20 +14,19 @@
*/
package me.filoghost.chestcommands.api;
import java.util.List;
import java.util.Map;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.banner.Pattern;
import org.bukkit.enchantments.Enchantment;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import java.util.List;
import java.util.Map;
public interface ConfigurableIcon extends Icon {
public interface ConfigurableIcon extends ClickableIcon {
public static ConfigurableIcon create(Material material) {
static ConfigurableIcon create(Material material) {
return BackendAPI.getImplementation().createConfigurableIcon(material);
}
@ -65,11 +64,11 @@ public interface ConfigurableIcon extends Icon {
Map<Enchantment, Integer> getEnchantments();
void addEnchantment(Enchantment ench);
void addEnchantment(Enchantment enchantment);
void addEnchantment(Enchantment ench, Integer level);
void addEnchantment(Enchantment enchantment, Integer level);
void removeEnchantment(Enchantment ench);
void removeEnchantment(Enchantment enchantment);
Color getLeatherColor();
@ -87,10 +86,6 @@ public interface ConfigurableIcon extends Icon {
void setBannerPatterns(List<Pattern> bannerPatterns);
void setCloseOnClick(boolean closeOnClick);
void setClickHandler(ClickHandler clickHandler);
ClickHandler getClickHandler();
void setPlaceholdersEnabled(boolean enabled);
}

View File

@ -15,13 +15,12 @@
package me.filoghost.chestcommands.api;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public interface Icon {
ItemStack createItemStack(Player viewer);
ItemStack render(Player viewer);
boolean onClick(Inventory inventory, Player clicker);
ClickResult onClick(ItemInventory itemInventory, Player clicker);
}

View File

@ -14,19 +14,19 @@
*/
package me.filoghost.chestcommands.api;
import org.bukkit.entity.Player;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public interface IconMenu {
public static IconMenu create(String title, int rowCount) {
return BackendAPI.getImplementation().createIconMenu(title, rowCount);
static IconMenu create(Plugin owner, String title, int rowCount) {
return BackendAPI.getImplementation().createIconMenu(owner, title, rowCount);
}
void setIcon(int x, int y, Icon icon);
void setIcon(int row, int column, Icon icon);
Icon getIcon(int x, int y);
Icon getIcon(int row, int column);
String getTitle();
@ -34,6 +34,12 @@ public interface IconMenu {
int getColumnCount();
void open(Player player);
/**
* Opens a view of the current menu configuration.
* Updating the menu doesn't automatically update all the views.
*
* @param player the player to which the menu will be displayed
*/
ItemInventory open(Player player);
}

View File

@ -0,0 +1,7 @@
package me.filoghost.chestcommands.api;
public interface ItemInventory {
void refresh();
}

View File

@ -14,14 +14,17 @@
*/
package me.filoghost.chestcommands.api;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import org.bukkit.inventory.ItemStack;
import me.filoghost.chestcommands.api.internal.BackendAPI;
public interface StaticIcon extends Icon {
public interface StaticIcon extends ClickableIcon {
public static StaticIcon create(ItemStack itemStack, boolean closeOnClick) {
return BackendAPI.getImplementation().createStaticIcon(itemStack, closeOnClick);
static StaticIcon create(ItemStack itemStack) {
return BackendAPI.getImplementation().createStaticIcon(itemStack);
}
ItemStack getItemStack();
void setItemStack(ItemStack itemStack);
}

View File

@ -14,13 +14,13 @@
*/
package me.filoghost.chestcommands.api.internal;
import me.filoghost.chestcommands.api.ConfigurableIcon;
import me.filoghost.chestcommands.api.IconMenu;
import me.filoghost.chestcommands.api.StaticIcon;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.filoghost.chestcommands.api.IconMenu;
import me.filoghost.chestcommands.api.StaticIcon;
import me.filoghost.chestcommands.api.ConfigurableIcon;
import org.bukkit.plugin.Plugin;
public abstract class BackendAPI {
@ -42,12 +42,10 @@ public abstract class BackendAPI {
public abstract boolean openPluginMenu(Player player, String yamlFile);
public abstract IconMenu createIconMenu(String title, int rows);
public abstract IconMenu createIconMenu(Plugin owner, String title, int rows);
public abstract ConfigurableIcon createConfigurableIcon(Material material);
public abstract StaticIcon createStaticIcon(ItemStack itemStack, boolean closeOnClick);
public abstract StaticIcon createStaticIcon(ItemStack itemStack);
}

View File

@ -14,6 +14,8 @@
*/
package me.filoghost.chestcommands;
import me.filoghost.chestcommands.api.impl.DefaultBackendAPI;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import me.filoghost.chestcommands.command.CommandHandler;
import me.filoghost.chestcommands.command.framework.CommandFramework;
import me.filoghost.chestcommands.config.ConfigLoader;
@ -77,6 +79,7 @@ public class ChestCommands extends JavaPlugin {
instance = this;
Log.setLogger(getLogger());
BackendAPI.setImplementation(new DefaultBackendAPI());
configManager = new ConfigManager(getDataFolder().toPath());
menuManager = new MenuManager();
@ -185,7 +188,7 @@ public class ChestCommands extends JavaPlugin {
public static void closeAllMenus() {
for (Player player : Bukkit.getOnlinePlayers()) {
if (MenuManager.getOpenMenu(player) != null) {
if (MenuManager.getOpenMenuInventory(player) != null) {
player.closeInventory();
}
}

View File

@ -24,14 +24,14 @@ public abstract class Action {
this.errorMessage = errorMessage;
}
public void execute(Player player) {
public final void execute(Player player) {
if (errorMessage != null) {
player.sendMessage(errorMessage);
} else {
executeInner(player);
execute0(player);
}
}
protected abstract void executeInner(Player player);
protected abstract void execute0(Player player);
}

View File

@ -29,7 +29,7 @@ public class BroadcastAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
Bukkit.broadcastMessage(message.getValue(player));
}

View File

@ -28,7 +28,7 @@ public class ChangeServerAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
BungeeCordHook.connect(player, targetServer.getValue(player));
}

View File

@ -28,7 +28,7 @@ public class ConsoleCommandAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.getValue(player));
}

View File

@ -48,7 +48,7 @@ public class DragonBarAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
if (BarAPIHook.INSTANCE.isEnabled()) {
BarAPIHook.setMessage(player, message.getValue(player), seconds);
}

View File

@ -35,7 +35,7 @@ public class GiveItemAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
player.getInventory().addItem(itemToGive.clone());
}

View File

@ -34,7 +34,7 @@ public class GiveMoneyAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
if (VaultEconomyHook.INSTANCE.isEnabled()) {
VaultEconomyHook.giveMoney(player, moneyToGive);
} else {

View File

@ -27,7 +27,7 @@ public class OpCommandAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
if (player.isOp()) {
player.chat("/" + command.getValue(player));
} else {

View File

@ -14,14 +14,13 @@
*/
package me.filoghost.chestcommands.action;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import me.filoghost.chestcommands.variable.RelativeString;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.variable.RelativeString;
public class OpenMenuAction extends Action {
private final RelativeString targetMenu;
@ -31,8 +30,8 @@ public class OpenMenuAction extends Action {
}
@Override
protected void executeInner(final Player player) {
final AdvancedIconMenu menu = ChestCommands.getInstance().getMenuManager().getMenuByFileName(targetMenu.getValue(player));
protected void execute0(final Player player) {
final InternalIconMenu menu = ChestCommands.getInstance().getMenuManager().getMenuByFileName(targetMenu.getValue(player));
if (menu != null) {
/*

View File

@ -62,7 +62,7 @@ public class PlaySoundAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
player.playSound(player.getLocation(), sound, volume, pitch);
}

View File

@ -27,7 +27,7 @@ public class PlayerCommandAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
player.chat('/' + command.getValue(player));
}

View File

@ -28,7 +28,7 @@ public class SendMessageAction extends Action {
}
@Override
protected void executeInner(Player player) {
protected void execute0(Player player) {
player.sendMessage(message.getValue(player));
}

View File

@ -0,0 +1,26 @@
package me.filoghost.chestcommands.api.impl;
import me.filoghost.chestcommands.api.ClickHandler;
import me.filoghost.chestcommands.api.ConfigurableIcon;
import me.filoghost.chestcommands.icon.BaseConfigurableIcon;
import org.bukkit.Material;
public class APIConfigurableIcon extends BaseConfigurableIcon implements ConfigurableIcon {
private ClickHandler clickHandler;
public APIConfigurableIcon(Material material) {
super(material);
}
@Override
public void setClickHandler(ClickHandler clickHandler) {
this.clickHandler = clickHandler;
}
@Override
public ClickHandler getClickHandler() {
return clickHandler;
}
}

View File

@ -1,29 +1,33 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.api.impl;
import me.filoghost.chestcommands.api.Icon;
import me.filoghost.chestcommands.api.IconMenu;
import me.filoghost.chestcommands.menu.BaseIconMenu;
public class IconMenuImpl extends BaseIconMenu<Icon> implements IconMenu {
public IconMenuImpl(String title, int rows) {
super(title, rows);
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.api.impl;
import me.filoghost.chestcommands.menu.BaseIconMenu;
import org.bukkit.plugin.Plugin;
public class APIIconMenu extends BaseIconMenu {
private final Plugin owner;
public APIIconMenu(Plugin owner, String title, int rows) {
super(title, rows);
this.owner = owner;
}
public Plugin getOwner() {
return owner;
}
}

View File

@ -0,0 +1,42 @@
package me.filoghost.chestcommands.api.impl;
import me.filoghost.chestcommands.api.ClickHandler;
import me.filoghost.chestcommands.api.StaticIcon;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class APIStaticIcon implements StaticIcon {
private ItemStack itemStack;
private ClickHandler clickHandler;
public APIStaticIcon(ItemStack itemStack) {
this.itemStack = itemStack;
}
@Override
public ItemStack getItemStack() {
return itemStack;
}
@Override
public void setItemStack(ItemStack itemStack) {
this.itemStack = itemStack;
}
@Override
public ClickHandler getClickHandler() {
return clickHandler;
}
@Override
public void setClickHandler(ClickHandler clickHandler) {
this.clickHandler = clickHandler;
}
@Override
public ItemStack render(Player viewer) {
return itemStack;
}
}

View File

@ -1,77 +1,62 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.api.impl;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.api.ConfigurableIcon;
import me.filoghost.chestcommands.api.IconMenu;
import me.filoghost.chestcommands.api.StaticIcon;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
public class BackendAPIImpl extends BackendAPI {
@Override
public boolean isPluginMenu(String yamlFile) {
return ChestCommands.getInstance().getMenuManager().getMenuByFileName(yamlFile) != null;
}
@Override
public boolean openPluginMenu(Player player, String yamlFile) {
AdvancedIconMenu menu = ChestCommands.getInstance().getMenuManager().getMenuByFileName(yamlFile);
if (menu != null) {
menu.open(player);
return true;
} else {
return false;
}
}
@Override
public ConfigurableIcon createConfigurableIcon(Material material) {
return new ConfigurableIconImpl(material);
}
@Override
public IconMenu createIconMenu(String title, int rows) {
return new IconMenuImpl(title, rows);
}
@Override
public StaticIcon createStaticIcon(ItemStack itemStack, boolean closeOnClick) {
ItemStack itemStackCopy = itemStack.clone();
return new StaticIcon() {
@Override
public ItemStack createItemStack(Player viewer) {
return itemStackCopy;
}
@Override
public boolean onClick(Inventory inventory, Player clicker) {
return closeOnClick;
}
};
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.api.impl;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.api.ConfigurableIcon;
import me.filoghost.chestcommands.api.IconMenu;
import me.filoghost.chestcommands.api.StaticIcon;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
public class DefaultBackendAPI extends BackendAPI {
@Override
public boolean isPluginMenu(String yamlFile) {
return ChestCommands.getInstance().getMenuManager().getMenuByFileName(yamlFile) != null;
}
@Override
public boolean openPluginMenu(Player player, String yamlFile) {
InternalIconMenu menu = ChestCommands.getInstance().getMenuManager().getMenuByFileName(yamlFile);
if (menu != null) {
menu.open(player);
return true;
} else {
return false;
}
}
@Override
public ConfigurableIcon createConfigurableIcon(Material material) {
return new APIConfigurableIcon(material);
}
@Override
public IconMenu createIconMenu(Plugin owner, String title, int rows) {
return new APIIconMenu(owner, title, rows);
}
@Override
public StaticIcon createStaticIcon(ItemStack itemStack) {
return new APIStaticIcon(itemStack);
}
}

View File

@ -14,20 +14,19 @@
*/
package me.filoghost.chestcommands.command;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.Permissions;
import me.filoghost.chestcommands.command.framework.CommandFramework;
import me.filoghost.chestcommands.command.framework.CommandValidate;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.Permissions;
import me.filoghost.chestcommands.command.framework.CommandFramework;
import me.filoghost.chestcommands.command.framework.CommandValidate;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
public class CommandHandler extends CommandFramework {
private final MenuManager menuManager;
@ -101,7 +100,7 @@ public class CommandHandler extends CommandFramework {
CommandValidate.notNull(target, "That player is not online.");
String menuName = args[1].toLowerCase().endsWith(".yml") ? args[1] : args[1] + ".yml";
AdvancedIconMenu menu = menuManager.getMenuByFileName(menuName);
InternalIconMenu menu = menuManager.getMenuByFileName(menuName);
CommandValidate.notNull(menu, "The menu \"" + menuName + "\" was not found.");
if (!sender.hasPermission(menu.getOpenPermission())) {

View File

@ -1,372 +1,335 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.api.impl;
import me.filoghost.chestcommands.api.ClickHandler;
import me.filoghost.chestcommands.api.ClickResult;
import me.filoghost.chestcommands.api.ConfigurableIcon;
import me.filoghost.chestcommands.util.Log;
import me.filoghost.chestcommands.util.Preconditions;
import me.filoghost.chestcommands.util.collection.CollectionUtils;
import me.filoghost.chestcommands.variable.RelativeString;
import me.filoghost.chestcommands.variable.RelativeStringList;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.banner.Pattern;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BannerMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.SkullMeta;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class ConfigurableIconImpl implements ConfigurableIcon {
private Material material;
private int amount;
private short durability;
private String nbtData;
private RelativeString name;
private RelativeStringList lore;
private Map<Enchantment, Integer> enchantments;
private Color leatherColor;
private RelativeString skullOwner;
private DyeColor bannerColor;
private List<Pattern> bannerPatterns;
protected boolean closeOnClick;
private ClickHandler clickHandler;
private ItemStack cachedItem; // When there are no variables, we don't recreate the item
public ConfigurableIconImpl(Material material) {
Preconditions.checkArgumentNotAir(material, "material");
this.material = material;
this.amount = 1;
this.closeOnClick = true;
}
public boolean hasVariables() {
return (name != null && name.hasVariables())
|| (lore != null && lore.hasVariables())
|| (skullOwner != null && skullOwner.hasVariables());
}
@Override
public void setMaterial(Material material) {
Preconditions.checkArgumentNotAir(material, "material");
this.material = material;
}
@Override
public Material getMaterial() {
return material;
}
@Override
public void setAmount(int amount) {
Preconditions.checkArgument(amount >= 1, "Amount must 1 or greater");
this.amount = Math.min(amount, 127);
}
@Override
public int getAmount() {
return amount;
}
@Override
public void setDurability(short durability) {
Preconditions.checkArgument(durability >= 0, "Durability must not be negative");
this.durability = durability;
}
@Override
public short getDurability() {
return durability;
}
@Override
public void setNBTData(String nbtData) {
this.nbtData = nbtData;
}
@Override
public String getNBTData() {
return nbtData;
}
@Override
public void setName(String name) {
this.name = RelativeString.of(name);
}
@Override
public boolean hasName() {
return name != null;
}
public String getName() {
if (name != null) {
return name.getRawValue();
} else {
return null;
}
}
@Override
public void setLore(String... lore) {
if (lore != null) {
setLore(Arrays.asList(lore));
}
}
@Override
public void setLore(List<String> lore) {
if (!CollectionUtils.isNullOrEmpty(lore)) {
this.lore = new RelativeStringList(lore);
} else {
this.lore = null;
}
}
@Override
public boolean hasLore() {
return lore != null;
}
@Override
public List<String> getLore() {
if (lore != null) {
return new ArrayList<>(lore.getRawValue());
} else {
return null;
}
}
@Override
public void setEnchantments(Map<Enchantment, Integer> enchantments) {
this.enchantments = CollectionUtils.nullableCopy(enchantments);
}
@Override
public Map<Enchantment, Integer> getEnchantments() {
return CollectionUtils.nullableCopy(enchantments);
}
@Override
public void addEnchantment(Enchantment ench) {
addEnchantment(ench, 1);
}
@Override
public void addEnchantment(Enchantment ench, Integer level) {
if (enchantments == null) {
enchantments = new HashMap<>();
}
enchantments.put(ench, level);
}
@Override
public void removeEnchantment(Enchantment ench) {
if (enchantments == null) {
return;
}
enchantments.remove(ench);
}
@Override
public Color getLeatherColor() {
return leatherColor;
}
@Override
public void setLeatherColor(Color leatherColor) {
this.leatherColor = leatherColor;
}
@Override
public String getSkullOwner() {
if (skullOwner != null) {
return skullOwner.getRawValue();
} else {
return null;
}
}
@Override
public void setSkullOwner(String skullOwner) {
this.skullOwner = RelativeString.of(skullOwner);
}
@Override
public DyeColor getBannerColor() {
return bannerColor;
}
@Override
public void setBannerColor(DyeColor bannerColor) {
this.bannerColor = bannerColor;
}
@Override
public List<Pattern> getBannerPatterns() {
return CollectionUtils.nullableCopy(bannerPatterns);
}
@Override
public void setBannerPatterns(List<Pattern> bannerPatterns) {
this.bannerPatterns = CollectionUtils.nullableCopy(bannerPatterns);
}
@Override
public void setCloseOnClick(boolean closeOnClick) {
this.closeOnClick = closeOnClick;
}
@Override
public void setClickHandler(ClickHandler clickHandler) {
this.clickHandler = clickHandler;
}
@Override
public ClickHandler getClickHandler() {
return clickHandler;
}
public String calculateName(Player viewer) {
if (!hasName()) {
return null;
}
String name = this.name.getValue(viewer);
if (name.isEmpty()) {
// Add a color to display the name empty
return ChatColor.WHITE.toString();
} else {
return name;
}
}
public List<String> calculateLore(Player viewer) {
if (hasLore()) {
return lore.getValue(viewer);
} else {
return null;
}
}
@Override
@SuppressWarnings("deprecation")
public ItemStack createItemStack(Player viewer) {
if (!this.hasVariables() && cachedItem != null) {
// Performance: return a static item
return cachedItem;
}
ItemStack itemStack = new ItemStack(material, amount, durability);
// First try to apply NBT data
if (nbtData != null) {
try {
// Note: this method should not throw any exception. It should log directly to the console
Bukkit.getUnsafe().modifyItemStack(itemStack, nbtData);
} catch (Throwable t) {
this.nbtData = null;
Log.warning("Could not apply NBT-DATA to an item.", t);
}
}
// Then apply data from config nodes, overwriting NBT data if there are confliting values
ItemMeta itemMeta = itemStack.getItemMeta();
if (hasName()) {
itemMeta.setDisplayName(calculateName(viewer));
}
if (hasLore()) {
itemMeta.setLore(calculateLore(viewer));
}
if (leatherColor != null && itemMeta instanceof LeatherArmorMeta) {
((LeatherArmorMeta) itemMeta).setColor(leatherColor);
}
if (skullOwner != null && itemMeta instanceof SkullMeta) {
String skullOwner = this.skullOwner.getValue(viewer);
((SkullMeta) itemMeta).setOwner(skullOwner);
}
if (bannerColor != null && itemMeta instanceof BannerMeta) {
BannerMeta bannerMeta = (BannerMeta) itemMeta;
bannerMeta.setBaseColor(bannerColor);
if (bannerPatterns != null) {
((BannerMeta) itemMeta).setPatterns(bannerPatterns);
}
}
// Hide all text details (damage, enchantments, potions, etc,)
if (CollectionUtils.isNullOrEmpty(itemMeta.getItemFlags())) {
itemMeta.addItemFlags(ItemFlag.values());
}
itemStack.setItemMeta(itemMeta);
if (enchantments != null) {
for (Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
itemStack.addUnsafeEnchantment(entry.getKey(), entry.getValue());
}
}
if (!this.hasVariables()) {
// If there are no variables, cache the item
cachedItem = itemStack;
}
return itemStack;
}
@Override
public boolean onClick(Inventory inventory, Player clicker) {
if (clickHandler == null) {
return closeOnClick;
}
ClickResult result = clickHandler.onClick(clicker);
switch (result) {
case CLOSE:
return true;
case KEEP_OPEN:
return false;
default:
return closeOnClick;
}
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.icon;
import me.filoghost.chestcommands.api.Icon;
import me.filoghost.chestcommands.parsing.icon.IconSettingsNode;
import me.filoghost.chestcommands.util.Log;
import me.filoghost.chestcommands.util.Preconditions;
import me.filoghost.chestcommands.util.collection.CollectionUtils;
import me.filoghost.chestcommands.variable.RelativeString;
import me.filoghost.chestcommands.variable.RelativeStringList;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.banner.Pattern;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BannerMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.SkullMeta;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class BaseConfigurableIcon implements Icon {
private Material material;
private int amount;
private short durability;
private String nbtData;
private RelativeString name;
private RelativeStringList lore;
private Map<Enchantment, Integer> enchantments;
private Color leatherColor;
private RelativeString skullOwner;
private DyeColor bannerColor;
private List<Pattern> bannerPatterns;
private boolean placeholdersEnabled;
protected ItemStack cachedRendering; // Cache the rendered item when there are no variables and values haven't changed
public BaseConfigurableIcon(Material material) {
Preconditions.checkArgumentNotAir(material, "material");
this.material = material;
this.amount = 1;
}
protected boolean shouldCacheRendering() {
if (placeholdersEnabled) {
return false;
}
return (name == null || !name.hasVariables())
&& (lore == null || !lore.hasVariables())
&& (skullOwner == null || !skullOwner.hasVariables());
}
public void setMaterial(Material material) {
Preconditions.checkArgumentNotAir(material, "material");
this.material = material;
cachedRendering = null;
}
public Material getMaterial() {
return material;
}
public void setAmount(int amount) {
Preconditions.checkArgument(amount >= 1, "Amount must 1 or greater");
this.amount = Math.min(amount, 127);
cachedRendering = null;
}
public int getAmount() {
return amount;
}
public void setDurability(short durability) {
Preconditions.checkArgument(durability >= 0, "Durability must not be negative");
this.durability = durability;
cachedRendering = null;
}
public short getDurability() {
return durability;
}
public void setNBTData(String nbtData) {
this.nbtData = nbtData;
cachedRendering = null;
}
public String getNBTData() {
return nbtData;
}
public void setName(String name) {
this.name = RelativeString.of(name);
cachedRendering = null;
}
public boolean hasName() {
return name != null;
}
public String getName() {
if (name != null) {
return name.getRawValue();
} else {
return null;
}
}
public void setLore(String... lore) {
if (lore != null) {
setLore(Arrays.asList(lore));
}
}
public void setLore(List<String> lore) {
if (!CollectionUtils.isNullOrEmpty(lore)) {
this.lore = new RelativeStringList(lore);
} else {
this.lore = null;
}
cachedRendering = null;
}
public boolean hasLore() {
return lore != null;
}
public List<String> getLore() {
if (lore != null) {
return new ArrayList<>(lore.getRawValue());
} else {
return null;
}
}
public void setEnchantments(Map<Enchantment, Integer> enchantments) {
this.enchantments = CollectionUtils.nullableCopy(enchantments);
cachedRendering = null;
}
public Map<Enchantment, Integer> getEnchantments() {
return CollectionUtils.nullableCopy(enchantments);
}
public void addEnchantment(Enchantment enchantment) {
addEnchantment(enchantment, 1);
}
public void addEnchantment(Enchantment enchantment, Integer level) {
if (enchantments == null) {
enchantments = new HashMap<>();
}
enchantments.put(enchantment, level);
cachedRendering = null;
}
public void removeEnchantment(Enchantment enchantment) {
if (enchantments == null) {
return;
}
enchantments.remove(enchantment);
cachedRendering = null;
}
public Color getLeatherColor() {
return leatherColor;
}
public void setLeatherColor(Color leatherColor) {
this.leatherColor = leatherColor;
cachedRendering = null;
}
public String getSkullOwner() {
if (skullOwner != null) {
return skullOwner.getRawValue();
} else {
return null;
}
}
public void setSkullOwner(String skullOwner) {
this.skullOwner = RelativeString.of(skullOwner);
cachedRendering = null;
}
public DyeColor getBannerColor() {
return bannerColor;
}
public void setBannerColor(DyeColor bannerColor) {
this.bannerColor = bannerColor;
cachedRendering = null;
}
public List<Pattern> getBannerPatterns() {
return CollectionUtils.nullableCopy(bannerPatterns);
}
public void setBannerPatterns(List<Pattern> bannerPatterns) {
this.bannerPatterns = CollectionUtils.nullableCopy(bannerPatterns);
cachedRendering = null;
}
public void setPlaceholdersEnabled(boolean placeholdersEnabled) {
this.placeholdersEnabled = placeholdersEnabled;
cachedRendering = null;
}
public String renderName(Player viewer) {
if (!hasName()) {
return null;
}
if (!placeholdersEnabled) {
return name.getRawValue();
}
String name = this.name.getValue(viewer);
if (name.isEmpty()) {
// Add a color to display the name empty
return ChatColor.WHITE.toString();
} else {
return name;
}
}
public List<String> renderLore(Player viewer) {
if (!hasLore()) {
return null;
}
if (!placeholdersEnabled) {
return lore.getRawValue();
}
return lore.getValue(viewer);
}
@Override
@SuppressWarnings("deprecation")
public ItemStack render(Player viewer) {
if (shouldCacheRendering() && cachedRendering != null) {
// Performance: return a cached item
return cachedRendering;
}
ItemStack itemStack = new ItemStack(material, amount, durability);
// First try to apply NBT data
if (nbtData != null) {
try {
// Note: this method should not throw any exception. It should log directly to the console
Bukkit.getUnsafe().modifyItemStack(itemStack, nbtData);
} catch (Throwable t) {
this.nbtData = null;
Log.warning("Could not apply NBT data to an item.", t);
}
}
// Then apply data from config nodes, overwriting NBT data if there are conflicting values
ItemMeta itemMeta = itemStack.getItemMeta();
if (hasName()) {
itemMeta.setDisplayName(renderName(viewer));
}
if (hasLore()) {
itemMeta.setLore(renderLore(viewer));
}
if (leatherColor != null && itemMeta instanceof LeatherArmorMeta) {
((LeatherArmorMeta) itemMeta).setColor(leatherColor);
}
if (skullOwner != null && itemMeta instanceof SkullMeta) {
String skullOwner = this.skullOwner.getValue(viewer);
((SkullMeta) itemMeta).setOwner(skullOwner);
}
if (itemMeta instanceof BannerMeta) {
BannerMeta bannerMeta = (BannerMeta) itemMeta;
if (bannerColor != null) {
bannerMeta.setBaseColor(bannerColor);
}
if (bannerPatterns != null) {
((BannerMeta) itemMeta).setPatterns(bannerPatterns);
}
}
// Hide all text details (damage, enchantments, potions, etc,)
if (CollectionUtils.isNullOrEmpty(itemMeta.getItemFlags())) {
itemMeta.addItemFlags(ItemFlag.values());
}
itemStack.setItemMeta(itemMeta);
if (enchantments != null) {
enchantments.forEach(itemStack::addUnsafeEnchantment);
}
if (shouldCacheRendering()) {
// If there are no variables, cache the item
cachedRendering = itemStack;
}
return itemStack;
}
}

View File

@ -1,172 +1,185 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.icon;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.filoghost.chestcommands.action.Action;
import me.filoghost.chestcommands.action.OpenMenuAction;
import me.filoghost.chestcommands.api.impl.ConfigurableIconImpl;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.menu.BaseIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import me.filoghost.chestcommands.util.collection.CollectionUtils;
public class AdvancedIcon extends ConfigurableIconImpl {
private PermissionChecker viewPermission;
private PermissionChecker clickPermission;
private RequiredMoney requiredMoney;
private RequiredExpLevel requiredExpLevel;
private RequiredItems requiredItems;
private List<Action> clickActions;
public AdvancedIcon(Material material) {
super(material);
}
public boolean canViewIcon(Player player) {
return viewPermission == null || viewPermission.hasPermission(player);
}
public boolean hasViewPermission() {
return viewPermission != null && !viewPermission.isEmpty();
}
public void setClickPermission(String permission) {
this.clickPermission = new PermissionChecker(permission);
}
public void setNoClickPermissionMessage(String clickNoPermissionMessage) {
clickPermission.setNoPermissionMessage(clickNoPermissionMessage);
}
public void setViewPermission(String viewPermission) {
this.viewPermission = new PermissionChecker(viewPermission);
}
public void setRequiredMoney(double requiredMoney) {
if (requiredMoney > 0.0) {
this.requiredMoney = new RequiredMoney(requiredMoney);
} else {
this.requiredMoney = null;
}
}
public void setRequiredExpLevel(int requiredLevels) {
if (requiredLevels > 0) {
this.requiredExpLevel = new RequiredExpLevel(requiredLevels);
} else {
this.requiredExpLevel = null;
}
}
public void setRequiredItems(List<RequiredItem> requiredItems) {
if (!CollectionUtils.isNullOrEmpty(requiredItems)) {
this.requiredItems = new RequiredItems(requiredItems);
} else {
this.requiredItems = null;
}
}
public void setClickActions(List<Action> clickActions) {
this.clickActions = CollectionUtils.nullableCopy(clickActions);
}
@Override
public ItemStack createItemStack(Player viewer) {
if (canViewIcon(viewer)) {
return super.createItemStack(viewer);
} else {
return null;
}
}
public ItemStack refreshItemStack(Player viewer, ItemStack currentItemStack) {
if (!hasViewPermission() && !hasVariables()) {
// Icon is not dynamic, no need to refresh
return currentItemStack;
}
if (!canViewIcon(viewer)) {
// Player can't view the icon
return null;
}
if (currentItemStack == null) {
// Create item from scratch
return createItemStack(viewer);
} else {
// Performance: only update name and lore
ItemMeta meta = currentItemStack.getItemMeta();
meta.setDisplayName(calculateName(viewer));
meta.setLore(calculateLore(viewer));
currentItemStack.setItemMeta(meta);
return currentItemStack;
}
}
@Override
public boolean onClick(Inventory inventory, Player player) {
// Check all the requirements
boolean hasAllRequirements = Requirement.hasAll(player, clickPermission, requiredMoney, requiredExpLevel, requiredItems);
if (!hasAllRequirements) {
return closeOnClick;
}
// If all requirements are satisfied, take their cost
boolean takenAllCosts = Requirement.takeAllCosts(player, clickPermission, requiredMoney, requiredExpLevel, requiredItems);
if (!takenAllCosts) {
return closeOnClick;
}
boolean hasOpenMenuAction = false;
if (clickActions != null) {
for (Action action : clickActions) {
action.execute(player);
if (action instanceof OpenMenuAction) {
hasOpenMenuAction = true;
}
}
}
// Update the menu after taking requirement costs and executing all actions
BaseIconMenu<?> menu = MenuManager.getOpenMenu(inventory);
if (menu instanceof AdvancedIconMenu) {
((AdvancedIconMenu) menu).refresh(player, inventory);
}
// Force menu to stay open if actions open another menu
if (hasOpenMenuAction) {
return false;
} else {
return closeOnClick;
}
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.icon;
import me.filoghost.chestcommands.action.Action;
import me.filoghost.chestcommands.action.OpenMenuAction;
import me.filoghost.chestcommands.api.ClickResult;
import me.filoghost.chestcommands.api.ItemInventory;
import me.filoghost.chestcommands.icon.requirement.PermissionChecker;
import me.filoghost.chestcommands.icon.requirement.RequiredExpLevel;
import me.filoghost.chestcommands.icon.requirement.RequiredItem;
import me.filoghost.chestcommands.icon.requirement.RequiredItems;
import me.filoghost.chestcommands.icon.requirement.RequiredMoney;
import me.filoghost.chestcommands.icon.requirement.Requirement;
import me.filoghost.chestcommands.util.Preconditions;
import me.filoghost.chestcommands.util.collection.CollectionUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.List;
public class InternalConfigurableIcon extends BaseConfigurableIcon implements RefreshableIcon {
private PermissionChecker viewPermission;
private PermissionChecker clickPermission;
private RequiredMoney requiredMoney;
private RequiredExpLevel requiredExpLevel;
private RequiredItems requiredItems;
private List<Action> clickActions;
private ClickResult clickResult;
public InternalConfigurableIcon(Material material) {
super(material);
setPlaceholdersEnabled(true);
this.clickResult = ClickResult.CLOSE;
}
public boolean canViewIcon(Player player) {
return viewPermission == null || viewPermission.hasPermission(player);
}
public boolean hasViewPermission() {
return viewPermission != null && !viewPermission.isEmpty();
}
public void setClickPermission(String permission) {
this.clickPermission = new PermissionChecker(permission);
}
public void setNoClickPermissionMessage(String clickNoPermissionMessage) {
clickPermission.setNoPermissionMessage(clickNoPermissionMessage);
}
public void setViewPermission(String viewPermission) {
this.viewPermission = new PermissionChecker(viewPermission);
}
public void setRequiredMoney(double requiredMoney) {
if (requiredMoney > 0.0) {
this.requiredMoney = new RequiredMoney(requiredMoney);
} else {
this.requiredMoney = null;
}
}
public void setRequiredExpLevel(int requiredLevels) {
if (requiredLevels > 0) {
this.requiredExpLevel = new RequiredExpLevel(requiredLevels);
} else {
this.requiredExpLevel = null;
}
}
public void setRequiredItems(List<RequiredItem> requiredItems) {
if (!CollectionUtils.isNullOrEmpty(requiredItems)) {
this.requiredItems = new RequiredItems(requiredItems);
} else {
this.requiredItems = null;
}
}
public void setClickActions(List<Action> clickActions) {
this.clickActions = CollectionUtils.nullableCopy(clickActions);
}
@Override
public ItemStack render(Player viewer) {
if (canViewIcon(viewer)) {
return super.render(viewer);
} else {
return null;
}
}
@Override
protected boolean shouldCacheRendering() {
return super.shouldCacheRendering() && !hasViewPermission();
}
public void setClickResult(ClickResult clickResult) {
Preconditions.notNull(clickResult, "clickResult");
this.clickResult = clickResult;
}
@Override
public ClickResult onClick(ItemInventory itemInventory, Player player) {
// Check all the requirements
boolean hasAllRequirements = Requirement.hasAll(player, clickPermission, requiredMoney, requiredExpLevel, requiredItems);
if (!hasAllRequirements) {
return clickResult;
}
// If all requirements are satisfied, take their cost
boolean takenAllCosts = Requirement.takeAllCosts(player, clickPermission, requiredMoney, requiredExpLevel, requiredItems);
if (!takenAllCosts) {
return clickResult;
}
boolean hasOpenMenuAction = false;
if (clickActions != null) {
for (Action action : clickActions) {
action.execute(player);
if (action instanceof OpenMenuAction) {
hasOpenMenuAction = true;
}
}
}
// Update the menu after taking requirement costs and executing all actions
itemInventory.refresh();
// Force menu to stay open if actions open another menu
if (hasOpenMenuAction) {
return ClickResult.KEEP_OPEN;
} else {
return clickResult;
}
}
@Override
public ItemStack updateRendering(Player viewer, ItemStack currentRendering) {
if (currentRendering != null && shouldCacheRendering()) {
// Internal icons do not change, no need to update if the item is already rendered
return currentRendering;
}
if (!canViewIcon(viewer)) {
// Hide the current item
return null;
}
if (currentRendering == null) {
// Render item normally
return render(viewer);
} else {
// Internal icons are loaded and then never change, we can safely update only name and lore (for performance)
ItemMeta meta = currentRendering.getItemMeta();
meta.setDisplayName(renderName(viewer));
meta.setLore(renderLore(viewer));
currentRendering.setItemMeta(meta);
return currentRendering;
}
}
}

View File

@ -0,0 +1,10 @@
package me.filoghost.chestcommands.icon;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public interface RefreshableIcon {
ItemStack updateRendering(Player viewer, ItemStack currentRendering);
}

View File

@ -1,88 +1,88 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.icon;
import org.bukkit.entity.Player;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.util.Strings;
public class PermissionChecker implements Requirement {
private final String permission;
private final boolean negated;
private String noPermissionMessage;
public PermissionChecker(String permission) {
if (permission != null) {
permission = permission.trim();
}
if (Strings.isNullOrEmpty(permission)) {
this.permission = null;
negated = false;
} else {
if (permission.startsWith("-")) {
this.permission = permission.substring(1);
negated = true;
} else {
this.permission = permission;
negated = false;
}
}
}
public void setNoPermissionMessage(String noPermissionMessage) {
this.noPermissionMessage = noPermissionMessage;
}
@Override
public boolean hasCost(Player player) {
if (hasPermission(player)) {
return true;
} else {
if (noPermissionMessage != null) {
player.sendMessage(noPermissionMessage);
} else {
player.sendMessage(ChestCommands.getLang().default_no_icon_permission);
}
return false;
}
}
public boolean hasPermission(Player player) {
if (isEmpty()) {
return true;
}
if (negated) {
return !player.hasPermission(permission);
} else {
return player.hasPermission(permission);
}
}
@Override
public boolean takeCost(Player player) {
return true;
}
public boolean isEmpty() {
return this.permission == null;
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.icon.requirement;
import org.bukkit.entity.Player;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.util.Strings;
public class PermissionChecker implements Requirement {
private final String permission;
private final boolean negated;
private String noPermissionMessage;
public PermissionChecker(String permission) {
if (permission != null) {
permission = permission.trim();
}
if (Strings.isNullOrEmpty(permission)) {
this.permission = null;
negated = false;
} else {
if (permission.startsWith("-")) {
this.permission = permission.substring(1);
negated = true;
} else {
this.permission = permission;
negated = false;
}
}
}
public void setNoPermissionMessage(String noPermissionMessage) {
this.noPermissionMessage = noPermissionMessage;
}
@Override
public boolean hasCost(Player player) {
if (hasPermission(player)) {
return true;
} else {
if (noPermissionMessage != null) {
player.sendMessage(noPermissionMessage);
} else {
player.sendMessage(ChestCommands.getLang().default_no_icon_permission);
}
return false;
}
}
public boolean hasPermission(Player player) {
if (isEmpty()) {
return true;
}
if (negated) {
return !player.hasPermission(permission);
} else {
return player.hasPermission(permission);
}
}
@Override
public boolean takeCost(Player player) {
return true;
}
public boolean isEmpty() {
return this.permission == null;
}
}

View File

@ -1,57 +1,57 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.icon;
import org.bukkit.entity.Player;
import com.google.common.base.Preconditions;
import me.filoghost.chestcommands.ChestCommands;
public class RequiredExpLevel implements Requirement {
private final int levels;
public RequiredExpLevel(int levels) {
Preconditions.checkArgument(levels > 0, "levels must be positive");
this.levels = levels;
}
public int getLevels() {
return levels;
}
@Override
public boolean hasCost(Player player) {
if (player.getLevel() < levels) {
player.sendMessage(ChestCommands.getLang().no_exp.replace("{levels}", Integer.toString(levels)));
return false;
}
return true;
}
@Override
public boolean takeCost(Player player) {
int newLevel = player.getLevel() - levels;
if (newLevel < 0) {
newLevel = 0;
}
player.setLevel(newLevel);
return true;
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.icon.requirement;
import org.bukkit.entity.Player;
import com.google.common.base.Preconditions;
import me.filoghost.chestcommands.ChestCommands;
public class RequiredExpLevel implements Requirement {
private final int levels;
public RequiredExpLevel(int levels) {
Preconditions.checkArgument(levels > 0, "levels must be positive");
this.levels = levels;
}
public int getLevels() {
return levels;
}
@Override
public boolean hasCost(Player player) {
if (player.getLevel() < levels) {
player.sendMessage(ChestCommands.getLang().no_exp.replace("{levels}", Integer.toString(levels)));
return false;
}
return true;
}
@Override
public boolean takeCost(Player player) {
int newLevel = player.getLevel() - levels;
if (newLevel < 0) {
newLevel = 0;
}
player.setLevel(newLevel);
return true;
}
}

View File

@ -1,111 +1,111 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.icon;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.filoghost.chestcommands.util.Preconditions;
public class RequiredItem {
private final Material material;
private final int amount;
private short durability;
private boolean isDurabilityRestrictive = false;
public RequiredItem(Material material, int amount) {
Preconditions.checkArgumentNotAir(material, "material");
this.material = material;
this.amount = amount;
}
public Material getMaterial() {
return material;
}
public int getAmount() {
return amount;
}
public short getDurability() {
return durability;
}
public void setRestrictiveDurability(short durability) {
Preconditions.checkArgument(durability >= 0, "Durability cannot be negative");
this.durability = durability;
isDurabilityRestrictive = true;
}
public boolean hasRestrictiveDurability() {
return isDurabilityRestrictive;
}
public boolean isItemContainedIn(Inventory inventory) {
int amountFound = 0;
for (ItemStack item : inventory.getContents()) {
if (isMatchingType(item)) {
amountFound += item.getAmount();
}
}
return amountFound >= amount;
}
public boolean takeItemFrom(Inventory inventory) {
if (amount <= 0) {
return true;
}
int itemsToTake = amount; // Start from amount and decrease
ItemStack[] contents = inventory.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack current = contents[i];
if (isMatchingType(current)) {
if (current.getAmount() > itemsToTake) {
current.setAmount(current.getAmount() - itemsToTake);
return true;
} else {
itemsToTake -= current.getAmount();
inventory.setItem(i, new ItemStack(Material.AIR));
}
}
// The end
if (itemsToTake <= 0) return true;
}
return false;
}
private boolean isMatchingType(ItemStack item) {
return item != null && item.getType() == material && isMatchingDurability(item.getDurability());
}
private boolean isMatchingDurability(short data) {
if (!isDurabilityRestrictive) {
return true;
}
return data == this.durability;
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.icon.requirement;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.filoghost.chestcommands.util.Preconditions;
public class RequiredItem {
private final Material material;
private final int amount;
private short durability;
private boolean isDurabilityRestrictive = false;
public RequiredItem(Material material, int amount) {
Preconditions.checkArgumentNotAir(material, "material");
this.material = material;
this.amount = amount;
}
public Material getMaterial() {
return material;
}
public int getAmount() {
return amount;
}
public short getDurability() {
return durability;
}
public void setRestrictiveDurability(short durability) {
Preconditions.checkArgument(durability >= 0, "Durability cannot be negative");
this.durability = durability;
isDurabilityRestrictive = true;
}
public boolean hasRestrictiveDurability() {
return isDurabilityRestrictive;
}
public boolean isItemContainedIn(Inventory inventory) {
int amountFound = 0;
for (ItemStack item : inventory.getContents()) {
if (isMatchingType(item)) {
amountFound += item.getAmount();
}
}
return amountFound >= amount;
}
public boolean takeItemFrom(Inventory inventory) {
if (amount <= 0) {
return true;
}
int itemsToTake = amount; // Start from amount and decrease
ItemStack[] contents = inventory.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack current = contents[i];
if (isMatchingType(current)) {
if (current.getAmount() > itemsToTake) {
current.setAmount(current.getAmount() - itemsToTake);
return true;
} else {
itemsToTake -= current.getAmount();
inventory.setItem(i, new ItemStack(Material.AIR));
}
}
// The end
if (itemsToTake <= 0) return true;
}
return false;
}
private boolean isMatchingType(ItemStack item) {
return item != null && item.getType() == material && isMatchingDurability(item.getDurability());
}
private boolean isMatchingDurability(short data) {
if (!isDurabilityRestrictive) {
return true;
}
return data == this.durability;
}
}

View File

@ -1,72 +1,72 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.icon;
import java.util.List;
import me.filoghost.chestcommands.util.Utils;
import org.bukkit.entity.Player;
import com.google.common.collect.ImmutableList;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.util.Preconditions;
public class RequiredItems implements Requirement {
private final List<RequiredItem> items;
public RequiredItems(List<RequiredItem> items) {
Preconditions.notEmpty(items, "items");
this.items = ImmutableList.copyOf(items);
}
public List<RequiredItem> geItems() {
return items;
}
@Override
public boolean hasCost(Player player) {
boolean missingItems = false;
for (RequiredItem item : items) {
if (!item.isItemContainedIn(player.getInventory())) {
missingItems = true;
player.sendMessage(ChestCommands.getLang().no_required_item
.replace("{material}", Utils.formatEnum(item.getMaterial()))
.replace("{amount}", Integer.toString(item.getAmount()))
.replace("{durability}", item.hasRestrictiveDurability() ? Short.toString(item.getDurability()) : ChestCommands.getLang().any)
);
}
}
return !missingItems;
}
@Override
public boolean takeCost(Player player) {
boolean missingItems = false;
for (RequiredItem item : items) {
boolean success = item.takeItemFrom(player.getInventory());
if (!success) {
missingItems = true;
}
}
return !missingItems;
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.icon.requirement;
import java.util.List;
import me.filoghost.chestcommands.util.Utils;
import org.bukkit.entity.Player;
import com.google.common.collect.ImmutableList;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.util.Preconditions;
public class RequiredItems implements Requirement {
private final List<RequiredItem> items;
public RequiredItems(List<RequiredItem> items) {
Preconditions.notEmpty(items, "items");
this.items = ImmutableList.copyOf(items);
}
public List<RequiredItem> geItems() {
return items;
}
@Override
public boolean hasCost(Player player) {
boolean missingItems = false;
for (RequiredItem item : items) {
if (!item.isItemContainedIn(player.getInventory())) {
missingItems = true;
player.sendMessage(ChestCommands.getLang().no_required_item
.replace("{material}", Utils.formatEnum(item.getMaterial()))
.replace("{amount}", Integer.toString(item.getAmount()))
.replace("{durability}", item.hasRestrictiveDurability() ? Short.toString(item.getDurability()) : ChestCommands.getLang().any)
);
}
}
return !missingItems;
}
@Override
public boolean takeCost(Player player) {
boolean missingItems = false;
for (RequiredItem item : items) {
boolean success = item.takeItemFrom(player.getInventory());
if (!success) {
missingItems = true;
}
}
return !missingItems;
}
}

View File

@ -1,64 +1,64 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.icon;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import com.google.common.base.Preconditions;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.hook.VaultEconomyHook;
public class RequiredMoney implements Requirement {
private final double moneyAmount;
public RequiredMoney(double moneyAmount) {
Preconditions.checkArgument(moneyAmount > 0.0, "money amount must be positive");
this.moneyAmount = moneyAmount;
}
public double getAmount() {
return moneyAmount;
}
@Override
public boolean hasCost(Player player) {
if (!VaultEconomyHook.INSTANCE.isEnabled()) {
player.sendMessage(ChatColor.RED + "This action has a price, but Vault with a compatible economy plugin was not found. For security, the action has been blocked. Please inform the staff.");
return false;
}
if (!VaultEconomyHook.hasMoney(player, moneyAmount)) {
player.sendMessage(ChestCommands.getLang().no_money.replace("{money}", VaultEconomyHook.formatMoney(moneyAmount)));
return false;
}
return true;
}
@Override
public boolean takeCost(Player player) {
boolean success = VaultEconomyHook.takeMoney(player, moneyAmount);
if (!success) {
player.sendMessage(ChatColor.RED + "Error: a money transaction couldn't be executed. Please inform the staff.");
}
return success;
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.icon.requirement;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import com.google.common.base.Preconditions;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.hook.VaultEconomyHook;
public class RequiredMoney implements Requirement {
private final double moneyAmount;
public RequiredMoney(double moneyAmount) {
Preconditions.checkArgument(moneyAmount > 0.0, "money amount must be positive");
this.moneyAmount = moneyAmount;
}
public double getAmount() {
return moneyAmount;
}
@Override
public boolean hasCost(Player player) {
if (!VaultEconomyHook.INSTANCE.isEnabled()) {
player.sendMessage(ChatColor.RED + "This action has a price, but Vault with a compatible economy plugin was not found. For security, the action has been blocked. Please inform the staff.");
return false;
}
if (!VaultEconomyHook.hasMoney(player, moneyAmount)) {
player.sendMessage(ChestCommands.getLang().no_money.replace("{money}", VaultEconomyHook.formatMoney(moneyAmount)));
return false;
}
return true;
}
@Override
public boolean takeCost(Player player) {
boolean success = VaultEconomyHook.takeMoney(player, moneyAmount);
if (!success) {
player.sendMessage(ChatColor.RED + "Error: a money transaction couldn't be executed. Please inform the staff.");
}
return success;
}
}

View File

@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.icon;
package me.filoghost.chestcommands.icon.requirement;
import org.bukkit.entity.Player;

View File

@ -0,0 +1,72 @@
package me.filoghost.chestcommands.inventory;
import me.filoghost.chestcommands.api.ClickResult;
import me.filoghost.chestcommands.api.Icon;
import me.filoghost.chestcommands.api.ItemInventory;
import me.filoghost.chestcommands.icon.RefreshableIcon;
import me.filoghost.chestcommands.menu.BaseIconMenu;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/**
* Represents a particular view of a menu.
*/
public class DefaultItemInventory implements ItemInventory {
private final BaseIconMenu menu;
private final InventoryGrid bukkitInventory;
private final Player viewer;
public DefaultItemInventory(BaseIconMenu menu, Player viewer) {
this.menu = menu;
this.viewer = viewer;
this.bukkitInventory = new InventoryGrid(new MenuInventoryHolder(this), menu.getRowCount(), menu.getTitle());
refresh();
}
public BaseIconMenu getMenu() {
return menu;
}
@Override
public void refresh() {
for (int i = 0; i < menu.getIcons().getSize(); i++) {
Icon icon = menu.getIcons().getByIndex(i);
if (icon == null) {
bukkitInventory.setByIndex(i, null);
} else if (icon instanceof RefreshableIcon) {
ItemStack newItemStack = ((RefreshableIcon) icon).updateRendering(viewer, bukkitInventory.getByIndex(i));
bukkitInventory.setByIndex(i, newItemStack);
} else {
bukkitInventory.setByIndex(i, icon.render(viewer));
}
}
}
public void open(Player viewer) {
viewer.openInventory(bukkitInventory.getInventory());
}
public SlotClickHandler getSlotClickHandler(int slot, Player clicker) {
if (slot < 0 || slot >= bukkitInventory.getSize()) {
return null;
}
Icon icon = menu.getIcons().getByIndex(slot);
if (icon == null) {
return null;
}
return () -> icon.onClick(this, clicker);
}
@FunctionalInterface
public interface SlotClickHandler {
ClickResult onClick();
}
}

View File

@ -0,0 +1,31 @@
package me.filoghost.chestcommands.inventory;
import me.filoghost.chestcommands.util.collection.Grid;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class InventoryGrid extends Grid<ItemStack> {
private final Inventory inventory;
public InventoryGrid(MenuInventoryHolder inventoryHolder, int rows, String title) {
super(rows, 9);
this.inventory = Bukkit.createInventory(inventoryHolder, getSize(), title);
}
public Inventory getInventory() {
return inventory;
}
@Override
protected ItemStack getByIndex0(int ordinalIndex) {
return inventory.getItem(ordinalIndex);
}
@Override
protected void setByIndex0(int ordinalIndex, ItemStack element) {
inventory.setItem(ordinalIndex, element);
}
}

View File

@ -1,51 +1,45 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.inventory;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import me.filoghost.chestcommands.menu.BaseIconMenu;
import me.filoghost.chestcommands.util.Preconditions;
/**
* This class links an IconMenu with an Inventory, via InventoryHolder.
*/
public class MenuInventoryHolder implements InventoryHolder {
private final BaseIconMenu<?> iconMenu;
public MenuInventoryHolder(BaseIconMenu<?> iconMenu) {
Preconditions.notNull(iconMenu, "iconMenu");
this.iconMenu = iconMenu;
}
@Override
public Inventory getInventory() {
/*
* This inventory will not do anything.
* I'm 90% sure that it doesn't break any other plugin,
* because the only way you can get here is using InventoryClickEvent,
* that is cancelled by ChestCommands, or using InventoryOpenEvent.
*/
return Bukkit.createInventory(null, 9);
}
public BaseIconMenu<?> getIconMenu() {
return iconMenu;
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.inventory;
import me.filoghost.chestcommands.util.Preconditions;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
public class MenuInventoryHolder implements InventoryHolder {
private final DefaultItemInventory menuInventory;
public MenuInventoryHolder(DefaultItemInventory menuInventory) {
Preconditions.notNull(menuInventory, "menuInventory");
this.menuInventory = menuInventory;
}
@Override
public Inventory getInventory() {
/*
* This inventory will not do anything.
* I'm 90% sure that it doesn't break any other plugin,
* because the only way you can get here is using InventoryClickEvent,
* that is cancelled by ChestCommands, or using InventoryOpenEvent.
*/
return Bukkit.createInventory(null, 9);
}
public DefaultItemInventory getMenuInventory() {
return menuInventory;
}
}

View File

@ -14,14 +14,13 @@
*/
package me.filoghost.chestcommands.listener;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
public class CommandListener implements Listener {
private final MenuManager menuManager;
@ -38,7 +37,7 @@ public class CommandListener implements Listener {
return;
}
AdvancedIconMenu menu = menuManager.getMenuByCommand(command);
InternalIconMenu menu = menuManager.getMenuByCommand(command);
if (menu == null) {
return;

View File

@ -14,9 +14,11 @@
*/
package me.filoghost.chestcommands.listener;
import java.util.HashMap;
import java.util.Map;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.api.ClickResult;
import me.filoghost.chestcommands.inventory.DefaultItemInventory.SlotClickHandler;
import me.filoghost.chestcommands.menu.MenuManager;
import me.filoghost.chestcommands.inventory.DefaultItemInventory;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -25,22 +27,19 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.api.Icon;
import me.filoghost.chestcommands.menu.BaseIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import java.util.Map;
import java.util.WeakHashMap;
public class InventoryListener implements Listener {
private static final Map<Player, Long> antiClickSpam = new HashMap<>();
private final MenuManager menuManager;
private final Map<Player, Long> antiClickSpam;
public InventoryListener(MenuManager menuManager) {
this.menuManager = menuManager;
this.antiClickSpam = new WeakHashMap<>();
}
@ -62,25 +61,20 @@ public class InventoryListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
public void onLateInventoryClick(InventoryClickEvent event) {
Inventory inventory = event.getInventory();
BaseIconMenu<?> menu = MenuManager.getOpenMenu(inventory);
if (menu == null) {
DefaultItemInventory menuInventory = MenuManager.getOpenMenuInventory(inventory);
if (menuInventory == null) {
return;
}
// Make sure the event is still cancelled (in case another plugin wrongly uncancels it)
event.setCancelled(true);
// Cancel the event again just in case a plugin un-cancels it
event.setCancelled(true);
int slot = event.getRawSlot();
if (slot < 0 || slot >= menu.getSize()) {
return;
}
Icon icon = menu.getIconAtSlot(slot);
if (icon == null || event.getInventory().getItem(slot) == null) {
return;
}
Player clicker = (Player) event.getWhoClicked();
SlotClickHandler slotClickHandler = menuInventory.getSlotClickHandler(slot, clicker);
if (slotClickHandler == null) {
return;
}
Long cooldownUntil = antiClickSpam.get(clicker);
long now = System.currentTimeMillis();
@ -96,17 +90,12 @@ public class InventoryListener implements Listener {
// Only handle the click AFTER the event has finished
Bukkit.getScheduler().runTask(ChestCommands.getInstance(), () -> {
boolean close = icon.onClick(inventory, clicker);
ClickResult result = slotClickHandler.onClick();
if (close) {
if (result == ClickResult.CLOSE) {
clicker.closeInventory();
}
});
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
antiClickSpam.remove(event.getPlayer());
}
}

View File

@ -14,6 +14,10 @@
*/
package me.filoghost.chestcommands.listener;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.Permissions;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import org.bukkit.ChatColor;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
@ -25,11 +29,6 @@ import org.bukkit.event.block.Action;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.Permissions;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
public class SignListener implements Listener {
private static final int HEADER_LINE = 0;
@ -65,7 +64,7 @@ public class SignListener implements Listener {
}
String menuFileName = addYamlExtension(sign.getLine(FILENAME_LINE).trim());
AdvancedIconMenu menu = menuManager.getMenuByFileName(menuFileName);
InternalIconMenu menu = menuManager.getMenuByFileName(menuFileName);
if (menu == null) {
event.getPlayer().sendMessage(ChestCommands.getLang().menu_not_found);
@ -88,7 +87,7 @@ public class SignListener implements Listener {
menuFileName = addYamlExtension(menuFileName);
AdvancedIconMenu iconMenu = menuManager.getMenuByFileName(menuFileName);
InternalIconMenu iconMenu = menuManager.getMenuByFileName(menuFileName);
if (iconMenu == null) {
event.setCancelled(true);
event.getPlayer().sendMessage(ChatColor.RED + "Menu \"" + menuFileName + "\" was not found.");

View File

@ -1,95 +1,76 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.filoghost.chestcommands.api.Icon;
import me.filoghost.chestcommands.menu.inventory.Grid;
import me.filoghost.chestcommands.menu.inventory.MenuInventoryHolder;
import me.filoghost.chestcommands.util.Preconditions;
public class BaseIconMenu<T extends Icon> {
protected final String title;
protected final Grid<T> inventoryGrid;
public BaseIconMenu(String title, int rows) {
this.title = title;
this.inventoryGrid = new Grid<>(rows, 9);
}
public void setIcon(int x, int y, T icon) {
inventoryGrid.setElement(x, y, icon);
}
public T getIcon(int x, int y) {
return inventoryGrid.getElement(x, y);
}
public T getIconAtSlot(int slot) {
return inventoryGrid.getElementAtIndex(slot);
}
public int getRowCount() {
return inventoryGrid.getRows();
}
public int getColumnCount() {
return inventoryGrid.getColumns();
}
public int getSize() {
return inventoryGrid.getSize();
}
public String getTitle() {
return title;
}
public void open(Player player) {
Preconditions.notNull(player, "player");
Inventory inventory = Bukkit.createInventory(new MenuInventoryHolder(this), getSize(), title);
for (int i = 0; i < inventoryGrid.getSize(); i++) {
T icon = inventoryGrid.getElementAtIndex(i);
if (icon == null) {
continue;
}
ItemStack itemStack = icon.createItemStack(player);
if (itemStack == null) {
continue;
}
inventory.setItem(i, itemStack);
}
player.openInventory(inventory);
}
@Override
public String toString() {
return "IconMenu [title=" + title + ", icons=" + inventoryGrid + "]";
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu;
import me.filoghost.chestcommands.api.Icon;
import me.filoghost.chestcommands.api.IconMenu;
import me.filoghost.chestcommands.api.ItemInventory;
import me.filoghost.chestcommands.inventory.DefaultItemInventory;
import me.filoghost.chestcommands.util.Preconditions;
import me.filoghost.chestcommands.util.collection.ArrayGrid;
import me.filoghost.chestcommands.util.collection.Grid;
import org.bukkit.entity.Player;
public abstract class BaseIconMenu implements IconMenu {
protected final String title;
protected final Grid<Icon> icons;
public BaseIconMenu(String title, int rows) {
this.title = title;
this.icons = new ArrayGrid<>(rows, 9);
}
@Override
public void setIcon(int row, int column, Icon icon) {
icons.set(row, column, icon);
}
@Override
public Icon getIcon(int row, int column) {
return icons.get(row, column);
}
@Override
public int getRowCount() {
return icons.getRows();
}
@Override
public int getColumnCount() {
return icons.getColumns();
}
@Override
public String getTitle() {
return title;
}
public Grid<Icon> getIcons() {
return icons;
}
@Override
public ItemInventory open(Player player) {
Preconditions.notNull(player, "player");
DefaultItemInventory menuInventory = new DefaultItemInventory(this, player);
menuInventory.open(player);
return menuInventory;
}
}

View File

@ -1,103 +1,87 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.Permissions;
import me.filoghost.chestcommands.action.Action;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.util.collection.CollectionUtils;
public class AdvancedIconMenu extends BaseIconMenu<AdvancedIcon> {
private final String fileName;
private final String openPermission;
private List<Action> openActions;
private int refreshTicks;
public AdvancedIconMenu(String title, int rows, String fileName) {
super(title, rows);
this.fileName = fileName;
this.openPermission = Permissions.OPEN_MENU_BASE + fileName;
}
public String getFileName() {
return fileName;
}
public void setOpenActions(List<Action> openAction) {
this.openActions = CollectionUtils.nullableCopy(openAction);
}
public String getOpenPermission() {
return openPermission;
}
public int getRefreshTicks() {
return refreshTicks;
}
public void setRefreshTicks(int refreshTicks) {
this.refreshTicks = refreshTicks;
}
@Override
public void open(Player player) {
if (openActions != null) {
for (Action openAction : openActions) {
openAction.execute(player);
}
}
super.open(player);
}
public void openCheckingPermission(Player player) {
if (player.hasPermission(openPermission)) {
open(player);
} else {
sendNoOpenPermissionMessage(player);
}
}
public void refresh(Player player, Inventory inventory) {
for (int i = 0; i < inventoryGrid.getSize(); i++) {
AdvancedIcon icon = inventoryGrid.getElementAtIndex(i);
if (icon == null) {
continue;
}
ItemStack newItemStack = icon.refreshItemStack(player, inventory.getItem(i));
inventory.setItem(i, newItemStack);
}
}
public void sendNoOpenPermissionMessage(CommandSender sender) {
String noPermMessage = ChestCommands.getLang().no_open_permission;
if (noPermMessage != null && !noPermMessage.isEmpty()) {
sender.sendMessage(noPermMessage.replace("{permission}", this.openPermission));
}
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.Permissions;
import me.filoghost.chestcommands.action.Action;
import me.filoghost.chestcommands.api.ItemInventory;
import me.filoghost.chestcommands.util.collection.CollectionUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class InternalIconMenu extends BaseIconMenu {
private final String fileName;
private final String openPermission;
private List<Action> openActions;
private int refreshTicks;
public InternalIconMenu(String title, int rows, String fileName) {
super(title, rows);
this.fileName = fileName;
this.openPermission = Permissions.OPEN_MENU_BASE + fileName;
}
public String getFileName() {
return fileName;
}
public void setOpenActions(List<Action> openAction) {
this.openActions = CollectionUtils.nullableCopy(openAction);
}
public String getOpenPermission() {
return openPermission;
}
public int getRefreshTicks() {
return refreshTicks;
}
public void setRefreshTicks(int refreshTicks) {
this.refreshTicks = refreshTicks;
}
@Override
public ItemInventory open(Player player) {
if (openActions != null) {
for (Action openAction : openActions) {
openAction.execute(player);
}
}
return super.open(player);
}
public void openCheckingPermission(Player player) {
if (player.hasPermission(openPermission)) {
open(player);
} else {
sendNoOpenPermissionMessage(player);
}
}
public void sendNoOpenPermissionMessage(CommandSender sender) {
String noPermMessage = ChestCommands.getLang().no_open_permission;
if (noPermMessage != null && !noPermMessage.isEmpty()) {
sender.sendMessage(noPermMessage.replace("{permission}", this.openPermission));
}
}
}

View File

@ -14,8 +14,9 @@
*/
package me.filoghost.chestcommands.menu;
import me.filoghost.chestcommands.inventory.DefaultItemInventory;
import me.filoghost.chestcommands.inventory.MenuInventoryHolder;
import me.filoghost.chestcommands.parsing.menu.LoadedMenu;
import me.filoghost.chestcommands.menu.inventory.MenuInventoryHolder;
import me.filoghost.chestcommands.parsing.menu.OpenTrigger;
import me.filoghost.chestcommands.util.collection.CaseInsensitiveMap;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
@ -32,9 +33,9 @@ import java.util.Map;
public class MenuManager {
private static Map<String, AdvancedIconMenu> menusByFile;
private static Map<String, AdvancedIconMenu> menusByCommand;
private static Map<OpenTrigger, AdvancedIconMenu> menusByOpenTrigger;
private static Map<String, InternalIconMenu> menusByFile;
private static Map<String, InternalIconMenu> menusByCommand;
private static Map<OpenTrigger, InternalIconMenu> menusByOpenTrigger;
public MenuManager() {
menusByFile = new CaseInsensitiveMap<>();
@ -48,12 +49,12 @@ public class MenuManager {
menusByOpenTrigger.clear();
}
public AdvancedIconMenu getMenuByFileName(String fileName) {
public InternalIconMenu getMenuByFileName(String fileName) {
return menusByFile.get(fileName);
}
public void registerMenu(LoadedMenu loadedMenu, ErrorCollector errorCollector) {
AdvancedIconMenu menu = loadedMenu.getMenu();
InternalIconMenu menu = loadedMenu.getMenu();
if (menusByFile.containsKey(loadedMenu.getFileName())) {
errorCollector.addError("Two menus have the same file name \"" + loadedMenu.getFileName() + "\". "
@ -86,7 +87,7 @@ public class MenuManager {
});
}
public AdvancedIconMenu getMenuByCommand(String command) {
public InternalIconMenu getMenuByCommand(String command) {
return menusByCommand.get(command);
}
@ -97,44 +98,26 @@ public class MenuManager {
public static boolean isMenuInventory(Inventory inventory) {
return getMenuInventoryHolder(inventory) != null;
}
public static BaseIconMenu<?> getOpenMenu(Player player) {
MenuView menuView = getOpenMenuView(player);
if (menuView != null) {
return menuView.getMenu();
} else {
return null;
}
}
public static BaseIconMenu<?> getOpenMenu(Inventory inventory) {
MenuView menuView = getOpenMenuView(inventory);
if (menuView != null) {
return menuView.getMenu();
} else {
return null;
}
}
public static MenuView getOpenMenuView(Player player) {
public static DefaultItemInventory getOpenMenuInventory(Player player) {
InventoryView view = player.getOpenInventory();
if (view == null) {
return null;
}
MenuView openMenuView = getOpenMenuView(view.getTopInventory());
if (openMenuView == null) {
openMenuView = getOpenMenuView(view.getBottomInventory());
DefaultItemInventory menuInventory = getOpenMenuInventory(view.getTopInventory());
if (menuInventory == null) {
menuInventory = getOpenMenuInventory(view.getBottomInventory());
}
return openMenuView;
return menuInventory;
}
public static MenuView getOpenMenuView(Inventory inventory) {
public static DefaultItemInventory getOpenMenuInventory(Inventory inventory) {
MenuInventoryHolder inventoryHolder = getMenuInventoryHolder(inventory);
if (inventoryHolder != null) {
return new MenuView(inventoryHolder.getIconMenu(), inventory);
return inventoryHolder.getMenuInventory();
} else {
return null;
}

View File

@ -1,37 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu;
import org.bukkit.inventory.Inventory;
public class MenuView {
private final BaseIconMenu<?> menu;
private final Inventory inventory;
public MenuView(BaseIconMenu<?> menu, Inventory inventory) {
this.menu = menu;
this.inventory = inventory;
}
public BaseIconMenu<?> getMenu() {
return menu;
}
public Inventory getInventory() {
return inventory;
}
}

View File

@ -14,10 +14,10 @@
*/
package me.filoghost.chestcommands.parsing.icon;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
public interface ApplicableIconAttribute extends IconAttribute {
void apply(AdvancedIcon icon);
void apply(InternalConfigurableIcon icon);
}

View File

@ -16,7 +16,7 @@ package me.filoghost.chestcommands.parsing.icon;
import me.filoghost.chestcommands.config.ConfigSection;
import me.filoghost.chestcommands.config.ConfigValueException;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.attributes.ActionsAttribute;
import me.filoghost.chestcommands.parsing.icon.attributes.AmountAttribute;
@ -38,8 +38,8 @@ import me.filoghost.chestcommands.parsing.icon.attributes.PriceAttribute;
import me.filoghost.chestcommands.parsing.icon.attributes.RequiredItemsAttribute;
import me.filoghost.chestcommands.parsing.icon.attributes.SkullOwnerAttribute;
import me.filoghost.chestcommands.parsing.icon.attributes.ViewPermissionAttribute;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
import me.filoghost.chestcommands.util.Preconditions;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
import java.util.ArrayList;
import java.util.HashMap;
@ -118,7 +118,7 @@ public class IconSettings {
applicableAttributes.add(iconAttribute);
}
public void applyAttributesTo(AdvancedIcon icon) {
public void applyAttributesTo(InternalConfigurableIcon icon) {
if (materialAttribute != null) {
materialAttribute.apply(icon);
}

View File

@ -15,7 +15,7 @@
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.action.Action;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ActionParser;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -40,7 +40,7 @@ public class ActionsAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setClickActions(actions);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -31,7 +31,7 @@ public class AmountAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setAmount(amount);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ItemMetaParser;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
@ -30,7 +30,7 @@ public class BannerColorAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setBannerColor(dyeColor);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ItemMetaParser;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
@ -47,7 +47,7 @@ public class BannerPatternsAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setBannerPatterns(patterns);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -27,7 +27,7 @@ public class ClickPermissionAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setClickPermission(clickPermission);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -27,7 +27,7 @@ public class ClickPermissionMessageAttribute implements ApplicableIconAttribute
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setNoClickPermissionMessage(clickPermissionMessage);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -27,7 +27,7 @@ public class DurabilityAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setDurability(durability);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.EnchantmentParser;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
@ -47,7 +47,7 @@ public class EnchantmentsAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setEnchantments(enchantments);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -31,7 +31,7 @@ public class ExpLevelsAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setRequiredExpLevel(expLevels);
}

View File

@ -14,21 +14,26 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.api.ClickResult;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
public class KeepOpenAttribute implements ApplicableIconAttribute {
private final boolean keepOpen;
private final ClickResult clickResult;
public KeepOpenAttribute(boolean keepOpen, AttributeErrorCollector attributeErrorCollector) {
this.keepOpen = keepOpen;
if (keepOpen) {
this.clickResult = ClickResult.KEEP_OPEN;
} else {
this.clickResult = ClickResult.CLOSE;
}
}
@Override
public void apply(AdvancedIcon icon) {
icon.setCloseOnClick(!keepOpen);
public void apply(InternalConfigurableIcon icon) {
icon.setClickResult(clickResult);
}
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ItemMetaParser;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
@ -30,7 +30,7 @@ public class LeatherColorAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setLeatherColor(color);
}

View File

@ -15,7 +15,7 @@
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
import me.filoghost.chestcommands.util.Colors;
@ -31,7 +31,7 @@ public class LoreAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setLore(lore);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -38,7 +38,7 @@ public class MaterialAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setMaterial(material);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -37,7 +37,7 @@ public class NBTDataAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setNBTData(nbtData);
}

View File

@ -15,7 +15,7 @@
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
import me.filoghost.chestcommands.util.Colors;
@ -29,7 +29,7 @@ public class NameAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setName(name);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -31,7 +31,7 @@ public class PriceAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setRequiredMoney(price);
}

View File

@ -14,8 +14,8 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.menu.icon.RequiredItem;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.icon.requirement.RequiredItem;
import me.filoghost.chestcommands.parsing.ItemStackParser;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
@ -46,7 +46,7 @@ public class RequiredItemsAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setRequiredItems(requiredItems);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -27,7 +27,7 @@ public class SkullOwnerAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setSkullOwner(skullOwner);
}

View File

@ -14,7 +14,7 @@
*/
package me.filoghost.chestcommands.parsing.icon.attributes;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.icon.ApplicableIconAttribute;
import me.filoghost.chestcommands.parsing.icon.AttributeErrorCollector;
@ -27,7 +27,7 @@ public class ViewPermissionAttribute implements ApplicableIconAttribute {
}
@Override
public void apply(AdvancedIcon icon) {
public void apply(InternalConfigurableIcon icon) {
icon.setViewPermission(viewPermission);
}

View File

@ -1,24 +1,24 @@
package me.filoghost.chestcommands.parsing.menu;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import java.util.List;
public class LoadedMenu {
private final AdvancedIconMenu menu;
private final InternalIconMenu menu;
private final String fileName;
private final List<String> triggerCommands;
private final OpenTrigger openTrigger;
public LoadedMenu(AdvancedIconMenu menu, String fileName, List<String> triggerCommands, OpenTrigger openTrigger) {
public LoadedMenu(InternalIconMenu menu, String fileName, List<String> triggerCommands, OpenTrigger openTrigger) {
this.menu = menu;
this.fileName = fileName;
this.triggerCommands = triggerCommands;
this.openTrigger = openTrigger;
}
public AdvancedIconMenu getMenu() {
public InternalIconMenu getMenu() {
return menu;
}

View File

@ -18,16 +18,16 @@ import me.filoghost.chestcommands.action.Action;
import me.filoghost.chestcommands.config.Config;
import me.filoghost.chestcommands.config.ConfigSection;
import me.filoghost.chestcommands.config.ConfigValueException;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.menu.icon.AdvancedIcon;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ActionParser;
import me.filoghost.chestcommands.parsing.ErrorFormat;
import me.filoghost.chestcommands.parsing.ItemStackParser;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.IconSettingsNode;
import me.filoghost.chestcommands.parsing.icon.IconSettings;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
import me.filoghost.chestcommands.parsing.icon.IconSettingsNode;
import me.filoghost.chestcommands.util.Colors;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -41,7 +41,7 @@ public class MenuParser {
MenuSettings menuSettings = loadMenuSettings(menuConfig, errorCollector);
List<IconSettings> iconSettingsList = loadIconSettingsList(menuConfig, errorCollector);
AdvancedIconMenu iconMenu = new AdvancedIconMenu(menuSettings.getTitle(), menuSettings.getRows(), menuConfig.getFileName());
InternalIconMenu iconMenu = new InternalIconMenu(menuSettings.getTitle(), menuSettings.getRows(), menuConfig.getFileName());
for (IconSettings iconSettings : iconSettingsList) {
try {
@ -58,7 +58,7 @@ public class MenuParser {
}
private static void addIconToMenu(AdvancedIconMenu iconMenu, IconSettings iconSettings, ErrorCollector errorCollector) throws IconAddException {
private static void addIconToMenu(InternalIconMenu iconMenu, IconSettings iconSettings, ErrorCollector errorCollector) throws IconAddException {
if (iconSettings.getPositionX() == null) {
throw new IconAddException(ErrorFormat.missingAttribute(iconSettings, IconSettingsNode.POSITION_X));
}
@ -67,19 +67,19 @@ public class MenuParser {
throw new IconAddException(ErrorFormat.missingAttribute(iconSettings, IconSettingsNode.POSITION_Y));
}
int actualX = iconSettings.getPositionX().getPosition() - 1;
int actualY = iconSettings.getPositionY().getPosition() - 1;
int row = iconSettings.getPositionY().getPosition() - 1;
int column = iconSettings.getPositionX().getPosition() - 1;
if (actualX < 0 || actualX >= iconMenu.getColumnCount()) {
throw new IconAddException(ErrorFormat.invalidAttribute(iconSettings, IconSettingsNode.POSITION_X,
"it must be between 1 and " + iconMenu.getColumnCount()));
}
if (actualY < 0 || actualY >= iconMenu.getRowCount()) {
if (row < 0 || row >= iconMenu.getRowCount()) {
throw new IconAddException(ErrorFormat.invalidAttribute(iconSettings, IconSettingsNode.POSITION_Y,
"it must be between 1 and " + iconMenu.getRowCount()));
}
if (column < 0 || column >= iconMenu.getColumnCount()) {
throw new IconAddException(ErrorFormat.invalidAttribute(iconSettings, IconSettingsNode.POSITION_X,
"it must be between 1 and " + iconMenu.getColumnCount()));
}
if (iconMenu.getIcon(actualX, actualY) != null) {
if (iconMenu.getIcon(row, column) != null) {
throw new IconAddException(ErrorFormat.iconError(iconSettings,
"is overriding another icon with the same position"));
}
@ -88,9 +88,9 @@ public class MenuParser {
errorCollector.addError(ErrorFormat.missingAttribute(iconSettings, IconSettingsNode.MATERIAL));
}
AdvancedIcon icon = new AdvancedIcon(Material.BEDROCK);
InternalConfigurableIcon icon = new InternalConfigurableIcon(Material.BEDROCK);
iconSettings.applyAttributesTo(icon);
iconMenu.setIcon(actualX, actualY, icon);
iconMenu.setIcon(row, column, icon);
}

View File

@ -14,13 +14,12 @@
*/
package me.filoghost.chestcommands.task;
import me.filoghost.chestcommands.inventory.DefaultItemInventory;
import me.filoghost.chestcommands.menu.InternalIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.filoghost.chestcommands.menu.AdvancedIconMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import me.filoghost.chestcommands.menu.MenuView;
public class RefreshMenusTask implements Runnable {
private long elapsedTenths;
@ -28,19 +27,16 @@ public class RefreshMenusTask implements Runnable {
@Override
public void run() {
for (Player player : Bukkit.getOnlinePlayers()) {
MenuView openMenuView = MenuManager.getOpenMenuView(player);
if (openMenuView == null) {
return;
DefaultItemInventory itemInventory = MenuManager.getOpenMenuInventory(player);
if (itemInventory == null || !(itemInventory.getMenu() instanceof InternalIconMenu)) {
continue;
}
if (!(openMenuView.getMenu() instanceof AdvancedIconMenu)) {
return;
}
AdvancedIconMenu iconMenu = (AdvancedIconMenu) openMenuView.getMenu();
if (elapsedTenths % iconMenu.getRefreshTicks() == 0) {
iconMenu.refresh(player, openMenuView.getInventory());
int refreshTicks = ((InternalIconMenu) itemInventory.getMenu()).getRefreshTicks();
if (refreshTicks > 0 && elapsedTenths % refreshTicks == 0) {
itemInventory.refresh();
}
}

View File

@ -1,7 +1,5 @@
package me.filoghost.chestcommands.util;
import org.bukkit.Material;
public class Utils {
public static boolean isClassLoaded(String name) {

View File

@ -0,0 +1,23 @@
package me.filoghost.chestcommands.util.collection;
public class ArrayGrid<T> extends Grid<T> {
private final T[] elements;
@SuppressWarnings("unchecked")
public ArrayGrid(int rows, int columns) {
super(rows, columns);
this.elements = (T[]) new Object[getSize()];
}
@Override
protected T getByIndex0(int ordinalIndex) {
return elements[ordinalIndex];
}
@Override
protected void setByIndex0(int ordinalIndex, T element) {
elements[ordinalIndex] = element;
}
}

View File

@ -1,82 +1,89 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.menu.inventory;
import me.filoghost.chestcommands.util.Preconditions;
/*
* Example:
* There 3 rows and 9 columns. The number inside the cells is the index.
*
* <--- Column --->
*
* 0 1 2 3 4 5 6 7 8
* ^ +--------------------------------------------+
* | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
* |----+----+----+----+----+----+----+----+----|
* Row 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
* |----+----+----+----+----+----+----+----+----|
* | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
* v +--------------------------------------------+
*
*/
public class Grid<T> {
private final int rows, columns;
private final T[] elements;
@SuppressWarnings("unchecked")
public Grid(int rows, int columns) {
this.rows = rows;
this.columns = columns;
elements = (T[]) new Object[rows * columns];
}
public void setElement(int x, int y, T element) {
elements[getOrdinalIndex(x, y)] = element;
}
public T getElement(int x, int y) {
return getElementAtIndex(getOrdinalIndex(x, y));
}
public T getElementAtIndex(int ordinalIndex) {
Preconditions.checkIndex(ordinalIndex, getSize(), "ordinalIndex");
return elements[ordinalIndex];
}
private int getOrdinalIndex(int x, int y) {
Preconditions.checkIndex(x, getColumns(), "x");
Preconditions.checkIndex(y, getRows(), "y");
int ordinalIndex = y * getColumns() + x;
Preconditions.checkIndex(ordinalIndex, getSize(), "ordinalIndex");
return ordinalIndex;
}
public int getRows() {
return rows;
}
public int getColumns() {
return columns;
}
public int getSize() {
return elements.length;
}
}
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package me.filoghost.chestcommands.util.collection;
import me.filoghost.chestcommands.util.Preconditions;
/*
* Example:
* There 3 rows and 9 columns. The number inside the cells is the index.
*
* <--- Column --->
*
* 0 1 2 3 4 5 6 7 8
* ^ +--------------------------------------------+
* | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
* |----+----+----+----+----+----+----+----+----|
* Row 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
* |----+----+----+----+----+----+----+----+----|
* | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
* v +--------------------------------------------+
*
*/
public abstract class Grid<T> {
private final int rows, columns, size;
public Grid(int rows, int columns) {
this.rows = rows;
this.columns = columns;
this.size = rows * columns;
}
public final void set(int row, int column, T element) {
setByIndex(toOrdinalIndex(row, column), element);
}
public final T get(int row, int column) {
return getByIndex(toOrdinalIndex(row, column));
}
public final T getByIndex(int ordinalIndex) {
Preconditions.checkIndex(ordinalIndex, getSize(), "ordinalIndex");
return getByIndex0(ordinalIndex);
}
protected abstract T getByIndex0(int ordinalIndex);
public final void setByIndex(int ordinalIndex, T element) {
Preconditions.checkIndex(ordinalIndex, getSize(), "ordinalIndex");
setByIndex0(ordinalIndex, element);
}
protected abstract void setByIndex0(int ordinalIndex, T element);
private int toOrdinalIndex(int row, int column) {
Preconditions.checkIndex(row, getRows(), "row");
Preconditions.checkIndex(column, getColumns(), "column");
int ordinalIndex = row * getColumns() + column;
Preconditions.checkIndex(ordinalIndex, getSize(), "ordinalIndex");
return ordinalIndex;
}
public int getRows() {
return rows;
}
public int getColumns() {
return columns;
}
public int getSize() {
return size;
}
}