Jump to content

How to make a custom gui?


MrPonyCaptain

Recommended Posts

There is already a tutorial for this and the full answer is too long to put in one post anyhow.

 

I too would like help with this, but I noticed that the tutorial you linked was intended for December 20, 2012. I'm sure forge has been massively changed since then, because literally copying and pasting those files yields errors. I'm finding it very difficult to learn how to program minecraft. I would know because I spent a while programming Runescape bots for RS Bot (which uses java). I know java fairly well.

Link to comment
Share on other sites

I don't want to post entire class files, so I'll assume you know how to set up a basic block and tile entity. Ensure these methods are in your respective classes and tweak them from there.

 

Block:

//If you want your gui to have an inventory, have your block extend BlockContainer
//If not, have it extend Block and implement ITileEntityProvider

@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer playerEntity, int w, float px, float py, float pz)
{
                //the second parameter (0) is the gui ID and is used in the gui handler
                //for it to know which gui window to use - use a different ID for each gui window
	playerEntity.openGui(MainModClass.instance, 0, world, x, y, z);
	return false;
}

    public TileEntity createNewTileEntity(World world)
    {
    	return new TileEntityClass ();
    }

 

GuiHandler:

public class GuiHandler implements IGuiHandler
{
@Override
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
                //I don't use any containers in my GUIs (GuiContainer), but if I did, I'd return them here.
                //You can only get away with what I'm doing here if your GUIs extend GuiScreen and not GuiContainer
                //Servers get containers - Clients get GUIs
	return null;
}

@Override
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
	switch(ID)
	{
	case 0:
		return new BlockGuiWindow();
	//etc
	case 1:
		return new DialogGUI();
        //etc
	case 2:
                        return new QuestGUI();
                //etc
        case 3:
                        return new ShopGUI();
	}
	return null;
                //It is common Java convention to "break;" a switch case, but because all my cases end in returns, I don't need to
}
}

 

BlockGuiWindow:

@SideOnly(Side.CLIENT)
public class BlockGuiWindow extends GuiScreen //extend GuiContainer if you want your gui to have an inventory
{
final int xSizeOfTexture = 192
	   , ySizeOfTexture = 135
                   , white = Color.white.getRGB();
int posX
  , posY;

        //If you want your gui to change based on TileEntity values, reference the tile entity in the constructor
        //you must pass the tile entity using "return new BlockGuiWindow(world.getBlockTileEntity(x, y, z))" in the GuiHandler
        TileEntityClass te;

public BlockGuiWindow(TileEntityClass te)
{
	this.te = te;
}

        public void initGui()
{
	this.buttonList.clear();

	posX = (this.width - xSizeOfTexture) / 2;
	posY = (this.height - ySizeOfTexture) / 2;

	this.buttonList.add(new GuiButton(0, posX + 4, posY + 4, 20, 20, "ButtonText"));
                /*Parameters:
                 * button id used when checking what to do when a button is pressed
                 * The X position of the button
                 * The Y position of the button
                 * The width
                 * The height (keep this at 20 if you can)
                 * The text to be displayed on the button*/
        }

        public void actionPerformed(GuiButton button)
{
	switch(button.id)
	{
                     case 0:
                         //Do button stuff
                         break;
                }
        }

        @Override
public void drawScreen(int x, int y, float f)
{
	drawDefaultBackground();

	GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
	this.mc.renderEngine.bindTexture("path/to/the/background/texture");

	int posX = (this.width - xSizeOfTexture) / 2;
	int posY = (this.height - ySizeOfTexture) / 2;

	drawTexturedModalRect(posX, posY, 0, 0, xSizeOfTexture, ySizeOfTexture); //This draws the background
                //Make sure your background texture is a multiple of 256x256.
                //The xSizeOfTexture and ySizeOfTexture assume that the texture is 256x256. so 128 and 128 always reference half of the texture.
                //Look in the Gui class to see what else you can do here (like rendering textures and strings)
                this.drawString(fontRenderer, "Text", posX + 20, posY + 31, white); //this is where the white variable we set up at the beginning is used
                super.drawScreen(x, y, f);
                /*Here is a trick:
                   If you reset the texture after "super.drawScreen(x, y, f);" (this.mc.renderEngine.bindTexture("path/to/the/background/texture"),
                   you can draw on top of everything, including buttons.
                   Use this to texture buttons, if you don't want them to have text.*/
        }

 

MainModClass:

@Instance //The @Instance goes with the following line, nothing else
    public static MainModClass instance = new MainModClass();

GameRegistry.registerTileEntity(TileEntityClass.class, "TileEntityName");
NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler());

 

Those are the major snippets of the code I use for my stuff (with the names changed.) I have specific needs and you'll need to change the code a bit to do what you want it to, mainly adding a Container class and referencing it in the GuiHandler if you need a GuiContainer. You also may want to change my parenthetical syntax. I'm a C# programmer and the java parenthetical syntax bugs me :P

width=336 height=83http://img836.imageshack.us/img836/1237/cooltext624963071.png[/img]

I make games, minecraft mods/plugins, and some graphic art.

 

Current Project: LoECraft - An industrial minecraft server with its own modpack and custom launcher.

Link to comment
Share on other sites

I don't want to post entire class files, so I'll assume you know how to set up a basic block and tile entity. Ensure these methods are in your respective classes and tweak them from there.

 

Block:

//If you want your gui to have an inventory, have your block extend BlockContainer
//If not, have it extend Block and implement ITileEntityProvider

