About

Minecraft Datapacks is a community-driven minecraft server about datapacks. This means we need a way to ensure compatibility between many datapacks to create a stable and friendly datapack ecosystem.

Discord

How we are going to do it

To achieve this we will use the "programming conventions" method, which we will kindly ask other users to follow to improve compatibility between datapacks. And to do that we need to create a way for users to be able to access these conventions very quickly. and that is the aim of this website.

Contribution

If you wish to contribute to this project you can do it via this Github repository

As of right now, there are 3 types of contribution Grammar Contribution, Tips Contribution and Convention Contribution

  1. Grammar Contribution is a simple grammar correction pull-request, anyone can make this contribution if they notice grammar errors.
  2. Tips Contribution is a contribution to a "tips" section of this repository, similar to Grammar Contribution you just need to make a pull-request and wait for approval.
  3. Convention Contribution is a contribution to the "conventions" section of this repository, to contribute this please read the next section.

Convention Contribution

To contribute to this you must first create an issue with the Convention Suggestion label in this format:

  1. explanation of the convention.
  2. explanation on how to implement it.
  3. explanation of why it should be added.

After that, we will discuss it, modify it, then vote on whether to add it or not. If the vote passed you can then submit a pull-request and wait for approval.

Official Conventions

These are official conventions that everyone must followed for datapack compatibility.

Datapack Advancement Convention

About

This convention aims to generalize the installation message of datapacks. This is done by using the Advancement tab to display installation message branching from the root advancement to datapack creator to the datapack itself.

The convention is split into 3 sections: Root, Namespace and Datapack

1. Root Advancement

This is the advancement that every datapacks will branch off from. This advancement must be located at /data/global/advancements/root.json file.

{
    "display": {
        "title": "Installed Datapacks",
        "description": "",
        "icon": {
            "item": "minecraft:knowledge_book"
        },
        "background": "minecraft:textures/block/gray_concrete.png",
        "show_toast": false,
        "announce_to_chat": false
    },
    "criteria": {
        "trigger": {
            "trigger": "minecraft:tick"
        }
    }
}

2. Namespace Advancement

This is the advancement is for each datapack creator, it should be the same for all of your datapacks. It should be located at /data/global/advancement/<namespace>.json.

{
    "display": {
        "title": "<Your name>",
        "description": "",
        "icon": {
            "item": "minecraft:player_head",
            "nbt": "{SkullOwner: '<your_minecraft_name>'}"
        },
        "show_toast": false,
        "announce_to_chat": false
    },
    "parent": "global:root",
    "criteria": {
        "trigger": {
            "trigger": "minecraft:tick"
        }
    }
}

3. Datapack Advancement

This is an advancement for your datapack, it should be unique from your other Datapack Advancements. You can create this advancement anywhere as long as you don't pollute /data/global/advancements/ folder.

{
    "display": {
        "title": "<datapack name>",
        "description": "<datapack description>",
        "icon": {
            "item": "<item>"
        },
        "announce_to_chat": false,
        "show_toast": false
    },
    "parent": "global:<namespace>",
    "criteria": {
        "trigger": {
            "trigger": "minecraft:tick"
        }
    }
}

Note

everything encased inside <...> should be changed to the specified information.

Result

Your advancement tab should now look something like this:

