Wednesday, 14 January 2015

GUI containers

To skip straight to sample code for containers, see here (MBE30, MBE31).

A number of advanced blocks use "containers" - these are blocks that can store items, including
  • chests
  • crafting table
  • furnaces
It is relatively easy to implement a custom container once you understand how the components fit together and communicate with each other.  As shown in the diagram below:

  • The data about the container is stored in the TileEntity for that block.  Typical examples of the data are -what items are in the container, furnace fuel burning time & smelting time.
  • The "master copy" of the TileEntity data is always on the server.  During initial load, and when chunk data is updated/resent, the client copy is updated as for normal TileEntities (using NBT in getDescriptionPacket() and onDataPacket() - see here.
  • While the GUI is open, two extra classes are used to synchronise the data in real time and display it interactively to the user(s).  These are:
    a) GuiContainer, which 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 GuiContainer is a number of "Slots" where items can be placed.
    b) Container, which collates the information from various sources into a single instance that the GUIContainer can use.  For example, the ContainerFurnace collates information from the TileEntityFurnace and player inventory.  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.
  • The Server Container is responsible for detecting changes to the Container that might need updating:
    a) for any clients which have the container open (eg multiple users accessing the same chest) - sendSlotContents() for items and sendProgressBarUpdate() for other data
    b) for other clients - marking the block for update (which then uses the getDescriptionPacket() / onDataPacket() to update the client copy
  • Simple information can be sent from the client container to the server container using the crafters member variable of the container - icrafting.sendProgressBarUpdate() and icrafting.updateProgressBar().
The GuiContainer and Container are both generated by a single IGuiHandler-
  • getServerGuiElement() for the server side Container
  • getClientGuiElement() for the GuiContainer (which contains a Container during construction)



Communication between various parts of the container

The Container and GUIContainer combine elements from different data sources (TileEntity Items, Player Inventory Items, TileEntity extra data such as progress bars) into a single display



14 comments:

  1. Excеllent posts, do not stop. Watch for updates. And add to favorites. ;)

    ReplyDelete
  2. The Grey Ghost, please, write posts for modify player inventory (count slots) and use own gui of player inventory instead of default.

    ReplyDelete
  3. Hi, thanks for the feedback :)
    I'm not sure what you're asking me to write about? Do you mean- replace the default player inventory GUI with a custom GUI?
    -TGG

    ReplyDelete
  4. TGG, Yes!
    Sory for my poor English.
    I want to understand two points:
    1. How change default player inventory and gui, so that there is more inventory slots. Now 3x9, I want 6x9 (as a double chest)
    2. And in some cases replace default player inventory logic and gui own inventory logic and gui. For example, player inventory worked as a ender chest. That is stored in the inventory really stored in the ender chest.

    ReplyDelete
    Replies
    1. You can read source code of mods that implements similar features. E.g. https://github.com/LothrazarMinecraftMods/OverpoweredInventory/tree/master/src/main/java/com/lothrazar/powerinventory

      Delete
  5. Hi,your English is fine :) I understand you better now.
    You could probably better ask this question on the forge forum, lots of helpful folks there.
    I have never tried what you say, but I think you could try something like this:
    1) design your own GUI similar to vanilla GuiInventory. You will need to store more slots in the inventory, which I think you can do using IExtendedEntityProperties (never done it myself)
    2) subscribe to the GuiOpenEvent, and when the vanilla GuiInventory gets opened, replace it with your custom inventory.

    ReplyDelete
  6. TGG, please, add navigate panel to your blog (archive messages).
    Now very hard navigate.

    ReplyDelete
  7. Hi - you mean, a "List of Topics" page for the old pages (1.6 / 1.7)? -TGG

    ReplyDelete
  8. Hi, TGG.
    Yes, I found an interesting old message, and I am desperate to find it again

    ReplyDelete
  9. Hi Sam, I've added the old list of topics back to the menu bar. One or two link to the new topic where I had updated the post instead of making a new one. If you can't find the message you're looking for, let me know what it was about and I'll see if I can dig it up. -TGG

    ReplyDelete
  10. Hi TGG, I have a problem with my custom furnace. When I try to open my custom furnace in a spectator mode. It throwing an error message like IndexArrayOutOfBound 32 or something. I copies furnace code from Minecraft. Why I getting this?

    ReplyDelete
  11. Hi. I haven't tested with spectator mode, but perhaps the inventory size is different? Does it work with a normal player?
    You might try looking at this tutorial furnace which is easier to understand than the vanilla. https://github.com/TheGreyGhost/MinecraftByExample (see MBE31).
    You could also try asking your question here
    http://www.minecraftforge.net/forum/index.php/board,73.0.html
    Lots of helpful folks there.

    -TGG

    ReplyDelete
  12. Do crafters represent players interacting with container? Or what do they mean?

    ReplyDelete