diff --git a/server/src/main/java/dev/plex/command/impl/DebugCMD.java b/server/src/main/java/dev/plex/command/impl/DebugCMD.java index 5b7c91b..2e1b041 100644 --- a/server/src/main/java/dev/plex/command/impl/DebugCMD.java +++ b/server/src/main/java/dev/plex/command/impl/DebugCMD.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList; import dev.plex.command.PlexCommand; import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandPermissions; +import dev.plex.menu.impl.MaterialMenu; import dev.plex.util.GameRuleUtil; import dev.plex.util.PlexLog; import dev.plex.util.PlexUtils; @@ -20,6 +21,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.List; import java.util.Locale; +import java.util.concurrent.CompletableFuture; @CommandParameters(name = "pdebug", description = "Plex's debug command", usage = "/ | redis-reset | gamerules>") @CommandPermissions(permission = "plex.debug") @@ -76,6 +78,15 @@ public class DebugCMD extends PlexCommand return mmString("Aliases for " + commandName + " are: " + Arrays.toString(command.getAliases().toArray(new String[0]))); } } + if (args[0].equalsIgnoreCase("pagination")) + { + if (playerSender == null) + { + return messageComponent("noPermissionConsole"); + } + new MaterialMenu().open(playerSender); + return null; + } return usage(); } diff --git a/server/src/main/java/dev/plex/command/impl/PunishmentsCMD.java b/server/src/main/java/dev/plex/command/impl/PunishmentsCMD.java index b3e811b..451bb80 100644 --- a/server/src/main/java/dev/plex/command/impl/PunishmentsCMD.java +++ b/server/src/main/java/dev/plex/command/impl/PunishmentsCMD.java @@ -5,8 +5,8 @@ import dev.plex.command.PlexCommand; import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.source.RequiredCommandSource; -import dev.plex.menu.PunishmentMenu; +import dev.plex.menu.impl.PunishmentMenu; import dev.plex.util.PlexUtils; import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; @@ -23,7 +23,7 @@ public class PunishmentsCMD extends PlexCommand @Override protected Component execute(@NotNull CommandSender sender, @Nullable Player playerSender, String[] args) { - new PunishmentMenu().openInv(playerSender, 0); + new PunishmentMenu().open(playerSender); return null; } diff --git a/server/src/main/java/dev/plex/command/impl/ToggleCMD.java b/server/src/main/java/dev/plex/command/impl/ToggleCMD.java index c8539f0..6ec561b 100644 --- a/server/src/main/java/dev/plex/command/impl/ToggleCMD.java +++ b/server/src/main/java/dev/plex/command/impl/ToggleCMD.java @@ -5,7 +5,7 @@ import dev.plex.command.PlexCommand; import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.source.RequiredCommandSource; -import dev.plex.menu.ToggleMenu; +import dev.plex.menu.impl.ToggleMenu; import dev.plex.util.PlexUtils; import net.kyori.adventure.text.Component; @@ -59,7 +59,7 @@ public class ToggleCMD extends PlexCommand } } } - new ToggleMenu().openInv(playerSender, 0); + new ToggleMenu().open(playerSender); return null; } diff --git a/server/src/main/java/dev/plex/listener/impl/MenuListener.java b/server/src/main/java/dev/plex/listener/impl/MenuListener.java new file mode 100644 index 0000000..852cef0 --- /dev/null +++ b/server/src/main/java/dev/plex/listener/impl/MenuListener.java @@ -0,0 +1,70 @@ +package dev.plex.listener.impl; + +import dev.plex.listener.PlexListener; +import dev.plex.menu.AbstractMenu; +import dev.plex.menu.pagination.PageableMenu; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.meta.ItemMeta; + +/** + * @author Taah + * @since 7:01 AM [02-09-2023] + */ +public class MenuListener extends PlexListener +{ + @EventHandler(priority = EventPriority.LOWEST) + public void onClick(InventoryClickEvent event) + { + if (event.getClickedInventory() == null) + { + return; + } + + if (event.getCurrentItem() == null) + { + return; + } + + if (!(event.getWhoClicked() instanceof Player player)) + { + return; + } + + AbstractMenu.INVENTORIES.entrySet().stream().filter(entry -> entry.getKey().equals(event.getView().title())) + .findFirst() + .ifPresent(entry -> + { + if (entry.getValue() instanceof PageableMenu.Page page) + { + final ItemMeta meta = event.getCurrentItem().getItemMeta(); + if (meta != null && meta.displayName() != null) + { + if (meta.displayName().equals(PageableMenu.PREVIOUS.getItemMeta().displayName())) + { + page.parent().currentPage(page.parent().currentPage() - 1); + page.parent().open(player, page.parent().currentPage()); + event.setCancelled(true); + return; + } + else if (meta.displayName().equals(PageableMenu.NEXT.getItemMeta().displayName())) + { + page.parent().currentPage(page.parent().currentPage() + 1); + page.parent().open(player, page.parent().currentPage()); + event.setCancelled(true); + return; + } + else if (meta.displayName().equals(PageableMenu.CLOSE.getItemMeta().displayName())) + { + player.closeInventory(); + event.setCancelled(true); + return; + } + } + } + event.setCancelled(entry.getValue().onClick(event.getView(), event.getClickedInventory(), player, event.getCurrentItem())); + }); + } +} diff --git a/server/src/main/java/dev/plex/menu/AbstractMenu.java b/server/src/main/java/dev/plex/menu/AbstractMenu.java new file mode 100644 index 0000000..77be4b0 --- /dev/null +++ b/server/src/main/java/dev/plex/menu/AbstractMenu.java @@ -0,0 +1,66 @@ +package dev.plex.menu; + +import com.google.common.collect.Maps; +import dev.plex.util.minimessage.SafeMiniMessage; +import lombok.Getter; +import lombok.experimental.Accessors; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.ItemStack; + +import java.util.Map; + +/** + * @author Taah + * @since 6:49 AM [02-09-2023] + */ + +@Getter +@Accessors(fluent = true) +public abstract class AbstractMenu +{ + public static final Map INVENTORIES = Maps.newHashMap(); + private final Component name; + private final Inventory inventory; + + public AbstractMenu(Component name, Rows rows) + { + this.name = name; + this.inventory = Bukkit.createInventory(null, rows.slots, name); + + INVENTORIES.put(name, this); + } + + public AbstractMenu(String name, Rows rows) + { + this(SafeMiniMessage.mmDeserializeWithoutEvents(name), rows); + } + + public void open(Player player) + { + player.openInventory(this.inventory); + } + + public abstract boolean onClick(InventoryView view, Inventory inventory, Player player, ItemStack clicked); + + public enum Rows + { + ONE(9), TWO(18), THREE(27), FOUR(36), FIVE(45), SIX(54); + + private final int slots; + + Rows(int slots) + { + this.slots = slots; + } + + public int slots() + { + return this.slots; + } + } + +} diff --git a/server/src/main/java/dev/plex/menu/PunishedPlayerMenu.java b/server/src/main/java/dev/plex/menu/PunishedPlayerMenu.java deleted file mode 100644 index ea2d47d..0000000 --- a/server/src/main/java/dev/plex/menu/PunishedPlayerMenu.java +++ /dev/null @@ -1,192 +0,0 @@ -package dev.plex.menu; - -import com.google.common.collect.Lists; -import dev.plex.Plex; -import dev.plex.cache.DataUtils; -import dev.plex.player.PlexPlayer; -import dev.plex.punishment.Punishment; -import dev.plex.util.PlexUtils; -import dev.plex.util.menu.AbstractMenu; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.SkullMeta; - -import java.util.Collections; -import java.util.List; - -public class PunishedPlayerMenu extends AbstractMenu -{ - private final PlexPlayer punishedPlayer; - - private final List inventories = Lists.newArrayList(); - - public PunishedPlayerMenu(PlexPlayer player) - { - super("§c§lPunishments"); - this.punishedPlayer = player; - for (int i = 0; i <= punishedPlayer.getPunishments().size() / 53; i++) - { - Inventory inventory = Bukkit.createInventory(null, 54, PlexUtils.mmDeserialize("Punishments Page " + (i + 1))); - ItemStack nextPage = new ItemStack(Material.FEATHER); - ItemMeta meta = nextPage.getItemMeta(); - meta.displayName(Component.text("Next Page").color(NamedTextColor.LIGHT_PURPLE)); - nextPage.setItemMeta(meta); - - ItemStack previousPage = new ItemStack(Material.FEATHER); - ItemMeta meta2 = previousPage.getItemMeta(); - meta2.displayName(Component.text("Previous Page").color(NamedTextColor.LIGHT_PURPLE)); - previousPage.setItemMeta(meta2); - - ItemStack back = new ItemStack(Material.BARRIER); - ItemMeta meta3 = back.getItemMeta(); - meta3.displayName(Component.text("Back").color(NamedTextColor.LIGHT_PURPLE)); - back.setItemMeta(meta3); - - inventory.setItem(50, nextPage); - inventory.setItem(49, back); - inventory.setItem(48, previousPage); - inventories.add(inventory); - } - } - - public List getInventory() - { - return inventories; - } - - public void openInv(Player player, int index) - { - int currentItemIndex = 0; - int currentInvIndex = 0; - for (Punishment punishment : punishedPlayer.getPunishments()) - { - Inventory inv = inventories.get(currentInvIndex); - if (currentInvIndex > inventories.size() - 1) - { - break; - } - - if (currentItemIndex == inv.getSize() - 1) - { - currentInvIndex++; - currentItemIndex = 0; - inv = inventories.get(currentInvIndex); - } - - - ItemStack item = new ItemStack(Material.NETHER_STAR); - ItemMeta meta = item.getItemMeta(); - meta.displayName(Component.text(punishment.getType().name().toUpperCase()).color(NamedTextColor.RED)); - meta.lore(Collections.singletonList(Component.text("Reason: ").color(NamedTextColor.YELLOW).append(Component.text(punishment.getReason()).color(NamedTextColor.GRAY)))); - item.setItemMeta(meta); - - inv.setItem(currentItemIndex, item); - - currentItemIndex++; - } - player.openInventory(inventories.get(index)); - } - - @EventHandler - public void onClick(InventoryClickEvent event) - { - if (event.getClickedInventory() == null) - { - return; - } - Inventory inv = event.getClickedInventory(); - if (!isValidInventory(inv)) - { - return; - } - if (event.getCurrentItem() == null) - { - return; - } - ItemStack item = event.getCurrentItem(); - if (!item.hasItemMeta()) - { - return; - } - if (!item.getItemMeta().hasDisplayName()) - { - return; - } - event.setCancelled(true); - if (item.getType() == Material.FEATHER) - { - if (item.getItemMeta().displayName().equals(Component.text("Next Page").color(NamedTextColor.LIGHT_PURPLE))) - { - if (getCurrentInventoryIndex(inv) + 1 > inventories.size() - 1) - { - return; - } - if (inventories.get(getCurrentInventoryIndex(inv) + 1).getContents().length == 0) - { - return; - } - openInv((Player) event.getWhoClicked(), getCurrentInventoryIndex(inv) + 1); - } - else if (item.getItemMeta().displayName().equals(Component.text("Previous Page").color(NamedTextColor.LIGHT_PURPLE))) - { - if (getCurrentInventoryIndex(inv) - 1 < 0) - { - return; - } - if (getCurrentInventoryIndex(inv) - 1 > inventories.size() - 1) - { - return; - } - if (inventories.get(getCurrentInventoryIndex(inv) - 1).getContents().length == 0) - { - return; - } - openInv((Player) event.getWhoClicked(), getCurrentInventoryIndex(inv) - 1); - } - - } - else if (item.getType() == Material.BARRIER) - { - new PunishmentMenu().openInv((Player) event.getWhoClicked(), 0); - } - else if (item.getType() == Material.PLAYER_HEAD) - { - SkullMeta meta = (SkullMeta) item.getItemMeta(); - OfflinePlayer player = meta.getOwningPlayer(); - assert player != null; - PlexPlayer punishedPlayer = DataUtils.getPlayer(player.getUniqueId()) == null ? null : Plex.get().getPlayerCache().getPlexPlayer(player.getUniqueId()); - if (punishedPlayer == null) - { - event.getWhoClicked().sendMessage(Component.text("This player does not exist. Try doing /punishments instead.").color(NamedTextColor.RED)); - event.getWhoClicked().closeInventory(); - } - } - - } - - public int getCurrentInventoryIndex(Inventory inventory) - { - for (int i = 0; i <= inventories.size() - 1; i++) - { - if (inventories.get(i).hashCode() == inventory.hashCode()) - { - return i; - } - } - return 0; - } - - private boolean isValidInventory(Inventory inventory) - { - return inventories.contains(inventory); - } -} diff --git a/server/src/main/java/dev/plex/menu/PunishmentMenu.java b/server/src/main/java/dev/plex/menu/PunishmentMenu.java deleted file mode 100644 index 6ab779b..0000000 --- a/server/src/main/java/dev/plex/menu/PunishmentMenu.java +++ /dev/null @@ -1,179 +0,0 @@ -package dev.plex.menu; - -import com.google.common.collect.Lists; -import dev.plex.cache.DataUtils; -import dev.plex.player.PlexPlayer; -import dev.plex.util.PlexUtils; -import dev.plex.util.menu.AbstractMenu; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.SkullMeta; - -import java.util.List; - -public class PunishmentMenu extends AbstractMenu -{ - - private final List inventories = Lists.newArrayList(); - - public PunishmentMenu() - { - super("§c§lPunishments"); - for (int i = 0; i <= Bukkit.getOnlinePlayers().size() / 53; i++) - { - Inventory inventory = Bukkit.createInventory(null, 54, PlexUtils.mmDeserialize("Punishments Page " + (i + 1))); - ItemStack nextPage = new ItemStack(Material.FEATHER); - ItemMeta meta = nextPage.getItemMeta(); - meta.displayName(PlexUtils.mmDeserialize("Next Page")); - nextPage.setItemMeta(meta); - - ItemStack previousPage = new ItemStack(Material.FEATHER); - ItemMeta meta2 = previousPage.getItemMeta(); - meta2.displayName(PlexUtils.mmDeserialize("Previous Page")); - previousPage.setItemMeta(meta2); - - inventory.setItem(50, nextPage); - inventory.setItem(48, previousPage); - inventories.add(inventory); - } - } - - public List getInventory() - { - return inventories; - } - - public void openInv(Player player, int index) - { - int currentItemIndex = 0; - int currentInvIndex = 0; - for (Player players : Bukkit.getOnlinePlayers()) - { - Inventory inv = inventories.get(currentInvIndex); - if (currentInvIndex > inventories.size() - 1) - { - break; - } - - if (currentItemIndex == inv.getSize() - 1) - { - currentInvIndex++; - currentItemIndex = 0; - inv = inventories.get(currentInvIndex); - } - - - ItemStack item = new ItemStack(Material.PLAYER_HEAD); - SkullMeta meta = (SkullMeta) item.getItemMeta(); - meta.setOwningPlayer(players); - meta.displayName(PlexUtils.mmDeserialize("" + players.getName())); - item.setItemMeta(meta); - - inv.setItem(currentItemIndex, item); - - currentItemIndex++; - } - player.openInventory(inventories.get(index)); - } - - @EventHandler - public void onClick(InventoryClickEvent event) - { - if (event.getClickedInventory() == null) - { - return; - } - Inventory inv = event.getClickedInventory(); - if (!isValidInventory(inv)) - { - return; - } - if (event.getCurrentItem() == null) - { - return; - } - if (!event.getCurrentItem().hasItemMeta()) - { - return; - } - if (!event.getCurrentItem().getItemMeta().hasDisplayName()) - { - return; - } - ItemStack item = event.getCurrentItem(); - event.setCancelled(true); - if (item.getType() == Material.FEATHER) - { - if (item.getItemMeta().displayName().equals(PlexUtils.mmDeserialize("Next Page"))) - { - if (getCurrentInventoryIndex(inv) + 1 > inventories.size() - 1) - { - return; - } - if (inventories.get(getCurrentInventoryIndex(inv) + 1).getContents().length == 0) - { - return; - } - openInv((Player) event.getWhoClicked(), getCurrentInventoryIndex(inv) + 1); - } - else if (item.getItemMeta().displayName().equals(PlexUtils.mmDeserialize("Previous Page"))) - { - if (getCurrentInventoryIndex(inv) - 1 < 0) - { - return; - } - if (getCurrentInventoryIndex(inv) - 1 > inventories.size() - 1) - { - return; - } - if (inventories.get(getCurrentInventoryIndex(inv) - 1).getContents().length == 0) - { - return; - } - openInv((Player) event.getWhoClicked(), getCurrentInventoryIndex(inv) - 1); - } - - } - else if (item.getType() == Material.PLAYER_HEAD) - { - SkullMeta meta = (SkullMeta) item.getItemMeta(); - OfflinePlayer player = meta.getOwningPlayer(); - assert player != null; - PlexPlayer punishedPlayer = DataUtils.getPlayer(player.getUniqueId()); - if (punishedPlayer == null) - { - event.getWhoClicked().sendMessage(Component.text("This player does not exist. Try doing /punishments instead.").color(NamedTextColor.RED)); - event.getWhoClicked().closeInventory(); - return; - } - new PunishedPlayerMenu(punishedPlayer).openInv((Player) event.getWhoClicked(), 0); - } - - } - - public int getCurrentInventoryIndex(Inventory inventory) - { - for (int i = 0; i <= inventories.size() - 1; i++) - { - if (inventories.get(i).hashCode() == inventory.hashCode()) - { - return i; - } - } - return 0; - } - - private boolean isValidInventory(Inventory inventory) - { - return inventories.contains(inventory); - } -} diff --git a/server/src/main/java/dev/plex/menu/ToggleMenu.java b/server/src/main/java/dev/plex/menu/ToggleMenu.java deleted file mode 100644 index faedebc..0000000 --- a/server/src/main/java/dev/plex/menu/ToggleMenu.java +++ /dev/null @@ -1,146 +0,0 @@ -package dev.plex.menu; - -import com.google.common.collect.Lists; -import dev.plex.PlexBase; -import dev.plex.util.PlexUtils; -import dev.plex.util.menu.AbstractMenu; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.List; - -public class ToggleMenu extends AbstractMenu implements PlexBase -{ - private final List inventories = Lists.newArrayList(); - - public ToggleMenu() - { - super("§a§lToggles"); - Inventory inventory = Bukkit.createInventory(null, 9, PlexUtils.mmDeserialize("Toggles")); - resetExplosionItem(inventory); - resetFluidspreadItem(inventory); - resetDropsItem(inventory); - resetRedstoneItem(inventory); - inventories.add(inventory); - } - - public void openInv(Player player, int index) - { - player.openInventory(inventories.get(index)); - } - - @EventHandler - public void onClick(InventoryClickEvent event) - { - if (event.getClickedInventory() == null) - { - return; - } - Inventory inv = event.getClickedInventory(); - if (!isValidInventory(inv)) - { - return; - } - if (event.getCurrentItem() == null) - { - return; - } - if (!event.getCurrentItem().hasItemMeta()) - { - return; - } - if (!event.getCurrentItem().getItemMeta().hasDisplayName()) - { - return; - } - ItemStack item = event.getCurrentItem(); - event.setCancelled(true); - if (item.getType() == Material.TNT) - { - plugin.toggles.set("explosions", !plugin.toggles.getBoolean("explosions")); - resetExplosionItem(inv); - event.getWhoClicked().sendMessage(PlexUtils.mmDeserialize("Toggled explosions.")); - } - if (item.getType() == Material.WATER_BUCKET) - { - plugin.toggles.set("fluidspread", !plugin.toggles.getBoolean("fluidspread")); - resetFluidspreadItem(inv); - event.getWhoClicked().sendMessage(PlexUtils.mmDeserialize("Toggled fluid spread.")); - } - if (item.getType() == Material.FEATHER) - { - plugin.toggles.set("drops", !plugin.toggles.getBoolean("drops")); - resetDropsItem(inv); - event.getWhoClicked().sendMessage(PlexUtils.mmDeserialize("Toggled drops.")); - } - if (item.getType() == Material.REDSTONE) - { - plugin.toggles.set("redstone", !plugin.toggles.getBoolean("redstone")); - resetRedstoneItem(inv); - event.getWhoClicked().sendMessage(PlexUtils.mmDeserialize("Toggled redstone.")); - } - } - - public int getCurrentInventoryIndex(Inventory inventory) - { - for (int i = 0; i <= inventories.size() - 1; i++) - { - if (inventories.get(i).hashCode() == inventory.hashCode()) - { - return i; - } - } - return 0; - } - - private boolean isValidInventory(Inventory inventory) - { - return inventories.contains(inventory); - } - - private void resetExplosionItem(Inventory inventory) - { - ItemStack explosions = new ItemStack(Material.TNT); - ItemMeta explosionsItemMeta = explosions.getItemMeta(); - explosionsItemMeta.displayName(PlexUtils.mmDeserialize("Toggle explosions")); - explosionsItemMeta.lore(List.of(PlexUtils.mmDeserialize("Explosions are " + (plugin.toggles.getBoolean("explosions") ? "enabled" : "disabled")))); - explosions.setItemMeta(explosionsItemMeta); - inventory.setItem(0, explosions); - } - - private void resetFluidspreadItem(Inventory inventory) - { - ItemStack water = new ItemStack(Material.WATER_BUCKET); - ItemMeta waterItemMeta = water.getItemMeta(); - waterItemMeta.displayName(PlexUtils.mmDeserialize("Toggle fluid spread")); - waterItemMeta.lore(List.of(PlexUtils.mmDeserialize("Fluid spread is " + (plugin.toggles.getBoolean("fluidspread") ? "enabled" : "disabled")))); - water.setItemMeta(waterItemMeta); - inventory.setItem(1, water); - } - - private void resetDropsItem(Inventory inventory) - { - ItemStack feather = new ItemStack(Material.FEATHER); - ItemMeta featherItemMeta = feather.getItemMeta(); - featherItemMeta.displayName(PlexUtils.mmDeserialize("Toggle drops")); - featherItemMeta.lore(List.of(PlexUtils.mmDeserialize("Drops are " + (plugin.toggles.getBoolean("drops") ? "enabled" : "disabled")))); - feather.setItemMeta(featherItemMeta); - inventory.setItem(2, feather); - } - - private void resetRedstoneItem(Inventory inventory) - { - ItemStack redstone = new ItemStack(Material.REDSTONE); - ItemMeta redstoneItemMeta = redstone.getItemMeta(); - redstoneItemMeta.displayName(PlexUtils.mmDeserialize("Redstone")); - redstoneItemMeta.lore(List.of(PlexUtils.mmDeserialize("Redstone is " + (plugin.toggles.getBoolean("redstone") ? "enabled" : "disabled")))); - redstone.setItemMeta(redstoneItemMeta); - inventory.setItem(3, redstone); - } -} diff --git a/server/src/main/java/dev/plex/menu/impl/MaterialMenu.java b/server/src/main/java/dev/plex/menu/impl/MaterialMenu.java new file mode 100644 index 0000000..9267795 --- /dev/null +++ b/server/src/main/java/dev/plex/menu/impl/MaterialMenu.java @@ -0,0 +1,40 @@ +package dev.plex.menu.impl; + +import dev.plex.menu.AbstractMenu; +import dev.plex.menu.pagination.PageableMenu; +import dev.plex.util.item.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; +import java.util.List; + +/** + * @author Taah + * @since 8:44 AM [02-09-2023] + */ +public class MaterialMenu extends PageableMenu +{ + public MaterialMenu() + { + super("Materials", AbstractMenu.Rows.SIX); + onClick((inventoryView, inventory, player, itemStack) -> + { + player.sendMessage(itemStack.displayName()); + return true; + }); + this.init(); + } + + @Override + protected ItemStack toItem(Material object) + { + return new ItemBuilder(object).displayName("" + object.name()).build(); + } + + @Override + protected List list() + { + return Arrays.stream(Material.values()).filter(material -> !material.isAir()).toList(); + } +} diff --git a/server/src/main/java/dev/plex/menu/impl/PunishedPlayerMenu.java b/server/src/main/java/dev/plex/menu/impl/PunishedPlayerMenu.java new file mode 100644 index 0000000..256edd6 --- /dev/null +++ b/server/src/main/java/dev/plex/menu/impl/PunishedPlayerMenu.java @@ -0,0 +1,37 @@ +package dev.plex.menu.impl; + +import dev.plex.Plex; +import dev.plex.menu.AbstractMenu; +import dev.plex.menu.pagination.PageableMenu; +import dev.plex.player.PlexPlayer; +import dev.plex.punishment.Punishment; +import dev.plex.util.TimeUtils; +import dev.plex.util.item.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class PunishedPlayerMenu extends PageableMenu +{ + private final PlexPlayer punishedPlayer; + public PunishedPlayerMenu(PlexPlayer player) + { + super("Punishments - " + player.getName(), AbstractMenu.Rows.SIX); + this.punishedPlayer = player; + onClick((inventoryView, itemStacks, player1, itemStack) -> true); + this.init(); + } + + @Override + protected ItemStack toItem(Punishment object) + { + return new ItemBuilder(Material.PAPER).displayName("" + object.getType().name()).lore("By: " + (object.getPunisher() == null ? "CONSOLE" : Plex.get().getSqlPlayerData().getNameByUUID(object.getPunished())), "Expire(d/s): " + TimeUtils.useTimezone(object.getEndDate()), "Reason: " + object.getReason()).build(); + } + + @Override + protected List list() + { + return this.punishedPlayer.getPunishments(); + } +} diff --git a/server/src/main/java/dev/plex/menu/impl/PunishmentMenu.java b/server/src/main/java/dev/plex/menu/impl/PunishmentMenu.java new file mode 100644 index 0000000..76649d7 --- /dev/null +++ b/server/src/main/java/dev/plex/menu/impl/PunishmentMenu.java @@ -0,0 +1,63 @@ +package dev.plex.menu.impl; + +import dev.plex.cache.DataUtils; +import dev.plex.menu.AbstractMenu; +import dev.plex.menu.pagination.PageableMenu; +import dev.plex.player.PlexPlayer; +import dev.plex.util.PlexLog; +import dev.plex.util.item.ItemBuilder; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.List; + +/** + * @author Taah + * @since 9:27 AM [02-09-2023] + */ +public class PunishmentMenu extends PageableMenu +{ + public PunishmentMenu() + { + super("Punishments", AbstractMenu.Rows.SIX); + PlexLog.debug("list: {0}", list().size()); + onClick((inventoryView, itemStacks, player, itemStack) -> + { + if (itemStack.getType() != Material.PLAYER_HEAD) return true; + final SkullMeta meta = (SkullMeta) itemStack.getItemMeta(); + if (meta.getOwningPlayer() == null) + { + meta.setOwningPlayer(Bukkit.getOfflinePlayer("markbyron")); + } + PlexPlayer punishedPlayer = DataUtils.getPlayer(meta.getOwningPlayer().getUniqueId()); + if (punishedPlayer == null) + { + player.sendMessage(Component.text("This player does not exist. Try doing /punishments instead.").color(NamedTextColor.RED)); + player.closeInventory(); + return true; + } + new PunishedPlayerMenu(punishedPlayer).open(player); + return true; + }); + + this.init(); + } + + @Override + protected ItemStack toItem(Player object) + { + return new ItemBuilder(Material.PLAYER_HEAD).owner(object).displayName("" + object.getName()).build(); + } + + @Override + protected List list() + { + return Bukkit.getOnlinePlayers().stream().map(OfflinePlayer::getPlayer).toList(); + } +} diff --git a/server/src/main/java/dev/plex/menu/impl/ToggleMenu.java b/server/src/main/java/dev/plex/menu/impl/ToggleMenu.java new file mode 100644 index 0000000..4f0bf06 --- /dev/null +++ b/server/src/main/java/dev/plex/menu/impl/ToggleMenu.java @@ -0,0 +1,98 @@ +package dev.plex.menu.impl; + +import dev.plex.Plex; +import dev.plex.menu.AbstractMenu; +import dev.plex.util.PlexUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +public class ToggleMenu extends AbstractMenu +{ + private final Plex plugin; + + public ToggleMenu() + { + super("Toggles", Rows.ONE); + this.plugin = Plex.get(); + resetExplosionItem(this.inventory()); + resetFluidspreadItem(this.inventory()); + resetDropsItem(this.inventory()); + resetRedstoneItem(this.inventory()); + } + + private void resetExplosionItem(Inventory inventory) + { + ItemStack explosions = new ItemStack(Material.TNT); + ItemMeta explosionsItemMeta = explosions.getItemMeta(); + explosionsItemMeta.displayName(PlexUtils.mmDeserialize("Toggle explosions")); + explosionsItemMeta.lore(List.of(PlexUtils.mmDeserialize("Explosions are " + (plugin.toggles.getBoolean("explosions") ? "enabled" : "disabled")))); + explosions.setItemMeta(explosionsItemMeta); + inventory.setItem(0, explosions); + } + + private void resetFluidspreadItem(Inventory inventory) + { + ItemStack water = new ItemStack(Material.WATER_BUCKET); + ItemMeta waterItemMeta = water.getItemMeta(); + waterItemMeta.displayName(PlexUtils.mmDeserialize("Toggle fluid spread")); + waterItemMeta.lore(List.of(PlexUtils.mmDeserialize("Fluid spread is " + (plugin.toggles.getBoolean("fluidspread") ? "enabled" : "disabled")))); + water.setItemMeta(waterItemMeta); + inventory.setItem(1, water); + } + + private void resetDropsItem(Inventory inventory) + { + ItemStack feather = new ItemStack(Material.FEATHER); + ItemMeta featherItemMeta = feather.getItemMeta(); + featherItemMeta.displayName(PlexUtils.mmDeserialize("Toggle drops")); + featherItemMeta.lore(List.of(PlexUtils.mmDeserialize("Drops are " + (plugin.toggles.getBoolean("drops") ? "enabled" : "disabled")))); + feather.setItemMeta(featherItemMeta); + inventory.setItem(2, feather); + } + + private void resetRedstoneItem(Inventory inventory) + { + ItemStack redstone = new ItemStack(Material.REDSTONE); + ItemMeta redstoneItemMeta = redstone.getItemMeta(); + redstoneItemMeta.displayName(PlexUtils.mmDeserialize("Redstone")); + redstoneItemMeta.lore(List.of(PlexUtils.mmDeserialize("Redstone is " + (plugin.toggles.getBoolean("redstone") ? "enabled" : "disabled")))); + redstone.setItemMeta(redstoneItemMeta); + inventory.setItem(3, redstone); + } + + @Override + public boolean onClick(InventoryView view, Inventory inventory, Player player, ItemStack clicked) + { + if (clicked.getType() == Material.TNT) + { + plugin.toggles.set("explosions", !plugin.toggles.getBoolean("explosions")); + resetExplosionItem(inventory); + player.sendMessage(PlexUtils.mmDeserialize("Toggled explosions.")); + } + if (clicked.getType() == Material.WATER_BUCKET) + { + plugin.toggles.set("fluidspread", !plugin.toggles.getBoolean("fluidspread")); + resetFluidspreadItem(inventory); + player.sendMessage(PlexUtils.mmDeserialize("Toggled fluid spread.")); + } + if (clicked.getType() == Material.FEATHER) + { + plugin.toggles.set("drops", !plugin.toggles.getBoolean("drops")); + resetDropsItem(inventory); + player.sendMessage(PlexUtils.mmDeserialize("Toggled drops.")); + } + if (clicked.getType() == Material.REDSTONE) + { + plugin.toggles.set("redstone", !plugin.toggles.getBoolean("redstone")); + resetRedstoneItem(inventory); + player.sendMessage(PlexUtils.mmDeserialize("Toggled redstone.")); + } + return true; + } +} diff --git a/server/src/main/java/dev/plex/menu/pagination/PageableMenu.java b/server/src/main/java/dev/plex/menu/pagination/PageableMenu.java new file mode 100644 index 0000000..7bf6ab7 --- /dev/null +++ b/server/src/main/java/dev/plex/menu/pagination/PageableMenu.java @@ -0,0 +1,176 @@ +package dev.plex.menu.pagination; + +import com.google.common.collect.Maps; +import dev.plex.menu.AbstractMenu; +import dev.plex.util.PlexUtils; +import dev.plex.util.function.ConditionalQuadConsumer; +import dev.plex.util.item.ItemBuilder; +import dev.plex.util.minimessage.SafeMiniMessage; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.Map; + +/** + * @author Taah + * @since 8:04 AM [02-09-2023] + */ + +@Getter +@Setter +@Accessors(fluent = true) +public abstract class PageableMenu +{ + public static final ItemStack NEXT = new ItemBuilder(Material.FEATHER).displayName("Next Page").build(); + public static final ItemStack PREVIOUS = new ItemBuilder(Material.FEATHER).displayName("Previous Page").build(); + public static final ItemStack CLOSE = new ItemBuilder(Material.BARRIER).displayName("Close").build(); + protected final Map pages = Maps.newHashMap(); + private final Component name; + private final AbstractMenu.Rows rows; + private final Inventory inventory; + private int currentPage; + private boolean initialized; + + @Setter(AccessLevel.NONE) + private ConditionalQuadConsumer onClick; + + public PageableMenu(Component name, AbstractMenu.Rows rows) + { + this.name = name; + this.rows = rows; + this.inventory = Bukkit.createInventory(null, rows.slots(), name); + + if (rows.slots() < AbstractMenu.Rows.TWO.slots()) + { + throw new RuntimeException("A pageable menu must have at least two rows to compensate for the navigation!"); + } + } + + protected void init() + { + this.initialized = true; + // Preload all needed pages, a better solution is probably just to dynamically create the pages as they go but no! + if (list().size() < (rows.slots() - 9)) + { + final Page page = new Page(name.append(Component.space()).append(PlexUtils.mmDeserialize("(1)")), rows); + page.parent = this; + page.inventory().setItem(rows.slots() - 5, CLOSE); + this.pages.put(0, page); + } + else + { + for (int i = 0; i < Math.ceil(list().size() / (double) (rows.slots() - 9)); i++) + { + final Page page = new Page(name.append(Component.space()).append(PlexUtils.mmDeserialize("(" + (i + 1) + ")")), rows); + page.parent = this; + if (i > 0) // If not first page set previous page button + { + page.inventory().setItem(rows.slots() - 6, PREVIOUS); + } + page.inventory().setItem(rows.slots() - 5, CLOSE); + if (i < (list().size() / (rows.slots() - 9)) - 1) // If not last page set next page button + { + page.inventory().setItem(rows.slots() - 4, NEXT); + } + this.pages.put(i, page); + } + } + + int currentSlotIndex = 0; + int currentPageIndex = 0; + int currentIndex = 0; + while (currentSlotIndex < rows.slots() - 9 && currentIndex < list().size()) + { + final Page page = this.pages.get(currentPageIndex); + if (page == null) + { + return; + } + page.inventory().setItem(currentSlotIndex, toItem(list().get(currentIndex))); + currentIndex++; + currentSlotIndex++; + if (currentSlotIndex == rows.slots() - 9) + { + currentSlotIndex = 0; + currentPageIndex++; + } + } + if (onClick != null) // To make sure this wasn't declared already + { + this.pages.forEach((integer, page) -> page.onClick(this.onClick)); + } + } + + public PageableMenu(String name, AbstractMenu.Rows rows) + { + this(SafeMiniMessage.mmDeserializeWithoutEvents(name), rows); + } + + public void open(Player player) + { + open(player, 0); + } + + public void open(Player player, int pageNum) + { + if (!this.initialized) + { + player.sendMessage(Component.text("Looks like this inventory was not initialized! Please contact a developer to report this.").color(NamedTextColor.RED)); + return; + } + final Page page = this.pages.get(pageNum); + if (page == null) + { + player.sendMessage(Component.text("Could not find a page to open").color(NamedTextColor.RED)); + return; + } + player.openInventory(page.inventory()); + } + + public void onClick(ConditionalQuadConsumer onClick) + { + this.onClick = onClick; + this.pages.forEach((integer, page) -> page.onClick(this.onClick)); + } + + protected abstract ItemStack toItem(T object); + + protected abstract List list(); + + + @Getter + @Setter + @Accessors(fluent = true) + public static class Page extends AbstractMenu + { + private ConditionalQuadConsumer onClick; + private PageableMenu parent; + + private Page(Component name, Rows rows) + { + super(name, rows); + } + + private Page(String name, AbstractMenu.Rows rows) + { + this(SafeMiniMessage.mmDeserializeWithoutEvents(name), rows); + } + + @Override + public boolean onClick(InventoryView view, Inventory inventory, Player player, ItemStack clicked) + { + return onClick.accept(view, inventory, player, clicked); + } + } +} diff --git a/server/src/main/java/dev/plex/util/function/ConditionalQuadConsumer.java b/server/src/main/java/dev/plex/util/function/ConditionalQuadConsumer.java new file mode 100644 index 0000000..f2e3cd4 --- /dev/null +++ b/server/src/main/java/dev/plex/util/function/ConditionalQuadConsumer.java @@ -0,0 +1,10 @@ +package dev.plex.util.function; + +/** + * @author Taah + * @since 8:40 AM [02-09-2023] + */ +public interface ConditionalQuadConsumer +{ + boolean accept(K k, V v, S s, T t); +} diff --git a/server/src/main/java/dev/plex/util/function/QuadConsumer.java b/server/src/main/java/dev/plex/util/function/QuadConsumer.java new file mode 100644 index 0000000..77842c4 --- /dev/null +++ b/server/src/main/java/dev/plex/util/function/QuadConsumer.java @@ -0,0 +1,10 @@ +package dev.plex.util.function; + +/** + * @author Taah + * @since 8:40 AM [02-09-2023] + */ +public interface QuadConsumer +{ + void accept(K k, V v, S s, T t); +} diff --git a/server/src/main/java/dev/plex/util/item/ItemBuilder.java b/server/src/main/java/dev/plex/util/item/ItemBuilder.java index 09ccf4b..abee052 100644 --- a/server/src/main/java/dev/plex/util/item/ItemBuilder.java +++ b/server/src/main/java/dev/plex/util/item/ItemBuilder.java @@ -1,13 +1,17 @@ package dev.plex.util.item; +import dev.plex.util.minimessage.SafeMiniMessage; import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.OfflinePlayer; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; import java.util.Arrays; @@ -19,7 +23,7 @@ public class ItemBuilder public ItemBuilder(Material material) { - this.itemStack = new ItemStack(material); + this.itemStack = new ItemStack(Bukkit.getItemFactory().getItemMeta(material) == null ? Material.LIGHT_BLUE_STAINED_GLASS_PANE : material); this.meta = itemStack.getItemMeta(); } @@ -29,12 +33,22 @@ public class ItemBuilder return this; } + public ItemBuilder lore(String... lore) + { + return this.lore(Arrays.stream(lore).map(SafeMiniMessage::mmDeserialize).toArray(Component[]::new)); + } + public ItemBuilder displayName(Component displayName) { this.meta.displayName(displayName); return this; } + public ItemBuilder displayName(String displayName) + { + return this.displayName(SafeMiniMessage.mmDeserialize(displayName)); + } + public ItemBuilder addEnchantment(Enchantment enchantment, int level) { this.meta.addEnchant(enchantment, level, true); @@ -53,6 +67,15 @@ public class ItemBuilder return this; } + public ItemBuilder owner(OfflinePlayer player) + { + if (this.meta instanceof SkullMeta skullMeta) + { + skullMeta.setOwningPlayer(player); + } + return this; + } + public ItemStack build() { this.itemStack.setItemMeta(this.meta); diff --git a/server/src/main/java/dev/plex/util/menu/AbstractMenu.java b/server/src/main/java/dev/plex/util/menu/AbstractMenu.java deleted file mode 100644 index 6cf298b..0000000 --- a/server/src/main/java/dev/plex/util/menu/AbstractMenu.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.plex.util.menu; - -import dev.plex.Plex; -import org.bukkit.event.Listener; - -public abstract class AbstractMenu implements Listener -{ - private final String name; - - public AbstractMenu(String name) - { - this.name = name; - - Plex.get().getServer().getPluginManager().registerEvents(this, Plex.get()); - } - - public String getName() - { - return name; - } -} diff --git a/server/src/main/java/dev/plex/util/menu/IMenu.java b/server/src/main/java/dev/plex/util/menu/IMenu.java deleted file mode 100644 index b356536..0000000 --- a/server/src/main/java/dev/plex/util/menu/IMenu.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.plex.util.menu; - - -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; - -public interface IMenu -{ - - Inventory getInventory(); - - - void openInv(Player player); - - @EventHandler - void onClick(InventoryClickEvent event); - -}