当风过时
本帖最后由 当风过时 于 2016-2-16 22:08 编辑

看这篇教程需要一定的mod制作基础,没有什么基础的话请先去看看基础教程,把基础打好再说
http://www.mcbbs.net/thread-54579-1-1.html

1.8.9的教程:http://www.windworkshop.cn/?p=889
1.7.10的教程http://www.windworkshop.cn/?p=36
第二篇,自定义TileEntity的行为:http://www.mcbbs.net/thread-76005-1-1.html
第三篇,同步客户端与服务端的数据:http://www.mcbbs.net/thread-78145-1-1.html

说起GUI,是我心中难以磨灭的阴影。。。当初在学的时候各种坑,刚爬出来就到另外一个坑,方块GUI可以说是minecraft里面很麻烦的东西,源代码里没用可供参考的东西(那些源码中的各种displayGUI纯粹是坑爹- -),全部都得靠modloader或者forge提供的调用函数才能打开。。。如果事先没有仔细研究教程,中间漏了哪步都不行。不废话了,直接开始吧。
首先创建mod文件,这个教程就以制作一个修复台为目标吧。
mod文件就叫做mod_RepairTable.java吧。现在先解释一下要显示右键方块的gui需要什么东西,需要BlockContainerGuiTileEntity,他们的职责分别是:提供方块的基本操作,GUI的内容管理,GUI的绘制,方块的数据管理。
先来做BlockBlock需要继承BlockContainerBlockContainer需要返回对应的TileEntityBlock命名为rtBlockRepairTable(谨遵szszss触的教诲,开头写上mod的缩写可以大大的减少寻找文件的时间)经过eclipse的修正后如下:
  1. package net.minecraft.src;

  2. public class rtBlockRepairTable extends BlockContainer{

  3.        protected rtBlockRepairTable(int par1, int par2, Material par3Material) {
  4.               super(par1, par2, par3Material);
  5.               // TODO Auto-generated constructor stub
  6.        }

  7.        @Override
  8.        public TileEntity createNewTileEntity(World var1) {
  9.               // TODO Auto-generated method stub
  10.               return null;
  11.        }

  12. }
复制代码

目前这只是一个没有任何功能的方块。先来做TileEntity,新建一个类,名称为rtTileEntityRepairTable,继承TileEntity重写updateEntity()updateEntity是更新TileEntity的函数,想让TileEntity工作全部都得依赖于它。在updateEntity中写上个输出语句吧。
  1. package net.minecraft.src;

  2. public class rtTileEntityRepairTable extends TileEntity{

  3.        @Override
  4.        public void updateEntity() {
  5.               // TODO Auto-generated method stub
  6.               super.updateEntity();
  7.               System.out.println("Hello GUI");
  8.        }

  9. }
复制代码

然后给Block里的createNewTileEntity方法返回一个TileEntity,返回刚在写好的rtTileEntityRepairTable
  1.        @Override
  2.        public TileEntity createNewTileEntity(World var1) {
  3.               // TODO Auto-generated method stub
  4.               return new rtTileEntityRepairTable();
  5.        }
复制代码

这个步骤完成后还需要在mod文件中注册各种东西(因为这个是直接更换过来的,过程没有重新做,这个地方如果出现bug的话就以最终的那个为准)要引用IGuiHandler,这个接口是打开GUI的制定接口,根据接口所需的函数就能打开GUI

  1. package net.minecraft.src;

  2. import cpw.mods.fml.common.Mod;
  3. import cpw.mods.fml.common.event.FMLInitializationEvent;
  4. import cpw.mods.fml.common.network.IGuiHandler;
  5. import cpw.mods.fml.common.network.NetworkMod;
  6. import cpw.mods.fml.common.network.NetworkRegistry;
  7. import cpw.mods.fml.common.registry.GameRegistry;
  8. import cpw.mods.fml.common.registry.LanguageRegistry;

  9. @Mod(modid = "RepairTable", name = "Repair Table", version="1.0.0")
  10. @NetworkMod(channels = { "RepairTable" }, versionBounds = "1.4.5", clientSideRequired = true, serverSideRequired = false)
  11. public class mod_RepairTable implements IGuiHandler{
  12.        public Block repairTable;
  13.        @Mod.Instance("RepairTable")
  14.        public static mod_RepairTable instance;

  15.        @Mod.Init
  16.        public void load(FMLInitializationEvent evt) {
  17.               // TODO Auto-generated method stub
  18.               repairTable = new rtBlockRepairTable(187, Block.brick.blockIndexInTexture, Material.rock)
  19.               .setBlockName("RepairTable").setCreativeTab(CreativeTabs.tabBlock);
  20.               GameRegistry.registerBlock(repairTable);
  21.               LanguageRegistry.addName(repairTable, "RepairTable");
  22.               GameRegistry.registerTileEntity(rtTileEntityRepairTable.class, "TileEntityRepairTable");
  23.               instance = this;
  24.        }

  25.         @Override
  26.         public Object getClientGuiElement(int ID, EntityPlayer player, World world,
  27.                         int x, int y, int z) {
  28.                 // TODO Auto-generated method stub
  29.         return null;
  30.         }

  31.         @Override
  32.         public Object getServerGuiElement(int ID, EntityPlayer player, World world,
  33.                         int x, int y, int z) {
  34.                 // TODO Auto-generated method stub
  35.         return null;
  36.         }
  37.       
  38. }
复制代码

我暂时先用砖块的贴图来代替吧- -

放置方块后你会看见调试窗里出现了刚才写的输出语句。

