diff --git a/src/main/java/com/alttd/GUI/GUIListener.java b/src/main/java/com/alttd/GUI/GUIListener.java index ca73f0a..3bf5ba7 100644 --- a/src/main/java/com/alttd/GUI/GUIListener.java +++ b/src/main/java/com/alttd/GUI/GUIListener.java @@ -1,63 +1,80 @@ package com.alttd.GUI; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.TradeSelectEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.MerchantInventory; public class GUIListener implements Listener { + private static ItemStack air = new ItemStack(Material.AIR); + /** * Handles clicking inside a gui * @param event gui click event */ @EventHandler public void onClick(InventoryClickEvent event){ - if (!(event.getWhoClicked() instanceof Player player)){ - return; - } + if (!(event.getWhoClicked() instanceof Player player)) return; GUI gui = GUI.GUIByUUID.get(player.getUniqueId()); - if (gui == null || gui.getInventory() == null) - return; - if (!gui.getInventory().equals(event.getInventory())) - return; + if (gui == null) return; + if (gui.getInventory() != null) { + if (!gui.getInventory().equals(event.getInventory())) return; + } else if (gui instanceof GUIMerchant) { + HumanEntity trader = gui.getMerchant().getTrader(); + if (trader == null || !trader.equals(player)) return; + } else return; + event.setCancelled(true); + + Inventory clickedInventory = event.getClickedInventory(); + if (clickedInventory == null || clickedInventory.getType().equals(InventoryType.PLAYER)) return; + GUIAction action = gui.getGuiAction(event.getSlot()); - if (action != null){ - action.click(player); - } + if (action != null) action.click(player); } @EventHandler public void onTradeSelect(TradeSelectEvent event) { - if (!(event.getWhoClicked() instanceof Player player)){ - return; - } + if (!(event.getWhoClicked() instanceof Player player)) return; GUI gui = GUI.GUIByUUID.get(player.getUniqueId()); - if ((!(gui instanceof GUIMerchant guiMerchant))) - return; - if (!gui.getMerchant().equals(event.getMerchant())) { - return; - } + + if ((!(gui instanceof GUIMerchant guiMerchant))) return; + if (!gui.getMerchant().equals(event.getMerchant())) return; + event.setCancelled(true); GUIAction action = guiMerchant.getTradeAction(event.getIndex()); gui.setMerchantInventory(event.getInventory()); - if (action != null){ - action.click(player); - } + if (action != null) action.click(player); } @EventHandler public void onClose(InventoryCloseEvent event) { + if (!(event.getInventory() instanceof MerchantInventory merchantInventory)) return; + + HumanEntity player = event.getPlayer(); + GUI gui = GUI.GUIByUUID.get(player.getUniqueId()); + + if (!(gui instanceof GUIMerchant)) return; + + HumanEntity trader = gui.getMerchant().getTrader(); + if (trader == null || !trader.equals(player)) return; + merchantInventory.setItem(0, air); + merchantInventory.setItem(1, air); GUI.GUIByUUID.remove(event.getPlayer().getUniqueId()); } diff --git a/src/main/java/com/alttd/GUI/windows/BuyGUI.java b/src/main/java/com/alttd/GUI/windows/BuyGUI.java index 19d930b..0be9af8 100644 --- a/src/main/java/com/alttd/GUI/windows/BuyGUI.java +++ b/src/main/java/com/alttd/GUI/windows/BuyGUI.java @@ -7,8 +7,10 @@ import com.alttd.config.WorthConfig; import com.alttd.events.SpawnShopEvent; import com.alttd.objects.EconUser; import com.alttd.objects.Price; +import com.alttd.objects.Purchase; import com.alttd.objects.VillagerType; import com.alttd.util.Utilities; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.Template; import net.kyori.adventure.text.minimessage.template.TemplateResolver; @@ -20,6 +22,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -32,7 +35,7 @@ public class BuyGUI extends GUIMerchant { static { ItemStack itemStack = new ItemStack(Material.EMERALD_BLOCK); ItemMeta itemMeta = itemStack.getItemMeta(); - itemMeta.displayName(MiniMessage.miniMessage().deserialize("Confirm")); + itemMeta.displayName(MiniMessage.miniMessage().deserialize(Config.CONFIRM_BUTTON)); itemStack.setItemMeta(itemMeta); confirm = itemStack; } @@ -60,72 +63,93 @@ public class BuyGUI extends GUIMerchant { } private void buy(VillagerType villagerType, Player player, Material material, int amount, Price price) { - Economy econ = VillagerUI.getInstance().getEconomy(); - double balance = econ.getBalance(player); int itemPts = (int) (Math.floor(price.getPrice(1) / WorthConfig.POINT_MOD) + 1); int transPts = itemPts * amount; EconUser econUser = EconUser.getUser(player.getUniqueId()); int oldPoints = Objects.requireNonNullElse(econUser.getPointsMap().get(villagerType.getName()), 0); double cost = price.calculatePriceThing(oldPoints, transPts, true, itemPts); - if (balance < cost) { - player.sendMiniMessage(Config.NOT_ENOUGH_MONEY, List.of( - Template.template("money", String.valueOf(Utilities.round(balance, 2))), - Template.template("price", String.valueOf(cost)) - )); - return; - } + Purchase purchase = new Purchase(material, cost, itemPts, transPts, amount); + ItemStack itemStack = new ItemStack(Material.CANDLE); ItemMeta itemMeta = itemStack.getItemMeta(); itemMeta.displayName(miniMessage.deserialize(String.valueOf(cost))); itemStack.setItemMeta(itemMeta); - setItem(0, new ItemStack(material), null); - setItem(1, new ItemStack(Material.CANDLE), null); - setItem(2, confirm, player1 -> - buy2(player1, amount, cost, material, econUser, villagerType, transPts, oldPoints, price)); + setItem(0, getBuyItemHover(purchase), null); + setItem(1, confirm, player1 -> + buy2(player1, purchase, econUser, villagerType, oldPoints, price)); player.updateInventory(); } - private void buy2(Player player, int amount, double cost, Material material, EconUser econUser, VillagerType villagerType, int transPts, int oldPoints, Price price) { + private void buy2(Player player, Purchase purchase, EconUser econUser, VillagerType villagerType, int oldPoints, Price price) { Economy econ = VillagerUI.getInstance().getEconomy(); - var ref = new Object() { - int space = 0; - }; - Arrays.stream(player.getInventory().getContents()) - .filter(itemStack -> itemStack == null || itemStack.getType().equals(material)) - .forEach(itemStack -> { - if (itemStack == null) - ref.space += material.getMaxStackSize(); - else - ref.space += itemStack.getMaxStackSize() - itemStack.getAmount(); - }); - if (ref.space < amount) { - player.sendMiniMessage(Config.NOT_ENOUGH_SPACE, List.of( - Template.template("space", String.valueOf(ref.space)), - Template.template("amount", String.valueOf(amount)) + double balance = econ.getBalance(player); + + if (balance < purchase.price()) { + player.sendMiniMessage(Config.NOT_ENOUGH_MONEY, List.of( + Template.template("money", String.valueOf(Utilities.round(balance, 2))), + Template.template("price", String.valueOf(purchase.price())) )); return; } - econ.withdrawPlayer(player, cost); - econUser.addPoints(villagerType.getName(), transPts); - player.getInventory().addItem(new ItemStack(material, amount)); + var ref = new Object() { + int space = 0; + }; + Arrays.stream(player.getInventory().getContents()) + .filter(itemStack -> itemStack == null || itemStack.getType().equals(purchase.material())) + .forEach(itemStack -> { + if (itemStack == null) + ref.space += purchase.material().getMaxStackSize(); + else + ref.space += itemStack.getMaxStackSize() - itemStack.getAmount(); + }); + if (ref.space < purchase.amount()) { + player.sendMiniMessage(Config.NOT_ENOUGH_SPACE, List.of( + Template.template("space", String.valueOf(ref.space)), + Template.template("amount", String.valueOf(purchase.amount())) + )); + return; + } + + econ.withdrawPlayer(player, purchase.price()); + econUser.addPoints(villagerType.getName(), purchase.totalPointCost()); + player.getInventory().addItem(new ItemStack(purchase.material(), purchase.amount())); int newPoints = econUser.getPointsMap().get(villagerType.getName()); player.sendMiniMessage(Config.PURCHASED_ITEM, List.of( - Template.template("amount", String.valueOf(amount)), - Template.template("item", StringUtils.capitalize(material.name() + Template.template("amount", String.valueOf(purchase.amount())), + Template.template("item", StringUtils.capitalize(purchase.material().name() .toLowerCase().replaceAll("_", " "))), - Template.template("price", "-" + cost), - Template.template("points", String.valueOf(transPts)), + Template.template("price", "-" + purchase.price()), + Template.template("points", String.valueOf(purchase.totalPointCost())), Template.template("total_points", String.valueOf(newPoints)), Template.template("villager_name", villagerType.getDisplayName()) )); Bukkit.getServer().getPluginManager() - .callEvent(new SpawnShopEvent(player, amount, cost, material, + .callEvent(new SpawnShopEvent(player, purchase, oldPoints, newPoints, true)); - buy(villagerType, player, material, amount, price); + buy(villagerType, player, purchase.material(), purchase.amount(), price); + } + + private ItemStack getBuyItemHover(Purchase purchase) { + ItemStack itemStack = new ItemStack(purchase.material()); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(miniMessage.deserialize(Config.TRANSACTION_ITEM_NAME, TemplateResolver.resolving( + Template.template("item_name", purchase.material().name()) + ))); + List lore = new ArrayList<>(); + for (String entry : Config.TRANSACTION_ITEM_DESCRIPTION) { + lore.add(miniMessage.deserialize(entry, TemplateResolver.resolving( + Template.template("amount", String.valueOf(purchase.amount())), + Template.template("price", String.valueOf(purchase.price())), + Template.template("points", String.valueOf(purchase.totalPointCost())) + ))); + } + itemMeta.lore(lore); + itemStack.setItemMeta(itemMeta); + return itemStack; } private ItemStack getPriceItem(double price) { diff --git a/src/main/java/com/alttd/GUI/windows/SellGUI.java b/src/main/java/com/alttd/GUI/windows/SellGUI.java index 313fcd6..c868b40 100644 --- a/src/main/java/com/alttd/GUI/windows/SellGUI.java +++ b/src/main/java/com/alttd/GUI/windows/SellGUI.java @@ -7,8 +7,10 @@ import com.alttd.config.WorthConfig; import com.alttd.events.SpawnShopEvent; import com.alttd.objects.EconUser; import com.alttd.objects.Price; +import com.alttd.objects.Purchase; import com.alttd.objects.VillagerType; import com.alttd.util.Utilities; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.Template; import net.kyori.adventure.text.minimessage.template.TemplateResolver; @@ -23,6 +25,7 @@ import org.bukkit.inventory.MerchantInventory; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -30,6 +33,15 @@ import java.util.Objects; public class SellGUI extends GUIMerchant { private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private static final ItemStack confirm; + + static { + ItemStack itemStack = new ItemStack(Material.EMERALD_BLOCK); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(MiniMessage.miniMessage().deserialize(Config.CONFIRM_BUTTON)); + itemStack.setItemMeta(itemMeta); + confirm = itemStack; + } public SellGUI(VillagerType villagerType, EconUser econUser, boolean bulk) { super(MiniMessage.miniMessage().deserialize(Config.SELL_WINDOW, TemplateResolver.resolving( @@ -55,44 +67,73 @@ public class SellGUI extends GUIMerchant { private void sell(VillagerType villagerType, Player player, Material material, int amount, Price price, boolean bulk) { PlayerInventory inventory = player.getInventory(); - if (!inventory.containsAtLeast(new ItemStack(material), bulk ? 1 : amount)) { - player.sendMiniMessage(Config.NOT_ENOUGH_ITEMS, List.of( - Template.template("type", material.name()), - Template.template("amount", String.valueOf(bulk ? 1 : amount)))); - return; - } - if (bulk) amount = Arrays.stream(inventory.getContents()) .filter(Objects::nonNull) .filter(itemStack -> itemStack.getType().equals(material)) .mapToInt(ItemStack::getAmount).sum(); - Economy econ = VillagerUI.getInstance().getEconomy(); + EconUser econUser = EconUser.getUser(player.getUniqueId()); int oldPoints = Objects.requireNonNullElse(econUser.getPointsMap().get(villagerType.getName()), 0); int itemPts = (int) (Math.floor(price.getPrice(1) / WorthConfig.POINT_MOD) + 1); int transPts = (itemPts * amount) * -1; double cost = price.calculatePriceThing(oldPoints, transPts, false, itemPts); - econ.depositPlayer(player, cost); - econUser.addPoints(villagerType.getName(), transPts); + Purchase purchase = new Purchase(material, cost, itemPts, transPts, amount); + setItem(0, getSellItemHover(purchase), null); + setItem(1, confirm, player1 -> + sell2(player1, purchase, econUser, villagerType, oldPoints, price, bulk)); + player.updateInventory(); + } - removeItems(inventory, material, amount); + private void sell2(Player player, Purchase purchase, EconUser econUser, VillagerType villagerType, int oldPoints, Price price, boolean bulk) { + PlayerInventory inventory = player.getInventory(); + if (!inventory.containsAtLeast(new ItemStack(purchase.material()), purchase.amount())) { + player.sendMiniMessage(Config.NOT_ENOUGH_ITEMS, List.of( + Template.template("type", purchase.material().name()), + Template.template("amount", String.valueOf(purchase.amount())))); + return; + } + + Economy econ = VillagerUI.getInstance().getEconomy(); + econ.depositPlayer(player, purchase.price()); + econUser.addPoints(villagerType.getName(), purchase.totalPointCost()); + + removeItems(inventory, purchase.material(), purchase.amount()); int newPoints = econUser.getPointsMap().get(villagerType.getName()); player.sendMiniMessage(Config.SOLD_ITEM, List.of( - Template.template("amount", String.valueOf(amount)), - Template.template("item", StringUtils.capitalize(material.name() + Template.template("amount", String.valueOf(purchase.amount())), + Template.template("item", StringUtils.capitalize(purchase.material().name() .toLowerCase().replaceAll("_", " "))), - Template.template("price", String.valueOf(cost)), - Template.template("points", String.valueOf(transPts)), + Template.template("price", String.valueOf(purchase.price())), + Template.template("points", String.valueOf(purchase.totalPointCost())), Template.template("total_points", String.valueOf(newPoints)), Template.template("villager_name", villagerType.getDisplayName()) )); Bukkit.getServer().getPluginManager() - .callEvent(new SpawnShopEvent(player, amount, cost, material, - oldPoints, newPoints, false)); + .callEvent(new SpawnShopEvent(player, purchase, oldPoints, newPoints, false)); + sell(villagerType, player, purchase.material(), bulk ? 1 : purchase.amount(), price, bulk); + } + + private ItemStack getSellItemHover(Purchase purchase) { + ItemStack itemStack = new ItemStack(purchase.material()); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(miniMessage.deserialize(Config.TRANSACTION_ITEM_NAME, TemplateResolver.resolving( + Template.template("item_name", purchase.material().name()) + ))); + List lore = new ArrayList<>(); + for (String entry : Config.TRANSACTION_ITEM_DESCRIPTION) { + lore.add(miniMessage.deserialize(entry, TemplateResolver.resolving( + Template.template("amount", String.valueOf(purchase.amount())), + Template.template("price", String.valueOf(purchase.price())), + Template.template("points", String.valueOf(purchase.totalPointCost())) + ))); + } + itemMeta.lore(lore); + itemStack.setItemMeta(itemMeta); + return itemStack; } private void removeItems(Inventory inventory, Material material, int amount) { diff --git a/src/main/java/com/alttd/config/AbstractConfig.java b/src/main/java/com/alttd/config/AbstractConfig.java index b93c028..005b825 100644 --- a/src/main/java/com/alttd/config/AbstractConfig.java +++ b/src/main/java/com/alttd/config/AbstractConfig.java @@ -104,6 +104,11 @@ abstract class AbstractConfig { return yaml.getList(path, yaml.getList(path)); } + List getStringList(String path, List def) { + yaml.addDefault(path, def); + return yaml.getStringList(path); + } + @NonNull Map getMap(final @NonNull String path, final @Nullable Map def) { final ImmutableMap.Builder builder = ImmutableMap.builder(); diff --git a/src/main/java/com/alttd/config/Config.java b/src/main/java/com/alttd/config/Config.java index df673af..fdfbd8f 100644 --- a/src/main/java/com/alttd/config/Config.java +++ b/src/main/java/com/alttd/config/Config.java @@ -8,6 +8,7 @@ import org.bukkit.inventory.ItemStack; import java.io.File; import java.util.HashSet; +import java.util.List; import java.util.Set; public final class Config extends AbstractConfig { @@ -76,9 +77,18 @@ public final class Config extends AbstractConfig { } public static String VILLAGER_NAME = ""; + public static String CONFIRM_BUTTON = "Confirm"; + public static String TRANSACTION_ITEM_NAME = ""; + public static List TRANSACTION_ITEM_DESCRIPTION = List.of( + "Amount: ", + "Price: ", + "Points: "); - private static void loadIDKYET() {//TODO rename - VILLAGER_NAME = config.getString("idkyet.villager-name", VILLAGER_NAME); //TODO change path + private static void guiText() { + VILLAGER_NAME = config.getString("gui-text.villager-name", VILLAGER_NAME); + CONFIRM_BUTTON = config.getString("gui-text.confirm-button", CONFIRM_BUTTON); + TRANSACTION_ITEM_NAME = config.getString("gui-text.transaction-item-name", TRANSACTION_ITEM_NAME); + TRANSACTION_ITEM_DESCRIPTION = config.getStringList("gui-text.transaction-item-description", TRANSACTION_ITEM_DESCRIPTION); } public static String NOT_ENOUGH_MONEY = "You only have $, you need at least $ for this purchase."; diff --git a/src/main/java/com/alttd/events/SpawnShopEvent.java b/src/main/java/com/alttd/events/SpawnShopEvent.java index e2f2327..da5c36a 100644 --- a/src/main/java/com/alttd/events/SpawnShopEvent.java +++ b/src/main/java/com/alttd/events/SpawnShopEvent.java @@ -1,5 +1,6 @@ package com.alttd.events; +import com.alttd.objects.Purchase; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.Event; @@ -16,12 +17,11 @@ public final class SpawnShopEvent extends Event { private final boolean buy; private static final HandlerList handlers = new HandlerList(); - public SpawnShopEvent(Player player, int amount, double price, Material item, - int pointsBefore, int pointsAfter, boolean buy) { + public SpawnShopEvent(Player player, Purchase purchase, int pointsBefore, int pointsAfter, boolean buy) { this.player = player; - this.amount = amount; - this.price = price; - this.item = item; + this.amount = purchase.amount(); + this.price = purchase.price(); + this.item = purchase.material(); this.pointsBefore = pointsBefore; this.pointsAfter = pointsAfter; this.buy = buy; diff --git a/src/main/java/com/alttd/objects/Purchase.java b/src/main/java/com/alttd/objects/Purchase.java new file mode 100644 index 0000000..f84a9f7 --- /dev/null +++ b/src/main/java/com/alttd/objects/Purchase.java @@ -0,0 +1,6 @@ +package com.alttd.objects; + +import org.bukkit.Material; + +public record Purchase(Material material, double price, int singlePointCost, int totalPointCost, int amount) { +}