Skip to main content

Custom Items

Minecraft: Java Edition supports creating "custom" items that are based on vanilla items. With Minecraft 1.21.4+, the introduction of item components further allows the customization of item behavior on a per-item-stack basis, such as changing the visual appearance using the item model component, and modifying item properties such as the ability to eat or equip an item.

Unlike Java Edition, Bedrock natively supports adding custom items that are not based on vanilla items. However, Bedrock does not support extending vanilla items or modifying vanilla item behavior. Therefore, Geyser has a mapping system that allows mapping custom Bedrock items to modified vanilla Java items. Geyser further supports mapping custom Bedrock items to modded non-vanilla items which would normally require mods to be installed on the Java client.

To set up custom items in Geyser, you have to choose how you are going to register your items. The easiest is using a json mapping file, but you can also use a Geyser extension which uses the Geyser API. Further, a Bedrock edition resource pack must also be supplied to ensure Bedrock players can see custom items.

warning

Geyser does not convert resource packs from Java Edition, and also does not generate custom item mappings automatically. However, you can use automatic tools such as Rainbow to make converting content simpler.

info

Since the Geyser API version 2.9.3 (Build #1062 and up), the old custom item format (v1) is deprecated and is no longer being updated. Old docs can still be found here

Custom items (v2)

Geyser supports mapping items using item_model and item component features introduced in 1.21.4+. The previous custom-model-data approach continues to be supported using legacy definitions. However, there are some caveats. Unlike Java Edition, Bedrock Edition does not support modifying item properties dynamically at runtime (e.g. making dirt edible with a command). For such use-cases, Geyser supports a predicate system which allows registering multiple custom Bedrock items with different properties to map to different item stacks with specific components.

How does it work?

"Custom" items in Java edition are based on vanilla items, with a modified appearance (using item models on 1.21.4+, or custom model data on older versions). Therefore, all mapped Bedrock custom item definitions are based on vanilla Java items and their components. Further, mapped definitions can specify additional components to modify the items' behavior.

Prerequisites: Vocabulary

  • Java item: Any vanilla item that exists in the Minecraft: Java Edition base game. Java datapacks / plugins can create custom items by overriding components of a Java item.
  • Java item component: On Java Edition since 1.21.4+, items have their properties and behavior defined using item components. Every Java item has a set of default components, which can be overridden to change how an item looks or functions.
  • Bedrock item component: Custom Bedrock items also have components that determine item behavior, similar to Java Edition. However, these components cannot be changed at runtime for item stacks and have to be pre-defined when the Bedrock client joins.
  • Java legacy custom model data: The system used before Java 1.21.4. Before 1.21.4, each "custom item" had a custom model data number, used to decide which model a Java item should use (= different texture for players).
  • Java item model definition: Introduced in Java 1.21.4, they are found in the assets/<namespace>/items/ directory of Java resource packs. These textures are used to set the appearance of Java items, and can be dynamically changed with a set of rules and item properties. Every Java item stores its item model definition in the minecraft:item_model item data component. It can be overridden on a per-item-stack-basis by a datapack/plugin to use a custom item model definition defined in a resource pack.
  • Custom item definition: a custom item definition is a Geyser term. It represents a single Bedrock custom item that is used to map a Java item model definition. It contains info on the item's properties on Java and Bedrock. Multiple custom item definitions, and thus multiple Bedrock items, can exist for the same Java item model definition, but for every combination of a Java item and Java item model definition, there can only be one custom item definition without predicates.
  • Non-vanilla custom item definition: also a Geyser term. Represents a Bedrock custom item that maps a Java non-vanilla (modded) item. Like normal custom item definitions, it contains info on the item's properties on Java and Bedrock. At the moment, there can only be one non-vanilla custom item definition per Java non-vanilla item.

Definitions

Every custom item definition represents one custom Bedrock item that has a specific set of pre-defined Bedrock options. It is tied to a specific Java item + item model combination (or, for legacy items, a specific Java item + custom model data combination).

Mandatory definition properties

  • bedrock_identifier: This identifier is used for the custom Bedrock item (and also in e.g. attachables in Bedrock resource packs), and cannot be shared with any other custom item definition. This identifier cannot be in the minecraft namespace. If no namespace is provided, geyser_custom is used.
  • model (or custom_model_data for legacy definitions in json mappings) is also required.

Optional definition properties

  • display_name: A string, or json text component for the item's default display name. If not set, it is derived from the bedrock identifier.
  • bedrock_options: The bedrock options that specify additional Bedrock properties
  • components: Java item components that specify item behavior, such as the maximum stack size.
  • predicate: Predicates used to match a specific custom item definition to an item stack.
  • predicate_strategy: Specifies how multiple predicates are evaluated. Only used when predicates are specified.
  • priority: Optionally specifies a priority of a definition over other definitions for the same item + item model combination. Only used when there are multiple custom item definitions.

Json mapping files have to specify the format_version set to 2, and list all definitions for each item under the items key. It holds an object in which keys are Java items, and in which each value is an array of objects, specifying custom item definitions for that Java item.

Example structure of a mappings.json mappings file:

{
"format_version": 2,
"items": {
"minecraft:flint": [
// definition
],
"minecraft:apple": [
// definition1,
// definition2
],
"minecraft:diamond": [
// definition
]
}
}

There are multiple types of custom item definitions:

  • definition: a single custom item, defined for a Java item model definition.
  • legacy: a single custom item, defined for a Java custom item making use of legacy custom model data numbers.
  • group: a group of custom item definitions. The type of a definition is defined in the type key.
{
"type": "definition",
"model": "example:example_model",
"bedrock_identifier": "example:example_item"
}

The definition type is used to map one definition for a specific item's item_model component value. This should be used for 1.21.4+ and above. For custom items using the legacy custom_model_data format, use the legacy type.

Expand to see examples of all definition types
{
"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
}
}
}
]
}
]
}
}

