From 7d6c3784a35abd8d0cf313c1a63a457b6eb08a1a Mon Sep 17 00:00:00 2001 From: themodernhakr Date: Mon, 24 Mar 2025 23:50:46 -0500 Subject: [PATCH] vault backup: 2025-03-24 23:50:46 --- .../When Two Macros are Faster than One.md | 70 ++++++++++++++----- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Minecraft Datapacking/When Two Macros are Faster than One.md b/Minecraft Datapacking/When Two Macros are Faster than One.md index 9759ec0..e862f73 100644 --- a/Minecraft Datapacking/When Two Macros are Faster than One.md +++ b/Minecraft Datapacking/When Two Macros are Faster than One.md @@ -34,13 +34,32 @@ function searchArray(keyword: string) { searchArray('entry500') ``` -In mcfunction, this is not so easy. We *could* use macros +In mcfunction, this is not so straightforward. Macros would make this really clean: +```vb +function test_namespace:search_array {keyword: "entry500"} +``` +Unfortunately, macros come with a performance hit. A more performant method, albeit less elegant, is to store the keyword in NBT storage prior to calling the function. The storage can be removed after the function is run: +```vb +data modify storage test_namespace:test_namespace temp.keyword set value 'entry500' +function test_namespace:search_array +data remove storage test_namespace:test_namespace temp.keyword + +``` +Once the entry is found, it is stored in the `temp.result` storage, which can then be consumed by another function. + +Now for the logic to do the actual array searching... # one macro -Macros allow us to reach into our array and pick out an entry that matching value in the `string` property. +Macros allow us to reach into our array and pick out an entry that matching value in the `string` property. This is something that I didn't realize (for some reason) and was pointed out by **PuckiSilver** and **amandin** on the Datapack Hub discord server. ```vb ... one_macro.array[string:$(keyword)] ``` +This method is super clean and results in a one liner that is wordy but simple: +```vb +'# one_macro/_searcharray.mcfunction +$data modify storage test_namespace:test_namespace temp.result set from storage test_namespace:test_namespace one_macro.array[string:$(keyword)] +``` +`_searcharray` can then be called using the `temp.keyword` storage: ```vb '# one_macro/run.mcfunction @@ -49,15 +68,37 @@ data modify storage test_namespace:test_namespace temp.keyword set value 'entry5 function test_namespace:one_macro/_searcharray with storage test_namespace:test_namespace temp data remove storage test_namespace:test_namespace temp.keyword + +'# call the function that consumes 'temp.result', then remove it data remove storage test_namespace:test_namespace temp.result ``` - -```vb -'# one_macro/_searcharray.mcfunction - -$data modify storage test_namespace:test_namespace temp.result set from storage test_namespace:test_namespace one_macro.array[string:$(keyword)] -``` # two macro +Another way to crack the problem is through indexing. This was my original plan when I didn't realize that `...[string:$(keyword)]` was possible. + +This method requires the creation of an index of the field that is going to be searched. The index will look something like this: +```json +[ + {entry1: 0}, + {entry2: 1}, + ... + {entry500: 499} +] +``` +The *key*, e.g. `entry2:` corresponds with the value of a `string` field in the main array, while the value `1` indicates the main array index where we'll find the full entry. The index can be searched with a direct path, `index.$(keyword)`, and the main array can also be searched with a direct reference to the entry index, `array.#(index)`. Keep in mind that *the index must already exist prior to running the search function*. In a practical application, an index could be updated every time the main array is updated. A scheduled task could also audit the index to ensure that it's up to date. + +The index search looks like this: +```vb +'# two_macro/_searchindex.mcfunction + +$data modify storage test_namespace:test_namespace temp.index set from storage test_namespace:test_namespace two_macro.index.$(keyword) +``` +And the array search looks like this: +```vb +'# two_macro/_searcharray.mcfunction + +$data modify storage test_namespace:test_namespace temp.result set from storage test_namespace:test_namespace two_macro.array[$(index)] +``` +The index and array search functions are then called using the `temp.keyword` storage: ```vb '# two_macro/run.mcfunction @@ -69,17 +110,8 @@ function test_namespace:two_macro/_searcharray with storage test_namespace:test_ data remove storage test_namespace:test_namespace temp.keyword data remove storage test_namespace:test_namespace temp.index + +'# call the function that consumes 'temp.result', then remove it data remove storage test_namespace:test_namespace temp.result ``` -```vb -'# two_macro/_searchindex.mcfunction - -$data modify storage test_namespace:test_namespace temp.index set from storage test_namespace:test_namespace two_macro.index.$(keyword) -``` - -```vb -'# two_macro/_searcharray.mcfunction - -$data modify storage test_namespace:test_namespace temp.result set from storage test_namespace:test_namespace two_macro.array[$(index)] -``` \ No newline at end of file