Window outside click handlers

This commit is contained in:
NichtStudioCode 2023-03-20 14:03:32 +01:00
parent 3ca3a0a76e
commit 13bef06660
4 changed files with 125 additions and 44 deletions

@ -11,6 +11,7 @@ import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -45,6 +46,7 @@ public abstract class AbstractWindow implements Window, GuiParent {
private final SlotElement[] elementsDisplayed;
private List<Runnable> openHandlers;
private List<Runnable> closeHandlers;
private List<Consumer<InventoryClickEvent>> outsideClickHandlers;
private ComponentWrapper title;
private boolean closeable;
private boolean currentlyOpen;
@ -133,7 +135,7 @@ public abstract class AbstractWindow implements Window, GuiParent {
}
}
public void handleDrag(InventoryDragEvent event) {
public void handleDragEvent(InventoryDragEvent event) {
Player player = ((Player) event.getWhoClicked()).getPlayer();
UpdateReason updateReason = new PlayerUpdateReason(player, event);
Map<Integer, ItemStack> newItems = event.getNewItems();
@ -197,6 +199,32 @@ public abstract class AbstractWindow implements Window, GuiParent {
}
}
public void handleClickEvent(InventoryClickEvent event) {
if (Arrays.asList(getInventories()).contains(event.getClickedInventory())) {
// The inventory that was clicked is part of the open window
handleClick(event);
} else if (event.getSlotType() == InventoryType.SlotType.OUTSIDE) {
// The player clicked outside the inventory
if (outsideClickHandlers != null) {
for (var handler : outsideClickHandlers) {
handler.accept(event);
}
}
} else {
switch (event.getAction()) {
// The inventory that was clicked is not part of the open window, so it is the player inventory
case MOVE_TO_OTHER_INVENTORY:
handleItemShift(event);
break;
// items have been collected by clicking a slot in the player inv
case COLLECT_TO_CURSOR:
handleCursorCollect(event);
break;
}
}
}
public void handleItemProviderUpdate(Item item) {
getItemSlotElements(item).forEach((index, slotElement) ->
redrawItem(index, slotElement, false));
@ -324,6 +352,25 @@ public abstract class AbstractWindow implements Window, GuiParent {
closeHandlers.remove(closeHandler);
}
@Override
public void setOutsideClickHandlers(@NotNull List<@NotNull Consumer<@NotNull InventoryClickEvent>> outsideClickHandlers) {
this.outsideClickHandlers = outsideClickHandlers;
}
@Override
public void addOutsideClickHandler(@NotNull Consumer<@NotNull InventoryClickEvent> outsideClickHandlers) {
if (this.outsideClickHandlers == null)
this.outsideClickHandlers = new ArrayList<>();
this.outsideClickHandlers.add(outsideClickHandlers);
}
@Override
public void removeOutsideClickHandler(@NotNull Consumer<@NotNull InventoryClickEvent> outsideClickHandlers) {
if (this.outsideClickHandlers != null)
this.outsideClickHandlers.remove(outsideClickHandlers);
}
@Override
public @Nullable Player getCurrentViewer() {
List<HumanEntity> viewers = getInventories()[0].getViewers();
@ -380,11 +427,11 @@ public abstract class AbstractWindow implements Window, GuiParent {
protected abstract void handleClosed();
public abstract void handleClick(InventoryClickEvent event);
protected abstract void handleClick(InventoryClickEvent event);
public abstract void handleItemShift(InventoryClickEvent event);
protected abstract void handleItemShift(InventoryClickEvent event);
public abstract void handleCursorCollect(InventoryClickEvent event);
protected abstract void handleCursorCollect(InventoryClickEvent event);
public abstract void handleViewerDeath(PlayerDeathEvent event);
@ -396,6 +443,7 @@ public abstract class AbstractWindow implements Window, GuiParent {
protected boolean closeable = true;
protected List<Runnable> openHandlers;
protected List<Runnable> closeHandlers;
protected List<Consumer<InventoryClickEvent>> outsideClickHandlers;
protected List<Consumer<Window>> modifiers;
@Override
@ -458,6 +506,21 @@ public abstract class AbstractWindow implements Window, GuiParent {
return (S) this;
}
@Override
public @NotNull S setOutsideClickHandlers(@NotNull List<@NotNull Consumer<@NotNull InventoryClickEvent>> outsideClickHandlers) {
this.outsideClickHandlers = outsideClickHandlers;
return (S) this;
}
@Override
public @NotNull S addOutsideClickHandler(@NotNull Consumer<@NotNull InventoryClickEvent> outsideClickHandler) {
if (outsideClickHandlers == null)
outsideClickHandlers = new ArrayList<>();
outsideClickHandlers.add(outsideClickHandler);
return (S) this;
}
@Override
public @NotNull S setModifiers(List<Consumer<Window>> modifiers) {
this.modifiers = modifiers;
@ -477,6 +540,9 @@ public abstract class AbstractWindow implements Window, GuiParent {
if (closeHandlers != null)
window.setCloseHandlers(closeHandlers);
if (outsideClickHandlers != null)
window.setOutsideClickHandlers(outsideClickHandlers);
if (modifiers != null)
modifiers.forEach(modifier -> modifier.accept(window));
}

@ -2,7 +2,6 @@ package xyz.xenondevs.invui.window;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.MapMeta;
import org.jetbrains.annotations.NotNull;
@ -13,6 +12,7 @@ import xyz.xenondevs.inventoryaccess.component.ComponentWrapper;
import xyz.xenondevs.inventoryaccess.map.MapIcon;
import xyz.xenondevs.inventoryaccess.map.MapPatch;
import xyz.xenondevs.invui.gui.AbstractGui;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.util.MathUtils;
import java.util.List;
@ -28,7 +28,7 @@ final class CartographySingleWindowImpl extends AbstractSingleWindow implements
@NotNull AbstractGui gui,
boolean closeable
) {
super(player.getUniqueId(), title, gui, null, closeable);
super(player.getUniqueId(), title, createWrappingGui(gui), null, closeable);
if (gui.getWidth() != 2 || gui.getHeight() != 1) throw new IllegalArgumentException("Gui has to be 2x1");
cartographyInventory = InventoryAccess.createCartographyInventory(player, title.localized(player));
@ -37,6 +37,15 @@ final class CartographySingleWindowImpl extends AbstractSingleWindow implements
resetMap();
}
private static AbstractGui createWrappingGui(Gui upperGui) {
if (upperGui.getWidth() != 2 || upperGui.getHeight() != 1)
throw new IllegalArgumentException("Gui has to be 2x1");
Gui wrapperGui = Gui.empty(3, 1);
wrapperGui.fillRectangle(1, 0, upperGui, true);
return (AbstractGui) wrapperGui;
}
@Override
public void updateMap(@Nullable MapPatch patch, @Nullable List<MapIcon> icons) {
InventoryAccess.getPlayerUtils().sendMapUpdate(getViewer(), mapId, (byte) 0, false, patch, icons);
@ -53,20 +62,6 @@ final class CartographySingleWindowImpl extends AbstractSingleWindow implements
cartographyInventory.setItem(0, map);
}
@Override
protected void setInvItem(int slot, ItemStack itemStack) {
cartographyInventory.setItem(slot + 1, itemStack);
}
@Override
public void handleClick(InventoryClickEvent event) {
if (event.getSlot() != 0) {
getGui().handleClick(event.getSlot() - 1, (Player) event.getWhoClicked(), event.getClick(), event);
} else {
event.setCancelled(true);
}
}
@Override
protected void openInventory(@NotNull Player viewer) {
cartographyInventory.open();

@ -2,6 +2,7 @@ package xyz.xenondevs.invui.window;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@ -196,6 +197,26 @@ public interface Window {
*/
void removeCloseHandler(@NotNull Runnable closeHandler);
/**
* Replaces the currently registered outside click handlers with the given list.
* @param outsideClickHandlers The new outside click handlers
*/
void setOutsideClickHandlers(@NotNull List<@NotNull Consumer<@NotNull InventoryClickEvent>> outsideClickHandlers);
/**
* Adds an outside click handler that will be called when a player clicks outside the inventory.
*
* @param outsideClickHandlers The outside click handler to add
*/
void addOutsideClickHandler(@NotNull Consumer<@NotNull InventoryClickEvent> outsideClickHandlers);
/**
* Removes an outside click handler that has been added previously.
*
* @param outsideClickHandlers The outside click handler to remove
*/
void removeOutsideClickHandler(@NotNull Consumer<@NotNull InventoryClickEvent> outsideClickHandlers);
/**
* A {@link Window} builder.
*
@ -285,6 +306,24 @@ public interface Window {
@Contract("_ -> this")
@NotNull S addCloseHandler(Runnable closeHandler);
/**
* Sets the outside click handlers of the {@link Window}.
*
* @param outsideClickHandlers The outside click handlers of the {@link Window}
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
@NotNull S setOutsideClickHandlers(@NotNull List<@NotNull Consumer<@NotNull InventoryClickEvent>> outsideClickHandlers);
/**
* Adds an outside click handler to the {@link Window}.
*
* @param outsideClickHandler The outside click handler to add
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
@NotNull S addOutsideClickHandler(@NotNull Consumer<@NotNull InventoryClickEvent> outsideClickHandler);
/**
* Sets the modifiers of the {@link Window}.
*

@ -105,28 +105,9 @@ public class WindowManager implements Listener {
@EventHandler
private void handleInventoryClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
AbstractWindow window = (AbstractWindow) getOpenWindow(player);
AbstractWindow window = (AbstractWindow) getOpenWindow((Player) event.getWhoClicked());
if (window != null) {
Inventory clicked = event.getClickedInventory();
if (Arrays.asList(window.getInventories()).contains(clicked)) {
// The inventory that was clicked is part of the open window
window.handleClick(event);
} else {
// The inventory that was clicked is not part of the open window, so it is the player inventory
switch (event.getAction()) {
case MOVE_TO_OTHER_INVENTORY:
window.handleItemShift(event);
break;
// items have been collected by clicking a slot in the player inv
case COLLECT_TO_CURSOR:
window.handleCursorCollect(event);
break;
}
}
window.handleClickEvent(event);
}
}
@ -134,17 +115,17 @@ public class WindowManager implements Listener {
private void handleInventoryDrag(InventoryDragEvent event) {
AbstractWindow window = (AbstractWindow) getOpenWindow((Player) event.getWhoClicked());
if (window != null) {
window.handleDrag(event);
window.handleDragEvent(event);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
private void handleInventoryClose(InventoryCloseEvent event) {
Player player = (Player) event.getPlayer();
AbstractWindow window = (AbstractWindow) getWindow(event.getInventory());
if (window != null)
if (window != null) {
window.handleCloseEvent(player);
}
openWindows.remove(player);
}