diff --git a/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java b/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java index e0c5afa..826accc 100644 --- a/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java +++ b/src/main/java/dev/esophose/playerparticles/gui/GuiInventoryLoadPresetGroups.java @@ -44,7 +44,7 @@ public GuiInventoryLoadPresetGroups(PPlayer pplayer, boolean isEndPoint, int pag continue; int slot = group.getGuiSlot(); - if (slot == -1) { + if (slot == -1 || slot == -2) { slot = this.getFirstEmptySlot(); if (slot == -1) break; diff --git a/src/main/java/dev/esophose/playerparticles/manager/ParticleGroupPresetManager.java b/src/main/java/dev/esophose/playerparticles/manager/ParticleGroupPresetManager.java index 94af959..2cab60a 100644 --- a/src/main/java/dev/esophose/playerparticles/manager/ParticleGroupPresetManager.java +++ b/src/main/java/dev/esophose/playerparticles/manager/ParticleGroupPresetManager.java @@ -265,31 +265,69 @@ public void disable() { * @return a Map of page numbers to preset pages for a PPlayer */ public Map getPresetGroupPages(PPlayer pplayer) { - // Hide pages the player doesn't have access to anything for - Map presetGroupPages = new HashMap<>(); + List configPageNumbers = this.presetGroupPages.keySet().stream().sorted().collect(Collectors.toList()); - List pageNumbers = this.presetGroupPages.keySet().stream().sorted().collect(Collectors.toList()); + // Collect all "globally-packed" (gui-slot = -2) presets visible to the player, preserving config page order + List globalPresets = new ArrayList<>(); + for (int key : configPageNumbers) { + ParticleGroupPresetPage page = this.presetGroupPages.get(key); + page.getPresets().stream() + .filter(p -> p.getGuiSlot() == -2 && p.canPlayerUse(pplayer)) + .forEach(globalPresets::add); + } + + Map result = new HashMap<>(); int pageNumber = 1; - for (int key : pageNumbers) { + + // Pack "globally-packed" presets into pages, using each config page's title and border + if (!globalPresets.isEmpty()) { + int presetIndex = 0; + for (int key : configPageNumbers) { + if (presetIndex >= globalPresets.size()) break; + + ParticleGroupPresetPage configPage = this.presetGroupPages.get(key); + Map extraBorder = configPage.getExtraBorder(); + + long freeSlotCount = IntStream.range(0, 54) + .filter(i -> !extraBorder.containsKey(i)) + .count(); + if (freeSlotCount == 0) + continue; + + List pagePresets = new ArrayList<>(); + for (int i = 0; i < freeSlotCount && presetIndex < globalPresets.size(); i++) + pagePresets.add(globalPresets.get(presetIndex++)); + + result.put(pageNumber++, new ParticleGroupPresetPage(configPage.getTitle(), pagePresets, extraBorder)); + } + } + + // Handle regular pages (presets with gui-slot != -2), skipping pages with nothing visible + for (int key : configPageNumbers) { ParticleGroupPresetPage page = this.presetGroupPages.get(key); - if (page.getPresets().stream().noneMatch(x -> x.canPlayerUse(pplayer))) + + List nonGlobalPresets = page.getPresets().stream() + .filter(p -> p.getGuiSlot() != -2) + .collect(Collectors.toList()); + + if (nonGlobalPresets.stream().noneMatch(x -> x.canPlayerUse(pplayer))) continue; - presetGroupPages.put(pageNumber++, page); + result.put(pageNumber++, new ParticleGroupPresetPage(page.getTitle(), nonGlobalPresets, page.getExtraBorder())); } // Use a default page - if (presetGroupPages.isEmpty()) { + if (result.isEmpty()) { LocaleManager localeManager = this.rosePlugin.getManager(LocaleManager.class); Map extraBorder = new HashMap<>(); BorderColor borderColor = BorderColor.getOrDefault(Settings.GUI_GLASS_COLORS_LOAD_PRESET_GROUPS.get(), BorderColor.GREEN); IntStream.range(0, 9).forEach(x -> extraBorder.put(x, borderColor)); IntStream.range(45, 54).forEach(x -> extraBorder.put(x, borderColor)); Arrays.asList(9, 18, 27, 36, 17, 26, 35, 44).forEach(x -> extraBorder.put(x, borderColor)); - presetGroupPages.put(1, new ParticleGroupPresetPage(localeManager.getLocaleMessage("gui-load-a-preset-group"), Collections.emptyList(), extraBorder)); + result.put(1, new ParticleGroupPresetPage(localeManager.getLocaleMessage("gui-load-a-preset-group"), Collections.emptyList(), extraBorder)); } - return Collections.unmodifiableMap(presetGroupPages); + return Collections.unmodifiableMap(result); } /** diff --git a/src/main/resources/preset_groups.yml b/src/main/resources/preset_groups.yml index cb260ce..044d7d2 100644 --- a/src/main/resources/preset_groups.yml +++ b/src/main/resources/preset_groups.yml @@ -17,7 +17,8 @@ # group-name: The name of the group, how it will be applied by using /pp group load . # display-name: The display name of the group, how it will show up in the GUI. # gui-icon: The icon to use for the GUI. -# gui-slot: The slot that will be filled in the GUI. Use -1 to automatically fill in the next available slot. +# gui-slot: The slot that will be filled in the GUI. Use -1 to automatically fill in the next available slot on the current page. +# Use -2 to automatically fill in the next available slot across ALL pages, packing all -2 presets together starting from page 1. # lore: Extra text that will appear on the preset group button. # permission: The permission that the player must have to see this group, may be left blank as ''. The player must still have permission for all effects/styles within the group in order to use it. # allow-permission-override: Allow the player to see and apply the group even if they don't have access to all the effects/styles within it. This does nothing if the permission is set to ''.