From e4980188e27cb727558fd36e133f18fc5f512346 Mon Sep 17 00:00:00 2001 From: NichtStudioCode <51272202+NichtStudioCode@users.noreply.github.com> Date: Thu, 28 Jan 2021 00:31:21 +0100 Subject: [PATCH] GUIParent & GUI-based Animations --- .../invgui/animation/Animation.java | 19 ++- .../invgui/animation/impl/BaseAnimation.java | 94 +++++++----- .../invgui/animation/impl/SoundAnimation.java | 4 +- .../java/de/studiocode/invgui/gui/GUI.java | 43 +++++- .../de/studiocode/invgui/gui/GUIParent.java | 13 ++ .../studiocode/invgui/gui/impl/BaseGUI.java | 8 +- .../invgui/gui/impl/IndexedGUI.java | 140 +++++++++++++++++- .../de/studiocode/invgui/window/Window.java | 21 +-- .../invgui/window/WindowManager.java | 2 - .../invgui/window/impl/BaseWindow.java | 63 ++------ 10 files changed, 272 insertions(+), 135 deletions(-) create mode 100644 src/main/java/de/studiocode/invgui/gui/GUIParent.java diff --git a/src/main/java/de/studiocode/invgui/animation/Animation.java b/src/main/java/de/studiocode/invgui/animation/Animation.java index 4f129e3..1c32657 100644 --- a/src/main/java/de/studiocode/invgui/animation/Animation.java +++ b/src/main/java/de/studiocode/invgui/animation/Animation.java @@ -1,7 +1,7 @@ package de.studiocode.invgui.animation; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; +import de.studiocode.invgui.gui.GUI; +import de.studiocode.invgui.window.Window; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -10,20 +10,19 @@ import java.util.function.BiConsumer; public interface Animation { /** - * Sets the {@link Player} that will see this animation. - * Useful for playing sounds in a showHandler. ({@link #addShowHandler(BiConsumer)}) + * Sets the {@link GUI} this {@link Animation} will take place in. * - * @param player The {@link Player} that will se this {@link Animation}. + * @param gui The {@link GUI} this {@link Animation} will take place in */ - void setPlayer(@NotNull Player player); + void setGUI(GUI gui); /** - * Sets the bounds of the {@link Inventory} this {@link Animation} will take place in. + * Sets the {@link Window}s that will see this animation. + * Useful for playing sounds in a showHandler. ({@link #addShowHandler(BiConsumer)}) * - * @param width The width of the {@link Inventory} - * @param height The height {@link Inventory} + * @param windows The {@link Window}s that will see this animation */ - void setBounds(int width, int height); + void setWindows(@NotNull List windows); /** * Sets the slots that should be shown. diff --git a/src/main/java/de/studiocode/invgui/animation/impl/BaseAnimation.java b/src/main/java/de/studiocode/invgui/animation/impl/BaseAnimation.java index 4cdf987..bc06e6e 100644 --- a/src/main/java/de/studiocode/invgui/animation/impl/BaseAnimation.java +++ b/src/main/java/de/studiocode/invgui/animation/impl/BaseAnimation.java @@ -2,41 +2,58 @@ package de.studiocode.invgui.animation.impl; import de.studiocode.invgui.InvGui; import de.studiocode.invgui.animation.Animation; +import de.studiocode.invgui.gui.GUI; import de.studiocode.invgui.util.SlotUtils; +import de.studiocode.invgui.window.Window; import org.bukkit.Bukkit; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.BiConsumer; +import java.util.stream.Collectors; public abstract class BaseAnimation implements Animation { - private final int tickDelay; private final List finishHandlers = new ArrayList<>(); + private final int tickDelay; + + private GUI gui; private int width; private int height; - private int size; - private Player player; + + private List windows; private CopyOnWriteArrayList slots; private BiConsumer show; private BukkitTask task; + private int frame; + private int noViewerTicks; public BaseAnimation(int tickDelay) { this.tickDelay = tickDelay; } - protected abstract void handleFrame(int frame); + @Override + public void setGUI(GUI gui) { + this.gui = gui; + this.width = gui.getWidth(); + this.height = gui.getHeight(); + } @Override - public void setBounds(int width, int height) { - this.width = width; - this.height = height; - this.size = width * height; + public void setWindows(@NotNull List windows) { + this.windows = windows; + } + + @Override + public void setSlots(List slots) { + this.slots = new CopyOnWriteArrayList<>(slots); } @Override @@ -45,22 +62,32 @@ public abstract class BaseAnimation implements Animation { else this.show = show; } - protected void show(int... slots) { - for (int i : slots) show.accept(frame, i); - } - @Override public void addFinishHandler(@NotNull Runnable finish) { finishHandlers.add(finish); } - public CopyOnWriteArrayList getSlots() { - return slots; + @Override + public void start() { + task = Bukkit.getScheduler().runTaskTimer(InvGui.getInstance().getPlugin(), () -> { + // if there are now viewers for more than 3 ticks, the animation can be cancelled + if (getViewers().isEmpty()) { + noViewerTicks++; + if (noViewerTicks > 3) { + gui.cancelAnimation(); + return; + } + } else noViewerTicks = 0; + + // handle the next frame + handleFrame(frame); + frame++; + }, 0, tickDelay); } @Override - public void setSlots(List slots) { - this.slots = new CopyOnWriteArrayList<>(slots); + public void cancel() { + task.cancel(); } protected void finish() { @@ -68,11 +95,14 @@ public abstract class BaseAnimation implements Animation { finishHandlers.forEach(Runnable::run); } - public void start() { - task = Bukkit.getScheduler().runTaskTimer(InvGui.getInstance().getPlugin(), () -> { - handleFrame(frame); - frame++; - }, 0, tickDelay); + protected abstract void handleFrame(int frame); + + public CopyOnWriteArrayList getSlots() { + return slots; + } + + protected void show(int... slots) { + for (int i : slots) show.accept(frame, i); } protected int convToIndex(int x, int y) { @@ -82,10 +112,6 @@ public abstract class BaseAnimation implements Animation { return SlotUtils.convertToIndex(x, y, width); } - public void cancel() { - task.cancel(); - } - protected int getWidth() { return width; } @@ -94,16 +120,14 @@ public abstract class BaseAnimation implements Animation { return height; } - protected int getSize() { - return size; - } - - protected Player getPlayer() { - return player; - } - - public void setPlayer(@NotNull Player player) { - this.player = player; + public List getViewers() { + return windows.stream() + .map(window -> { + List viewers = window.getInventory().getViewers(); + return (Player) (viewers.isEmpty() ? null : viewers.get(0)); + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } } diff --git a/src/main/java/de/studiocode/invgui/animation/impl/SoundAnimation.java b/src/main/java/de/studiocode/invgui/animation/impl/SoundAnimation.java index 5aa911d..ffd1e33 100644 --- a/src/main/java/de/studiocode/invgui/animation/impl/SoundAnimation.java +++ b/src/main/java/de/studiocode/invgui/animation/impl/SoundAnimation.java @@ -7,8 +7,8 @@ public abstract class SoundAnimation extends BaseAnimation { public SoundAnimation(int tickDelay, boolean sound) { super(tickDelay); - if (sound) addShowHandler((frame, index) -> getPlayer().playSound(getPlayer().getLocation(), - Sound.ENTITY_ITEM_PICKUP, 1, 1)); + if (sound) addShowHandler((frame, index) -> getViewers().forEach(player -> + player.playSound(player.getLocation(), Sound.ENTITY_ITEM_PICKUP, 1, 1))); } } diff --git a/src/main/java/de/studiocode/invgui/gui/GUI.java b/src/main/java/de/studiocode/invgui/gui/GUI.java index 07b66da..bb0a592 100644 --- a/src/main/java/de/studiocode/invgui/gui/GUI.java +++ b/src/main/java/de/studiocode/invgui/gui/GUI.java @@ -1,5 +1,6 @@ package de.studiocode.invgui.gui; +import de.studiocode.invgui.animation.Animation; import de.studiocode.invgui.gui.SlotElement.ItemStackHolder; import de.studiocode.invgui.gui.impl.*; import de.studiocode.invgui.item.Item; @@ -11,6 +12,10 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; +import java.util.function.Predicate; /** * A GUI is a container for width * height {@link SlotElement}s.
@@ -59,7 +64,7 @@ public interface GUI { * @param y The y coordinate * @param slotElement The {@link SlotElement} to be placed there. */ - void setSlotElement(int x, int y, @NotNull SlotElement slotElement); + void setSlotElement(int x, int y, SlotElement slotElement); /** * Sets the {@link SlotElement} on these coordinates. @@ -68,7 +73,7 @@ public interface GUI { * @param index The slot index * @param slotElement The {@link SlotElement} to be placed there. */ - void setSlotElement(int index, @NotNull SlotElement slotElement); + void setSlotElement(int index, SlotElement slotElement); /** * Gets the {@link SlotElement} on these coordinates. @@ -204,6 +209,40 @@ public interface GUI { */ void handleItemShift(InventoryClickEvent event); + /** + * Adds a {@link GUIParent} to the set of {@link GUIParent}s. + * + * @param parent The {@link GUIParent} to add + */ + void addParent(@NotNull GUIParent parent); + + /** + * Removes a {@link GUIParent} from the set of {@link GUIParent}s + * + * @param parent The {@link GUIParent} to remove + */ + void removeParent(@NotNull GUIParent parent); + + /** + * Gets all {@link GUIParent}s. + * + * @return The {@link GUIParent}s of this {@link GUI} + */ + Set getParents(); + + /** + * Plays an {@link Animation}. + * + * @param animation The {@link Animation} to play. + * @param filter The filter that selects which {@link ItemStackHolder}s should be animated. + */ + void playAnimation(@NotNull Animation animation, @Nullable Predicate filter); + + /** + * Cancels the running {@link Animation} if there is one. + */ + void cancelAnimation(); + // ---- fill methods ---- /** diff --git a/src/main/java/de/studiocode/invgui/gui/GUIParent.java b/src/main/java/de/studiocode/invgui/gui/GUIParent.java new file mode 100644 index 0000000..f271e8b --- /dev/null +++ b/src/main/java/de/studiocode/invgui/gui/GUIParent.java @@ -0,0 +1,13 @@ +package de.studiocode.invgui.gui; + +public interface GUIParent { + + /** + * Called by the child {@link GUI} to report an update of a {@link SlotElement}. + * + * @param child The child {@link GUI} whose {@link SlotElement} has changed + * @param slotIndex The slot index of the changed {@link SlotElement} in the child {@link GUI} + */ + void handleSlotElementUpdate(GUI child, int slotIndex); + +} diff --git a/src/main/java/de/studiocode/invgui/gui/impl/BaseGUI.java b/src/main/java/de/studiocode/invgui/gui/impl/BaseGUI.java index 9404004..83183ca 100644 --- a/src/main/java/de/studiocode/invgui/gui/impl/BaseGUI.java +++ b/src/main/java/de/studiocode/invgui/gui/impl/BaseGUI.java @@ -28,7 +28,7 @@ public abstract class BaseGUI extends IndexedGUI { } @Override - public void setSlotElement(int x, int y, @NotNull SlotElement slotElement) { + public void setSlotElement(int x, int y, SlotElement slotElement) { setSlotElement(convToIndex(x, y), slotElement); } @@ -81,7 +81,7 @@ public abstract class BaseGUI extends IndexedGUI { public void fill(@NotNull SortedSet slots, Item item, boolean replaceExisting) { for (int slot : slots) { - if (!replaceExisting && slotElements[slot] != null) continue; + if (!replaceExisting && hasSlotElement(slot)) continue; setItem(slot, item); } } @@ -89,14 +89,14 @@ public abstract class BaseGUI extends IndexedGUI { @Override public void fill(int start, int end, Item item, boolean replaceExisting) { for (int i = start; i < end; i++) { - if (!replaceExisting && slotElements[i] != null) continue; + if (!replaceExisting && hasSlotElement(i)) continue; setItem(i, item); } } @Override public void fill(Item item, boolean replaceExisting) { - fill(0, size, item, replaceExisting); + fill(0, getSize(), item, replaceExisting); } @Override diff --git a/src/main/java/de/studiocode/invgui/gui/impl/IndexedGUI.java b/src/main/java/de/studiocode/invgui/gui/impl/IndexedGUI.java index ca0a5f1..93c487b 100644 --- a/src/main/java/de/studiocode/invgui/gui/impl/IndexedGUI.java +++ b/src/main/java/de/studiocode/invgui/gui/impl/IndexedGUI.java @@ -1,6 +1,8 @@ package de.studiocode.invgui.gui.impl; +import de.studiocode.invgui.animation.Animation; import de.studiocode.invgui.gui.GUI; +import de.studiocode.invgui.gui.GUIParent; import de.studiocode.invgui.gui.SlotElement; import de.studiocode.invgui.gui.SlotElement.ItemSlotElement; import de.studiocode.invgui.gui.SlotElement.ItemStackHolder; @@ -10,19 +12,26 @@ import de.studiocode.invgui.item.Item; import de.studiocode.invgui.util.ArrayUtils; import de.studiocode.invgui.virtualinventory.VirtualInventory; import de.studiocode.invgui.virtualinventory.event.ItemUpdateEvent; +import de.studiocode.invgui.window.Window; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.function.Predicate; -abstract class IndexedGUI implements GUI { +abstract class IndexedGUI implements GUI, GUIParent { - protected final int size; - protected final SlotElement[] slotElements; + private final int size; + private final SlotElement[] slotElements; + private final Set parents = new HashSet<>(); + + private SlotElement[] animationElements; + private Animation animation; public IndexedGUI(int size) { this.size = size; @@ -31,6 +40,12 @@ abstract class IndexedGUI implements GUI { @Override public void handleClick(int slotNumber, Player player, ClickType clickType, InventoryClickEvent event) { + if (animation != null) { + // cancel all clicks if an animation is running + event.setCancelled(true); + return; + } + SlotElement slotElement = slotElements[slotNumber]; if (slotElement instanceof LinkedSlotElement) { LinkedSlotElement linkedElement = (LinkedSlotElement) slotElement; @@ -123,6 +138,8 @@ abstract class IndexedGUI implements GUI { public void handleItemShift(InventoryClickEvent event) { event.setCancelled(true); + if (animation != null) return; // cancel all clicks if an animation is running + Player player = (Player) event.getWhoClicked(); ItemStack clicked = event.getCurrentItem(); @@ -157,8 +174,119 @@ abstract class IndexedGUI implements GUI { } @Override - public void setSlotElement(int index, @NotNull SlotElement slotElement) { + public void handleSlotElementUpdate(GUI child, int slotIndex) { + // find all SlotElements that link to this slotIndex in this child GUI and notify all parents + for (int index = 0; index < size; index++) { + SlotElement element = slotElements[index]; + if (element instanceof LinkedSlotElement) { + LinkedSlotElement linkedSlotElement = (LinkedSlotElement) element; + if (linkedSlotElement.getGui() == child && linkedSlotElement.getSlotIndex() == slotIndex) + for (GUIParent parent : parents) parent.handleSlotElementUpdate(this, index); + } + } + } + + @Override + public void addParent(@NotNull GUIParent parent) { + parents.add(parent); + } + + @Override + public void removeParent(@NotNull GUIParent parent) { + parents.remove(parent); + } + + @Override + public Set getParents() { + return parents; + } + + private List findAllWindows() { + List windows = new ArrayList<>(); + List parents = new ArrayList<>(this.parents); + + while (!parents.isEmpty()) { + List parents1 = new ArrayList<>(parents); + parents.clear(); + for (GUIParent parent : parents1) { + if (parent instanceof GUI) parents.addAll(((GUI) parent).getParents()); + else if (parent instanceof Window) windows.add((Window) parent); + } + } + + return windows; + } + + @Override + public void playAnimation(@NotNull Animation animation, @Nullable Predicate filter) { + if (animation != null) cancelAnimation(); + + this.animation = animation; + this.animationElements = slotElements.clone(); + + List slots = new ArrayList<>(); + for (int i = 0; i < size; i++) { + ItemStackHolder holder = getItemStackHolder(i); + if (holder != null && (filter == null || filter.test(holder))) { + slots.add(i); + setSlotElement(i, null); + } + } + + animation.setSlots(slots); + animation.setGUI(this); + animation.setWindows(findAllWindows()); + animation.addShowHandler((frame, index) -> setSlotElement(index, animationElements[index])); + animation.addFinishHandler(() -> { + this.animation = null; + this.animationElements = null; + }); + + animation.start(); + } + + @Override + public void cancelAnimation() { + if (this.animation != null) { + // cancel the scheduler task and set animation to null + animation.cancel(); + animation = null; + + // show all SlotElements again + for (int i = 0; i < size; i++) setSlotElement(i, animationElements[i]); + animationElements = null; + } + } + + @Override + public void setSlotElement(int index, SlotElement slotElement) { + SlotElement oldElement = slotElements[index]; + GUI oldLink = oldElement instanceof LinkedSlotElement ? ((LinkedSlotElement) oldElement).getGui() : null; + + // set new SlotElement on index slotElements[index] = slotElement; + + GUI newLink = slotElement instanceof LinkedSlotElement ? ((LinkedSlotElement) slotElement).getGui() : null; + + // notify parents that a SlotElement has been changed + parents.forEach(parent -> parent.handleSlotElementUpdate(this, index)); + + // if newLink is the same as oldLink, there isn't anything to be done + if (newLink == oldLink) return; + + // if the slot previously linked to GUI + if (oldLink != null) { + // If no other slot still links to that GUI, remove this GUI from parents + if (Arrays.stream(slotElements) + .filter(element -> element instanceof LinkedSlotElement) + .map(element -> ((LinkedSlotElement) element).getGui()) + .noneMatch(gui -> gui == oldLink)) oldLink.removeParent(this); + } + + // if the slot now links to a GUI add this as parent + if (newLink != null) { + newLink.addParent(this); + } } @Override @@ -179,7 +307,7 @@ abstract class IndexedGUI implements GUI { @Override public void setItem(int index, Item item) { remove(index); - if (item != null) slotElements[index] = new ItemSlotElement(item); + if (item != null) setSlotElement(index, new ItemSlotElement(item)); } @Override @@ -211,7 +339,7 @@ abstract class IndexedGUI implements GUI { @Override public void remove(int index) { - slotElements[index] = null; + setSlotElement(index, null); } @Override diff --git a/src/main/java/de/studiocode/invgui/window/Window.java b/src/main/java/de/studiocode/invgui/window/Window.java index 2d90ccb..ffad200 100644 --- a/src/main/java/de/studiocode/invgui/window/Window.java +++ b/src/main/java/de/studiocode/invgui/window/Window.java @@ -1,8 +1,6 @@ package de.studiocode.invgui.window; -import de.studiocode.invgui.animation.Animation; import de.studiocode.invgui.gui.GUI; -import de.studiocode.invgui.gui.SlotElement.ItemStackHolder; import de.studiocode.invgui.item.Item; import de.studiocode.invgui.item.itembuilder.ItemBuilder; import de.studiocode.invgui.virtualinventory.VirtualInventory; @@ -15,15 +13,12 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.UUID; -import java.util.function.Predicate; /** * A window is the way to show a player a GUI. - * Windows can only have one viewer at a time. + * Windows can only have one viewer. * * @see BaseWindow * @see NormalInventoryWindow @@ -46,12 +41,6 @@ public interface Window { */ GUI getGui(); - /** - * A method called every tick by the {@link WindowManager} - * to re-draw the {@link Item}s. - */ - void handleTick(); - /** * A method called by the {@link WindowManager} to notify the Window * that one of its {@link Item}s has been clicked. @@ -126,14 +115,6 @@ public interface Window { */ void show(); - /** - * Plays an animation. - * - * @param animation The animation to play. - * @param filter The filter that selects which Items should be animated. - */ - void playAnimation(@NotNull Animation animation, @Nullable Predicate filter); - /** * Gets if the player is able to close the {@link Inventory}. * diff --git a/src/main/java/de/studiocode/invgui/window/WindowManager.java b/src/main/java/de/studiocode/invgui/window/WindowManager.java index 8185935..2bf7c01 100644 --- a/src/main/java/de/studiocode/invgui/window/WindowManager.java +++ b/src/main/java/de/studiocode/invgui/window/WindowManager.java @@ -27,8 +27,6 @@ public class WindowManager implements Listener { private WindowManager() { Bukkit.getPluginManager().registerEvents(this, InvGui.getInstance().getPlugin()); - Bukkit.getScheduler().scheduleSyncRepeatingTask(InvGui.getInstance().getPlugin(), - () -> windows.forEach(Window::handleTick), 0, 1); InvGui.getInstance().addDisableHandler(() -> windows.forEach(w -> w.close(true))); } diff --git a/src/main/java/de/studiocode/invgui/window/impl/BaseWindow.java b/src/main/java/de/studiocode/invgui/window/impl/BaseWindow.java index e908901..40002a3 100644 --- a/src/main/java/de/studiocode/invgui/window/impl/BaseWindow.java +++ b/src/main/java/de/studiocode/invgui/window/impl/BaseWindow.java @@ -1,8 +1,8 @@ package de.studiocode.invgui.window.impl; import de.studiocode.invgui.InvGui; -import de.studiocode.invgui.animation.Animation; import de.studiocode.invgui.gui.GUI; +import de.studiocode.invgui.gui.GUIParent; import de.studiocode.invgui.gui.SlotElement.ItemSlotElement; import de.studiocode.invgui.gui.SlotElement.ItemStackHolder; import de.studiocode.invgui.gui.SlotElement.VISlotElement; @@ -18,13 +18,10 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.function.Predicate; -public abstract class BaseWindow implements Window { +public abstract class BaseWindow implements Window, GUIParent { private final GUI gui; private final int size; @@ -33,7 +30,6 @@ public abstract class BaseWindow implements Window { private final boolean closeOnEvent; private final ItemStackHolder[] itemsDisplayed; - private Animation animation; private boolean closeable; private boolean closed; @@ -46,6 +42,7 @@ public abstract class BaseWindow implements Window { this.closeOnEvent = closeOnEvent; this.itemsDisplayed = new ItemStackHolder[size]; + gui.addParent(this); initItems(); WindowManager.getInstance().addWindow(this); } @@ -95,25 +92,18 @@ public abstract class BaseWindow implements Window { } @Override - public void handleTick() { - for (int i = 0; i < size; i++) { - ItemStackHolder holder = gui.getItemStackHolder(i); - if (itemsDisplayed[i] != holder) redrawItem(i, holder, true); - } + public void handleSlotElementUpdate(GUI child, int slotIndex) { + redrawItem(slotIndex, gui.getItemStackHolder(slotIndex), true); } @Override public void handleClick(InventoryClickEvent event) { - if (animation == null) { // if not in animation, let the gui handle the click - gui.handleClick(event.getSlot(), (Player) event.getWhoClicked(), event.getClick(), event); - } else event.setCancelled(true); + gui.handleClick(event.getSlot(), (Player) event.getWhoClicked(), event.getClick(), event); } @Override public void handleItemShift(InventoryClickEvent event) { - if (animation == null) { // if not in animation, let the gui handle the item shift - gui.handleItemShift(event); - } else event.setCancelled(true); + gui.handleItemShift(event); } @Override @@ -125,7 +115,6 @@ public abstract class BaseWindow implements Window { @Override public void handleClose(Player player) { if (closeable) { - stopAnimation(); if (closeOnEvent) close(false); } else { if (player.equals(getViewer())) @@ -168,6 +157,8 @@ public abstract class BaseWindow implements Window { .map(holder -> ((ItemSlotElement) holder).getItem()) .forEach(item -> item.removeWindow(this)); + gui.removeParent(this); + if (closeForViewer) closeForViewer(); } @@ -187,42 +178,6 @@ public abstract class BaseWindow implements Window { viewer.openInventory(inventory); } - @Override - public void playAnimation(@NotNull Animation animation, @Nullable Predicate filter) { - if (getViewer() != null) { - this.animation = animation; - - List slots = new ArrayList<>(); - for (int i = 0; i < size; i++) { - ItemStackHolder holder = itemsDisplayed[i]; - if (holder != null && (filter == null || filter.test(holder))) { - slots.add(i); - inventory.setItem(i, null); - } - } - - animation.setBounds(getGui().getWidth(), getGui().getHeight()); - animation.setPlayer(getViewer()); - animation.addShowHandler((frame, index) -> redrawItem(index, itemsDisplayed[index], false)); - animation.addFinishHandler(() -> this.animation = null); - animation.setSlots(slots); - - animation.start(); - } - } - - private void stopAnimation() { - if (this.animation != null) { - // cancel the scheduler task and set animation to null - animation.cancel(); - animation = null; - - // show all items again - for (int i = 0; i < gui.getSize(); i++) - redrawItem(i, itemsDisplayed[i], false); - } - } - @Override public Player getViewer() { return Bukkit.getPlayer(viewerUUID);