Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion docs/SELECT_CRATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ SelectCrate is a new crate type for CrazyCrates that allows players to **choose*
- An enchantment glow effect
- A special marker in the lore indicating it's selected

When the prizes occupy more than one page, the previous- and next-page buttons are displayed beside the confirmation button. The selection is preserved while navigating.

3. **Confirming**: After selecting a prize, the player clicks the confirmation button (default: green concrete in slot 49).

4. **Receiving the Prize**: Upon confirmation:
Expand All @@ -25,6 +27,7 @@ SelectCrate is a new crate type for CrazyCrates that allows players to **choose*
- **Key Consumption**: Keys are only consumed when the player **confirms** their selection, not when opening the GUI
- **Visual Feedback**: Selected items have a glow effect and special lore
- **Configurable**: GUI size, button placement, messages, and marker appearance are all configurable
- **Pagination**: All configured prizes remain accessible through previous- and next-page controls
- **Safe**: Players can close the GUI without confirming to cancel the operation (no keys consumed)

## Configuration
Expand All @@ -49,6 +52,22 @@ Crate:
Name: '&aConfirm Choice'
Lore:
- '&7Click to receive the selected prize.'

Navigation:
Previous:
Slot: 48
Item:
Material: ARROW
Name: '&ePrevious Page'
Lore:
- '&7Current page: %page% of %pages%'
Next:
Slot: 50
Item:
Material: ARROW
Name: '&aNext Page'
Lore:
- '&7Current page: %page% of %pages%'

SelectionMarker:
Material: NETHER_STAR
Expand Down Expand Up @@ -87,7 +106,7 @@ Prizes in SelectCrate work the same as other crate types, but MaxRange and Chanc

## Important Notes

1. **GUI Size**: The GUI size must be large enough to display all your prizes plus the confirmation button. Reserve the bottom row (slots 45-53) for control buttons.
1. **GUI Size**: Reserve the bottom row (slots 45-53 in a 54-slot GUI) for controls. Prizes that do not fit in the remaining slots are automatically split into pages.

2. **Required Keys**: While you can set `RequiredKeys` to any value, SelectCrate will consume keys based on this setting when the player confirms.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,30 @@ public void onInventoryClick(final InventoryClickEvent event) {

// Check if clicked the confirm button
final int confirmSlot = crate.getFile() != null ?
crate.getFile().getInt("Crate.SelectCrate.Confirm.Slot", 49) : 49;
crate.getFile().getInt("Crate.SelectCrate.Confirm.Slot", SelectCrate.DEFAULT_CONFIRM_SLOT) :
SelectCrate.DEFAULT_CONFIRM_SLOT;

if (slot == confirmSlot) {
handleConfirmClick(player, session, view);
this.plugin.debug(() -> "Player clicked the confirm button in SelectCrate.");
return;
}

final int pageCount = SelectCrate.getPageCount(crate, topInventory.getSize());
if (pageCount > 1) {
final int previousSlot = crate.getFile() != null
? crate.getFile().getInt("Crate.SelectCrate.Navigation.Previous.Slot", SelectCrate.DEFAULT_PREVIOUS_PAGE_SLOT)
: SelectCrate.DEFAULT_PREVIOUS_PAGE_SLOT;
final int nextSlot = crate.getFile() != null
? crate.getFile().getInt("Crate.SelectCrate.Navigation.Next.Slot", SelectCrate.DEFAULT_NEXT_PAGE_SLOT)
: SelectCrate.DEFAULT_NEXT_PAGE_SLOT;

if (slot == previousSlot || slot == nextSlot) {
handleNavigationClick(player, session, topInventory, slot == nextSlot, pageCount);
return;
}
}

// Check if clicked on a prize
final Prize prize = crate.getPrize(clickedItem);
if (prize == null) {
Expand All @@ -126,7 +142,7 @@ public void onInventoryClick(final InventoryClickEvent event) {
private void handlePrizeSelection(final Player player, final SelectCrateSession session, final Prize prize,
final int slot, final Inventory inventory, final Crate crate) {
// Clear previous selection marker if any
if (session.hasSelection()) {
if (session.hasSelection() && session.isSelectionOnCurrentPage()) {
final int previousSlot = session.getSelectedSlot();
final Prize previousPrize = session.getSelectedPrize();
if (previousPrize != null) {
Expand All @@ -145,6 +161,28 @@ private void handlePrizeSelection(final Player player, final SelectCrateSession
crate.playSound(player, player.getLocation(), "click-sound", "UI_BUTTON_CLICK", SoundCategory.PLAYERS);
}

/**
* Moves the session to an adjacent page and redraws its prizes and controls.
*
* @param player player navigating the selection GUI
* @param session active selection session
* @param inventory inventory to redraw
* @param next whether to move forward instead of backward
* @param pageCount total number of available pages
*/
private void handleNavigationClick(final Player player, final SelectCrateSession session,
final Inventory inventory, final boolean next, final int pageCount) {
final int offset = next ? 1 : -1;
final int destination = Math.clamp(session.getCurrentPage() + offset, 0, pageCount - 1);
if (destination == session.getCurrentPage()) {
return;
}

session.setCurrentPage(destination);
SelectCrate.renderPage(inventory, player, session.getCrate(), destination, session.getSelectedPrize());
session.getCrate().playSound(player, player.getLocation(), "click-sound", "UI_BUTTON_CLICK", SoundCategory.PLAYERS);
}

/**
* Handles the confirm button click.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class SelectCrateSession {
private final Crate crate;
private Prize selectedPrize;
private int selectedSlot;
private int currentPage;
private int selectedPage;

/**
* Creates a new SelectCrate session for a player.
Expand All @@ -30,6 +32,8 @@ public SelectCrateSession(@NotNull Player player, @NotNull Crate crate) {
this.crate = crate;
this.selectedPrize = null;
this.selectedSlot = -1;
this.currentPage = 0;
this.selectedPage = -1;
}

/**
Expand Down Expand Up @@ -65,6 +69,7 @@ public Prize getSelectedPrize() {
public void setSelectedPrize(@Nullable Prize prize, int slot) {
this.selectedPrize = prize;
this.selectedSlot = slot;
this.selectedPage = this.currentPage;
}

/**
Expand All @@ -74,6 +79,29 @@ public int getSelectedSlot() {
return this.selectedSlot;
}

/**
* @return zero-based page currently displayed to the player
*/
public int getCurrentPage() {
return this.currentPage;
}

/**
* Changes the page currently displayed to the player.
*
* @param currentPage zero-based destination page
*/
public void setCurrentPage(final int currentPage) {
this.currentPage = currentPage;
}

/**
* @return whether the selected prize is visible on the current page
*/
public boolean isSelectionOnCurrentPage() {
return this.selectedPage == this.currentPage;
}

/**
* @return true if a prize is currently selected
*/
Expand All @@ -87,5 +115,6 @@ public boolean hasSelection() {
public void clearSelection() {
this.selectedPrize = null;
this.selectedSlot = -1;
this.selectedPage = -1;
}
}
Loading
Loading