Advanced Modding - GUI Handler

Goal

I want to show you how a GUI Handler works and how we create one. The Handler will be used in the next tutorial where we create an actual GUI.

Difficulty

3/10 - Relatively Easy

Prerequisites

We're working with the Workspace from the Tile Entity with Inventory Tutorial

Forge Version

This Tutorial was created with Forge 11.14.1.1334 for Minecraft 1.8. If anything doesn't work with other versions, please contact me!


Creating a GUI Handler

A GUI Handler is necessary if we want to add GUIs. It's used to get the right data for Client and Server when a GUI is opened.
A GUI Handler class extends the interface IGuiHandler which adds two methods: getServerGuiElement and getClientGuiElement. Those methods need to return a GUI component based on a given ID.
Generally speaking, there are two main types of GUIs: Those with a linked inventory and those without. GUIs with an inventory need an instance of GuiContainer on the client side and an instance of Container on the server side. GUIs without an inventory have an instance of GuiScreen on client and an empty Container on Server side. It's also possible to return null in this case, but then the GUI may only be opend from client side; the server will have no access on the GUI an all.
We're creating the GUIs themselves in the next tutorials, now we only write our GUI Handler. Therefore we need to create a new class. Mine is named ModGuiHandler and I placed it in the package com.bedrockminer.tutorial.network. This class needs to implement IGuiHandler.

ModGuiHandler.java:
public class ModGuiHandler implements IGuiHandler {

    @Override
    public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        return null;
    }

    @Override
    public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        return null;
    }
}

This GUI Handler needs to be registered with the game. This is done in the init() method of the CommonProxy using this line of code:

CommonProxy.java:
public void init(FMLInitializationEvent e) {
    NetworkRegistry.INSTANCE.registerGuiHandler(Main.instance, new ModGuiHandler());
}

Main.instance is your mod's instance object (The one marked with the @Instance annotation).

Note that you can only have a single GuiHandler per mod!

Now the handler is finished and we could add our GUIs if we had some. As I said, we are going to create the GUIs in the next tutorials, so this part here will be slightly abstract.
A GUI is defined by an ID which is unique inside the mod. The GUI's ID is used when an opening procedure is called. It is then passed to the GUI Handler. In the handler's method we need to check for the IDs and return the corresponding objects.
Here, I'll show you an example how this can look like (This is actually the GUI we'll create for the Tile Entity with Inventory):
The GUI's ID is 0. This is hardcoded in a constant integer (MOD_TILE_ENTITY_GUI). If the ID passed to the methods is equal to this ID, the GUI objects are created and returned. On server side this is a new instance of a subclass of Container, on client side its a new instance of a subclass of GuiContainer (Both classes will be created in the next tutorial).

ModGuiHandler.java:
public class ModGuiHandler implements IGuiHandler {

    public static final int MOD_TILE_ENTITY_GUI = 0;

    @Override
    public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        if (ID == MOD_TILE_ENTITY_GUI)
            return new ContainerModTileEntity();

        return null;
    }

    @Override
    public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        if (ID == MOD_TILE_ENTITY_GUI)
            return new GuiModTileEntity();

        return null;
    }
}

That's how a "registration" of a GUI object looks in the GUI Handler.

As an example I want to open the GUI on right clicking the Tile Entity block from the tutorial about Tile Entities. Therefore, we override onBlockActivated in the ModBlockTileEntity class.
To open a GUI using our handler we need to call player.openGui(ModInstance, GUIID, World, x, y, z); as you can see here.

ModBlockTileEntity.java:
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ) {
    if (!world.isRemote) {
        player.openGui(Main.instance, ModGuiHandler.MOD_TILE_ENTITY_GUI, world, pos.getX(), pos.getY(), pos.getZ());
    }
    return true;
}

This example only shows how to add a GUI handler and how to use it. In the next tutorial (GUI with Inventory) we'll create our first real GUI.


You can download the code used in this tutorial as a .zip file from here.


Recommended tutorials to continue with


Comments and Questions:

If you want to report modding problems, please make sure to include the code in a pastebin link or something else! Don't just write "It doesn't work", otherwise your post will be deleted. For more complicated problems, please use the troubleshooter form.