A number of advanced blocks use "containers" - these are blocks that can store items, including
- Chests (permanent storage)
- Furnaces (permanent storage)
- Crafting table (temporary storage only)
The logic for containers can be quite confusing until you understand how they are structured.
- A Container is used to bundle together different “Slots” into a single location. Each Slot contains an ItemStack. The Container may also contain other information, eg progress bar time. For example, the FurnaceContainer collates information from the FurnaceTileEntity and the PlayerInventory. It provides a consecutive list of Slots numbered from 0 .. N-1, where (eg) 0..35 might come from the player inventory, and 36 - 44 might come from the TileEntity. It also tracks the smelting progress as an int.
- Containers don’t permanently store information. They are created, exist for a short time, then disappear. Any items permanently stored in the “container” are actually stored elsewhere (usually – in the TileEntity).
- Two Containers are created, one on the server and one on the client. Vanilla will keep the slots in synch for you automatically, but extra information (eg progress bar information) you will need to synchronise yourself.
- These two containers are created in two different ways:
- The server Container is constructed by a NamedContainerProvider::createMenu(), which is usually a TileEntity that implements the interface. The NCP gives the container a link to its “permanent storage” inventory of items, which allows the container to alter the permanently stored items in the TileEntity. In vanilla, this link is via the IInventory interface.
- The client Container is constructed (in response to a packet from the server) by using the registered ContainerType::create() method, which gives the container a link to an empty/temporary inventory instead of to a TileEntity’s “permanent storage”.
- In addition to the client container, the client also has a ContainerScreen, which is the visual representation of the container. It specifies the layout of the GUI, retrieves items and other data (eg progress bars) for display, and interacts with the user. The basic element of the Screen is a number of "Slots" where items can be placed, you can add other graphic elements as desired. The Screen only ever exists on the client, and is created by the registered IScreenFactory for that ContainerType.
- PlayerEntity::openContainer instead of NetworkHooks::openGUI
You can use the Vanilla methods if you prefer to do so, although the Forge methods are slightly more convenient / flexible.
It is not essential to use TileEntities as the NamedContainerProvider. Blocks without TileEntities (eg CraftingTableBlock), an Entity (similar to the player's inventory), or even an Itemstack (eg using Capability) can be used instead.
|Screen representation of a Container|
|Information flow involved with Containers|
|Creation/initialisation sequence for Containers|