Containers are objects that hold items in Allay. This includes player inventories, chests, furnaces,
and many other blocks that can store items. Allay also provides a powerful "fake container" system
for creating custom GUIs.
ContainerType represents the type of a container and defines its size. Container types are used
to identify and retrieve containers from a ContainerHolder.
ContainerHolder is an interface for objects that hold multiple containers. EntityPlayer implements
this interface to hold inventory, armor, and offhand containers.
importorg.allaymc.api.container.ContainerTypes;importorg.allaymc.api.entity.interfaces.EntityPlayer;publicvoidaccessPlayerContainers(EntityPlayerplayer){// Get player's inventory containervarinventory=player.getContainer(ContainerTypes.INVENTORY);// Get player's armor containervararmor=player.getContainer(ContainerTypes.ARMOR);// Get player's offhand containervaroffhand=player.getContainer(ContainerTypes.OFFHAND);}
importorg.allaymc.api.container.ContainerTypes;importorg.allaymc.api.entity.interfaces.EntityPlayer;importorg.allaymc.api.item.ItemStack;publicvoidgetPlayerItems(EntityPlayerplayer){// Get the item in the player's handItemStackitemInHand=player.getItemInHand();// Get the current hand slot index (0-8)inthandSlot=player.getHandSlot();// Get an item from a specific inventory slotvarinventory=player.getContainer(ContainerTypes.INVENTORY);ItemStackitem=inventory.getItemStack(0);// Get all items in the inventoryvarallItems=inventory.getItemStacks();}
importorg.allaymc.api.container.ContainerTypes;importorg.allaymc.api.entity.interfaces.EntityPlayer;importorg.allaymc.api.item.type.ItemTypes;publicvoidsetPlayerItems(EntityPlayerplayer){// Set item in handplayer.setItemInHand(ItemTypes.DIAMOND_SWORD.createItemStack());// Clear item in handplayer.clearItemInHand();// Set item at a specific slotvarinventory=player.getContainer(ContainerTypes.INVENTORY);inventory.setItemStack(0,ItemTypes.DIAMOND.createItemStack(64));// Clear a specific slotinventory.clearSlot(0);// Clear the entire inventoryinventory.clearAllSlots();}
importorg.allaymc.api.entity.interfaces.EntityPlayer;importorg.allaymc.api.item.type.ItemTypes;publicvoidaddItemsToPlayer(EntityPlayerplayer){vardiamond=ItemTypes.DIAMOND.createItemStack(32);// Try to add item - will merge with existing stacks or find empty slot// If inventory is full, the item will be dropped at the player's positionplayer.tryAddItem(diamond);}
importorg.allaymc.api.container.ContainerTypes;importorg.allaymc.api.entity.interfaces.EntityPlayer;importorg.allaymc.api.item.type.ItemTypes;publicvoidworkWithBlockContainer(EntityPlayerplayer){// Get the container the player has opened (e.g., a chest)varcontroller=player.getController();if(controller!=null){varopenedChest=controller.getOpenedContainer(ContainerTypes.CHEST);if(openedChest!=null){// Add an item to the chestopenedChest.tryAddItem(ItemTypes.GOLD_INGOT.createItemStack(16));// Get an item from the chestvaritem=openedChest.getItemStack(0);}}}
importorg.allaymc.api.container.Container;importorg.allaymc.api.container.ContainerViewer;publicvoidsetupContainerListeners(Containercontainer){// Listen for container open eventscontainer.addOpenListener((ContainerViewerviewer)->{System.out.println("Container opened by a viewer");});// Listen for container close eventscontainer.addCloseListener((ContainerViewerviewer)->{System.out.println("Container closed by a viewer");});// Listen for changes to a specific slotcontainer.addSlotChangeListener(0,(itemStack)->{System.out.println("Slot 0 changed to: "+itemStack.getItemType().getIdentifier());});}
Fake containers are virtual containers that don't correspond to any real block in the world.
They are useful for creating custom GUIs like menus, shops, or interactive interfaces.
importorg.allaymc.api.container.FakeContainerFactory;importorg.allaymc.api.item.type.ItemTypes;publicvoidconfigureFakeContainer(){varfakeChest=FakeContainerFactory.getFactory().createFakeChestContainer();// Set a custom name (displayed in the container header)fakeChest.setCustomName("My Custom Menu");// Add items to the containerfakeChest.setItemStack(0,ItemTypes.DIAMOND.createItemStack());fakeChest.setItemStack(4,ItemTypes.EMERALD.createItemStack());fakeChest.setItemStack(8,ItemTypes.GOLD_INGOT.createItemStack());}
importorg.allaymc.api.container.FakeContainerFactory;importorg.allaymc.api.item.type.ItemTypes;importorg.allaymc.api.player.Player;publicvoidcreateInteractiveMenu(Playerplayer){varmenu=FakeContainerFactory.getFactory().createFakeChestContainer();menu.setCustomName("Shop Menu");// Add item with click listenermenu.setItemStackWithListener(0,ItemTypes.DIAMOND_SWORD.createItemStack(),()->{player.sendMessage("You clicked on the Diamond Sword!");// Add your shop logic here});// Or add listener separatelymenu.setItemStack(4,ItemTypes.GOLDEN_APPLE.createItemStack());menu.addClickListener(4,()->{player.sendMessage("You clicked on the Golden Apple!");});// Show the menu to the playermenu.addPlayer(player);}
Use addPlayer() instead of addViewer() for fake containers. The addPlayer() method
handles sending fake blocks to the client before opening the container.
importorg.allaymc.api.container.FakeContainerFactory;importorg.allaymc.api.player.Player;publicvoidshowFakeContainer(Playerplayer){varfakeChest=FakeContainerFactory.getFactory().createFakeChestContainer();fakeChest.setCustomName("My Menu");// Show to player (with optional callback)fakeChest.addPlayer(player,success->{if(success){System.out.println("Container opened successfully");}else{System.out.println("Failed to open container");}});// Or without callbackfakeChest.addPlayer(player);}
importorg.allaymc.api.container.interfaces.FakeContainer;importorg.allaymc.api.player.Player;publicvoidcloseFakeContainer(FakeContainercontainer,Playerplayer){// Remove a specific playercontainer.removeViewer(player);// Remove all viewerscontainer.removeAllViewers();}
importorg.allaymc.api.container.FakeContainerFactory;importorg.allaymc.api.container.interfaces.FakeContainer;importorg.allaymc.api.item.ItemStack;importorg.allaymc.api.item.type.ItemTypes;importorg.allaymc.api.player.Player;importjava.util.List;publicclassPaginatedMenu{privatefinalPlayerplayer;privatefinalList<ItemStack>items;privatefinalintitemsPerPage=45;// Leave bottom row for navigationprivateintcurrentPage=0;privateFakeContainermenu;publicPaginatedMenu(Playerplayer,List<ItemStack>items){this.player=player;this.items=items;}publicvoidopen(){showPage(0);}privatevoidshowPage(intpage){this.currentPage=page;// Close previous menu if openif(menu!=null){menu.removeViewer(player);}menu=FakeContainerFactory.getFactory().createFakeDoubleChestContainer();menu.setCustomName("Items - Page "+(page+1));// Calculate items for this pageintstartIndex=page*itemsPerPage;intendIndex=Math.min(startIndex+itemsPerPage,items.size());// Add itemsfor(inti=startIndex;i<endIndex;i++){intslot=i-startIndex;ItemStackitem=items.get(i);menu.setItemStackWithListener(slot,item,()->{player.sendMessage("You selected: "+item.getItemType().getIdentifier());});}// Previous page button (slot 45)if(page>0){menu.setItemStackWithListener(45,ItemTypes.ARROW.createItemStack(),()->{showPage(currentPage-1);});}// Next page button (slot 53)if(endIndex<items.size()){menu.setItemStackWithListener(53,ItemTypes.ARROW.createItemStack(),()->{showPage(currentPage+1);});}// Close button (slot 49)menu.setItemStackWithListener(49,ItemTypes.BARRIER.createItemStack(),()->{menu.removeViewer(player);});menu.addPlayer(player);}publicintgetTotalPages(){return(int)Math.ceil((double)items.size()/itemsPerPage);}}
Remember to remove viewers from fake containers when they are no longer needed. Fake
containers send fake blocks to the client, which are cleaned up when the viewer is removed.
Click Listener Cleanup
If you're reusing fake containers, call removeAllClickListeners() before setting up new
listeners to avoid duplicate callbacks.
Player.getController()
When working with fake containers, use player.getController() to get the Player interface
from an EntityPlayer. The controller handles the network communication for containers.
Container Updates
When you modify items in a container using setItemStack(), viewers are automatically
notified. If you modify an ItemStack directly (e.g., changing count), call
notifySlotChange(slot) to update viewers.