promotional bannermobile promotional banner
premium banner
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.

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

  1. Install Minecraft Forge for 1.20.1 (loader 47+).
  2. Place dphelper-1.0-SNAPSHOT.jar into your server's mods/ folder.
  3. 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 ... with macros from 1.21+, including $ lines, ^ context forwarding, and return statements.
  • Persistent Variables/var command and @var! / @load directives that survive server restarts.
  • Control Flow@if/@else/@endif, @switch/@case/@endswitch, @while/@endwhile, @for/@endfor, and @break directly in .mcfunction files.
  • Player Data Commands — Backported /data commands for player entities from 1.21.2+.
  • Display Entity Commands/display opacity and /display transform for manipulating display entities with unsigned values and interpolation.
  • Falling Block Command/fallingblock to 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 namesSteve, 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 as 2500
  • Input 3.141 → stored as 3141
  • 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.745)
<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 × scale
  • success: 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

  1. Write a .mcfunction file with macro lines — lines starting with $
  2. Use $(variable) placeholders inside those lines
  3. 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 &gt; @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 SavedData system
  • Attached to the overworld dimension
  • Saved automatically when the world saves
  • File location: &lt;world&gt;/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 &lt;id&gt; with args {...} ✅ Native ✅ Identical syntax
/function &lt;id&gt; with storage &lt;id&gt; ✅ Native ✅ Identical syntax
/function &lt;id&gt; with entity &lt;sel&gt; ✅ Native ✅ Identical syntax
/function &lt;id&gt; with block &lt;pos&gt; ✅ Native ✅ Identical syntax
/function &lt;id&gt; with var &lt;ns&gt; ❌ 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 &lt;block&gt; [pos] [nbt] ❌ Not in vanilla ✅ DPHelper exclusive
/display opacity &lt;targets&gt; &lt;value&gt; [interp] ❌ Not in vanilla ✅ DPHelper exclusive
/display transform &lt;targets&gt; &lt;nbt&gt; [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