我的世界Java版1.21.4的Fabric模组开发教程(十一)创建方块

article/2025/8/27 14:29:13

这是适用于Minecraft Java版1.21.4的Fabric模组开发系列教程专栏第十一章——创建方块。想要阅读其他内容,请查看或订阅上面的专栏。

方块(Block) 是构成Minecraft世界的主要组成部分,是组成游戏地图的最基本单元,也是模组开发的核心元素之一。

与创建物品类似,方块同样也需要在游戏注册表中注册,也同样需要创建对应的模型文件、模型描述文件和方块纹理。方块的复杂程度要高于物品,因此方块需要创建更多的配置文件来完成方块各种功能的设置。如果是首次阅读到本文且没有Fabric模组开发基础,请先访问我的世界Java版1.21.4的Fabric模组开发教程(二)创建物品;

在本章,我们将创建一个自定义方块——浓缩泥土(condensed_dirt)。文章将先以最简单方块的形式详细讲解创建方块的步骤,然后在最简单方块的基础上,拓展更多关于方块其他功能的配置方式。

通常,如果是首次创建方块,以最简单的方块为例,整个过程应当按照以下步骤推进:

  • 创建方块注册类;
  • 封装register()方法;
  • 注册方块并将其添加到指定物品组中;
  • 在语言文件中为方块添加翻译键值对;
  • 创建方块的模型文件、模型描述文件和方块纹理;
  • 创建方块状态定义文件;

此外还可以为方块:

  • 配置掉落物;
  • 配置挖掘工具。

创建方块注册类

对于简单的方块,我们可以直接将其在游戏注册表中注册。不过,在此之前可以提前封装Minecraft API中提供的Registry.register()方法,使注册过程更加简单。

一般,方块注册类中有三种内容:

  • register():封装了Registry.register()方法并用于注册方块的核心方法,将在下一小节详细讲解;
  • initialize():用于初始化方块注册类,需要在入口点类中调用;
  • 类型为Block的方块注册静态常量:用于注册自定义方块。

1.在com/example/test/utils目录中创建ModBlocks.java,作为方块注册类;

public class ModBlocks {}

2.声明静态方法register(),用于注册方块;

public static Block register(){}

下一小节将详细讲解方法体中的内容;

3.声明静态方法initialize(),用于初始化方块注册类;

public static void initialize(){Test.LOGGER.info("注册方块!");
}

其中可以输出日志信息;

4.在入口点类的onInitialize()方法中调用ModBlocks.initialize(),完成方块注册类的初始化;

@Override
public void onInitialize() {...ModBlocks.initialize();...
}

封装register()方法

根据Fabric官方文档所述,应当使用下面的写法封装Registry.register()方法,来简化注册方块的代码;

private static Block register(String name, Function<AbstractBlock.Settings, Block> blockFactory, AbstractBlock.Settings settings, boolean shouldRegisterItem) {// Create a registry key for the blockRegistryKey<Block> blockKey = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(FabricDocsReference.MOD_ID, name));// Create the block instanceBlock block = blockFactory.apply(settings.registryKey(blockKey));// Sometimes, you may not want to register an item for the block.// Eg: if it's a technical block like `minecraft:moving_piston` or `minecraft:end_gateway`if (shouldRegisterItem) {// Items need to be registered with a different type of registry key, but the ID can be the same.RegistryKey<Item> itemKey = RegistryKey.of(RegistryKeys.ITEM, Identifier.of(FabricDocsReference.MOD_ID, name));BlockItem blockItem = new BlockItem(block, new Item.Settings().registryKey(itemKey));Registry.register(Registries.ITEM, itemKey, blockItem);}return Registry.register(Registries.BLOCK, blockKey, block);
}

方法中需要传递四个参数:

  • String name:指定方块名,即标识符中的路径;
  • Function<AbstractBlock.Settings, Block> blockFactory:抽象方块设置内部类对象和方块对象的函数表达式,仅用于创建Block对象;
  • AbstractBlock.Settings settings:抽象方块设置内部类对象,可以用于配置方的属性;
  • boolean shouldRegisterItem:指定是否需要为方块注册方块物品,使其可以在创造模式物品栏中显示;

