当前位置: 首页 > article >正文

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

这是适用于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.lryc.cn/news/2394165.html

相关文章:

  • VR/AR 视网膜级显示破局:10000PPI 如何终结颗粒感时代?
  • C++ 命令模式:设计与实现详解
  • 系统思考:化繁为简的艺术
  • java/mysql/ES下的日期类型分析
  • Angularjs-Hello
  • Python训练营---Day41
  • Linux 1.0.4
  • Qt -下载Qt6与OpenCV
  • 机器学习无监督学习sklearn实战一:K-Means 算法聚类对葡萄酒数据集进行聚类分析和可视化( 主成分分析PCA特征降维)
  • 可灵2.1 vs Veo 3:AI视频生成谁更胜一筹?
  • C语言之编译器集合
  • 计量表计的演进历程与技术变革:从机械到物联网时代
  • 更换Homebrew 源
  • 人工智能在智能供应链中的创新应用与未来趋势
  • 鸿蒙OSUniApp自定义手势识别与操作控制实践#三方框架 #Uniapp
  • LLM优化技术——Paged Attention
  • 推荐几个不错的AI入门学习视频
  • 采用Bright Data+n8n+AI打造自动化新闻助手:每天5分钟实现内容日更
  • Real SQL Programming
  • Sentinel限流熔断机制实战
  • Java 数据处理 - 数值转不同进制的字符串(数值转十进制字符串、数值转二进制字符串、数值转八进制字符串、数值转十六进制字符串)
  • 79. 单词搜索-极致优化,可行性剪枝和顺序剪枝
  • ICDMC 2025:创新媒体模式,迎接数字时代的挑战
  • 深入解析C#多态性:基类引用、虚方法与覆写机制
  • SoftThinking:让模型学会模糊思考,同时提升准确性和推理速度!!
  • C++中 newdelete 与 mallocfree 的异同详解
  • 晨控CK-UR08与欧姆龙PLC配置Ethernet/IP通讯连接操作手册
  • STM32入门教程——LED闪烁LED流水灯蜂鸣器
  • 鸿蒙OSUniApp 实现的数据可视化图表组件#三方框架 #Uniapp
  • Tornado WebSocket实时聊天实例