Improved window building

- Removed the "retain" parameter from Windows - all Windows can now be closed and reopened
- Added open handlers to Windows
- Added quick build methods Window.Builder.build(Player) and Window.Builder.show(Player)
- Added some NotNull annotations
This commit is contained in:
NichtStudioCode 2023-03-03 17:36:07 +01:00
parent 62e1a2c591
commit 3d4e062901
17 changed files with 251 additions and 264 deletions

@ -14,4 +14,4 @@ import xyz.xenondevs.invui.window.Window
* @return This Window Builder
*/
@Contract("_ -> this")
fun <B : Window.Builder<*, *, B>> B.setTitle(title: Component): B = setTitle(AdventureComponentWrapper(title))
fun <B : Window.Builder<*, B>> B.setTitle(title: Component): B = setTitle(AdventureComponentWrapper(title))

@ -24,34 +24,33 @@ public abstract class AbstractDoubleWindow extends AbstractWindow {
private final Inventory playerInventory;
private final ItemStack[] playerItems = new ItemStack[36];
protected Inventory upperInventory;
private boolean isCurrentlyOpened;
public AbstractDoubleWindow(Player player, ComponentWrapper title, int size, Inventory upperInventory, boolean closeable, boolean retain) {
super(player.getUniqueId(), title, size, closeable, retain);
public AbstractDoubleWindow(Player player, ComponentWrapper title, int size, Inventory upperInventory, boolean closeable) {
super(player.getUniqueId(), title, size, closeable);
this.upperInventory = upperInventory;
this.playerInventory = player.getInventory();
}
protected void initUpperItems() {
@Override
protected void initItems() {
// init upper inventory
for (int i = 0; i < upperInventory.getSize(); i++) {
SlotElement element = getSlotElement(i);
redrawItem(i, element, true);
}
}
private void initPlayerItems() {
for (int i = upperInventory.getSize(); i < upperInventory.getSize() + 36; i++) {
SlotElement element = getSlotElement(i);
redrawItem(i, element, true);
}
}
private void clearPlayerInventory() {
// store and clear player inventory
Inventory inventory = getViewer().getInventory();
for (int i = 0; i < 36; i++) {
playerItems[i] = inventory.getItem(i);
inventory.setItem(i, null);
}
// init player inventory
for (int i = upperInventory.getSize(); i < upperInventory.getSize() + 36; i++) {
SlotElement element = getSlotElement(i);
redrawItem(i, element, true);
}
}
private void restorePlayerInventory() {
@ -71,7 +70,7 @@ public abstract class AbstractDoubleWindow extends AbstractWindow {
@Override
protected void setInvItem(int slot, ItemStack itemStack) {
if (slot >= upperInventory.getSize()) {
if (isCurrentlyOpened) {
if (isOpen()) {
int invSlot = SlotUtils.translateGuiToPlayerInv(slot - upperInventory.getSize());
setPlayerInvItem(invSlot, itemStack);
}
@ -88,7 +87,7 @@ public abstract class AbstractDoubleWindow extends AbstractWindow {
@Override
public void handleViewerDeath(PlayerDeathEvent event) {
if (isCurrentlyOpened) {
if (isOpen()) {
List<ItemStack> drops = event.getDrops();
if (!event.getKeepInventory()) {
drops.clear();
@ -103,15 +102,10 @@ public abstract class AbstractDoubleWindow extends AbstractWindow {
protected void handleOpened() {
// Prevent players from receiving advancements from UI items
InventoryAccess.getPlayerUtils().stopAdvancementListening(getViewer());
isCurrentlyOpened = true;
clearPlayerInventory();
initPlayerItems();
}
@Override
protected void handleClosed() {
isCurrentlyOpened = false;
restorePlayerInventory();
// Start the advancement listeners again
@ -136,7 +130,7 @@ public abstract class AbstractDoubleWindow extends AbstractWindow {
@Override
public Inventory[] getInventories() {
return isCurrentlyOpened ? new Inventory[] {upperInventory, playerInventory} : new Inventory[] {upperInventory};
return isOpen() ? new Inventory[] {upperInventory, playerInventory} : new Inventory[] {upperInventory};
}
public Inventory getUpperInventory() {
@ -147,8 +141,6 @@ public abstract class AbstractDoubleWindow extends AbstractWindow {
return playerInventory;
}
protected abstract SlotElement getSlotElement(int index);
protected abstract Pair<AbstractGui, Integer> getWhereClicked(InventoryClickEvent event);
}

@ -17,12 +17,11 @@ public abstract class AbstractMergedWindow extends AbstractDoubleWindow {
private final AbstractGui gui;
public AbstractMergedWindow(Player player, ComponentWrapper title, AbstractGui gui, Inventory upperInventory, boolean closeable, boolean retain) {
super(player, title, gui.getSize(), upperInventory, closeable, retain);
public AbstractMergedWindow(Player player, ComponentWrapper title, AbstractGui gui, Inventory upperInventory, boolean closeable) {
super(player, title, gui.getSize(), upperInventory, closeable);
this.gui = gui;
gui.addParent(this);
initUpperItems();
}
@Override

@ -25,16 +25,16 @@ public abstract class AbstractSingleWindow extends AbstractWindow {
private final int size;
protected Inventory inventory;
public AbstractSingleWindow(UUID viewerUUID, ComponentWrapper title, AbstractGui gui, Inventory inventory, boolean initItems, boolean closeable, boolean retain) {
super(viewerUUID, title, gui.getSize(), closeable, retain);
public AbstractSingleWindow(UUID viewerUUID, ComponentWrapper title, AbstractGui gui, Inventory inventory, boolean closeable) {
super(viewerUUID, title, gui.getSize(), closeable);
this.gui = gui;
this.size = gui.getSize();
this.inventory = inventory;
gui.addParent(this);
if (initItems) initItems();
}
@Override
protected void initItems() {
for (int i = 0; i < size; i++) {
SlotElement element = gui.getSlotElement(i);
@ -109,27 +109,27 @@ public abstract class AbstractSingleWindow extends AbstractWindow {
}
@SuppressWarnings("unchecked")
public abstract static class AbstractBuilder<W extends Window, V, S extends Builder.Single<W, V, S>>
extends AbstractWindow.AbstractBuilder<W, V, S>
implements Builder.Single<W, V, S>
public abstract static class AbstractBuilder<W extends Window, S extends Builder.Single<W, S>>
extends AbstractWindow.AbstractBuilder<W, S>
implements Builder.Single<W, S>
{
protected Supplier<Gui> guiSupplier;
@Override
public S setGui(@NotNull Supplier<Gui> guiSupplier) {
public @NotNull S setGui(@NotNull Supplier<Gui> guiSupplier) {
this.guiSupplier = guiSupplier;
return (S) this;
}
@Override
public S setGui(@NotNull Gui gui) {
public @NotNull S setGui(@NotNull Gui gui) {
this.guiSupplier = () -> gui;
return (S) this;
}
@Override
public S setGui(@NotNull Gui.Builder<?, ?> builder) {
public @NotNull S setGui(@NotNull Gui.Builder<?, ?> builder) {
this.guiSupplier = builder::build;
return (S) this;
}

@ -21,14 +21,13 @@ public abstract class AbstractSplitWindow extends AbstractDoubleWindow {
private final AbstractGui upperGui;
private final AbstractGui lowerGui;
public AbstractSplitWindow(Player player, ComponentWrapper title, AbstractGui upperGui, AbstractGui lowerGui, Inventory upperInventory, boolean initItems, boolean closeable, boolean retain) {
super(player, title, upperGui.getSize() + lowerGui.getSize(), upperInventory, closeable, retain);
public AbstractSplitWindow(Player player, ComponentWrapper title, AbstractGui upperGui, AbstractGui lowerGui, Inventory upperInventory, boolean closeable) {
super(player, title, upperGui.getSize() + lowerGui.getSize(), upperInventory, closeable);
this.upperGui = upperGui;
this.lowerGui = lowerGui;
upperGui.addParent(this);
lowerGui.addParent(this);
if (initItems) initUpperItems();
}
@Override
@ -68,46 +67,46 @@ public abstract class AbstractSplitWindow extends AbstractDoubleWindow {
}
@SuppressWarnings("unchecked")
public static abstract class AbstractBuilder<W extends Window, V, S extends Window.Builder.Double<W, V, S>>
extends AbstractWindow.AbstractBuilder<W, V, S>
implements Window.Builder.Double<W, V, S>
public static abstract class AbstractBuilder<W extends Window, S extends Window.Builder.Double<W, S>>
extends AbstractWindow.AbstractBuilder<W, S>
implements Window.Builder.Double<W, S>
{
protected Supplier<Gui> upperGuiSupplier;
protected Supplier<Gui> lowerGuiSupplier;
@Override
public S setUpperGui(@NotNull Supplier<Gui> guiSupplier) {
public @NotNull S setUpperGui(@NotNull Supplier<Gui> guiSupplier) {
this.upperGuiSupplier = guiSupplier;
return (S) this;
}
@Override
public S setUpperGui(@NotNull Gui gui) {
public @NotNull S setUpperGui(@NotNull Gui gui) {
this.upperGuiSupplier = () -> gui;
return (S) this;
}
@Override
public S setUpperGui(@NotNull Gui.Builder<?, ?> builder) {
public @NotNull S setUpperGui(@NotNull Gui.Builder<?, ?> builder) {
this.upperGuiSupplier = builder::build;
return (S) this;
}
@Override
public S setLowerGui(@NotNull Supplier<Gui> guiSupplier) {
public @NotNull S setLowerGui(@NotNull Supplier<Gui> guiSupplier) {
this.lowerGuiSupplier = guiSupplier;
return (S) this;
}
@Override
public S setLowerGui(@NotNull Gui gui) {
public @NotNull S setLowerGui(@NotNull Gui gui) {
this.lowerGuiSupplier = () -> gui;
return (S) this;
}
@Override
public S setLowerGui(@NotNull Gui.Builder<?, ?> builder) {
public @NotNull S setLowerGui(@NotNull Gui.Builder<?, ?> builder) {
this.lowerGuiSupplier = builder::build;
return (S) this;
}

@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
import xyz.xenondevs.inventoryaccess.InventoryAccess;
import xyz.xenondevs.inventoryaccess.component.BaseComponentWrapper;
import xyz.xenondevs.inventoryaccess.component.ComponentWrapper;
import xyz.xenondevs.inventoryaccess.component.i18n.Languages;
import xyz.xenondevs.invui.InvUI;
import xyz.xenondevs.invui.gui.AbstractGui;
import xyz.xenondevs.invui.gui.Gui;
@ -41,25 +42,20 @@ public abstract class AbstractWindow implements Window, GuiParent {
private static final NamespacedKey SLOT_KEY = new NamespacedKey(InvUI.getInstance().getPlugin(), "slot");
private final UUID viewerUUID;
private final boolean retain;
private final SlotElement[] elementsDisplayed;
private List<Runnable> openHandlers;
private List<Runnable> closeHandlers;
private ComponentWrapper title;
private boolean closeable;
private boolean removed;
private boolean currentlyOpen;
public AbstractWindow(UUID viewerUUID, ComponentWrapper title, int size, boolean closeable, boolean retain) {
public AbstractWindow(UUID viewerUUID, ComponentWrapper title, int size, boolean closeable) {
this.viewerUUID = viewerUUID;
this.title = title;
this.closeable = closeable;
this.retain = retain;
this.elementsDisplayed = new SlotElement[size];
}
protected void register() {
WindowManager.getInstance().addWindow(this);
}
protected void redrawItem(int index) {
redrawItem(index, getSlotElement(index), false);
}
@ -168,18 +164,29 @@ public abstract class AbstractWindow implements Window, GuiParent {
event.setCursor(cursorStack);
}
public void handleOpen(InventoryOpenEvent event) {
if (!event.getPlayer().equals(getViewer()))
public void handleOpenEvent(InventoryOpenEvent event) {
if (!event.getPlayer().equals(getViewer())) {
event.setCancelled(true);
else handleOpened();
} else {
if (currentlyOpen)
throw new IllegalStateException("Window is already opened!");
currentlyOpen = true;
handleOpened();
if (openHandlers != null) {
openHandlers.forEach(Runnable::run);
}
}
}
public void handleClose(Player player) {
public void handleCloseEvent(Player player) {
if (closeable) {
if (!retain) {
remove(false);
}
if (!currentlyOpen)
throw new IllegalStateException("Window is already closed!");
currentlyOpen = false;
remove(false);
handleClosed();
if (closeHandlers != null) {
@ -211,15 +218,7 @@ public abstract class AbstractWindow implements Window, GuiParent {
&& ((SlotElement.VISlotElement) element).getVirtualInventory() == virtualInventory);
}
public void remove() {
remove(true);
}
public void remove(boolean closeForViewer) {
if (removed)
return;
removed = true;
WindowManager.getInstance().removeWindow(this);
Arrays.stream(elementsDisplayed)
@ -252,14 +251,20 @@ public abstract class AbstractWindow implements Window, GuiParent {
@Override
public void show() {
if (removed) throw new IllegalStateException("The Window has already been closed.");
Player viewer = getViewer();
if (viewer == null) throw new IllegalStateException("The player is not online.");
if (viewer == null)
throw new IllegalStateException("The player is not online.");
initItems();
WindowManager.getInstance().addWindow(this);
openInventory(viewer);
}
protected void openInventory(@NotNull Player viewer) {
InventoryAccess.getInventoryUtils().openCustomInventory(
viewer,
getInventories()[0],
title.localized(viewer.getLocale())
title.localized(viewer)
);
}
@ -270,7 +275,7 @@ public abstract class AbstractWindow implements Window, GuiParent {
if (currentViewer != null) {
InventoryAccess.getInventoryUtils().updateOpenInventoryTitle(
currentViewer,
title.localized(currentViewer.getLocale())
title.localized(currentViewer)
);
}
}
@ -285,6 +290,19 @@ public abstract class AbstractWindow implements Window, GuiParent {
changeTitle(TextComponent.fromLegacyText(title));
}
@Override
public void setOpenHandlers(@NotNull List<@NotNull Runnable> openHandlers) {
this.openHandlers = openHandlers;
}
@Override
public void addOpenHandler(@NotNull Runnable openHandler) {
if (openHandlers == null)
openHandlers = new ArrayList<>();
openHandlers.add(openHandler);
}
@Override
public void setCloseHandlers(@NotNull List<@NotNull Runnable> closeHandlers) {
this.closeHandlers = closeHandlers;
@ -321,7 +339,7 @@ public abstract class AbstractWindow implements Window, GuiParent {
if (player == null)
throw new IllegalStateException("Tried to receive the language from a viewer that is not online.");
return player.getLocale();
return Languages.getInstance().getLanguage(player);
}
@Override
@ -340,8 +358,8 @@ public abstract class AbstractWindow implements Window, GuiParent {
}
@Override
public boolean isRemoved() {
return removed;
public boolean isOpen() {
return currentlyOpen;
}
protected abstract void setInvItem(int slot, ItemStack itemStack);
@ -354,6 +372,8 @@ public abstract class AbstractWindow implements Window, GuiParent {
protected abstract Inventory[] getInventories();
protected abstract void initItems();
protected abstract void handleOpened();
protected abstract void handleClosed();
@ -367,59 +387,68 @@ public abstract class AbstractWindow implements Window, GuiParent {
public abstract void handleViewerDeath(PlayerDeathEvent event);
@SuppressWarnings("unchecked")
public static abstract class AbstractBuilder<W extends Window, V, S extends Window.Builder<W, V, S>> implements Window.Builder<W, V, S> {
public static abstract class AbstractBuilder<W extends Window, S extends Window.Builder<W, S>> implements Window.Builder<W, S> {
protected V viewer;
protected Player viewer;
protected ComponentWrapper title;
protected boolean closeable = true;
protected boolean retain = false;
protected List<Runnable> openHandlers;
protected List<Runnable> closeHandlers;
protected List<Consumer<Window>> modifiers;
@Override
public S setViewer(@NotNull V viewer) {
public @NotNull S setViewer(@NotNull Player viewer) {
this.viewer = viewer;
return (S) this;
}
@Override
public S setTitle(@NotNull ComponentWrapper title) {
public @NotNull S setTitle(@NotNull ComponentWrapper title) {
this.title = title;
return (S) this;
}
@Override
public S setTitle(@NotNull BaseComponent @NotNull [] title) {
public @NotNull S setTitle(@NotNull BaseComponent @NotNull [] title) {
this.title = new BaseComponentWrapper(title);
return (S) this;
}
@Override
public S setTitle(@NotNull String title) {
public @NotNull S setTitle(@NotNull String title) {
this.title = new BaseComponentWrapper(TextComponent.fromLegacyText(title));
return (S) this;
}
@Override
public S setCloseable(boolean closeable) {
public @NotNull S setCloseable(boolean closeable) {
this.closeable = closeable;
return (S) this;
}
@Override
public S setRetain(boolean retain) {
this.retain = retain;
public @NotNull S setOpenHandlers(List<Runnable> openHandlers) {
this.openHandlers = openHandlers;
return (S) this;
}
@Override
public S setCloseHandlers(List<Runnable> closeHandlers) {
public @NotNull S addOpenHandler(Runnable openHandler) {
if (openHandlers == null)
openHandlers = new ArrayList<>();
openHandlers.add(openHandler);
return (S) this;
}
@Override
public @NotNull S setCloseHandlers(List<Runnable> closeHandlers) {
this.closeHandlers = closeHandlers;
return (S) this;
}
@Override
public S addCloseHandler(Runnable closeHandler) {
public @NotNull S addCloseHandler(Runnable closeHandler) {
if (closeHandlers == null)
closeHandlers = new ArrayList<>();
@ -428,13 +457,13 @@ public abstract class AbstractWindow implements Window, GuiParent {
}
@Override
public S setModifiers(List<Consumer<Window>> modifiers) {
public @NotNull S setModifiers(List<Consumer<Window>> modifiers) {
this.modifiers = modifiers;
return (S) this;
}
@Override
public S addModifier(Consumer<Window> modifier) {
public @NotNull S addModifier(Consumer<Window> modifier) {
if (modifiers == null)
modifiers = new ArrayList<>();
@ -450,11 +479,21 @@ public abstract class AbstractWindow implements Window, GuiParent {
modifiers.forEach(modifier -> modifier.accept(window));
}
@Override
public @NotNull W build() {
return build(viewer);
}
@Override
public void show(Player viewer) {
build(viewer).show();
}
@SuppressWarnings("unchecked")
@Override
public @NotNull S clone() {
try {
var clone = (AbstractBuilder<W, V, S>) super.clone();
var clone = (AbstractBuilder<W, S>) super.clone();
if (title != null)
clone.title = title.clone();
if (closeHandlers != null)
@ -469,5 +508,4 @@ public abstract class AbstractWindow implements Window, GuiParent {
}
}

@ -22,15 +22,11 @@ final class AnvilSingleWindowImpl extends AbstractSingleWindow implements AnvilW
@Nullable ComponentWrapper title,
@NotNull AbstractGui gui,
@Nullable List<@NotNull Consumer<@NotNull String>> renameHandlers,
boolean closable,
boolean retain
boolean closable
) {
super(player.getUniqueId(), title, gui, null, false, closable, retain);
anvilInventory = InventoryAccess.createAnvilInventory(player, title, renameHandlers);
super(player.getUniqueId(), title, gui, null, closable);
anvilInventory = InventoryAccess.createAnvilInventory(player, title.localized(player), renameHandlers);
inventory = anvilInventory.getBukkitInventory();
initItems();
register();
}
@Override
@ -39,11 +35,7 @@ final class AnvilSingleWindowImpl extends AbstractSingleWindow implements AnvilW
}
@Override
public void show() {
if (isRemoved()) throw new IllegalStateException("The Window has already been closed.");
Player viewer = getViewer();
if (viewer == null) throw new IllegalStateException("The player is not online.");
protected void openInventory(@NotNull Player viewer) {
anvilInventory.open();
}
@ -53,7 +45,7 @@ final class AnvilSingleWindowImpl extends AbstractSingleWindow implements AnvilW
}
public static final class BuilderImpl
extends AbstractSingleWindow.AbstractBuilder<AnvilWindow, Player, AnvilWindow.Builder.Single>
extends AbstractSingleWindow.AbstractBuilder<AnvilWindow, AnvilWindow.Builder.Single>
implements AnvilWindow.Builder.Single
{
@ -75,7 +67,7 @@ final class AnvilSingleWindowImpl extends AbstractSingleWindow implements AnvilW
}
@Override
public @NotNull AnvilWindow build() {
public @NotNull AnvilWindow build(Player viewer) {
if (viewer == null)
throw new IllegalStateException("Viewer is not defined.");
if (guiSupplier == null)
@ -86,8 +78,7 @@ final class AnvilSingleWindowImpl extends AbstractSingleWindow implements AnvilW
title,
(AbstractGui) guiSupplier.get(),
renameHandlers,
closeable,
retain
closeable
);
applyModifiers(window);

@ -23,16 +23,12 @@ final class AnvilSplitWindowImpl extends AbstractSplitWindow implements AnvilWin
@NotNull AbstractGui upperGui,
@NotNull AbstractGui lowerGui,
@Nullable List<@NotNull Consumer<@NotNull String>> renameHandlers,
boolean closeable,
boolean retain
boolean closeable
) {
super(player, title, upperGui, lowerGui, null, false, closeable, retain);
super(player, title, upperGui, lowerGui, null, closeable);
anvilInventory = InventoryAccess.createAnvilInventory(player, title, renameHandlers);
anvilInventory = InventoryAccess.createAnvilInventory(player, title.localized(player), renameHandlers);
upperInventory = anvilInventory.getBukkitInventory();
initUpperItems();
register();
}
@Override
@ -41,11 +37,7 @@ final class AnvilSplitWindowImpl extends AbstractSplitWindow implements AnvilWin
}
@Override
public void show() {
if (isRemoved()) throw new IllegalStateException("The Window has already been closed.");
Player viewer = getViewer();
if (viewer == null) throw new IllegalStateException("The player is not online.");
protected void openInventory(@NotNull Player viewer) {
anvilInventory.open();
}
@ -55,7 +47,7 @@ final class AnvilSplitWindowImpl extends AbstractSplitWindow implements AnvilWin
}
public static final class BuilderImpl
extends AbstractSplitWindow.AbstractBuilder<AnvilWindow, Player, AnvilWindow.Builder.Split>
extends AbstractSplitWindow.AbstractBuilder<AnvilWindow, AnvilWindow.Builder.Split>
implements AnvilWindow.Builder.Split
{
@ -77,7 +69,7 @@ final class AnvilSplitWindowImpl extends AbstractSplitWindow implements AnvilWin
}
@Override
public @NotNull AnvilWindow build() {
public @NotNull AnvilWindow build(Player viewer) {
if (viewer == null)
throw new IllegalStateException("Viewer is not defined.");
if (upperGuiSupplier == null)
@ -91,8 +83,7 @@ final class AnvilSplitWindowImpl extends AbstractSplitWindow implements AnvilWin
(AbstractGui) upperGuiSupplier.get(),
(AbstractGui) lowerGuiSupplier.get(),
renameHandlers,
closeable,
retain
closeable
);
applyModifiers(window);

@ -65,7 +65,7 @@ public interface AnvilWindow extends Window {
* @see Window.Builder.Normal
* @see CartographyWindow.Builder
*/
interface Builder<S extends Builder<S>> extends Window.Builder<AnvilWindow, Player, S> {
interface Builder<S extends Builder<S>> extends Window.Builder<AnvilWindow, S> {
/**
* Sets the rename handlers of the {@link AnvilWindow}.
@ -90,7 +90,7 @@ public interface AnvilWindow extends Window {
* @see Window.Builder.Normal.Single
* @see CartographyWindow.Builder.Single
*/
interface Single extends Builder<Single>, Window.Builder.Single<AnvilWindow, Player, Single> {}
interface Single extends Builder<Single>, Window.Builder.Single<AnvilWindow, Single> {}
/**
* A split {@link AnvilWindow} builder. Combines both {@link AnvilWindow.Builder} and {@link Window.Builder.Double}
@ -100,7 +100,7 @@ public interface AnvilWindow extends Window {
* @see Window.Builder.Normal.Split
* @see CartographyWindow.Builder.Split
*/
interface Split extends Builder<Split>, Window.Builder.Double<AnvilWindow, Player, Split> {}
interface Split extends Builder<Split>, Window.Builder.Double<AnvilWindow, Split> {}
}

@ -26,18 +26,15 @@ final class CartographySingleWindowImpl extends AbstractSingleWindow implements
@NotNull Player player,
@Nullable ComponentWrapper title,
@NotNull AbstractGui gui,
boolean closeable,
boolean retain
boolean closeable
) {
super(player.getUniqueId(), title, gui, null, false, closeable, retain);
super(player.getUniqueId(), title, gui, null, closeable);
if (gui.getWidth() != 2 || gui.getHeight() != 1) throw new IllegalArgumentException("Gui has to be 2x1");
cartographyInventory = InventoryAccess.createCartographyInventory(player, title);
cartographyInventory = InventoryAccess.createCartographyInventory(player, title.localized(player));
inventory = cartographyInventory.getBukkitInventory();
initItems();
resetMap();
register();
}
@Override
@ -71,23 +68,17 @@ final class CartographySingleWindowImpl extends AbstractSingleWindow implements
}
@Override
public void show() {
if (isRemoved())
throw new IllegalStateException("The Window has already been closed.");
Player viewer = getViewer();
if (viewer == null)
throw new IllegalStateException("The player is not online.");
protected void openInventory(@NotNull Player viewer) {
cartographyInventory.open();
}
public static final class BuilderImpl
extends AbstractSingleWindow.AbstractBuilder<CartographyWindow, Player, CartographyWindow.Builder.Single>
extends AbstractSingleWindow.AbstractBuilder<CartographyWindow, CartographyWindow.Builder.Single>
implements CartographyWindow.Builder.Single
{
@Override
public @NotNull CartographyWindow build() {
public @NotNull CartographyWindow build(Player viewer) {
if (viewer == null)
throw new IllegalStateException("Viewer is not defined.");
if (guiSupplier == null)
@ -97,8 +88,7 @@ final class CartographySingleWindowImpl extends AbstractSingleWindow implements
viewer,
title,
(AbstractGui) guiSupplier.get(),
closeable,
retain
closeable
);
applyModifiers(window);

@ -27,17 +27,14 @@ final class CartographySplitWindowImpl extends AbstractSplitWindow implements Ca
@Nullable ComponentWrapper title,
@NotNull AbstractGui upperGui,
@NotNull AbstractGui lowerGui,
boolean closeable,
boolean retain
boolean closeable
) {
super(player, title, createWrappingGui(upperGui), lowerGui, null, false, closeable, retain);
super(player, title, createWrappingGui(upperGui), lowerGui, null, closeable);
cartographyInventory = InventoryAccess.createCartographyInventory(player, title);
cartographyInventory = InventoryAccess.createCartographyInventory(player, title.localized(player));
upperInventory = cartographyInventory.getBukkitInventory();
initUpperItems();
resetMap();
register();
}
private static AbstractGui createWrappingGui(Gui upperGui) {
@ -66,23 +63,17 @@ final class CartographySplitWindowImpl extends AbstractSplitWindow implements Ca
}
@Override
public void show() {
if (isRemoved())
throw new IllegalStateException("The Window has already been closed.");
Player viewer = getViewer();
if (viewer == null)
throw new IllegalStateException("The player is not online.");
protected void openInventory(@NotNull Player viewer) {
cartographyInventory.open();
}
public static final class BuilderImpl
extends AbstractSplitWindow.AbstractBuilder<CartographyWindow, Player, CartographyWindow.Builder.Split>
extends AbstractSplitWindow.AbstractBuilder<CartographyWindow, CartographyWindow.Builder.Split>
implements CartographyWindow.Builder.Split
{
@Override
public @NotNull CartographyWindow build() {
public @NotNull CartographyWindow build(Player viewer) {
if (viewer == null)
throw new IllegalStateException("Viewer is not defined.");
if (upperGuiSupplier == null)
@ -93,8 +84,7 @@ final class CartographySplitWindowImpl extends AbstractSplitWindow implements Ca
title,
(AbstractGui) upperGuiSupplier.get(),
(AbstractGui) lowerGuiSupplier.get(),
closeable,
retain
closeable
);
applyModifiers(window);

@ -95,21 +95,21 @@ public interface CartographyWindow extends Window {
* @see Window.Builder.Normal
* @see Window.Builder
*/
interface Builder<S extends Builder<S>> extends Window.Builder<CartographyWindow, Player, S> {
interface Builder<S extends Builder<S>> extends Window.Builder<CartographyWindow, S> {
/**
* A single {@link CartographyWindow} builder. Combines both {@link CartographyWindow.Builder} an
* {@link Window.Builder.Single} for a {@link CartographyWindow} with only one {@link Gui} that does not
* access the {@link Player Player's} inventory.
*/
interface Single extends Builder<Single>, Window.Builder.Single<CartographyWindow, Player, Single> {}
interface Single extends Builder<Single>, Window.Builder.Single<CartographyWindow, Single> {}
/**
* A split {@link CartographyWindow} builder. Combines both {@link CartographyWindow.Builder} an
* {@link Window.Builder.Double} for a {@link CartographyWindow} with two {@link Gui Guis}, where the lower
* {@link Gui} is used to fill the {@link Player Player's} inventory.
*/
interface Split extends Builder<Split>, Window.Builder.Double<CartographyWindow, Player, Split> {}
interface Split extends Builder<Split>, Window.Builder.Double<CartographyWindow, Split> {}
}

@ -15,11 +15,9 @@ final class NormalMergedWindowImpl extends AbstractMergedWindow {
@NotNull Player player,
@Nullable ComponentWrapper title,
@NotNull AbstractGui gui,
boolean closeable,
boolean retain
boolean closeable
) {
super(player, title, gui, createInventory(gui), closeable, retain);
register();
super(player, title, gui, createInventory(gui), closeable);
}
private static Inventory createInventory(Gui gui) {
@ -32,12 +30,12 @@ final class NormalMergedWindowImpl extends AbstractMergedWindow {
}
public static final class BuilderImpl
extends AbstractSingleWindow.AbstractBuilder<Window, Player, Window.Builder.Normal.Merged>
extends AbstractSingleWindow.AbstractBuilder<Window, Window.Builder.Normal.Merged>
implements Window.Builder.Normal.Merged
{
@Override
public @NotNull Window build() {
public @NotNull Window build(Player viewer) {
if (viewer == null)
throw new IllegalStateException("Viewer is not defined.");
if (guiSupplier == null)
@ -47,8 +45,7 @@ final class NormalMergedWindowImpl extends AbstractMergedWindow {
viewer,
title,
(AbstractGui) guiSupplier.get(),
closeable,
retain
closeable
);
applyModifiers(window);

@ -1,41 +1,30 @@
package xyz.xenondevs.invui.window;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.Contract;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.xenondevs.inventoryaccess.component.ComponentWrapper;
import xyz.xenondevs.invui.gui.AbstractGui;
import xyz.xenondevs.invui.util.InventoryUtils;
import java.util.UUID;
final class NormalSingleWindowImpl extends AbstractSingleWindow {
public NormalSingleWindowImpl(
@NotNull UUID viewerUUID,
@NotNull Player player,
@Nullable ComponentWrapper title,
@NotNull AbstractGui gui,
boolean closeable,
boolean retain
boolean closeable
) {
super(viewerUUID, title, gui, InventoryUtils.createMatchingInventory(gui, ""), true, closeable, retain);
register();
super(player.getUniqueId(), title, gui, InventoryUtils.createMatchingInventory(gui, ""), closeable);
}
public static final class BuilderImpl
extends AbstractSingleWindow.AbstractBuilder<Window, UUID, Window.Builder.Normal.Single>
extends AbstractSingleWindow.AbstractBuilder<Window, Window.Builder.Normal.Single>
implements Window.Builder.Normal.Single
{
@Contract("_ -> this")
public BuilderImpl setViewer(@NotNull OfflinePlayer player) {
setViewer(player.getUniqueId());
return this;
}
@Override
public @NotNull Window build() {
public @NotNull Window build(Player viewer) {
if (viewer == null)
throw new IllegalStateException("Viewer is not defined.");
if (guiSupplier == null)
@ -45,8 +34,7 @@ final class NormalSingleWindowImpl extends AbstractSingleWindow {
viewer,
title,
(AbstractGui) guiSupplier.get(),
closeable,
retain
closeable
);
applyModifiers(window);

@ -14,20 +14,18 @@ final class NormalSplitWindowImpl extends AbstractSplitWindow {
@Nullable ComponentWrapper title,
@NotNull AbstractGui upperGui,
@NotNull AbstractGui lowerGui,
boolean closeable,
boolean retain
boolean closeable
) {
super(player, title, upperGui, lowerGui, InventoryUtils.createMatchingInventory(upperGui, ""), true, closeable, retain);
register();
super(player, title, upperGui, lowerGui, InventoryUtils.createMatchingInventory(upperGui, ""), closeable);
}
public static final class BuilderImpl
extends AbstractSplitWindow.AbstractBuilder<Window, Player, Window.Builder.Normal.Split>
extends AbstractSplitWindow.AbstractBuilder<Window, Window.Builder.Normal.Split>
implements Window.Builder.Normal.Split
{
@Override
public @NotNull Window build() {
public @NotNull Window build(Player viewer) {
if (viewer == null)
throw new IllegalStateException("Viewer is not defined.");
if (upperGuiSupplier == null)
@ -40,8 +38,7 @@ final class NormalSplitWindowImpl extends AbstractSplitWindow {
title,
(AbstractGui) upperGuiSupplier.get(),
(AbstractGui) lowerGuiSupplier.get(),
closeable,
retain
closeable
);
applyModifiers(window);

@ -1,7 +1,6 @@
package xyz.xenondevs.invui.window;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.Contract;
@ -113,17 +112,11 @@ public interface Window {
void close();
/**
* Gets if the {@link Window} is closed and can't be shown again.
* Gets if the viewer is currently viewing this {@link Window}.
*
* @return If the {@link Window} is closed.
* @return If the {@link Window} is currently open.
*/
boolean isRemoved();
/**
* Removes the {@link Window} from the {@link WindowManager} list.
* If this method is called, the {@link Window} can't be shown again.
*/
void remove();
boolean isOpen();
/**
* Changes the title of the {@link Inventory}.
@ -168,6 +161,20 @@ public interface Window {
*/
@NotNull UUID getViewerUUID();
/**
* Replaces the currently registered open handlers with the given list.
*
* @param openHandlers The new open handlers
*/
void setOpenHandlers(@NotNull List<@NotNull Runnable> openHandlers);
/**
* Adds an open handler that will be called when this window gets opened.
*
* @param openHandler The close handler to add
*/
void addOpenHandler(@NotNull Runnable openHandler);
/**
* Replaces the currently registered close handlers with the given list.
*
@ -193,10 +200,9 @@ public interface Window {
* A {@link Window} builder.
*
* @param <W> The window type
* @param <V> The viewer type
* @param <S> The builder type
*/
interface Builder<W extends Window, V, S extends Builder<W, V, S>> extends Cloneable {
interface Builder<W extends Window, S extends Builder<W, S>> extends Cloneable {
/**
* Sets the viewer of the {@link Window}.
@ -205,7 +211,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setViewer(@NotNull V viewer);
@NotNull S setViewer(@NotNull Player viewer);
/**
* Sets the title of the {@link Window}.
@ -214,7 +220,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setTitle(@NotNull ComponentWrapper title);
@NotNull S setTitle(@NotNull ComponentWrapper title);
/**
* Sets the title of the {@link Window}.
@ -223,7 +229,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setTitle(@NotNull BaseComponent @NotNull [] title);
@NotNull S setTitle(@NotNull BaseComponent @NotNull [] title);
/**
* Sets the title of the {@link Window}.
@ -232,7 +238,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setTitle(@NotNull String title);
@NotNull S setTitle(@NotNull String title);
/**
* Configures if the {@link Window} is closeable.
@ -241,16 +247,25 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setCloseable(boolean closeable);
@NotNull S setCloseable(boolean closeable);
/**
* Configures if the {@link Window} should be retained after it has been closed.
* Sets the open handlers of the {@link Window}.
*
* @param retain If the {@link Window} should be retained
* @param openHandlers The open handlers of the {@link Window}
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setRetain(boolean retain);
@NotNull S setOpenHandlers(List<Runnable> openHandlers);
/**
* Adds an open handler to the {@link Window}.
*
* @param openHandler The open handler to add
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
@NotNull S addOpenHandler(Runnable openHandler);
/**
* Sets the close handlers of the {@link Window}.
@ -259,7 +274,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setCloseHandlers(List<Runnable> closeHandlers);
@NotNull S setCloseHandlers(List<Runnable> closeHandlers);
/**
* Adds a close handler to the {@link Window}.
@ -268,7 +283,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S addCloseHandler(Runnable closeHandler);
@NotNull S addCloseHandler(Runnable closeHandler);
/**
* Sets the modifiers of the {@link Window}.
@ -277,7 +292,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S setModifiers(List<Consumer<Window>> modifiers);
@NotNull S setModifiers(List<Consumer<Window>> modifiers);
/**
* Adds a modifier to the {@link Window}.
@ -286,7 +301,7 @@ public interface Window {
* @return This {@link Builder Window Builder}
*/
@Contract("_ -> this")
S addModifier(Consumer<Window> modifier);
@NotNull S addModifier(Consumer<Window> modifier);
/**
* Builds the {@link Window}.
@ -296,6 +311,23 @@ public interface Window {
@Contract("-> new")
@NotNull W build();
/**
* Builds the {@link Window} with the specified viewer.
* If this method is used, the viewer does not need to be set using {@link #setViewer(Player)}.
*
* @param viewer The {@link Player} to build the {@link Window} for.
*/
@Contract("_ -> new")
@NotNull W build(Player viewer);
/**
* Builds and shows the {@link Window} to the specified viewer.
* If this method is used, the viewer does not need to be set using {@link #setViewer(Player)}.
*
* @param viewer The {@link Player} to show the {@link Window} to.
*/
void show(Player viewer);
/**
* Clones the {@link Builder Window Builder}.
*
@ -308,15 +340,13 @@ public interface Window {
* A single {@link Window} builder. Single Windows only have on {@link Gui}.
*
* @param <W> The window type
* @param <V> The viewer type
* @param <S> The builder type
*
* @see Window.Builder.Normal.Single
* @see Window.Builder.Normal.Merged
* @see AnvilWindow.Builder.Single
* @see CartographyWindow.Builder.Single
*/
interface Single<W extends Window, V, S extends Single<W, V, S>> extends Builder<W, V, S> {
interface Single<W extends Window, S extends Single<W, S>> extends Builder<W, S> {
/**
* Sets the {@link Gui} of the {@link Window}.
@ -325,7 +355,7 @@ public interface Window {
* @return This {@link Single Window Builder}
*/
@Contract("_ -> this")
S setGui(@NotNull Gui gui);
@NotNull S setGui(@NotNull Gui gui);
/**
* Sets the {@link Gui.Builder} for this {@link Single Window Builder}.
@ -335,7 +365,7 @@ public interface Window {
* @return This {@link Single Window Builder}
*/
@Contract("_ -> this")
S setGui(@NotNull Gui.Builder<?, ?> builder);
@NotNull S setGui(@NotNull Gui.Builder<?, ?> builder);
/**
* Sets the {@link Gui} {@link Supplier} for this {@link Single Window Builder}.
@ -345,7 +375,7 @@ public interface Window {
* @return This {@link Single Window Builder}
*/
@Contract("_ -> this")
S setGui(@NotNull Supplier<Gui> guiSupplier);
@NotNull S setGui(@NotNull Supplier<Gui> guiSupplier);
}
@ -353,14 +383,12 @@ public interface Window {
* A double {@link Window} builder. Double Windows have two {@link Gui Guis}.
*
* @param <W> The window type
* @param <V> The viewer type
* @param <S> The builder type
*
* @see Window.Builder.Normal.Split
* @see AnvilWindow.Builder.Split
* @see CartographyWindow.Builder.Split
*/
interface Double<W extends Window, V, S extends Builder.Double<W, V, S>> extends Builder<W, V, S> {
interface Double<W extends Window, S extends Builder.Double<W, S>> extends Builder<W, S> {
/**
* Sets the upper {@link Gui} of the {@link Window}.
@ -369,7 +397,7 @@ public interface Window {
* @return This {@link Double Window Builder}
*/
@Contract("_ -> this")
S setUpperGui(@NotNull Gui gui);
@NotNull S setUpperGui(@NotNull Gui gui);
/**
* Sets the {@link Gui.Builder} for the upper {@link Gui} of this {@link Double Window Builder}.
@ -379,7 +407,7 @@ public interface Window {
* @return This {@link Double Window Builder}
*/
@Contract("_ -> this")
S setUpperGui(@NotNull Gui.Builder<?, ?> builder);
@NotNull S setUpperGui(@NotNull Gui.Builder<?, ?> builder);
/**
* Sets the {@link Gui} {@link Supplier} for the upper {@link Gui} of this {@link Double Window Builder}.
@ -389,7 +417,7 @@ public interface Window {
* @return This {@link Double Window Builder}
*/
@Contract("_ -> this")
S setUpperGui(@NotNull Supplier<Gui> guiSupplier);
@NotNull S setUpperGui(@NotNull Supplier<Gui> guiSupplier);
/**
* Sets the lower {@link Gui} of the {@link Window}.
@ -398,7 +426,7 @@ public interface Window {
* @return This {@link Double Window Builder}
*/
@Contract("_ -> this")
S setLowerGui(@NotNull Gui gui);
@NotNull S setLowerGui(@NotNull Gui gui);
/**
* Sets the {@link Gui.Builder} for the lower {@link Gui} of this {@link Double Window Builder}.
@ -408,7 +436,7 @@ public interface Window {
* @return This {@link Double Window Builder}
*/
@Contract("_ -> this")
S setLowerGui(@NotNull Gui.Builder<?, ?> builder);
@NotNull S setLowerGui(@NotNull Gui.Builder<?, ?> builder);
/**
* Sets the {@link Gui} {@link Supplier} for the lower {@link Gui} of this {@link Double Window Builder}.
@ -418,7 +446,7 @@ public interface Window {
* @return This {@link Double Window Builder}
*/
@Contract("_ -> this")
S setLowerGui(@NotNull Supplier<Gui> guiSupplier);
@NotNull S setLowerGui(@NotNull Supplier<Gui> guiSupplier);
}
@ -426,13 +454,11 @@ public interface Window {
* A normal {@link Window} builder for {@link Window Windows} of inventories with no special functionality, such
* as chests, hoppers and droppers.
*
* @param <V> The viewer type
* @param <S> The builder type
*
* @see AnvilWindow.Builder
* @see CartographyWindow.Builder
*/
interface Normal<V, S extends Normal<V, S>> extends Builder<Window, V, S> {
interface Normal<V, S extends Normal<V, S>> extends Builder<Window, S> {
/**
* A normal single {@link Window} builder. Combines both {@link Builder.Single} and {@link Builder.Normal}
@ -441,18 +467,7 @@ public interface Window {
* @see AnvilWindow.Builder.Single
* @see CartographyWindow.Builder.Single
*/
interface Single extends Builder.Normal<UUID, Single>, Builder.Single<Window, UUID, Single> {
/**
* Sets the viewer of the {@link Window}.
*
* @param viewer The viewer of the {@link Window}
* @return This {@link Normal.Single Window Builder}
*/
@Contract("_ -> this")
Normal.Single setViewer(@NotNull OfflinePlayer viewer);
}
interface Single extends Builder.Normal<UUID, Single>, Builder.Single<Window, Single> {}
/**
* A normal split {@link Window} builder. Combines both {@link Builder.Double} and {@link Builder.Normal}
@ -462,14 +477,14 @@ public interface Window {
* @see AnvilWindow.Builder.Split
* @see CartographyWindow.Builder.Split
*/
interface Split extends Builder.Normal<Player, Split>, Builder.Double<Window, Player, Split> {}
interface Split extends Builder.Normal<Player, Split>, Builder.Double<Window, Split> {}
/**
* A normal merged {@link Window} builder. Combines both {@link Builder.Single} and {@link Builder.Normal}
* for a normal {@link Window} with one {@link Gui}, which fills both the upper inventory and the
* {@link Player Player's} inventory.
*/
interface Merged extends Builder.Normal<Player, Merged>, Builder.Single<Window, Player, Merged> {}
interface Merged extends Builder.Normal<Player, Merged>, Builder.Single<Window, Merged> {}
}

@ -152,7 +152,7 @@ public class WindowManager implements Listener {
AbstractWindow window = (AbstractWindow) getWindow(event.getInventory());
if (window != null)
window.handleClose(player);
window.handleCloseEvent(player);
openWindows.remove(player);
}
@ -161,7 +161,7 @@ public class WindowManager implements Listener {
private void handleInventoryOpen(InventoryOpenEvent event) {
AbstractWindow window = (AbstractWindow) getWindow(event.getInventory());
if (window != null) {
window.handleOpen(event);
window.handleOpenEvent(event);
openWindows.put((Player) event.getPlayer(), window);
}
}
@ -171,7 +171,7 @@ public class WindowManager implements Listener {
Player player = event.getPlayer();
AbstractWindow window = (AbstractWindow) getOpenWindow(player);
if (window != null) {
window.handleClose(player);
window.handleCloseEvent(player);
openWindows.remove(player);
}
}