Handling Item Drop with Loot Tables

Following the last chapter, we are going to implement item drop for our newly created block. The good news is there won't be any Java coding in this chapter, and we will only be writing JSON files.

Basic Item Drop

basic loot table

Let's start with the most basic case. We want the block to drop an item of itself when mined. This is the same behavior as iron ore or gold ore in game.

We are going to update the src/main/resources folder:

src/main/resources
├── assets
│   └── ...
├── data
│   └── examplemod
│       └── loot_tables
│           └── blocks
│               └── copper_ore.json*
├── META-INF
│   └── mods.toml
└── pack.mcmeta

filenames with a * next to them are ones added or modified


Inside copper_ore.json, we are going to ask it to drop one copper_ore item:

loot_tables/blocks/copper_ore.json

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "examplemod:copper_ore"
        }
      ]
    }
  ]
}

Crash course on loot tables

Here's a quick attempt in explaining what's going on. In short, a loot table is made up of pools which you can think of as individual dice that can be rolled.

In the example above, we have only one pool or one dice:

{
  "rolls": 1,
  "entries": [
    {
      "type": "minecraft:item",
      "name": "examplemod:copper_ore"
    }
  ]
}

The rolls attribute is quite self-explanatory as it defines the number of times the dice is rolled.

The entries attribute defines the various faces of the dice. In our case, there's only one face that is a copper_ore item.

So, what the loot table above describes is that whenever a player breaks a copper ore, we roll a one-sided dice once (don't know how that's possible irl...) and as expected, drops a copper ore item every single time.

More loot!

Let's go a bit more advanced and try to increase the number of copper ore the block drops.

Attempt #1

The most obvious solution is to just roll the same dice a few more times:

loot_tables/blocks/copper_ore.json

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 3,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "examplemod:copper_ore"
        }
      ]
    }
  ]
}

+ indicate added lines / - indicate deleted lines

In this case, we get 3 copper_ore when breaking one block.

We can also make the rolls count random by specifying a range:

"rolls": {
  "min": 1,
  "max": 10
}

Attempt #2

Another way we can approach this is to redefine what's on the face of the dice.

loot_tables/blocks/copper_ore.json

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "examplemod:copper_ore",
          "functions": [
            {
              "function": "set_count",
              "count": 3
            }
          ]
        }
      ]
    }
  ]
}

Here we added a function to our entry to set the count and the outcome is the same as before. We get 3 items per block.

And the similarity continues, we can also set the count to a range:

"count": {
  "min": 1,
  "max": 10
}

Dealing with enchantments

Fortune

If you try to mine our copper ore block with a fortune pickaxe right now, the item drop would not change. To fix this, we need to add some more to our loot table:

loot_tables/blocks/copper_ore.json

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "examplemod:copper_ore",
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 1,
                "max": 3
              }
            },
            {
              "function": "minecraft:apply_bonus",
              "enchantment": "minecraft:fortune",
              "formula": "minecraft:uniform_bonus_count",
              "parameters": {
                "bonusMultiplier": 1
              }
            }
          ]
        }
      ]
    }
  ]
}

Here the apply_bonus function handles the fortune enchantment and the bonusMultiplier can be used to control how much more items would be dropped.

If you what to mimic the vanilla game as close as possible, there's also a ore_drops formula for you to use:

{
  "function": "minecraft:apply_bonus",
  "enchantment": "minecraft:fortune",
  "formula": "minecraft:ore_drops"
}

Silk Touch

This doesn't apply to our block currently, but let's implement it anyways. We want the block to drop copper ingots (added in this chapter) when mining using a normal pickaxe, and only drop the copper ore item when a silk touch pickaxe is used.

Here's how we would do it:

loot_tables/blocks/copper_ore.json

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:item",
              "name": "examplemod:copper_ore",
              "conditions": [
                {
                  "condition": "minecraft:match_tool",
                  "predicate": {
                    "enchantments": [
                      {
                        "enchantment": "minecraft:silk_touch",
                        "levels": {
                          "min": 1
                        }
                      }
                    ]
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "name": "examplemod:copper",
              "functions": [
                {
                  "function": "set_count",
                  "count": {
                    "min": 1,
                    "max": 3
                  }
                },
                {
                  "function": "minecraft:apply_bonus",
                  "enchantment": "minecraft:fortune",
                  "formula": "minecraft:uniform_bonus_count",
                  "parameters": {
                    "bonusMultiplier": 1
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

There are two things to note here. First, we defined a face with the type minecraft:alternatives. What this does is to have a list of potential entries and return the first one from top to bottom.

The two entries here are either a copper_ore or a copper:

{
  "type": "minecraft:item",
  "name": "examplemod:copper_ore",
  "conditions": [
    {
      "condition": "minecraft:match_tool",
      "predicate": {
        "enchantments": [
          {
            "enchantment": "minecraft:silk_touch",
            "levels": {
              "min": 1
            }
          }
        ]
      }
    }
  ]
},
{
  "type": "minecraft:item",
  "name": "examplemod:copper",
  "functions": [
    {
      "function": "set_count",
      "count": {
        "min": 1,
        "max": 3
      }
    },
    {
      "function": "minecraft:apply_bonus",
      "enchantment": "minecraft:fortune",
      "formula": "minecraft:uniform_bonus_count",
      "parameters": {
        "bonusMultiplier": 1
      }
    }
  ]
}

The first case will be valid only if the match_tool condition is met; otherwise, it falls through to the second case and we get our copper.

Closing and other resources

Hope this chapter can help you get started with writing loot tables and give you an idea of what's possible.

The minecraft wiki has a great page on how to write more complex loot tables. Do give it a read if you want to dive even deeper.

There are also loot table generators out there if you are feeling lazy.

See you in the next chapter where we are going to make crafting recipes and handle smelting.

results matching ""

    No results matching ""