Datapack Advancement Convention Preview
(Image by @Hashs#9531)

Custom Model ID

About

This convention aims to reduce conflict within the custom model data system as much as possible by assigning a unique id for every creator to use.

1. Register your id

"id" is an integer between 1-999 which we'll use to uniquely namespaced custom model data to prevent conflict between resourcepacks.

You can register your id at https://mc-datapacks.web.app.

Do note that any id above 700 is susceptible to floating-point precision error.

2. Prefix your model with your id

You will prefix your custom model data with your id in this format where XXX is your ID and 0000 is any custom model data that fits within 4 digits.

idcmd
XXX0000

Here are some examples:

2.1. id = 42

{
    "overrides": [
        {"predicate": {"custom_model_data": 420001}, "model": "path/to/model/1"},
        {"predicate": {"custom_model_data": 420020}, "model": "path/to/model/2"},
        {"predicate": {"custom_model_data": 420300}, "model": "path/to/model/3"}
    ]
}

2.2. id = 808

{
    "overrides": [
        {"predicate": {"custom_model_data": 8081001}, "model": "path/to/model/1"},
        {"predicate": {"custom_model_data": 8082002}, "model": "path/to/model/2"},
        {"predicate": {"custom_model_data": 8083003}, "model": "path/to/model/3"}
    ]
}

2.3. id = 1

{
    "overrides": [
        {"predicate": {"custom_model_data": 10001}, "model": "path/to/model/1"},
        {"predicate": {"custom_model_data": 10010}, "model": "path/to/model/2"},
        {"predicate": {"custom_model_data": 10011}, "model": "path/to/model/3"}
    ]
}

Global Ignoring Tag

About

This convention provides a way for datapack to communicate with each other by specifying entity tags other datapacks can then look for. This is used heavily to prevent other datapacks from killing/removing custom entities from the world unexpectedly.

There are currently 4 ignoring tags: global.ignore, global.ignore.pos, global.ignore.gui, global.ignore.kill

1. global.ignore.kill

Any entity with this tag must not be killed by other datapack. This includes but not limited to /kill command.

execute as @e[type=creeper, tag=!global.ignore.kill] run kill @s

2. global.ignore.gui

Any entity with this tag must not display visual effects around them. This includes but not limited to /title, /particle, /playsound commands.

execute as @a[tag=!global.ignore.gui] at @s run title @s actionbar [{"text": "Hello, World!", "color": "green"}]

3. global.ignore.pos

Any entity with this tag must not be moved from where it was. This includes but not limited to /tp, /teleport commands.

execute as @e[type=witch, tag=!global.ignore.pos] at @s run tp @s ~ ~0.1 ~

4. global.ignore

Any entity with this tag must not be included in the entity selector at all, you can also think of this tag as a combination of every ignoring tags above.

execute as @e[tag=!global.ignore] at @s run function namespace:internal/logic/function

Note

The convention only applies if your function will change NBT of an unknown entity. if you are trying to change NBT of known entity (i.e. an entity with a special tag attached) you don't need to follow this convention.

Common Trait Convention

About

This convention intended to bring the Ore Dictionary system from Forge to datapack's custom item. This is done by utilizing Item's custom nbt feature. We can insert any kind of nbt inside item which we can use other commands to check/look into it.

With that, we can create a unified lookup system that every datapacks can use to search for a specific item they want. You can then use the Common Trait Convention's provided syntax to construct a search function to find the item you need.

Example Usage

It can be hard to visualize how this convention would be useful in the real world, so we compile some useful usage that would not be possible without this convention.

  1. Suppose you added a custom furnace which let you smelt copper ore into ingots. With this convention, you can detect for any copper ore from any datapacks to smelt it.
  2. Suppose you added a fridge which only accept food items, with this convention you can detect for any food items even the custom ones from other datapack.
  3. Suppose you added a custom anvil which lets you repair tools straight from the material instead of the ingot, with this convention you can detect any kind of material from other datapacks even when the base material doesn't match.

Traits

Traits are behavior and properties that an object can have. By specifying these traits inside the item's nbt. Other datapacks will be able to refer to that item via traits instead of item id directly.

Trait is an array of strings and so will look like this in nbt (notice traits: [...]?)

/give @s diamond{ctc: {traits: ["some", "trait", "here"], id: "example", from: "convention:wiki"}}

Syntax

Common Trait Convention's syntax will be stored inside ctc nbt of item. insidectc contains: id, from and traits nbts.

  • id: internal id of your item, this should not be used outside of your datapack but should be unique within your datapack.
  • from: a namespace specifying which datapack is the item comes from.
  • traits: an array of traits that you can use to refer to items outside of your datapack.

We will assume the following syntax is the NBT structure of /give command

{
    ctc: {
        id: "my_copper_ore",
        from: "convention:wiki",
        traits: ["metal/copper", "block", "ore"]
    }
}

Let's look at traits nbt

  • metal/copper, this trait tells us that this item is copper.
  • block, this trait tells us that this item is a placeable block.
  • ore, this trait tells us that this item is an ore.

Slash Notation

In the above example, you will notice the use of / in metal/copper, this is used when the trait alone can be ambiguous. For example, what does trait orange mean? is it the color orange or the fruit orange?

In such case we'll use slash notation to separate them. color/orange and fruit/orange

Usage

To detect or check for trait items you just need to check for traits nbt of the item.

Detect if the player is holding a weapon

execute as @a if entity @s SelectedItem.tag.ctc{traits: ["tool/weapon"]} run ...

Detect if the container contains copper ore

execute if block ~ ~ ~ Items[].tag.ctc{traits: ["metal/copper", "ore"]} run ...

Detect if the container contains a placeable item

execute if block ~ ~ ~ Items[].tag.ctc{traits: ["block"]} run ...

Basic Traits

This is a provided list of traits that you can use, this doesn't mean you can't create new traits for your own use but if there is a trait that suits your need in this you should use it instead.

The list is split into multiple groups and you should not use traits from the same group twice.

Object Type Group

This trait represents the state of matter that this item holds.

TraitDescription
gasGaseous substance
liquidLiquid substance
blockPlaceable item
itemNormal minecraft item

Special Type Group

This trait represents common behavior from modded minecraft, this should help with integrating your pack into this convention.

This group is an exception to the rule above, you can use multiple traits from this group as much as you like.

TraitDescription
oreOre block that can usually be found in cave
seedItem that can be used to grow plant
flowerFlower item
grassBlock that can spread from one block to another
saplingBlock that can grow into tree
vegetableFood item that comes from seed
logItem that drops from tree
planksItem that come from processing log

Compression Group

This trait represents an item that can be combined to create a more compact version of itself and vice versa

For example:

  • redstone dust -> redstone block
  • ice -> packed ice
  • iron block -> iron ingot
TraitDescription
packedMost packed form of item, usually be a block form of this item
ingotNormal form of item, usually be an ingot form of this item
nuggetSmallest form of item, usually be a nugget form of this item

Edible Group

This trait represents an edible item that can be used by the player (drinking included)

TraitDescription
foodAll types of edible item

Armor Group

This trait represents an item that can be worn by players and other entities

TraitDescription
armorAll types of wearable item

Tool Sub-group

This trait use Slash Notation!

This trait represents an item that can be used to interact with the world.

TraitDescription
tool/miningThis item can be used to mine a stone block and other related blocks
tool/choppingThis item can be used to cut trees and wood material
tool/tillingThis item can be used to till the soil
tool/wateringThis item can be used to water the soil
tool/weaponThis item can be used to fight monsters and other players

Gem Sub-group

This trait use Slash Notation!

This trait represents an item that can be considered "gemstone"

TraitDescription
gem/diamondDiamond gemstone
gem/rubyRuby gemstone
gem/emeraldEmerald gemstone
gem/saphireSaphire gemstone

Metal Sub-group

This trait use Slash Notation!

This trait represents the metallic items that are often added by mods

TraitDescription
metal/ironItem that made up of iron
metal/goldItem that made up of gold
metal/copperItem that made up of copper
metal/aluminiumItem that made up of aluminium
metal/tinItem that made up of tin
metal/silverItem that made up of silver
metal/leadItem that made up of lead
metal/nickleItem that made up of nickle
metal/platinumItem that made up of platinum

Reference

Datapack Uninstallation Convention

About

Every datapacks are required to implement a way to "uninstall" theirs datapack from the world.

There is no specific implementation that you need to follow. This convention only enforces that you added some way to uninstall your datapack from the world.

These are some example list of what could be uninstalled from the world

  • Used scoreboards.
  • Custom/Marker entities.
  • /data storage
  • forceloaded chunks

Shulker Box Loot Table Convention

About

This convention aims to make Shulker Box Inventory Manipulation as conflicted-free as possible by enforcing a specific loot table for minecraft:yellow_shulker_box block.

Implementation

Simply use this loot table inside /data/minecraft/loot_tables/blocks/yellow_shulker_box.json when you want to use the Inventory Manipulation trick.

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:dynamic",
              "name": "minecraft:contents",
              "conditions": [
                {
                  "condition": "minecraft:match_tool",
                  "predicate": {
                    "nbt": "{drop_contents: 1b}"
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "functions": [
                {
                  "function": "minecraft:copy_name",
                  "source": "block_entity"
                },
                {
                  "function": "minecraft:copy_nbt",
                  "source": "block_entity",
                  "ops": [
                    {
                      "source": "Lock",
                      "target": "BlockEntityTag.Lock",
                      "op": "replace"
                    },
                    {
                      "source": "LootTable",
                      "target": "BlockEntityTag.LootTable",
                      "op": "replace"
                    },
                    {
                      "source": "LootTableSeed",
                      "target": "BlockEntityTag.LootTableSeed",
                      "op": "replace"
                    }
                  ]
                },
                {
                  "function": "minecraft:set_contents",
                  "entries": [
                    {
                      "type": "minecraft:dynamic",
                      "name": "minecraft:contents"
                    }
                  ]
                }
              ],
              "name": "minecraft:yellow_shulker_box"
            }
          ]
        }
      ]
    }
  ]
}

