Minecraft Blogs / Tutorial

Guide: How to make a Minecraft Datapack

  • 2,266 views, 26 today
  • 36
  • 26
  • 8
Datapack Hub's Avatar Datapack Hub
Level 18 : Journeyman Organization
179
watch_later
Reading/Completion time: 30m-1h.
info
This tutorial will teach you how to make a datapack with no experience. Before you start, it's a good idea to install a code editor. We recommend Visual Studio Code with the Datapack Extension Pack. It's not required, but it will make your life much easier!

🗃️ If you can't see the endings of file names (ie .png, .pdf) in the file explorer, do this:
Guide: How to make a Minecraft Datapack

Guide: How to make a Minecraft Datapack
...in under an hour or so

Hello there, traveller!

Creating a Minecraft Datapack is an easy way to change something in Minecraft. If you've ever done anything with Minecraft commands or command blocks, then it's very simple.

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!

Pay close attention, because some of this will be a bit difficult if you're new to making datapacks. If you need any help, please join our Discord server.

Guide: How to make a Minecraft Datapack

Getting Started - Setting up the empty datapack folder

Learn: How to create 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. Once you've created the world, the next step is to find and open your world folder. Getting to the world folder is pretty simple:
1. Leave your world
2. Go to your world in Minecraft and hit "Edit"
3. Press "Open World Folder"

This folder opens contains all the data in your Minecraft world. You should see that there's lots of other subfolders in this folder. Find the one which is called datapacks, and open it.



This folder is where the world's datapacks are stored. Open this and create a folder - this is the root folder of your datapack project. The name doesn't matter for now. I'm just going to call it Example Datapack.

info
Unlike mods, datapacks are essentially just folders containing more folders. This is called a folder structure.
The root folder is the folder at the top of the structure - in this case, the folder we just created now.
Subfolders are the name given to a folder inside another folder. Any folders we make under the root folder are subfolders of the root folder.

