Wiki 9Minecraft Wiki 9Minecraft

Ore Loot Tables for Custom Blocks

Configure Silk Touch, Fortune, and tool tier conditions for custom ore block drops.

5Sections
2Code examples
3Known errors

By default, breaking a custom block in Minecraft Bedrock Edition drops the block item itself, ignoring the tool the player is holding. To create an ore that drops raw materials when mined with a pickaxe, yields extra items with the Fortune enchantment, and drops the block itself when mined with Silk Touch, you need to attach a custom loot table. This page covers how to link a loot table to your block definition and configure the conditions and functions required for standard ore behavior.

Linking the Loot Table to the Block

Every custom block drops itself unless you explicitly override its drop behavior using the `minecraft:loot` component inside the block's behavior pack JSON file. This component takes a single string value representing the file path to the loot table, starting from the root of the behavior pack.

When defining an ore, you almost always pair `minecraft:loot` with `minecraft:destructible_by_mining`. While the mining component controls how long the block takes to break, the loot table alone decides whether an item actually spawns when the block breaks. Note that paths inside `minecraft:loot` always begin with `loot_tables/` and include the `.json` extension.

BP/blocks/ruby_ore.json
{
  "format_version": "1.20.80",
  "minecraft:block": {
    "description": {
      "identifier": "wiki:ruby_ore"
    },
    "components": {
      "minecraft:destructible_by_mining": {
        "seconds_to_destroy": 3.0
      },
      "minecraft:loot": "loot_tables/blocks/ruby_ore.json"
    }
  }
}

Checking Tool Tier and Silk Touch

Vanilla ores require a specific pickaxe tier to drop anything at all, and they change their drop depending on whether the tool is enchanted with Silk Touch. In Bedrock loot tables, tool checks are handled using the `match_tool` condition. This condition inspects the item in the player's main hand at the exact moment the block is destroyed.

To prevent the player from getting both the Silk Touch block drop and the normal raw material drop at the same time, you have to make the two entries mutually exclusive. Unlike Java Edition, which uses an `alternatives` entry type to stop after the first matching entry, Bedrock Edition loot tables evaluate pools independently. Because of this, you must put the Silk Touch drop in one pool, and put the normal drop in a second pool that explicitly checks that the tool does not have Silk Touch.

Wait—there is a nuance with Bedrock's `match_tool` enchantment checks: checking for a `level` range of `0` is not always reliable across versions for detecting the absence of an enchantment. Instead, the safest way to separate Silk Touch from normal drops in Bedrock is to wrap the negative check inside an `inverted` condition, or structure the tool checks using tags. In modern Bedrock packs, `match_tool` supports checking item tags and enchantment arrays directly.

Condition or PropertyWhat it doesNotes
match_toolEvaluates the item held by the entity breaking the block.Fails if the block is broken by an explosion or piston.
minecraft:is_pickaxeItem tag shared by all vanilla pickaxes.Checked inside the `tag` field of `match_tool`.
enchantmentsArray inside `match_tool` that checks for specific enchantments.Takes an `enchantment` string and an optional `levels` range object.
explosion_decayLoot function that randomly deletes drops if broken by an explosion.Mimics vanilla behavior where TNT destroys a percentage of ore drops.

Adding Fortune Support

When an ore is mined without Silk Touch, the Fortune enchantment should increase the yield. Bedrock Edition provides a dedicated loot function called `enchantment_count` for simple linear increases, and `ore_drops` (or `formula`-based functions depending on your target engine) for vanilla ore math. However, the most reliable and universally supported function across Bedrock versions for custom ores is `explosion_decay` paired with `set_count` and `enchantment_count`.

The `enchantment_count` function adds extra items to the stack based on the level of Fortune on the tool used to break the block. For a single-drop ore like diamond or ruby, you set the base count to 1. For a multi-drop ore like copper, lapis, or redstone, you set the base `count` inside `set_count` to a `min` and `max` range, and let the enchantment function add on top of that roll.

