Performance Improvements

This commit is contained in:
NichtStudioCode 2022-02-25 19:47:02 +01:00
parent 0136354b57
commit 09cfebd152
15 changed files with 123 additions and 102 deletions

@ -210,7 +210,7 @@ public abstract class BaseGUI implements GUI, Controllable {
ItemStack previousStack = clicked.clone();
UpdateReason updateReason = new PlayerUpdateReason(player, event);
Window window = WindowManager.getInstance().findOpenWindow(player).orElse(null);
Window window = WindowManager.getInstance().getOpenWindow(player);
ItemUpdateEvent updateEvent = inventory.callPreUpdateEvent(updateReason, slot, previousStack, null);
if (!updateEvent.isCancelled()) {
@ -241,7 +241,7 @@ public abstract class BaseGUI implements GUI, Controllable {
// TODO: add support for merged windows
protected void handleVINumberKey(InventoryClickEvent event, VirtualInventory inventory, int slot, Player player, ItemStack clicked) {
Window window = WindowManager.getInstance().findOpenWindow(player).orElse(null);
Window window = WindowManager.getInstance().getOpenWindow(player);
if (window instanceof SingleWindow) {
Inventory playerInventory = player.getInventory();
int hotbarButton = event.getHotbarButton();
@ -257,7 +257,7 @@ public abstract class BaseGUI implements GUI, Controllable {
// TODO: add support for merged windows
protected void handleVIOffHandKey(InventoryClickEvent event, VirtualInventory inventory, int slot, Player player, ItemStack clicked) {
Window window = WindowManager.getInstance().findOpenWindow(player).orElse(null);
Window window = WindowManager.getInstance().getOpenWindow(player);
if (window instanceof SingleWindow) {
PlayerInventory playerInventory = player.getInventory();
ItemStack offhandItem = playerInventory.getItemInOffHand();

@ -1,13 +1,11 @@
package de.studiocode.invui.virtualinventory;
import de.studiocode.invui.InvUI;
import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.util.ArrayUtils;
import de.studiocode.invui.virtualinventory.event.InventoryUpdatedEvent;
import de.studiocode.invui.virtualinventory.event.ItemUpdateEvent;
import de.studiocode.invui.virtualinventory.event.UpdateReason;
import de.studiocode.invui.window.Window;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -102,8 +100,7 @@ public class VirtualInventory {
* {@link ItemMeta} of an {@link ItemStack} in this inventory has changed.
*/
public void notifyWindows() {
Bukkit.getScheduler().runTask(InvUI.getInstance().getPlugin(), () ->
windows.forEach(window -> window.handleVirtualInventoryUpdate(this)));
windows.forEach(window -> window.handleVirtualInventoryUpdate(this));
}
/**

@ -16,26 +16,23 @@ import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.*;
/**
* Manages all {@link Window}s and provides methods for searching them.
* Manages all {@link Window Windows} and provides methods for searching them.
*/
public class WindowManager implements Listener {
private static WindowManager instance;
private final List<Window> windows = new CopyOnWriteArrayList<>();
private final Map<Inventory, Window> windows = new HashMap<>();
private final Map<Player, Window> openWindows = new HashMap<>();
private WindowManager() {
Bukkit.getPluginManager().registerEvents(this, InvUI.getInstance().getPlugin());
InvUI.getInstance().addDisableHandler(() -> windows.forEach(window -> window.close(true)));
InvUI.getInstance().addDisableHandler(() -> getWindows().forEach(window -> window.close(true)));
}
/**
@ -54,7 +51,7 @@ public class WindowManager implements Listener {
* @param window The {@link Window} to add
*/
public void addWindow(Window window) {
windows.add(window);
windows.put(window.getInventories()[0], window);
}
/**
@ -64,7 +61,7 @@ public class WindowManager implements Listener {
* @param window The {@link Window} to remove
*/
public void removeWindow(Window window) {
windows.remove(window);
windows.remove(window.getInventories()[0]);
}
/**
@ -73,57 +70,54 @@ public class WindowManager implements Listener {
* @param inventory The {@link Inventory}
* @return The {@link Window} that belongs to that {@link Inventory}
*/
public Optional<Window> findWindow(Inventory inventory) {
return windows.stream()
.filter(w -> Arrays.stream(w.getInventories()).anyMatch(inv -> inv == inventory))
.findFirst();
@Nullable
public Window getWindow(Inventory inventory) {
return windows.get(inventory);
}
/**
* Finds all {@link Window}s to a {@link Player}
*
* @param player The {@link Player}
* @return A list of {@link Window}s that have the {@link Player} as their viewer.
*/
public List<Window> findWindows(Player player) {
return windows.stream()
.filter(w -> w.getViewer().getUniqueId().equals(player.getUniqueId()))
.collect(Collectors.toCollection(ArrayList::new));
}
/**
* Finds the {@link Window} the {@link Player} has currently open.
* Gets the {@link Window} the {@link Player} has currently open.
*
* @param player The {@link Player}
* @return The {@link Window} the {@link Player} has currently open
*/
public Optional<Window> findOpenWindow(Player player) {
return windows.stream()
.filter(w -> player.equals(w.getCurrentViewer()))
.findFirst();
@Nullable
public Window getOpenWindow(Player player) {
return openWindows.get(player);
}
/**
* Gets a list of all currently active {@link Window}s.
* Gets a set of all registered {@link Window Windows}.
*
* @return A list of all {@link Window}s
* @return A set of all {@link Window Windows}
*/
public List<Window> getWindows() {
return windows;
public Set<Window> getWindows() {
return new HashSet<>(windows.values());
}
/**
* Gets a set of all currently opened {@link Window Windows}.
*
* @return A set of all opened {@link Window Windows}
*/
public Set<Window> getOpenWindows() {
return new HashSet<>(openWindows.values());
}
@EventHandler
public void handleInventoryClick(InventoryClickEvent event) {
Optional<Window> w = findWindow(event.getClickedInventory());
if (w.isPresent()) { // player clicked window
w.get().handleClick(event);
private void handleInventoryClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
Window window = getOpenWindow(player);
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 {
Optional<Window> w1 = findWindow(event.getView().getTopInventory());
// player inventory (not merged window) clicked
if (w1.isPresent()) {
Window window = w1.get();
// The inventory that was clicked is not part of the open window, so it is the player inventory
switch (event.getAction()) {
// items have been shift clicked from player inv to Window
case MOVE_TO_OTHER_INVENTORY:
window.handleItemShift(event);
break;
@ -138,36 +132,57 @@ public class WindowManager implements Listener {
}
@EventHandler
public void handleInventoryDrag(InventoryDragEvent event) {
findWindow(event.getInventory()).ifPresent(window -> window.handleDrag(event));
private void handleInventoryDrag(InventoryDragEvent event) {
Window window = getOpenWindow((Player) event.getWhoClicked());
if (window != null) {
window.handleDrag(event);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void handleInventoryClose(InventoryCloseEvent event) {
findWindow(event.getInventory()).ifPresent(window -> window.handleClose((Player) event.getPlayer()));
private void handleInventoryClose(InventoryCloseEvent event) {
Window window = getWindow(event.getInventory());
if (window != null) {
Player player = (Player) event.getPlayer();
window.handleClose(player);
openWindows.remove(player);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void handleInventoryOpen(InventoryOpenEvent event) {
findWindow(event.getInventory()).ifPresent(window -> window.handleOpen(event));
private void handleInventoryOpen(InventoryOpenEvent event) {
Window window = getWindow(event.getInventory());
if (window != null) {
window.handleOpen(event);
openWindows.put((Player) event.getPlayer(), window);
}
}
@EventHandler
public void handlePlayerQuit(PlayerQuitEvent event) {
findWindow(event.getPlayer().getOpenInventory().getTopInventory()).ifPresent(window -> window.handleClose(event.getPlayer()));
private void handlePlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
Window window = getOpenWindow(player);
if (window != null) {
window.handleClose(player);
openWindows.remove(player);
}
}
@EventHandler
public void handlePlayerDeath(PlayerDeathEvent event) {
findWindows(event.getEntity()).forEach(window -> window.handleViewerDeath(event));
private void handlePlayerDeath(PlayerDeathEvent event) {
Player player = event.getEntity();
Window window = getOpenWindow(player);
if (window != null) {
window.handleViewerDeath(event);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void handleItemPickup(EntityPickupItemEvent event) {
private void handleItemPickup(EntityPickupItemEvent event) {
Entity entity = event.getEntity();
if (entity instanceof Player) {
Optional<Window> window = findOpenWindow(((Player) entity));
if (window.isPresent() && window.get() instanceof MergedWindow)
Window window = getOpenWindow((Player) entity);
if (window instanceof MergedWindow)
event.setCancelled(true);
}
}

@ -36,20 +36,22 @@ public abstract class BaseWindow implements Window {
private static final NamespacedKey SLOT_KEY = new NamespacedKey(InvUI.getInstance().getPlugin(), "slot");
private final UUID viewerUUID;
private final boolean closeOnEvent;
private final boolean removeOnClose;
private final SlotElement[] elementsDisplayed;
private final ArrayList<Runnable> closeHandlers = new ArrayList<>();
private BaseComponent[] title;
private boolean closeable;
private boolean closed;
public BaseWindow(UUID viewerUUID, BaseComponent[] title, int size, boolean closeable, boolean closeOnEvent) {
public BaseWindow(UUID viewerUUID, BaseComponent[] title, int size, boolean closeable, boolean removeOnClose) {
this.viewerUUID = viewerUUID;
this.title = title;
this.closeable = closeable;
this.closeOnEvent = closeOnEvent;
this.removeOnClose = removeOnClose;
this.elementsDisplayed = new SlotElement[size];
}
protected void register() {
WindowManager.getInstance().addWindow(this);
}
@ -157,7 +159,7 @@ public abstract class BaseWindow implements Window {
@Override
public void handleClose(Player player) {
if (closeable) {
if (closeOnEvent) close(false);
if (removeOnClose) close(false);
handleClosed();
closeHandlers.forEach(Runnable::run);
} else {

@ -28,8 +28,8 @@ public abstract class MergedWindow extends BaseWindow {
protected Inventory upperInventory;
private boolean isCurrentlyOpened;
public MergedWindow(Player player, BaseComponent[] title, int size, Inventory upperInventory, boolean closeable, boolean closeOnEvent) {
super(player.getUniqueId(), title, size, closeable, closeOnEvent);
public MergedWindow(Player player, BaseComponent[] title, int size, Inventory upperInventory, boolean closeable, boolean removeOnClose) {
super(player.getUniqueId(), title, size, closeable, removeOnClose);
this.upperInventory = upperInventory;
this.playerInventory = player.getInventory();
}

@ -18,8 +18,8 @@ public abstract class CombinedWindow extends MergedWindow {
private final GUI gui;
public CombinedWindow(Player player, BaseComponent[] title, GUI gui, Inventory upperInventory, boolean closeable, boolean closeOnEvent) {
super(player, title, gui.getSize(), upperInventory, closeable, closeOnEvent);
public CombinedWindow(Player player, BaseComponent[] title, GUI gui, Inventory upperInventory, boolean closeable, boolean removeOnClose) {
super(player, title, gui.getSize(), upperInventory, closeable, removeOnClose);
this.gui = gui;
gui.addParent(this);

@ -7,14 +7,15 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
public class SimpleCombinedWindow extends CombinedWindow {
public final class SimpleCombinedWindow extends CombinedWindow {
public SimpleCombinedWindow(Player player, BaseComponent[] title, GUI gui, boolean closeable, boolean closeOnEvent) {
super(player, title, gui, createInventory(gui), closeable, closeOnEvent);
public SimpleCombinedWindow(Player player, BaseComponent[] title, GUI gui, boolean closeable, boolean removeOnClose) {
super(player, title, gui, createInventory(gui), closeable, removeOnClose);
register();
}
public SimpleCombinedWindow(Player player, String title, GUI gui, boolean closeable, boolean closeOnEvent) {
this(player, TextComponent.fromLegacyText(title), gui, closeable, closeOnEvent);
public SimpleCombinedWindow(Player player, String title, GUI gui, boolean closeable, boolean removeOnClose) {
this(player, TextComponent.fromLegacyText(title), gui, closeable, removeOnClose);
}
public SimpleCombinedWindow(Player player, String title, GUI gui) {

@ -10,7 +10,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.function.Consumer;
public class AnvilSplitWindow extends SplitWindow {
public final class AnvilSplitWindow extends SplitWindow {
private final AnvilInventory anvilInventory;
@ -21,6 +21,7 @@ public class AnvilSplitWindow extends SplitWindow {
upperInventory = anvilInventory.getBukkitInventory();
initUpperItems();
register();
}
public AnvilSplitWindow(Player player, BaseComponent[] title, GUI upperGui, GUI lowerGui, Consumer<String> renameHandler) {

@ -17,7 +17,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class CartographySplitWindow extends SplitWindow {
public final class CartographySplitWindow extends SplitWindow {
private final CartographyInventory cartographyInventory;
private int mapId;
@ -42,6 +42,7 @@ public class CartographySplitWindow extends SplitWindow {
initUpperItems();
resetMap();
register();
}
private static GUI createWrappingGUI(GUI upperGui) {

@ -6,18 +6,19 @@ import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.entity.Player;
public class SimpleSplitWindow extends SplitWindow {
public final class SimpleSplitWindow extends SplitWindow {
public SimpleSplitWindow(Player player, BaseComponent[] title, GUI upperGui, GUI lowerGui, boolean closeable, boolean closeOnEvent) {
super(player, title, upperGui, lowerGui, InventoryUtils.createMatchingInventory(upperGui, ""), true, closeable, closeOnEvent);
public SimpleSplitWindow(Player player, BaseComponent[] title, GUI upperGui, GUI lowerGui, boolean closeable, boolean removeOnClose) {
super(player, title, upperGui, lowerGui, InventoryUtils.createMatchingInventory(upperGui, ""), true, closeable, removeOnClose);
register();
}
public SimpleSplitWindow(Player player, BaseComponent[] title, GUI upperGui, GUI lowerGui) {
this(player, title, upperGui, lowerGui, true, true);
}
public SimpleSplitWindow(Player player, String title, GUI upperGui, GUI lowerGui, boolean closeable, boolean closeOnEvent) {
this(player, TextComponent.fromLegacyText(title), upperGui, lowerGui, closeable, closeOnEvent);
public SimpleSplitWindow(Player player, String title, GUI upperGui, GUI lowerGui, boolean closeable, boolean removeOnClose) {
this(player, TextComponent.fromLegacyText(title), upperGui, lowerGui, closeable, removeOnClose);
}
public SimpleSplitWindow(Player player, String title, GUI upperGui, GUI lowerGui) {

@ -19,8 +19,8 @@ public abstract class SplitWindow extends MergedWindow {
private final GUI upperGui;
private final GUI lowerGui;
public SplitWindow(Player player, BaseComponent[] title, GUI upperGui, GUI lowerGui, Inventory upperInventory, boolean initItems, boolean closeable, boolean closeOnEvent) {
super(player, title, upperGui.getSize() + lowerGui.getSize(), upperInventory, closeable, closeOnEvent);
public SplitWindow(Player player, BaseComponent[] title, GUI upperGui, GUI lowerGui, Inventory upperInventory, boolean initItems, boolean closeable, boolean removeOnClose) {
super(player, title, upperGui.getSize() + lowerGui.getSize(), upperInventory, closeable, removeOnClose);
this.upperGui = upperGui;
this.lowerGui = lowerGui;

@ -10,7 +10,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.function.Consumer;
public class AnvilWindow extends SingleWindow {
public final class AnvilWindow extends SingleWindow {
private final AnvilInventory anvilInventory;
@ -20,6 +20,7 @@ public class AnvilWindow extends SingleWindow {
inventory = anvilInventory.getBukkitInventory();
initItems();
register();
}
public AnvilWindow(Player player, String title, GUI gui, boolean closeable, Consumer<String> renameHandler) {

@ -18,7 +18,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
@SuppressWarnings("deprecation")
public class CartographyWindow extends SingleWindow {
public final class CartographyWindow extends SingleWindow {
private final CartographyInventory cartographyInventory;
private int mapId;
@ -44,6 +44,7 @@ public class CartographyWindow extends SingleWindow {
initItems();
resetMap();
register();
}
public void updateMap(@Nullable MapPatch patch, @Nullable List<MapIcon> icons) {

@ -8,34 +8,35 @@ import org.bukkit.entity.Player;
import java.util.UUID;
public class SimpleWindow extends SingleWindow {
public final class SimpleWindow extends SingleWindow {
public SimpleWindow(UUID viewerUUID, BaseComponent[] title, GUI gui, boolean closeable, boolean closeOnEvent) {
super(viewerUUID, title, gui, InventoryUtils.createMatchingInventory(gui, ""), true, closeable, closeOnEvent);
public SimpleWindow(UUID viewerUUID, BaseComponent[] title, GUI gui, boolean closeable, boolean removeOnClose) {
super(viewerUUID, title, gui, InventoryUtils.createMatchingInventory(gui, ""), true, closeable, removeOnClose);
register();
}
public SimpleWindow(UUID viewerUUID, BaseComponent[] title, GUI gui) {
this(viewerUUID, title, gui, true, true);
}
public SimpleWindow(Player player, BaseComponent[] title, GUI gui, boolean closeable, boolean closeOnEvent) {
this(player.getUniqueId(), title, gui, closeable, closeOnEvent);
public SimpleWindow(Player player, BaseComponent[] title, GUI gui, boolean closeable, boolean removeOnClose) {
this(player.getUniqueId(), title, gui, closeable, removeOnClose);
}
public SimpleWindow(Player player, BaseComponent[] title, GUI gui) {
this(player, title, gui, true, true);
}
public SimpleWindow(UUID viewerUUID, String title, GUI gui, boolean closeable, boolean closeOnEvent) {
this(viewerUUID, TextComponent.fromLegacyText(title), gui, closeable, closeOnEvent);
public SimpleWindow(UUID viewerUUID, String title, GUI gui, boolean closeable, boolean removeOnClose) {
this(viewerUUID, TextComponent.fromLegacyText(title), gui, closeable, removeOnClose);
}
public SimpleWindow(UUID viewerUUID, String title, GUI gui) {
this(viewerUUID, title, gui, true, true);
}
public SimpleWindow(Player player, String title, GUI gui, boolean closeable, boolean closeOnEvent) {
this(player.getUniqueId(), title, gui, closeable, closeOnEvent);
public SimpleWindow(Player player, String title, GUI gui, boolean closeable, boolean removeOnClose) {
this(player.getUniqueId(), title, gui, closeable, removeOnClose);
}
public SimpleWindow(Player player, String title, GUI gui) {

@ -24,8 +24,8 @@ public abstract class SingleWindow extends BaseWindow {
private final int size;
protected Inventory inventory;
public SingleWindow(UUID viewerUUID, BaseComponent[] title, GUI gui, Inventory inventory, boolean initItems, boolean closeable, boolean closeOnEvent) {
super(viewerUUID, title, gui.getSize(), closeable, closeOnEvent);
public SingleWindow(UUID viewerUUID, BaseComponent[] title, GUI gui, Inventory inventory, boolean initItems, boolean closeable, boolean removeOnClose) {
super(viewerUUID, title, gui.getSize(), closeable, removeOnClose);
this.gui = gui;
this.size = gui.getSize();
this.inventory = inventory;