Open the folder you just made. By the end, this folder is going to contain three things - the pack.mcmeta file (this tells Minecraft that it is a datapack), the pack.png (the project's icon), and the data folder (which contains all the code and features of your datapack - hence the name!).

Before we go further, if you have downloaded and installed Visual Studio Code and the relevant extensions, then you should be able to right click and "Open in Code". If not, then no worries, it isn't required.

We first need to create the pack.mcmeta file. Go ahead and create a new empty file, and name it pack.mcmeta. In this file, you put the description and version of your pack:
{
  "pack":{
    "description":"Float when you sneak",
    "pack_format":18
  }
}
Here's the run-down of what this all means:
description: This is a short description of what your pack does. Here, you should put the name of your datapack, your name, and a very short description. This description will be shown in the datapack viewer.
pack_format: This represents the version that your project supports. You can find the list of pack_format values here. 18 is 1.20.2.

Writing your first function

Learn: How to create and use functions

This is where the fun part begins!

info
First, a brief explanation. Most datapacks will mostly consist of functions, stored in mcfunction files (such as example.mcfunction). Functions are essentially just lists of commands (such as /give, /summon, etc) which are all ran at once in order.

When you run a function, it is always run as a mob/entity (or the game) and at a position/rotation. If your function places a block, it will place a block at the position the function is run at.

We'll get started by writing a simple function. In traditional programming fashion, let's make a function to show you "Hello World" when it is run. Open the data folder, then inside it create a new folder. This can have any name, but for this tutorial, we're going to call it example.

Open the new folder, and then inside it create... another folder! Call this one functions. Open this folder. Now, you should have a structure which looks like this:
/world/datapacks/Example Datapack/data/example/functions
Once you've done that, we can finally get started creating the function. Create a new empty file, and name it hello_world.mcfunction. Open it with any text editor (we recommend VS code - see the top of this article).

Inside the function, put this:
# Show the player Hello World on their screen
title @s title "Hello World!"

# Give the player a diamond
give @s diamond

info
You may be wondering why some lines start with #. In datapacks, lines which start with a # mean that the line is a comment. You can put whatever you want on that line and Minecraft doesn't care. They're useful for keeping your code organised.

It's that simple! Once you save that file and then join your minecraft world if you haven't already, then you can run /reload to, well, reload the data pack. Then, in chat, run /function example:hello_world to see it in action!



So, what's next?

Learn: How to plan your project

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 project into smaller steps. (In computer science, this is called decomposition).
  1. Detect when an arrow lands on the ground. We can do this by running a simple operation on a loop which selects all arrows in the world, but only if they are in the ground.
  2. If an arrow is in the ground, make an explosion. We can do this by summoning a TNT block.
  3. Remove the arrow so it only explodes once.

[​1] Running functions in a loop

Learn: How to loop functions

The first step on our to-do list is to detect arrows which have landed on the ground. To do this, we're going to have to run a command on loop which will select all arrows which are in the ground. Luckily, Minecraft makes looping commands very easy.

First, let's make the function which we want to run on a loop. In your functions folder, create a new function - call it loop.mcfunction. For now, let's make this function say "Hi" when it's ran. The contents of the function should be just this:
say Hi
After you've done that, we're going to need to create some more folders. Pay attention here, because this is where some people mess up.
  1. In data, create another folder. Call this one minecraft, all lower case.
  2. In the new minecraft folder, create a tags folder.
  3. In the new tags folder, create a functions folder.
  4. Finally, create a new file: tick.json.
In the new tick.json file, we're going to put a list of files which we want to run on a loop. More specifically, every game tick, which is 20 times per second. We only want one function to run on a loop, so just put this in tick.json:
{
  "values":[
    "example:loop"
  ]
}
Here, example is the name of the folder in data which contains the functions folder. (/data/example/functions/loop.mcfunction). loop is just the name of your function.

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!

[​1] Selecting the arrows

Learn: How to select an entity and run a command as it.

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. But how are we going to do this?

As far as the game is concerned, an arrow is an entity, just like a pig, cow, zombie, skeleton, or anything else like that. In our code, we can select entities which match a set of criteria, and then run commands as the entity. Selecting an entity is basically like finding any entity which matches a set of criteria, and then doing something to it. We're going to want to select all arrow entities which are in the ground.

Firstly, how do you select an entity? I'm going to turn on teacher mode for a little bit here. Hang on tight, otherwise you'll get a bit confused. To select an entity, we want to use an entity selector. There are 5 basic selectors, which by themselves are not very useful:
@eAll Entities - By itself, this selector will select every single entity which is currently loaded in the world
@sThis 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. This might not seem useful, but in reality it is.
@aAll Players - This selects all currently online players. (All players are always loaded in the world).
@rRandom Player - This selects one random player.
@pNearest Player - This selects the nearest player to the position this command is ran from.

These are the 5 different kinds of selectors. But what if you wanted to narrow it down more, and select, for example, all arrows?
For this, we would want to use @e[​type=arrow]. After the selector, we can put criteria in square brackets. That selector will select all arrow entities. I'm not going to explain every single criteria you can put in the selector, but here are the some basics:
@e[​type=arrow]Entity Type - This will select entities of a certain type. For example, all arrows.
@e[​distance=..5]Entity Distance - This will select all entities which match a criteria for distance. ..5 means less than 5, and likewise 5.. means more than 5 blocks.
@e[​nbt={x:y}]Entity Data - This is a bit advanced: the NBT selector criterion will select all entities which have specific data.

So, how do we select arrows which are in the ground? We know we can select all arrows with @e[​type=arrow], but this will include arrows that are in the air. To select arrows which are in the ground, we need to check if their entity data says that they've landed. The final selector will be @e[​type=arrow,nbt={inGround:1b}]. (Here, 1b basically means "true").

The next part is very easy. We want to execute a command as all arrows which are in the ground. We also want to make sure that the command is run at the position of the arrow. Minecraft makes this super duper easy for us!
execute as @e[type=arrow,nbt={inGround:1b}] at @s run say I'm an arrow, I'm in the ground!

If you put this command in your loop.mcfunction (remove the other one first), then save and reload, then nothing will happen. That's because there probably aren't any arrows lying around on the ground. Fire an arrow onto the ground, and you should see that the arrow says "I'm an arrow, I'm in the ground!"



[​2, 3] Make it go 💥 boom!

Learn: How to make it go boom

This is the fun part! We've made a simple system which will select all arrows in the ground, and run a command as those arrows. From here, it isn't too hard to make it explode. We can split the last section up into two parts:
  1. Make an explosion
  2. Remove the arrow, so it only explodes once.
There's a very simple way to create an explosion. We can just spawn a tnt entity. Even better - when you spawn a TNT from a datapack, it explodes instantly!

Firstly, we can remove the old command in loop.mcfunction which makes the arrow say it's an arrow and that it's in the ground. Replace it with the command to spawn a TNT entity as the arrow, as follows:
execute as @e[type=arrow,nbt={inGround:1b}] at @s run summon tnt
But if you just put this in the loop.mcfunction, then it will keep summoning tnt forever. That's because when you summon the TNT, the arrow stays there, and in the next loop it will summon the TNT again. We can stop this by killing the arrow after you summon the TNT. This is as simple as it sounds:
execute as @e[type=arrow,nbt={inGround:1b}] at @s run summon tnt
execute as @e[type=arrow,nbt={inGround:1b}] at @s run kill @s

And, that's it! You're done! If you put that in loop.mcfunction and save, reload, and join your world, then again nothing will immediately happen. But once you fire an arrow, if all goes well, then it should explode when it lands.


Thanks for reading!

You made it to the end! Hopefully, your datapack works, and I hope I've taught you enough for you to start making your own projects and improving your skills. Happy datapacking!

If you want more help, or if you want to improve your skills more, please join our super friendly Discord community: https://discord.datapackhub.net/. We've got teams of people waiting to help you with any questions or projects you may have!

© 2023 Silabear (Datapack Hub). Licensed under CC BY-SA 4.0


This was created as part of an IRL project!



CreditThis tutorial was written by Silabear. #DatapackHub
Tags

Create an account or sign in to comment.

1
03/25/2024 3:05 pm
Level 11 : Journeyman Engineer
glitched_assasin
glitched_assasin's Avatar
thanks
1
03/25/2024 3:42 pm
Level 67 : High Grandmaster Bear
Silabear
Silabear's Avatar
you are welcome :)
2
11/07/2023 2:46 am
Level 36 : Artisan Miner
ScotsMiser
ScotsMiser's Avatar
Good coverage of the basics 🍻
2
11/06/2023 10:38 pmhistory
Level 43 : Master Engineer
GalSergey
GalSergey's Avatar
Hello. I think that this tutorial is missing the main thing - an explanation that functions in a datapack are not the same as command blocks, and that you can executed other functions as the specified entity. As an example from the tutorial, you can continue that at least executing these commands in a tick function will work:
# tick function
execute as @e[type=arrow,nbt={inGround:true}] at @s run summon tnt
execute as @e[type=arrow,nbt={inGround:true}] at @s run kill @s
But it would be more correct to select this entity once and execute another function with these commands:
# tick function
execute as @e[type=arrow,nbt={inGround:true}] at @s run function example:arrow/boom