updateEntity会在每个tick里调用一次,每调用一次就相当于刷新一次数据,至于刷新什么数据,这些都是由你自己定的了,一般就是燃烧时间之类的。基本的功能方块就构成了。不过这个方块还没有窗口,只具备了基本的刷新数据的功能,接下来就该做GUI了。
新建一个类,名字为rtGuiRepairTable,继承GuiContainereclipse修正一下。
  1. package net.minecraft.src;

  2. public class rtGuiRepairTable extends GuiContainer{

  3.        public rtGuiRepairTable(Container par1Container) {
  4.               super(par1Container);
  5.               // TODO Auto-generated constructor stub
  6.        }

  7.        @Override
  8.        protected void drawGuiContainerBackgroundLayer(float var1, int var2,
  9.                      int var3) {
  10.               // TODO Auto-generated method stub
  11.             
  12.        }

  13. }
复制代码
这是一个没有任何东西的基本的GUI然后再新建一个类,名字为rtContainerRepairTable,继承Container
  1. package net.minecraft.src;

  2. public class rtContainerRepairTable extends Container{

  3.        @Override
  4.        public boolean canInteractWith(EntityPlayer var1) {
  5.               // TODO Auto-generated method stub
  6.               return true;
  7.        }

  8. }
复制代码
canInteractWith返回的是是否打开GUI,设定为true
gui中覆写drawGuiContainerForegroundLayer(描绘前景文字),以及在drawGuiContainerBackgroundLayer中描绘背景,最后修改一下构造函数:
  1. package net.minecraft.src;

  2. import org.lwjgl.opengl.GL11;

  3. public class rtGuiRepairTable extends GuiContainer{

  4.        private rtTileEntityRepairTable tile;
  5.        public rtGuiRepairTable(rtContainerRepairTable par1Container, rtTileEntityRepairTable tileEntity) {
  6.               super(par1Container);
  7.               // TODO Auto-generated constructor stub
  8.               this.tile = tileEntity;
  9.               this.doesGuiPauseGame();
  10.        }

  11.              @Override
复制代码

附上描绘用的GUI窗口

doesGuiPauseGame是是否在打开gui的时候停止游戏。构造函数那里需要返回一个Container。为啥要返回我也不清楚- -我觉得在某些方面有些多余。

接下来就是接口部分了(这个地方很多得重新做啊。。。)

mod文件中注册IGuiHandler,注册后就能在回调函数getClientGuiElement和getServerGuiElement分别获得Gui和Container,至于这两个函数怎么用,待会解释。
  1. NetworkRegistry.instance().registerGuiHandler(this, this);
复制代码
重写mod中的getClientGuiElement

  1. @Override
  2.         public Object getClientGuiElement(int ID, EntityPlayer player, World world,
  3.                         int x, int y, int z) {
  4.                 // TODO Auto-generated method stub
  5.                 switch(ID)
  6.         {
  7.         case 10:
  8.                return new rtGuiRepairTable(player.inventory, (rtTileEntityRepairTable)player.worldObj.getBlockTileEntity(x, y, z));
  9.         }
  10.         return null;
  11.         }
复制代码
重写mod中的getServerGuiElement

  1. @Override
  2.         public Object getServerGuiElement(int ID, EntityPlayer player, World world,
  3.                         int x, int y, int z) {
  4.                 // TODO Auto-generated method stub
  5.                 switch(ID)
  6.         {
  7.         case 10:
  8.                return new rtContainerRepairTable(player.inventory, (rtTileEntityRepairTable)player.worldObj.getBlockTileEntity(x, y, z));
  9.         }
  10.         return null;
  11.         }
复制代码
接着是重写blockonBlockActivated
  1. @Override
  2.        public boolean onBlockActivated(World par1World, int par2, int par3,
  3.                      int par4, EntityPlayer par5EntityPlayer, int par6, float par7,
  4.                      float par8, float par9) {
  5.               // TODO Auto-generated method stub
  6.               par5EntityPlayer.openGui(mod_RepairTable.instance, 10, par1World, par2, par3, par4);
  7.         return true;
  8.        }
复制代码
现在就可以来解释一下GUI的打开流程了:右键激活方块,方块调用EntityPlayer.openGui来打开回调相应端的GUI组件,第一个参数是相应mod的实例,第二个参数是gui的ID,第三个是World实例,第四个到第六个是三个数字,怎么填随你喜欢,一般是给出方块的坐标,方便通过world来查找到对应的TileEntity,由于在1.4中,服务端和客户端是整合在一块的,所以需要两个函数来管理,就是之前在mod文件中的getClientGuiElement和getServerGuiElement,通过这两个函数共同协助才能构建一个GUI,只有经过这条路径来打开的GUI才是能使用的GUI,用Modloader.openGUI来打开的GUI无法更新,只能作为提示窗口来用(基本也没什么提示作用- -)。 完成上述步骤后,你应该就能看到久违的窗口了。



完成这个步骤后得到的代码:
mod_RepairTable.java

rtBlockRepairTable.java

rtGuiRepairTable.java

rtContainerRepairTable.java

rtTileEntityRepairTable.java


貌似有些地方跳过了- -跟着工程的代码凑合一下吧(我觉得我真心不适合教书- -)。。。第一篇就先做到这里,后面还有很多东西要说。。。
预定的内容:自定义TileEntity的行为
进度条的描绘
数据的同步
一些注意事项
或者还有些什么突然想起的东西- -




















响响丶
不会MOD的路过围观

Vidocq
速度拿下SF

洛音
强大啊1.4已出

hendyzone
前排支持{:10_512:}  GUI和Entity 都是蛋疼的东西。。。

1440519152
好屌,我要看看

第一页 上一页 下一页 最后一页