自定义物品
Minecraft: Java Edition 支持创建基于原版物品的"自定义"物品。通过 Minecraft 1.21.4+,引入的物品组件进一步允许在每个物品堆栈的基础上自定义物品行为,例如使用物品模型组件更改视觉外观,以及修改物品属性(如吃东西或装备物品的能力)。
与 Java Edition 不同,Bedrock 原生支持添加不基于原版物品的自定义物品。但是,Bedrock 不支持扩展原版物品或修改原版物品行为。因此,Geyser 有一个映射系统,允许将自定义 Bedrock 物品映射到修改后的原版 Java 物品。Geyser 还支持将自定义 Bedrock 物品映射到模组非原版物品,这些物品通常需要在 Java 客户端上安装模组。
要在 Geyser 中设置自定义物品,你需要选择注册物品的方式。最简单的方式是使用 JSON 映射文件,但你也可以使用使用 Geyser API 的 Geyser 扩展。此外,还必须提供 Bedrock 版资源包,以确保 Bedrock 玩家可以看到自定义物品。
Geyser 不会转换 Java Edition 的资源包,也不会自动生成自定义物品映射。 但是,你可以使用自动化工具(如 Rainbow)来简化内容转换。
自 Geyser API 版本 2.9.3(Build #1062 及以上)起,旧的自定义物品格式(v1)已弃用,不再更新。 旧文档仍可在此处找到。
自定义物品 (v2)
Geyser 支持使用 1.21.4+ 引入的 item_model 和物品组件功能映射物品。之前的 custom-model-data 方法继续受支持,使用 legacy 定义。
但是,有一些注意事项。与 Java Edition 不同,Bedrock Edition 不支持在运行时动态修改物品属性(例如使用命令使泥土可食用)。
对于此类用例,Geyser 支持谓词系统,允许注册具有不同属性的多个自定义 Bedrock 物品,以映射到具有特定组件的不同物品堆栈。
工作原理
Java Edition 中的"自定义"物品基于原版物品,使用修改后的外观(1.21.4+ 使用物品模型,或旧版本使用自定义模型数据)。 因此,所有映射的 Bedrock 自定义物品定义都基于原版 Java 物品及其组件。此外,映射的定义可以指定额外的组件来修改物品的行为。
先决条件:词汇表
Java 物品:存在于 Minecraft: Java Edition 基础游戏中的任何原版物品。Java 数据包/插件可以通过覆盖 Java 物品的组件来创建自定义物品。Java 物品组件:自 1.21.4+ 起,Java Edition 中的物品使用物品组件定义其属性和行为。 每个 Java 物品都有一组默认组件,可以覆盖这些组件以更改物品的外观或功能。Bedrock 物品组件:自定义 Bedrock 物品也有决定物品行为的组件,类似于 Java Edition。 但是,这些组件不能为物品堆栈在运行时更改,必须在 Bedrock 客户端加入时预先定义。Java legacy 自定义模型数据:1.21.4 之前使用的系统。在 1.21.4 之前,每个"自定义物品"都有一个自定义模型数据数字, 用于决定 Java 物品应使用哪个模型(= 玩家的不同纹理)。Java 物品模型定义:在 Java 1.21.4 中引入,位于 Java 资源包的assets/<namespace>/items/目录中。 这些纹理用于设置 Java 物品的外观,并且可以使用一组规则和物品属性动态更改。 每个 Java 物品将其物品模型定义存储在minecraft:item_model物品数据组件中。可以通过数据包/插件在每个物品堆栈的基础上覆盖它,以使用资源包中定义的自定义物品模型定义。自定义物品定义:自定义物品定义是 Geyser 的一个术语。它表示用于映射 Java 物品模型定义的单个 Bedrock 自定义物品。它包含物品在 Java 和 Bedrock 上的属性信息。 对于同一个 Java 物品模型定义,可以存在多个自定义物品定义,但对于 Java 物品和 Java 物品模型定义的每种组合,没有谓词的自定义物品定义只能有一个。非原版自定义物品定义:也是一个 Geyser 术语。表示映射 Java 非原版(模组)物品的 Bedrock 自定义物品。与普通自定义物品定义一样,它包含物品在 Java 和 Bedrock 上的属性信息。 目前,每个 Java 非原版物品只能有一个非原版自定义物品定义。
定义
每个自定义物品定义代表一个具有一组预定义 Bedrock 选项的自定义 Bedrock 物品。 它绑定到特定的 Java 物品 + 物品模型组合(或者,对于 legacy 物品,绑定到特定的 Java 物品 + 自定义模型数据组合)。
必需的定义属性
bedrock_identifier:此标识符用于自定义 Bedrock 物品(也在 Bedrock 资源包中的 attachables 等中使用), 不能与任何其他自定义物品定义共享。 此标识符不能在minecraft命名空间中。如果没有提供命名空间,则使用geyser_custom。model(对于 JSON 映射中的legacy定义为custom_model_data)也是必需的。
可选的定义属性
display_name:一个字符串,或物品默认显示名称的 json 文本组件。如果未设置,则从 Bedrock 标识符派生。bedrock_options:指定额外 Bedrock 属性的 bedrock optionscomponents:指定物品行为的 Java 物品组件,例如最大堆叠数量。predicate:用于将特定自定义物品定义匹配到物品堆栈的谓词。predicate_strategy:指定如何评估多个谓词。仅在指定谓词时使用。priority:可选地指定定义相对于同一物品 + 物品模型组合的其他定义的优先级。仅在有多个自定义物品定义时使用。
- Definitions: Json mappings
- Definitions: Geyser API
Json 映射文件必须指定 format_version 设置为 2,并在 items 键下列出每个物品的所有定义。它持有一个对象,其中键是 Java 物品,每个值是一个对象数组,
指定该 Java 物品的自定义物品定义。
mappings.json 映射文件的示例结构:
{
"format_version": 2,
"items": {
"minecraft:flint": [
// definition
],
"minecraft:apple": [
// definition1,
// definition2
],
"minecraft:diamond": [
// definition
]
}
}
自定义物品定义有多种类型:
definition:为 Java 物品模型定义的一个自定义物品。legacy:为使用 legacy 自定义模型数据数字的 Java 自定义物品的一个自定义物品。group:自定义物品定义的组。 定义的类型在type键中定义。
- Item Model Definition (1.21.4+)
- Group Definition
- Legacy Definition (pre 1.21.4+)
{
"type": "definition",
"model": "example:example_model",
"bedrock_identifier": "example:example_item"
}
definition 类型用于为特定物品的 item_model 组件值映射一个定义。
这应用于 1.21.4+ 及以上版本。对于使用 legacy custom_model_data 格式的自定义物品,
请使用 legacy 类型。
{
"type": "group",
"model": "example:example_model", // Optional, can be set per-definition
"definitions": [...]
}
group 定义代表一组自定义物品定义。它们可以是标准定义或 legacy 定义。
组中所有非 legacy 定义都继承该组的 Java 物品 model 定义(如果设置了)。
如果组没有设置 model,则组中的所有定义必须自行指定物品模型。
组中的定义也可以是组,组中的定义也可以覆盖组的 Java 物品模型定义。
{
"type": "legacy",
"custom_model_data": 42,
"bedrock_identifier": "example:example_item_legacy"
}
legacy 定义应用于在数据组件(因此 item_models)引入之前创建的版本的自 定义物品。这些必须指定 custom_model_data 浮点值。
展开查看所有定义类型的示例
{
"format_version": 2,
"items": {
"minecraft:flint": [
{
"type": "definition",
"model": "geyser_mc:test_item",
"bedrock_identifier": "geyser_mc:test_item",
"display_name": "An Example Item!",
"bedrock_options": {
"icon": "potato",
"creative_category": "items"
}
},
{
"type": "legacy",
"custom_model_data": 42,
"bedrock_identifier": "geyser_mc:test_legacy_item",
"display_name": "A Very Old Item!",
"bedrock_options": {
"icon": "cobweb"
}
},
{
"type": "group",
"model": "geyser_mc:another_test_item",
"definitions": [
{
"bedrock_identifier": "geyser_mc:another_test_item_nether",
"predicate": {
"type": "match",
"property": "context_dimension",
"value": "minecraft:the_nether"
},
"components": {
"minecraft:consumable": {
"animation": "drink",
"consume_seconds": 10
}
}
},
{
"bedrock_identifier": "geyser_mc:another_test_item",
"bedrock_options": {
"icon": "carrot"
},
"components": {
"minecraft:consumable": {
"animation": "drink",
"consume_seconds": 10
}
}
}
]
}
]
}
}
在此示例中,Java 物品 minecraft:flint 有四个映射定义:
- 第一个使用
geyser_mc:test_item模型的"简单"定义映射。因此,当 Geyser 遇到将item_model组件设置为geyser_mc:test_item模型的燧石物品时,它将始终使用此定义。 - 第二个是自定义模型数据值 42 的"legacy"定义。因此,如果 Geyser 遇到
floats列表中第一个浮点值设置为42的燧石物品,它将使用第二个定义。 此类物品可以使用以下命令获取:/give @s flint[custom_model_data={floats:[42]}] 1 - 第三个和第四个定义是
group类型的一部分,将多个定义映射到minecraft:flint物品在geyser_mc:another_test_item物品模型下在不同条件下使用。具体来说,当提供的维度谓词与下界维度匹配时,使用第三个定义(Bedrock 标识符为geyser_mc:another_test_item_nether)。否则,使用没有谓词的第四个定义。
自定义物品定义使用 GeyserDefineCustomItemsEvent 注册。
@Subscribe
public void onGeyserDefineCustomItems(GeyserDefineCustomItemsEvent event) {
event.register(Identifier.of("flint"), CustomItemDefinition.builder(
Identifier.of("example:example_item_identifier"), // mandatory: Bedrock item identifier
Identifier.of("example:custom_item_model") // mandatory: item model
)
// The following are optional
.displayName("displayName")
.bedrockOptions(...)
.component(JavaItemDataComponents.MAX_STACK_SIZE, 60)
.predicate(ItemRangeDispatchPredicate.count(32))
.predicateStrategy(PredicateStrategy.OR)
.priority(1)
.build());
}
register 方法接受两个参数:原版物品的标识符,以及一个
CustomItemDefinition。后者必须使用 CustomItemDefinition.Builder 创建,
需要传入 Bedrock 物品标识符和物品模型作为参数。
Bedrock 选项
这些选项允许配置 Bedrock 特定的选项,这些选项在组件中未表示。 包括:
-
icon:确定物品使用的图标。如果未设置,则使用物品的 Bedrock 标识符。 此值对应于item_texture.json文件中定义的图标简写。如果使用 Bedrock 物品的标识符,则进行以下更改:
:将被替换为./替换为_
示例:
geyser_mc:a_cool_item->geyser_mc.a_cool_item。 -
allow_offhand:自定义物品是否可以持有/放入副手。默认为true。 -
display_handheld:物品是否应以手持方式显示(例如工具或武器)。默认为false。 -
protection_value:确定穿戴此物品时显示的护甲保护点数。这纯粹是视觉上的, 只有在物品可装备时才有效。默认为0。 -
creative_category:设置物品的创意模式类别(也显示在配方书中)。可以是none、construction、nature、equipment或items。默认为none。 -
creative_group:设置物品的创意模式分组(用于配方书)。请参阅此处 获取可能的值列表。Geyser 目前不支持创建自定义创意分组。 -
tags:设置物品具有的标签。这些可用于资源包中的 Molang 表达式。
如果你的合成配方输出自定义物品,则必须设置 creative_category(以及可选的 creative_group)。
否则,Bedrock 将不 会在配方书中显示自定义物品的配方!
展开查看 bedrock 选项示例
- Json mappings
- Geyser API
"bedrock_options": {
"icon": "example:chestplate", // must match shorthands defined in item_texture.json
"protection_value": 4,
"creative_category": "equipment",
"creative_group": "itemGroup.name.chestplate",
"tags": ["example:tag_one", "example:tag_two"]
}
"bedrock_options": {
"icon": "example:my_sword", // must match shorthands defined in item_texture.json
"display_handheld": true, // usually only set for weapons or tools
"creative_category": "items",
"creative_group": "itemGroup.name.sword",
"tags": ["example:my_weapon"]
}
在 API 中,Bedrock 物品选项使用 CustomItemBedrockOptions#Builder 定义。
以下代码片段显示示例用法:
.bedrockOptions(CustomItemBedrockOptions.builder()
.icon("example:chestplate")
.protectionValue(4)
.creativeCategory(CreativeCategory.EQUIPMENT)
.creativeGroup("itemGroup.name.chestplate")
.tags(Set.of(Identifier.of("example:tag_one"), Identifier.of("example:tag_two")))
)
.bedrockOptions(CustomItemBedrockOptions.builder()
.icon("example:my_sword")
.displayHandheld(true)
.creativeCategory(CreativeCategory.ITEMS)
.creativeGroup("itemGroup.name.sword")
.tag(Identifier.of("example:my_weapon"))
)
组件
物品组件在 Java Edition 中用于自定义物品的功能和行为。 Java Edition 允许在运行时修改这些物品的任何物品堆栈。不幸的是,这不是 Bedrock Edition 支持的功能。 因此,对基础 Java 物品的数据组件的任何修改都必须在映射文件中指定。 当使用自定义物品定义时,预期服务器将始终发送这些组件。对于不同的组件集,应使用带谓词的多个自定义物品定义。
你不需要映射与基础 Java 物品相同的组件。
某些组件一起使用有一些限制! 例如,Bedrock 目前不支持可穿戴堆叠物品。 当使用可装备物品(如马铠)作为基础物品时,你可以移除冲突的默认组件作为临时修复。
添加或修改组件
以下 Java 物品组件受支持(有一些限制):
minecraft:consumable:不支持消耗粒子/声音。minecraft:equippable:不支持相机覆盖或可交换属性。minecraft:foodminecraft:max_damageminecraft:max_stack_sizeminecraft:use_cooldownminecraft:enchantable- 在 Bedrock 上,这将映射到
minecraft:enchantable组件,slot=all。这应该,但不能保证,与原版附魔兼容。非原版附魔可能无法工作。
- 在 Bedrock 上,这将映射到
minecraft:toolminecraft:repairableminecraft:enchantment_glint_overrideminecraft:attack_range- 由于 Bedrock 限制,仅在与
minecraft:kinetic_weapon或minecraft:piercing_weapon组件结合时才有效。
- 由于 Bedrock 限制,仅在与
minecraft:kinetic_weaponminecraft:piercing_weaponminecraft:swing_animation- 由于 Bedrock 限制,实际播放的动画是硬编码的,只能更改动画的持续时间。
minecraft:use_effects- 由于 Bedrock 限制,
can_sprint属性无法翻译。此外,仅当基础物品能够射箭、投掷投射物或可食用(或通过食物组件变为可食用)时,才会翻译此组件。
- 由于 Bedrock 限制,
某些组件(如 minecraft:rarity 和 minecraft:attribute_modifiers)已经自动翻译,不应列出。
有关所有物品组件及其各自 json 格式的文档,请参阅 Minecraft wiki 上的物品数据组件页面。
展开查看组件使用示例
- Json mappings
- Geyser API
所有列出的组件遵循与数据包中使用的相同的 json 结构,这些在 Minecraft wiki 上有文档。以下是一些示例:
"components": {
"minecraft:max_stack_size": 16,
"minecraft:enchantment_glint_override": true
}
所有支持的组件可以在 JavaItemDataComponents 类中找到,通常使用构建器构建。
一些示例:
.component(JavaItemDataComponents.MAX_STACK_SIZE, 16)
.component(JavaItemDataComponents.ENCHANTMENT_GLINT_OVERRIDE, true)
移除默认组件
就像在 Java edition 上可以做到的那样,可以移除基础物品的默认组件(例如使苹果不可食用)。
展开查看组件移除使用示例
- Json mappings
- Geyser API
在 Json 映射中,这是通过在组件前面添加 ! 来完成的。
"components": {
"!minecraft:food": {}
}
CustomItemDefinition#Builder
构建器支持通过指定物品数据组件标识符或传递类型来移除默认组件。
@Subscribe
public void onDefineCustomItems5(GeyserDefineCustomItemsEvent event) {
event.register(Identifier.of("apple"), CustomItemDefinition.builder(
Identifier.of("example:rotten_apple"), Identifier.of("example:rotten_apple")
)
.displayName("Rotten apple")
.removeComponent(JavaItemDataComponents.FOOD)
.build());
}
谓词
谓词用于告诉 Geyser 对于特定的 Java 物品和物品模型组合使用哪个自定义物品定义。 对于更简单的 legacy 映射或没有多个组件变体的自定义物品,不需要谓词。
对于 Java 物品和 Java 物品模型定义的每种组合,可以有一个没有谓词的物品定义,以及一个或多个带有谓词的定义。对于相同的 Java 物品和 Java 物品模型定义,不能有多个具有相同谓词的物品定义。
如果 Java 物品模型定义在 minecraft 命名空间中,则不能有没有谓词的物品定义。
谓词也可以反转以匹配反向条件。
条件谓词
condition 谓词类型检查布尔属性并在属性匹配预期值时返回 true。它有 5 个可能的属性:
broken:物品是否损坏(只剩 1 点耐久度)。damaged:物品是否损坏(未满耐久度)。custom_model_data:检查物品在index键指定的索引处的自定义模型数据标志。默认为false。has_component:物品是否设置了component键中设置的组件。包括默认组件。fishing_rod_cast:玩家当前是否持有已抛出的钓鱼竿。
展开查看使用示例。
- Json mappings
- Geyser API
所有条件谓词类型必须将 type 设置为 condition。
"predicate": {
"type": "condition",
"property": "broken"
}
"predicate": {
"type": "condition",
"property": "damaged"
}
"predicate": {
"type": "condition",
"property": "has_component",
"component": "minecraft:unbreakable"
}
"predicate": {
"type": "condition",
"property": "custom_model_data",
"index": 1
}
"predicate": {
"type": "condition",
"property": "fishing_rod_cast"
}
也可以通过添加并将 expected 键设置为 false 来反转组件。如果未设置,默认为 true。
示例:
"predicate": {
"type": "condition",
"property": "broken",
"expected": false
}
所有条件谓词可以在 ItemConditionPredicate 接口中找到。示例:
.predicate(ItemConditionPredicate.FISHING_ROD_CAST)
一些谓词需要额外的参数:
.predicate(ItemConditionPredicate.customModelData(1))
.predicate(ItemConditionPredicate.hasComponent(ItemDataComponents.REPAIRABLE.identifier()))
要否定谓词,请调用 #negate():
.predicate(ItemConditionPredicate.DAMAGEABLE.negate())
匹配谓词
match 谓词类型检查文本属性并在匹配给定值时返回 true。它有 4 个可能的属性:
charge_type:十字弓当前充电的物品(在minecraft:charged_projectiles组件中)。可以是arrow或rocket。trim_material:此物品的修剪材料(资源位置)。context_dimension:玩家当前所在的维度(资源位置)。custom_model_data:从物品的自定义模型数据字符串中获取字符串。
match 谓词需要在 value 键中指定一个值。
展开查看使用示例。
- Json mappings
- Geyser API
所有匹配谓词类型必须将 type 设置为 match。
"predicate": {
"type": "match",
"property": "charge_type",
"value": "arrow"
}
"predicate": {
"type": "match",
"property": "trim_material",
"value": "minecraft:coast_armor_trim"
}
"predicate": {
"type": "match",
"property": "context_dimension",
"value": "minecraft:the_end"
}
"predicate": {
"type": "match",
"property": "custom_model_data",
"value": "MyString",
"index": 1
}
也可以通过添加并将 expected 键设置为 false 来反转谓词。如果未设置,默认为 true。
示例:
"predicate": {
"type": "match",
"property": "context_dimension",
"value": "minecraft:the_end",
"expected": false
}
物品匹配谓词可以在 ItemMatchPredicate
接口中找到,另外还有 MatchPredicate 接口中的通用匹配谓词。
示例:
.predicate(ItemMatchPredicate.chargeType(ChargedProjectile.ChargeType.ARROW));
.predicate(MatchPredicate.dimension(Identifier.of("the_end")));