# function example:arrow/boom
summon tnt
kill @s

And we can even go ahead and complicate this a little by adding a delay before exploding, with only one command per tick of the function trying to execute, which is much more efficient than trying to execute all those commands per tick of the function every tick:
# load function
scoreboard objectives add delay dummy

# tick function
execute as @e[type=arrow,nbt={inGround:true}] at @s run function example:arrow/delay

# function example:arrow/delay
scoreboard players add @s delay 1
execute if score @s delay matches 1..20 run particle minecraft:dust 0 1 0 1
execute if score @s delay matches 21..30 run particle minecraft:dust 1 1 0 1
execute if score @s delay matches 31..40 run particle minecraft:dust 1 0 0 1
execute if score @s delay matches 41.. run function example:arrow/boom

# function example:arrow/boom
summon tnt
kill @s
And this is the most important difference and advantage of datapacks over command blocks.
1
11/07/2023 2:50 am
Level 67 : High Grandmaster Bear
Silabear
Silabear's Avatar
I did explain how you can run functions as/at an entity in the info box under the “Writing your first function” section. I wanted to keep it as simple as possible.
1
01/30/2024 5:38 pmhistory
Level 74 : Legendary Programmer
KawaMood
KawaMood's Avatar
You can still change the kill part to a simpler command:
execute as @e[type=arrow,nbt={inGround:true}] at @s run summon tnt
kill @e[type=arrow,nbt={inGround:true}]

Even if (or even especially since) it is a tutorial for beginners, it's better to directly show them the very basics in terms of best-practices. Running an extra "execute as" command isn't necessary to kill these arrows, and redefining the position may be confusing for readers. They may end up believing the kill command has a radius limit or something.

Apart from that, good job. That's helpful to have a resource to share. It was a pain to redirect people who didn't know yet about data pack to a simple guide. The "official" wiki page doesn’t explain much. Maybe some parts still need references to better explanations (like what is a "tick" for example) but I presume you will make this tutorial evolve with time!
1
01/31/2024 3:00 am
Level 67 : High Grandmaster Bear
Silabear
Silabear's Avatar
That’s true. I didn’t really think of that tbh. I wanted to teach them how execute works but I guess that’s explained in the first line :P

And I’ll definitely update it at some point. I had to rush this a bit as part of an irl project that needed submitting quickly.
3
11/06/2023 3:19 pm
Level 57 : Grandmaster uwu
amandin
amandin's Avatar
talk about amazing, duh! thanks for including my extension pack too!
Planet Minecraft

Website

© 2010 - 2024
www.planetminecraft.com

Welcome