diff --git a/src/main/java/com/alttd/fishingevent/config/Messages.java b/src/main/java/com/alttd/fishingevent/config/Messages.java index d4b5679..1b70b8c 100644 --- a/src/main/java/com/alttd/fishingevent/config/Messages.java +++ b/src/main/java/com/alttd/fishingevent/config/Messages.java @@ -50,6 +50,7 @@ public class Messages extends AbstractConfig { public static String NO_FISHING_ROD = "You need to have a fishing rod to use this NPC"; public static String UPGRADE_GUI_NAME = "Upgrade GUI"; public static String PRIZES_GUI_NAME = "Prizes GUI"; + public static String SELL_GUI_NAME = "Sell GUI";; public static String NOT_INITIALIZED = "There was an error initializing this GUI, please contact staff"; @SuppressWarnings("unused") @@ -57,6 +58,7 @@ public class Messages extends AbstractConfig { NO_FISHING_ROD = config.getString(prefix, "no-fishing-rod", NO_FISHING_ROD); UPGRADE_GUI_NAME = config.getString(prefix, "upgrade-gui-name", UPGRADE_GUI_NAME); PRIZES_GUI_NAME = config.getString(prefix, "prizes-gui-name", PRIZES_GUI_NAME); + SELL_GUI_NAME = config.getString(prefix, "sell-gui-name", SELL_GUI_NAME); NOT_INITIALIZED = config.getString(prefix, "not-initialized", NOT_INITIALIZED); } } @@ -98,10 +100,12 @@ public class Messages extends AbstractConfig { public static class OTHER_ERRORS { private static final String prefix = "other-errors."; public static String UNABLE_TO_CREATE_FISH = "Unable to create fish, please contact a staff member"; + public static String UNABLE_TO_SELL_ITEMS = "Unable to sell items, please contact a staff member"; @SuppressWarnings("unused") private static void load() { UNABLE_TO_CREATE_FISH = config.getString(prefix, "unable-to-create-fish", UNABLE_TO_CREATE_FISH); + UNABLE_TO_SELL_ITEMS = config.getString(prefix, "unable-to-sell-items", UNABLE_TO_SELL_ITEMS); } } } diff --git a/src/main/java/com/alttd/fishingevent/gui/GUI.java b/src/main/java/com/alttd/fishingevent/gui/GUI.java index c5b7ca3..9c5c0c5 100644 --- a/src/main/java/com/alttd/fishingevent/gui/GUI.java +++ b/src/main/java/com/alttd/fishingevent/gui/GUI.java @@ -11,7 +11,7 @@ import java.util.HashMap; import java.util.UUID; public abstract class GUI { - HashMap GUIByUUID = new HashMap<>(); + static HashMap GUIByUUID = new HashMap<>(); protected final Inventory inventory; protected final HashMap guiActions; @@ -44,4 +44,8 @@ public abstract class GUI { GUIByUUID.put(player.getUniqueId(), this); return true; } + + protected abstract void closed(); + + protected abstract boolean canMoveItems(); } diff --git a/src/main/java/com/alttd/fishingevent/gui/GUIListener.java b/src/main/java/com/alttd/fishingevent/gui/GUIListener.java new file mode 100644 index 0000000..8f199e4 --- /dev/null +++ b/src/main/java/com/alttd/fishingevent/gui/GUIListener.java @@ -0,0 +1,65 @@ +package com.alttd.fishingevent.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 { + + /** + * Handles clicking inside a gui + * @param event gui click event + */ + @EventHandler + public void onClick(InventoryClickEvent event){ + if (!(event.getWhoClicked() instanceof Player player)) return; + + GUI gui = GUI.GUIByUUID.get(player.getUniqueId()); + if (gui == null) + return; + if (gui.getInventory() != null) { + if (!gui.getInventory().equals(event.getInventory())) + return; + } + else + return; + + if (gui.canMoveItems()) + 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); + } + + @EventHandler + public void onClose(InventoryCloseEvent event) { + HumanEntity player = event.getPlayer(); + GUI gui = GUI.GUIByUUID.get(player.getUniqueId()); + + gui.closed(); + + GUI.GUIByUUID.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event){ + GUI.GUIByUUID.remove(event.getPlayer().getUniqueId()); + } + +} diff --git a/src/main/java/com/alttd/fishingevent/gui/windows/PrizesWindow.java b/src/main/java/com/alttd/fishingevent/gui/windows/PrizesWindow.java index a0c8fe5..877031c 100644 --- a/src/main/java/com/alttd/fishingevent/gui/windows/PrizesWindow.java +++ b/src/main/java/com/alttd/fishingevent/gui/windows/PrizesWindow.java @@ -33,4 +33,14 @@ public class PrizesWindow extends GUI { public boolean canOpen() { return true; } + + @Override + protected void closed() { + + } + + @Override + protected boolean canMoveItems() { + return false; + } } diff --git a/src/main/java/com/alttd/fishingevent/gui/windows/SellWindow.java b/src/main/java/com/alttd/fishingevent/gui/windows/SellWindow.java new file mode 100644 index 0000000..a1f6bab --- /dev/null +++ b/src/main/java/com/alttd/fishingevent/gui/windows/SellWindow.java @@ -0,0 +1,96 @@ +package com.alttd.fishingevent.gui.windows; + +import com.alttd.fishingevent.FishingEvent; +import com.alttd.fishingevent.config.Messages; +import com.alttd.fishingevent.gui.GUI; +import com.alttd.fishingevent.points.PointsManagement; +import com.alttd.fishingevent.util.Logger; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.*; + +public class SellWindow extends GUI { + + private final Logger logger; + private final FishingEvent fishingEvent; + private final Player player; + + public SellWindow(FishingEvent fishingEvent, Player player, Logger logger) { + super(InventoryType.CHEST, MiniMessage.miniMessage().deserialize(Messages.GUI.SELL_GUI_NAME)); + this.fishingEvent = fishingEvent; + this.logger = logger; + this.player = player; + } + + + @Override + public boolean canOpen() { + return true; + } + + @Override + protected void closed() { + Optional optionalNamespacedKey = getNamespacedKey(); + if (optionalNamespacedKey.isEmpty()) { + player.getInventory().addItem(Arrays.stream(getInventory().getContents()) + .filter(Objects::nonNull) + .toArray(ItemStack[]::new)) + .values() + .forEach(item -> player.getWorld().dropItem(player.getLocation(), item)); + player.sendMiniMessage(Messages.OTHER_ERRORS.UNABLE_TO_SELL_ITEMS, null); + return; + } + + PointsManagement pointsManagement = PointsManagement.getInstance(); + NamespacedKey namespacedKey = optionalNamespacedKey.get(); + List itemsToMoveBack = new ArrayList<>(); + + for (ItemStack content : getInventory().getContents()) { + if (content == null) { + continue; + } + int points = getPoints(content, namespacedKey); + if (points == -1) { + itemsToMoveBack.add(content); + } else { + pointsManagement.addPoints(player.getUniqueId(), points); + } + } + player.getInventory().addItem(itemsToMoveBack.toArray(ItemStack[]::new)).values() + .forEach(item -> player.getWorld().dropItem(player.getLocation(), item)); + } + + /** + * @param itemStack ItemStack to check + * @return -1 if it has no points, otherwise returns points + */ + public int getPoints(ItemStack itemStack, NamespacedKey namespacedKey) { + ItemMeta itemMeta = itemStack.getItemMeta(); + Integer integer = itemMeta.getPersistentDataContainer().get(namespacedKey, PersistentDataType.INTEGER); + return integer == null ? -1 : integer; + } + + private Optional getNamespacedKey() { + try { + NamespacedKey namespacedKey = NamespacedKey.fromString("points", fishingEvent); + if (namespacedKey != null) + return Optional.of(namespacedKey); + } catch (Exception e) { + logger.warning("Error while creating namespaced key for points"); + return Optional.empty(); + } + logger.warning("Error while creating namespaced key for points"); + return Optional.empty(); + } + + @Override + protected boolean canMoveItems() { + return true; + } +} diff --git a/src/main/java/com/alttd/fishingevent/gui/windows/UpgradeWindow.java b/src/main/java/com/alttd/fishingevent/gui/windows/UpgradeWindow.java index 3e5bdcf..e28fafa 100644 --- a/src/main/java/com/alttd/fishingevent/gui/windows/UpgradeWindow.java +++ b/src/main/java/com/alttd/fishingevent/gui/windows/UpgradeWindow.java @@ -167,4 +167,14 @@ public class UpgradeWindow extends GUI { public boolean canOpen() { return canOpen; } + + @Override + protected void closed() { + + } + + @Override + protected boolean canMoveItems() { + return false; + } } diff --git a/src/main/java/com/alttd/fishingevent/npc/types/SellNPC.java b/src/main/java/com/alttd/fishingevent/npc/types/SellNPC.java index 1490b53..ccda976 100644 --- a/src/main/java/com/alttd/fishingevent/npc/types/SellNPC.java +++ b/src/main/java/com/alttd/fishingevent/npc/types/SellNPC.java @@ -1,4 +1,86 @@ package com.alttd.fishingevent.npc.types; -public class SellNPC { +import com.alttd.fishingevent.FishingEvent; +import com.alttd.fishingevent.config.Messages; +import com.alttd.fishingevent.gui.windows.SellWindow; +import com.alttd.fishingevent.gui.windows.UpgradeWindow; +import com.alttd.fishingevent.npc.LibNPC; +import com.alttd.fishingevent.npc.NPC; +import com.alttd.fishingevent.objects.EnchantmentTrack; +import com.alttd.fishingevent.util.Logger; +import com.alttd.fishingevent.util.NPCCreateData; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.List; + +public class SellNPC extends LibNPC implements NPC { + + private final NPCCreateData npcCreateData; + private final Logger logger; + private boolean isSpawned = false; + private FishingEvent fishingEvent = null; + + public SellNPC(Logger logger, NPCCreateData npcCreateData) { + this.npcCreateData = npcCreateData; + this.logger = logger; + } + + @Override + public String getName() { + return npcCreateData.name(); + } + + @Override + public void spawnNPC(FishingEvent fishingEvent, Location location) { + defaultSpawnNPC(fishingEvent, location, npcCreateData, logger, this); + this.fishingEvent = fishingEvent; + isSpawned = true; + } + + @Override + public void leftClick(Player player) { + player.sendMiniMessage(Messages.NPC.UPGRADE_NPC_LEFT_CLICK_MESSAGE, Placeholder.component("player", player.name())); + } + + @Override + public void rightClick(Player player) { + if (fishingEvent == null) { + player.sendMiniMessage(Messages.GUI.NOT_INITIALIZED, null); + return; + } + SellWindow sellWindow = new SellWindow(fishingEvent, player, logger); + if (!sellWindow.canOpen()) { + player.sendMiniMessage(Messages.GUI.NO_FISHING_ROD, null); + return; + } + new BukkitRunnable() { + @Override + public void run() { + sellWindow.open(player); + } + }.runTaskAsynchronously(fishingEvent); + } + + @Override + public boolean showToPlayer(Player player) { + return super.showToPlayer(player); + } + + @Override + public boolean hideFromPlayer(Player player) { + return super.hideFromPlayer(player); + } + + @Override + public boolean isSpawned(FishingEvent fishingEvent) { + return isSpawned; + } + + @Override + public void updateSkin(Player player) { + super.updateSkin(player); + } }