Repository navigation
Home
Extract Components Library: Minecraft Java Data Pack Library for using variables in the 1.20.5+ command structure for item components (with the square brackets). To understand this data pack library, you need some context for referencing items dynamically in data packs.
In 1.20.2, macro functions got introduced, which are functions that variables are inserted to. In the context of items, this can instantiate a function with the item data from a source (like the chest example below) and use it in other commands used for item manipulation.
# function 1:
function example:function_2 with block ~ ~ ~ Items[0]
# function 2:
$give @p $(id)$(tag) $(Count)
In 1.20.5, NBT tags for items got replaced with item components (and the storing of the count changed slightly).
# function 1:
function example:function_2 with block ~ ~ ~ Items[0]
# function 2:
$loot give @s loot {"pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"$(id)"}],"functions":[{"function":"minecraft:set_count","count":$(count)},{"function":"minecraft:set_components","components":$(components)}]}]}
So now you have got the context, almost. There is a problem with this method: if the item doesn't have a components field, function 2 doesn't instantiate, because it's missing the components variable. I encourage you to search a more lag-efficient and native solution before resorting to this data pack library. You can split all your functions with this problem in 2, one for each of:
$loot give @s loot {"pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"$(id)"}],"functions":[{"function":"minecraft:set_count","count":$(count)},{"function":"minecraft:set_components","components":$(components)}]}]}
$loot give @s loot {"pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"$(id)"}],"functions":[{"function":"minecraft:set_count","count":$(count)}]}]}
This, however, can be annoying, so I made a solution that makes it so you just need to one macro function, and it also adds some bonus features
For the new item components commands structure, ill give the syntax with an example: /give @p dirt[custom_name='"Hello"'] 1. This syntax also applies to the /item command and the new /execute if|unless items subcommand, for example: /execute if items entity @p inventory.* dirt[custom_name='"Hello"'] run item replace entity @p hotbar.0 with dirt[custom_name='"Bye"'] 1
Such a dirt block would have the following data: {id:"minecraft:dirt",count:1,components:{"minecraft:custom_name":'"Hello"'}}
This data pack extracts that data and saves the id, count, and it uses an iterative algorithm that I tried to make as efficient as possible, that extracts the component as a string, and appends the component's data to that string. It then chains all the components together, so that the components field becomes custom_name='{"text":"Hello"}', or even for a more complicated item: custom_name='{"text":"test"}',enchantments={levels:{"minecraft:looting":3,"minecraft:sharpness":5}}. As you can see, the data pack also makes sure that data quoted in single quotation marks, gets applied properly, by putting it in a text field, though this happens only if the first character in the data is a '. For single quotation marks nested deeper, like {id:"minecraft:command_block",count:1,components:{"minecraft:block_entity_data":{Command:'/tellraw @p {"entity":"@p","color":"yellow","nbt":"SelectedItem.components"}',LastExecution:8717969L,SuccessCount:1,TrackOutput:1b,UpdateLastExecution:1b,auto:0b,conditionMet:1b,id:"minecraft:command_block",powered:0b},"minecraft:custom_name":'"test block"'}}, the data automatically gets nested properly, so the data pack can convert it without issues. That data, when saved to the output location, look like block_entity_data={Command:'/tellraw @p {"entity":"@p","color":"yellow","nbt":"SelectedItem.components"}',LastExecution:8717969L,SuccessCount:1,TrackOutput:1b,UpdateLastExecution:1b,auto:0b,conditionMet:1b,id:"minecraft:command_block",powered:0b},custom_name='{"text":"test block"}'
That is all well and good, but what about the components/no components problem? Well, before the algorithm of this data pack is set in motion, the first function check if the item you are referencing has a components field. If not, the data pack halts the component extraction and sets the output field to be empty, but present, so your function will not fail to instantiate. All this technical jargon is explained in the syntax chapter.
So of the item, the id, count, and component structure get extracted and saved, but where? And how do I reference the item in the first place? Let's take our example of macro functions again, with this data pack, that would simplify to:
# function 1:
function sntlibrary:list1/init {source:'block',target:'~ ~ ~',path:'Items[0]'}
function example:function_2 with storage get_components:extract
# function 2:
$give @p $(item_id)[$(components_command)] $(item_count)
There are a few things to note here:
before running your macro function with the command for your item, you run a command with the following syntax: function sntlibrary:list1/init {source:'<source>',target:'<target>',path:'<path>'}. The variables here that I put in the angle brackets are the same used in the /data get command: /data get (block <targetPos>|entity <target>|storage <target>) .... If you dont need a path, because the item data is surface level for some reason, put path:''
Your macro function comes after this command, and since all the data of your item that this library extracted is stored in its storage, you run your function like so: function your:function with storage get_components:extract.
Like I mentioned, you can use this library for the /give command, though I recommend the earlier mentioned solution with /loot give .... However, item data is not the only stuff stored in this data pack's storage. Your original source, target, and path are also stored in there, meaning you can do even more, like: $give $(source) $(item_id)[$(components_command)] $(item_count)
Apart from the /give command, which I have covered plenty in this wiki, the /item and /execute if|unless items also use this new format. Here are some examples for uses:
Replacing locations with the stored item (paths work different for the /item command)
# function 1:
function sntlibrary:list1/init {source:'block',target:'~ ~ ~',path:'Items[0]'}
function example:function_2 with storage get_components:extract
# function 2:
$item replace $(source) $(target) container.3 with $(item_id)[$(components_command)] $(item_count)
The one I'm most existed about is matching item in a query:
# function 1:
function sntlibrary:list1/init {source:'entity',target:'@s',path:'SelectedItem'}
function example:function_2 with storage get_components:extract
# function 2:
$execute unless items block ~ ~ ~ container.0 $(item_id)[$(components_command)] run item replace block ~ ~ ~ container.0 with air
I will be uploading the releases to this GitHub repo, instead of to Modrinth like I normally do, you can download the zip, or find the releases on this page. After that, you can just drag the folder inside the data folder to your data pack, so you can use this library in your data pack. I've included a credit.txt file, because I'm just like that ;)