利用Forge API开发联机MOD【基础篇】【第九章】
为你的刷怪笼添加一个可操作的GUI
作者:yuxuanchiadm
索引贴地址:http://www.mcbbs.net/thread-38211-1-1.html
请确定你已经阅读完成第八章的内容:
http://www.mcbbs.net/thread-114901-1-1.html
否则不要阅读此贴!
序:
在上一章里,我们完成了我们MOD的网络通信框架,现在,是时候阅读联机MOD篇的最后一章了:),当你阅读完这一章时,你将得到一个完整的利用ForgeAPI制作的MOD!
制作一个新的GUI:
/**知识点:什么是GUI
GUI指的是用户图形界面,在Minecraft里,所有的用户图形界面都继承自GUI类。在显示一个GUI时一般是通过调用Minecraft类里的displayGuiScreen()函数来显示一个继承自GuiScreen类的GUI,在通过调用这个函数打开GUI时会关闭其他通过这个函数打开的GUI。
**/
首先,制作一个刷怪笼设置面板GUI的背景:
在myFirstMod/sprites下新建文件:SpawnerSettingGui.png
然后乱涂成这样:)
然后,打开BlockAdvancedMobSpawner,看到当时我们留下的
- // 以后会在这里添加代码
在这里插入代码:
- myFristModPacket pak = new myFristModPacket();
- //我们要发送3个int数据,所以初始化数组大小为3
- pak.dataInt = new int[3];
- //数据包ID为0
- pak.packetType = 0;
- //方块X轴坐标
- pak.dataInt[0] = par2;
- //方块Y轴坐标
- pak.dataInt[1] = par3;
- //方块Z轴坐标
- pak.dataInt[2] = par4;
- //发送数据包
- PacketDispatcher.sendPacketToPlayer(pak.toPacket(), (Player)par5EntityPlayer);
服务端发送数据包后,客户端需要接收和处理数据包,打开mod_myFirstMod类,找到handlePacketFromServer方法,写入以下内容:
- if(packet.packetType == 0)
- {
- //等下会在这里添加代码
- }
其次,我们需要创建自己的一个GUI。首先新建包myFirstMod.GUI,然后再在其中新建类GuiMobSpawnerSetting。
然后,再让其继承自GuiScreen类:
- package myFirstMod.GUI;
- import net.minecraft.client.gui.GuiScreen;
- import cpw.mods.fml.relauncher.Side;
- import cpw.mods.fml.relauncher.SideOnly;
- @SideOnly(Side.CLIENT)
- public class GuiMobSpawnerSetting extends GuiScreen
- {
-
- }
- public int SpawnerX;
- public int SpawnerY;
- public int SpawnerZ;
- public GuiMobSpawnerSetting(int x, int y, int z)
- {
- SpawnerX = x;
- SpawnerY = y;
- SpawnerZ = z;
- }
- private ArrayList<Integer> mobList = new ArrayList<Integer>();
- public void initGui()
- {
- mobList.addAll(EntityList.entityEggs.keySet());
- }
- private GuiButton prev;
- private GuiButton next;
- private GuiButton Cut1;
- private GuiButton Cut10;
- private GuiButton Cut100;
- private GuiButton Add1;
- private GuiButton Add10;
- private GuiButton Add100;
- private GuiTextField MobNameTextBox;
- private GuiTextField SpawnDelayTextBox;
- prev = new GuiButton(1, (width - 175) / 2 + 20, (height - 165) / 2 + 60, 40, 20, "上一个");
- controlList.add(prev);
继续初始化其他的按钮:
- next = new GuiButton(2, (width - 175) / 2 + 20, (height - 165) / 2 + 80, 40, 20, "下一个");
- controlList.add(next);
- Cut100 = new GuiButton(3, (width - 175) / 2 + 10, (height - 165) / 2 + 137, 20, 20, "-100");
- controlList.add(Cut100);
- Cut10 = new GuiButton(4, (width - 175) / 2 + 29, (height - 165) / 2 + 137, 20, 20, "-10");
- controlList.add(Cut10);
- Cut1 = new GuiButton(5, (width - 175) / 2 + 48, (height - 165) / 2 + 137, 20, 20, "-1");
- controlList.add(Cut1);
- Add1 = new GuiButton(6, (width - 175) / 2 + 108, (height - 165) / 2 + 137, 20, 20, "+1");
- controlList.add(Add1);
- Add10 = new GuiButton(7, (width - 175) / 2 + 127, (height - 165) / 2 + 137, 20, 20, "+10");
- controlList.add(Add10);
- Add100 = new GuiButton(8, (width - 175) / 2 + 146, (height - 165) / 2 + 137, 20, 20, "+100");
- controlList.add(Add100);
- private int CurrentID;
- private int Delay;
- TileEntity tileEntity = Minecraft.getMinecraft().theWorld.getBlockTileEntity(SpawnerX, SpawnerY, SpawnerZ);
- if(tileEntity instanceof TileEntityAdvancedMobSpawner)
- {
- TileEntityAdvancedMobSpawner tileEntitySpawner = (TileEntityAdvancedMobSpawner)tileEntity;
- Field stringToIDMapping = null;
- Map strToIDMap = null;
- try
- {
- stringToIDMapping = EntityList.class.getDeclaredField("stringToIDMapping");
- stringToIDMapping.setAccessible(true);
- strToIDMap = (Map)stringToIDMapping.get(null);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- String mobName = tileEntitySpawner.getMobID();
- CurrentID = mobList.indexOf(strToIDMap.get(mobName));
- Delay = tileEntitySpawner.getSpawnDelay();
- }
然后根据按钮的mobList和CurrentID的状态来调整按钮的状态:
- if((mobList.size() - 1) == 0)
- {
- prev.enabled = false;
- next.enabled = false;
- }
- else
- {
- if(CurrentID > 0 && CurrentID < (mobList.size() - 1))
- {
- prev.enabled = true;
- next.enabled = true;
- }
- if(CurrentID >= (mobList.size() - 1))
- {
- prev.enabled = true;
- next.enabled = false;
- }
- if(CurrentID <= 0)
- {
- prev.enabled = false;
- next.enabled = true;
- }
- }
- MobNameTextBox = new GuiTextField(fontRenderer, (width - 175) / 2 + 10, (height - 165) / 2 + 30, 150, 20);
- MobNameTextBox.setText(StatCollector.translateToLocal("entity." + EntityList.getStringFromID(mobList.get(CurrentID)) + ".name"));
- SpawnDelayTextBox = new GuiTextField(fontRenderer, (width - 175) / 2 + 10, (height - 165) / 2 + 115, 150, 20);
- SpawnDelayTextBox.setText(Integer.toString(Delay));
然后,我们需要对我们的GUI进行绘制,重写方法drawScreen:
- public void drawScreen(int par1, int par2, float par3)
- {
- }
- drawDefaultBackground();
- int k = mc.renderEngine.getTexture("/myFirstMod/sprites/SpawnerSettingGui.png");
- GL11.glColor3f(1.0F, 1.0F, 1.0F);
- mc.renderEngine.bindTexture(k);
- int l = (width - 175) / 2;
- int i1 = (height - 165) / 2;drawTexturedModalRect(l, i1, 0, 0, 175, 165);
- MobNameTextBox.drawTextBox();
- SpawnDelayTextBox.drawTextBox();
- super.drawScreen(par1,par2,par3);
- fontRenderer.drawString("刷怪笼设置面板", (width - 175) / 2 + 6, (height - 165) / 2 + 6, 0x404040);
- fontRenderer.drawString("生成的怪物:", (width - 175) / 2 + 10, (height - 165) / 2 + 18, 0x404040);
- fontRenderer.drawString("生成间隔:", (width - 175) / 2 + 10, (height - 165) / 2 + 104, 0x404040);
- protected void actionPerformed(GuiButton par1GuiButton)
- {
- if(par1GuiButton.id == 1)
- {
- CurrentID --;
- if(CurrentID <= 0)
- {
- prev.enabled = false;
- }
- if(CurrentID < (mobList.size() - 1))
- {
- next.enabled = true;
- }
- MobNameTextBox.setText(StatCollector.translateToLocal("entity." + EntityList.getStringFromID(mobList.get(CurrentID)) + ".name"));
- }
- if(par1GuiButton.id == 2)
- {
- CurrentID ++;
- if(CurrentID >= (mobList.size() - 1))
- {
- next.enabled = false;
- }
- if(CurrentID > 0)
- {
- prev.enabled = true;
- }
- MobNameTextBox.setText(StatCollector.translateToLocal("entity." + EntityList.getStringFromID(mobList.get(CurrentID)) + ".name"));
- }
- if(par1GuiButton.id == 3)
- {
- ChangeDelay(-100);
- }
- if(par1GuiButton.id == 4)
- {
- ChangeDelay(-10);
- }
- if(par1GuiButton.id == 5)
- {
- ChangeDelay(-1);
- }
- if(par1GuiButton.id == 6)
- {
- ChangeDelay(+1);
- }
- if(par1GuiButton.id == 7)
- {
- ChangeDelay(+10);
- }
- if(par1GuiButton.id == 8)
- {
- ChangeDelay(+100);
- }
- }
- public void ChangeDelay(int i)
- {
- Delay += i;
- if(Delay > 50000)
- {
- Delay = 50000;
- }
- if(Delay < 50)
- {
- Delay = 50;
- }
- SpawnDelayTextBox.setText(Integer.toString(Delay));
- }
- public void onGuiClosed()
- {
- TileEntity tileEntity = Minecraft.getMinecraft().theWorld.getBlockTileEntity(SpawnerX, SpawnerY, SpawnerZ);
- if(tileEntity instanceof TileEntityAdvancedMobSpawner)
- {
- TileEntityAdvancedMobSpawner tileEntitySpawner = (TileEntityAdvancedMobSpawner)tileEntity;
- tileEntitySpawner.setMobID(EntityList.getStringFromID(mobList.get(CurrentID)));
- tileEntitySpawner.setSpawnDelay(Delay);
- }
- myFristModPacket pak = new myFristModPacket();
- //我们要发送4个int数据,所以初始化数组大小为4
- pak.dataInt = new int[4];
- //我们要发送1个String数据,所以初始化数组大小为1
- pak.dataString = new String[1];
- //数据包ID为1
- pak.packetType = 1;
- //方块X轴坐标
- pak.dataInt[0] = SpawnerX;
- //方块Y轴坐标
- pak.dataInt[1] = SpawnerY;
- //方块Z轴坐标
- pak.dataInt[2] = SpawnerZ;
- //刷怪间隔
- pak.dataInt[3] = Delay;
- //怪物名称
- pak.dataString[0] = EntityList.getStringFromID(mobList.get(CurrentID));
- //发送数据包
- PacketDispatcher.sendPacketToServer(pak.toPacket());
- }
- public boolean doesGuiPauseGame()
- {
- return false;
- }
- if(packet.packetType == 0)
- {
- //等下会在这里添加代码
- }
- Minecraft.getMinecraft().displayGuiScreen(new GuiMobSpawnerSetting(packet.dataInt[0], packet.dataInt[1], packet.dataInt[2]));
- if(packet.packetType == 1)
- {
- TileEntity tileEntity = player.worldObj.getBlockTileEntity(packet.dataInt[0], packet.dataInt[1], packet.dataInt[2]);
- if(tileEntity instanceof TileEntityAdvancedMobSpawner)
- { TileEntityAdvancedMobSpawner tileEntitySpawner = (TileEntityAdvancedMobSpawner)tileEntity;
- if(tileEntitySpawner != null)
- {
- tileEntitySpawner.setSpawnDelay(packet.dataInt[3]);
- tileEntitySpawner.setMobID(packet.dataString[0]);
- }
- }
- }
总结:
首先祝贺你已经完成了大部分联机MOD的制作学习,并且做出了一个属于你自己动手创作的MOD:),你已经可以毫不犹豫的说:“我是一个Forge MOD的制作者!”。但是,此MOD仍然没有完成,只能在MCP下运行,在玩家手里就运行不能了。原因就是我们使用了反射,所以产生了反混淆问题,下一章我们将详细讨论如何解决这个问题。