【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【06-给你唱一首岁月的歌】

老实说我已经忘了这个mod是怎么写出来的了。

所以下面的代码不能运行是非常正常的。

上回书说到,我们处理了玩家拿着背包右键时触发的事件,发送了一条打开背包窗口的命令,但是背包窗口还没有写,这回就来解决这个问题。

这次因为嵌套关系太多,所以我按执行顺序反过来说。

那么先不管上次没有打开的那个GUI。

MC中的每一个能放进物品的容器,不管是箱子、熔炉还是酿造台,各自都持有一个自己的内容空间(Inventory)实例,在这个内容空间中各自保存自己的内容物。

内容空间的基类是InventoryBasic,实现了IInventory接口,为了方便,咱直接继承InventoryBasic类。

InventoryBasic类已经实现了大部分内容空间需要的功能,可以粗读一下代码,挺好懂的。

于是我们黑猫背包的内容空间类只需要处理内容物的保存和读取。

 1 public class InventoryKuroNeko extends InventoryBasic {
 2     public static final String TITLE = "黑猫";
 3     public static final int SLOTS_PER_LINE = 9;
 4     public static final int LINES = 2;
 5
 6     private ItemStack itemStack;
 7
 8     private String id;
 9
10     public InventoryKuroNeko(ItemStack itemStack) {
11         super(TITLE, true, LINES * SLOTS_PER_LINE);
12
13         this.itemStack = itemStack;
14
15         if (!itemStack.hasTagCompound()) {
16             itemStack.setTagCompound(new NBTTagCompound());
17             id = UUID.randomUUID().toString();
18         }
19
20         readFromNBT(itemStack.getTagCompound());
21     }
22
23     public NBTTagCompound writeToNBT(NBTTagCompound compound) {
24         NBTTagList items = new NBTTagList();
25
26         for (int i = 0; i < getSizeInventory(); i++) {
27             ItemStack itemStack = getStackInSlot(i);
28             if (itemStack != null) {
29                 NBTTagCompound item = new NBTTagCompound();
30                 item.setInteger("slot", i);
31                 itemStack.writeToNBT(item);
32                 items.appendTag(item);
33             }
34         }
35
36         compound.setTag("items", items);
37
38         compound.setString("id", id);
39
40         return compound;
41     }
42
43     public void readFromNBT(NBTTagCompound compound) {
44         if (id == null) {
45             id = compound.getString("id");
46         }
47         if (id == null) {
48             id = UUID.randomUUID().toString();
49         }
50
51         NBTTagList items = compound.getTagList("items", 10);
52
53         for (int i = 0; i < items.tagCount(); i++) {
54             NBTTagCompound item = items.getCompoundTagAt(i);
55
56             int slot = item.getInteger("slot");
57             if (slot >= 0 && slot < getSizeInventory()) {
58                 ItemStack itemStack = ItemStack.loadItemStackFromNBT(item);
59                 setInventorySlotContents(slot, itemStack);
60             }
61         }
62     }
63
64     @Override
65     public void markDirty() {
66         super.markDirty();
67         writeToNBT(this.itemStack.stackTagCompound);
68     }
69 }

先扔代码

自己写两个方法,名字可以随便起,我这里一个叫writeToNBT,用于保存内容物,一个叫readFromNBT,用于读取内容物。

保存和读取用到的是NBT机制,NBT全称是什么我已经忘了。

先说保存。

首先创建一个NBT的列表NBTTagList,用于保存各个物品和它们的位置。这个类可以简单理解为一个列表。

然后遍历所有内容空间中的格子,只要发现格子中有物品,就把当前的格子位置保存在一个NBTTagCompound中,这个类理解为一个存储单元。

光保存位置不够,调用现成的API把这个物品的信息也加到存储单元中。

最后把这个存储单元添加到列表里。

这样遍历下来,所有物品的信息都保存起来了,最后把这个列表放到参数中传来的存储单元中。

怎么处理参数中的那个存储单元就不是你的事了。

最后是writeToNBT这个方法的调用,按照经验,应该会有一个回调方法,由系统在需要保存内容空间的内容的时候自动调用。

确实有。

找得我好苦啊。

重写父类的markDirty方法,先调用一遍父类的实现,然后加上

writeToNBT(this.itemStack.stackTagCompound);

这里的itemStack指的是使用了这个内容空间的物品,也就是黑猫背包。

在构造方法里接收并保存一下就好了。

这样系统就会自动把背包中的所有物品保存到这个背包实例中了。

但是光保存不行,还得读取。

于是来处理readFromNBT。

首先回到构造方法里。

第一次打开背包的时候肯定是不会有已经保存了的内容物的,this.itemStack.stackTagCompound这个东西也是不存在的,所以判断一下,初始化一个。

if (!itemStack.hasTagCompound()) {
    itemStack.setTagCompound(new NBTTagCompound());
    id = UUID.randomUUID().toString();
}

再给当前内容空间一个id用来识别不同的背包。

不作id的区分的话就变成末影背包了。

现在已经不会有空指针的问题了,于是不管三七二十一,读取一下吧。

我这上面用访问器下面直接访问变量效果是一样的,请不要在意。

首先从物品中保存的存储单元中拿到当前内容空间的id。

然后取出在刚才保存了所有物品的列表NBTTagList,这个方法的第二个参数我忘了是干嘛用的了,照抄吧。

接下来就是遍历了,拿出一个存储单元,找出格子的位置,然后用ItemStack类中的方法和存储单元中保存的信息创建一个物品栈并设置到指定的位置上。

就完美地恢复了之前保存的东西。

最后说一下三个常量。

TITLE是内容空间的名称,貌似会显示在界面上。

