GUI & Inventory API
PotatoMC provides a native, high-performance Virtual Chest GUI and Inventory management API mirroring the simplicity and power of Paper's InventoryHolder and custom screen handlers—running at native C/Rust speeds with zero JVM GC pressure.
1. Creating Virtual Chest GUIs
Create custom chest screens with Gui::chest(title, rows):
use potato_api::gui::Gui;
use potato_api::types::ItemStack;
// Create a 3-row (27 slots) virtual chest GUI
let mut gui = Gui::chest("§6§lPotato Rewards Shop", 3);
// Prevent players from taking decorative items
gui.set_allow_grab(false);
gui.set_allow_put(false);
// Configure decorative border
let mut border = ItemStack::new("minecraft:gray_stained_glass_pane", 1);
border.set_custom_name(" ");
gui.fill_border(border);
// Place interactive items in specific slots
let mut reward = ItemStack::new("minecraft:netherite_sword", 1);
reward.set_custom_name("§4§lExecutioner Blade");
reward.add_lore("§7Click to purchase for 50 Coins");
reward.add_enchantment("minecraft:sharpness", 5);
gui.set_item(13, reward); // Center slotGUI Configuration Options
| Method | Description |
|---|---|
Gui::chest(title, rows) | Create a chest GUI with 1–6 rows (9 to 54 slots). |
gui.set_item(slot, item) | Set an ItemStack at an explicit slot index (0-indexed). |
gui.get_item(slot) | Retrieve a reference to the item at slot. |
gui.fill_border(item) | Fill row 0, row N-1, and column 0 & 8 borders with an item. |
gui.fill_all(item) | Fill all unoccupied slots with an item. |
gui.set_allow_grab(bool) | Flag whether players can take items out of the GUI (default: false). |
gui.set_allow_put(bool) | Flag whether players can place items into the GUI (default: false). |
2. Opening & Closing GUIs
Open or close screens directly on Player:
// Open custom GUI for player
player.open_gui(&gui);
// Close currently opened screen
player.close_inventory();When open_gui is called, PotatoMC dynamically constructs a container screen, synchronizes all item slots to the client via native protocol packets, and handles cross-play transparently for both Java Edition and Bedrock Edition players.
3. Handling GUI Clicks
Listen to InventoryClickEvent to implement custom shop logic, menu navigation, or item protection:
use potato_api::event::{InventoryClickEvent, Cancellable};
context.register_event(|event: &mut InventoryClickEvent| {
// Check clicked slot
if event.slot == 13 {
// Cancel to prevent grabbing the display item
event.set_cancelled(true);
event.player.send_message("§a[Shop] You purchased the Executioner Blade!");
let mut reward = ItemStack::new("minecraft:netherite_sword", 1);
reward.set_custom_name("§4§lExecutioner Blade");
reward.add_enchantment("minecraft:sharpness", 5);
// Give item to player
event.player.give_item(&reward);
event.player.close_inventory();
}
});Event Fields
event.player: ThePlayerwho clicked.event.slot: Slot number clicked (0 to size-1 for top inventory, 36–44 for hotbar, 9–35 for main inventory).event.click_type: Click action identifier (0 = Pickup, 1 = QuickMove/ShiftClick, etc.).event.clicked_item:Option<ItemStack>of the item in the clicked slot.event.cursor_item:Option<ItemStack>of the item currently held on the cursor.event.set_cancelled(true): Reverts and cancels the click on both server and client.
4. Player Inventory Manipulation
Giving Items (give_item)
Adds an item directly to the player's inventory. If the inventory is full, the remaining items are spawned naturally at the player's feet:
let mut apple = ItemStack::new("minecraft:enchanted_golden_apple", 5);
apple.set_custom_name("§6§lSuper Apple");
// Give directly to player
player.give_item(&apple);Dropping Items (drop_item)
Spawns an item drop directly from the player:
let diamond = ItemStack::new("minecraft:diamond", 3);
player.drop_item(&diamond);World Dropped Items
Spawn dropped items anywhere in the world:
use potato_api::types::{Location, ItemStack};
let loc = Location::new("world", 100.5, 64.0, -200.5);
let gem = ItemStack::new("minecraft:emerald", 10);
// Drop at exact coordinates
world.drop_item(loc, &gem);
// Drop naturally with random horizontal velocity
world.drop_item_naturally(loc, &gem);