How to make a Minecraft Datapack
Datapacks are a Minecraft feature that lets you customize Minecraft worlds without mods. They allow you to modify and enhance the game by adding new features and mechanics by using Minecraft commands, advancements, worldgen, and more! This guide will walk you through the process of creating your first Minecraft datapack from scratch in the latest version.
info
If you don’t know what datapacks are, then take this explanation. Datapacks are essentially add-ons to Minecraft which can change the game, whether by adding a simple game mechanic, or creating completely new experiences! The best part is that they’re really easy to create, even if you have little coding knowledge
This guide will help you to create your first datapack, whether you’ve never tried coding before or if you’ve got loads of experience. The process of coding a datapack is a bit different to other typical programs. By the end of this tutorial, you’ll have made a simple datapack which makes arrows explode when they land!
Prerequisites
Minecraft Datapacks basically just consist of text files inside folders. For this reason, you can technically make a datapack with just the default text editor and a file explorer. However, if you are able to, we highly suggest downloading a code editor such as Visual Studio Code.
With VS Code, you will be able to view errors in your datapack, autocomplete commands, and highlight syntax with different colours so that making datapacks isn’t as painful as using Notepad.
- Download Visual Studio Code: https://code.visualstudio.com/download
- Get the VS Code extensions for datapack development: https://marketplace.visualstudio.com/items?itemName=amandin.dpc-pack
info
If you prefer not to download programs, then you can use a web version of Visual Studio Code which essentially has all the same features, except it can be slower or more difficult to work with. https://vscode.dev/
Setting up an empty datapack
The first step when creating a datapack is to make a new world to test it
in. Go ahead and do that now - make sure that your world has cheats enabled and it is set to creative mode. In the world, you will need to run the /datapack create command -
it will create your datapack folder as well as the necessary metadata for you, which saves you a bunch of time.
For example, to make a datapack with the ID ExampleDatapack and the
description “This is an example datapack”, you would run the following command:
/datapack create ExampleDatapack "This is an example datapack" Once you’ve created your empty datapack, the next step is to find and open the world folder:
- Save and quit your world
- Go to your world in the Singleplayer menu and hit “Edit”
- Press “Open World Folder”
The folder that opens contains your Minecraft world’s data. There will be loads of subfolders in
this folder: find the one which is called datapacks, and open it. This folder is where the world’s datapacks are stored. If you used /datapack create, you should see your datapack’s folder here already. (If not, you’ll have to create it yourself. This is explained in the “NOTE” box below)
tip
If you are using Visual Studio Code, at this point you should open it, find Open Folder, and open the newly created folder. Navigating through your
datapack will be so much easier! 
The datapack folder will contain pack.mcmeta and a folder called data. pack.mcmeta tells Minecraft that the folder is a datapack,
as well as containing the basic information about the pack, such
as what versions it works in. /datapack create made this file automatically, but you can open the file like normal and view it if you want:
{
"pack": {
"description": "This is an example datapack",
"pack_format": 88
}
} If you’re interested, here’s what this file means:
packis an object containing the metadata of the file.descriptionis the name of your datapack, usually along with a short description of what your pack does.pack_formattells Minecraft what versions this datapack works in.88(or 88.0) is the latest for 1.21.10
note
If you’re in a version earlier than 1.21.6, you may notice that /datapack create doesn’t
exist. You will have to create your datapack folder (inside datapacks) yourself. Just make
a folder, and then inside that folder, create pack.mcmeta (as shown above) and the data folder.
Writing your first function
info
What are functions? In short, functions are the majority of what makes up most datapacks. A function is a file containing Minecraft commands. When a function is ran, every command in the function is ran in order. Functions are always ran as an entity (or as the Server) and at a position
Let’s get started by writing one simple function. In traditional programming fashion, let’s make a function which sends “Hello World” to chat.
- Open your empty
datafolder. - In the
datafolder, create a new folder. This folder is your namespace - it will contain all the data specific to your datapack. Usually this needs to have a unique name (one which other people would not have picked), but for this tutorial just call itexample. - In the
examplefolder, create a folder calledfunction. This folder will contain all the .mcfunction files.
You should now have a folder structure that looks something like this:
/world/datapacks/ExampleDatapack/data/example/function warning
In versions earlier than 1.21, the function folder should be called functions,
due to some pesky name changes Mojang introduced in a recent update.
Once you’re sure that’s correct, you can start writing the actual function.
In the function folder, create an empty text file called hello_world.mcfunction.
Open this file with any text editor (we recommend Visual Studio Code)
Inside hello_world.mcfunction, put the following:
# Show the player Hello World on their screen
title @s title "Hello World!"
# Give the player a diamond
give @s diamond info
Commands in functions shouldn’t have the default slash / symbol which in-world
commands have! Having the / before a command will make the mcfunction invalid
and fail when it tries to run
It’s that simple! Once you save that file, and then run /reload (or if that doesn’t work, rejoin your world), you should be able to use the following command to run the function:
/function example:hello_world What’s next?
Now you know how to create a basic function and run it, we’ll next start to think about how to create our project. For more advanced projects, this can sometimes be the most difficult part. Luckily for us, what we want to create won’t be too difficult.
Let’s break down the idea into smaller steps. Remember, we want to create a datapack which makes arrows explode.
- Detect when an arrow lands on the ground. We can do this by running a command on a loop which will select any arrow on the ground and then run a function.
- Create an explosion. This is as simple as summoning a TNT at the position of the arrow.
- Remove the arrow. If you don’t do this, then it will keep on exploding forever.
The next steps of this guide will guide you through the typical process of each of those steps.
Running functions on a loop
The first step on our list is to detect arrows which land on the ground. To do this, we need to run a command on a loop. Luckily, Minecraft makes this pretty easy for us.
Firstly, let’s make the function which you want to run on a loop. In the function folder, create a new mcfunction file - call this one loop.mcfunction.
For now, let’s just make it say “Hi” every time it loops. You can do this by putting this in the new function:
say Hi To make this function run on a loop, we need to create a JSON file which tells Minecraft “run this command every tick” (every tick = 20 times per second)
- In the
datafolder, create theminecraftfolder. - In the
minecraftfolder, create atagsfolder - In the
tagsfolder, create afunctionfolder - In the new
functionfolder, create a new text file:tick.json
The final path would look like this:
/world/datapacks/ExampleDatapack/data/minecraft/tags/function/tick.json tick.json is NOT a function. In tick.json, we are going to put a list
of functions which we want to run every tick. If you put any commands in
tick.json, it will break your pack.
In tick.json, put the following:
{
"values": ["example:loop"]
} valuesis a list of function references which will be run on a loop.example:loopis a reference to theloop.mcfunctionfile we created earlier.examplerefers to the namespace (the folder indata), andlooprefers to the mcfunction file name.
If you save this file, go back to your world, and run /reload, you should see
that the chat is being spammed with “Hi” over and over again!
Selecting the arrows
Now we’ve created a function which will run infinitely on a loop, we can move on to detecting when an arrow is in the ground.
As far as the game is concerned, an arrow is an entity, just like a pig, cow or zombie. Minecraft gives us a special way to select any types of entities with target selectors. Once we’ve selected an entity, we can use the /execute command to run a command as the entity.
We can use these to select all arrows which are in the ground, and then run a command to make them explode (and then remove themselves).
As mentioned, to select an entity, we need to use a target selectors. I’m going to teach you a bit about target selectors. You should pay attention here, but if you only want the code, scroll past this section.
What are target selectors?
Target selectors are a special bit of code we can use to find an entity in the
world. They all start with an @ symbol. There are 6 base target selectors:
| Target Selector | Description |
|---|---|
@e | All Entities - By itself, this selector will select every single entity which is currently loaded in the world. |
@s | This Entity - This selector will select the entity which is currently running the command. For example, if I run a command as @s, then it will run the commands as me. |
@a | All Players - This selects all currently online players. (All players are always loaded in the world). |
@r | Random Player - This selects one random player. |
@p | Nearest Player - This selects the nearest player to the position this command is ran from. |
@n | Nearest Entity - This selects the nearest entity (player or non-player) to the position this command is ran from. |
On it’s own, a base target selector (like in the table) does not do much. We can narrow down the selection even more by using criteria. Criteria are put in square brackets after the base selector.
For example, we can use @e with a type criteria to select all entities of a
certain type - for example, @e[type=minecraft:cow] would select all cow
entities.
I’m not going to explain every single criteria you can use - you can view a list here. These are the basic ones which you might see quite often:
| Criteria | Description |
|---|---|
[type=minecraft:arrow] | Entity Type - This criteria will narrow down the selection to only include entities of a certain type. For good pack optimisation, you should use this often. |
[distance=..5] | Distance to entity - This criteria will only include entities based on their distance to their distance to the current position. .. can be used to represent a greater/less than symbol - for example, ..5 means less than 5 blocks away. |
[limit=2] | Limit selection - Using the limit criteria, you can make specify a max amount of entities to be selected. This is often used in conjunction with the sort criteria. For example, @e[sort=nearest,limit=1] would select the nearest entity of any type. |
[nbt={key:value}] | Entity Data - This criteria will select entities if their NBT (entity data) matches a pattern. (note: if you do this loads of times, it might start to be a bit laggy!) |
How are we going to use them?
We can use these selectors to only select arrows which are in the ground. We can
select all arrows with @e[type=arrow], but this will also include arrows in
the air. To select arrows in the ground, we can check if they have the data {inGround:1b}, so we would use @e[type=arrow,nbt={inGround:1b}]
This target selector can be used in an execute command to run a command as the
entity. Try putting this in your loop.mcfunction:
execute as @e[type=arrow,nbt={inGround:1b}] run say I'm an arrow, I'm in the ground! /reload your datapack and fire an arrow at at a block. You should see that your
chat is spammed with messages, meaning that we successfully selected arrows in
the ground, and executed a command as them!
Make it go boom
Now we can move onto the fun part! We have a simple command which will run another command as any arrow in the ground. We only need to do two things with this command:
- Get the arrow’s position
- Spawn an explosion at the position of the arrow
- Kill the arrow so that it only explodes once
To create an explosion in Minecraft, we can simply summon a TNT entity that has an instant fuse length - we can do this by summoning tnt with the data {fuse:0} at the position of the arrow. We can do this using the execute at command, which tells the game that the summon command should be ran at the position of the entity, instead of at the world spawn (because all commands are run at a position in the world). This way, when we summon an entity at ~ ~ ~, the game knows that it’s referring to the position of the arrow. This sounds complicated, but in reality, its a really easy and intuitive system when you understand it :P
execute at @e[type=arrow,nbt={inGround:1b}] run summon tnt ~ ~ ~ {fuse:0} Then, we just need to copy this command and make it kill the arrow after the
explosion has happened. This is as simple as it sounds - we can use /kill to
remove the arrow. Your finished loop.mcfunction should look like this:
execute as @e[type=arrow,nbt={inGround:1b}] at @s run summon tnt ~ ~ ~ {fuse:0}
kill @e[type=arrow,nbt={inGround:1b}] note
In reality, this method might be a bit laggy if there are a lot of arrows in the world. A better system would involve creating a function which referenced @s (the “current” entity) instead of @e[...], and then runnning that function as all arrows in the ground. This way, we only use @e[...] once, which is a lot more efficient. However, for the purposes of this tutorial, it doesn’t matter at all.
You’re done! Once you /reload your pack, you should be free to play around
with a simple exploding arrows datapack which you made with the help of this
tutorial. Take a break to play around with it - you deserve one!
And when you want to move on to other datapack ideas you might have, feel free to join our Discord server for extra support from our team of helpers. We’re more than happy to help you on your journey to creating awesome Minecraft datapacks!
If you need any more help with your datapacks, don't hesitate to join the Datapack Hub Discord server!
Join us now! https://discord.gg/xHTHbZqXr6