Wiki 9Minecraft Wiki 9Minecraft

Adding Loot Tables, Spawn Rules, and Crafting Recipes

Connect your custom entities, items, and blocks to survival gameplay using behavior pack JSON files.

5Sections
3Code examples
4Known errors

Creating custom blocks, items, and entities is only half the work of making a survival-friendly add-on; players also need a way to encounter, harvest, and craft your content. In Minecraft Bedrock, this integration is handled entirely inside the behavior pack using three data-driven systems: loot tables, spawn rules, and crafting recipes. You reach for these files whenever you want a custom mob to appear naturally in the Overworld, drop specific items on death, or allow players to turn those drops into new gear at a crafting table.

Where the Files Live in Your Behavior Pack

All three systems live strictly inside your behavior pack (often abbreviated as BP). Unlike entities or blocks, which require paired definitions in both the behavior pack and the resource pack, loot tables, spawn rules, and recipes are pure server-side logic. The game discovers them automatically by scanning specific directories when a world loads.

Folder naming is strict. Loot tables must sit inside BP/loot_tables/, spawn rules go into BP/spawn_rules/, and recipes belong in BP/recipes/. You can organize files into subfolders within those directories—for example, separating mob drops from chest loot inside BP/loot_tables/entities/ and BP/loot_tables/chests/—and the engine will still parse every JSON file it finds. The only system where the exact file path matters after loading is loot tables, because components reference them by their relative path string rather than an internal identifier.

Creating and Hooking Up a Loot Table

A loot table is a JSON file that defines a list of pools. When the game evaluates a loot table—whether because an entity died, a block was broken, or a player opened a generated chest—it runs through each pool in the array, determines how many times to roll that pool, and picks entries based on their relative weight. Unlike most other Bedrock JSON files, loot tables do not have a format_version key or a top-level identifier block; they begin directly with the pools array.

Within a pool, the entries array holds the actual results. An entry of type item names a specific item identifier to drop, while an entry of type empty acts as a blank weight so a roll can deliberately yield nothing. To vary stack sizes or respond to enchantments, you attach a functions array to an entry. Functions modify the chosen item stack before it spawns in the world. The two most common functions are set_count, which chooses a stack size between a minimum and maximum, and looting_enchant, which adds extra items per level of the Looting enchantment on the weapon that killed the mob.

FieldWhat it doesNotes
rollsSets how many times the game picks from this pool.Can be a fixed integer or an object with min and max keys.
weightDetermines the probability of an entry being picked relative to other entries in the same pool.In the example above, the claw has a 3-in-4 (75%) chance per roll.
set_countSets the stack size of the dropped item.Applied inside the entry's functions array.
looting_enchantIncreases stack count when an entity is killed using a Looting weapon.Has no effect when the loot table is triggered by a broken block.
BP/loot_tables/entities/crab_claw_drops.json
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "item",
          "name": "myaddon:crab_claw",
          "weight": 3,
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 1,
                "max": 2
              }
            },
            {
              "function": "looting_enchant",
              "count": {
                "min": 0,
                "max": 1
              }
            }
          ]
        },
        {
          "type": "empty",
          "weight": 1
        }
      ]
    }
  ]
}

Attaching the Loot Table to an Entity or Block

Writing the file in BP/loot_tables/ does nothing until a block or entity points to it. You link the table using the minecraft:loot component inside an entity's components group (or a block's components block). The table field takes a string starting with loot_tables/ that matches the exact path and filename inside your behavior pack.

For example, to attach the file created in the previous section to a custom entity, add {"minecraft:loot": {"table": "loot_tables/entities/crab_claw_drops.json"}} to the entity's behavior file. Always include the .json file extension in the path string. If you want to replace a vanilla mob's drops without editing its entity file, you can simply place a file in your pack that mirrors the vanilla path, such as BP/loot_tables/entities/zombie.json, and your file will override the built-in table.

Defining Natural Spawn Rules

For a custom mob to appear naturally in the world without spawn eggs or commands, it needs a spawn rule file in BP/spawn_rules/. Also check your entity's behavior file first: inside its description block, the is_spawnable boolean must be set to true, or the spawn engine will ignore your rule file completely. A spawn rule file uses format_version 1.8.0 (the standard stable version for spawn rules across modern Bedrock) and contains a description object and a conditions array.

The description.identifier must exactly match the identifier of the entity you want to spawn. The description.population_control field puts your mob into one of the game's global mob caps—typically animal for passive creatures, monster for hostile mobs, water_animal for aquatic life, or ambient for creatures like bats. If that cap is currently full in the area around the player, your mob will not spawn until existing mobs despawn or are killed.

The conditions array lists one or more sets of requirements. For a mob to spawn at a given coordinate, every component inside a single condition block must pass at the same time. You combine surface checks, light level filters, weight, herd size, and biome filter tests here. The minecraft:biome_filter component works just like standard entity filters, testing biome tags such as monster, animal, ocean, or beach so your mob only appears in appropriate environments.

