本帖最后由 当风过时 于 2013-1-15 15:31 编辑
被吐槽标题第一眼看成是“过时的教程”了……是“当风过时的教程”,不是“过时的教程”啊喂= =
上一个教程地址:http://www.mcbbs.net/thread-59702-1-1.html
经过上一个教程后,我们可以做出个拥有特定功能带GUI的方块了,不过显示出的GUI还存在着不能显示进度条问题,这次的教程就讲这个问题。
这次主要进行修改的文件是Container和Gui。
先是Gui文件rtGuiRepairTable:
在drawGuiContainerBackgroundLayer里增加一些东西复制代码描绘火焰图像那里,我姑且引用一下szszss大神的GUI教程的东西吧,当初我也是看那里知道怎么绘制这些进度条的
http://www.mcbbs.net/thread-23681-1-1.html
简单的说,在我们的GUI里就是根据取得的燃烧数据,从右侧的燃烧条按燃烧时间和最大燃烧时间的百分比截取出图像,将截得的火焰图像渲染到GUI的对应位置(空的火焰的那个地方)。其实GUI本身的绘制都是基于这个方式。
之后就可以进行调试了,这时你会发现,在还保留着燃烧时间的时候退出,然后再进入游戏时,显示燃烧时间的火苗不见了,意味着时间被清零了,但TileEntity中是已经写好保存燃烧时间了的,其实这个时候燃烧时间还是存在的,只是存在于服务端里,启动游戏时服务端还没有把燃烧时间发送给客户端,这时我们就需要对客户端和服务端进行同步。
接下来就是Container开大招的时刻了!
为rtContainerRepairTable添加如下代码
复制代码addCraftingToCrafters是添加监视器初始化的函数(这个地方我还不太敢确定,不过功能大概就是这样),返回的ICrafting的sendProgressBarUpdate就是将服务器上的数据发送给客户端第一个参数为Container本身,第二个是识别的ID,第三个是数据
updateProgressBar是客户端取得数据后进行同步的函数返回的第一个参数是ID,第二个是要同步的数据。
detectAndSendChanges是服务端发送数据的函数,当服务端上发现数据有变化时,就会将数据变化后的数据发送给客户端。
完成上述步骤后整个GUI就可以正常工作了
只是正常工作,还有一个比较重要的细节要说,那就是shift键对应的动作,大家应该都知道shift可以很方便的传送物品,把物品堆放到指定的槽位中,但在没有设定的情况下按下shift键很容易报错。
要定义shift键功能需要重写transferStackInSlot函数,我们这样改写:
复制代码mergeItemStack是传送物品栈的函数,它能将物品栈传送到指定的ID范围内,第一个参数物品栈,第二个是被传送到的起始ID,第三个是被传送到的结束ID,第四个是正序或逆序传送(就是优先从开头数还是从末尾数起)。这个的ID范围没设定好的话很容易造成复制物品的bug,我的mod就曾经被这个bug弄得很惨……在这个函数中,你可以定义相应物品的传送方式,比如熔炉,它能将可被冶炼的物品通过shift键放入冶炼槽中,将燃料放入燃料槽中,等等。
以上这些就是制作GUI的全部步骤和注意事项了。
于是乎整个GUI方块的教程就完事了。
附上整个工程的源码,稍微对TileEntity进行了一些规则bug的修改,以及升级到1.4.6了:
mod_RepairTable-src.zip
(5.68 KB, 下载次数: 66)
被吐槽标题第一眼看成是“过时的教程”了……是“当风过时的教程”,不是“过时的教程”啊喂= =
上一个教程地址:http://www.mcbbs.net/thread-59702-1-1.html
经过上一个教程后,我们可以做出个拥有特定功能带GUI的方块了,不过显示出的GUI还存在着不能显示进度条问题,这次的教程就讲这个问题。
这次主要进行修改的文件是Container和Gui。
先是Gui文件rtGuiRepairTable:
在drawGuiContainerBackgroundLayer里增加一些东西
- int var4 = this.mc.renderEngine.getTexture("/gui/RepairTable.png");
- GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
- this.mc.renderEngine.bindTexture(var4);
- int var5 = (this.width - this.xSize) / 2;
- int var6 = (this.height - this.ySize) / 2;
- this.drawTexturedModalRect(var5, var6, 0, 0, this.xSize, this.ySize);
- // 下面是新增的东西
- int b = tile.tableBurnTime; // 取得Tile内的燃料燃烧时间
- float maxBurnTime = tile.maxBurnTime*1.0F;// 取得最大燃料燃烧时间,用float,不用的话得不出百分比
- if (b > 0 && maxBurnTime > 0) // 确定描绘的时机
- {
- // 描绘火焰图像
- this.drawTexturedModalRect(this.guiLeft + 81, this.guiTop + 37 + (int)(14 - 14 * ((float)b / maxBurnTime)), 176, (int)(14 - 14 * ((float)b / maxBurnTime)), 14, (int)(14 * ((float)b / maxBurnTime)));
- }
http://www.mcbbs.net/thread-23681-1-1.html
drawTexturedModalRect(x,y,u,v,w,h) 截取渲染引擎中绑定的纹理,并渲染到屏幕上.这个是最常用的方法.
它的使用很特殊,你需要向渲染引擎绑定纹理,首先你需要使用渲染引擎的getTexture方法来载入一个纹理并获得它的ID,之后你要将ID作为参数来调用渲染引擎的bindTexture方法来将它绑定上.绑定完毕后你便可以使用drawTexturedModalRect来绘制纹理.这里有6个参数作用的图解.
x,y : 将要在用户屏幕上绘制的纹理的左上角坐标.
u,v : 被绑定纹理中,需要绘制部分的左上角坐标.
w,h : 纹理的宽和高.
绘制的流程可以这样理解:
渲染引擎会截取被绑定的纹理,将纹理中一个以(u,v)为左上角,(u+w,v+h)为右下角的矩形区域截下来,并将其绘制到用户屏幕上,其左上角位于点(x,y).
简单的说,在我们的GUI里就是根据取得的燃烧数据,从右侧的燃烧条按燃烧时间和最大燃烧时间的百分比截取出图像,将截得的火焰图像渲染到GUI的对应位置(空的火焰的那个地方)。其实GUI本身的绘制都是基于这个方式。
之后就可以进行调试了,这时你会发现,在还保留着燃烧时间的时候退出,然后再进入游戏时,显示燃烧时间的火苗不见了,意味着时间被清零了,但TileEntity中是已经写好保存燃烧时间了的,其实这个时候燃烧时间还是存在的,只是存在于服务端里,启动游戏时服务端还没有把燃烧时间发送给客户端,这时我们就需要对客户端和服务端进行同步。
接下来就是Container开大招的时刻了!
为rtContainerRepairTable添加如下代码
- @Override
- public void addCraftingToCrafters(ICrafting par1iCrafting) {
- // TODO Auto-generated method stub
- super.addCraftingToCrafters(par1iCrafting);
- par1iCrafting.sendProgressBarUpdate(this, 0, this.tile.tableBurnTime);
- par1iCrafting.sendProgressBarUpdate(this, 1, this.tile.maxBurnTime);
- }
- @SideOnly(Side.CLIENT)
- public void updateProgressBar(int par1, int par2)
- {
- if (par1 == 0)
- {
- this.tile.tableBurnTime = par2;
- }
- if (par1 == 1)
- {
- this.tile.maxBurnTime = par2;
- }
- }
- @Override
- public void detectAndSendChanges()
- {
- // TODO Auto-generated method stub
- super.detectAndSendChanges();
- Iterator var1 = this.crafters.iterator();
- while (var1.hasNext())
- {
- ICrafting var2 = (ICrafting)var1.next();
- if (this.lastTableBurnTime != this.tile.tableBurnTime)
- {
- var2.sendProgressBarUpdate(this, 0, this.tile.tableBurnTime);
- }
- if (this.lastMaxBurnTime != this.tile.maxBurnTime)
- {
- var2.sendProgressBarUpdate(this, 1, this.tile.maxBurnTime);
- }
- }
- this.lastTableBurnTime = this.tile.tableBurnTime;
- this.lastMaxBurnTime = this.tile.maxBurnTime;
- }
updateProgressBar是客户端取得数据后进行同步的函数返回的第一个参数是ID,第二个是要同步的数据。
detectAndSendChanges是服务端发送数据的函数,当服务端上发现数据有变化时,就会将数据变化后的数据发送给客户端。
完成上述步骤后整个GUI就可以正常工作了
只是正常工作,还有一个比较重要的细节要说,那就是shift键对应的动作,大家应该都知道shift可以很方便的传送物品,把物品堆放到指定的槽位中,但在没有设定的情况下按下shift键很容易报错。
要定义shift键功能需要重写transferStackInSlot函数,我们这样改写:
- @Override
- public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2)
- {
- ItemStack var3 = null;
- Slot var4 = (Slot)this.inventorySlots.get(par2);
- if (var4 != null && var4.getHasStack())
- {
- ItemStack var5 = var4.getStack();
- var3 = var5.copy();
- // 点击到Slot的ID为0-2之间的时候,将物品送回玩家的背包中,这个地方是
- if (par2 >= 0 && par2 <= 2)
- {
- if (!this.mergeItemStack(var5, 3, 30, false))
- {
- return null;
- }
- var4.onSlotChange(var5, var3);
- }
- // 点击到玩家的背包的时候将物品送到玩家的快捷栏中
- else if (par2 > 3 && par2 < 30)
- {
- if (!this.mergeItemStack(var5, 30, 39, false))
- {
- return null;
- }
- }
- // 点击到玩家的快捷栏的时候将物品送到背包中
- else if (par2 >= 30 && par2 < 39)
- {
- if (!this.mergeItemStack(var5, 3, 30, false))
- {
- return null;
- }
- }
- if (var5.stackSize == 0)
- {
- var4.putStack((ItemStack)null);
- }
- else
- {
- var4.onSlotChanged();
- }
- if (var5.stackSize == var3.stackSize)
- {
- return null;
- }
- var4.onPickupFromSlot(par1EntityPlayer, var5);
- }
- return var3;
- }
以上这些就是制作GUI的全部步骤和注意事项了。
于是乎整个GUI方块的教程就完事了。
附上整个工程的源码,稍微对TileEntity进行了一些规则bug的修改,以及升级到1.4.6了:

果断占领前排,当风大神大爱
太棒咯

太棒咯
这样的技术帖居然才1回复?没错我就是来挖坟的。。。正在做1.7.2版本的mod,楼主的帖子帮了我很多,感激不尽!
yudia 发表于 2014-7-19 06:26
这样的技术帖居然才1回复?没错我就是来挖坟的。。。正在做1.7.2版本的mod,楼主的帖子帮了我很多,感激不 ...
9494,技术贴啊