Skip to main content

Bukkit Gui

Bukkit Gui Module is a new replacement of the old Bukkit Menu Module. With the power feature of pane, mapping, and more independent components, you can create a GUI with ease.


First Release: 0.7.1b1-SNAPSHOT

Adding the gui module​

In your module build.gradle, please add the following dependency:

dependencies {
api 'io.fairyproject:bukkit-gui'

// Other dependencies
}

Creating a Gui​

To create a Gui, you'll first need to inject the GuiFactory class into your component, and include a title in the create function.

@InjectableComponent
public class MyComponent {
private final GuiFactory guiFactory;

public MyComponent(GuiFactory guiFactory) {
this.guiFactory = guiFactory;
}

public void open(Player player) {
Gui gui = guiFactory.create(Component.text("My Gui"));

// configure

gui.open(player);
}
}

Done! you created a Gui with a title of My Gui, easy right? but what if you want to add a pane to the Gui?


Pane System​

Here it comes, the main difference between the old Menu Module and the new Gui Module, the Pane System.

A Pane is a container that holds gui items, and it can be added to the Gui to display the components. A Gui can hold multiple panes, and each pane will have their specific position and region.

Creating a Pane​

Creating a pane is simple, you can use the Pane class to create a new pane, and add it to the Gui. Let's start with a normal pane.

NormalPane pane = Pane.normal(9, 3); // 9 slots, 3 rows

gui.addPane(pane);

A normal pane is a pane that holds a fixed amount of slots, there is also other types of panes such as PaginatedPane for paginated slots.

Adding Slots​

To add slots to the pane, you can use the setSlot method to add an item to the pane.

pane.setSlot(0, GuiSlot.of(XMaterial.APPLE));

pane.fillEmptySlots(GuiSlot.of(XMaterial.GRAY_STAINED_GLASS_PANE)); // fill empty slots with a specific gui slot

You have a Gui with an apple in the first slot, and the rest of the slots are filled with gray stained-glass pane! Easy so far?


Gui Slot​

With the previous example, you know how to create a GuiSlot with plain material. But actually, you can do more with GuiSlot. Not only accepting XMaterial, but also ItemStack, ItemBuilder, and regular Bukkit Material etc.

GuiSlot withItemBuilder = GuiSlot.of(ItemBuilder
.of(XMaterial.APPLE)
.name("&bApple")
.build());
GuiSlot withItemStack = GuiSlot.of(new ItemStack(Material.APPLE));
GuiSlot withMaterial = GuiSlot.of(Material.APPLE);

Behavior​

GuiSlot also supports behavior, you can add a click event to the slot, and it will be triggered when the player clicks on the slot.

GuiSlot onClick = GuiSlot.of(XMaterial.APPLE, clickedPlayer -> {
clickedPlayer.sendMessage("You clicked the apple!");
});

GuiSlot onRightClick = GuiSlot.of(XMaterial.APPLE, (clickedPlayer, clickType) -> {
if (clickType != ClickType.RIGHT)
return;
clickedPlayer.sendMessage("You right-clicked the apple!");
});

Item Selector​

Item Selector is a special type of GuiSlot that allows the player to select an item from their inventory.

import java.util.concurrent.atomic.AtomicReference;

AtomicReference<ItemStack> item = new AtomicReference<>(new ItemStack(Material.APPLE));

// Create an item selector in the first slot of the pane.
// Make sure when you setSlot to the pane, you set the slot to 0 too.
GuiSlot itemSelectorSlot = GuiSlot.itemSelector(pane, 0)
.emptyItem(new ItemStack(Material.BARRIER)) // The item to display when there is no item in the item selector.
.currentItem(new ItemStack(Material.APPLE)) // The default item available in the item selector.
.canPlacePredicate(itemStack ->itemStack.getType() == Material.APPLE) // The predicate to check if the player can place the item.
.updateCallback(itemStack -> {
// The callback to update the item in the item selector.
// This will be called when the player places an item in the item selector.
item.set(itemStack);
})
.build();

pane.setSlot(0, itemSelectorSlot);

Paginated​

PaginatedPane is a special type of pane that holds a paginated list of slots, and it allows the player to navigate through the pages.

PaginatedPane paginatedPane = Pane.paginated(9, 3); // 9 slots, 3 rows

// Add slots to the paginated pane
for (int i = 0; i < 100; i++) {
int index = i;
paginatedPane.addSlot(GuiSlot.of(XMaterial.APPLE, clickedPlayer -> {
clickedPlayer.sendMessage("You clicked the apple number " + index);
});
}

NormalPane navigationPane = Pane.normal(0, 4, 9, 1); // 9 slots, 1 row, starting from the 4th row
navigationPane.setSlot(0, GuiSlot.previousPage(paginatedPane)); // The previous page button
navigationPane.setSlot(8, GuiSlot.nextPage(paginatedPane)); // The next page button

gui.addPane(paginatedPane);
gui.addPane(navigationPane);