Menus

MenuRegistry is used for registering MenuTypes and Screens for containers. It provides methods to open menus, create MenuTypes, and register Screen factories.

Opening the Menu

openExtendedMenu(ServerPlayer, MenuProvider, Consumer<FriendlyByteBuf>)

This method opens an extended menu for the specified ServerPlayer. It takes a MenuProvider for the menu and a Consumer<FriendlyByteBuf> for writing extra data to the menu. The extra data is sent to the server and can be used to modify the menu's behavior.

openMenu(ServerPlayer, MenuProvider)

This method opens a simple menu for the specified ServerPlayer. It takes a MenuProvider for the menu. This method can not be used to open an extended menu.

Creating the MenuType

of(SimpleMenuTypeFactory<T>)

This method creates and returns a simple MenuType for the specified AbstractContainerMenu type T. It takes a SimpleMenuTypeFactory functional interface that is used to create the MenuType.

To open this menu, use the openMenu method above.

ofExtended(ExtendedMenuTypeFactory<T>)

This method creates and returns an extended MenuType for the specified AbstractContainerMenu type T. It takes an ExtendedMenuTypeFactory functional interface that is used to create the MenuType, this extended factory contains the FriendlyByteBuf added in the lambda in openExtendedMenu.

To open this menu, use the openExtendedMenu method above.

Handling creating the Screen for the Menu

registerScreenFactory(MenuType<? extends H>, ScreenFactory<H, S>)

This method registers a ScreenFactory for the specified MenuType. The ScreenFactory is used to create new Screens for the specified AbstractContainerMenu type.

Example

First, we need to define a MenuType for our custom menu:

private static final RegistrySupplier<MenuType<ExampleMenu>> EXAMPLE_MENU_TYPE = MENUS.register("example_menu", () -> MenuRegistry.of(ExampleMenu::new));

Next, let's define our custom menu class, which extends AbstractContainerMenu:

public class ExampleMenu extends AbstractContainerMenu {
   public ExampleMenu(int id, Inventory inventory) {
      super(EXAMPLE_MENU_TYPE.get(), id);
   }
 
   // other methods...
}

Once you've registered your MenuType, you can register a screen for your custom menu.

First, let's define our custom screen class, which extends AbstractContainerScreen:

public class ExampleScreen extends AbstractContainerScreen<ExampleMenu> {
   public ExampleScreen(ExampleMenu menu, Inventory inventory, Component title) {
      super(menu, inventory, title);
   }
 
   // other methods...
}

Next, we need to register our screen, be sure to do this in a ClientLifecycleEvent.CLIENT_SETUP.

MenuRegistry.registerScreenFactory(EXAMPLE_MENU_TYPE.get(), ExampleScreen::new);

To open the menu:

MenuRegistry.openMenu(player, new MenuProvider() {
   @Override
   public AbstractContainerMenu createMenu(int id, Inventory inventory, Player player) {
      return EXAMPLE_MENU_TYPE.create(id, inventory);
   }
 
   @Override
   public Component getDisplayName() {
      return Component.translatable("container.examplemod.example_menu");
   }
});