@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer playerEntity, int w, float px, float py, float pz)
{
                //the second parameter (0) is the gui ID and is used in the gui handler
                //for it to know which gui window to use - use a different ID for each gui window
	playerEntity.openGui(MainModClass.instance, 0, world, x, y, z);
	return false;
}

    public TileEntity createNewTileEntity(World world)
    {
    	return new TileEntityClass ();
    }

 

GuiHandler:

public class GuiHandler implements IGuiHandler
{
@Override
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
                //I don't use any containers in my GUIs (GuiContainer), but if I did, I'd return them here.
                //You can only get away with what I'm doing here if your GUIs extend GuiScreen and not GuiContainer
                //Servers get containers - Clients get GUIs
	return null;
}

@Override
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
	switch(ID)
	{
	case 0:
		return new BlockGuiWindow();
	//etc
	case 1:
		return new DialogGUI();
        //etc
	case 2:
                        return new QuestGUI();
                //etc
        case 3:
                        return new ShopGUI();
	}
	return null;
                //It is common Java convention to "break;" a switch case, but because all my cases end in returns, I don't need to
}
}

 

BlockGuiWindow:

@SideOnly(Side.CLIENT)
public class BlockGuiWindow extends GuiScreen //extend GuiContainer if you want your gui to have an inventory
{
final int xSizeOfTexture = 192
	   , ySizeOfTexture = 135
                   , white = Color.white.getRGB();
int posX
  , posY;

        //If you want your gui to change based on TileEntity values, reference the tile entity in the constructor
        //you must pass the tile entity using "return new BlockGuiWindow(world.getBlockTileEntity(x, y, z))" in the GuiHandler
        TileEntityClass te;

public BlockGuiWindow(TileEntityClass te)
{
	this.te = te;
}

        public void initGui()
{
	this.buttonList.clear();

	posX = (this.width - xSizeOfTexture) / 2;
	posY = (this.height - ySizeOfTexture) / 2;

	this.buttonList.add(new GuiButton(0, posX + 4, posY + 4, 20, 20, "ButtonText"));
                /*Parameters:
                 * button id used when checking what to do when a button is pressed
                 * The X position of the button
                 * The Y position of the button
                 * The width
                 * The height (keep this at 20 if you can)
                 * The text to be displayed on the button*/
        }

        public void actionPerformed(GuiButton button)
{
	switch(button.id)
	{
                     case 0:
                         //Do button stuff
                         break;
                }
        }

        @Override
public void drawScreen(int x, int y, float f)
{
	drawDefaultBackground();

	GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
	this.mc.renderEngine.bindTexture("path/to/the/background/texture");

	int posX = (this.width - xSizeOfTexture) / 2;
	int posY = (this.height - ySizeOfTexture) / 2;

	drawTexturedModalRect(posX, posY, 0, 0, xSizeOfTexture, ySizeOfTexture); //This draws the background
                //Make sure your background texture is a multiple of 256x256.
                //The xSizeOfTexture and ySizeOfTexture assume that the texture is 256x256. so 128 and 128 always reference half of the texture.
                //Look in the Gui class to see what else you can do here (like rendering textures and strings)
                this.drawString(fontRenderer, "Text", posX + 20, posY + 31, white); //this is where the white variable we set up at the beginning is used
                super.drawScreen(x, y, f);
                /*Here is a trick:
                   If you reset the texture after "super.drawScreen(x, y, f);" (this.mc.renderEngine.bindTexture("path/to/the/background/texture"),
                   you can draw on top of everything, including buttons.
                   Use this to texture buttons, if you don't want them to have text.*/
        }

 

MainModClass:

@Instance //The @Instance goes with the following line, nothing else
    public static MainModClass instance = new MainModClass();

GameRegistry.registerTileEntity(TileEntityClass.class, "TileEntityName");
NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler());

 

Those are the major snippets of the code I use for my stuff (with the names changed.) I have specific needs and you'll need to change the code a bit to do what you want it to, mainly adding a Container class and referencing it in the GuiHandler if you need a GuiContainer. You also may want to change my parenthetical syntax. I'm a C# programmer and the java parenthetical syntax bugs me :P

width=336 height=83http://img836.imageshack.us/img836/1237/cooltext624963071.png[/img]

I make games, minecraft mods/plugins, and some graphic art.

 

Current Project: LoECraft - An industrial minecraft server with its own modpack and custom launcher.

Link to comment
Share on other sites

When you click this is what initiates the gui, correct?

It's the onBlockActivated method in the Block class that opens the gui, so yes if I understood what you said correctly.

"MainModClass.instance"

 

What are you referencing with .instance?

I knew I was forgetting something!

I edited my post ;D

Look at the MainModClass definition again.

width=336 height=83http://img836.imageshack.us/img836/1237/cooltext624963071.png[/img]

I make games, minecraft mods/plugins, and some graphic art.

 

Current Project: LoECraft - An industrial minecraft server with its own modpack and custom launcher.

Link to comment
Share on other sites

When you click this is what initiates the gui, correct?

It's the onBlockActivated method in the Block class that opens the gui, so yes if I understood what you said correctly.

"MainModClass.instance"

 

What are you referencing with .instance?

I knew I was forgetting something!

I edited my post ;D

Look at the MainModClass definition again.

width=336 height=83http://img836.imageshack.us/img836/1237/cooltext624963071.png[/img]

I make games, minecraft mods/plugins, and some graphic art.

 

Current Project: LoECraft - An industrial minecraft server with its own modpack and custom launcher.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.