Minecraft mod制作简易教程(三)——创建一个物品

  • 一、模块化管理你的程序
  • 二、简易物品
    • 设置物品参数
    • 注册这个物品
    • 访问这个物品
    • 给物品添加材质
  • 三、更复杂的物品
    • 创建一个物品类
    • 实现鼠标右键事件

一、模块化管理你的程序

一个mod可能包含数百个物品,还有block、Recipe、WorldGenerator等很多东西,如果不进行模块化管理,到后期将会难以进行调试和bug处理。
所以从一开始就要好好管理你的代码
我们现在com.hexatomic_ring.realmining下新建一个包item
这里的模块化管理当然不是简单地把所有关于Item的代码都扔到这个包里。如果翻一下Minecraft源代码,就会发现对item的调用都是以这样的格式:

Items.AIR

但是mc所有的物品都是在Item.java里实例化的,这里的Items类相当于一个封装
所以我们也照样在item下建两个类ModItems和ItemLoader

二、简易物品

在较新版的mc中不是每一个物品都有一个专门的类来实例化,例如在1.12.2中一共只有80个与item相关的类。这是如何做到的呢?
我们来看一种最基础的item,它的属性只有名称、创造模式物品栏、耐久、挖掘等级、最大堆叠数量等,你就不需要用一个特殊的类来构建这些性质。这一点在官方教程中写得很清楚:https://mcforge.readthedocs.io/en/latest/items/items/
其实现方法是用setUnlocalizedName()之类的方法,其返回值为this,即可以把各种设置写成一条链,只占用一行的空间,于是没有必要单独创建一个类。
关于item的具体结构可以自由发挥,这里仅代表个人见解。
现在我要做一个物品叫做rubble
我们在ItemLoader.java中类的声明前一行加一个注解:

@Mod.EventBusSubscriber(modid = “realmining”)

设置物品参数

这样Forge就能注意到这个类会注册一些东西。
我们先建一个类型为Item的数组

private static Item[] items = {
new Item().setUnlocalizedName(“rubble”).setRegistryName(“rubble”).setCreativeTab(CreativeTabs.MATERIALS)
};

这里的setUnlocalizedName是设置非本地化名称,建议使用小写驼峰写法,由于rubble只有一个单词,换个例子:realMining
setRegistryName是设置注册名,建议使用下划线写法,如real_mining
setCreativeTab是设置创在模式物品栏,这样我的物品就能在“杂项”一栏中找到。你可以翻看net.minecraft.creativetab.CreativeTabs并选择合适的物品栏
你应该注意到了这个数组被声明为private,那我们就需要一个拆封的方法,比如按照非本地化名称找到对应的item。
如果翻看Item.java就会找到这样一条方法:

public String getUnlocalizedName()
{
return “item.” + this.unlocalizedName;
}

我们就利用这条方法查找:

public static Item getByName(String name){
for(Item item:items)
if(item.getUnlocalizedName().equals(name))
return item;
return Items.AIR;
}

注册这个物品

下面注册这个item:

@SubscribeEvent
public static void registerItems(RegistryEvent.Register< Item> event) {
for(Item item : items){
event.getRegistry().register(item);
}
}
}

虽然forge提供了registerAll方法,但由于我是用一个数组来管理所有物品的,所以仍然多次使用register。

访问这个物品

在ModItems.java中写入:

public static final Item RUBBLE;
static{
RUBBLE = ItemLoader.getByName(“item.rubble”);
}

这里注意一下final表示这个变量的值一经定义不能再修改,也就是常量,一般用全大写加下划线表示,如REAL_MINING。
这样就可以用ModItems.RUBBLE来调取这个物品啦

给物品添加材质

一个物品再简单,也不能没有材质
我们把前面注册物品的部分改成这样:

public static void registerItems(RegistryEvent.Register< Item> event) {
for(Item item : items){
ModelLoader.setCustomModelResourceLocation(item,0,new ModelResourceLocation(item.getRegistryName(), “inventory”));
event.getRegistry().register(item);
}
}

也就是加了一行,这一行制定了这个物品材质模型文件的路径,即src/resources/assets//models/item/.json,我们需要New一些包和这个文件。注意文件名是用register name注册的,所以也要按小写字母下划线的格式。我们把这下写进.json,我这里是rubble.json:

{
“parent”: “builtin/generated”,
“textures”: {
“layer0”: “realmining:items/rubble”
},
“display”: {
“thirdperson”: {
“rotation”: [ -90, 0, 0 ],
“translation”: [ 0, 1, -2 ],
“scale”: [ 0.55, 0.55, 0.55 ]
},
“firstperson”: {
“rotation”: [ 0, -135, 25 ],
“translation”: [ 0, 4, 2 ],
“scale”: [ 1.7, 1.7, 1.7 ]
}
}
}

realmining:items/rubble定义了它的材质文件的位置,我们需要把一个材质文件放到src\main\resources\assets\realmining\textures\rubble.png。它的分辨率要求是nn,n必须是二的指数,一般用1616。
后面的一堆代码定义了这个物品拿在手里时的状态。
现在可以打开游戏,在指令中输入/give @p reaalmining:rubble试试看了

三、更复杂的物品

上面的方法只适合制作最简单的物品
现在,我需要做几个共享一些共性的物品
我还需要让它们有一些特殊的功能
解决方法就是——创建一个物品类

创建一个物品类

我现在要做三种不同形状的石块,它们右击硬度大于等于石头的方块时会都碎成两块小石块
在item包下New一个ItemRock类,并把类的声明改成这样:

public class ItemRock extends Item {
}

也就是它继承了Item,我们创建实例的时候也符合Item类型
随后修改ItemLoader:

private static Item[] items = {
new Item().setUnlocalizedName(“rubble”).setRegistryName(“rubble”).setCreativeTab(CreativeTabs.MATERIALS),
new ItemRock().setUnlocalizedName(“rockStrip”).setRegistryName(“rock_strip”).setCreativeTab(CreativeTabs.MATERIALS),
new ItemRock().setUnlocalizedName(“rockPlate”).setRegistryName(“rock_plate”).setCreativeTab(CreativeTabs.MATERIALS),
new ItemRock().setUnlocalizedName(“rockDiscoid”).setRegistryName(“rock_discoid”).setCreativeTab(CreativeTabs.MATERIALS),
new Item().setUnlocalizedName(“rocklet”).setRegistryName(“rocklet”).setCreativeTab(CreativeTabs.MATERIALS)
};

修改ModItems:

public static final Item RUBBLE;
public static final Item ROCK_STRIP;
public static final Item ROCK_PLATE;
public static final Item ROCK_DISCOID;
public static final Item ROCKLET;
static{
RUBBLE = ItemLoader.getByName(“item.rubble”);
ROCK_STRIP = ItemLoader.getByName(“item.rockStrip”);
ROCK_PLATE = ItemLoader.getByName(“item.rockPlate”);
ROCK_DISCOID = ItemLoader.getByName(“item.rockDiscoid”);
ROCKLET = ItemLoader.getByName(“item.rocklet”);
}

当然还要给新物品添加对应的材质,这里就不加赘述了。

实现鼠标右键事件

像这种简单的事件并不需要Event类,如果翻看过ItemBucket或者ItemBoat的话就会发现一个叫onItemRightClick的方法,输入值为World worldIn, EntityPlayer playerIn, EnumHand handIn,返回值为ActionResult
虽然一眼还不是很清楚ActionResult是什么,但我们可以游戏效果来倒推一下,也可以通过Ctrl+Click追踪源代码。
更重要的是我们要直到如何清除手里的物品,获取对准的方块的信息以及在该位置生成掉落物品的方法。
首先看这一句

ItemStack itemstack = playerIn.getHeldItem(handIn);

很显然获得了手中的物品

return new ActionResult(EnumActionResult.FAIL, itemstack);

表示动作失败,还有PASS和SUCCESSFUL,其中只有返回SUCCESSFUL时才会有使用物品的动画效果。

itemstack.shrink(1);

表示移除了手上的一个物品

worldIn.rayTraceBlocks(vec3d, vec3d1, true)

会返回一个RayTraceResult,与玩家看着的方块有关
通过解读源代码,我们可以写出自己的方法:

public ActionResult< ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
{
ItemStack itemstack = playerIn.getHeldItem(handIn);
float f = 1.0F;
float f1 = playerIn.prevRotationPitch + (playerIn.rotationPitch - playerIn.prevRotationPitch) * 1.0F;
float f2 = playerIn.prevRotationYaw + (playerIn.rotationYaw - playerIn.prevRotationYaw) * 1.0F;
double d0 = playerIn.prevPosX + (playerIn.posX - playerIn.prevPosX) * 1.0D;
double d1 = playerIn.prevPosY + (playerIn.posY - playerIn.prevPosY) * 1.0D + (double)playerIn.getEyeHeight();
double d2 = playerIn.prevPosZ + (playerIn.posZ - playerIn.prevPosZ) * 1.0D;
Vec3d vec3d = new Vec3d(d0, d1, d2);
float f3 = MathHelper.cos(-f2 * 0.017453292F - (float)Math.PI);
float f4 = MathHelper.sin(-f2 * 0.017453292F - (float)Math.PI);
float f5 = -MathHelper.cos(-f1 * 0.017453292F);
float f6 = MathHelper.sin(-f1 * 0.017453292F);
float f7 = f4 * f5;
float f8 = f3 * f5;
double d3 = 5.0D;
Vec3d vec3d1 = vec3d.addVector((double)f7 * d3, (double)f6 * d3, (double)f8 * d3);
RayTraceResult raytraceresult = worldIn.rayTraceBlocks(vec3d, vec3d1, true);
if (raytraceresult == null){
return new ActionResult< ItemStack>(EnumActionResult.PASS, itemstack);
}else if(raytraceresult.typeOfHit == RayTraceResult.Type.BLOCK && !worldIn.isRemote){
BlockPos pos = raytraceresult.getBlockPos();
if(worldIn.getBlockState(pos).getBlockHardness(worldIn,pos) >= 1.5F){
itemstack.shrink(1);
worldIn.spawnEntity(new EntityItem(worldIn,2*(pos.getX()+0.5)-vec3d1.x,2*(pos.getY()+0.5)-vec3d1.y,2*(pos.getZ()+0.5)-vec3d1.z,new ItemStack(ModItems.ROCKLET,2)));
}
return new ActionResult< ItemStack>(EnumActionResult.SUCCESS, itemstack);
}else{
return new ActionResult(EnumActionResult.FAIL, itemstack);
}
}

这里Vec3d是一个坐标,它与BlockPos的区别在于它的坐标是double类型的
创建一个RayTraceResult 需要一个起点和一个终点,它会返回玩家视线是对着方块、实体还是空的。World.spawnEntity方法用来创建一个实体。
虽然一开始一段代码确定了视线的终点,但从游戏效果看,这个点通常在目标方块内部远离玩家的位置,所以我采用了一种不是很规范的方式来取得一个相对准确的坐标。

上一篇:Minecraft mod制作简易教程(二)——Mod配置
https://blog.csdn.net/lyh20000420/article/details/83659163
下一篇:Minecraft mod制作简易教程(四)——创建一个方块
https://blog.csdn.net/lyh20000420/article/details/83660874
回到目录:https://blog.csdn.net/lyh20000420/article/details/83659423