方法首先使用RegistryKey.of()方法获取方块注册键对象,其中按顺序传递了注册键为方块RegistryKeys.BLOCK和由模组Id和方块路径组成的Identifier标识符对象。然后通过RegistryKey<Block>注册键创建方块Block对象。至此,方块对象创建完毕;

接着,根据shouldRegisterItem变量的值,来确定是否需要注册方块对应的方块物品。如果需要注册,则再次使用RegistryKey.of()方法获取物品的注册键对象,其中按顺序传递了注册键为物品RegistryKeys.Item和由模组Id和方块路径组成的Identifier标识符对象。然后调用BlockItem类的构造方法来创建方块物品BlockItem对象,方法中按顺序传递了方块对象和物品注册键对象。最后调用Registry.register()方法将方块物品在游戏注册表中注册,方法中按顺序传递了注册键常量Registries.ITEM、方块物品注册键对象和方块物品对象;

如果不需要注册方块物品,则直接调用Registry.register()方法将方块在游戏注册表中注册,方法中按顺序传递了注册键常量Registries.BLOCK、方块注册键对象和方块对象。

关于IdentifierRegistry类的详细用法说明请参考我的世界Java版1.21.4的Fabric模组开发教程(二)创建物品;关于RegistryKey.of()方法的详细用法说明请参考我的世界Java版1.21.4的Fabric模组开发教程(五)创建高级物品:盔甲。


方块类Block

Block类是Minecraft中所有方块的基类,定义了方块的核心行为和属性。通常,创建带有复杂自定义行为和属性的方块时,可以创建继承了Block类的自定义方块类。在游戏中,同一类型的方块共享同一个Block实例,例如,一个世界中的所有石头方块只共享一个石头方块实例,而不是为每一个石头方块都创建实例。创建方块对象后对应的方块物品对象不会自动创建,创建方块物品对象还需调用Registy.register()方法。

Block类中提供了许多方法,可以在涉及到方块的任何场景调用:

  • asItem():方法返回与方块对应的物品对象;

在后续章节中用到的方法将在此处补充。

抽象方块类AbstractBlock及其设置内部类AbstractBlock.Settings

AbstractBlock作为一个抽象类,定义了所有方块的基础属性和通用行为AbstractBlockBlock类的父类,但AbstractBlock不能直接继承自定义方块类。

方块的自定义属性由内部类AbstractBlock.Settings的实例控制,其构造方法已经被私有化,想要创建AbstractBlock.Settings的实例,只能调用其静态方法create(),直接返回一个内部类AbstractBlock.Settings的实例;

public static AbstractBlock.Settings create() {return new AbstractBlock.Settings();
}

AbstractBlock.Settings类中提供了许多方法来配置方块的属性,所有方法均支持链式编程,包括:

  • requiresTool():配置方块只能由工具采集;
  • sounds():配置方块与玩家交互的声音,通常传递一个BlockSoundGroup类中的静态常量;
  • hardness():指定方块硬度。参考值:橡木木板2.0f;

在后续章节中用到的方法将在此处补充。

方块物品类BlockItem

BlockItem类继承了Item类,用于将方块和物品关联起来,使得方块能够以物品的形式存在于玩家的背包、快捷栏或合成表中,并允许玩家在世界中通过方块物品来使用方块。

一般,调用其构造方法来创建BlockItem类的对象;

public BlockItem(Block block, Item.Settings settings) {super(settings);this.block = block;
}

其中需要传递两个参数:

  • Block block:指定要创建方块物品的方块对象;
  • Item.Settings settings:指定物品设置内部类对象,在注册时通常通过此参数传递注册键;关于内部类Item.Settings的详细用法说明,请参考我的世界Java版1.21.4的Fabric模组开发教程(二)创建物品。

直接将register()方法体复制到方块注册类ModBlocks.javaregister()方法中,然后将访问修饰符改为private

注册方块并将其添加到指定物品组中

现在,我们将方块“浓缩泥土”在游戏注册表中注册,然后将其方块物品添加到物品组中。方块注册逻辑可以写在方块注册类ModBlocks.java中,但将方块物品添加到物品组的逻辑依然需要写在入口点类中。