Reference

Certified Datapacks

Certified Datapack Banner

https://i.imgur.com/NbVuvwA.png

You can attach this banner to your project page after your datapack has been verified as a Certified Datapack.

Certified Datapacks have a benefit of knowing that your datapack will be compatible with other datapacks.

Requirement

Datapack must satisfy these requirements to receive Certified Datapack title

  • Datapack must be portable, it must not be tied down to a specific save.
  • Datapack must use mcfunction directly. For example, using mcfunction to create a custom recipe does not count.
  • Datapack must modify or add features to Minecraft.

Note

  1. We may rule a datapack out at our discretion, for reasons we would then specify.
  2. This requirement is not final and can be changed in the future.

Tips

Various tips and tricks for developing datapack.

Enum Scoreboard

You can use a fake player to represent a state of your scoreboard instead of using the number directly. This makes your code more verbose and increases maintainability for the future.

Declaring enum

scoreboard players set #state.idle bb.enum 1
scoreboard players set #state.foo bb.enum 2
scoreboard players set #state.bar bb.enum 3

The enum can hold any value that you want as long as it's unique, we only care about the existence of the fake player itself.

Using enum state

execute if score @s bb.state = #state.idle bb.enum run function <idle_state>
execute if score @s bb.state = #state.running bb.enum run function <running_state>
execute if score @s bb.state = #state.stopping bb.enum run function <stopping_state>

