diff --git a/src/main/java/com/artillexstudios/axvaults/AxVaults.java b/src/main/java/com/artillexstudios/axvaults/AxVaults.java index 884012b..02ca1ab 100644 --- a/src/main/java/com/artillexstudios/axvaults/AxVaults.java +++ b/src/main/java/com/artillexstudios/axvaults/AxVaults.java @@ -20,11 +20,7 @@ import com.artillexstudios.axvaults.database.impl.SQLite; import com.artillexstudios.axvaults.database.messaging.SQLMessaging; import com.artillexstudios.axvaults.libraries.Libraries; -import com.artillexstudios.axvaults.listeners.BlackListListener; -import com.artillexstudios.axvaults.listeners.BlockBreakListener; -import com.artillexstudios.axvaults.listeners.InventoryCloseListener; -import com.artillexstudios.axvaults.listeners.PlayerInteractListener; -import com.artillexstudios.axvaults.listeners.PlayerListeners; +import com.artillexstudios.axvaults.listeners.*; import com.artillexstudios.axvaults.schedulers.AutoSaveScheduler; import com.artillexstudios.axvaults.utils.UpdateNotifier; import com.artillexstudios.axvaults.vaults.Vault; @@ -91,6 +87,7 @@ public void enable() { getServer().getPluginManager().registerEvents(new PlayerListeners(), this); getServer().getPluginManager().registerEvents(new BlackListListener(), this); + getServer().getPluginManager().registerEvents(new WhiteListListener(), this); getServer().getPluginManager().registerEvents(new PlayerInteractListener(), this); getServer().getPluginManager().registerEvents(new BlockBreakListener(), this); getServer().getPluginManager().registerEvents(new InventoryCloseListener(), this); diff --git a/src/main/java/com/artillexstudios/axvaults/guis/VaultSelector.java b/src/main/java/com/artillexstudios/axvaults/guis/VaultSelector.java index 8fb82ef..eb0c546 100644 --- a/src/main/java/com/artillexstudios/axvaults/guis/VaultSelector.java +++ b/src/main/java/com/artillexstudios/axvaults/guis/VaultSelector.java @@ -4,6 +4,7 @@ import com.artillexstudios.axapi.reflection.ClassUtils; import com.artillexstudios.axapi.utils.ItemBuilder; import com.artillexstudios.axapi.utils.StringUtils; +import com.artillexstudios.axvaults.utils.IntRange; import com.artillexstudios.axvaults.vaults.VaultManager; import dev.triumphteam.gui.guis.Gui; import dev.triumphteam.gui.guis.GuiItem; @@ -15,6 +16,7 @@ import org.jetbrains.annotations.NotNull; import java.util.HashMap; +import java.util.List; import java.util.function.Consumer; import static com.artillexstudios.axvaults.AxVaults.CONFIG; @@ -43,10 +45,22 @@ public void open(@NotNull Player player, int page) { .disableAllInteractions() .create(); + List slots = MESSAGES.getList("guis.selector.slots").stream() + .map(IntRange::valueOf) + .flatMap((range) -> range.getValues().stream()) + .toList(); + for (int i = 0; i < pageSize * (page + 1); i++) { + final int index = i; // We have to set this here to ensure the list index is final getItemOfVault(player, i + 1, gui, guiItem -> { if (guiItem == null) return; - gui.addItem(guiItem); + + if (slots.isEmpty()) { + gui.addItem(guiItem); + } else { + int slot = slots.get(index); + gui.setItem(slot, guiItem); + } }); } @@ -64,9 +78,14 @@ public void open(@NotNull Player player, int page) { gui.next(); for (int i = 0; i < pageSize; i++) { + final int index = i; // We have to set this here to ensure the list index is final getItemOfVault(player, (gui.getCurrentPageNum() * pageSize) + i + 1, gui, guiItem -> { - if (guiItem == null) return; - gui.addItem(guiItem); + if (slots.isEmpty()) { + gui.addItem(guiItem); + } else { + int slot = slots.get(index); + gui.setItem(slot, guiItem); + } }); } }); @@ -80,6 +99,20 @@ public void open(@NotNull Player player, int page) { gui.setItem(rows, 5, item3); } + for (String s : MESSAGES.getSection("gui-items").getRoutesAsStrings(false)) { + if (s.equals("close") || s.equals("back") || s.equals("previous-page") || s.equals("next-page")) { + continue; + } + + Section itemSection = MESSAGES.getSection("gui-items." + s); + final GuiItem item = new GuiItem(new ItemBuilder(itemSection).get()); + + gui.setItem(MESSAGES.getList("gui-items.%s.slots".formatted(s)).stream() + .map(IntRange::valueOf) + .flatMap((range) -> range.getValues().stream()) + .toList(), item); + } + gui.open(player, page); } diff --git a/src/main/java/com/artillexstudios/axvaults/listeners/BlackListListener.java b/src/main/java/com/artillexstudios/axvaults/listeners/BlackListListener.java index 24b2029..1fd0a11 100644 --- a/src/main/java/com/artillexstudios/axvaults/listeners/BlackListListener.java +++ b/src/main/java/com/artillexstudios/axvaults/listeners/BlackListListener.java @@ -1,5 +1,6 @@ package com.artillexstudios.axvaults.listeners; +import com.artillexstudios.axvaults.utils.IntRange; import com.artillexstudios.axvaults.vaults.Vault; import com.artillexstudios.axvaults.vaults.VaultManager; import org.bukkit.entity.Player; @@ -38,6 +39,17 @@ public void onClick(@NotNull InventoryClickEvent event) { banned = true; } + if (CONFIG.getString("blacklisted-items." + s + ".custom-model-data") != null) { + if (it.getItemMeta() == null + || !it.getItemMeta().hasCustomModelData() + || !IntRange.valueOf(CONFIG.get("blacklisted-items." + s + ".custom-model-data")).contains(it.getItemMeta().getCustomModelData()) + ) { + continue; + } + + banned = true; + } + if (CONFIG.getString("blacklisted-items." + s + ".name-contains") != null) { if (it.getItemMeta() == null) continue; if (!it.getItemMeta().getDisplayName().contains(CONFIG.getString("blacklisted-items." + s + ".name-contains"))) continue; diff --git a/src/main/java/com/artillexstudios/axvaults/listeners/WhiteListListener.java b/src/main/java/com/artillexstudios/axvaults/listeners/WhiteListListener.java new file mode 100644 index 0000000..f79de6e --- /dev/null +++ b/src/main/java/com/artillexstudios/axvaults/listeners/WhiteListListener.java @@ -0,0 +1,55 @@ +package com.artillexstudios.axvaults.listeners; + +import com.artillexstudios.axvaults.utils.IntRange; +import com.artillexstudios.axvaults.vaults.Vault; +import com.artillexstudios.axvaults.vaults.VaultManager; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import static com.artillexstudios.axvaults.AxVaults.CONFIG; +import static com.artillexstudios.axvaults.AxVaults.MESSAGEUTILS; + +public class WhiteListListener implements Listener { + + @EventHandler(priority = EventPriority.LOW) + public void onClick(InventoryClickEvent event) { + if (CONFIG.getSection("whitelisted-items") == null) return; + boolean isVault = false; + for (Vault vault : VaultManager.getVaults()) { + if (vault.getStorage().equals(event.getView().getTopInventory())) { + isVault = true; + break; + } + } + if (!isVault) return; + + final Player player = (Player) event.getWhoClicked(); + final ItemStack it = event.getClick() == ClickType.NUMBER_KEY ? player.getInventory().getItem(event.getHotbarButton()) : event.getCurrentItem(); + if (it == null) return; + for (String s : CONFIG.getSection("whitelisted-items").getRoutesAsStrings(false)) { + if (CONFIG.getString("whitelisted-items." + s + ".material") != null + && !it.getType().toString().equalsIgnoreCase(CONFIG.getString("whitelisted-items." + s + ".material")) + ) { + continue; + } + + if (CONFIG.getString("whitelisted-items." + s + ".custom-model-data") != null + && (it.getItemMeta() == null + || !it.getItemMeta().hasCustomModelData() + || !IntRange.valueOf(CONFIG.get("whitelisted-items." + s + ".custom-model-data")).contains(it.getItemMeta().getCustomModelData())) + ) { + continue; + } + + return; + } + + event.setCancelled(true); + MESSAGEUTILS.sendLang(player, "banned-item"); + } +} diff --git a/src/main/java/com/artillexstudios/axvaults/utils/IntRange.java b/src/main/java/com/artillexstudios/axvaults/utils/IntRange.java new file mode 100644 index 0000000..b713f44 --- /dev/null +++ b/src/main/java/com/artillexstudios/axvaults/utils/IntRange.java @@ -0,0 +1,110 @@ +package com.artillexstudios.axvaults.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class IntRange implements Cloneable { + private static final Random RANDOM = new Random(); + + private final int min; + private final int max; + + /** + * @param min Minimum value (inclusive) + * @param max Maximum value in range (inclusive) + */ + public IntRange(int min, int max) { + this.min = min; + this.max = max; + } + + /** + * @param value Minimum and maximum value (inclusive) + */ + public IntRange(int value) { + this.min = value; + this.max = value; + } + + public int getMin() { + return min; + } + + public int getMax() { + return max; + } + + public List getValues() { + List list = new ArrayList<>(); + + for (int i = min; i <= max; i++) { + list.add(i); + } + + return list; + } + + public boolean contains(int number) { + return number >= min && number <= max; + } + + /** + * @see IntRange#contains(int) + */ + @Deprecated + public boolean inRange(int number) { + return contains(number); + } + + public int next() { + if (min == max) { + return min; + } + + return RANDOM.nextInt(min, max + 1); + } + + public static IntRange parseIntRange(String string) throws NumberFormatException { + if (string == null) { + throw new NumberFormatException("Cannot parse null string"); + } + + String[] values = string.split("-"); + switch (values.length) { + case 1 -> { + int value = Integer.parseInt(values[0]); + return new IntRange(value, value); + } + case 2 -> { + return new IntRange(Integer.parseInt(values[0]), Integer.parseInt(values[1])); + } + default -> throw new NumberFormatException("Cannot parse invalid range format"); + } + } + + public static IntRange valueOf(Object object) throws NumberFormatException { + String s; + try { + s = (String) object; + } catch (ClassCastException e) { + return new IntRange((int) object); + } + + return parseIntRange(s); + } + + @Override + public String toString() { + return min + "-" + max; + } + + @Override + public IntRange clone() { + try { + return (IntRange) super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 2685a48..776f2c3 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -65,6 +65,15 @@ max-vault-amount: -1 # if enabled, the icon picker will not close after selecting an item selector-stay-open: false +# list of items that CAN be put in vaults +whitelisted-items: + "1": + material: "paper" + custom-model-data: 100-250 + "2": + material: "paper" + custom-model-data: 300-700 + # list of items that CAN'T be put in vaults # note: the name-contains string shouldn't include any color codes blacklisted-items: