DPHelper
No reviews yet
A server-side Forge mod for Minecraft 1.20.1 that adds a 64-bit scoreboard system with fixed-point decimals, backported 1.21+ function macros with control flow, persistent variables, and NBT integration — all designed to supercharge datapacks.
Forge is a popular mod loader for versions 1.1+ of Minecraft.
Community voices
Reviews
Click once to include, again to exclude, again to clear
No reviews yet. Be the first to review this project!
Get it on
Available Platforms
About
Project Details
For authors
Embed Badge
If you're the author of this project, you can embed a live badge anywhere that supports HTML or Markdown. It updates automatically whenever ratings change.
Use HTML for any page that supports it, or Markdown for README files and Markdown-based descriptions.
Identifiers
Platform IDs
Resources
External Links
About
Description
A server-side Forge mod for Minecraft 1.20.1 that adds a 64-bit scoreboard system with fixed-point decimals, backported 1.21+ function macros with control flow, persistent variables, and NBT integration — all designed to supercharge datapacks.
Installation
- Install Minecraft Forge for 1.20.1 (loader 47+).
- Place
dphelper-1.0-SNAPSHOT.jarinto your server'smods/folder. - Start the server — no client-side mod is needed.
Vanilla clients can connect without any modifications.
What DPHelper Provides
- score64 — A 64-bit scoreboard-style system with fixed-point decimal support.
- Function Macros — Backported
function ... withmacros from 1.21+, including$lines,^context forwarding, andreturnstatements. - Persistent Variables —
/varcommand and@var!/@loaddirectives that survive server restarts. - Control Flow —
@if/@else/@endif,@switch/@case/@endswitch,@while/@endwhile,@for/@endfor, and@breakdirectly in.mcfunctionfiles. - Player Data Commands — Backported
/datacommands for player entities from 1.21.2+. - Display Entity Commands —
/display opacityand/display transformfor manipulating display entities with unsigned values and interpolation. - Falling Block Command —
/fallingblockto spawn configurable falling block entities. - NBT Integration — Read, write, and do arithmetic between score64 values and entity/block/storage NBT.
score64 System
Core Concepts
Vanilla scoreboards are limited to signed 32-bit integers (±2,147,483,647). The score64 system provides a parallel 64-bit alternative:
| Feature | Vanilla Scoreboard | score64 |
|---|---|---|
| Value range | −2³¹ to 2³¹−1 | −2⁶³ to 2⁶³−1 |
| Decimal support | ❌ | ✅ Fixed-point |
| Precision | Integer only | Configurable per-objective |
| Persists with world | ✅ | ✅ |
| Works with vanilla clients | ✅ | ✅ |
| Sidebar / nametag display | ✅ Native | Via sync bridge |
score64 does NOT replace or modify the vanilla scoreboard. It is a completely parallel system.
Objectives
Each score64 objective has:
- Name — A unique string identifier (e.g.
energy,currency,distance) - Scale — A long integer ≥ 1 that defines decimal precision
| Scale | Decimal Places | Example |
|---|---|---|
1 |
0 (integers only) | 42 |
100 |
2 | 42.50 |
1000 |
3 | 42.500 |
1000000 |
6 | 42.500000 |
Holders
Holders are the entities or names that have scores — identical to vanilla scoreboard holders:
- Player names —
Steve,Alex - Entity selectors —
@a,@p,@e[type=zombie] - Fake players —
#temp,$counter,MyVar - Arbitrary strings — anything used by datapacks
Fixed-Point Decimals
Values are stored as raw long integers, scaled by the objective's scale factor:
raw = round(input × scale)
For example, with scale = 1000:
- Input
2.5→ stored as2500 - Input
3.141→ stored as3141 - Input
-0.001→ stored as-1
No floating-point math is ever used. All parsing and arithmetic uses pure integer operations with BigInteger for intermediate computations, ensuring deterministic results. Rounding mode: HALF_UP.
Objective Management
All commands are under /score64 and require operator permission level 2.
| Command | Description |
|---|---|
/score64 objectives add <name> |
Create integer objective (scale=1) |
/score64 objectives add <name> <scale> |
Create fixed-point objective |
/score64 objectives list |
List all objectives |
/score64 objectives remove <name> |
Remove objective + all its data |
Examples:
/score64 objectives add coins
/score64 objectives add energy 1000
/score64 objectives add precise_pos 1000000
Player / Holder Values
| Command | Description |
|---|---|
/score64 players set <targets> <obj> <value> |
Set value |
/score64 players add <targets> <obj> <value> |
Add to value |
/score64 players remove <targets> <obj> <value> |
Subtract from value |
/score64 players get <target> <obj> |
Display value |
/score64 players reset <targets> <obj> |
Remove score from objective |
/score64 players reset <targets> |
Remove all scores |
<targets>: @a, @s, @p, @e[...], player name, fake player (#var)
<value>: "42", "3.14", "-0.5", ".25"
> Note: Decimal values must be quoted as strings in commands.
Examples:
/score64 players set @s energy "100.5"
/score64 players set #temp coins "999999999999"
/score64 players add @s energy "1.5"
/score64 players remove @s energy "0.25"
/score64 players get @s energy
Output example:
Steve has energy = 2.020 (raw: 2020, scale: 1000)
Arithmetic Operations
/score64 players operation <target> <targetObj> <op> <source> <sourceObj>
All operations work on raw stored values (not formatted decimals).
| Op | Meaning |
|---|---|
= |
target = source |
+= |
target += source |
-= |
target −= source |
*= |
target ×= source |
/= |
target ÷= source (integer division, 0 = no change) |
%= |
target %= source (modulo, 0 = no change) |
< |
target = min(target, source) |
> |
target = max(target, source) |
>< |
swap target and source |
min |
target = min(target, source) |
max |
target = max(target, source) |
> Operators containing special characters (=, *, %, <, >) must be quoted: "*=", "+=", "<", "><", etc.
> Word-only operators (min, max) can be unquoted.
> Important: When using *= or /= with fixed-point objectives, operations work on raw values. Multiplying two scale-1000 values produces a value at scale 1000000. You may need a follow-up /= by the scale to correct the decimal point.
Examples:
/score64 players operation @s total += @s income total
/score64 players operation #result math *= #factor math
/score64 players operation @s health min #max_hp health
Math Library
All math commands: /score64 math ...
Unary Operations
| Command | Description |
|---|---|
/score64 math abs <target> <obj> |
Absolute value |
/score64 math neg <target> <obj> |
Negate |
/score64 math sign <target> <obj> |
Sign (−1, 0, or 1) |
/score64 math sqrt <target> <obj> |
Scale-aware square root (negative → 0) |
sqrt is scale-aware: for scale S and raw value R, it computes floor(sqrt(R × S)), correctly representing sqrt(R/S) in fixed-point.
Binary Operations (literal value or holder reference)
/score64 math <func> <target> <obj> <value>
/score64 math <func> <target> <obj> from <source> <sourceObj>
| Function | Description |
|---|---|
add |
target += operand |
sub |
target −= operand |
mul |
target ×= operand |
div |
target ÷= operand |
mod |
target %= operand |
min |
target = min(target, operand) |
max |
target = max(target, operand) |
Advanced Operations
| Command | Description |
|---|---|
/score64 math pow <target> <obj> <exponent> |
Integer power (O(log n)) |
/score64 math clamp <target> <obj> <min> <max> |
Clamp to range |
/score64 math random <target> <obj> <min> <max> |
Random long in [min, max] |
/score64 math atan2 <target> <obj> <source> <sourceObj> |
Angle in radians × scale |
Examples:
/score64 math abs @s velocity
/score64 math pow @s power 3
/score64 math clamp @s health 0 100000
/score64 math random @s loot_roll 1 100
/score64 math add @s coins "10.50"
/score64 math mul @s damage from #multiplier damage
NBT Integration
Read, write, and perform arithmetic between score64 values and Minecraft NBT data.
Read NBT → score64
/score64 nbt get <holder> <obj> entity <selector> <path>
/score64 nbt get <holder> <obj> block <pos> <path>
/score64 nbt get <holder> <obj> storage <id> <path>
Float/double NBT values are truncated toward zero, matching vanilla behavior.
Scaled mode (preserves float/double precision):
/score64 nbt get <holder> <obj> entity <selector> <path> scaled
/score64 nbt get <holder> <obj> entity <selector> <path> <scale>
When scaled is specified, float/double values are multiplied by the objective's scale then truncated: raw = (long)(nbt_value × scale).
An explicit numeric scale can also be provided instead.
| Example | Scale | NBT Value | Stored Raw |
|---|---|---|---|
Rotation[0] |
100000 | -0.00061 |
-61 |
Pos[1] |
1000 | 64.5 |
64500 |
Health |
1 | 20.0 |
20 |
Write score64 → NBT
/score64 nbt set entity <selector> <path> <holder> <obj>
/score64 nbt set block <pos> <path> <holder> <obj>
/score64 nbt set storage <id> <path> <holder> <obj>
Default: writes raw value as TAG_Long.
Scaled write mode (as_scaled):
/score64 nbt set entity <selector> <path> <holder> <obj> as_scaled
Divides by the objective's scale and writes as TAG_Double: value_to_write = raw / scale.
Arithmetic with NBT operand
/score64 nbt op <holder> <obj> <op> entity <selector> <path>
/score64 nbt op <holder> <obj> <op> block <pos> <path>
/score64 nbt op <holder> <obj> <op> storage <id> <path>
Ops: "=" "+=" "-=" "*=" "/=" "%="
Entity Yaw & Pitch
Convenient shortcuts to read an entity's rotation:
/score64 nbt yaw <holder> <obj> entity <selector>
/score64 nbt yaw <holder> <obj> entity <selector> <scale>
/score64 nbt yaw <holder> <obj> entity <selector> scaled
/score64 nbt pitch <holder> <obj> entity <selector>
/score64 nbt pitch <holder> <obj> entity <selector> <scale>
/score64 nbt pitch <holder> <obj> entity <selector> scaled
| Variant | Behavior |
|---|---|
| No modifier | Truncates to integer (e.g. 45.7 → 45) |
<scale> |
(long)(rotation × scale) |
scaled |
Uses the objective's scale |
Examples:
score64 nbt yaw @s facing entity @s
score64 objectives add facing 1000
score64 nbt yaw @s facing entity @s scaled
score64 nbt pitch @s look entity @s 100
NBT Examples:
/score64 nbt get @s health entity @s Health
/score64 nbt set storage mypack:data Result.value #result math
/score64 nbt op @s damage "*=" entity @s AttackDamage
score64 nbt get @s rotation entity @s Rotation[0] scaled
score64 nbt set entity @s Rotation[0] @s rotation as_scaled
Result Storage
score64 store command
/score64 store <target> <obj> run <command>
Runs <command>, stores its integer return value into score64. For decimal objectives, the result is multiplied by the scale.
execute store integration
execute store result score64 <target> <obj> run <command>
execute store success score64 <target> <obj> run <command>
result: stores the command's integer return value × scalesuccess: stores scale (= 1.0 in display) if succeeded, 0 if failed
Examples:
/score64 store #count enemies run execute if entity @e[type=zombie]
/score64 store @s xp_level run xp query @s levels
execute store result score64 @s energy run data get entity @s Air
execute store success score64 @s flag run say test
Vanilla Scoreboard Sync
Bridge score64 values to the vanilla scoreboard for sidebar/nametag display.
| Command | Description |
|---|---|
/score64 sync <obj64> <obj32> <target> |
Copy one holder to vanilla objective |
/score64 syncall <obj64> <obj32> |
Copy all holders to vanilla objective |
Values are clamped to ±2,147,483,647 (32-bit). A yellow warning appears if clamping occurs. The score64 value is never modified by syncing.
Example workflow:
scoreboard objectives add energy_display dummy
/score64 objectives add energy 1000
/score64 syncall energy energy_display
Execute Conditions
Range match
execute if score64 <target> <obj> matches <range> run ...
execute unless score64 <target> <obj> matches <range> run ...
| Range | Meaning |
|---|---|
"5" |
Exactly 5 |
"3..7" |
3 to 7 inclusive |
"..7" |
At most 7 |
"3.." |
At least 3 |
> Ranges use raw values. For scale=1000: checking ≥ 2.5 → "2500.."
Comparison
execute if score64 <target> <obj> <cmp> <source> <sourceObj> run ...
execute unless score64 <target> <obj> <cmp> <source> <sourceObj> run ...
Comparators: < <= = >= >
Examples:
execute if score64 @s energy matches "1000.." run say I have at least 1.0 energy
execute if score64 @s health < #threshold health run say Low health!
execute if score64 @s score = #target_score score run say Matched!
Predicates (JSON)
DPHelper registers custom loot conditions usable in advancements, loot tables, and execute if predicate.
dphelper:score64_range
Check whether a score64 value falls within a range.
{
"condition": "dphelper:score64_range",
"target": "this",
"objective": "energy",
"min": 0,
"max": 1000000
}
| Field | Required | Description |
|---|---|---|
target |
✅ | "this", "killer", "direct_killer", or any string (fake player) |
objective |
✅ | score64 objective name |
min |
❌ | Minimum raw value (inclusive) |
max |
❌ | Maximum raw value (inclusive) |
dphelper:score64_compare
Compare two score64 holders.
{
"condition": "dphelper:score64_compare",
"target": "this",
"objective": "energy",
"other_target": "killer",
"other_objective": "energy",
"operation": ">="
}
Supported operations: ==, !=, <, <=, >=, >
dphelper:nbt_numeric_range
Check a numeric NBT value on an entity.
{
"condition": "dphelper:nbt_numeric_range",
"target": "this",
"path": "CustomData.energy",
"min": 0,
"max": 1000
}
| Field | Required | Description |
|---|---|---|
target |
✅ | "this", "killer", or "direct_killer" |
path |
✅ | Dot-separated NBT path (e.g. "CustomData.level") |
min |
❌ | Minimum value (inclusive) |
max |
❌ | Maximum value (inclusive) |
Function Macros
> These features are backported from 1.21.2+ to 1.20.1 Forge by DPHelper. > They use the same syntax as vanilla 1.21+ so datapacks port seamlessly.
How It Works
- Write a
.mcfunctionfile with macro lines — lines starting with$ - Use
$(variable)placeholders inside those lines - Call the function with
/function <id> with ...to pass in the variables
Macro Invocation Syntax
/function <id> with args <compound>
/function <id> with entity <selector> [<path>]
/function <id> with block <pos> [<path>]
/function <id> with storage <id> [<path>]
/function <id> with var <namespace>
| Source | Description |
|---|---|
args <compound> |
Inline NBT compound (e.g. {key:"value"}) |
entity <selector> [<path>] |
Read NBT from an entity, optionally at a sub-path |
block <pos> [<path>] |
Read NBT from a block entity, optionally at a sub-path |
storage <id> [<path>] |
Read NBT from command storage, optionally at a sub-path |
var <namespace> |
Read from persistent DPHelper variables (see /var command) |
The top-level keys of the resolved compound become macro variables. String tags are unwrapped (no quotes); numeric tags become decimal strings; other types use SNBT.
Special Prefixes in .mcfunction Files
| Prefix | Description |
|---|---|
$ |
Macro line — $(var) placeholders are substituted at runtime, then the command is executed |
^ |
Macro call — calls another function, automatically forwarding the current macro context |
return |
Return statement — stops the function and returns a value (return <n>, return run <cmd>, return fail) |
@var |
Local variable — @var name = value sets a variable in the current scope |
@var! |
Persistent variable — @var! ns:id key = value saves to disk (survives restart) |
@load |
Load namespace — @load ns:id loads all persistent variables into scope |
@if |
Conditional block — @if <condition> starts a conditional |
@else |
Else branch — flips the current @if condition |
@endif |
End conditional — closes the @if block |
@switch |
Switch block — @switch <value> starts a switch on a value |
@case |
Case branch — @case <value> executes if the switch value matches |
@default |
Default branch — executes if no @case matched |
@endswitch |
End switch — closes the @switch block |
@while |
While loop — @while <condition> repeats the body while condition is true |
@endwhile |
End while — closes the @while block |
@for |
For loop — @for <var> <start> <end> [<step>] iterates a counter |
@endfor |
End for — closes the @for block |
@break |
Break — exits the innermost @for or @while loop early |
Lines without $ or ^ are parsed normally at load time (like vanilla).
Writing Macro Functions
Example function file (mypack:greet.mcfunction):
# This line is parsed at load time — no macros
say Starting greeting...
# These lines are macro lines — parsed at run time after substitution
$say Hello $(player)! You earned $(amount) diamonds.
$give $(player) minecraft:diamond $(amount)
Calling it:
function mypack:greet with args {player:"Steve",amount:"5"}
Result:
say Hello Steve! You earned 5 diamonds.
give Steve minecraft:diamond 5
From command storage:
data merge storage mypack:args {player:"Alex",amount:"10"}
function mypack:greet with storage mypack:args
From entity NBT (sub-path):
# If the entity has {data:{target:"Steve",count:3}}
function mypack:greet with entity @s data
The ^ Prefix — Forwarding Macro Context
Use ^ at the start of a line to call another function with the same macro variables automatically forwarded. No need to set up storage or pass with args again.
Three forms are supported:
# 1. Bare function id — call directly with forwarded context
^namespace:function_name
# 2. Execute chain — conditions, selectors, positioning, etc.
^execute <modifiers...> run namespace:function_name
# 3. Dynamic function name — $(var) in the id itself
^mypack:$(branch)
Example — Simple forwarding:
mypack:main.mcfunction:
$say Player $(name) has $(score) points
^mypack:reward
mypack:reward.mcfunction:
$say Rewarding $(name) for $(score) points!
$give $(name) minecraft:diamond $(score)
function mypack:main with args {name:"Steve",score:"5"}
Output:
[Server] Player Steve has 5 points
[Server] Rewarding Steve for 5 points!
Example — Conditional execution with execute if:
meteor:tick.mcfunction:
$say State check for $(target)
^execute if score temp meteor_states matches 1.. run meteor:apply_effect
Example — Execute as/at for all players:
mypack:broadcast.mcfunction:
$say Broadcasting event: $(event)
^execute as @a at @s run mypack:per_player_effect
Example — Dynamic function name:
mypack:dispatcher.mcfunction:
$say Running mode: $(mode)
^mypack:modes/$(mode)
Example — Chained ^ calls (multi-step pipeline):
mypack:pipeline.mcfunction:
$say === Pipeline for $(target) ===
^mypack:step1
^execute if score $(target) mypack_hp matches ..5 run mypack:step_heal
^mypack:step_final
Each ^ call shares the same macro variables without any manual forwarding.
Nested Macro Calls
Macro contexts are stack-based. A macro function can call another macro function with different variables — each call pushes a new scope, and it's popped when the function returns. Variables from outer calls don't leak into inner calls.
# outer.mcfunction
$say Outer: $(msg)
$function mypack:inner with args {msg:"inner message"}
$say Back to outer: $(msg)
# inner.mcfunction
$say Inner: $(msg)
Calling function mypack:outer with args {msg:"hello"} produces:
Outer: hello
Inner: inner message
Back to outer: hello
The ^ prefix, on the other hand, shares the same scope — $(msg) stays "hello" in both functions.
Missing variables: If a $(variable) has no matching key in the provided compound, it is replaced with an empty string. No error is thrown.
Function Return Values
Backports the 1.20.4+ return statement to 1.20.1. Stops function execution and returns a value to the caller.
return <value> # Stop the function and return an integer value
return run <command> # Stop the function and return the command's result
return fail # Stop the function and return 0 (failure)
When return is executed, all remaining lines in the function are skipped. The returned value becomes the function's result (usable by execute store, score64 store, etc.).
$(var) placeholders are resolved in return lines when inside a macro context.
Examples:
# mypack:get_five.mcfunction
return 5
say This line never runs
# mypack:get_health.mcfunction
return run data get entity @s Health 1
# Conditional early return
execute if score @s my_obj matches 0 run return fail
say Processing...
return run scoreboard players get @s my_obj
# Chained return with execute store
execute store result score @s doubled run function mypack:double_health
Variables
DPHelper adds a persistent variable system. Variables are stored in namespaces (like command storage) and survive server restarts.
/var Command
/var set <namespace> <key> <value>
/var get <namespace> [<key>]
/var remove <namespace> [<key>]
/var list [<namespace>]
| Command | Description |
|---|---|
var set mypack:config max_hp 100 |
Set variable max_hp to "100" in namespace mypack:config |
var get mypack:config max_hp |
Print the value of max_hp |
var get mypack:config |
Print all variables in the namespace |
var remove mypack:config max_hp |
Delete a single variable |
var remove mypack:config |
Delete the entire namespace |
var list |
List all namespaces |
var list mypack:config |
List all variables in a namespace |
All values are stored as strings. The return value of var get is the string length (for execute store).
@var — Local Variables
Set a variable in the current function scope. Available as $(name) in subsequent lines.
@var greeting = Hello World
$say $(greeting)
# Output: Hello World
@var count = 5
$give @s minecraft:diamond $(count)
# Compose from other variables
@var full = Player $(name) has $(count) items
$say $(full)
@var! — Persistent Variables
Set a variable that persists across restarts. Also available as $(key) immediately.
# Save to disk AND set in current scope
@var! mypack:stats kill_count = 42
$say Kills: $(kill_count)
@load — Load Persistent Vars into Scope
Load all variables from a namespace into the current scope.
@load mypack:config
# Now $(max_hp), $(difficulty), etc. are all available
$say Max HP: $(max_hp), Difficulty: $(difficulty)
with var — Call Function with Persistent Vars
function mypack:setup with var mypack:config
This loads all variables from mypack:config as macro variables for the function.
Example — Config system (set once, use everywhere):
# Setup (run once)
var set mypack:config max_hp 100
var set mypack:config spawn_rate 5
var set mypack:config difficulty hard
mypack:apply_config.mcfunction:
@load mypack:config
$say Max HP: $(max_hp), Spawn rate: $(spawn_rate), Mode: $(difficulty)
$scoreboard players set #max_hp config $(max_hp)
Example — Dynamic function selection based on persistent config:
var set mypack:config mode hard
function mypack:run_mode with var mypack:config
mypack:run_mode.mcfunction:
$say Running mode: $(mode)
^mypack:modes/$(mode)
Control Flow
Conditional Blocks (@if / @else / @endif)
If/else control flow directly inside .mcfunction files. No more splitting logic into dozens of separate functions.
@if <condition>
# commands to run if true
@else
# commands to run if false
@endif
The <condition> uses the same syntax as execute if — everything that follows execute if in a vanilla command:
entity <selector>score <target> <objective> matches <range>score <target> <objective> <op> <source> <sourceObjective>block <pos> <block>blocks <start> <end> <dest> <mode>data entity|block|storage ...predicate <id>
The @else branch is optional. Blocks can be nested.
Example — Basic if/else:
@if entity @s[tag=vip]
say Welcome, VIP!
give @s minecraft:diamond 10
@else
say Welcome!
give @s minecraft:diamond 1
@endif
Example — Score check:
@if score @s level matches 10..
say You are level 10 or higher!
effect give @s minecraft:strength 60 1
@endif
Example — Nested conditions:
@if entity @s[tag=admin]
say You are an admin
@if score @s power matches 100..
say And you have max power!
effect give @s minecraft:glowing 10 0
@else
say But your power is below 100
@endif
@else
say You are not an admin
@endif
Example — With macros (dynamic conditions):
$@if score $(target) kills matches $(threshold)..
$say $(target) has enough kills!
$give $(target) minecraft:diamond 1
$@endif
> Use $@if when the condition itself contains $(var) — the $ triggers macro substitution first.
Example — Combined with @var and @load:
@load mypack:config
@if score @s level matches 10..
@var reward = 10
@else
@var reward = 1
@endif
$give @s minecraft:diamond $(reward)
$say You received $(reward) diamonds!
Switch Blocks (@switch / @case / @default / @endswitch)
Match a value against multiple cases without chaining if/else blocks.
@switch <value>
@case <value1>
# commands if value matches value1
@case <value2>
# commands if value matches value2
@default
# commands if no case matched
@endswitch
The <value> in @switch is evaluated once (with macro substitution if using $@switch). Only the first matching @case executes. The @default branch executes only if no @case matched. Switch blocks can be nested.
Example — Basic switch on a variable:
@load mypack:config
@switch $(mode)
@case easy
say Easy mode — full healing
effect give @s minecraft:regeneration 30 2
@case normal
say Normal mode — standard gameplay
@case hard
say Hard mode — good luck!
effect give @s minecraft:hunger 60 1
@default
say Unknown mode: using normal
@endswitch
Example — Switch with macros (dynamic values):
$@switch $(class)
$@case warrior
$say $(player) is a warrior — bonus strength!
$effect give $(player) minecraft:strength 60 1
$@case mage
$say $(player) is a mage — bonus speed!
$effect give $(player) minecraft:speed 60 1
$@default
$say $(player) has no class assigned
$@endswitch
Example — Switch for dynamic function dispatch:
@load mypack:config
@switch $(difficulty)
@case peaceful
^mypack:setup/peaceful
@case normal
^mypack:setup/normal
@case hardcore
^mypack:setup/hardcore
@endswitch
While Loops (@while / @endwhile)
Repeat a block of commands as long as a condition is true.
@while <condition>
# commands to repeat
@endwhile
The <condition> uses the same syntax as execute if. The condition is re-evaluated before each iteration. A safety limit of 65,536 iterations prevents infinite loops.
Example — Countdown with scoreboard:
@while score @s temp matches 1..
$say Counter: $(counter)
scoreboard players remove @s temp 1
@endwhile
say Done!
Example — Process items in storage:
@while data storage mypack:queue Items[0]
say Processing next item...
data remove storage mypack:queue Items[0]
@endwhile
say Queue empty!
Example — Nested while loops:
scoreboard players set @s outer_count 3
@while score @s outer_count matches 1..
scoreboard players set @s inner_count 3
@while score @s inner_count matches 1..
say Inner iteration
scoreboard players remove @s inner_count 1
@endwhile
say Outer iteration
scoreboard players remove @s outer_count 1
@endwhile
If a @while loop exceeds 65,536 iterations, it breaks automatically and a warning is logged.
For Loops (@for / @endfor)
Counter-based loops with a variable you can reference.
@for <var> <start> <end> [<step>]
# commands to repeat — $(var) is available
@endfor
| Parameter | Description |
|---|---|
<var> |
Variable name — available as $(var) inside the loop body |
<start> |
Starting value (inclusive) |
<end> |
Ending value (inclusive) |
<step> |
Optional step increment. Defaults to 1 if start ≤ end, or -1 if start > end |
A safety limit of 65,536 iterations prevents infinite loops.
Example — Count from 1 to 10:
@for i 1 10
$say Number: $(i)
@endfor
Example — Countdown from 5 to 1:
@for i 5 1
$say Countdown: $(i)
@endfor
say Go!
Example — Custom step (even numbers):
@for i 2 20 2
$say Even: $(i)
@endfor
Example — Spawn entities at intervals:
@for x 0 10
$summon minecraft:armor_stand $(x) 64 0
@endfor
Example — With macros (dynamic range):
$@for i 1 $(max_count)
$say Iteration $(i) of $(max_count) for player $(player)
$give $(player) minecraft:diamond 1
$@endfor
Example — Nested for loops (grid pattern):
@for x 0 5
@for z 0 5
$setblock $(x) 64 $(z) minecraft:stone
@endfor
@endfor
Example — Combined with @if:
@for i 1 20
$scoreboard players set #temp obj $(i)
@if score #temp obj matches 10..
$say $(i) is 10 or higher
@else
$say $(i) is below 10
@endif
@endfor
Example — Tower builder:
@for y 64 74
$setblock 100 $(y) 200 minecraft:stone
@endfor
say Built a 10-block tower!
Break Statement (@break)
@break exits the innermost @for or @while loop early. When reached, the remaining body entries in the current iteration are skipped and no further iterations run.
@break only affects the innermost enclosing loop. In nested loops, the outer loop continues normally.
Example — Search and stop:
@for i 1 20
$execute as @e[tag=target,limit=1,sort=nearest,distance=..$(i)] run tag @s add found
@if entity @e[tag=found]
$say Found target within $(i) blocks
@break
@endif
@endfor
Example — While loop with early exit:
@while score @s attempts matches 1..
scoreboard players remove @s attempts 1
@if data storage mypack:state {done:"true"}
say Finished early!
@break
@endif
say Still trying...
@endwhile
Example — Nested loops (break only exits inner loop):
@for x 0 10
@for z 0 10
$setblock $(x) 64 $(z) minecraft:stone
@if score @s limit matches ..0
@break
@endif
scoreboard players remove @s limit 1
@endfor
$say Finished row $(x)
@endfor
Player Data Commands
Backports the 1.21.2+ change that allows /data commands to target player entities.
In vanilla 1.20.1, all /data commands on players fail with "Can't modify player data".
With DPHelper installed, they work — matching vanilla 1.21.2+ behavior.
What's Unlocked
| Command | Vanilla 1.20.1 | With DPHelper |
|---|---|---|
/data get entity @s |
❌ Blocked | ✅ Works |
/data get entity @s Health |
❌ Blocked | ✅ Works |
/data merge entity @s {Health:10f} |
❌ Blocked | ✅ Works |
/data modify entity @s Inventory[0].Count set value 64 |
❌ Blocked | ✅ Works |
/data modify entity @s Motion[1] set value 20d |
❌ Blocked | ✅ Works |
/data remove entity @s Inventory[0] |
❌ Blocked | ✅ Works |
/data get entity @e[type=pig,limit=1] |
✅ Works | ✅ Works |
Restricted Tags (Safety)
To match vanilla 1.21.2+ behavior, certain identity-critical tags are filtered on writes to prevent crashes, desyncs, or exploits:
| Tag | Reason |
|---|---|
UUID, UUIDMost, UUIDLeast |
Player identity — changing breaks everything |
Pos |
Position desync with client |
Dimension |
Forced dimension transfer — crashes/exploits |
RootVehicle |
Vehicle binding — duplication exploits |
WorldUUIDMost, WorldUUIDLeast |
Forge world tracking |
id |
Entity type — cannot change a player into a pig |
These tags are silently stripped from the data before it's applied. Reading them with /data get still works fine.
Live Field Sync
When writing player data, certain fields are re-applied to the entity's live state after the NBT load to ensure they take effect immediately:
| Field | Behavior |
|---|---|
Motion |
Applied via setDeltaMovement() + synced to client with unclamped float precision |
Rotation |
Applied via setYRot() / setXRot() |
FallDistance |
Applied directly to the entity field |
Fire |
Applied via setRemainingFireTicks() |
Velocity sync note: Vanilla's ClientboundSetEntityMotionPacket clamps velocity to ±4.096 blocks/tick. DPHelper uses ClientboundExplodePacket to sync velocity with float precision, allowing values like Motion[1] = 2000d to actually launch the player.
Player Data Examples
# Read player health
data get entity @s Health
# Read a specific inventory slot
data get entity @s Inventory[{Slot:0b}]
# Set player health
data merge entity @s {Health:1f}
# Modify inventory count
data modify entity @s Inventory[{Slot:0b}].Count set value 64
# Launch a player upward
data modify entity @s Motion[1] set value 20d
# Copy data between player and storage
data modify storage mypack:data SavedItem set from entity @s Inventory[{Slot:0b}]
data modify entity @s Inventory[{Slot:0b}] set from storage mypack:data SavedItem
# Give a player custom tags
data merge entity @s {Tags:["vip","admin"]}
# Remove a specific effect
data remove entity @s active_effects[{id:"minecraft:poison"}]
# Combine with score64 — read health with decimal precision
score64 objectives add hp 100
score64 nbt get @s hp entity @s Health scaled
# Health 18.5 → stored as 1850, displays as 18.50
# Write a score64 value back to player health
score64 players set @s hp "10.00"
score64 nbt set entity @s Health @s hp as_scaled
# 1000 / 100 = 10.0 → written as TAG_Double 10.0
Falling Block Command
Spawns a FallingBlockEntity with any block's appearance. It falls like sand and places the block where it lands. An optional NBT compound lets you configure motion, fall damage, gravity, and more.
Syntax
/fallingblock <block>
/fallingblock <block> <pos>
/fallingblock <block> <pos> <nbt>
/fallingblock convert <blockPos>
/fallingblock convert <blockPos> <nbt>
| Parameter | Description |
|---|---|
<block> |
Any block id, including block states (e.g. minecraft:oak_stairs[facing=east]) |
<pos> |
Spawn position (supports ~ ~ ~ relative coords). Defaults to executor position |
<nbt> |
Optional NBT compound to configure the entity |
<blockPos> |
Position of an existing block in the world to convert into a falling entity |
The convert variant reads the block at the given position, removes it from the world (replaces with air), and spawns a falling block entity with that block's state.
Supported NBT Tags
| Tag | Type | Default | Description |
|---|---|---|---|
Motion |
[double, double, double] |
[0d, 0d, 0d] |
Initial velocity (X, Y, Z) |
FallDistance |
float |
0.0f |
Starting fall distance for damage calculation |
HurtEntities |
byte |
0b |
1b to deal damage to entities on impact |
FallHurtMax |
int |
40 |
Max damage dealt on impact |
FallHurtAmount |
float |
2.0f |
Damage per block fallen |
DropItem |
byte |
0b |
1b to drop as item if it can't place |
Time |
int |
1 |
Ticks the entity has existed |
NoGravity |
byte |
0b |
1b to disable gravity (floats in place) |
Glowing |
byte |
0b |
1b to apply glowing outline |
Tags |
string list |
[] |
Scoreboard tags for targeting with selectors |
Falling Block Behavior
- Falls with gravity (unless
NoGravity:1b) - When it hits a solid surface, it places the block at the landing position
- If it can't place (e.g. another block is there), it disappears silently (unless
DropItem:1b)
Falling Block Examples
# Basic — spawn a falling diamond block above you
fallingblock minecraft:diamond_block ~ ~10 ~
# With motion — launch a glass block sideways
fallingblock minecraft:glass ~ ~5 ~ {Motion:[2.0d,1.0d,0d]}
# Damaging anvil drop — hurts entities on impact
fallingblock minecraft:anvil ~ ~30 ~ {HurtEntities:1b,FallHurtAmount:10.0f,FallHurtMax:100}
# Pre-charged fall distance — instant kill anvil
fallingblock minecraft:anvil ~ ~2 ~ {HurtEntities:1b,FallDistance:50.0f,FallHurtMax:999}
# Floating glowing block — no gravity, tagged for targeting
fallingblock minecraft:sea_lantern ~ ~3 ~ {NoGravity:1b,Glowing:1b,Time:-2147483648,Tags:["light","decoration"]}
# Any block state — falling stairs with specific orientation
fallingblock minecraft:oak_stairs[facing=east,half=top] ~ ~20 ~
# Meteor effect — fast downward magma that damages on impact
fallingblock minecraft:magma_block ~ ~50 ~ {Motion:[0d,-3.0d,0d],HurtEntities:1b,FallHurtAmount:5.0f}
# Combine with macros — dynamic block type and height
$fallingblock $(block) ~ ~$(height) ~ {HurtEntities:$(hurt)}
# Convert a block at a position — make it fall like sand
fallingblock convert 100 64 200
# Convert with motion — launch the block sideways
fallingblock convert ~ ~-1 ~ {Motion:[0d,1.0d,2.0d]}
# Convert with damage — make a block fall and hurt on impact
fallingblock convert 50 80 50 {HurtEntities:1b,FallHurtAmount:8.0f}
# Collapse a column — convert multiple blocks in a loop
execute positioned 100 70 200 run fallingblock convert ~ ~ ~
execute positioned 100 71 200 run fallingblock convert ~ ~ ~
execute positioned 100 72 200 run fallingblock convert ~ ~ ~
Display Entity Commands
Commands for manipulating display entities (text_display, block_display, item_display). Designed for smooth animations and transitions using Minecraft's display entity interpolation system.
Syntax
/display opacity <targets> <value>
/display opacity <targets> <value> <interpolation>
/display transform <targets> <nbt>
/display transform <targets> <nbt> <interpolation>
| Parameter | Description |
|---|---|
<targets> |
Entity selector — only display entities are affected, others are skipped |
<value> |
Unsigned opacity byte (0 = fully transparent, 255 = fully opaque) |
<nbt> |
NBT compound to merge onto the display entity |
<interpolation> |
Optional interpolation duration in ticks for smooth transition |
Opacity
Sets the text_opacity field on display entities using an unsigned value (0–255). Vanilla stores this as a signed byte (-128 to 127), but the command accepts the more intuitive unsigned range.
| Value | Effect |
|---|---|
0 |
Fully transparent (invisible) |
1 |
Nearly invisible |
128 |
Half transparent |
255 |
Fully opaque (default) |
When <interpolation> is provided, interpolation_duration is set and start_interpolation is set to 0 so the transition begins immediately.
Transform
Merges any NBT compound onto the targeted display entities. This is a general-purpose command — it can modify transformation, billboard, shadow_radius, view_range, glow_color_override, or any other display entity property.
When <interpolation> is provided, the entity smoothly transitions from its current state to the new one over the specified number of ticks.
Display Entity Examples
# Fade a text display to nearly invisible over 2 seconds
display opacity @s 1 40
# Make a text display fully opaque instantly
display opacity @e[type=text_display,tag=label] 255
# Half transparency with 1-second interpolation
display opacity @s 128 20
# Scale a display entity up smoothly over 2 seconds
display transform @s {transformation:{scale:[5f,5f,1f]}} 40
# Change billboard mode instantly
display transform @s {billboard:"center"}
# Move and rotate with interpolation
display transform @s {transformation:{translation:[0f,2f,0f],left_rotation:[0f,0.707f,0f,0.707f]}} 60
# Combine with macros — dynamic opacity
$display opacity @s $(opacity) $(fade_time)
# Combine with for loop — sequential fade
@for i 0 255 5
$display opacity @e[tag=fade_target] $(i) 2
@endfor
Datapack Usage Examples
Economy System (2 Decimal Places)
# init.mcfunction (load)
score64 objectives add coins 100
# give_coins.mcfunction
score64 players add @s coins "10.50"
# buy_item.mcfunction
score64 players remove @s coins "3.99"
# check_balance.mcfunction
score64 players get @s coins
# transfer.mcfunction (from @s to #shop)
score64 players operation #shop coins "+=" @s coins
score64 players set @s coins "0"
Precise Position Tracking (6 Decimal Places)
score64 objectives add pos_x 1000000
score64 objectives add pos_z 1000000
score64 store @s pos_x run data get entity @s Pos[0] 1000000
High-Score Counter Beyond 32-bit
score64 objectives add total_xp
score64 players add @s total_xp "1"
# Show on vanilla sidebar (clamped to 32-bit for display)
scoreboard objectives add xp_display dummy
score64 syncall total_xp xp_display
Conditional Logic
# Only run if player has ≥ 1.00 coins (raw 100 with scale 100)
execute if score64 @s coins matches "100.." run say Rich!
# Compare two players
execute if score64 @s score > @p[tag=opponent] score run say I'm winning!
Random Loot Rolls
score64 objectives add roll
score64 math random @s roll 1 100
execute if score64 @s roll matches "90.." run say Legendary drop!
execute if score64 @s roll matches "70..89" run say Rare drop!
Math Library — Distance Calculation
# Compute 2D distance: sqrt(dx² + dy²)
score64 objectives add dist 1000
score64 objectives add dx 1000
score64 objectives add dy 1000
score64 objectives add temp 1000
# temp = dx * dx
score64 players operation #calc temp = #calc dx
score64 math mul #calc temp from #calc dx
# dist = dy * dy
score64 players operation #calc dist = #calc dy
score64 math mul #calc dist from #calc dy
# dist = dx² + dy²
score64 math add #calc dist from #calc temp
# dist = sqrt(dist)
score64 math sqrt #calc dist
Using score64 Random with Macros
score64 math random @s temp 1 100
score64 nbt set storage mypack:args value @s temp
function mypack:use_random with storage mypack:args
mypack:use_random.mcfunction:
$say Random result: $(value)
Predicate in an Advancement
Create data/mypack/predicates/has_energy.json:
{
"condition": "dphelper:score64_range",
"target": "this",
"objective": "energy",
"min": 1000
}
Use with execute if predicate mypack:has_energy.
Technical Details
Persistence
- Data is stored via Minecraft's
SavedDatasystem - Attached to the overworld dimension
- Saved automatically when the world saves
- File location:
<world>/data/dphelper_score64.dat - NBT format: objectives list + nested compound tags for values
- Safe across server restarts and crashes (uses Minecraft's atomic save)
Overflow Behavior
All arithmetic uses Java long semantics — modular wraparound on overflow.
Long.MAX_VALUE + 1 = Long.MIN_VALUE
9223372036854775807 + 1 = -9223372036854775808
This is deterministic and matches how vanilla int scoreboards behave (just with 64 bits).
Performance
- O(1) lookup for any value (HashMap-based)
- No per-tick overhead — data is only accessed when commands are executed
- No world scanning — holders are string identifiers, not entity references
- Efficient for thousands of holders per objective
setDirty()is called only on mutations, not reads
Compatibility Table
| Feature | Vanilla 1.21.2+ syntax | DPHelper on 1.20.1 |
|---|---|---|
/function <id> with args {...} |
✅ Native | ✅ Identical syntax |
/function <id> with storage <id> |
✅ Native | ✅ Identical syntax |
/function <id> with entity <sel> |
✅ Native | ✅ Identical syntax |
/function <id> with block <pos> |
✅ Native | ✅ Identical syntax |
/function <id> with var <ns> |
❌ Not in vanilla | ✅ DPHelper exclusive |
$ macro lines in .mcfunction |
✅ Native | ✅ Identical syntax |
^ context-forwarding calls |
❌ Not in vanilla | ✅ DPHelper exclusive |
return / return run in functions |
✅ Native (1.20.4+) | ✅ Identical syntax |
@var / @var! local/persistent vars |
❌ Not in vanilla | ✅ DPHelper exclusive |
@load persistent var loading |
❌ Not in vanilla | ✅ DPHelper exclusive |
@if / @else / @endif |
❌ Not in vanilla | ✅ DPHelper exclusive |
@switch / @case / @default / @endswitch |
❌ Not in vanilla | ✅ DPHelper exclusive |
@while / @endwhile |
❌ Not in vanilla | ✅ DPHelper exclusive |
@for / @endfor |
❌ Not in vanilla | ✅ DPHelper exclusive |
@break |
❌ Not in vanilla | ✅ DPHelper exclusive |
/var set/get/remove/list |
❌ Not in vanilla | ✅ DPHelper exclusive |
/data get entity @s |
✅ Native (1.21.2+) | ✅ Identical syntax |
/data merge entity @s {...} |
✅ Native (1.21.2+) | ✅ Identical syntax |
/data modify entity @s ... |
✅ Native (1.21.2+) | ✅ Identical syntax |
| Motion velocity (unclamped) | ⚠️ Clamped in vanilla | ✅ Float precision via explosion packet |
| Restricted tags on player writes | ✅ Filtered | ✅ Filtered (same set + Forge extras) |
/fallingblock <block> [pos] [nbt] |
❌ Not in vanilla | ✅ DPHelper exclusive |
/display opacity <targets> <value> [interp] |
❌ Not in vanilla | ✅ DPHelper exclusive |
/display transform <targets> <nbt> [interp] |
❌ Not in vanilla | ✅ DPHelper exclusive |
Datapacks using vanilla 1.21+ features can be ported directly to DPHelper on 1.20.1 with no syntax changes.
Server Compatibility
| Requirement | Status |
|---|---|
| Server-only mod | ✅ |
| Vanilla clients can join | ✅ (IGNORE_SERVER_VERSION) |
| No client-side code | ✅ |
| No vanilla scoreboard modifications | ✅ |
| No networking protocol changes | ✅ |
| Forge 47+ / MC 1.20.1 | ✅ |
| Java 17 | ✅ |
Screenshots
Gallery
Versions
Files
Relations
Project Relations
More like this
Similar Mods
Suggestions use data such as tags, dependencies, dependents, descriptions, titles, and more to rank how much they overlap with this mod.
On ModDex
Community snapshot
By the numbers
Statistics
Want to reach Minecraft players?
We're looking for a server hosting partner to feature here and other parts of the site. Interested? Send us a message!
Get in touchGet it on
Available Platforms
On ModDex
Community snapshot
By the numbers
Statistics
Resources