Optimise snitch GUI

- Only render the snitches for the current page
- Also fix the plugin name (previously it was jukealert-paper, now it correctly shows as JukeAlert)
This commit is contained in:
okx-code
2024-02-21 22:22:57 +00:00
parent 74f6817326
commit 7c5da9f1ee
3 changed files with 163 additions and 19 deletions

View File

@@ -0,0 +1,134 @@
package vg.civcraft.mc.civmodcore.inventory.gui;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils;
/**
* Modification to MultiPageView that only generates the clickables as needed for each page.
* The "Fast" name comes from the fact that generating several pages of items upfront can be pretty taxing on the server
*/
public class FastMultiPageView {
private Player p;
private int currentPage = 0;
private BiFunction<Integer, Integer, List<IClickable>> clickableSupplier;
private String invName;
private int rows;
private IClickable[] extraMenuItems = new IClickable[7];
public FastMultiPageView(Player p, BiFunction<Integer, Integer, List<IClickable>> clickableSupplier, String invName, int rows) {
this.p = p;
this.clickableSupplier = clickableSupplier;
this.invName = invName;
this.rows = rows;
}
/**
* Construct a clickable inventory containing the clickables given in the constructor, split up on different pages.
* The view will also include bach and forth buttons to navigate. This method should only be called repeatedly to
* change pages, if the clickables need to change just make a new instance
*
* @return ClickableInventory of the current page
*/
private ClickableInventory constructInventory() {
ClickableInventory ci = new ClickableInventory(rows * 9, invName);
int contentSize = getContentSize();
List<IClickable> tempPageClickables = clickableSupplier.apply(currentPage * contentSize, contentSize);
// size may have changed
while (tempPageClickables.isEmpty() && currentPage != 0) {
// would show an empty page, so go to previous
currentPage--;
tempPageClickables = clickableSupplier.apply(currentPage * contentSize, contentSize + 1);
}
List<IClickable> pageClickables = tempPageClickables;
// fill gui
for (int i = 0; i < contentSize && i < Math.min(contentSize, pageClickables.size()); i++) {
ci.setSlot(pageClickables.get(i), i);
}
// back button
if (currentPage > 0) {
ItemStack back = new ItemStack(Material.ARROW);
ItemUtils.setDisplayName(back, ChatColor.GOLD + "Go to previous page");
Clickable baCl = new Clickable(back) {
@Override
public void clicked(Player arg0) {
if (currentPage > 0) {
currentPage--;
}
showScreen();
}
};
ci.setSlot(baCl, getContentSize());
}
// next button
if (pageClickables.size() > contentSize) {
ItemStack forward = new ItemStack(Material.ARROW);
ItemUtils.setDisplayName(forward, ChatColor.GOLD + "Go to next page");
Clickable forCl = new Clickable(forward) {
@Override
public void clicked(Player arg0) {
if (pageClickables.size() > contentSize) {
currentPage++;
}
showScreen();
}
};
ci.setSlot(forCl, getContentSize() + 8);
}
int extraSlot = getContentSize() + 2;
for (IClickable click : extraMenuItems) {
if (click != null) {
ci.setSlot(click, extraSlot++);
}
}
return ci;
}
private int getContentSize() {
return (rows - 1) * 9;
}
/**
* Shows the current page
*/
public void showScreen() {
ClickableInventory ci = constructInventory();
ci.showInventory(p);
}
/**
* Allows setting a menu slot at the bottom of the gui. The slot must be a number between 0 and 6 (inclusive on both
* ends), because only 7 slots are available
*
* @param click
* Clickable to put in slot
* @param slot
* Slot to put it in
*/
public void setMenuSlot(IClickable click, int slot) {
if (slot < 0 || slot > 6) {
throw new IllegalArgumentException("Slot for Multipageview menu item must be between 0 and 6");
}
extraMenuItems[slot] = click;
}
/**
* Force changes the page of this view. You will have to construct a new inventory for this to apply
*
* @param page
* Page to set to
*/
public void setPage(int page) {
this.currentPage = page;
}
}

View File