Here we check the state of @s and run appropriate function that must only be run in that state.

Shulker Box Inventory Manipulation

About

This technique allows us to manipulate the player's inventory just like any NBT using the shulker box's loot table.

Concept

We take advantage of the fact that the shulker box can be configured to drop their content on the ground instead of a shulker box containing its content, which can then be used by /loot command to replace the player's inventory.

Implementation

1. To follow with the Official Conventions you will have to modify the loot table of minecraft:yellow_shulker_box to the loot table below. The loot table will drop its content on the ground when it's mined by an item with NBT {drop_contents: 1b}
https://pastebin.com/4sspBvep

2. Create a placeholder shulker box that you will use to modify the player's inventory. Usually, this should be placed far away from player view but for simplicity's sake. I'll place it at ~ ~ ~.

setblock ~ ~ ~ minecraft:yellow_shulker_box

3. You need to clone the player's inventory into some sort of NBT buffer, you can clone this into a data storage since they are faster.

data modify storage <storage> inventory set from entity <player> Inventory

4. Due to a limited number of slots inside the shulker box, You have to process the nbt in "batch" the easiest way to organize this batch can be done by splitting it into "hotbar", "inventory", "armor" and "offhand" batch.

4.1. Create each batch using these commands.

                                      |--- Batch name                                     |---- Slot number
data modify storage <storage> batch.hotbar append from storage <storage> inventory[{Slot: 0b}]
data modify storage <storage> batch.hotbar append from storage <storage> inventory[{Slot: 1b}]
data modify storage <storage> batch.hotbar append from storage <storage> inventory[{Slot: 2b}]
.
.
.

// Don't forget to remove `Slot` nbt from the item before moving to the next step!
data remove storage <storage> batch.hotbar[].Slot

4.2. Modify the NBT of each item however you like it to be.

5. Copy the nbt from the previous step into the shulker box and then replace the player's inventory.

data modify block ~ ~ ~ Items set from storage <storage> batch.hotbar
loot replace entity <player> hotbar.0 9 mine ~ ~ ~ iron_pickaxe{drop_contents: 1b}

data modify block ~ ~ ~ Items set from storage <storage> batch.inventory
loot replace entity <player> inventory.0 27 mine ~ ~ ~ iron_pickaxe{drop_contents: 1b}

data modify block ~ ~ ~ Items set from storage <storage> batch.armor
loot replace entity <player> armor.feet 4 mine ~ ~ ~ iron_pickaxe{drop_contents: 1b}

data modify block ~ ~ ~ Items set from storage <storage> batch.offhand
loot replace entity <player> weapon.offhand 1 mine ~ ~ ~ iron_pickaxe{drop_contents: 1b}

Note: Notice the slots I used in each /loot command?

6. Cleaning up

setblock ~ ~ ~ minecraft:air
data remove storage <storage> batch
data remove storage <storage> inventory

Note

In this example, I assume that you need to modify NBT of all available slots but if you want to modify only items in your hotbar then you don't need to use "inventory", "armor" and "offhand" batch.