A datapack that can compare two NBT values.
This datapack can compare any two values of any numeric data type. This includes byte, short, int, long, float and double. If the value does not have a numeric data type (e.g. list or compound), the lengths of these values are compared. Generic data types which include string, list, compound, byte_array, int_array and long_array are compared using their length.
The type of comparison done is automatically determined by the type of the values, which are obtained using a modified version of the NBT type identifier, which has a cache size of 2 and uses a hard-coded function list of types for better performance.
This datapack uses forceload, which means that OP level 3 or higher is required to install it. When first loading the datapack, a popup will prompt all players to install it by clicking on said popup. As mentioned previously, this requires OP level 3 or higher to work.
- Minecraft version:
19w45band up - Namespace:
nbtcomp - Scorespace:
nbtcomp - Known incompatibilities:
none
- Use the
nbtcomp:inputstorage to input the data that you want to compare. There are two fields:DataLandDataR. Which value you put in which field will determine the result of the comparison (see Function output below). - Call the function
nbtcomp:compareusing the commandfunction nbtcomp:compare. - The result of the function will be stored in the
#nbtcomp.compare.resultfake player using the objectivenbtcomp.var(see Function output below). In short, the function can be read using something likescoreboard players get #nbtcomp.compare.result nbtcomp.var.
The function output is determined by the values in the DataL and DataR fields in the nbtcomp:input storage.
- If the value in
DataLis equal to the value inDataR, the result is0. - If the value in
DataLis smaller than the value inDataR, the result is-1. - If the value in
DataLis bigger than the valu einDataR, the result is1. - If
DataLandDataRcannot be compared, the result is2. This is the case when one of the data types is numeric an the other one is generic. In essence, the result value "points to" theDatafield that contains the smaller value.
Supported values are restricted by the minimum and maximum values that the corresponding data types support. In the case of this datapack, doubles and floats are limited by the maximum and minimum values of a long. This means that a floating-point number that exceeds the capabilities of a 32-bit number can still be compared (although with limited precision).
Comparison of floating-point numbers can be done up to 9 decimal places, with a precision of at least 15 (double) or 6 (float) significant figures.
In this datapack, each number is represented by an integral part and a fractional part.
The integral part is split into the higher 32 bits and the lower 32 bits of the number.
Integers,shortsandbytesalways have a higher integral part of 0 (positive) or -1 (negative). The lower integral part is equal to the value of the data.- The integral parts of a
longare determined by splitting the value into a lower and higher integral part by first storing the value inside of a field that can only hold integers. For this datapack, theColortag inside anarea_effect_cloudis used. This yields the lower integral part. The higher integral part is obtained by scaling the entire number with0.00000000023283064365386962890625. - The integral parts of a
floatordoubleare obtained by first converting the values to alongand then splitting it. The values are converted by storing it in a field that can only hold longs. In this case, theOwnerUUIDMosttag inside anarea_effect_cloudis used. After converting the value to along, the value is split into a higher and lower integral part in the same way as mentioned above.
The fractional part contains up to 9 decimal places.
Integers,shorts,bytesandlongsalways have a fractional part of 0.floatsanddoubleshave a fractional part that contains 9 decimal places. The value is put inside the Y position of anarea_effect_cloud. This number is then reduced to0.<fraction>by repeatedly subtracting (when number is positive) or adding (when number is negative) a value from/to the position. For more information, see this README.
- The higher integral parts are compared. If these are not equal, the comparison yields a result immediately. Otherwise, go to step 2.
- The lower integral parts are compared. If these are not equal, the comparison yields a result. Otherwise, go to step 3.
- If at least one of the numbers is a
floatordouble, the fractional parts are compared and the final result is returned.
The generic data types are represented by their length, which is computed by using execute store result ... data get ....
The lengths of the data types are compared and the result is returned.
Special thanks to the members of the MinecraftCommands discord server and expecially to Maxaxik and vdvman1 who helped me in creating the ideas for this datapack.