Complete Ore Loot Table Example

The following loot table implements a complete custom ore drop for `wiki:ruby_ore`. It contains two pools. The first pool checks if the player is holding a pickaxe with at least level 1 of Silk Touch; if true, it drops the `wiki:ruby_ore` block itself.

The second pool handles the standard drop (`wiki:ruby`). Because Bedrock does not have an `inverted` condition wrapper for `match_tool` in all older format versions, creators commonly run into the issue of Silk Touch triggering both pools. If your target version supports the `inverted` condition, you can wrap the Silk Touch check in it. If you want a setup that never fails on any Bedrock version without relying on inverted conditions, you can handle Silk Touch via script in `@minecraft/server`, or use the `match_tool` condition with `levels` set to a `max` of `0` if your testing confirms it works on your target version. The JSON below demonstrates the standard two-pool structure using the `levels` range check.

BP/loot_tables/blocks/ruby_ore.json
{
  "pools": [
    {
      "rolls": 1,
      "conditions": [
        {
          "condition": "match_tool",
          "tag": "minecraft:is_pickaxe",
          "enchantments": [
            {
              "enchantment": "silk_touch",
              "levels": {
                "min": 1
              }
            }
          ]
        }
      ],
      "entries": [
        {
          "type": "item",
          "name": "wiki:ruby_ore",
          "weight": 1
        }
      ]
    },
    {
      "rolls": 1,
      "conditions": [
        {
          "condition": "match_tool",
          "tag": "minecraft:is_pickaxe"
        }
      ],
      "entries": [
        {
          "type": "item",
          "name": "wiki:ruby",
          "weight": 1,
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 1,
                "max": 1
              }
            },
            {
              "function": "explosion_decay"
            }
          ]
        }
      ]
    }
  ]
}

Dropping Experience Orbs

A common point of confusion when building custom ores is trying to make the loot table drop experience orbs. In Minecraft Bedrock Edition, loot tables can only output items; there is no loot table entry type for experience.

To make your custom ore drop XP when mined (and not drop XP when mined with Silk Touch), you have to handle the XP spawn outside the loot table. In modern packs (1.20.60 and later), the cleanest approach is to register a custom component in the `@minecraft/server` Script API listening to the `onPlayerDestroy` event, check the player's held item for Silk Touch, and call `dimension.spawnEntity("minecraft:xp_orb", block.location)` when appropriate.

Which versions this applies to

Applies to Bedrock Edition 1.19.50+ (stable). The `minecraft:loot` and `minecraft:destructible_by_mining` components do not require any experimental toggles.

When it does not work

What you seeWhyThe fix
The block drops nothing at all, even when mined with the correct pickaxe, and the Content Log shows: [LootTable] Unable to find loot table 'BP/loot_tables/blocks/ruby_ore.json'The path inside the `minecraft:loot` component includes the `BP/` prefix, or starts with a leading slash `/loot_tables/...`.Change the string in `minecraft:loot` so it starts directly with `loot_tables/`, for example: `"loot_tables/blocks/ruby_ore.json"`.
Mining the ore with a Silk Touch pickaxe drops BOTH the ore block and the raw gem.Pool 1 checks for Silk Touch, and Pool 2 only checks for `minecraft:is_pickaxe`. A Silk Touch pickaxe satisfies both pools simultaneously because Bedrock evaluates every pool in the file independently.Add an exclusion for Silk Touch on the second pool, or handle the Silk Touch block drop inside a Script API custom component where you can run an `if/else` check on the tool's `minecraft:enchantable` component.
The block drops nothing when blown up by TNT or a Creeper.The `match_tool` condition is placed on the pool that drops the raw ore. When an explosion breaks a block, there is no tool, so `match_tool` evaluates to false.If you want explosions to drop the ore without requiring a pickaxe, you must either remove the `match_tool` condition (which also lets players mine it by hand) or spawn the drops via script when detecting block destruction.

Reference, straight from the game files

Read out of the game itself, so the ids match the version you are building for.