Condition ComponentWhat it doesNotes
minecraft:spawns_on_surfaceAllows the mob to spawn on the highest solid block open to the sky.Pair with minecraft:spawns_underground if you also want cave spawns.
minecraft:brightness_filterRestricts spawning to light levels between min and max (0 to 15).Hostile mobs typically use min 0 and max 7; passive mobs use min 7 and max 15.
minecraft:weightSets how frequently this mob is chosen compared to other mobs in the same biome and cap.Higher numbers mean more frequent spawns.
minecraft:herdDetermines how many mobs attempt to spawn together in a single cluster.Set min_size and max_size to control group sizes.
minecraft:biome_filterChecks tags on the biome at the candidate spawn spot.Uses standard filter syntax with test, operator, and value.
BP/spawn_rules/crab.json
{
  "format_version": "1.8.0",
  "minecraft:spawn_rules": {
    "description": {
      "identifier": "myaddon:crab",
      "population_control": "animal"
    },
    "conditions": [
      {
        "minecraft:spawns_on_surface": {},
        "minecraft:brightness_filter": {
          "min": 7,
          "max": 15,
          "adjust_for_weather": false
        },
        "minecraft:weight": {
          "default": 10
        },
        "minecraft:herd": {
          "min_size": 2,
          "max_size": 4
        },
        "minecraft:biome_filter": {
          "test": "has_biome_tag",
          "operator": "==",
          "value": "beach"
        }
      }
    ]
  }
}

Adding Shaped and Shapeless Crafting Recipes

Crafting recipes live in BP/recipes/ and let players create your custom items or blocks, or use your custom items to craft vanilla items. The two primary recipe types for crafting tables are minecraft:recipe_shaped, where the exact grid arrangement matters, and minecraft:recipe_shapeless, where only the combination of ingredients counts. In modern Bedrock (format_version 1.20.10 and newer), recipes also require an unlock block, which tells the recipe book when to reveal the recipe to the player in survival mode.

A shaped recipe uses a pattern array of up to three strings, each up to three characters long, representing rows on a 3x3 crafting grid. Spaces in the string represent empty slots. The key object maps each character used in the pattern to an item identifier. The tags array controls which crafting stations can process the recipe: use crafting_table for 3x3 recipes. If your pattern fits inside a 2x2 grid and you want players to craft it in their inventory as well, include both crafting_table and player in the tags array, or rely on crafting_table which covers standard table crafting.

For a shapeless recipe, replace the top-level key with minecraft:recipe_shapeless, remove pattern and key, and instead provide an ingredients array containing item objects (each with an item key and an optional count key). Everything else—including description, unlock, tags, and result—works the same way.

BP/recipes/crab_shell_helmet.json
{
  "format_version": "1.20.10",
  "minecraft:recipe_shaped": {
    "description": {
      "identifier": "myaddon:crab_shell_helmet"
    },
    "tags": [
      "crafting_table"
    ],
    "pattern": [
      "CCC",
      "C C"
    ],
    "key": {
      "C": {
        "item": "myaddon:crab_claw"
      }
    },
    "unlock": [
      {
        "item": "myaddon:crab_claw"
      }
    ],
    "result": {
      "item": "myaddon:crab_helmet",
      "count": 1
    }
  }
}

Which versions this applies to

Applies to stable Minecraft Bedrock 1.20.10 and newer. Loot tables, spawn rules (using format_version 1.8.0), and crafting recipes are fully stable features and do not require any experimental toggles to be enabled on the world.

When it does not work

What you seeWhyThe fix
Content Log shows: [Recipes][error]-recipe_shaped | myaddon:crab_shell_helmet | recipe is missing required field 'unlock'Starting in format_version 1.20.10, recipes require an unlock array so the survival recipe book knows which item unlocks the recipe.Add an "unlock" array to your recipe listing at least one item object (such as the primary ingredient), or set "unlock": {"context": "AlwaysUnlocked"}.
Your custom entity dies or your custom block breaks, but nothing drops and no error appears in the Content Log.The path string inside the entity's or block's "minecraft:loot" component includes the "BP/" prefix, omits the ".json" extension, or has a typo that does not match the actual file location.Ensure the "table" string starts directly with "loot_tables/" and ends with ".json", for example: "loot_tables/entities/crab_claw_drops.json".
Your custom mob works when summoned with /summon or a spawn egg, but never spawns naturally in the world.Either "is_spawnable" is set to false in the entity's behavior file description, or the "identifier" inside BP/spawn_rules/ does not exactly match the entity's identifier.Verify that "is_spawnable": true is set in the entity JSON, and check that description.identifier in your spawn rule file matches the entity's namespace and name character for character.
A crafting recipe does not show up at the crafting table even after obtaining the unlock item.The "tags" array is missing "crafting_table", or two different recipe files share the exact same "description.identifier".Make sure "tags": ["crafting_table"] is present in the recipe JSON and give every recipe file a unique identifier within your namespace.

Reference, straight from the game files

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