Menus
dev.architectury.registry.menu.MenuRegistry
Register container MenuTypes and open them for players. For simple menus you can use the
vanilla MenuType constructor directly; MenuRegistry adds cross-platform support for
extended menus that send extra data to the client when they open.
Registering a menu type
Register MenuTypes through a DeferredRegister for
Registries.MENU.
For an extended menu (one that needs extra data on open), create the type with
MenuRegistry.ofExtended, passing a StreamCodec for the extra data:
public static final DeferredRegister<MenuType<?>> MENUS =
DeferredRegister.create(MyMod.MOD_ID, Registries.MENU);
public static final RegistrySupplier<MenuType<MyMenu>> MY_MENU =
MENUS.register("my_menu", () -> MenuRegistry.ofExtended(
(windowId, inventory, pos) -> new MyMenu(windowId, inventory, pos),
BlockPos.STREAM_CODEC));
The factory receives the window id, the player Inventory, and the extra data already decoded by
the codec - a BlockPos in the example above. Any StreamCodec over RegistryFriendlyByteBuf
works, so a record holding several values can be sent in one go.
Opening a menu
| Method | Use for |
|---|---|
openMenu(ServerPlayer, MenuProvider) | A plain menu with no extra data. |
openExtendedMenu(ServerPlayer, ExtendedMenuDataProvider<D>) | An extended menu; the provider supplies the extra data. |
MenuRegistry.openExtendedMenu(serverPlayer, myProvider);
ExtendedMenuDataProvider
dev.architectury.registry.menu.ExtendedMenuDataProvider<D> is a MenuProvider with two extra
methods:
D getExtraData(ServerPlayer player);
StreamCodec<? super RegistryFriendlyByteBuf, D> getExtraDataCodec();
Implement it to bundle the menu's display name, the menu factory, and the extra data in one object,
then pass it to openExtendedMenu.
The codec returned by getExtraDataCodec() must be the same one passed to ofExtended when the
MenuType was created, otherwise the client fails to decode the data.
public class MyMenuProvider implements ExtendedMenuDataProvider<BlockPos> {
private final BlockPos pos;
public MyMenuProvider(BlockPos pos) {
this.pos = pos;
}
@Override
public BlockPos getExtraData(ServerPlayer player) {
return pos;
}
@Override
public StreamCodec<? super RegistryFriendlyByteBuf, BlockPos> getExtraDataCodec() {
return BlockPos.STREAM_CODEC;
}
@Override
public Component getDisplayName() {
return Component.translatable("menu.mymod.my_menu");
}
@Override
public AbstractContainerMenu createMenu(int windowId, Inventory inventory, Player player) {
return new MyMenu(windowId, inventory, pos);
}
}
The FriendlyByteBuf based API is deprecated and scheduled for removal in Architectury 23:
ofExtended(ExtendedMenuTypeFactory<T>)andExtendedMenuTypeFactory- useofExtended(ExtendedMenuDataFactory<T, D>, StreamCodec)andExtendedMenuDataFactory.openExtendedMenu(ServerPlayer, MenuProvider, Consumer<FriendlyByteBuf>)andopenExtendedMenu(ServerPlayer, ExtendedMenuProvider)- useopenExtendedMenu(ServerPlayer, ExtendedMenuDataProvider).ExtendedMenuProvider- useExtendedMenuDataProvider.
To migrate, define a StreamCodec for the data you were writing into the buffer by hand, and read
the decoded value in the menu factory instead of the buffer.
This page covers the server-side menu type and opening logic. To bind a screen (the client GUI) to your menu type, see Menu Screens.