diff --git a/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java b/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java index 0535240..a37d967 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java +++ b/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java @@ -23,6 +23,7 @@ import ca.tweetzy.core.database.DatabaseConnector; import ca.tweetzy.core.database.MySQLConnector; import ca.tweetzy.core.gui.GuiManager; import ca.tweetzy.core.utils.Metrics; +import ca.tweetzy.core.utils.TextUtils; import co.aikar.taskchain.BukkitTaskChainFactory; import co.aikar.taskchain.TaskChain; import co.aikar.taskchain.TaskChainFactory; @@ -138,6 +139,7 @@ public class AuctionHouse extends TweetyPlugin { // commands this.commandManager = new CommandManager(this); + this.commandManager.setSyntaxErrorMessage(TextUtils.formatText(getLocale().getMessage("commands.invalid_syntax").getMessageLines())); this.commandManager.addCommand(new CommandAuctionHouse()).addSubCommands( new CommandSell(), new CommandActive(), diff --git a/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java b/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java index d9885c5..1716b95 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java +++ b/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java @@ -4,13 +4,17 @@ import ca.tweetzy.auctionhouse.AuctionHouse; import ca.tweetzy.auctionhouse.api.events.AuctionEndEvent; import ca.tweetzy.auctionhouse.auction.AuctionItem; import ca.tweetzy.auctionhouse.auction.AuctionSaleType; +import ca.tweetzy.auctionhouse.helpers.ConfigurationItemHelper; import ca.tweetzy.auctionhouse.settings.Settings; import ca.tweetzy.core.compatibility.XMaterial; import ca.tweetzy.core.utils.PlayerUtils; import ca.tweetzy.core.utils.TextUtils; +import ca.tweetzy.core.utils.items.ItemUtils; +import ca.tweetzy.core.utils.nms.NBTEditor; import org.apache.commons.lang.WordUtils; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.util.io.BukkitObjectInputStream; @@ -223,11 +227,23 @@ public class AuctionAPI { } } + /** + * Get the name of an item stack + * + * @param stack is the item you want to get name from + * @return the item name + */ public String getItemName(ItemStack stack) { Objects.requireNonNull(stack, "Item stack cannot be null when getting name"); return stack.getItemMeta().hasDisplayName() ? stack.getItemMeta().getDisplayName() : TextUtils.formatText("&f" + WordUtils.capitalize(stack.getType().name().toLowerCase().replace("_", " "))); } + /** + * Used to get the lore from an item stack + * + * @param stack is the item being checked + * @return the item lore if available + */ public List getItemLore(ItemStack stack) { List lore = new ArrayList<>(); Objects.requireNonNull(stack, "Item stack cannot be null when getting lore"); @@ -239,23 +255,50 @@ public class AuctionAPI { return lore; } + /** + * Used to match patterns + * + * @param pattern is the keyword being searched for + * @param sentence is the sentence you're checking + * @return whether the keyword is found + */ public boolean match(String pattern, String sentence) { Pattern patt = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); Matcher matcher = patt.matcher(sentence); return matcher.find(); } + /** + * Used to format numbers with decimals and commas + * + * @param number is the number you want to format + * @return the formatted number string + */ public String formatNumber(double number) { String formatted = String.format("%,.2f", number); return Settings.USE_ALTERNATE_CURRENCY_FORMAT.getBoolean() ? replaceLast(formatted.replace(",", "."), ".", ",") : formatted; } + /** + * Used to replace the last portion of a string + * + * @param string is the string being edited + * @param substring is the to replace word/phrase + * @param replacement is the keyword(s) you're replacing the old substring with + * @return the updated string + */ private String replaceLast(String string, String substring, String replacement) { int index = string.lastIndexOf(substring); if (index == -1) return string; return string.substring(0, index) + replacement + string.substring(index + substring.length()); } + /** + * Used to get command flags (ex. -h, -f, -t, etc) + * + * @param args is the arguments passed when running a command + * @return any command flags if any + */ public List getCommandFlags(String... args) { List flags = new ArrayList<>(); for (String arg : args) { @@ -266,6 +309,100 @@ public class AuctionAPI { return flags; } + /** + * Get the total amount of an item in the player's inventory + * + * @param player is the player being checked + * @param stack is the item you want to find + * @return the total count of the item(s) + */ + public int getItemCountInPlayerInventory(Player player, ItemStack stack) { + int total = 0; + if (stack.getType() == XMaterial.PLAYER_HEAD.parseMaterial()) { + for (ItemStack item : player.getInventory().getContents()) { + if (item == null || item.getType() != XMaterial.PLAYER_HEAD.parseMaterial()) continue; + if (NBTEditor.getTexture(item).equals(NBTEditor.getTexture(stack))) total += item.getAmount(); + } + } else { + for (ItemStack item : player.getInventory().getContents()) { + if (item == null || !item.isSimilar(stack)) continue; + total += item.getAmount(); + } + } + return total; + } + + public List getSimilarItemsFromInventory(Player player, ItemStack stack) { + List items = new ArrayList<>(); + for (int i = 0; i < player.getInventory().getSize(); i++) { + ItemStack item = player.getInventory().getItem(i); + if (item == null) continue; + if (stack.getType() == XMaterial.PLAYER_HEAD.parseMaterial() && item.getType() == XMaterial.PLAYER_HEAD.parseMaterial()) { + if (!NBTEditor.getTexture(item).equals(NBTEditor.getTexture(stack))) continue; + } else { + if (!item.isSimilar(stack)) continue; + } + + items.add(item); + } + + return items; + } + + /** + * Removes a set amount of a specific item from the player inventory + * + * @param player is the player you want to remove the item from + * @param stack is the item that you want to remove + * @param amount is the amount of items you want to remove. + */ + public void removeSpecificItemQuantityFromPlayer(Player player, ItemStack stack, int amount) { + int i = amount; + for (int j = 0; j < player.getInventory().getSize(); j++) { + ItemStack item = player.getInventory().getItem(j); + if (item == null) continue; + if (stack.getType() == XMaterial.PLAYER_HEAD.parseMaterial() && item.getType() == XMaterial.PLAYER_HEAD.parseMaterial()) { + if (!NBTEditor.getTexture(item).equals(NBTEditor.getTexture(stack))) continue; + } else { + if (!item.isSimilar(stack)) continue; + + } + + if (i >= item.getAmount()) { + player.getInventory().clear(j); + i -= item.getAmount(); + } else if (i > 0) { + item.setAmount(item.getAmount() - i); + i = 0; + } else { + break; + } + } + } + + public ItemStack createBundledItem(ItemStack baseItem, ItemStack... items) { + Objects.requireNonNull(items, "Cannot create a bundled item with no items"); + ItemStack item = ConfigurationItemHelper.createConfigurationItem(Settings.ITEM_BUNDLE_ITEM.getString(), Settings.ITEM_BUNDLE_NAME.getString(), Settings.ITEM_BUNDLE_LORE.getStringList(), new HashMap(){{ + put("%item_name%", getItemName(baseItem)); + }}); + + int total = items.length; + item = NBTEditor.set(item, total, "AuctionBundleItem"); + item = NBTEditor.set(item, UUID.randomUUID().toString(), "AuctionBundleItemUUID-" + UUID.randomUUID().toString()); + + for (int i = 0; i < total; i++) { + item = NBTEditor.set(item, serializeItem(items[i]), "AuctionBundleItem-" + i); + } + + ItemUtils.addGlow(item); + return item; + } + + /** + * Used to end an auction + * + * @param item is the auction item you want to end + */ public void endAuction(AuctionItem item) { // check if the auction item owner is the same as the highest bidder if (item.getOwner().equals(item.getHighestBidder())) { diff --git a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java index bd678ad..c0523db 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java +++ b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java @@ -103,7 +103,7 @@ public class AuctionItem implements Serializable { lore.addAll(Settings.AUCTION_PURCHASE_CONTROL_HEADER.getStringList().stream().map(TextUtils::formatText).collect(Collectors.toList())); lore.addAll(this.bidStartPrice <= 0 || this.bidIncPrice <= 0 ? Settings.AUCTION_PURCHASE_CONTROLS_BID_OFF.getStringList().stream().map(TextUtils::formatText).collect(Collectors.toList()) : Settings.AUCTION_PURCHASE_CONTROLS_BID_ON.getStringList().stream().map(TextUtils::formatText).collect(Collectors.toList())); - if ((ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11) && itemStack.getType().name().contains("SHULKER_BOX")) || (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_14) && itemStack.getType() == XMaterial.SHULKER_BOX.parseMaterial() || itemStack.getType() == XMaterial.BARREL.parseMaterial())) { + if (NBTEditor.contains(itemStack, "AuctionBundleItem") || (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11) && itemStack.getType().name().contains("SHULKER_BOX")) || (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_14) && itemStack.getType() == XMaterial.SHULKER_BOX.parseMaterial() || itemStack.getType() == XMaterial.BARREL.parseMaterial())) { lore.addAll(Settings.AUCTION_PURCHASE_CONTROLS_INSPECTION.getStringList().stream().map(TextUtils::formatText).collect(Collectors.toList())); } diff --git a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandAdmin.java b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandAdmin.java index d018826..4264d3f 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandAdmin.java +++ b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandAdmin.java @@ -2,9 +2,14 @@ package ca.tweetzy.auctionhouse.commands; import ca.tweetzy.auctionhouse.AuctionHouse; import ca.tweetzy.auctionhouse.auction.AuctionItem; +import ca.tweetzy.auctionhouse.helpers.PlayerHelper; import ca.tweetzy.auctionhouse.settings.Settings; import ca.tweetzy.core.commands.AbstractCommand; +import ca.tweetzy.core.utils.PlayerUtils; +import ca.tweetzy.core.utils.items.ItemUtils; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.Arrays; import java.util.List; @@ -41,6 +46,13 @@ public class CommandAdmin extends AbstractCommand { case "cleanunknownusers": // Don't tell ppl that this exists just yet AuctionHouse.getInstance().getAuctionItemManager().removeUnknownOwnerItems(); + break; + case "stacksize": + Player player = (Player) sender; + ItemStack item = PlayerHelper.getHeldItem(player); + ItemUtils.setMaxStack(item, 127); + item.setAmount(127); + break; } diff --git a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java index 017093e..f99b8ad 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java +++ b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java @@ -14,6 +14,7 @@ import ca.tweetzy.core.compatibility.CompatibleHand; import ca.tweetzy.core.compatibility.XMaterial; import ca.tweetzy.core.utils.NumberUtils; import ca.tweetzy.core.utils.PlayerUtils; +import ca.tweetzy.core.utils.nms.NBTEditor; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -44,6 +45,7 @@ public class CommandSell extends AbstractCommand { Player player = (Player) sender; AuctionPlayer auctionPlayer = AuctionHouse.getInstance().getAuctionPlayerManager().getPlayer(player.getUniqueId()); + ItemStack originalItem = PlayerHelper.getHeldItem(player).clone(); ItemStack itemToSell = PlayerHelper.getHeldItem(player).clone(); if (itemToSell.getType() == XMaterial.AIR.parseMaterial()) { @@ -104,6 +106,8 @@ public class CommandSell extends AbstractCommand { List commandFlags = AuctionAPI.getInstance().getCommandFlags(args); List listingPrices = new ArrayList<>(); + boolean isUsingBundle = false; + for (String arg : args) { if (NumberUtils.isDouble(arg)) { listingPrices.add(Double.parseDouble(arg)); @@ -166,6 +170,16 @@ public class CommandSell extends AbstractCommand { return ReturnType.FAILURE; } + if (Settings.ALLOW_ITEM_BUNDLES.getBoolean() && commandFlags.contains("-b")) { + if (NBTEditor.contains(itemToSell, "AuctionBundleItem")) { + AuctionHouse.getInstance().getLocale().getMessage("general.cannotsellbundleditem").sendPrefixedMessage(player); + return ReturnType.FAILURE; + } + + itemToSell = AuctionAPI.getInstance().createBundledItem(itemToSell, AuctionAPI.getInstance().getSimilarItemsFromInventory(player, itemToSell).toArray(new ItemStack[0])); + isUsingBundle = true; + } + AuctionItem auctionItem = new AuctionItem( player.getUniqueId(), player.getUniqueId(), @@ -185,15 +199,21 @@ public class CommandSell extends AbstractCommand { if (startEvent.isCancelled()) return ReturnType.FAILURE; AuctionHouse.getInstance().getAuctionItemManager().addItem(auctionItem); - PlayerUtils.takeActiveItem(player, CompatibleHand.MAIN_HAND, itemToSell.getAmount()); + + if (isUsingBundle) { + AuctionAPI.getInstance().removeSpecificItemQuantityFromPlayer(player, originalItem, AuctionAPI.getInstance().getItemCountInPlayerInventory(player, originalItem)); + } else { + PlayerUtils.takeActiveItem(player, CompatibleHand.MAIN_HAND, itemToSell.getAmount()); + } + SoundManager.getInstance().playSound(player, Settings.SOUNDS_LISTED_ITEM_ON_AUCTION_HOUSE.getString(), 1.0F, 1.0F); AuctionHouse.getInstance().getLocale().getMessage(isBiddingItem ? "auction.listed.withbid" : "auction.listed.nobid") .processPlaceholder("amount", itemToSell.getAmount()) .processPlaceholder("item", AuctionAPI.getInstance().getItemName(itemToSell)) .processPlaceholder("base_price", listingPrices.get(0) <= -1 ? AuctionHouse.getInstance().getLocale().getMessage("auction.biditemwithdisabledbuynow").getMessage() : AuctionAPI.getInstance().formatNumber(listingPrices.get(0))) - .processPlaceholder("start_price", AuctionAPI.getInstance().formatNumber(listingPrices.get(1))) - .processPlaceholder("increment_price", AuctionAPI.getInstance().formatNumber(listingPrices.get(2))) + .processPlaceholder("start_price", isBiddingItem ? AuctionAPI.getInstance().formatNumber(listingPrices.get(1)) : 0) + .processPlaceholder("increment_price", isBiddingItem ? AuctionAPI.getInstance().formatNumber(listingPrices.get(2)) : 0) .sendPrefixedMessage(player); if (Settings.BROADCAST_AUCTION_LIST.getBoolean()) { diff --git a/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java b/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java index 342a23d..a4892ea 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java +++ b/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java @@ -13,6 +13,7 @@ import ca.tweetzy.core.gui.Gui; import ca.tweetzy.core.gui.events.GuiClickEvent; import ca.tweetzy.core.utils.TextUtils; import ca.tweetzy.core.utils.items.TItemBuilder; +import ca.tweetzy.core.utils.nms.NBTEditor; import org.bukkit.Bukkit; import org.bukkit.block.ShulkerBox; import org.bukkit.event.inventory.ClickType; @@ -183,8 +184,15 @@ public class GUIAuctionHouse extends Gui { private void handleContainerInspect(GuiClickEvent e) { if (!ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) return; + ItemStack clicked = e.clickedItem; + + if (NBTEditor.contains(clicked, "AuctionBundleItem")) { + cleanup(); + e.manager.showGUI(e.player, new GUIContainerInspect(e.clickedItem)); + return; + } + if (e.player.isOp() || e.player.hasPermission("auctionhouse.admin") || e.player.hasPermission("auctionhouse.inspectshulker")) { - ItemStack clicked = e.clickedItem; if (!(clicked.getItemMeta() instanceof BlockStateMeta)) return; BlockStateMeta meta = (BlockStateMeta) clicked.getItemMeta(); diff --git a/src/main/java/ca/tweetzy/auctionhouse/guis/GUIContainerInspect.java b/src/main/java/ca/tweetzy/auctionhouse/guis/GUIContainerInspect.java index dd04860..484a36a 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/guis/GUIContainerInspect.java +++ b/src/main/java/ca/tweetzy/auctionhouse/guis/GUIContainerInspect.java @@ -1,14 +1,23 @@ package ca.tweetzy.auctionhouse.guis; import ca.tweetzy.auctionhouse.AuctionHouse; +import ca.tweetzy.auctionhouse.api.AuctionAPI; import ca.tweetzy.auctionhouse.helpers.ConfigurationItemHelper; import ca.tweetzy.auctionhouse.settings.Settings; import ca.tweetzy.core.gui.Gui; import ca.tweetzy.core.utils.TextUtils; +import ca.tweetzy.core.utils.items.TItemBuilder; +import ca.tweetzy.core.utils.nms.NBTEditor; import org.bukkit.block.ShulkerBox; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BlockStateMeta; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + /** * The current file has been created by Kiran Hart * Date Created: April 14 2021 @@ -18,36 +27,57 @@ import org.bukkit.inventory.meta.BlockStateMeta; public class GUIContainerInspect extends Gui { final int[] fillSlots = {0, 1, 2, 3, 4, 5, 6, 7, 8, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 50, 51, 52, 53}; - final ItemStack shulker; + final ItemStack container; + List items; /** * Used to inspect a shulker box from it's item stack. * - * @param shulker is the shulker box + * @param container is the shulker box */ - public GUIContainerInspect(ItemStack shulker) { - this.shulker = shulker; - setTitle(TextUtils.formatText(Settings.GUI_SHULKER_INSPECT_TITLE.getString())); - setDefaultItem(Settings.GUI_SHULKER_INSPECT_BG_ITEM.getMaterial().parseItem()); + public GUIContainerInspect(ItemStack container) { + this.container = container; + setTitle(TextUtils.formatText(Settings.GUI_INSPECT_TITLE.getString())); + setDefaultItem(Settings.GUI_INSPECT_BG_ITEM.getMaterial().parseItem()); setUseLockedCells(false); setAcceptsItems(false); setAllowDrops(false); setRows(6); - draw(); + if (NBTEditor.contains(this.container, "AuctionBundleItem")) { + List items = new ArrayList<>(); + + for (int i = 0; i < NBTEditor.getInt(this.container, "AuctionBundleItem"); i++) { + items.add(AuctionAPI.getInstance().deserializeItem(NBTEditor.getByteArray(this.container, "AuctionBundleItem-" + i))); + } + + this.items = items; + } + + if (this.container.getType().name().contains("SHULKER_BOX")) { + BlockStateMeta meta = (BlockStateMeta) this.container.getItemMeta(); + ShulkerBox skulkerBox = (ShulkerBox) meta.getBlockState(); + this.items = Arrays.asList(skulkerBox.getInventory().getContents()); + } + + draw(); setOnClose(close -> close.manager.showGUI(close.player, new GUIAuctionHouse(AuctionHouse.getInstance().getAuctionPlayerManager().getPlayer(close.player.getUniqueId())))); } private void draw() { reset(); + pages = (int) Math.max(1, Math.ceil(this.items.size() / (double) 27L)); for (int i : fillSlots) setItem(i, getDefaultItem()); + + setPrevPage(5, 3, new TItemBuilder(Objects.requireNonNull(Settings.GUI_BACK_BTN_ITEM.getMaterial().parseMaterial())).setName(Settings.GUI_BACK_BTN_NAME.getString()).setLore(Settings.GUI_BACK_BTN_LORE.getStringList()).toItemStack()); setButton(5, 4, ConfigurationItemHelper.createConfigurationItem(Settings.GUI_CLOSE_BTN_ITEM.getString(), Settings.GUI_CLOSE_BTN_NAME.getString(), Settings.GUI_CLOSE_BTN_LORE.getStringList(), null), e -> e.manager.showGUI(e.player, new GUIAuctionHouse(AuctionHouse.getInstance().getAuctionPlayerManager().getPlayer(e.player.getUniqueId())))); - BlockStateMeta meta = (BlockStateMeta) this.shulker.getItemMeta(); - ShulkerBox skulkerBox = (ShulkerBox) meta.getBlockState(); + setNextPage(5, 5, new TItemBuilder(Objects.requireNonNull(Settings.GUI_NEXT_BTN_ITEM.getMaterial().parseMaterial())).setName(Settings.GUI_NEXT_BTN_NAME.getString()).setLore(Settings.GUI_NEXT_BTN_LORE.getStringList()).toItemStack()); + setOnPage(e -> draw()); int slot = 9; - for (ItemStack item : skulkerBox.getInventory().getContents()) { + List data = this.items.stream().skip((page - 1) * 27L).limit(27L).collect(Collectors.toList()); + for (ItemStack item : data) { setItem(slot++, item); } } diff --git a/src/main/java/ca/tweetzy/auctionhouse/listeners/PlayerListeners.java b/src/main/java/ca/tweetzy/auctionhouse/listeners/PlayerListeners.java index caf0363..19bbebb 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/listeners/PlayerListeners.java +++ b/src/main/java/ca/tweetzy/auctionhouse/listeners/PlayerListeners.java @@ -1,15 +1,28 @@ package ca.tweetzy.auctionhouse.listeners; import ca.tweetzy.auctionhouse.AuctionHouse; +import ca.tweetzy.auctionhouse.api.AuctionAPI; import ca.tweetzy.auctionhouse.api.UpdateChecker; import ca.tweetzy.auctionhouse.auction.AuctionPlayer; +import ca.tweetzy.auctionhouse.helpers.PlayerHelper; +import ca.tweetzy.core.compatibility.CompatibleHand; +import ca.tweetzy.core.compatibility.ServerVersion; +import ca.tweetzy.core.compatibility.XMaterial; +import ca.tweetzy.core.utils.PlayerUtils; import ca.tweetzy.core.utils.TextUtils; +import ca.tweetzy.core.utils.nms.NBTEditor; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; /** * The current file has been created by Kiran Hart @@ -38,4 +51,34 @@ public class PlayerListeners implements Listener { AuctionHouse.getInstance().getAuctionPlayerManager().getCooldowns().remove(player.getUniqueId()); AuctionHouse.getInstance().getLogger().info("Removing Auction Player and Cooldown instances for user: " + player.getName()); } + + @EventHandler + public void onBundleClick(PlayerInteractEvent e) { + Player player = e.getPlayer(); + ItemStack heldItem = PlayerHelper.getHeldItem(player); + + if (heldItem == null || (e.getAction() != Action.RIGHT_CLICK_AIR && e.getAction() != Action.RIGHT_CLICK_BLOCK)) return; + if (heldItem.getType() == XMaterial.AIR.parseMaterial()) return; + if (!NBTEditor.contains(heldItem, "AuctionBundleItem")) return; + e.setCancelled(true); + + List items = new ArrayList<>(); + + for (int i = 0; i < NBTEditor.getInt(heldItem, "AuctionBundleItem"); i++) { + items.add(AuctionAPI.getInstance().deserializeItem(NBTEditor.getByteArray(heldItem, "AuctionBundleItem-" + i))); + } + + // TODO FIX THE TWEETY CORE TAKE ACTIVE ITEM METHOD, IN THE MEAN TIME DO IT LIKE THIS + if (heldItem.getAmount() >= 2) { + heldItem.setAmount(heldItem.getAmount() - 1); + } else { + if (ServerVersion.isServerVersionAbove(ServerVersion.V1_8)) { + player.getInventory().setItemInMainHand(XMaterial.AIR.parseItem()); + } else { + player.getInventory().setItemInHand(XMaterial.AIR.parseItem()); + } + } + + PlayerUtils.giveItem(player, items); + } } diff --git a/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java b/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java index 9faaeac..0e78138 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java +++ b/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java @@ -63,6 +63,14 @@ public class Settings { public static final ConfigSetting DATE_FORMAT = new ConfigSetting(config, "auction setting.date format", "MMM dd, yyyy hh:mm aa", "You can learn more about date formats by googling SimpleDateFormat patterns or visiting this link", "https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html"); public static final ConfigSetting ALLOW_PLAYERS_TO_ACCEPT_BID = new ConfigSetting(config, "auction setting.allow players to accept bid", true, "If true, players can right click a biddable item inside their active listings menu to accept the current bid"); + public static final ConfigSetting ALLOW_ITEM_BUNDLES = new ConfigSetting(config, "auction setting.bundles.enabled", true, "If true, players can use -b in the sell command to bundle all similar items into a single item."); + public static final ConfigSetting ITEM_BUNDLE_ITEM = new ConfigSetting(config, "auction setting.bundles.item", XMaterial.GOLD_BLOCK.name()); + public static final ConfigSetting ITEM_BUNDLE_NAME = new ConfigSetting(config, "auction setting.bundles.name", "%item_name% &7Bundle"); + public static final ConfigSetting ITEM_BUNDLE_LORE = new ConfigSetting(config, "auction setting.bundles.lore", Arrays.asList( + "&7This is a bundle item, it contains", + "&7multiple items that can be unboxed." + )); + public static final ConfigSetting CLICKS_NON_BID_ITEM_PURCHASE = new ConfigSetting(config, "auction setting.clicks.non bid item purchase", "LEFT", "Valid Click Types", "LEFT", @@ -447,8 +455,8 @@ public class Settings { /* =============================== * INSPECTION GUI * ===============================*/ - public static final ConfigSetting GUI_SHULKER_INSPECT_TITLE = new ConfigSetting(config, "gui.shulker inspect.title", "&7&LInspecting Shulker Box"); - public static final ConfigSetting GUI_SHULKER_INSPECT_BG_ITEM = new ConfigSetting(config, "gui.shulker inspect.bg item", XMaterial.BLACK_STAINED_GLASS_PANE.name()); + public static final ConfigSetting GUI_INSPECT_TITLE = new ConfigSetting(config, "gui.inspect.title", "&7&LInspecting Container"); + public static final ConfigSetting GUI_INSPECT_BG_ITEM = new ConfigSetting(config, "gui.inspect.bg item", XMaterial.BLACK_STAINED_GLASS_PANE.name()); /* =============================== @@ -502,7 +510,7 @@ public class Settings { "&eLeft-Click&f: &bBuy Now" ), "This will be appended at the end of the lore", "If the auction item is not using a bid, this will show"); - public static final ConfigSetting AUCTION_PURCHASE_CONTROLS_INSPECTION = new ConfigSetting(config, "auction items.controls.inspection", Collections.singletonList("&eShift Right-Click to inspect"), "This will only be added to the control lore if the item can be inspected (skulker box)"); + public static final ConfigSetting AUCTION_PURCHASE_CONTROLS_INSPECTION = new ConfigSetting(config, "auction items.controls.inspection", Collections.singletonList("&eShift Right-Click to inspect"), "This will only be added to the control lore if the item can be inspected (skulker box/bundled item)"); public static final ConfigSetting AUCTION_PURCHASE_CONTROLS_ACCEPT_BID = new ConfigSetting(config, "auction items.controls.accept bid", Collections.singletonList("&eRight-Click to accept the current bid"), "This will only show on items within the active listings menu on biddable items."); public static final ConfigSetting AUCTION_PURCHASE_CONTROLS_BUY_NOW_OFF_FOR_BID = new ConfigSetting(config, "auction items.controls.buy now is off for bid", "&cN/A", "If they player sets the buy now price to -1 on a bid item, it will mean make the item", "a bid item, but users will not be able to use the buy now option on the item."); diff --git a/src/main/resources/en_US.lang b/src/main/resources/en_US.lang index 30101f7..67f2d1f 100644 --- a/src/main/resources/en_US.lang +++ b/src/main/resources/en_US.lang @@ -15,6 +15,7 @@ general: buynowdisabledonitem: "&cBuy now is disabled on this item." endedallauctions: "&cYou force ended all active auctions" relisteditems: "&aYou relisted all expired items!" + cannotsellbundleditem: "&cYou cannot sell a bundled item as a bundle." pricing: minbaseprice: "&cThe minimum base price must be &a$%price%" @@ -68,6 +69,7 @@ auction: biditemwithdisabledbuynow: "&cN/A" commands: + invalid_syntax: "&7The valid syntax is: &6%syntax%&7." syntax: active: "active" auctionhouse: "/ah"