1.在ModBlocks.java中声明静态常量CONDENSED_DIRT,类型为Block,并调用register()方法对其初始化;

public static final Block CONDENSED_DIRT = register("condensed_dirt",Block::new,AbstractBlock.Settings.create().sounds(BlockSoundGroup.GRASS),true
);

按顺序依次设置了物品名为“condensed_dirt”、抽象方块设置内部类对象和方块对象的函数式Block::new、交互声音为BlockSoundGroup.GRASS并要求注册方块对应的方块物品。

2.在入口点类的onInitialize()方法中,将方块添加到指定物品组中;

ItemGroupEvents.modifyEntriesEvent(CUSTOM_ITEM_GROUP_KEY).register((itemGroup) -> {...itemGroup.add(ModBlocks.CONDENSED_DIRT.asItem());...});

需要调用asItem()方法将方块转换为物品。

在语言文件中为方块添加翻译键值对

打开语言文件zh-cn.json,为方块添加中文翻译;

{..."item.test.condensed_dirt": "浓缩泥土",...
}

“condensed_dirt”为注册方块时使用的路径名。

创建方块的模型文件、模型描述文件和方块纹理

同物品一样,方块也需要创建模型文件、模型描述文件和对应的方块纹理。但是这些配置文件和物品的配置文件存放的位置不同。如果是首次创建自定义方块,可能需要创建新的目录。

1.在assets/test/models目录中创建block目录,用于存放方块的模型文件。在目录中创建condensed_dirt.json

{"parent": "minecraft:block/cube_all","textures": {"all": "test:block/condensed_dirt"}
}

此时我们使用的模型为block/cube_alltextures配置项中,需要添加all配置项,值为test:block/condensed_dirt,即“模组Id+:block/+标识符”,代表方块的所有面应用的纹理图位置;

2.在assets/test/items中创建condensed_dirt.json,代表方块的模型描述文件;

{"model": {"type": "minecraft:model","model": "test:block/condensed_dirt"}
}

此处与物品模型描述文件的写法大致相同;

3.在assets/test/textures目录中创建block目录,将方块纹理图移动到目录中;

在这里插入图片描述
图片大小为16*16,文件名为“condensed_dirt.png”,即方块路径名。不能使用其他格式的图片, 只能使用.png文件。

创建方块状态定义文件

方块状态定义用于指示游戏基于当前方块的状态要渲染哪个模型。目前,还不需要编程式的方块状态定义,只需要创建方块状态定义JSON文件即可。

“浓缩泥土”方块并没有复杂的状态,方块状态定义文件中只需要添加一条配置项;

assets/test目录中创建blockstates目录,用于存放方块的状态定义文件。在其中创建condensed_dirt.json,文件名应当与方块路径名相同;

{"variants": {"": {"model": "test:block/condensed_dirt"}}
}

其中的配置项包含:

  • "variants":设置变种与对应的模型,内部需要列出此方块的所有变种;
    • "":变种名。不含有方块属性的方块状态使用""作为变种名;
      • "model":指定模型文件的标识符;

其中有更多的配置项,将在后续章节详细讲解关于方块状态的知识。

启动游戏测试

现在,我们打开游戏测试一下“浓缩泥土”方块的各种功能。

1.启动游戏,打开创造模式物品栏,找到“浓缩泥土”;
在这里插入图片描述
可以看到方块物品已经成功注册,方块纹理和中文名称显示正常。将其添加到背包,然后主手持“浓缩泥土”,右键点击使用方块;
在这里插入图片描述
可以看到方块显示正常。

至此,一个最简单的方块已经创建完毕。如果想给方块添加更多自定义功能和属性,还请继续阅读下文。

添加方块的掉落物/战利品列表

现在,无论是在创造模式,还是生存模式,使用任何工具或徒手破坏方块都不会出现掉落物。我们可以为其添加掉落物,由于某些方块破坏后掉落的东西不止一种,方块的掉落物也称之为战利品列表

在开始前,确保你的项目已经启用数据生成(即使不使用数据生成类)。关于启用项目的数据生成说明,请参考我的世界Java版1.21.4的Fabric模组开发教程(二)创建物品中的“为物品添加合成配方”小节。

data/test目录中创建loot_table目录,用于存放方块战利品列表JSON配置文件,在其中创建blocks文件夹,代表方块的掉落物/战利品列表JSON配置文件,然后继续在其中创建condensed_dirt.json,文件名与方块注册时使用的路径相同。
在这里插入图片描述
对于“浓缩泥土”方块,破坏方块时只需掉落其本身即可,其配置文件的写法应当如下:

{"type": "minecraft:block","pools": [{"rolls": 1,"entries": [{"type": "minecraft:item","name": "test:condensed_dirt"}],"conditions": [{"condition": "minecraft:survives_explosion"}]}]
}

其中的配置项包含:

  • "type":战利品上下文的参数集类型。指定了调用该战利品时要应用的上下文环境,用于验证其他配置项的合法性,当某些配置错误或缺失时,游戏日志中会打印警告信息;
  • "pools":战利品表的随机池的列表。主要定义了若干待选的抽取项;
    • "rolls":指定该随机池的抽取次数;
    • "entries":指定随机池中的抽取项。抽取项分为单一抽取项和复合抽取项,单一抽取项定义了单个物品生成行为,是随机池中最终要抽取的带权重的项目。如果不使用物品修饰器,物品数量默认为1。此处我们使用的是单一抽取项,下面给出类型为item的战利品池抽取项的数据格式:
      • "type""minecraft:item"
      • "name":物品的标识符;
    • "conditions":战利品表谓词列表。仅当满足列表中的所有条件时,该随机池才会被使用;
      • "condition":战利品表谓词,又称战利品表物品条件,用于在战利品表中制定战利品的产生条件。此处使用了"minecraft:survives_explosion",代表物品可以通过爆炸掉落;

启动游戏,在创造模式下将“浓缩泥土”放入背包,然后切换为生存模式,放置方块,然后破坏方块,可以看到掉落物。
请添加图片描述

配置推荐的挖掘工具

如果想限制挖掘方块的工具,可以继续添加配置文件。例如,这里我们令“浓缩泥土”只能由锹类工具挖掘时才会掉落。

data目录中创建minecraft文件夹,然后在其中依次创建tag/block/mineable目录,最后创建shovel.json
在这里插入图片描述
配置文件中的结构如下:

{"values": ["test:condensed_dirt"]
}

"values"配置项中直接提供方块的标识符。将“浓缩泥土”的标识符添加到文件中,代表只能使用锹挖掘方块才能获得掉落物,否则挖掘速度将很慢且没有掉落物;

shovel.json文件中存放推荐使用锹类工具破坏的方块的集合。此外,还有其他配置文件:

  • hoe.json:推荐使用锄类工具破坏;
  • axe.json:推荐使用斧类工具破坏;
  • pickaxe.json:推荐使用镐类工具破坏;

这些文件和Minecraft原生配置文件的文件名和文件位置相同,数据将会追加到原生配置文件中,而不是完全替换原生配置文件。

配置指定的工具等级

如果想限制挖掘方块所用工具的材质级别,可以继续添加配置文件。例如,这里我们令“浓缩泥土”只能由“铁锹”及以上的材料(钻石锹、下界合金锹)挖掘时才会掉落。

data/minecraft/tags/block目录中创建needs_diamond_tool.json,文件结构与文的shovel.json相同;

{"values": ["test:condensed_dirt"]
}

为了演示效果,我们调用hardness()方法为方块设置硬度,使其破坏需要一定时间。找到ModBlocks.java,修改register()方法中的参数;

public static final Block CONDENSED_DIRT = register("condensed_dirt",Block::new,AbstractBlock.Settings.create().sounds(BlockSoundGroup.GRASS).requiresTool().hardness(2.5f),true
);

将硬度改为2.5。启动游戏,使用铁锹破坏方块;
请添加图片描述
可以看到掉落物。使用钻石锹或下界合金锹破坏方块也可以获得掉落物。

本章小结

本章详细阐述了创建一个自定义方块的步骤。本文篇幅较长,但难度一般,阅读本文要求开发者有创建物品的知识基础,才能理解文中的部分写法。感谢各位的阅读,有兴趣可以订阅此专栏!


http://www.hkcw.cn/article/klGYyyNPkV.shtml

相关文章

计算机网络:物理层

目录 一、物理层的基本概念 二、物理层下面的传输媒体 2.1 导引型传输媒体 2.1.1 同轴电缆 2.1.2 双绞线 2.1.3 光纤 2.1.4 电力线 2.2 非导引型传输媒体 2.2.1 无线电波 2.2.2 微波 2.2.3 红外线 2.2.4 可见光 三、传输方式 3.1 串行与并行 3.2 同步与异步 3.…

我的世界Java版1.21.4的Fabric模组开发教程(十)更多物品交互行为

这是适用于Minecraft Java版1.21.4的Fabric模组开发系列教程专栏第十章——更多物品交互行为。想要阅读其他内容&#xff0c;请查看或订阅上面的专栏。 在之前的创建自定义数据组件章节中&#xff0c;我们在自定义物品类中重写了来自Item类中的use()方法&#xff0c;实现了在右…

Linux531rsync定时同步 再回忆

rsync定时同步 环境配置 关闭防火墙&#xff0c;selinux systemctl stop firewalld systemctl disable firewall setenforce 0 cat /etc/selinux/configpei SELINUXdisable设置主机名 systemctl set-hostname code systemctl set-hostname backup设置静态IP rsync由于要设…

MySQL数据库复合查询

前言&#xff1a;本文不对SQL查询做详细讲解&#xff0c;而做案例实践&#xff0c;适合已掌握MySQL基础语法&#xff0c;需要通过实际案例巩固技能的开发者。 首先准备这样三张表 雇员信息表、部门信息、薪水等级。如下&#xff1a; 需要库文件的小伙伴私信我哦&#xff01;&am…

STM32 串口通信①:USART 全面理解 + 代码详解

一 前言 本篇文章并不会系统的从零开始讲起&#xff0c;适合大家对USART有一定的学习&#xff0c;再看本篇文章会有一定的收获&#xff0c;祝大家在本文中&#xff0c;吸收到新的知识。 二 通信方式 1&#xff09;按数据传输的方式分&#xff08;这就是“串行 vs 并行”&…

基于图神经网络的自然语言处理:融合LangGraph与大型概念模型的情感分析实践

在企业数字化转型进程中&#xff0c;非结构化文本数据的处理与分析已成为核心技术挑战。传统自然语言处理方法在处理客户反馈、社交媒体内容和内部文档等复杂数据集时&#xff0c;往往难以有效捕获文本间的深层语义关联和结构化关系。大型概念模型&#xff08;Large Concept Mo…

极地导航的难点及应对措施(上)

在之前的博文《南北极导航选用什么投影&#xff1f;》和何老师的博文《高纬度、跨极区导航技术》中简单说了说南北极导航的投影设置问题。 本文主要说一说南北极导航中实际工作的难点问题以及应对措施。下图是南北极的位置图&#xff0c;从图中可以看出&#xff0c;南极是大陆…

Centos系统搭建主备DNS服务

目录 一、主DNS服务器配置 1.安装 BIND 软件包 2.配置主配置文件 3.创建正向区域文件 4.创建区域数据文件 5.检查配置语法并重启服务 二、从DNS服务配置 1.安装 BIND 软件包 2.配置主配置文件 3.创建缓存目录 4.启动并设置开机自启 一、主DNS服务器配置 1.安装 BIN…

【图像处理入门】3. 几何变换基础:从平移旋转到插值魔法

摘要 掌握图像的几何变换相当于学会「图像的空间魔法」。本文将带你理解平移/旋转/缩放的数学原理&#xff0c;掌握OpenCV中warpAffine和getAffineTransform的核心用法&#xff0c;对比最近邻、双线性等插值算法的优劣。通过图像翻转、镜像、透视变换实战&#xff0c;学会用变…

TomatoSCI分析日记:数据分析为什么用csv不用excel

其实并不是多余&#xff0c;虽然看到的内容是一样的&#xff0c;但是相比excel文件&#xff0c;csv文件没这么多繁文缛节&#xff0c;效率更高。 1.csv更干净 csv本质是纯文本&#xff0c;只有你看到的数据&#xff0c;没有花里胡哨的单元格格式、颜色、批注等隐藏信息&#…

【鱼皮-用户中心】笔记

任务&#xff1a;完整了解做项目的思路&#xff0c;接触一些企业及的开发技术 title 企业做项目流程需求分析技术选型 计划一一、前端初始化1. **下载node.js**2. **安装yarn**3. **初始化 Ant Design Pro 脚⼿架&#xff08;关于更多可进入官网了解&#xff09;**4. **开启Umi…

基于 Chrome 浏览器扩展的Chroma简易图形化界面

简介 ChromaDB Manager 是基于 Chrome 浏览器扩展的一款 ChromaDB&#xff08;一个流行的向量数据库&#xff09;的数据查询工具。提供了一个用户友好的界面&#xff0c;可以直接从浏览器连接到本地 ChromaDB 实例、查看集合信息和分片数据。本工具特别适合开发人员快速查看和…

[ElasticSearch] ElasticSearch的初识与基本操作

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

Kafka 如何保证不重复消费

在消息队列的使用场景中&#xff0c;避免消息重复消费是保障数据准确性和业务逻辑正确性的关键。对于 Kafka 而言&#xff0c;保证不重复消费并非单一机制就能实现&#xff0c;而是需要从生产者、消费者以及业务层等多个维度协同配合。接下来&#xff0c;我们将结合图文详细解析…

【快速解决】数据库快速导出成sql文件

1、cmd直接打开 输入命令 mysqldump -u用户名 -p密码 数据库名 > 导出文件名.sql修改成自己mysql的用户名和密码&#xff0c;和要导出的数据库名称&#xff0c;给导出的文件起一个名字。 如图所示 这样就成功了。

OldRoll复古胶片相机:穿越时光,定格经典

在数字摄影盛行的今天&#xff0c;复古胶片相机的独特魅力依然吸引着无数摄影爱好者。OldRoll复古胶片相机这款软件&#xff0c;以其独特的复古风格和丰富的胶片滤镜效果&#xff0c;让用户仿佛穿越回了那个胶片摄影的黄金时代。它不仅模拟了胶片相机的操作界面&#xff0c;还提…

利用Dify创建一个公司产品知识问答

1、创建知识库 打开dify&#xff0c;创建知识库。 选择创建一个空知识库&#xff0c;对知识库进行命名&#xff0c;或者直接导入已有文本&#xff0c;拖曳或选择文件进入下一步&#xff0c;会自动命名知识库。 创新空知识库后&#xff0c;点击添加文件&#xff0c;再导入已有文…

redis核心知识点

Redis是一种基于内存的数据库&#xff0c;对数据的读写操作都是在内存中完成&#xff0c;因此读写速度非常快&#xff0c;常用于缓存&#xff0c;消息队列、分布式锁等场景。 Redis 提供了多种数据类型来支持不同的业务场景&#xff0c;比如 String(字符串)、Hash(哈希)、 Lis…

黄金价格查询接口如何用C#进行调用?

一、什么是黄金价格查询接口&#xff1f; 提供当日实时黄金行情数据&#xff0c;如上交所&#xff0c;银行账户黄金&#xff0c;国际金价、金店价格等&#xff0c;获取最低价、最高价、卖价、昨日收盘价、开盘价、涨跌值、最新价格、时间、买价、涨跌幅等行情。 二、科技赋能…

JVM 核心组件深度解析:堆、方法区、执行引擎与本地方法接口

一、JVM 堆内存&#xff1a;对象的生存与消亡之地 作为 Java 虚拟机中最大的内存区域&#xff0c;堆内存是所有对象实例的 “出生地” 与 “安息所”。从程序运行的角度看&#xff0c;所有通过new关键字创建的对象都在堆中分配内存&#xff0c;其生命周期完全由垃圾回收机制&am…