因为为了方便之后会直接拿箱子的界面来用,所以SLOTS_PER_LINE请不要乱动。

LINES就是行数了,我为了平衡给了个2,箱子貌似是4?给65535应该也是可行的。如果你显示器纵向分辨率有那么高的话……

写到这里背包的基本功能就已经完成了,后面就要开始蛋疼了。

如刚才所说,我打算直接复用箱子的界面,但是箱子相关的两个类都用了硬编码,所以没办法用继承的方式来创建背包的界面。

用英文说就是用了一个非常蛋疼的workaround。

下一篇再说。

时间: 2024-10-05 04:44:03

【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【06-给你唱一首岁月的歌】的相关文章

【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【04-铺垫三篇才进正题你说你有意思没意思】

Mod已经创建好了,现在该把内容添加进来了. 首先建一个类来统一管理Mod中所有的物品的实例和实例的初始化. 建包的事就不提了,看着建吧. public class ModItems { public static ItemKuroNekoBag kuroNekoBag; public static void init() { kuroNekoBag = new ItemKuroNekoBag(); } } 直接在主类中的preInit方法里用起来. @Mod.EventHandler publ

【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【01-引言】

刚学没多久,网上也没多少MOD开发的教程,只能自己一个接口一个接口地看过去. 所以叫开发研究. 重点是研究. 意思是要是写到一半发现写不下去了我就弃坑. 比我靠谱的人: http://www.hakugyokurou.net/wordpress/?page_id=126 http://www.261day.com/minecraft-forge%E6%95%99%E7%A8%8B/ http://www.orangetutorial.com/tutorial-list/#sthash.dIcQE

【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【05-一个周不更新根本说明不了什么我的字典里就没有太监这两个字不是字典大小的问题你不要说那些没用的】

然后该给背包添加功能了,背包的功能说起来很简单,无非就是右键打开一个和箱子长得差不多的窗口,然后把东西放进去保存起来. 然后还有一些附加事项,比如不能把自己放进自己里面,最好也不允许把同类放进自己里面,那样容量就以次方倍的速度增加,一个背包里就能放无限个道具了. 于是首先处理背包的右键事件. Item类自带一个方法,名字一看就懂,重写掉: @Override public ItemStack onItemRightClick(ItemStack itemStack, World world, E

【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【02-创建】

开发环境部署不提. 记得备好VPN. 一把辛酸泪. 工程目录下有两个文件夹,src/main/java和src/main/resources,前者用于放代码,后者用于放各种资源文件. 首先MOD需要一个主类,建包建好. 于我若是: mlxy.nekobags.NekoBags public class NekoBags { } 然后用注解的方式说明这个类就是我的MOD的主类. @Mod(modid="nekobags", name="Neko Bags", vers

【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【03-小刘老不干正事你们做家长的好好管管他不然这孩子就废了】

经过上一篇的配置,Mod已经显示在列表里了,但是下面还有两行小字,表示没Mod信息,打你Mod作者一顿让他把mcmod.info给填上. 于是来把Mod信息填上. src/main/resources文件夹在配置的时候应该已经自动生成了一个mcmod.info文件,没有的话自己建一个也无妨. 里面的内容是一个json列表,每一个列表项是一个Mod的信息,看不懂格式的话需要自己去补json知识. json大法好,退X保平安. 人在做,天在看,闭合标签留隐患. 解析失败天地灭,早换json保平安.

【Win 10应用开发】如何知道当前APP在哪个平台设备上运行

[Win 10应用开发]如何知道当前APP在哪个平台设备上运行 在做Win10开发的时候,我们可能经常会需要获得当前程序在在哪个平台设备上运行,用于UI和相关API的调用,那么可以通过什么方式知道当前APP运行的平台呢? 今天这里提供两个方法给大家做参考: 方法一:DeviceFamily 通过Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily,来获取当前的平台设备,目前只可以得到两个值Windows.Mobile或Wind

高德地图JavaScript API开发研究

原文:高德地图JavaScript API开发研究 高德地图JavaScript API是一套用JavaScript 语言编写的应用程序接口,可以通过各种API接口向地图添加内容,创建功能丰富.交互性强的地图应用.高德地图JavaScript API 提供了大量的实用工具和富有特色的插件功能,并提供了搜索和路线规划等服务. 1.首先 2.然后 3.最后就是看官方文档开发 高德地图API使用介绍:http://lbs.amap.com/api/javascript-api/guide-2/map_

GPS北斗双模技术应用开发研究—数据结构扩展

GPS北斗双模技术应用开发研究-数据结构扩展 还是从gps.h头文件入手,首先 GpsSvStatus结构体需要改造,GpsSvStatus当时设计的时候是考虑存储gps卫星信息的,但是我们现在是要存储双模的数据,因此我们需要扩展这个数据结构,那怎么扩展呢? 当然要代价小一点,不能完全推倒重来的,笔者想到的就是增加一个北斗卫星数量的变量,以及北斗的epemeris.almanac.还有一个定位的mask,以前数据结构里面的成员全部用着gps存储,这样就相互独立了,但是sv_list笔者就偷懒共用

物理小球开发研究委员会小组介绍

Section 1. 小组成员 张  慧(2016012019) ←组长 顾思宇(2016011993) 郑春雨(2016012011) 师浩然(2016012031) 郑  栋(2016012059) 范彦澜(2016012097) 小组名称 物理小球开发研究委员会 项目描述 寓教于乐,轻松学习,让孩子爱上学物理 队员档案 张慧 风格:时而精益求精,时而放弃治疗 技术:html.css.js.jq,美工 编程的兴趣:做网页 希望的软工角色:美工和前端 一句话宣言:I love study,st