1
mirror of https://github.com/Shiewk/SModeration.git synced 2026-04-28 05:54:16 +02:00

Amend custom inventory logic

- Make click events based on slot numbers instead of comparing item stacks
- Removed ItemStack parameter from CustomInventory#click as it is no longer needed
This commit is contained in:
Shy
2026-04-03 15:33:32 +02:00
parent c4e1aedeca
commit 5c4feea042
7 changed files with 67 additions and 82 deletions
@@ -19,33 +19,30 @@ public class ConfirmationInventory implements CustomInventory {
private final Inventory inventory; private final Inventory inventory;
private final Player player; private final Player player;
private final Component prompt; private final Component prompt;
private final ItemStack yesStack;
private final ItemStack noStack;
private final Runnable onAccept; private final Runnable onAccept;
private final Runnable onReject; private final Runnable onReject;
private final boolean reversed;
public ConfirmationInventory(Player player, Component prompt, Runnable onAccept, Runnable onReject, boolean reversed) { public ConfirmationInventory(Player player, Component prompt, Runnable onAccept, Runnable onReject) {
this.player = player; this.player = player;
this.prompt = prompt; this.prompt = prompt;
this.onAccept = onAccept; this.onAccept = onAccept;
this.onReject = onReject; this.onReject = onReject;
this.reversed = reversed;
inventory = Bukkit.createInventory(this, InventoryType.HOPPER, this.prompt); inventory = Bukkit.createInventory(this, InventoryType.HOPPER, this.prompt);
yesStack = new ItemStack(Material.LIME_STAINED_GLASS_PANE);
noStack = new ItemStack(Material.RED_STAINED_GLASS_PANE);
} }
@Override @Override
public void refresh() { public void refresh() {
yesStack.setData(DataComponentTypes.ITEM_NAME, renderComponent(player, applyFormatting(translatable("smod.confirm.yes")))); ItemStack accept = new ItemStack(Material.LIME_STAINED_GLASS_PANE);
noStack.setData(DataComponentTypes.ITEM_NAME, renderComponent(player, applyFormatting(translatable("smod.confirm.no"))));
ItemStack confirmation = new ItemStack(Material.PAPER); ItemStack confirmation = new ItemStack(Material.PAPER);
confirmation.setData(DataComponentTypes.ITEM_NAME, renderComponent(player, prompt.colorIfAbsent(NamedTextColor.GOLD))); ItemStack reject = new ItemStack(Material.RED_STAINED_GLASS_PANE);
inventory.setItem(reversed ? 4 : 0, noStack); accept.setData(DataComponentTypes.ITEM_NAME, renderComponent(player, applyFormatting(translatable("smod.confirm.yes"))));
confirmation.setData(DataComponentTypes.ITEM_NAME, renderComponent(player, prompt.colorIfAbsent(NamedTextColor.GOLD)));
reject.setData(DataComponentTypes.ITEM_NAME, renderComponent(player, applyFormatting(translatable("smod.confirm.no"))));
inventory.setItem(0, accept);
inventory.setItem(2, confirmation); inventory.setItem(2, confirmation);
inventory.setItem(reversed ? 0 : 4, yesStack); inventory.setItem(4, reject);
} }
@Override @Override
@@ -55,11 +52,11 @@ public class ConfirmationInventory implements CustomInventory {
} }
@Override @Override
public void click(ItemStack stack, InventoryClickEvent event) { public void click(InventoryClickEvent event) {
if (yesStack.equals(stack)){ if (event.getSlot() == 0){
inventory.close(); inventory.close();
onAccept.run(); onAccept.run();
} else if (noStack.equals(stack)) { } else if (event.getSlot() == 4) {
inventory.close(); inventory.close();
onReject.run(); onReject.run();
} }
@@ -16,7 +16,7 @@ public interface CustomInventory extends InventoryHolder {
void refresh(); void refresh();
void open(); void open();
void click(ItemStack stack, InventoryClickEvent event); void click(InventoryClickEvent event);
default ItemStack createEmptyStack(){ default ItemStack createEmptyStack(){
ItemStack stack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); ItemStack stack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE);
@@ -8,7 +8,6 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.text;
@@ -44,7 +43,7 @@ public class InvSeeEquipmentInventory implements AutoUpdatingCustomInventory {
} }
@Override @Override
public void click(ItemStack stack, InventoryClickEvent event) { public void click(InventoryClickEvent event) {
if (viewer.hasPermission("smod.invsee.modify") && !subject.hasPermission("smod.invsee.preventmodify")){ if (viewer.hasPermission("smod.invsee.modify") && !subject.hasPermission("smod.invsee.preventmodify")){
event.setCancelled(false); event.setCancelled(false);
changing = true; changing = true;
@@ -6,7 +6,6 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.text;
@@ -46,7 +45,7 @@ public class InvSeeInventory implements AutoUpdatingCustomInventory {
} }
@Override @Override
public void click(ItemStack stack, InventoryClickEvent event) { public void click(InventoryClickEvent event) {
if (viewer.hasPermission("smod.invsee.modify") && !subject.hasPermission("smod.invsee.preventmodify")){ if (viewer.hasPermission("smod.invsee.modify") && !subject.hasPermission("smod.invsee.preventmodify")){
event.setCancelled(false); event.setCancelled(false);
changing = true; changing = true;
@@ -8,24 +8,28 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public abstract class PageableCustomInventory implements CustomInventory { public abstract class PageableCustomInventory implements CustomInventory {
public abstract int lastPage();
public abstract void switchPage(); protected final int prevSlot, nextSlot;
private ItemStack previousStack = null;
private ItemStack nextStack = null;
private int page = 0; private int page = 0;
public PageableCustomInventory(int prevSlot, int nextSlot) {
this.prevSlot = prevSlot;
this.nextSlot = nextSlot;
}
public int getPage(){ public int getPage(){
return page; return page;
} }
public abstract int lastPage();
public abstract void switchPage();
@Override @Override
public void click(ItemStack stack, InventoryClickEvent event) { public void click(InventoryClickEvent event) {
if (stack != null){ if (event.getSlot() == prevSlot) {
if (stack.equals(previousStack)){ previousPage();
previousPage(); } else if (event.getSlot() == nextSlot) {
} else if (stack.equals(nextStack)) { nextPage();
nextPage();
}
} }
} }
@@ -51,7 +55,6 @@ public abstract class PageableCustomInventory implements CustomInventory {
int skip = allowed ? page : page+1; int skip = allowed ? page : page+1;
ItemStack stack = new ItemStack(allowed ? Material.GREEN_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE); ItemStack stack = new ItemStack(allowed ? Material.GREEN_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE);
stack.editMeta(meta -> meta.displayName(applyFormatting(Component.text("Previous page (%s/%s)".formatted(skip, lastPage()+1)).color(color)))); stack.editMeta(meta -> meta.displayName(applyFormatting(Component.text("Previous page (%s/%s)".formatted(skip, lastPage()+1)).color(color))));
previousStack = stack;
return stack; return stack;
} }
@@ -61,7 +64,6 @@ public abstract class PageableCustomInventory implements CustomInventory {
int skip = allowed ? page+2 : page+1; int skip = allowed ? page+2 : page+1;
ItemStack stack = new ItemStack(allowed ? Material.GREEN_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE); ItemStack stack = new ItemStack(allowed ? Material.GREEN_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE);
stack.editMeta(meta -> meta.displayName(applyFormatting(Component.text("Next page (%s/%s)".formatted(skip, lastPage()+1)).color(color)))); stack.editMeta(meta -> meta.displayName(applyFormatting(Component.text("Next page (%s/%s)".formatted(skip, lastPage()+1)).color(color))));
nextStack = stack;
return stack; return stack;
} }
} }
@@ -12,22 +12,19 @@ import de.shiewk.smoderation.paper.util.SchedulerUtil;
import de.shiewk.smoderation.paper.util.TimeUtil; import de.shiewk.smoderation.paper.util.TimeUtil;
import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.ItemLore; import io.papermc.paper.datacomponent.item.ItemLore;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Comparator; import java.util.Comparator;
@@ -73,22 +70,20 @@ public class SModMenu extends PageableCustomInventory {
this.comparator = comparator; this.comparator = comparator;
} }
} }
private static final NamespacedKey PUNISHMENT_STORE_KEY = new NamespacedKey("smod", "punishmentid");
private final Inventory inventory; private final Inventory inventory;
private final Player player; private final Player player;
private final PunishmentContainer container; private final PunishmentContainer container;
private final Int2ObjectArrayMap<Punishment> slotMap = new Int2ObjectArrayMap<>(45);
private List<Punishment> punishments; private List<Punishment> punishments;
private ItemStack sortStack = null;
private ItemStack filterStack = null;
private ItemStack searchStack = null;
private ItemStack typeStack = null;
private int sort = 0; private int sort = 0;
private int filter = 0; private int filter = 0;
private int type = -1; private int type = -1;
private int rfId = 0;
private String searchQuery = null; private String searchQuery = null;
public SModMenu(Player player, PunishmentContainer container) { public SModMenu(Player player, PunishmentContainer container) {
super(45, 53);
this.player = player; this.player = player;
this.container = container; this.container = container;
this.inventory = Bukkit.createInventory(this, 54, translatable("smod.menu")); this.inventory = Bukkit.createInventory(this, 54, translatable("smod.menu"));
@@ -209,7 +204,7 @@ public class SModMenu extends PageableCustomInventory {
loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.filter.switch", NamedTextColor.GOLD)))); loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.filter.switch", NamedTextColor.GOLD))));
stack.setData(DataComponentTypes.LORE, loreBuilder.build()); stack.setData(DataComponentTypes.LORE, loreBuilder.build());
return filterStack = stack; return stack;
} }
private ItemStack createTypeItem(){ private ItemStack createTypeItem(){
@@ -233,7 +228,7 @@ public class SModMenu extends PageableCustomInventory {
loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.type.switch", NamedTextColor.GOLD)))); loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.type.switch", NamedTextColor.GOLD))));
stack.setData(DataComponentTypes.LORE, loreBuilder); stack.setData(DataComponentTypes.LORE, loreBuilder);
return typeStack = stack; return stack;
} }
private ItemStack createSortItem(){ private ItemStack createSortItem(){
@@ -254,7 +249,7 @@ public class SModMenu extends PageableCustomInventory {
loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.sort.switch", NamedTextColor.GOLD)))); loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.sort.switch", NamedTextColor.GOLD))));
stack.setData(DataComponentTypes.LORE, loreBuilder); stack.setData(DataComponentTypes.LORE, loreBuilder);
return sortStack = stack; return stack;
} }
private ItemStack createSearchItem(){ private ItemStack createSearchItem(){
@@ -280,7 +275,7 @@ public class SModMenu extends PageableCustomInventory {
loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.search.remove", NamedTextColor.GOLD)))); loreBuilder.addLine(renderComponent(player, applyFormatting(translatable("smod.menu.search.remove", NamedTextColor.GOLD))));
} }
stack.setData(DataComponentTypes.LORE, loreBuilder); stack.setData(DataComponentTypes.LORE, loreBuilder);
return searchStack = stack; return stack;
} }
private CompletableFuture<ItemStack> createPunishmentItem(Punishment punishment){ private CompletableFuture<ItemStack> createPunishmentItem(Punishment punishment){
@@ -349,7 +344,6 @@ public class SModMenu extends PageableCustomInventory {
stack.setData(DataComponentTypes.LORE, lore); stack.setData(DataComponentTypes.LORE, lore);
} }
private int rfId = 0;
@Override @Override
public void refresh() { public void refresh() {
int rfId = ++this.rfId; int rfId = ++this.rfId;
@@ -357,11 +351,12 @@ public class SModMenu extends PageableCustomInventory {
previousPage(); previousPage();
} }
inventory.clear(); inventory.clear();
slotMap.clear();
for (int i = 45; i < 54; i++) { for (int i = 45; i < 54; i++) {
inventory.setItem(i, createEmptyStack()); inventory.setItem(i, createEmptyStack());
} }
inventory.setItem(45, createPreviousPageStack()); inventory.setItem(prevSlot, createPreviousPageStack());
inventory.setItem(53, createNextPageStack()); inventory.setItem(nextSlot, createNextPageStack());
inventory.setItem(47, createSearchItem()); inventory.setItem(47, createSearchItem());
inventory.setItem(48, createTypeItem()); inventory.setItem(48, createTypeItem());
inventory.setItem(50, createFilterItem()); inventory.setItem(50, createFilterItem());
@@ -372,13 +367,9 @@ public class SModMenu extends PageableCustomInventory {
if (punishments.size() > ci){ if (punishments.size() > ci){
final Punishment punishment = punishments.get(ci); final Punishment punishment = punishments.get(ci);
int slot = i; int slot = i;
slotMap.put(slot, punishment);
createPunishmentItem(punishment).thenAccept(item -> { createPunishmentItem(punishment).thenAccept(item -> {
if (rfId != this.rfId) return; if (rfId != this.rfId) return;
if (punishment.isActive()){
if ((punishment.type == PunishmentType.BAN && player.hasPermission("smod.unban")) || (punishment.type == PunishmentType.MUTE && player.hasPermission("smod.unmute"))) {
item.editMeta(meta -> meta.getPersistentDataContainer().set(PUNISHMENT_STORE_KEY, PersistentDataType.LONG, punishment.time));
}
}
inventory.setItem(slot, item); inventory.setItem(slot, item);
}).exceptionally(x -> { }).exceptionally(x -> {
LOGGER.warn("Error creating punishment item", x); LOGGER.warn("Error creating punishment item", x);
@@ -391,39 +382,36 @@ public class SModMenu extends PageableCustomInventory {
} }
@Override @Override
public void click(ItemStack stack, InventoryClickEvent event) { public void click(InventoryClickEvent event) {
super.click(stack, event); super.click(event);
if (stack != null) { int slot = event.getSlot();
if (stack.equals(filterStack)){ if (slot == 47) {
cycleFilter(event.isRightClick()); if (event.isRightClick() && searchQuery != null){
} else if (stack.equals(sortStack)){ player.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 0.8f);
cycleSort(event.isRightClick()); searchQuery = null;
} else if (stack.equals(searchStack)){ reload();
if (event.isRightClick() && searchQuery != null){ refresh();
player.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 0.8f); } else {
searchQuery = null; player.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 2f);
reload(); promptSearchQuery();
refresh();
} else {
player.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 2f);
promptSearchQuery();
}
} else if (stack.equals(typeStack)) {
cycleType(event.isRightClick());
} }
final ItemMeta itemMeta = stack.getItemMeta(); } else if (slot == 48) {
if (itemMeta != null) { cycleType(event.isRightClick());
final PersistentDataContainer persistentDataContainer = itemMeta.getPersistentDataContainer(); } else if (slot == 50) {
final Long timestamp = persistentDataContainer.get(PUNISHMENT_STORE_KEY, PersistentDataType.LONG); cycleFilter(event.isRightClick());
if (timestamp != null) { } else if (slot == 51) {
final Punishment punishment = container.findByTimestamp(timestamp); cycleSort(event.isRightClick());
if (punishment != null) { } else {
Punishment punishment = slotMap.get(slot);
if (punishment != null){
if (punishment.isActive()){
if ((punishment.type == PunishmentType.BAN && player.hasPermission("smod.unban")) || (punishment.type == PunishmentType.MUTE && player.hasPermission("smod.unmute"))) {
new ConfirmationInventory(player, translatable("smod.menu.undoConfirmation"), () -> { new ConfirmationInventory(player, translatable("smod.menu.undoConfirmation"), () -> {
punishment.undo(player.getUniqueId()); punishment.undo(player.getUniqueId());
punishment.broadcastUndo(container); punishment.broadcastUndo(container);
player.playSound(player, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 2f); player.playSound(player, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 2f);
this.open(); this.open();
}, this::open, false).open(); }, this::open).open();
} }
} }
} }
@@ -15,7 +15,7 @@ public class CustomInventoryListener implements Listener {
public void onInventoryClick(InventoryClickEvent event){ public void onInventoryClick(InventoryClickEvent event){
if (event.getInventory().getHolder() instanceof CustomInventory customInventory){ if (event.getInventory().getHolder() instanceof CustomInventory customInventory){
event.setCancelled(true); event.setCancelled(true);
customInventory.click(event.getCurrentItem(), event); customInventory.click(event);
} }
} }
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)