@@ -2,12 +2,21 @@ package com.untamedears.jukealert.gui;
import com.untamedears.jukealert.model.Snitch;
import com.untamedears.jukealert.model.appender.DormantCullingAppender;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.ItemMeta;
import vg.civcraft.mc.civmodcore.chat.ChatUtils;
import vg.civcraft.mc.civmodcore.inventory.gui.Clickable;
import vg.civcraft.mc.civmodcore.inventory.gui.FastMultiPageView;
import vg.civcraft.mc.civmodcore.inventory.gui.IClickable;
import vg.civcraft.mc.civmodcore.inventory.gui.MultiPageView;
import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils;
@@ -29,38 +38,39 @@ public class SnitchOverviewGUI {
this.canShowDetails = canShowDetails;
}
private List<IClickable> constructSnitchClickables() {
private List<IClickable> constructSnitchClickables(int start, int offset) {
final List<IClickable> clickables = new LinkedList<>();
for (final Snitch snitch : this.snitches) {
for (int i = start; i <= Math.min(snitches.size() - 1, start + offset); i++) {
Snitch snitch = snitches.get(i);
// Base the snitch icon on the snitch type
final var icon = snitch.getType().getItem().clone();
ItemUtils.handleItemMeta(icon, (ItemMeta meta) -> {
meta.setDisplayName(ChatColor.GOLD + snitch.getName());
meta.displayName(Component.text(snitch.getName()).color(NamedTextColor.GOLD));
final var location = snitch.getLocation();
MetaUtils.addLore(meta, ChatColor.AQUA + "Location: "
+ ChatColor.WHITE + location.getWorld().getName() + " "
+ ChatColor.RED + location.getBlockX()
+ ChatColor.WHITE + ", "
+ ChatColor.GREEN + location.getBlockY()
+ ChatColor.WHITE + ", "
+ ChatColor.BLUE + location.getBlockZ());
MetaUtils.addLore(meta, ChatColor.YELLOW + "Group: " + snitch.getGroup().getName());
List<Component> lore = new ArrayList<>();
lore.add(ChatUtils.newComponent("Location: ").color(NamedTextColor.AQUA)
.append(Component.text(location.getWorld().getName() + " ").color(NamedTextColor.WHITE))
.append(Component.text(location.getBlockX()).color(NamedTextColor.RED))
.append(Component.text(", ").color(NamedTextColor.WHITE))
.append(Component.text(location.getBlockY()).color(NamedTextColor.GREEN))
.append(Component.text(", ").color(NamedTextColor.WHITE))
.append(Component.text(location.getBlockZ()).color(NamedTextColor.BLUE)));
lore.add(ChatUtils.newComponent("Group: " + snitch.getGroup().getName()).color(NamedTextColor.YELLOW));
if (snitch.hasAppender(DormantCullingAppender.class)) {
final var cull = snitch.getAppender(DormantCullingAppender.class);
if (cull.isActive()) {
MetaUtils.addLore(meta, ChatColor.AQUA + "Will go dormant in " +
TextUtil.formatDuration(cull.getTimeUntilDormant()));
lore.add(ChatUtils.newComponent("Will go dormant in " + TextUtil.formatDuration(cull.getTimeUntilDormant())).color(NamedTextColor.AQUA));
MetaUtils.addGlow(meta);
}
else if (cull.isDormant()) {
MetaUtils.addLore(meta, ChatColor.AQUA + "Will cull in " +
TextUtil.formatDuration(cull.getTimeUntilCulling()));
lore.add(ChatUtils.newComponent("Will cull in " + TextUtil.formatDuration(cull.getTimeUntilCulling())).color(NamedTextColor.AQUA));
}
}
if (this.canShowDetails) {
MetaUtils.addLore(meta, ChatColor.GREEN + "Click to show details");
lore.add(ChatUtils.newComponent("Click to show details").color(NamedTextColor.GREEN));
}
MetaUtils.addLore(meta, ChatColor.GOLD + "Right click to send waypoint");
lore.add(ChatUtils.newComponent("Right click to send waypoint").color(NamedTextColor.GOLD));
meta.lore(lore);
return true;
});
clickables.add(new Clickable(icon) {
@@ -90,7 +100,7 @@ public class SnitchOverviewGUI {
}
public void showScreen() {
final var view = new MultiPageView(this.player, constructSnitchClickables(), this.title, true);
final var view = new FastMultiPageView(this.player, this::constructSnitchClickables, this.title, 6);
view.setMenuSlot(SnitchLogGUI.constructExitClick(), 3);
view.showScreen();
}

View File

@@ -1,4 +1,4 @@
name: ${name}
name: JukeAlert
main: com.untamedears.jukealert.JukeAlert
version: ${version}
authors: [mgrandi, Maxopoly]