Why Use Binary in Bedrock Commands
Minecraft Bedrock stores scoreboard scores as 32-bit signed integers, meaning any score on an entity or fake player can hold a value from -2,147,483,648 to 2,147,483,647. In a typical add-on, creators frequently make an entire scoreboard objective just to store a 0 or 1 flag—such as whether a player has opened a specific dungeon door or unlocked a skill. While creating ten objectives for ten flags is harmless, scaling up to hundreds of quests, triumphs, or dialog states creates massive scoreboard bloat and makes save files harder to inspect and maintain.
By treating a single scoreboard score as a series of binary bits (powers of two: 1, 2, 4, 8, 16, 32, and so on), you can pack 31 independent true/false flags into one positive integer. (The 32nd bit represents the negative sign in two's complement representation, which complicates division and modulo math in commands, so it is best left unused unless you specifically account for negative numbers).
A second major use case is data serialization across the server-client boundary. Scoreboards only exist on the server; client-side animations, render controllers, and particles cannot read scores directly. While synced entity properties (`minecraft:properties`) can be read by client-side Molang via `q.property()`, entities are strictly limited to 32 properties per identifier, and integers inside properties must have a fixed, pre-declared range. If you need to send a wide scoreboard integer (like a 16-bit currency balance or custom RGB color code) to a client-side render controller, decomposing the score into 16 boolean entity properties inside a behavior pack function is a reliable, script-free way to bridge the gap.
| Bit Index | Power of 2 | Score Value Added | Hex Equivalent |
|---|---|---|---|
| 0 | 2^0 | 1 | 0x01 |
| 1 | 2^1 | 2 | 0x02 |
| 2 | 2^2 | 4 | 0x04 |
| 3 | 2^3 | 8 | 0x08 |
| 4 | 2^4 | 16 | 0x10 |
| 5 | 2^5 | 32 | 0x20 |
| 6 | 2^6 | 64 | 0x40 |
| 7 | 2^7 | 128 | 0x80 |
| 8 | 2^8 | 256 | 0x100 |
| 15 | 2^15 | 32768 | 0x8000 |
| 30 | 2^30 | 1073741824 | 0x40000000 |
Setting Up the Scoreboard Registers
Because Bedrock commands do not have native bitwise operators (like `&`, `|`, `^`, or `<<`) inside `/scoreboard players operation`, all binary manipulation must be done through integer arithmetic: addition, subtraction, multiplication, division (`/=` rounds toward zero for positive integers), and modulo (`%=`).
To perform binary encoding and decoding without destroying the player's actual saved score, you need a working register objective (often called `math_temp` or `bit_work`) and a set of constant powers of two stored on fake player names under a `const` objective. You initialize these once when the world loads or via an setup function. Having constants on fake players allows you to run `/scoreboard players operation` to divide and modulo by powers of two.
# Create objectives for storage, temporary math, and constants
scoreboard objectives add player_flags dummy
scoreboard objectives add bit_work dummy
scoreboard objectives add const dummy
# Define powers of 2 on fake players (8-bit example, extendable to 30)
scoreboard players set #b0 const 1
scoreboard players set #b1 const 2
scoreboard players set #b2 const 4
scoreboard players set #b3 const 8
scoreboard players set #b4 const 16
scoreboard players set #b5 const 32
scoreboard players set #b6 const 64
scoreboard players set #b7 const 128
scoreboard players set #b8 const 256
# General math constant for modulo-2 checks
scoreboard players set #two const 2Decoding: Unpacking an Integer into Bits
Unpacking (or decoding) takes a single composite score on an entity and extracts the binary state of every bit. There are two primary algorithms to do this in `.mcfunction` files: greedy subtraction (top-down) and modulo-division (bottom-up). Both execute in a single tick.
The greedy subtraction method is generally faster and requires fewer commands per bit. You start by copying the target score into `bit_work`. Then, starting from the highest power of two you care about and moving down to 1, you check if `bit_work` is greater than or equal to that power of two. If it is, that bit is `1` (true), and you subtract that power of two from `bit_work` before testing the next smaller bit. If it is smaller, the bit is `0` (false).
In the example below, an 8-bit score (`0` to `255`) in `player_flags` is unpacked and written directly into eight boolean entity properties (`wiki:b0` through `wiki:b7`) using `/event` or `/execute` with property overrides, or simple tags. Using tags is the lightest approach for server-side command logic, while `/event` or `/scriptevent` is used when pushing state to entity components.
# Copy the persistent score into the working register so we don't overwrite it
scoreboard players operation @s bit_work = @s player_flags
# Clear existing bit tags before recalculating
tag @s remove bit_0
tag @s remove bit_1
tag @s remove bit_2
tag @s remove bit_3
tag @s remove bit_4
tag @s remove bit_5
tag @s remove bit_6
tag @s remove bit_7
# Bit 7 (128)
execute if score @s bit_work matches 128.. run tag @s add bit_7
execute if entity @s[tag=bit_7] run scoreboard players remove @s bit_work 128
# Bit 6 (64)
execute if score @s bit_work matches 64.. run tag @s add bit_6
execute if entity @s[tag=bit_6] run scoreboard players remove @s bit_work 64
# Bit 5 (32)
execute if score @s bit_work matches 32.. run tag @s add bit_5
execute if entity @s[tag=bit_5] run scoreboard players remove @s bit_work 32
# Bit 4 (16)
execute if score @s bit_work matches 16.. run tag @s add bit_4
execute if entity @s[tag=bit_4] run scoreboard players remove @s bit_work 16
# Bit 3 (8)
execute if score @s bit_work matches 8.. run tag @s add bit_3
execute if entity @s[tag=bit_3] run scoreboard players remove @s bit_work 8
# Bit 2 (4)
execute if score @s bit_work matches 4.. run tag @s add bit_2
execute if entity @s[tag=bit_2] run scoreboard players remove @s bit_work 4
# Bit 1 (2)
execute if score @s bit_work matches 2.. run tag @s add bit_1
execute if entity @s[tag=bit_1] run scoreboard players remove @s bit_work 2
# Bit 0 (1)
execute if score @s bit_work matches 1.. run tag @s add bit_0
execute if entity @s[tag=bit_0] run scoreboard players remove @s bit_work 1Encoding: Packing Flags into a Single Score
Packing is the reverse operation: taking separate boolean states on an entity (such as tags, scores, or entity property states) and combining them into one integer. This is simple addition: reset the target score to `0`, and for each active flag, add its corresponding power of two.
If you want to toggle, set, or clear just *one* specific bit inside `player_flags` without unpacking and repacking the entire number, you can isolate that bit first using division and modulo. To read bit `N` (where `2^N` is stored on `#bN const`) without changing any other bits: copy `player_flags` to `bit_work`, divide `bit_work` by `#bN const`, and then modulo `bit_work` by `#two const`. The result in `bit_work` will be `1` if the bit is currently set, or `0` if it is clear.
Knowing the current state of that single bit prevents the most dangerous bug in arithmetic bitpacking: adding a power of two when the bit is already `1`. In binary, `1 + 1 = 10` (which carries over and corrupts the next bit up instead of staying `1`). Always verify the bit is `0` before adding `2^N`, and verify it is `1` before subtracting `2^N`.
# Goal: Safely set Bit 3 (value 8) to TRUE without corrupting Bit 4 (value 16)
# Step 1: Isolate Bit 3 into bit_work using (player_flags / 8) % 2
scoreboard players operation @s bit_work = @s player_flags
scoreboard players operation @s bit_work /= #b3 const
scoreboard players operation @s bit_work %= #two const
# Step 2: Only add 8 to player_flags if Bit 3 is currently 0
execute if score @s bit_work matches 0 run scoreboard players add @s player_flags 8Syncing Unpacked Bits to Client-Side Molang
Once your command system can unpack a scoreboard value into individual bits, you can pipe arbitrary server numbers into client-side animations, particle emitters, or UI render controllers using `minecraft:properties` in the entity definition. While an integer property in Bedrock requires you to declare a fixed `[min, max]` range—and large ranges hurt network and memory overhead—eight or sixteen boolean properties (`"type": "bool"`) are extremely cheap and sync reliably to the client.
On the entity's behavior pack JSON, declare the boolean properties with `"client_sync": true` and set up component groups or events (using `set_property`) to flip them, or modify them through commands. Then, inside your resource pack, reconstruct the full integer inside a Molang variable by multiplying each boolean property by its power of two (`q.property('wiki:b0') * 1 + q.property('wiki:b1') * 2 ...`).
{
"format_version": "1.20.40",
"minecraft:entity": {
"description": {
"identifier": "wiki:data_carrier",
"is_spawnable": false,
"is_summonable": true,
"properties": {
"wiki:b0": { "type": "bool", "default": false, "client_sync": true },
"wiki:b1": { "type": "bool", "default": false, "client_sync": true },
"wiki:b2": { "type": "bool", "default": false, "client_sync": true },
"wiki:b3": { "type": "bool", "default": false, "client_sync": true }
}
},
"components": {
"minecraft:physics": {
"has_gravity": false,
"has_collision": false
}
},
"events": {
"wiki:set_b0_true": { "set_property": { "wiki:b0": true } },
"wiki:set_b0_false": { "set_property": { "wiki:b0": false } },
"wiki:set_b1_true": { "set_property": { "wiki:b1": true } },
"wiki:set_b1_false": { "set_property": { "wiki:b1": false } },
"wiki:set_b2_true": { "set_property": { "wiki:b2": true } },
"wiki:set_b2_false": { "set_property": { "wiki:b2": false } },
"wiki:set_b3_true": { "set_property": { "wiki:b3": true } },
"wiki:set_b3_false": { "set_property": { "wiki:b3": false } }
}
}
}Reconstructing the Integer in a Resource Pack Animation
When the client receives the synced boolean properties on `wiki:data_carrier`, a resource pack animation or animation controller can run a single Molang expression to rebuild the original integer. In Molang, boolean values evaluate to `1.0` for true and `0.0` for false inside arithmetic expressions, so you do not even need ternary `? :` operators for each bit.
This reconstructed variable (`v.unpacked_score`) can then drive UV offsets on a custom number display model, scale health bars smoothly with high precision, or select custom textures dynamically.
{
"format_version": "1.10.0",
"animations": {
"animation.data_carrier.decode": {
"loop": true,
"bones": {
"root": {
"scale": [
"v.unpacked_score = q.property('wiki:b0') * 1 + q.property('wiki:b1') * 2 + q.property('wiki:b2') * 4 + q.property('wiki:b3') * 8; return 1.0;",
1.0,
1.0
]
}
}
}
}
}Which versions this applies to
Scoreboard binary math works in all Bedrock versions supporting the modern `/execute` syntax (1.19.50 and later). Entity properties (`minecraft:properties` and `q.property()`) are stable and require no experimental toggles in `format_version` 1.20.40 and above.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Adjacent flags randomly flip on or off when setting a flag that was already active. | You ran `scoreboard players add @s player_flags <2^N>` without first checking if bit N was already set to 1. Adding 4 when the 4-bit is already active carries the value over into the 8-bit (4 + 4 = 8), clearing bit 2 and corrupting bit 3. | Always isolate the bit with `/=` and `%=` (or unpack the score first) and guard the `scoreboard players add` command with `execute if score @s bit_work matches 0`. |
| Greedy subtraction unpacker leaves all lower bits set to 1 if the score is higher than expected. | If an 8-bit unpacker (max 255) is fed a score of 300, subtracting 128 leaves 172, which is still greater than 64, 32, 16, 8, 4, 2, and 1. Every single `matches <2^N>..` check succeeds. | Sanitize the working register before unpacking by capping it with modulo: run `scoreboard players operation @s bit_work %= #b8 const` (where `#b8` is 256) at the very top of your 8-bit unpack function. |
| Unpacking or bit-isolation fails completely when using the 32nd bit (value 2147483648). | Bedrock scoreboards use 32-bit signed integers with a maximum positive value of 2,147,483,647 (`2^31 - 1`). Attempting to add `2^31` overflows into `-2147483648`, and Bedrock's `/=` and `%=` operators produce negative remainders on negative dividends. | Restrict command bitpacking to 31 bits (Bit 0 through Bit 30, maximum single bit value 1,073,741,824). Keep the sign bit unused so all scores remain positive. |
| Content Log shows: `[Molang][error]-query.property: property 'wiki:b0' not found on entity`. | Either `"client_sync": true` was omitted from the property definition in the behavior pack entity JSON, or the resource pack animation is running on a different entity than the one that owns the properties. | Ensure every bit property in the BP entity description includes `"client_sync": true` so the server transmits property updates to the client. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