In this example, the Java item minecraft:flint has four mapped definitions:

  • The first is mapped using a "simple" definition for the geyser_mc:test_item model. Hence, it will always be used when Geyser encounters a flint item with the item_model component being set to the geyser_mc:test_item model.
  • The second is a "legacy" definition for the custom model data value of 42. Hence, if Geyser encounters a flint item with the first float value in the floats list set to 42, it will use the second definition. Such an item could be retrieved using the following command: /give @s flint[custom_model_data={floats:[42]}] 1
  • The third and fourth definition is part of a group type, which maps multiple definitions to minecraft:flint items with the geyser_mc:another_test_item item model to use under different conditions. Specifically, the third definition (with the bedrock identifier geyser_mc:another_test_item_nether) is used when the supplied dimension predicate matches the nether dimension. Otherwise, the fourth definition, which does not specify a predicate, is used.

Bedrock Options

These options allow configuring Bedrock-specific options that aren't represented by components. These include:

  • icon: Determines the icon to use for the item. If not set, the item's Bedrock identifier is used. This value corresponds to icon shorthands defined in the item_texture.json file.

    If the Bedrock item's identifier is used, the following changes are made:

    • : would be replaced with .
    • / with _

    Example: geyser_mc:a_cool_item -> geyser_mc.a_cool_item.

  • allow_offhand: Whether the custom item may be held / put into the offhand. Defaults to true.

  • display_handheld: Whether the item should be displayed handheld (e.g. for tools or weapons). Defaults to false.

  • protection_value: Determines how many armor protection points should be shown when this item is worn. This is purely visual, and only has an effect if the item is equippable. Defaults to 0.

  • creative_category: Sets the item's creative category (also shown in the recipe book). Can be none, construction, nature, equipment, or items. Defaults to none.

  • creative_group: Sets the item's creative group (for the recipe book). See here for a list of possible values. Creating custom creative groups is not currently supported by Geyser.

  • tags: Sets tags that an item has. These can be used for Molang expressions in resource packs.

info

A creative_category (and optionally creative_group) must be set if you have crafting recipes that output a custom item. Otherwise, Bedrock will not show recipes for custom items in the recipe book!

Expand for bedrock option examples
    "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"]
}

Components

Item components are used in Java Edition to customize how items function and behave. Java Edition allows modifying these for any item stack at runtime. This is, unfortunately, not a feature Bedrock Edition supports. Therefore, any modifications to the base Java item's data components must be specified in mapping files. It is expected that a custom item will always have these components sent by the server when the custom item definition is used. For different sets of components, multiple custom item definitions with predicates should be used.

info

You do not need to map components that are unchanged from the base Java item.

Adding or Modifying components

The following Java item components are supported (some with limitations):

  • minecraft:consumable: doesn't support consume particles/sounds.
  • minecraft:equippable: doesn't support the camera overlay or swappable properties.
  • minecraft:food
  • minecraft:max_damage
  • minecraft:max_stack_size
  • minecraft:use_cooldown
  • minecraft:enchantable
    • On Bedrock, this will be mapped to the minecraft:enchantable component with slot=all. This should, but does not guarantee, allow for compatibility with vanilla enchantments. Non-vanilla enchantments are unlikely to work.
  • minecraft:tool
  • minecraft:repairable
  • minecraft:enchantment_glint_override
  • minecraft:attack_range
    • Due to Bedrock limitations, only has an effect in combination with the minecraft:kinetic_weapon or minecraft:piercing_weapon components.
  • minecraft:kinetic_weapon
  • minecraft:piercing_weapon
  • minecraft:swing_animation
    • Due to Bedrock limitations, the actual animation played is hardcoded, only the duration of the animation can be changed.
  • minecraft:use_effects
    • Due to Bedrock limitations, the can_sprint property cannot be translated. Further, this component will only be translated when the base item is either able to shoot arrows, throw projectiles, or is edible (or made edible with the food component).

Some components, like minecraft:rarity and minecraft:attribute_modifiers, are already automatically translated and should not be listed.

For documentation of all item components and their respective json formats, see the item data component page on the Minecraft wiki.

Expand for component usage examples

All components listed follow the same json structure as would be used in datapacks, which are documented on the Minecraft wiki. Here are some examples:

"components": {
"minecraft:max_stack_size": 16,
"minecraft:enchantment_glint_override": true
}

Removing default components

Just as is possible on Java edition, default components of the base item can be removed (e.g. making non-edible apples).

Expand for usage examples of component removal

In Json mappings, this is done by adding an ! in front of the component.

"components": {
"!minecraft:food": {}
}

Predicates

Predicates are used to tell Geyser which custom item definition to use for a particular combination of Java item and item model. For simpler legacy mappings or custom items that don't have multiple component variants, predicates aren't required.

For each combination of a Java item and a Java item model definition, there can be one item definition without predicates, and one or multiple definitions with predicates. There cannot be multiple item definitions with the same predicates for the same Java item and Java item model definition. If the Java item model definition is in the minecraft namespace, there cannot be an item definition without a predicate.

info

Predicates can also be inverted to match for the inverse condition.

Condition predicates

The condition predicate type checks for a boolean property and returns true if the property matches the expected value. It has 5 possible properties:

  • broken: if the item is broken (has only 1 durability point left).
  • damaged: if the item is damaged (not at full durability).
  • custom_model_data: checks the item's custom model data flags at the index specified in the index key. Defaults to false.
  • has_component: if the item has the component set in the component key. Includes default components.
  • fishing_rod_cast: if the player is currently holding a cast fishing rod.
Expand for usage examples.

All condition predicate types must set the type to 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"
}

Components can also be inverted by adding and setting the expected key to false. If not set, it defaults to true. Example:

"predicate": {
"type": "condition",
"property": "broken",
"expected": false
}

Match predicates

The match predicate type checks for a text-like property and returns true if it matches the given value. It has 4 possible properties:

  • charge_type: the item currently charged in the crossbow (in the minecraft:charged_projectiles component). Can be arrow or rocket.
  • trim_material: the trim material (resource location) of this item.
  • context_dimension: the dimension (resource location) the player is currently in.
  • custom_model_data: fetches a string from the item's custom model data strings.

The match predicate requires a value to be specified in the value key.

Expand for usage examples.

All match predicate types must set the type to 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
}

Predicates can also be inverted by adding and setting the expected key to false. If not set, it defaults to true. Example:

"predicate": {
"type": "match",
"property": "context_dimension",
"value": "minecraft:the_end",
"expected": false
}

Range dispatch predicates

The range_dispatch predicate type checks for a numeric property and returns true if it is at or above the specified threshold. It has 4 possible types:

  • bundle_fullness: checks the item's bundle fullness. Returns the total weight of all items (in the minecraft:bundle_contents component).
    • This property cannot be normalized!
  • damage: checks the item's damage value. Can be normalized.
  • count: checks the item's count. Can be normalized.
  • custom_model_data: checks the item's custom model data float at the specified index. Defaults to 0.0.
    • This property cannot be normalized!

The range_dispatch predicate has 3 extra keys:

  • threshold: the threshold required to return true (required).
  • scale: the factor to scale the property value by before comparing it with the threshold. Defaults to 1.0.
  • normalize: if the property value should be normalized before scaling it and comparing it with the threshold. Defaults to false, only works for certain properties.
Expand for usage examples.
"predicate": {
"type": "range_dispatch",
"property": "count",
"threshold": 32
}

This predicate evaluates to "true" when the count is equal or above 32.

"predicate": {
"type": "range_dispatch",
"property": "count",
"normalize": true,
"threshold": 0.5
}

This predicate evaluates to "true" when the normalized count (count / max count; between 0 and 1) is equal to or higher than 0.5.

"predicate": {
"type": "range_dispatch",
"property": "count",
"threshold": 8,
"scale": 2
}

This predicate evaluates to "true" when the scaled count (count × 2) is greater than or equal to the threshold.

Using the custom_model_data range dispatch property requires specifying an index to check! Indexes start at 0 - to check the first element in the floats list, you have to set index to 0:

"predicate": {
"type": "range_dispatch",
"property": "custom_model_data",
"threshold": 3,
"index": 0
}

Predicate strategy for multiple predicates

There is also a predicate_strategy key, which can be and or or and defaults to and. This was inspired by the advancement requirement strategies, and decides if all predicates (and), or only one predicate (or) of an item definition has to match for it to be used.

Expand for usage examples.
"predicate": [
{
"type": "match",
"property": "context_dimension",
"value": "minecraft:the_end"
},
{
"type": "condition",
"property": "broken"
}
],
"predicate_strategy": "and"

This would require two conditions to both match for a specific custom item definition to be used.

info

When multiple predicates are specified using the API, it is important to list all predicates separately and use the provided predicates, where possible. Chaining predicates manually or creating custom predicates results in Geyser being unable to cache results!

Details

Do NOT do this:

    .predicate(ItemConditionPredicate.BROKEN.and(MatchPredicate.dimension(Identifier.of("the_end"))))

Do this:

    .predicate(ItemConditionPredicate.BROKEN)
.predicate(MatchPredicate.dimension(Identifier.of("the_end")))
.predicateStrategy(PredicateStrategy.AND)

These have the same result, but only the result of the latter can be cached by Geyser.

Sorting and Priority

Custom item definitions are automatically sorted so that the definitions' predicates are checked in a correct order when translating items. Specifically, Geyser sorts custom item definitions in this order:

  1. First custom item definitions with a higher priority value are sorted above definitions with lower ones.
  2. Custom item definitions with similar range dispatch predicates are sorted by their threshold, with higher thresholds going first.
  3. Custom item definitions with more predicates are sorted over definitions with less.

This system ensures that in most cases, item definitions with predicates are checked in proper order, no matter which order they are put in the mappings. In the few cases that Geyser does not sort definitions correctly (that will most likely occur when using multiple range_dispatch predicates, or using them in combination with other predicates), the priority key can be used to specify which definitions should be checked first.

If there is only one custom item definition for an item + item model combination, specifying priorities is not necessary!

Expand for usage examples.
"priority": 5

Resource Packs

Custom items also require a Bedrock Edition resource pack. Geyser does not generate or convert Java Edition resource packs into Bedrock Edition resource packs, so you will need to set it up manually! You can also try using Rainbow or other third-party converters.

Creating your own Bedrock Edition resource pack

  1. Setup a basic bedrock resource pack with a valid manifest. If you need help, you can find it here.
  2. Create a textures folder.
  3. In that folder, create an item_texture.json file, and put this in it:
{
"resource_pack_name": "YOUR_PACK_NAME",
"texture_name": "atlas.items",
"texture_data": {

}
}
  1. Inside texture_data, you can add your items. The texture name and path must match the Bedrock identifier (and/or icon) that you set in your mappings. For example, an item registered with the Bedrock identifier example:yummy_food would need the following entry:
"example:yummy_food": {
"textures": [
"textures/items/yummy_food"
]
}
  1. Then you need to put your textures inside the textures/items folder. Make sure to have it match the texture path that you specified in item_texture.json!

Further references:

Loading mappings and resource packs

This section assumes you already set up and configured Geyser so Bedrock players are able to connect. Further, the enable-custom-content config option in Geyser's config must be set to true for custom items to work!

  1. Find the custom_mappings folder created by Geyser. For plugin/mod versions of Geyser, it will be under plugins/Geyser-[platform]/custom_mappings (or config/Geyser-[platform]/custom_mappings). For Geyser-Standalone, it will be in the root folder.
  2. Place the mapping .json file into the folder. You can have multiple mapping files with different file names.
  3. Place the Bedrock edition resource pack into the packs folder.
  4. Restart the server.

Full Examples

The full Java Edition datapack + resource pack, as well as the relevant Geyser mappings and Bedrock resource pack can be found here.