Minecraft mod制作简易教程(三)——创建一个物品相关推荐

  1. Minecraft 1.12.2模组开发(三) 创建一个物品(item)+物品栏

    本次我们来介绍一下如何创建一个基础物品: 演示包名:com.Joy187.newmod (之后都简称为包名) 1. 新建 -> 创建一个 包名.init 包 2.在刚刚创建的init包中新建一个 ...

  2. Minecraft Fabric Mod编写日记-02创建一个物品

    注:由于作者对于mod开发也是初出茅庐(甚至Java都还没学会),所以本教程可能有些地方有问题,还请大佬多多包容awa 棕锁粥之,Minecraft中的物品都是通过net.minecraft.item ...

  3. Scott Mitchell 的ASP.NET 2.0数据教程之一: 创建一个数据访问层

    原文 | 下载本教程中的编码例子 | 下载本教程的英文PDF版 导言 作为web开发人员,我们的生活围绕着数据操作.我们建立数据库来存储数据,写编码来访问和修改数据,设计网页来采集和汇总数据.本文是研 ...

  4. java写七彩文字_【PS精选案例教程】创建一个漂亮的七彩文字

    原标题:[PS精选案例教程]创建一个漂亮的七彩文字 效果图: 步骤1. 新建一个文档(大小随意) 步骤2. 滤镜→渲染→云彩 步骤3. 可以按Ctrl+Alt+F增加效果 步骤4. Ctrl+J复制一 ...

  5. [转]VS2010 教程:创建一个 WPF 应用程序 (第一节)

    [转]VS2010 教程:创建一个 WPF 应用程序 (第一节) http://msdn.microsoft.com/zh-cn/ff629048(zh-cn) Extended WPF Toolki ...

  6. ROM制作教程 如何创建一个刷机包

    目前有好几种方法来安装软件或是库文件到你的Android手机上.你可以使用市场程序来查找并安装软件,也可以使用adb命令行工具来安装或是发送文件到你的Android文件系统中.这些方法对于操作单个文件 ...

  7. PS网页设计教程XXIII——创建一个售卖iPhone 5应用程序的网站

    作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,"熟读唐诗三百首,不会作诗也会吟". 本系列的教程来源于网上的PS教程,都是国外的 ...

  8. Kile5安装教程和创建一个工程举例【图文STM32F407ZE芯片为例】

    文章目录 [一]开始安装 keil5 STM32F407ZE为例 [二]STM32工程创建步骤 [三]安装J-Link驱动+ST-LINK驱动及教程 [四]STM32的命名规则举例 --->面试 ...

  9. chrome谷歌浏览器插件制作简易教程

    1.在磁盘上创建一个目录,用来放应用的代码和资源 2.在这个目录中,创建一个文本文件,命名为manifest.json,其内容为: {"manifest_version": 2,& ...

  10. 【Unity教程】创建一个完整的驾驶游戏

    专业游戏设计 你会学到什么 在unity HDRP创建一个完整的驾驶游戏 定制不同类型的汽车 将人工智能汽车和人工智能航路点系统添加到你的赛道上 添加汽车展厅菜单以解锁和购买新车 在Blender中设 ...

最新文章

  1. HTML-参考手册: HTTP 方法:GET 对比 POST
  2. Leetcode 25.K个一组翻转链表
  3. 声音处理之-梅尔频率倒谱系数(MFCC)
  4. ES6公用花瓣飘落插件的封装及使用,支持npm安装
  5. python 垃圾回收机制
  6. LeetCode 551. Student Attendance Record I
  7. Ubuntu16.04下实时监控CPU/GPU内存的使用情况
  8. 基于express + express-myconnection 的请求处理模板
  9. substring的用法
  10. 如何在Android文本视图周围添加边框?
  11. java 获取字符串_详解Java String字符串获取每一个字符及常用方法
  12. 数学实验matlab课后习题,数学实验练习题(MATLAB)
  13. awstats 日志分析
  14. 支持xp的最高配置? 20210518
  15. 人工智能ai技术案例_AI在软件测试中的案例
  16. MyScript基础功能
  17. 黑科技项目:英雄无敌III Mod Fallen Angel介绍
  18. 【redis:二】持久化
  19. dfuse 的 GraphQL 端点现在提供经过 ABI 解码的数据库行为信息
  20. Python jupyter notebook Katex|Latex

热门文章

  1. 蓝桥杯省赛真题2016题解
  2. unity3d开发 打飞机小游戏(五)(飞机移动/敌机死亡动画)
  3. 理解Cookie机制
  4. 麦吉尔大学计算机科学,麦吉尔大学计算机专业
  5. Python 网络爬虫实现 QQ 音乐下载
  6. 程序员在体制内的工作与生活是怎样的?
  7. 怎样查找计算机死机日志,怎么查看电脑死机记录
  8. ubuntu16.04,exFAT格式U盘无法打开,离线解决方式
  9. jzoj6152. 【GDOI2019Day2模拟2019.4.29】Endless (倍增维护并查集,平方串)
  10. 张云茹计算机,重庆理工大学药学与生物工程学院研究生导师简介-张云茹