diff --git a/src/main/java/com/slampvp/factory/FactoryServer.java b/src/main/java/com/slampvp/factory/FactoryServer.java index 7c612d2..d159e3a 100644 --- a/src/main/java/com/slampvp/factory/FactoryServer.java +++ b/src/main/java/com/slampvp/factory/FactoryServer.java @@ -1,6 +1,7 @@ package com.slampvp.factory; import com.slampvp.factory.command.FactoryCommand; +import com.slampvp.factory.common.menu.MenuListener; import com.slampvp.factory.database.DatabaseManager; import com.slampvp.factory.player.PlayerListener; import com.slampvp.factory.plot.PlotGenerator; @@ -41,6 +42,7 @@ public static void main(String[] args) { instanceContainer.setTimeRate(0); new PlayerListener(instanceContainer); + new MenuListener(); PlotManager.getInstance().init(); DatabaseManager.getInstance().init(); diff --git a/src/main/java/com/slampvp/factory/common/menu/Menu.java b/src/main/java/com/slampvp/factory/common/menu/Menu.java new file mode 100644 index 0000000..10f38e6 --- /dev/null +++ b/src/main/java/com/slampvp/factory/common/menu/Menu.java @@ -0,0 +1,45 @@ +package com.slampvp.factory.common.menu; + +import net.kyori.adventure.text.TextComponent; +import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryCloseEvent; +import net.minestom.server.event.inventory.InventoryOpenEvent; +import net.minestom.server.inventory.Inventory; +import net.minestom.server.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Optional; + +public interface Menu { + @NotNull + TextComponent name(); + + @NotNull + InventoryType type(); + + @NotNull + List items(); + + default Optional itemBySlot(int slot) { + return items().stream() + .filter(menuItem -> menuItem.slots().contains(slot)) + .findFirst(); + } + + default void open(Player player) { + MenuManager.getInstance().setOpenMenu(player, this); + + Inventory inventory = new Inventory(type(), name()); + + items().forEach(menuItem -> menuItem.slots().forEach(slot -> inventory.setItemStack(slot, menuItem.itemStack()))); + + player.openInventory(inventory); + } + + default void onOpen(InventoryOpenEvent event) { + } + + default void onClose(InventoryCloseEvent event) { + } +} diff --git a/src/main/java/com/slampvp/factory/common/menu/MenuItem.java b/src/main/java/com/slampvp/factory/common/menu/MenuItem.java new file mode 100644 index 0000000..d9a43cb --- /dev/null +++ b/src/main/java/com/slampvp/factory/common/menu/MenuItem.java @@ -0,0 +1,88 @@ +package com.slampvp.factory.common.menu; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.IntStream; + +public record MenuItem(List slots, ItemStack itemStack, ClickAction action) { + public static Function CLOSE = slot -> + new MenuItem(slot, + ItemStack.of(Material.BARRIER) + .withCustomName(Component.text("Close").color(NamedTextColor.DARK_RED).decorate(TextDecoration.BOLD)), + event -> { + Player player = event.getPlayer(); + player.closeInventory(); + MenuManager.getInstance().clearOpenMenu(player); + }); + + public MenuItem(IntStream stream, ItemStack itemStack) { + this(stream.boxed().toList(), itemStack, new ClickAction() { + }); + } + + public MenuItem(IntStream stream, ItemStack itemStack, ClickAction action) { + this(stream.boxed().toList(), itemStack, action); + } + + public MenuItem(IntStream stream, ItemStack itemStack, Consumer consumer) { + this(stream.boxed().toList(), itemStack, true, consumer); + } + + public MenuItem(IntStream stream, ItemStack itemStack, boolean cancel, Consumer consumer) { + this(stream.boxed().toList(), itemStack, cancel, consumer); + } + + public MenuItem(List slots, ItemStack itemStack) { + this(slots, itemStack, new ClickAction() { + }); + } + + public MenuItem(List slots, ItemStack itemStack, Consumer consumer) { + this(slots, itemStack, true, consumer); + } + + public MenuItem(List slots, ItemStack itemStack, boolean cancel, Consumer consumer) { + this(slots, itemStack, new ClickAction() { + @Override + public boolean cancel() { + return cancel; + } + + @Override + public void onClick(InventoryPreClickEvent event) { + consumer.accept(event); + } + }); + } + + public MenuItem(int slot, ItemStack itemStack) { + this(List.of(slot), itemStack, new ClickAction() { + }); + } + + public MenuItem(int slot, ItemStack itemStack, Consumer consumer) { + this(List.of(slot), itemStack, consumer); + } + + public MenuItem(int slot, ItemStack itemStack, boolean cancel, Consumer consumer) { + this(List.of(slot), itemStack, cancel, consumer); + } + + public interface ClickAction { + default boolean cancel() { + return true; + } + + default void onClick(InventoryPreClickEvent event) { + } + } +} diff --git a/src/main/java/com/slampvp/factory/common/menu/MenuListener.java b/src/main/java/com/slampvp/factory/common/menu/MenuListener.java new file mode 100644 index 0000000..fc949fc --- /dev/null +++ b/src/main/java/com/slampvp/factory/common/menu/MenuListener.java @@ -0,0 +1,66 @@ +package com.slampvp.factory.common.menu; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.entity.Player; +import net.minestom.server.event.GlobalEventHandler; +import net.minestom.server.event.inventory.InventoryCloseEvent; +import net.minestom.server.event.inventory.InventoryOpenEvent; +import net.minestom.server.event.inventory.InventoryPreClickEvent; + +import java.util.Optional; + +public class MenuListener { + public MenuListener() { + GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler(); + + globalEventHandler.addListener(InventoryPreClickEvent.class, event -> { + Player player = event.getPlayer(); + Optional optionalMenu = MenuManager.getInstance().getOpenMenu(player); + + if (optionalMenu.isEmpty()) { + return; + } + + Menu menu = optionalMenu.get(); + int slot = event.getSlot(); + + Optional optionalMenuItem = menu.itemBySlot(slot); + + if (optionalMenuItem.isEmpty()) { + return; + } + + MenuItem item = optionalMenuItem.get(); + + if (item.action().cancel()) { + event.setCancelled(true); + } + + item.action().onClick(event); + }); + + globalEventHandler.addListener(InventoryOpenEvent.class, event -> { + Player player = event.getPlayer(); + Optional optionalMenu = MenuManager.getInstance().getOpenMenu(player); + + if (optionalMenu.isEmpty()) { + return; + } + + Menu menu = optionalMenu.get(); + menu.onOpen(event); + }); + + globalEventHandler.addListener(InventoryCloseEvent.class, event -> { + Player player = event.getPlayer(); + Optional optionalMenu = MenuManager.getInstance().getOpenMenu(player); + + if (optionalMenu.isEmpty()) { + return; + } + + Menu menu = optionalMenu.get(); + menu.onClose(event); + }); + } +} diff --git a/src/main/java/com/slampvp/factory/common/menu/MenuManager.java b/src/main/java/com/slampvp/factory/common/menu/MenuManager.java new file mode 100644 index 0000000..0e8de9c --- /dev/null +++ b/src/main/java/com/slampvp/factory/common/menu/MenuManager.java @@ -0,0 +1,36 @@ +package com.slampvp.factory.common.menu; + +import net.minestom.server.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public final class MenuManager { + private static MenuManager instance; + private final Map openMenus; + + private MenuManager() { + this.openMenus = new HashMap<>(); + } + + public static synchronized MenuManager getInstance() { + if (instance == null) { + instance = new MenuManager(); + } + return instance; + } + + public Optional getOpenMenu(Player player) { + return Optional.ofNullable(openMenus.get(player.getUuid())); + } + + public void setOpenMenu(Player player, Menu menu) { + openMenus.put(player.getUuid(), menu); + } + + public void clearOpenMenu(Player player) { + openMenus.remove(player.getUuid()); + } +} diff --git a/src/main/java/com/slampvp/factory/player/PlayerListener.java b/src/main/java/com/slampvp/factory/player/PlayerListener.java index ea53210..c1d1a76 100644 --- a/src/main/java/com/slampvp/factory/player/PlayerListener.java +++ b/src/main/java/com/slampvp/factory/player/PlayerListener.java @@ -11,7 +11,6 @@ import net.minestom.server.instance.InstanceContainer; public class PlayerListener { - public PlayerListener(InstanceContainer instanceContainer) { GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();