diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/TeamManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/TeamManager.java index a2f39589a..d0756fb1c 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/TeamManager.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/TeamManager.java @@ -197,42 +197,6 @@ public TeamKey getTeamKeyByName(String teamName) { .orElse(null); } - @Deprecated(forRemoval = true) - public int getTeamUpgradeLevel(String teamName, String upgradeKey) { - TeamKey teamKey = getTeamKeyByName(teamName); - return teamKey != null ? getTeamUpgradeLevel(teamKey, upgradeKey) : 0; - } - - @Deprecated(forRemoval = true) - public void setTeamUpgradeLevel(String teamName, String upgradeKey, int level) { - TeamKey teamKey = getTeamKeyByName(teamName); - if (teamKey != null) setTeamUpgradeLevel(teamKey, upgradeKey, level); - } - - @Deprecated(forRemoval = true) - public List getTeamTraps(String teamName) { - TeamKey teamKey = getTeamKeyByName(teamName); - return teamKey != null ? getTeamTraps(teamKey) : new ArrayList<>(); - } - - @Deprecated(forRemoval = true) - public void addTeamTrap(String teamName, String trapKey) { - TeamKey teamKey = getTeamKeyByName(teamName); - if (teamKey != null) addTeamTrap(teamKey, trapKey); - } - - @Deprecated(forRemoval = true) - public void removeTeamTrap(String teamName, String trapKey) { - TeamKey teamKey = getTeamKeyByName(teamName); - if (teamKey != null) removeTeamTrap(teamKey, trapKey); - } - - @Deprecated(forRemoval = true) - public List getPlayersOnTeam(String teamName) { - TeamKey teamKey = getTeamKeyByName(teamName); - return teamKey != null ? getPlayersOnTeam(teamKey) : new ArrayList<>(); - } - public void recordBedDestroyed(TeamKey teamKey) { teamBedStatus.put(teamKey, false); Logger.info("Bed destroyed for team: {}", teamKey.getName()); diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java index 2935c3433..e8ef366e9 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java @@ -10,6 +10,7 @@ import net.minestom.server.entity.Player; import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.InventoryType; +import net.minestom.server.inventory.click.Click; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; @@ -25,433 +26,513 @@ import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; import net.swofty.type.generic.gui.inventory.item.GUIItem; import net.swofty.type.generic.user.HypixelPlayer; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import static net.kyori.adventure.text.format.TextDecoration.ITALIC; import static net.swofty.type.bedwarsgame.util.ComponentManipulator.noItalic; public class GUIItemShop extends HypixelInventoryGUI { - private static final ItemStack QUICK_BUY = ItemStack.builder(Material.NETHER_STAR) - .customName(Component.text("Quick Buy").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.AQUA)) - .build(); - - private static final ItemStack BLOCKS = ItemStack.builder(Material.TERRACOTTA) - .customName(Component.text("Blocks").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - - private static final ItemStack WEAPONS = ItemStack.builder(Material.GOLDEN_SWORD) - .customName(Component.text("Weapons").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - - private static final ItemStack ARMOR = ItemStack.builder(Material.CHAINMAIL_BOOTS) - .customName(Component.text("Armor").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - - private static final ItemStack TOOLS = ItemStack.builder(Material.STONE_PICKAXE) - .customName(Component.text("Tools").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - - private static final ItemStack BOWS = ItemStack.builder(Material.BOW) - .customName(Component.text("Bows & Arrows").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - - private static final ItemStack POTIONS = ItemStack.builder(Material.BREWING_STAND) - .customName(Component.text("Potions").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - - private static final ItemStack UTILITY = ItemStack.builder(Material.TNT) - .customName(Component.text("Utility").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - - private static final ItemStack ROTATING_ITEMS = ItemStack.builder(Material.REDSTONE_TORCH) - .customName(Component.text("Rotating Items").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) - .build(); - private static final List> TIERED_ITEM_GROUPS = List.of( - List.of(Material.LEATHER_BOOTS, Material.GOLDEN_BOOTS, Material.CHAINMAIL_BOOTS, Material.IRON_BOOTS, Material.DIAMOND_BOOTS, Material.NETHERITE_BOOTS) - ); - private final ShopManager shopService = TypeBedWarsGameLoader.shopManager; - private int currentPage = 0; - private final Game game; - - public GUIItemShop(Game game) { - super("Item Shop", InventoryType.CHEST_6_ROW); - this.game = game; - } - - @Override - public boolean allowHotkeying() { - return true; - } - - @Override - public void onOpen(InventoryGUIOpenEvent e) { - updateGUI(e.player()); - } - - @Override - public void onBottomClick(InventoryPreClickEvent e) { - e.setCancelled(true); - } - - private void updateGUI(HypixelPlayer p) { - BedWarsPlayer player = (BedWarsPlayer) p; - - fill(ItemStackCreator.createNamedItemStack(Material.BLACK_STAINED_GLASS_PANE), 9, 17); - set(currentPage + 9, ItemStackCreator.createNamedItemStack(Material.GREEN_STAINED_GLASS_PANE)); - set(new GUIClickableItem(0) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 0; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(QUICK_BUY, currentPage, 0); - } - }); - - set(new GUIClickableItem(1) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 1; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(BLOCKS, currentPage, 1); - } - }); - - set(new GUIClickableItem(2) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 2; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(WEAPONS, currentPage, 2); - } - }); - - set(new GUIClickableItem(3) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 3; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(ARMOR, currentPage, 3); - } - }); - - set(new GUIClickableItem(4) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 4; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(TOOLS, currentPage, 4); - } - }); - - set(new GUIClickableItem(5) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 5; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(BOWS, currentPage, 5); - } - }); - - set(new GUIClickableItem(6) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 6; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(POTIONS, currentPage, 6); - } - }); - - set(new GUIClickableItem(7) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 7; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(UTILITY, currentPage, 7); - } - }); - - set(new GUIClickableItem(8) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 8; - updateGUI(player); - playClickSound(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(ROTATING_ITEMS, currentPage, 8); - } - }); - - populateShopItems(); - updateItemStacks(getInventory(), getPlayer()); - } - - private ItemStack.Builder convertToClickToView(ItemStack itemStack, int currentPage, int index) { - ItemStack.Builder builder = itemStack.builder(); - - if (currentPage != index) { - return builder.lore(noItalic(Component.text("Click to view!").color(NamedTextColor.YELLOW))); - } - - return builder; - } - - private void populateShopItems() { - int[] shopSlots = { - 19, 20, 21, 22, 23, 24, 25, - 28, 29, 30, 31, 32, 33, 34, - 37, 38, 39, 40, 41, 42, 43 - }; - - for (int i = 0; i < shopSlots.length; i++) { - int slot = shopSlots[i]; - int index = i; - - if (currentPage == 8) { - set(new GUIItem(49) { - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack("§aWhat are Rotating Items?", Material.PAPER, 1, List.of( - "§7Rotating Items are items that are", - "§7only available for a limited amount of", - "§7time. They may disappear and be", - "§7replaced with another temporary", - "§7item at any time." - )); - } - }); - } - - set(new GUIClickableItem(slot) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer p) { - BedWarsPlayer player = (BedWarsPlayer) p; - ShopItem shopItem; - if (currentPage == 0) { - shopItem = shopService.getQuickShopItem(player, index); - } else { - shopItem = shopService.getShopItem(currentPage, index); - } - - if (shopItem == null) return; - - if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { - int nextLevel = upgradeableShopItem.getNextLevel(player); - if (nextLevel >= upgradeableShopItem.getTiers().size()) { - player.sendMessage(noItalic(Component.text("You have already purchased the maximum tier of this item!").color(NamedTextColor.RED))); - return; - } - UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); - if (!hasPlayerEnoughCurrencyForTier(player, nextTier)) { - int owned = Arrays.stream(player.getInventory().getItemStacks()) - .filter(s -> s.material() == nextTier.currency().getMaterial()) - .mapToInt(ItemStack::amount) - .sum(); - int needed = nextTier.price().apply(game.getBedwarsGameType()) - owned; - player.sendMessage(noItalic(Component.text("You don't have enough " + nextTier.currency().getName() + "! Need " + needed + " more!").color(NamedTextColor.RED))); - return; - } - upgradeableShopItem.handlePurchase(player, game.getBedwarsGameType()); - player.sendMessage(noItalic(Component.text("You purchased " + nextTier.name() + "!").color(NamedTextColor.GREEN))); - playBuySound(player); - updateGUI(player); - return; - } - - if (!hasPlayerEnoughCurrency(player, shopItem)) { - player.sendMessage(noItalic(Component.text("You don't have enough " + shopItem.getCurrency().getName() + "!").color(NamedTextColor.RED))); - return; - } - if (!shopItem.isOwned(player)) { - player.sendMessage(noItalic(Component.text("You cannot buy this item!").color(NamedTextColor.RED))); - return; - } - if (hasBetterItem(player, shopItem.getDisplay().material())) { - player.sendMessage(noItalic(Component.text("You already have a better item!").color(NamedTextColor.RED))); - return; - } - shopItem.handlePurchase(player, game.getBedwarsGameType()); - playBuySound(player); - updateGUI(player); - } - - @Override - public ItemStack.Builder getItem(HypixelPlayer p) { - BedWarsPlayer player = (BedWarsPlayer) p; - ShopItem shopItem; - if (currentPage == 0) { - shopItem = shopService.getQuickShopItem(player, index); - } else { - shopItem = shopService.getShopItem(currentPage, index); - } - - if (shopItem == null) { - return ItemStack.builder(Material.AIR); - } - - if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { - int nextLevel = upgradeableShopItem.getNextLevel(player); - UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); - boolean hasEnough = hasPlayerEnoughCurrencyForTier(player, nextTier); - - List lore = new ArrayList<>(); - lore.add( - "§7Cost: " + nextTier.currency().getColor() + nextTier.price().apply(game.getBedwarsGameType()) + " " + nextTier.currency().getName() - ); - lore.add(" "); - if (upgradeableShopItem.getDescription() != null && !upgradeableShopItem.getDescription().isEmpty()) { - lore.addAll(StringUtility.splitByNewLine(upgradeableShopItem.getDescription(), "§7")); - lore.add(" "); - } - if (nextLevel >= upgradeableShopItem.getTiers().size()) { - lore.add("§cYou have already purchased the maximum tier of this item!"); - } else if (hasEnough) { - lore.add("§eClick to buy!"); - } else { - lore.add("§cYou don't have enough " + nextTier.currency().getName() + "!"); - } - return ItemStackCreator.getStack( - hasEnough ? "§a" + nextTier.name() : "§c" + nextTier.name(), - nextTier.material(), - 1, - lore - ); - } - - boolean hasEnough = hasPlayerEnoughCurrency(player, shopItem); - List lore = new ArrayList<>(); - lore.add( - "§7Cost: " + shopItem.getCurrency().getColor() + shopItem.getPrice().apply(game.getBedwarsGameType()) + " " + shopItem.getCurrency().getName() - ); - lore.add(" "); - if (shopItem.getDescription() != null && !shopItem.getDescription().isEmpty()) { - lore.addAll(StringUtility.splitByNewLine(shopItem.getDescription(), "§7")); - lore.add(" "); - } - - if (!hasEnough) { - lore.add("§cYou don't have enough " + shopItem.getCurrency().getName() + "!"); - } else if (!shopItem.isOwned(player)) { - lore.add("§aUNLOCKED"); - } else if (hasBetterItem(player, shopItem.getDisplay().material())) { - lore.add("§cYou already have a better item!"); - } else { - lore.add("§eClick to buy!"); - } - - return ItemStackCreator.updateLore( - shopItem.getDisplay().builder().set(DataComponents.CUSTOM_NAME, Component.text((hasEnough && shopItem.isOwned(player)) ? "§a" + shopItem.getName() : "§c" + shopItem.getName())), - lore - ); - } - }); - } - } - - private boolean hasPlayerEnoughCurrency(HypixelPlayer player, ShopItem shopItem) { - int requiredAmount = shopItem.getPrice().apply(game.getBedwarsGameType()); - Material currencyMaterial = shopItem.getCurrency().getMaterial(); - - int playerAmount = 0; - for (ItemStack item : player.getInventory().getItemStacks()) { - if (item.material() == currencyMaterial) { - playerAmount += item.amount(); - } - } - - return playerAmount >= requiredAmount; - } - - private boolean hasPlayerEnoughCurrencyForTier(HypixelPlayer player, UpgradeableItemTier tier) { - int required = tier.price().apply(game.getBedwarsGameType()); - Material cur = tier.currency().getMaterial(); - int have = 0; - for (ItemStack it : player.getInventory().getItemStacks()) { - if (it.material() == cur) have += it.amount(); - } - return have >= required; - } - - private boolean hasBetterItem(Player player, Material materialToBuy) { - for (List group : TIERED_ITEM_GROUPS) { - if (!group.contains(materialToBuy)) { - continue; - } - - int tierToBuy = group.indexOf(materialToBuy); - for (ItemStack stack : player.getInventory().getItemStacks()) { - if (group.contains(stack.material()) && group.indexOf(stack.material()) > tierToBuy) { - return true; - } - } - for (ItemStack stack : List.of( - player.getEquipment(EquipmentSlot.BOOTS), - player.getEquipment(EquipmentSlot.LEGGINGS), - player.getEquipment(EquipmentSlot.CHESTPLATE), - player.getEquipment(EquipmentSlot.HELMET))) { - if (group.contains(stack.material()) && group.indexOf(stack.material()) > tierToBuy) { - return true; - } - } - return false; - } - - return false; - } - - private void playClickSound(HypixelPlayer player) { - player.playSound(Sound.sound(Key.key("minecraft:ui.button.click"), Sound.Source.MASTER, 1.0f, 1.0f)); - } - - private void playBuySound(HypixelPlayer player) { - player.playSound(Sound.sound(Key.key("minecraft:entity.experience_orb.pickup"), Sound.Source.MASTER, 1.0f, 1.0f)); - } + private static final ItemStack QUICK_BUY = ItemStack.builder(Material.NETHER_STAR) + .customName(Component.text("Quick Buy").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.AQUA)) + .build(); + + private static final ItemStack BLOCKS = ItemStack.builder(Material.TERRACOTTA) + .customName(Component.text("Blocks").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + + private static final ItemStack WEAPONS = ItemStack.builder(Material.GOLDEN_SWORD) + .customName(Component.text("Weapons").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + + private static final ItemStack ARMOR = ItemStack.builder(Material.CHAINMAIL_BOOTS) + .customName(Component.text("Armor").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + + private static final ItemStack TOOLS = ItemStack.builder(Material.STONE_PICKAXE) + .customName(Component.text("Tools").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + + private static final ItemStack BOWS = ItemStack.builder(Material.BOW) + .customName(Component.text("Bows & Arrows").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + + private static final ItemStack POTIONS = ItemStack.builder(Material.BREWING_STAND) + .customName(Component.text("Potions").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + + private static final ItemStack UTILITY = ItemStack.builder(Material.TNT) + .customName(Component.text("Utility").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + + private static final ItemStack ROTATING_ITEMS = ItemStack.builder(Material.REDSTONE_TORCH) + .customName(Component.text("Rotating Items").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) + .build(); + private static final List> TIERED_ITEM_GROUPS = List.of( + List.of(Material.LEATHER_BOOTS, Material.GOLDEN_BOOTS, Material.CHAINMAIL_BOOTS, Material.IRON_BOOTS, Material.DIAMOND_BOOTS, Material.NETHERITE_BOOTS) + ); + private final ShopManager shopService = TypeBedWarsGameLoader.shopManager; + private int currentPage = 0; + private final Game game; + + public GUIItemShop(Game game) { + super("Item Shop", InventoryType.CHEST_6_ROW); + this.game = game; + } + + @Override + public boolean allowHotkeying() { + return true; + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + updateGUI(e.player()); + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + e.setCancelled(true); + } + + private void updateGUI(HypixelPlayer p) { + fill(ItemStackCreator.createNamedItemStack(Material.BLACK_STAINED_GLASS_PANE), 9, 17); + set(currentPage + 9, ItemStackCreator.createNamedItemStack(Material.GREEN_STAINED_GLASS_PANE)); + set(new GUIClickableItem(0) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 0; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(QUICK_BUY, currentPage, 0); + } + }); + + set(new GUIClickableItem(1) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 1; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(BLOCKS, currentPage, 1); + } + }); + + set(new GUIClickableItem(2) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 2; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(WEAPONS, currentPage, 2); + } + }); + + set(new GUIClickableItem(3) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 3; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(ARMOR, currentPage, 3); + } + }); + + set(new GUIClickableItem(4) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 4; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(TOOLS, currentPage, 4); + } + }); + + set(new GUIClickableItem(5) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 5; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(BOWS, currentPage, 5); + } + }); + + set(new GUIClickableItem(6) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 6; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(POTIONS, currentPage, 6); + } + }); + + set(new GUIClickableItem(7) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 7; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(UTILITY, currentPage, 7); + } + }); + + set(new GUIClickableItem(8) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + currentPage = 8; + updateGUI(player); + playClickSound(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return convertToClickToView(ROTATING_ITEMS, currentPage, 8); + } + }); + + populateShopItems(this, shopService, game, currentPage, null, this::updateGUI); + updateItemStacks(getInventory(), getPlayer()); + } + + private ItemStack.Builder convertToClickToView(ItemStack itemStack, int currentPage, int index) { + ItemStack.Builder builder = itemStack.builder(); + + if (currentPage != index) { + return builder.lore(noItalic(Component.text("Click to view!").color(NamedTextColor.YELLOW))); + } + + return builder; + } + + public static void populateShopItems(HypixelInventoryGUI gui, ShopManager shopService, Game game, @Nullable Integer currentPage, @Nullable ShopItem quickBuyEditor, Consumer update) { + int[] shopSlots = { + 19, 20, 21, 22, 23, 24, 25, + 28, 29, 30, 31, 32, 33, 34, + 37, 38, 39, 40, 41, 42, 43 + }; + + for (int i = 0; i < shopSlots.length; i++) { + int slot = shopSlots[i]; + int index = i; + + if (currentPage != null && currentPage == 8) { + gui.set(new GUIItem(49) { + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return ItemStackCreator.getStack("§aWhat are Rotating Items?", Material.PAPER, 1, List.of( + "§7Rotating Items are items that are", + "§7only available for a limited amount of", + "§7time. They may disappear and be", + "§7replaced with another temporary", + "§7item at any time." + )); + } + }); + } + + gui.set(new GUIClickableItem(slot) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer p) { + BedWarsPlayer player = (BedWarsPlayer) p; + ShopItem shopItem; + if ((currentPage != null && currentPage == 0 ) || quickBuyEditor != null) { + shopItem = shopService.getQuickShopItem(player, index); + } else if (currentPage != null) { + shopItem = shopService.getShopItem(currentPage, index); + } else { + throw new IllegalStateException("Current page cannot be null when clicking shop items!"); + } + + if (quickBuyEditor != null) { + shopService.setQuickBuyItem(player, index, quickBuyEditor); + player.closeInventory(); + new GUIItemShop(game).open(player); + player.sendMessage("§aAdded " + quickBuyEditor.getName() + " to Quick Buy!"); + return; + } + + if (shopItem == null) return; + + Click click = e.getClick(); + if (click instanceof Click.LeftShift || click instanceof Click.RightShift) { + boolean isInQuickBuy = shopService.isItemIDinQuickBuy(player, shopItem.getId()); + if (isInQuickBuy) { + if (currentPage != 0) return; + shopService.removeQuickBuyItem(player, shopItem); + player.sendMessage(noItalic(Component.text("Removed " + shopItem.getName() + " from Quick Buy!").color(NamedTextColor.RED))); + } else { + player.closeInventory(); + new GUIQuickBuyEditor(game, shopItem).open(player); + } + playClickSound(player); + update.accept(player); + return; + } + + if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { + int nextLevel = upgradeableShopItem.getNextLevel(player); + if (nextLevel >= upgradeableShopItem.getTiers().size()) { + player.sendMessage(noItalic(Component.text("You have already purchased the maximum tier of this item!").color(NamedTextColor.RED))); + return; + } + UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); + if (!hasPlayerEnoughCurrencyForTier(game, player, nextTier)) { + int owned = Arrays.stream(player.getInventory().getItemStacks()) + .filter(s -> s.material() == nextTier.currency().getMaterial()) + .mapToInt(ItemStack::amount) + .sum(); + int needed = nextTier.price().apply(game.getBedwarsGameType()) - owned; + player.sendMessage(noItalic(Component.text("You don't have enough " + nextTier.currency().getName() + "! Need " + needed + " more!").color(NamedTextColor.RED))); + return; + } + upgradeableShopItem.handlePurchase(player, game.getBedwarsGameType()); + player.sendMessage(noItalic(Component.text("You purchased " + nextTier.name() + "!").color(NamedTextColor.GREEN))); + playBuySound(player); + update.accept(player); + return; + } + + if (!hasPlayerEnoughCurrency(game, player, shopItem)) { + player.sendMessage(noItalic(Component.text("You don't have enough " + shopItem.getCurrency().getName() + "!").color(NamedTextColor.RED))); + return; + } + if (!shopItem.isOwned(player)) { + player.sendMessage(noItalic(Component.text("You already have the highest tier available!").color(NamedTextColor.RED))); + return; + } + + + if (hasBetterItem(player, shopItem.getDisplay().material())) { + player.sendMessage("§cYou already have a better item!"); + return; + } + shopItem.handlePurchase(player, game.getBedwarsGameType()); + playBuySound(player); + update.accept(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer p) { + BedWarsPlayer player = (BedWarsPlayer) p; + ShopItem shopItem; + if ((currentPage != null && currentPage == 0 ) || quickBuyEditor != null) { + shopItem = shopService.getQuickShopItem(player, index); + } else if (currentPage != null) { + shopItem = shopService.getShopItem(currentPage, index); + } else { + throw new IllegalStateException("Current page cannot be null when getting shop items!"); + } + + if (shopItem == null) { + if (quickBuyEditor != null) { + return ItemStackCreator.getStack( + "§cEmpty slot!", + Material.RED_STAINED_GLASS_PANE, + 1, + List.of("§eClick to set!") + ); + } + if (currentPage != 0) return ItemStack.builder(Material.AIR); + return ItemStackCreator.getStack( + "§cEmpty slot!", + Material.RED_STAINED_GLASS_PANE, + 1, + List.of("§7This is a Quick Buy Slot! §bShift Click", "§7any item in the shop to add it here.") + ); + } + + if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { + int nextLevel = upgradeableShopItem.getNextLevel(player); + UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); + boolean hasEnough = hasPlayerEnoughCurrencyForTier(game, player, nextTier); + + List lore = new ArrayList<>(); + if (quickBuyEditor != null) { + lore.add("§eClick to replace!"); + } else { + lore.add( + "§7Cost: " + nextTier.currency().getColor() + nextTier.price().apply(game.getBedwarsGameType()) + " " + nextTier.currency().getName() + ); + lore.add(" "); + if (upgradeableShopItem.getDescription() != null && !upgradeableShopItem.getDescription().isEmpty()) { + lore.addAll(StringUtility.splitByNewLine(upgradeableShopItem.getDescription(), "§7")); + lore.add(" "); + } + + boolean isItemInQuickBuy = shopService.isItemIDinQuickBuy(player, upgradeableShopItem.getId()); + if (currentPage != 0 && !isItemInQuickBuy) { + lore.add("§bShift Click to add to Quick Buy"); + } else if (currentPage == 0 && isItemInQuickBuy) { + lore.add("§bShift Click to remove from Quick Buy"); + } + if (nextLevel >= upgradeableShopItem.getTiers().size()) { + lore.add("§cYou have already purchased the maximum tier of this item!"); + } else if (hasEnough) { + lore.add("§eClick to buy!"); + } else { + lore.add("§cYou don't have enough " + nextTier.currency().getName() + "!"); + } + } + + String name; + if (quickBuyEditor != null) { + name = "§a" + nextTier.name(); + } else { + name = hasEnough ? "§a" + nextTier.name() : "§c" + nextTier.name(); + } + + return ItemStackCreator.getStack( + name, + nextTier.material(), + 1, + lore + ); + } + + boolean hasEnough = hasPlayerEnoughCurrency(game, player, shopItem); + List lore = new ArrayList<>(); + if (quickBuyEditor != null) { + lore.add("§eClick to replace!"); + } else { + lore.add( + "§7Cost: " + shopItem.getCurrency().getColor() + shopItem.getPrice().apply(game.getBedwarsGameType()) + " " + shopItem.getCurrency().getName() + ); + lore.add(" "); + if (shopItem.getDescription() != null && !shopItem.getDescription().isEmpty()) { + lore.addAll(StringUtility.splitByNewLine(shopItem.getDescription(), "§7")); + lore.add(" "); + } + + boolean isItemInQuickBuy = shopService.isItemIDinQuickBuy(player, shopItem.getId()); + if (currentPage != 0 && !isItemInQuickBuy) { + lore.add("§bShift Click to add to Quick Buy"); + } else if (currentPage == 0 && isItemInQuickBuy) { + lore.add("§bShift Click to remove from Quick Buy"); + } + if (!hasEnough) { + lore.add("§cYou don't have enough " + shopItem.getCurrency().getName() + "!"); + } else if (!shopItem.isOwned(player)) { + lore.add("§aUNLOCKED"); + } else if (hasBetterItem(player, shopItem.getDisplay().material())) { + lore.add("§cYou already have a better item!"); + } else { + lore.add("§eClick to buy!"); + } + } + + Component name; + if (quickBuyEditor != null) { + name = Component.text("§a" + shopItem.getName()); + } else { + name = hasEnough && shopItem.isOwned(player) ? Component.text("§a" + shopItem.getName()) : Component.text("§c" + shopItem.getName()); + } + + return ItemStackCreator.updateLore( + shopItem.getDisplay().builder().set(DataComponents.CUSTOM_NAME, name), + lore + ); + } + }); + } + } + + private static boolean hasPlayerEnoughCurrency(Game game, HypixelPlayer player, ShopItem shopItem) { + int requiredAmount = shopItem.getPrice().apply(game.getBedwarsGameType()); + Material currencyMaterial = shopItem.getCurrency().getMaterial(); + + int playerAmount = 0; + for (ItemStack item : player.getInventory().getItemStacks()) { + if (item.material() == currencyMaterial) { + playerAmount += item.amount(); + } + } + + return playerAmount >= requiredAmount; + } + + private static boolean hasPlayerEnoughCurrencyForTier(Game game, HypixelPlayer player, UpgradeableItemTier tier) { + int required = tier.price().apply(game.getBedwarsGameType()); + Material cur = tier.currency().getMaterial(); + int have = 0; + for (ItemStack it : player.getInventory().getItemStacks()) { + if (it.material() == cur) have += it.amount(); + } + return have >= required; + } + + private static boolean hasBetterItem(Player player, Material materialToBuy) { + for (List group : TIERED_ITEM_GROUPS) { + if (!group.contains(materialToBuy)) { + continue; + } + + int tierToBuy = group.indexOf(materialToBuy); + for (ItemStack stack : player.getInventory().getItemStacks()) { + if (group.contains(stack.material()) && group.indexOf(stack.material()) > tierToBuy) { + return true; + } + } + for (ItemStack stack : List.of( + player.getEquipment(EquipmentSlot.BOOTS), + player.getEquipment(EquipmentSlot.LEGGINGS), + player.getEquipment(EquipmentSlot.CHESTPLATE), + player.getEquipment(EquipmentSlot.HELMET))) { + if (group.contains(stack.material()) && group.indexOf(stack.material()) > tierToBuy) { + return true; + } + } + return false; + } + + return false; + } + + private static void playClickSound(HypixelPlayer player) { + player.playSound(Sound.sound(Key.key("minecraft:ui.button.click"), Sound.Source.MASTER, 1.0f, 1.0f)); + } + + private static void playBuySound(HypixelPlayer player) { + player.playSound(Sound.sound(Key.key("minecraft:entity.experience_orb.pickup"), Sound.Source.MASTER, 1.0f, 1.0f)); + } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickBuyEditor.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickBuyEditor.java new file mode 100644 index 000000000..20f3ec903 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickBuyEditor.java @@ -0,0 +1,67 @@ +package net.swofty.type.bedwarsgame.gui; + +import net.kyori.adventure.text.Component; +import net.minestom.server.component.DataComponents; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.swofty.commons.StringUtility; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.Game; +import net.swofty.type.bedwarsgame.shop.ShopItem; +import net.swofty.type.bedwarsgame.shop.ShopManager; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.item.GUIItem; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.ArrayList; +import java.util.List; + +public class GUIQuickBuyEditor extends HypixelInventoryGUI { + private final ShopManager shopService = TypeBedWarsGameLoader.shopManager; + private final ShopItem shopItem; + private final Game game; + + public GUIQuickBuyEditor(Game game, ShopItem shopItem) { + super("Adding to Quick Buy...", InventoryType.CHEST_6_ROW); + this.shopItem = shopItem; + this.game = game; + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + set(new GUIItem(4) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + List lore = new ArrayList<>(); + lore.add( + "§7Cost: " + shopItem.getCurrency().getColor() + shopItem.getPrice().apply(game.getBedwarsGameType()) + " " + shopItem.getCurrency().getName() + ); + lore.add(" "); + if (shopItem.getDescription() != null && !shopItem.getDescription().isEmpty()) { + lore.addAll(StringUtility.splitByNewLine(shopItem.getDescription(), "§7")); + lore.add(" "); + } + lore.add("§eAdding item to Quick Slot!"); + + return ItemStackCreator.updateLore( + shopItem.getDisplay().builder().set(DataComponents.CUSTOM_NAME, Component.text("§a" + shopItem.getName())), + lore + ); + } + }); + GUIItemShop.populateShopItems(this, shopService, game, null, shopItem, null); + updateItemStacks(getInventory(), getPlayer()); + } + + @Override + public boolean allowHotkeying() { + return false; + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/ShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/ShopItem.java index 9ecebe5e4..57e6f3f9d 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/ShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/ShopItem.java @@ -13,6 +13,7 @@ @Getter public abstract class ShopItem { + private final String id; private final String name; private final String description; private final Function price; @@ -20,7 +21,8 @@ public abstract class ShopItem { private final Currency currency; private final ItemStack display; - public ShopItem(String name, String description, int price, int amount, Currency currency, Material display) { + public ShopItem(String id, String name, String description, int price, int amount, Currency currency, Material display) { + this.id = id; this.name = name; this.description = description; this.price = (_) -> price; @@ -29,7 +31,8 @@ public ShopItem(String name, String description, int price, int amount, Currency this.display = ItemStack.of(display); } - public ShopItem(String name, String description, Function price, int amount, Currency currency, Material display) { + public ShopItem(String id, String name, String description, Function price, int amount, Currency currency, Material display) { + this.id = id; this.name = name; this.description = description; this.price = price; @@ -41,7 +44,7 @@ public ShopItem(String name, String description, Function t.isDoublesSolo() ? 3 : 4, Currency.EMERALD, Material.DIAMOND_SWORD); - private final ShopItem ENDER_PEARL = new ReplaceAdderItem("Ender Pearl", "The quickest way to invade enemy\nbases.", 2, Currency.EMERALD, Material.ENDER_PEARL); - private final ShopItem TNT = new BasicItem("TNT", "Instantly ignites, appropriate to\nexpode things!", 4, 1, Currency.GOLD, Material.TNT); - private final ShopItem WATER_BUCKET = new BasicItem("Water Bucket", "Great to slow down approaching\nenemies. Can also protect against\nTNT.", 6, 1, Currency.GOLD, Material.WATER_BUCKET); + private final ShopItem GLASS = new BasicItem("glass", "Blast-Proof Glass", "Immune to explosions.", 12, 4, Currency.IRON, Material.GLASS); + private final ShopItem ENDSTONE = new BasicItem("endstone", "Endstone", "Solid block to defend your bed. w", 24, 12, Currency.IRON, Material.END_STONE); + private final ShopItem OBSIDIAN = new BasicItem("obsidian", "Obsidian", "Great for defending.", 4, 4, Currency.EMERALD, Material.OBSIDIAN); + private final ShopItem LADDER = new BasicItem("ladder", "Ladder", "Useful to save cats stuck in trees.", 8, 8, Currency.IRON, Material.LADDER); + private final ShopItem PLANKS = new BasicItem("wood", "Wood", "Good block to defend your bed.\nStrong against pickaxes.", 4, 16, Currency.GOLD, Material.OAK_PLANKS); + private final ShopItem STONE_SWORD = new ReplaceAdderItem("stone_sword", "Stone Sword", "", 10, Currency.IRON, Material.STONE_SWORD); + private final ShopItem IRON_SWORD = new ReplaceAdderItem("iron_sword", "Iron Sword", "", 7, Currency.GOLD, Material.IRON_SWORD); + private final ShopItem DIAMOND_SWORD = new ReplaceAdderItem("diamond_sword", "Diamond Sword", "", (t) -> t.isDoublesSolo() ? 3 : 4, Currency.EMERALD, Material.DIAMOND_SWORD); + private final ShopItem ENDER_PEARL = new ReplaceAdderItem("ender_pearl", "Ender Pearl", "The quickest way to invade enemy\nbases.", 2, Currency.EMERALD, Material.ENDER_PEARL); + private final ShopItem TNT = new BasicItem("tnt", "TNT", "Instantly ignites, appropriate to\nexpode things!", 4, 1, Currency.GOLD, Material.TNT); + private final ShopItem WATER_BUCKET = new BasicItem("water_bucket", "Water Bucket", "Great to slow down approaching\nenemies. Can also protect against\nTNT.", 6, 1, Currency.GOLD, Material.WATER_BUCKET); private final ShopItem BRIDGE_EGG = new BridgeEggShopItem(); - private final ShopItem ARROW = new BasicItem("Arrows", "", 3, 16, Currency.GOLD, Material.ARROW); - private final ShopItem BOW = new BowShopItem("Bow", "", 6, Currency.IRON, EnchantmentList.EMPTY.with(Enchantment.POWER, 1)); + private final ShopItem ARROW = new BasicItem("arrow", "Arrows", "", 3, 16, Currency.GOLD, Material.ARROW); + private final ShopItem BOW = new BowShopItem("bow_1", "Bow", "", 6, Currency.IRON, EnchantmentList.EMPTY.with(Enchantment.POWER, 1)); private final ShopItem PICKAXE = new PickaxeShopItem(); private final ShopItem AXE = new AxeShopItem(); private final ShopItem FIREBALL = new FireballShopItem(); private final ShopItem POPUP_TOWER = new PopupTowerItem(); private final ShopItem GOLDEN_APPLE = new GappleShopItem(); - private final ShopItem INVISIBILITY_POTION = new PotionShopItem("Invisibility Potion (30 seconds)", "§9Complete invisibility (0:30).", 2, 1, Currency.EMERALD, PotionType.INVISIBILITY); - private final ShopItem SPEED_POTION = new PotionShopItem("Speed II Potion (45 seconds)", "§9Speed II (0:45).", 2, 1, Currency.EMERALD, PotionType.SWIFTNESS); - private final ShopItem JUMP_POTION = new PotionShopItem("Jump V Potion (45 seconds)", "§9Jump Boost V (0:45).", 2, 1, Currency.EMERALD, PotionType.LEAPING); - private final ShopItem CHAINMAIL_ARMOR = new ArmorShopItem("Permanent Chainmail Armor", "", 24, Currency.IRON, Material.CHAINMAIL_BOOTS, Material.CHAINMAIL_LEGGINGS, 1); - private final ShopItem IRON_ARMOR = new ArmorShopItem("Permanent Iron Armor", "", 12, Currency.GOLD, Material.IRON_BOOTS, Material.IRON_LEGGINGS, 2); - private final ShopItem DIAMOND_ARMOR = new ArmorShopItem("Permanent Diamond Armor", "", 6, Currency.EMERALD, Material.DIAMOND_BOOTS, Material.DIAMOND_LEGGINGS, 3); - private final ShopItem SHEARS = new BasicItem("Shears", "Great to get rid of wool. You will\nalways spawn with these shears.", 20, 1, Currency.IRON, Material.SHEARS); + private final ShopItem INVISIBILITY_POTION = new PotionShopItem("invisibility_potion", "Invisibility Potion (30 seconds)", "§9Complete invisibility (0:30).", 2, 1, Currency.EMERALD, PotionType.INVISIBILITY); + private final ShopItem SPEED_POTION = new PotionShopItem("speed_potion", "Speed II Potion (45 seconds)", "§9Speed II (0:45).", 2, 1, Currency.EMERALD, PotionType.SWIFTNESS); + private final ShopItem JUMP_POTION = new PotionShopItem("jump_potion", "Jump V Potion (45 seconds)", "§9Jump Boost V (0:45).", 2, 1, Currency.EMERALD, PotionType.LEAPING); + private final ShopItem CHAINMAIL_ARMOR = new ArmorShopItem("chainmail_armor", "Permanent Chainmail Armor", "", 24, Currency.IRON, Material.CHAINMAIL_BOOTS, Material.CHAINMAIL_LEGGINGS, 1); + private final ShopItem IRON_ARMOR = new ArmorShopItem("iron_armor", "Permanent Iron Armor", "", 12, Currency.GOLD, Material.IRON_BOOTS, Material.IRON_LEGGINGS, 2); + private final ShopItem DIAMOND_ARMOR = new ArmorShopItem("diamond_armor", "Permanent Diamond Armor", "", 6, Currency.EMERALD, Material.DIAMOND_BOOTS, Material.DIAMOND_LEGGINGS, 3); + private final ShopItem SHEARS = new BasicItem("shears", "Shears", "Great to get rid of wool. You will\nalways spawn with these shears.", 20, 1, Currency.IRON, Material.SHEARS); public ShopManager() { @@ -96,30 +98,30 @@ public ShopItem getShopItem(int categoryId, int itemIndex) { return null; } - // TODO: actual fetching + public ShopItem getShopItemById(String itemId) { + for (List items : categorizedShopItems.values()) { + for (ShopItem item : items) { + if (item.getId().equals(itemId)) { + return item; + } + } + } + return null; + } + public Map getQuickBuy(BedWarsPlayer player) { + BedWarsDataHandler dataHandler = BedWarsDataHandler.getUser(player); + DatapointBedWarsQuickBuy.PlayerQuickBuy playerQuickBuy = dataHandler.get(BedWarsDataHandler.Data.QUICK_BUY, DatapointBedWarsQuickBuy.class).getValue(); Map quickBuy = new HashMap<>(); - quickBuy.put(0, WOOL); - quickBuy.put(1, STONE_SWORD); - quickBuy.put(2, CHAINMAIL_ARMOR); - quickBuy.put(3, PICKAXE); - quickBuy.put(4, BOW); - quickBuy.put(5, INVISIBILITY_POTION); - quickBuy.put(6, TNT); - quickBuy.put(7, PLANKS); - quickBuy.put(8, IRON_SWORD); - quickBuy.put(9, IRON_ARMOR); - quickBuy.put(10, SHEARS); - quickBuy.put(11, ARROW); - quickBuy.put(12, SPEED_POTION); - quickBuy.put(13, WATER_BUCKET); - quickBuy.put(14, GOLDEN_APPLE); - quickBuy.put(15, JUMP_POTION); - quickBuy.put(16, GLASS); - quickBuy.put(17, ENDSTONE); - quickBuy.put(18, AXE); - quickBuy.put(19, WOOL); - quickBuy.put(20, WOOL); + + for (int slot : playerQuickBuy.getOccupiedSlots()) { + String itemId = playerQuickBuy.getItemId(slot); + ShopItem item = getShopItemById(itemId); + if (item != null) { + quickBuy.put(slot, item); + } + } + return quickBuy; } @@ -128,4 +130,37 @@ public ShopItem getQuickShopItem(BedWarsPlayer player, int itemIndex) { return quickBuy.get(itemIndex); } + public void setQuickBuyItem(BedWarsPlayer player, int slot, ShopItem item) { + if (item == null) { + throw new IllegalArgumentException("Item cannot be null"); + } + + BedWarsDataHandler dataHandler = BedWarsDataHandler.getUser(player); + DatapointBedWarsQuickBuy quickBuyData = dataHandler.get(BedWarsDataHandler.Data.QUICK_BUY, DatapointBedWarsQuickBuy.class); + DatapointBedWarsQuickBuy.PlayerQuickBuy playerQuickBuy = quickBuyData.getValue(); + + playerQuickBuy.setItemId(slot, item.getId()); + quickBuyData.setValue(playerQuickBuy); + } + + public void removeQuickBuyItem(BedWarsPlayer player, ShopItem item) { + if (item == null) return; + + BedWarsDataHandler dataHandler = BedWarsDataHandler.getUser(player); + DatapointBedWarsQuickBuy quickBuyData = dataHandler.get(BedWarsDataHandler.Data.QUICK_BUY, DatapointBedWarsQuickBuy.class); + DatapointBedWarsQuickBuy.PlayerQuickBuy playerQuickBuy = quickBuyData.getValue(); + + int slotToRemove = playerQuickBuy.findSlotByItemId(item.getId()); + if (slotToRemove != -1) { + playerQuickBuy.removeFromSlot(slotToRemove); + quickBuyData.setValue(playerQuickBuy); + } + } + + public boolean isItemIDinQuickBuy(BedWarsPlayer player, String itemId) { + BedWarsDataHandler dataHandler = BedWarsDataHandler.getUser(player); + DatapointBedWarsQuickBuy.PlayerQuickBuy playerQuickBuy = dataHandler.get(BedWarsDataHandler.Data.QUICK_BUY, DatapointBedWarsQuickBuy.class).getValue(); + return playerQuickBuy.containsItemId(itemId); + } + } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/UpgradeableShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/UpgradeableShopItem.java index fc7f67382..587fe29ef 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/UpgradeableShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/UpgradeableShopItem.java @@ -17,9 +17,9 @@ public abstract class UpgradeableShopItem extends ShopItem { private final List tiers; private final Tag upgradeTag; - public UpgradeableShopItem(String name, String description, List tiers, Tag upgradeTag) { + public UpgradeableShopItem(String id, String name, String description, List tiers, Tag upgradeTag) { // The initial price and other details are taken from the first tier. - super(name, description, tiers.getFirst().price(), 1, tiers.getFirst().currency(), tiers.getFirst().material()); + super(id, name, description, tiers.getFirst().price(), 1, tiers.getFirst().currency(), tiers.getFirst().material()); this.tiers = tiers; this.upgradeTag = upgradeTag; } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ArmorShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ArmorShopItem.java index 4a55fa426..d277a02a4 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ArmorShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ArmorShopItem.java @@ -16,8 +16,8 @@ public class ArmorShopItem extends ShopItem { private final Material leggings; private final int armorLevel; - public ArmorShopItem(String name, String description, int price, Currency currency, Material boots, Material leggings, int armorLevel) { - super(name, description, price, 1, currency, boots); + public ArmorShopItem(String id, String name, String description, int price, Currency currency, Material boots, Material leggings, int armorLevel) { + super(id, name, description, price, 1, currency, boots); this.boots = boots; this.leggings = leggings; this.armorLevel = armorLevel; diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/AxeShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/AxeShopItem.java index cd8b00588..3559abae1 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/AxeShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/AxeShopItem.java @@ -13,7 +13,7 @@ public class AxeShopItem extends UpgradeableShopItem { public static final Tag AXE_UPGRADE_TAG = Tag.Integer("axe_upgrade"); public AxeShopItem() { - super("Upgradeable Axe", "This is an upgradable item.\nIt will lose 1 tier upn death!\n\nYou will permanently respawn with at\nleast the lowest tier.", + super("axe", "Upgradeable Axe", "This is an upgradable item.\nIt will lose 1 tier upn death!\n\nYou will permanently respawn with at\nleast the lowest tier.", List.of( new UpgradeableItemTier("Wooden Axe (Efficiency I)", _ -> 10, Currency.IRON, Material.WOODEN_AXE), new UpgradeableItemTier("Stone Axe (Efficiency I)", _ ->10, Currency.IRON, Material.STONE_AXE), diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BasicItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BasicItem.java index 792af7538..724d35a68 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BasicItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BasicItem.java @@ -7,8 +7,8 @@ public class BasicItem extends ShopItem { - public BasicItem(String name, String description, int cost, int amount, Currency currency, Material material) { - super(name, description, cost, amount, currency, material); + public BasicItem(String id, String name, String description, int cost, int amount, Currency currency, Material material) { + super(id, name, description, cost, amount, currency, material); } @Override diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BowShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BowShopItem.java index 9461a2757..3a44d62f5 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BowShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BowShopItem.java @@ -12,8 +12,8 @@ public class BowShopItem extends ShopItem { final EnchantmentList enchantmentList; - public BowShopItem(String name, String description, int price, Currency currency, EnchantmentList enchantmentList) { - super(name, description, price, 1, currency, Material.BOW); + public BowShopItem(String id, String name, String description, int price, Currency currency, EnchantmentList enchantmentList) { + super(id, name, description, price, 1, currency, Material.BOW); this.enchantmentList = enchantmentList; } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BridgeEggShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BridgeEggShopItem.java index 837eabfdc..9f4c17969 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BridgeEggShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/BridgeEggShopItem.java @@ -9,7 +9,7 @@ public class BridgeEggShopItem extends ShopItem { public BridgeEggShopItem() { - super("Bridge Egg", "This egg creates a bridge in its trail\nafter being thrown.", 1, 1, Currency.EMERALD, Material.EGG); + super("bridge_egg", "Bridge Egg", "This egg creates a bridge in its trail\nafter being thrown.", 1, 1, Currency.EMERALD, Material.EGG); } @Override diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/FireballShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/FireballShopItem.java index 461343a67..231366b96 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/FireballShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/FireballShopItem.java @@ -9,7 +9,7 @@ public class FireballShopItem extends ShopItem { public FireballShopItem() { - super("Fireball", "Right-click to launch! Great to knock\nback enemies walking on thin bridges.", 40, 1, Currency.IRON, Material.FIRE_CHARGE); + super("fireball", "Fireball", "Right-click to launch! Great to knock\nback enemies walking on thin bridges.", 40, 1, Currency.IRON, Material.FIRE_CHARGE); } @Override diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/GappleShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/GappleShopItem.java index 78b88cb6f..ee484092b 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/GappleShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/GappleShopItem.java @@ -9,7 +9,7 @@ public class GappleShopItem extends ShopItem { public GappleShopItem() { - super("Golden Apple", "Well-rounded healing.", 3, 1, Currency.GOLD, Material.GOLDEN_APPLE); + super("golden_apple", "Golden Apple", "Well-rounded healing.", 3, 1, Currency.GOLD, Material.GOLDEN_APPLE); } @Override diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/HardenedClay.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/HardenedClay.java index 5ab9cd857..2d1076f49 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/HardenedClay.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/HardenedClay.java @@ -10,7 +10,7 @@ public class HardenedClay extends ShopItem { public HardenedClay() { - super("Hardened Clay", "Basic block to defend your bed.", 12, 16, Currency.IRON, Material.TERRACOTTA); + super("hardened_clay", "Hardened Clay", "Basic block to defend your bed.", 12, 16, Currency.IRON, Material.TERRACOTTA); } private Material mapTeamToTerracotta(BedWarsMapsConfig.TeamKey teamKey) { diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PickaxeShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PickaxeShopItem.java index 860de0462..569252742 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PickaxeShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PickaxeShopItem.java @@ -14,7 +14,7 @@ public class PickaxeShopItem extends UpgradeableShopItem { public static final Tag<@NotNull Integer> PICKAXE_UPGRADE_TAG = Tag.Integer("pickaxe_upgrade"); public PickaxeShopItem() { - super("Upgradeable Pickaxe", "This is an upgradable item.\nIt will lose 1 tier upn death!\n\nYou will permanently respawn with at\nleast the lowest tier.", + super("pickaxe", "Upgradeable Pickaxe", "This is an upgradable item.\nIt will lose 1 tier upn death!\n\nYou will permanently respawn with at\nleast the lowest tier.", List.of( new UpgradeableItemTier("Wooden Pickaxe (Efficiency I)", _ -> 10, Currency.IRON, Material.WOODEN_PICKAXE), new UpgradeableItemTier("Iron Pickaxe (Efficiency II) ", _ -> 10, Currency.IRON, Material.IRON_PICKAXE), diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PopupTowerItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PopupTowerItem.java index 22a2a86cf..3a60f5c7c 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PopupTowerItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PopupTowerItem.java @@ -9,7 +9,7 @@ public class PopupTowerItem extends ShopItem { public PopupTowerItem() { - super("Pop-Up Tower", "Place a pop-up defence!", 24, 1, Currency.IRON, Material.CHEST); + super("pop_up_tower", "Pop-Up Tower", "Place a pop-up defence!", 24, 1, Currency.IRON, Material.CHEST); } @Override diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PotionShopItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PotionShopItem.java index 8714feb86..14cb9ed71 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PotionShopItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/PotionShopItem.java @@ -13,8 +13,8 @@ public class PotionShopItem extends ShopItem { final PotionType potionType; - public PotionShopItem(String name, String description, int cost, int amount, Currency currency, PotionType potionType) { - super(name, description, cost, amount, currency, Material.POTION); + public PotionShopItem(String id, String name, String description, int cost, int amount, Currency currency, PotionType potionType) { + super(id, name, description, cost, amount, currency, Material.POTION); this.potionType = potionType; } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ReplaceAdderItem.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ReplaceAdderItem.java index e3dc37a13..93ca7028f 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ReplaceAdderItem.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/ReplaceAdderItem.java @@ -14,18 +14,18 @@ public class ReplaceAdderItem extends ShopItem { private final Material replacementMaterial; - public ReplaceAdderItem(String name, String description, Function cost, Currency currency, Material material) { - super(name, description, cost, 1, currency, material); + public ReplaceAdderItem(String id, String name, String description, Function cost, Currency currency, Material material) { + super(id, name, description, cost, 1, currency, material); this.replacementMaterial = Material.WOODEN_SWORD; } - public ReplaceAdderItem(String name, String description, int cost, Currency currency, Material material) { - super(name, description, cost, 1, currency, material); + public ReplaceAdderItem(String id, String name, String description, int cost, Currency currency, Material material) { + super(id, name, description, cost, 1, currency, material); this.replacementMaterial = Material.WOODEN_SWORD; } - public ReplaceAdderItem(String name, String description, int cost, Currency currency, Material material, Material replacementMaterial) { - super(name, description, cost, 1, currency, material); + public ReplaceAdderItem(String id, String name, String description, int cost, Currency currency, Material material, Material replacementMaterial) { + super(id, name, description, cost, 1, currency, material); this.replacementMaterial = replacementMaterial; } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/Wool.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/Wool.java index d8fd1e68e..4ae43fe8f 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/Wool.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/shop/impl/Wool.java @@ -10,7 +10,7 @@ public class Wool extends ShopItem { public Wool() { - super("Wool", "Great for bridging across islands.\nTurns into your team's color.", 4, 16, Currency.IRON, Material.WHITE_WOOL); + super("wool", "Wool", "Great for bridging across islands.\nTurns into your team's color.", 4, 16, Currency.IRON, Material.WHITE_WOOL); } private Material mapTeamToWool(BedWarsMapsConfig.TeamKey teamKey) { diff --git a/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointBedWarsQuickBuy.java b/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointBedWarsQuickBuy.java new file mode 100644 index 000000000..88e5156cf --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointBedWarsQuickBuy.java @@ -0,0 +1,144 @@ +package net.swofty.type.generic.data.datapoints; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.protocol.Serializer; +import net.swofty.type.generic.data.Datapoint; +import org.jetbrains.annotations.Nullable; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class DatapointBedWarsQuickBuy extends Datapoint { + public static Serializer serializer = new Serializer<>() { + @Override + public String serialize(PlayerQuickBuy value) { + Map serialized = new HashMap<>(); + + for (Map.Entry entry : value.getQuickBuyMap().entrySet()) { + serialized.put(String.valueOf(entry.getKey()), entry.getValue()); + } + + return new JSONObject(serialized).toString(); + } + + @Override + public PlayerQuickBuy deserialize(String json) { + if (json == null || !json.startsWith("{")) { + return new PlayerQuickBuy(new HashMap<>(DEFAULT_QUICK_BUY)); + } + + try { + JSONObject obj = new JSONObject(json); + Map quickBuyMap = new HashMap<>(); + + for (String key : obj.keySet()) { + String itemId = obj.getString(key); + if (itemId != null && !itemId.isEmpty()) { + quickBuyMap.put(Integer.parseInt(key), itemId); + } + } + + return new PlayerQuickBuy(quickBuyMap); + } catch (Exception e) { + return new PlayerQuickBuy(new HashMap<>(DEFAULT_QUICK_BUY)); + } + } + + @Override + public PlayerQuickBuy clone(PlayerQuickBuy value) { + return new PlayerQuickBuy(new HashMap<>(value.getQuickBuyMap())); + } + }; + + private static final Map DEFAULT_QUICK_BUY = Map.ofEntries( + Map.entry(0, "wool"), + Map.entry(1, "stone_sword"), + Map.entry(2, "chainmail_armor"), + Map.entry(3, "pickaxe"), + Map.entry(4, "bow_1"), + Map.entry(5, "invisibility_potion"), + Map.entry(6, "tnt"), + Map.entry(7, "wood"), + Map.entry(8, "iron_sword"), + Map.entry(9, "iron_armor"), + Map.entry(10, "shears"), + Map.entry(11, "arrow"), + Map.entry(12, "speed_potion"), + Map.entry(13, "water_bucket"), + Map.entry(14, "golden_apple"), + Map.entry(15, "jump_potion"), + Map.entry(16, "glass"), + Map.entry(17, "endstone"), + Map.entry(18, "axe") + ); + + public DatapointBedWarsQuickBuy(String key, PlayerQuickBuy value) { + super(key, value, serializer); + } + + public DatapointBedWarsQuickBuy(String key) { + super(key, new PlayerQuickBuy(new HashMap<>(DEFAULT_QUICK_BUY)), serializer); + } + + @Getter + @Setter + @AllArgsConstructor + @NoArgsConstructor + public static class PlayerQuickBuy { + private Map quickBuyMap = new HashMap<>(); + + /** + * Gets the item ID at the specified slot. + * + * @param slot the slot index (0-20) + * @return the item ID, or null if the slot is empty + */ + public @Nullable String getItemId(int slot) { + return quickBuyMap.get(slot); + } + + /** + * Sets the item ID at the specified slot. + * + * @param slot the slot index (0-20) + * @param itemId the item ID to set + */ + public void setItemId(int slot, String itemId) { + if (slot < 0 || slot > 20) { + throw new IllegalArgumentException("Quick buy slot must be between 0 and 20"); + } + if (itemId == null || itemId.isEmpty()) { + quickBuyMap.remove(slot); + } else { + quickBuyMap.put(slot, itemId); + } + } + + public void removeFromSlot(int slot) { + quickBuyMap.remove(slot); + } + + public Set getOccupiedSlots() { + return quickBuyMap.keySet(); + } + + public boolean containsItemId(String itemId) { + return quickBuyMap.containsValue(itemId); + } + + public int findSlotByItemId(String itemId) { + for (Map.Entry entry : quickBuyMap.entrySet()) { + if (itemId.equals(entry.getValue())) { + return entry.getKey(); + } + } + return -1; + } + + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/data/handlers/BedWarsDataHandler.java b/type.generic/src/main/java/net/swofty/type/generic/data/handlers/BedWarsDataHandler.java index b4ea3f420..df0e8e6b6 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/data/handlers/BedWarsDataHandler.java +++ b/type.generic/src/main/java/net/swofty/type/generic/data/handlers/BedWarsDataHandler.java @@ -7,12 +7,10 @@ import net.swofty.type.generic.data.GameDataHandler; import net.swofty.commons.bedwars.BedWarsModeStats; import net.swofty.commons.bedwars.LeaderboardPreferences; +import net.swofty.type.generic.data.datapoints.*; import net.swofty.type.generic.data.datapoints.DatapointBedWarsModeStats; -import net.swofty.type.generic.data.datapoints.DatapointLeaderboardLong; +import net.swofty.type.generic.data.datapoints.DatapointBedWarsQuickBuy; import net.swofty.type.generic.data.datapoints.DatapointLeaderboardPreferences; -import net.swofty.type.generic.data.datapoints.DatapointLong; -import net.swofty.type.generic.data.datapoints.DatapointMapStringLong; -import net.swofty.type.generic.data.datapoints.DatapointStringList; import net.swofty.type.generic.leaderboard.LeaderboardService; import net.swofty.type.generic.user.HypixelPlayer; import org.bson.Document; @@ -20,7 +18,6 @@ import org.tinylog.Logger; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.BiConsumer; @@ -196,6 +193,7 @@ public enum Data { SLUMBER_TICKETS("bedwars_slumber_tickets", DatapointLeaderboardLong.class, new DatapointLeaderboardLong("bedwars_slumber_tickets", 0L, "bedwars:slumber_tickets")), FAVORITE_MAPS("bedwars_favorite_maps", DatapointStringList.class, new DatapointStringList("bedwars_favorite_maps")), + QUICK_BUY("bedwars_quick_buy", DatapointBedWarsQuickBuy.class, new DatapointBedWarsQuickBuy("bedwars_quick_buy")), MAP_JOIN_COUNTS("bedwars_map_join_counts", DatapointMapStringLong.class, new DatapointMapStringLong("bedwars_map_join_counts")), // Cumulative lifetime stats (for quick access without DB aggregation)