Привет, улучши код
package dev.okenote.project.menu;

import dev.okenote.entities.player.JediPlayer;
import dev.okenote.services.menu.Button;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.minestom.server.MinecraftServer;
import net.minestom.server.event.inventory.*;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType;
import net.minestom.server.item.ItemStack;
import net.minestom.server.tag.Tag;
import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class JediInventory implements Menu {

    final Component title;
    final MenuType menuType;
    final InventoryType inventoryType;

    final List<TButton> buttons = new ArrayList<>();

    final Map<Integer, Inventory> pages = new HashMap<>();
    int currentPage = 1;
    final Set<Integer> slots = new LinkedHashSet<>();

    Consumer<JediPlayer> onOpen;
    Consumer<JediPlayer> onClose;

    public JediInventory(@NotNull Component title, @NotNull MenuType menuType, @NotNull InventoryType inventoryType, int... slots) {
        this.title = title;
        this.menuType = menuType;
        this.inventoryType = inventoryType;
        addSlots(slots);
        registerEvents();
    }

    public JediInventory(@NotNull Component title, int... slots) {
        this(title, MenuType.AUTO, InventoryType.CHEST_1_ROW, slots);
    }

    @Override
    public void setButton(@NotNull Integer page, @NotNull Integer slot, @NotNull ItemStack icon, BiConsumer<JediPlayer, InventoryPreClickEvent> onClick) {
        buttons.add(new TButton(page, slot, icon, onClick));
    }

    @Override
    public void addButton(@NotNull ItemStack icon, BiConsumer<JediPlayer, InventoryPreClickEvent> onClick) {
        int page = 1;

        while (true) {
            boolean slotFound = false;

            for (Integer slot : slots) {
                int finalCurrentPage = page;
                Optional<TButton> existingButton = buttons.stream()
                        .filter(button -> button.page() == finalCurrentPage && button.slot().equals(slot))
                        .findFirst();

                if (existingButton.isEmpty()) {
                    setButton(page, slot, icon, onClick);

                    slotFound = true;
                    break;
                }
            }

            if (slotFound) return;
            page++;
        }
    }

    @Override
    public void setButtonInAllPages(@NotNull Integer slot, @NotNull ItemStack icon, BiConsumer<JediPlayer, InventoryPreClickEvent> onClick) {
        int maxPage = buttons.stream()
                .mapToInt(TButton::page)
                .max()
                .orElse(0);

        for (int i = 1; i <= maxPage; i++) {
            setButton(i, slot, icon, onClick);
        }
    }

    @Override
    public void open(@NotNull JediPlayer jediPlayer, int page) {
        switch (menuType) {
            case AUTO -> createAutoMenu();
            case FIXED -> createFixedMenu();
            case CLASSIC -> createClassicMenu();
        }
        fillItems();

        if (onOpen != null) onOpen.accept(jediPlayer);

        currentPage = page;
        jediPlayer.openInventory(pages.get(currentPage));
    }

    private void createClassicMenu() {
        Inventory inventory = new Inventory(centerText(title));
        inventory.setInventoryType(inventoryType);
        inventory.setTag(Tag.String("menu"), "classic");
        pages.put(currentPage, inventory);
    }

    private void createFixedMenu() {
        Set<Integer> pagesSet = buttons.stream()
                .map(TButton::page)
                .collect(Collectors.toCollection(TreeSet::new));

        int lastPage = pagesSet.isEmpty() ? 1 : Collections.max(pagesSet);

        for (int page : pagesSet) {
            Inventory inventory = new Inventory(centerText(title).append(Component.text(" - Страница " + page)));
            inventory.setInventoryType(inventoryType);
            inventory.setTag(Tag.String("menu"), "fixed");
            pages.put(page, inventory);

            setupToolBar(inventory, page, lastPage);
        }
    }

    private void createAutoMenu() {
        Set<Integer> pagesSet = buttons.stream()
                .map(TButton::page)
                .collect(Collectors.toCollection(TreeSet::new));

        int lastPage = pagesSet.isEmpty() ? 1 : Collections.max(pagesSet);

        for (int page : pagesSet) {
            Inventory inventory;

            if (page != lastPage) {
                inventory = new Inventory(centerText(title).append(Component.text(" - Страница " + page)));
                inventory.setInventoryType(InventoryType.CHEST_6_ROW);
            } else {
                int maxSlot = buttons.stream()
                        .filter(button -> button.page() == page)
                        .mapToInt(TButton::slot)
                        .max()
                        .orElse(0);

                int rows = Math.min((maxSlot / 9) + 2, 7);

                InventoryType inventoryType = switch (rows) {
                    case 1 -> InventoryType.CHEST_1_ROW;
                    case 2 -> InventoryType.CHEST_2_ROW;
                    case 3 -> InventoryType.CHEST_3_ROW;
                    case 4 -> InventoryType.CHEST_4_ROW;
                    case 5 -> InventoryType.CHEST_5_ROW;
                    default -> InventoryType.CHEST_6_ROW;
                };


                inventory = new Inventory(centerText(title).append(Component.text(" - Страница " + page)));
                inventory.setInventoryType(inventoryType);
            }

            setupToolBar(inventory, page, lastPage);

            inventory.setTag(Tag.String("menu"), "auto");
            pages.put(page, inventory);
        }
    }

    private void fillItems() {
        for (TButton button : buttons) {
            int page = button.page();
            int slot = button.slot();
            ItemStack icon = button.icon();

            Inventory inventory = pages.get(page);

            inventory.setItemStack(slot, icon);
        }
    }

    private void registerEvents() {
        var globalEventHandler = MinecraftServer.getGlobalEventHandler();
        globalEventHandler.addListener(InventoryPreClickEvent.class, this::onInventoryClick);
        globalEventHandler.addListener(InventoryCloseEvent.class, this::onCloseEvent);

        globalEventHandler.addListener(InventoryClickEvent.class, event -> {
        });
        globalEventHandler.addListener(InventoryItemChangeEvent.class, event -> {
        });
        globalEventHandler.addListener(PlayerInventoryItemChangeEvent.class, event -> {
        });
    }

    private void onCloseEvent(InventoryCloseEvent event) {
        JediPlayer jediPlayer = (JediPlayer) event.getPlayer();
        Inventory inventory = event.getInventory();
        if (inventory == null) return;

        if (!pages.containsValue(inventory)) return;

        if (onClose != null) onClose.accept(jediPlayer);
    }

    private void onInventoryClick(InventoryPreClickEvent event) {
        JediPlayer jediPlayer = (JediPlayer) event.getPlayer();
        Inventory inventory = event.getInventory();
        if (inventory == null) return;

        if (!pages.containsValue(inventory)) return;

        event.setCancelled(true);

        int slot = event.getSlot();
        int page = getPageByInventory(inventory);
        if (page == -1) return;

        for (TButton button : buttons) {
            if (button.onClick() != null) {
                if (button.page() == page && button.slot() == slot) {
                    button.onClick().accept(jediPlayer, event);
                    break;
                }
            }
        }
    }

    private int getPageByInventory(Inventory inventory) {
        for (Map.Entry<Integer, Inventory> entry : pages.entrySet()) {
            if (entry.getValue().equals(inventory)) {
                return entry.getKey();
            }
        }
        return -1;
    }

    private void setupToolBar(Inventory inventory, int currentPage, int totalPages) {
        if (currentPage > 1)
            setToolBarItem(inventory, Button.BACK_BUTTON_ITEM, currentPage, 7, (jediPlayer, inventoryPreClickEvent) -> switchPage(jediPlayer, -1));

        if (currentPage < totalPages)
            setToolBarItem(inventory, Button.NEXT_BUTTON_ITEM, currentPage, 3, (jediPlayer, inventoryPreClickEvent) -> switchPage(jediPlayer, 1));

        setToolBarItem(inventory, Button.UPDATE_BUTTON_ITEM, currentPage, 5, (jediPlayer, inventoryPreClickEvent) -> inventory.update());

        setToolBarItem(inventory, Button.INFO_BUTTON_ITEM, currentPage, 2, (jediPlayer, inventoryPreClickEvent) -> {
        });
        setToolBarItem(inventory, Button.CLOSE_BUTTON_ITEM, currentPage, 1, (jediPlayer, inventoryPreClickEvent) -> {

        });
        setToolBarItem(inventory, Button.SORT_BUTTON_ITEM, currentPage, 8, (jediPlayer, inventoryPreClickEvent) -> {
        });
        setToolBarItem(inventory, Button.SEARCH_BUTTON_ITEM, currentPage, 9, (jediPlayer, inventoryPreClickEvent) -> {
        });
    }

    private void setToolBarItem(Inventory inventory, ItemStack item, int page, int positionFromEnd, BiConsumer<JediPlayer, InventoryPreClickEvent> action) {
        int slot = inventory.getSize() - positionFromEnd;
        setButton(page, slot, item, action);
    }

    private void switchPage(JediPlayer jediPlayer, int delta) {
        int newPage = currentPage + delta;
        if (pages.containsKey(newPage)) {
            currentPage = newPage;
            jediPlayer.openInventory(pages.get(currentPage));
        }
    }

    private void addSlots(int... boundaries) {
        if (boundaries.length % 2 != 0) {
            throw new IllegalArgumentException("Неверное количество аргументов. Должно быть четное количество чисел.");
        }

        IntStream.range(0, boundaries.length / 2)
                .flatMap(i -> IntStream.rangeClosed(boundaries[2 * i], boundaries[2 * i + 1]))
                .forEach(slots::add);
    }

    private static Component centerText(Component textComponent) {
        int textLength = PlainTextComponentSerializer.plainText().serialize(textComponent).length();
        return 36 <= textLength ? textComponent : Component.text(" ".repeat((36 - textLength) / 2)).append(textComponent);
    }
}