提供: Minecraft Modding Wiki
移動先: 案内検索

この記事は"Minecraft Forge4.3x"を前提MODとしています。

GUIの追加

 チェストや作業台を右クリックしたとき, ブロックに応じて適切なGUIが表示される. このGUIは実はクライアント側でGUIの描画とコンテナの生成, サーバー側ではコンテナの生成のみ行っている. 今回は単純な(何も機能を持たない)GUIを追加し, 追加ブロックを右クリックしてGUIを展開できるようにする.

ソースコード

  • GuiSampleCore
package mods.guisample;

import net.minecraft.src.*;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.network.NetworkMod;

import cpw.mods.fml.common.event.FMLInitializationEvent;

import cpw.mods.fml.common.network.NetworkRegistry;

import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;

@Mod
(
	modid   = "GuiSampleCore",
	name    = "Gui Sample Core",
	version = "1.0.0"
)	
@NetworkMod
(
	clientSideRequired = true,
	serverSideRequired = false
)
public class GuiSampleCore
{
	@Mod.Instance("GuiSampleCore")
	public static GuiSampleCore instance;
	
	public static Block blockNoop;
	
	public static final int guiID = 1;
	
	@Mod.Init
	public void init(FMLInitializationEvent event)
	{
		blockNoop = (new BlockGuiNoop(3500)).setBlockName("guisampleblock").setCreativeTab(CreativeTabs.tabBlock);
		
		GameRegistry.registerBlock(blockNoop);
		LanguageRegistry.addName(blockNoop, "GUI Sample Block");
		
		NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler());
	}
}
  • BlockGuiNoop
package mods.guisample;

import net.minecraft.src.*;

public class BlockGuiNoop extends Block
{
	public BlockGuiNoop(int blockId)
	{
		super(blockId, 0, Material.wood);
	}
	
    public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int side, float par7, float par8, float par9)
	{
		if (!world.isRemote)
		{
			entityPlayer.openGui(GuiSampleCore.instance, GuiSampleCore.guiID, world, x, y, z);
		}
		return true;
	}
}
  • GuiHandler
package mods.guisample;

import net.minecraft.src.*;

import cpw.mods.fml.common.network.IGuiHandler;

import mods.guisample.client.GuiSampleNoop;

public class GuiHandler implements IGuiHandler
{
	@Override
	public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
	{
		if (ID == GuiSampleCore.guiID)
		{
			return new GuiSampleNoop(player, world, x, y, z);
		}

		return null;
	}

	@Override
	public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
	{
		if (ID == GuiSampleCore.guiID)
		{
			return new ContainerSampleNoop(player, world, x, y, z);
		}

		return null;
	}

}
  • ContainerSampleNoop
package mods.guisample;

import net.minecraft.src.*;

public class ContainerSampleNoop extends Container
{
	private World world;
	private int xCoord;
	private int yCoord;
	private int zCoord;
	
	public ContainerSampleNoop(EntityPlayer player, World world, int x, int y, int z)
	{
		this.world  = world;
		this.xCoord = x;
		this.yCoord = y;
		this.zCoord = z;
	}
	
	@Override
	public boolean canInteractWith(EntityPlayer entityPlayer)
	{
		return this.world.getBlockId(this.xCoord, this.yCoord, this.zCoord) != GuiSampleCore.blockNoop.blockID ? false 
			: entityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
	}
}
  • GuiSampleNoop
package mods.guisample.client;

import org.lwjgl.opengl.GL11;

import net.minecraft.src.*;

import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;

import mods.guisample.ContainerSampleNoop;

@SideOnly(Side.CLIENT)
public class GuiSampleNoop extends GuiContainer
{
	public GuiSampleNoop(EntityPlayer player, World world, int x, int y, int z)
	{
		super(new ContainerSampleNoop(player, world, x, y, z));
	}
	
	@Override
	protected void drawGuiContainerForegroundLayer()
	{
		fontRenderer.drawString("Gui Sample", 58, 6, 0x404040);
		fontRenderer.drawString("Inventory", 8, (ySize - 96) + 2, 0x404040);
	}

	@Override
	protected void drawGuiContainerBackgroundLayer(float f, int i, int j)
	{
		int texture = mc.renderEngine.getTexture("/gui/trap.png");
		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
		mc.renderEngine.bindTexture(texture);
		int xStart = width - xSize >> 1;
		int yStart = height - ySize >> 1;
		drawTexturedModalRect(xStart, yStart, 0, 0, xSize, ySize);
	}
}

解説

GuiSampleCore

public static final int guiID = 1;

GUI固有のID. ただし, このIDはこのMOD内で重複してない値でよいため, 他のMODとの競合などは考慮しなくてよく, ほとんど自由な値を使える.

NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler());

IGuiHandlerを実装したクラスをNetworkRegistryに登録するメソッド.

BlockGuiNoop

public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int side, float par7, float par8, float par9)
{
	if (!world.isRemote)
	{
		entityPlayer.openGui(GuiSampleCore.instance, GuiSampleCore.guiID, world, x, y, z);
	}
	return true;
}

ブロックを右クリックしたときに呼ばれるメソッド. ここでGUIを開く処理を行う.

GuiHandler

public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
	if (ID == GuiSampleCore.guiID)
	{
		return new GuiSampleNoop(player, world, x, y, z);
	}

	return null;
}

IGuiHandlerのうち, クライアント側のGUIの実装. IDごとにGUIのクラスを生成し, 返す.

public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
	if (ID == GuiSampleCore.guiID)
	{
		return new ContainerSampleNoop(player, world, x, y, z);
	}

	return null;
}

IGuiHandlerのうち, サーバー側のGUIの実装. こちらはコンテナを返す.

ContainerSampleNoop

public boolean canInteractWith(EntityPlayer entityPlayer)
{
	return this.world.getBlockId(this.xCoord, this.yCoord, this.zCoord) != GuiSampleCore.blockNoop.blockID ? false 
		: entityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
}

このコンテナが呼び出される適切なブロックと距離かどうか判定するメソッド.

GuiSampleNoop

protected void drawGuiContainerBackgroundLayer(float f, int i, int j)
{
	int texture = mc.renderEngine.getTexture("/gui/trap.png");
	GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
	mc.renderEngine.bindTexture(texture);
	int xStart = width - xSize >> 1;
	int yStart = height - ySize >> 1;
	drawTexturedModalRect(xStart, yStart, 0, 0, xSize, ySize);
}

GUIの背景を描画するメソッド. mc.renderEngine.getTexture()の引数で指定した画像を描画している. 今回はディスペンサーの画像をそのまま利用.

実際の挙動

 今回はレシピを追加していないのでクリエイティブモードでブロックを設置する. ブロックを右クリックするとディスペンサーと同じ画像が表示される. しかしディスペンサーなどと異なり, アイテムスロットの箇所はマウスカーソルを合わせても色は変わらないし, アイテムも置けない. 単純にGUIを追加しただけなので, 実際にアイテムを置けるようにするにはコンテナ側でスロットを生成する必要がある.