Simple custom food item mapping
{
"format_version": 2,
"items": {
"minecraft:flint": [
{
"type": "definition",
"model": "geyser_mc:yummy_food",
"bedrock_identifier": "geyser_mc:yummy_food",
"display_name": "Yummy food!",
"components": {
"minecraft:consumable": {},
"minecraft:food": {
"nutrition": 5,
"saturation": 0.0
},
"minecraft:max_stack_size": 16
}
}
]
}
}
Not-yummy-food - group and dimension predicate example
    {
"format_version": 2,
"items": {
"minecraft:flint": [
{
"type": "group",
"model": "geyser_mc:not_so_yummy_food",
"definitions": [
{
"bedrock_identifier": "geyser_mc:not_so_yummy_food",
"display_name": "Not so yummy food",
"components": {
"minecraft:consumable": {
"consume_seconds": 5.0
},
"minecraft:food": {
"nutrition": 2,
"saturation": 0.7
}
}
},
{
"bedrock_identifier": "geyser_mc:not_so_yummy_food_end",
"display_name": "Not so yummy food",
"predicate": {
"type": "match",
"property": "context_dimension",
"value": "minecraft:the_end"
},
"components": {
"minecraft:consumable": {
"consume_seconds": 5.0
},
"minecraft:food": {
"nutrition": 2,
"saturation": 0.7
}
}
}
]
}
]
}
}
Magic item (consumable with cooldown)
    {
"format_version": 2,
"items": {
"minecraft:flint": [
{
"type": "definition",
"model": "geyser_mc:magic_item",
"bedrock_identifier": "geyser_mc:magic_item",
"display_name": "Magic item",
"components": {
"minecraft:consumable": {
"consume_seconds": 0.05,
"animation": "none"
},
"minecraft:use_cooldown": {
"seconds": 5.0,
"cooldown_group": "geyser_mc:magic_item"
}
}
}
]
}
}
Flint pickaxe (broken-state predicate)
    {
"format_version": 2,
"items": {
"minecraft:flint": [
{
"type": "group",
"model": "geyser_mc:flint_pickaxe",
"definitions": [
{
"bedrock_identifier": "geyser_mc:flint_pickaxe",
"display_name": "Flint Pickaxe",
"bedrock_options": {
"display_handheld": true
},
"components": {
"minecraft:max_damage": 10,
"minecraft:max_stack_size": 1
}
},
{
"bedrock_identifier": "geyser_mc:flint_pickaxe_broken",
"display_name": "Flint Pickaxe",
"bedrock_options": {
"display_handheld": true
},
"predicate": {
"type": "condition",
"property": "broken"
},
"components": {
"minecraft:max_damage": 10,
"minecraft:max_stack_size": 1
}
}
]
}
]
}
}
Red wool chestplate (equippable armor)
{
"format_version": 2,
"items": {
"minecraft:flint": [
{
"type": "definition",
"model": "geyser_mc:red_wool_chestplate",
"bedrock_identifier": "geyser_mc:red_wool_chestplate",
"display_name": "Red Wool Chestplate",
"bedrock_options": {
"protection_value": 5
},
"components": {
"minecraft:equippable": {
"slot": "chest"
},
"minecraft:max_stack_size": 1
}
}
]
}
}

Non-vanilla items

Geyser also supports registering non-vanilla items (available on modded servers, such as Fabric/NeoForge), which are not based on vanilla items and require a modded Java client to join. These must be registered through the API, and cannot be registered with Json mappings.

Example:

event.register(NonVanillaCustomItemDefinition.builder(Identifier.of("hydraulic_test_mod:irauri_ingot"), 99)
.component(JavaItemDataComponents.MAX_STACK_SIZE, 3)
.component(JavaItemDataComponents.CONSUMABLE, JavaConsumable.builder()
.consumeSeconds(2.5f)
.animation(JavaConsumable.Animation.NONE)
.build())
.component(JavaItemDataComponents.USE_COOLDOWN, JavaUseCooldown.builder()
.seconds(999999f)
.cooldownGroup(Identifier.of("hydraulic_test_mod:irauri_says_fly"))
.build())
.build());

Notable differences however are the following:

  • The Java item id which is sent over the network must be provided in the NonVanillaCustomItemDefinition#builder method
  • Predicates, predicate strategies, and priority are not supported
  • Non-vanilla items can use additional components, which would otherwise be inherited from vanilla base items.

The GeyserItemDataComponent class contains all additional components available for modded items:

  • chargeable: Allows creating custom shooter items
  • attack_damage: Allows placing a visual indicators for the item's attack damage.
  • block_placer: Indicates that the item is able to place blocks
  • throwable: Indicates that the item is throwable
  • projectile: Marks a custom item as a projectile to make these usable for custom shooter items
  • entity_placer: Notes that an item is able to place entities