Repository navigation
Container Screens
Your own chests and machines with a Lumina screen, synced by the server.
A chest, furnace or custom machine window owned by the server, just like a vanilla chest. MenuSpec is a
description shared by server and client (usually a constant): slot sections and synced numbers. On the loader,
LuminaMenu is a regular AbstractContainerMenu with vanilla slots (broadcastChanges sends the contents and the
cursor, Shift+click defaults to chest behavior), values go through DataSlot (an int as two 16-bit halves), and the
screen is a LuminaMenuScreen with the UiRoot from your factory.
// shared code
static final MenuSpec SPEC = MenuSpec.builder()
.container("chest", 27).playerInventory() // menu slots: 0..26, then backpack and hotbar
.intValue("progress").boolValue("burning").build();
static final LuminaMenuType CHEST = new LuminaMenuType(SPEC);
MENUS.register("chest", CHEST::create); // DeferredRegister<MenuType<?>>
// server
CHEST.open(player, Component.literal("Chest"), container, index -> progress, (p, action, value) -> sort());
// client: Forge in FMLClientSetupEvent.enqueueWork, NeoForge in RegisterMenuScreensEvent
LuminaMenuScreen.register(CHEST, menu -> new UiRoot(InventoryPanel.chest(menu.title(),
menu.inventory("chest"), menu.playerInventory(), Slot.Look.MODERN), ModernTheme.dark()));
new ProgressBar().bind(menu.intValue("progress").map(p -> p / 100f));
new Button("Sort", () -> menu.sendAction(SORT, 0));RemoteMenu gives each section a regular Inventory, but a remote one (Inventory.remote): slots and grids look
and drag as usual, but a drop sends vanilla clicks through handleInventoryMouseClick: the server validates and the
game predicts the result immediately. A transfer is "pick up" (all or half), "place" and, if something is left on
the cursor, "put back"; Shift+click is a quick move (the server decides the route, Slot.quickMoveTo is not
needed); outside the slots it's a throw if onDropOutside returned true; keys 1–9 and F over a slot swap with the
hotbar and offhand, Q throws (with Ctrl the whole stack). Without remote the inventory is local as before; you
can't mix remote and local slots in one transfer.
The screen checks slot contents every frame (reference and count, fully once per tick) and builds a Stack only
for the changed ones: name, the game's tooltip lines (with colors), durability, stack limit and the game stack
itself (Stack.platformStack()) so potions and heads render exactly. Values are intValue/boolValue signals,
updated together once per frame. Your own buttons use sendAction(id, number): the pair is encoded as menu button
clicks (clickMenuButton, 7 bits per click, usually two), so no custom network channel is needed. Demo:
/luminatest chest.
Начало работы: Установка · Первый экран
Основы: Раскладка · Стили и темы · Цвета и градиенты · Анимации · Данные и сигналы · События и ввод
Виджеты: Каталог виджетов · Всплывающие окна · Формы · Markdown и книги
Игра: Инвентарь и слоты · Окна-контейнеры · Мобы, предметы и 3D · HUD · Карты
Оформление: Эффекты · Размытие, обрезка и GIF
HTML и CSS: HTML и CSS
Возможности: Языки · Экран настроек · Доступность и звуки
Для продвинутых: Расширение · Отладка и советы · Архитектура
Getting started: Installation · Your First Screen
Basics: Layout · Styles and Themes · Colors and Gradients · Animations · Data and Signals · Events and Input
Widgets: Widget Catalog · Popups · Forms · Markdown and Books
Game: Inventory and Slots · Container Screens · Mobs, Items and 3D · HUD Overlay · Maps
Visuals: Effects · Blur, Clipping and GIF
HTML and CSS: HTML and CSS
Features: Languages · Config Screen · Accessibility and Sounds
Advanced: Extending · Debugging and Tips · Architecture