-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial
A production-grade Minecraft Java Edition datapack framework providing a unified macro execution engine, event system, permission layer, and 80+ scripting utilities.
Compatibility: MC 1.20.3 – 26.1+ · pack_format 26 – 101.1
Dependencies: StringLib, Lantern Load, PlayerAction
- Overview
- Installation
- Load Gate
-
Modules
- API · cmd
- API · trigger / hook / wand / interaction
- API · cooldown
- API · dialog
- API · inv
- Systems · math
- Systems · string
- Systems · sound
- Systems · log
- Systems · raycast
- Systems · geo / region_watch
- Systems · hook
- Core · event / queue / fiber / batch
- Core · cooldown
- Core · perm / state / flag
- Core · tick channels
- Core · uuid / player / team
- Core · rate_limit
- Sandbox mode
- Gate · dangerous commands
- Storage Layout
- Scoreboard Reference
- Overlays
- Debug
- Admin tags
- Changelog
AME provides a single macro:engine storage namespace and a set of scoreboard objectives that form the runtime state of the engine. All public API calls are macro functions under macro:api/ and macro:systems/. Internal implementation details live under macro:core/ — do not call these directly.
The engine is driven by #minecraft:tick and processes events, scheduled callbacks, fiber continuations, wand clicks, interaction binds, hook triggers, and tick channel subscribers each game tick.
- Place the datapack in
world/datapacks/. - Also install StringLib and a Lantern Load provider in the same world.
- Run
/reload. - The AME load gate opens. Confirm with:
/function ame_load:load/yes - Verify:
/function macro:version
Sandbox auto-confirm (skip the gate on every reload):
/data modify storage macro:engine sandbox set value 1b
AME never writes to macro:engine storage at load time without explicit operator confirmation. On every /reload or world open, a 5-minute confirmation window opens.
| Command | Effect |
|---|---|
/function ame_load:load/yes |
Confirm — run full init pipeline |
/function ame_load:load/no |
Cancel — storage untouched |
| (5 min timeout) | Auto-cancel |
The gate uses scoreboard players set #pending ame.load and broadcasts via marker entity say so messages appear in the server log even when zero players are online.
Macro wrappers for every common command. All functions accept named macro parameters and emit debug tellraw to players tagged macro.debug.
Usage pattern:
data modify storage macro:input player set value "Steve"
data modify storage macro:input effect set value "minecraft:speed"
data modify storage macro:input duration set value 60
data modify storage macro:input amplifier set value 1
function macro:api/cmd/effect_give with storage macro:input {}Available commands (partial list):
| Function | Parameters |
|---|---|
cmd/give |
player, item, count
|
cmd/effect_give |
player, effect, duration, amplifier
|
cmd/effect_clear |
player |
cmd/effect_give_all |
effect, duration, amplifier, hide
|
cmd/tp |
player, x, y, z
|
cmd/tp_to_player |
player, target
|
cmd/tp_to_entity |
player, type, tag
|
cmd/tp_to_coords |
player, x, y, z
|
cmd/tp_facing |
player, x, y, z, fx, fy, fz
|
cmd/gamemode |
player, mode
|
cmd/title |
player, text, color
|
cmd/title_sub |
player, title, color, subtitle, sub_color
|
cmd/title_bold |
player, text, color
|
cmd/title_times |
player, fade_in, stay, fade_out
|
cmd/title_clear |
player |
cmd/title_reset |
player |
cmd/title_all |
title |
cmd/actionbar |
player, text, color
|
cmd/subtitle |
player, text, color
|
cmd/msg |
player, message
|
cmd/msg_raw |
player, json
|
cmd/sound |
player, sound, volume, pitch
|
cmd/sound_all |
sound, volume, pitch
|
cmd/stopsound |
player, category, sound
|
cmd/heal |
player, amount
|
cmd/damage |
player, amount, type
|
cmd/damage_typed |
player, amount, damage_type
|
cmd/xp_add |
player, amount, type
|
cmd/xp_set |
player, amount, type
|
cmd/xp_get |
player, type → macro:output result
|
cmd/scoreboard_set |
player, objective, value
|
cmd/scoreboard_get |
player, objective → macro:output result
|
cmd/scoreboard_add |
player, objective, amount
|
cmd/tag_add |
player, tag
|
cmd/tag_remove |
player, tag
|
cmd/advancement_grant |
player, advancement
|
cmd/advancement_revoke |
player, advancement
|
cmd/advancement_check |
player, advancement → macro:output result
|
cmd/attribute_get |
player, attribute → macro:output result
|
cmd/attribute_set |
player, attribute, value
|
cmd/attribute_add_modifier |
player, attribute, id, amount, operation
|
cmd/attribute_remove_modifier |
player, attribute, id
|
cmd/enchant |
player, enchantment, level
|
cmd/give_one |
player, item
|
cmd/clear |
player |
cmd/clear_item |
player, item, count
|
cmd/spectate |
player, target
|
cmd/spectate_stop |
player |
cmd/ride |
player, vehicle
|
cmd/ride_dismount |
player |
cmd/kill |
player |
cmd/deop |
player |
cmd/whitelist |
action, player
|
cmd/difficulty |
level |
cmd/gamerule |
rule, value
|
cmd/weather |
type, duration
|
cmd/time_set |
value |
cmd/time_add |
value |
cmd/fill |
x1 y1 z1 x2 y2 z2, block, mode
|
cmd/setblock |
x, y, z, block, mode
|
cmd/clone |
x1 y1 z1 x2 y2 z2 dx dy dz |
cmd/clone_masked |
same as clone |
cmd/summon |
entity, x, y, z, nbt
|
cmd/particle |
name, x y z, dx dy dz, speed, count
|
cmd/bossbar_add |
id, text, color
|
cmd/bossbar_remove |
id |
cmd/bossbar_set_value |
id, value
|
cmd/bossbar_set_max |
id, max
|
cmd/bossbar_set_players |
id |
cmd/place_feature |
feature, x, y, z
|
cmd/place_structure |
structure, x, y, z
|
cmd/spreadplayers |
cx, cz, spread, max_range, target
|
cmd/locate_structure |
player, structure
|
cmd/loot_give |
player, loot_table
|
cmd/loot_drop |
x, y, z, loot_table
|
cmd/storage_set |
storage, nbt, actionType, value
|
cmd/data_remove_storage |
storage, path
|
cmd/data_remove_entity |
target, path
|
cmd/data_remove_block |
x, y, z, path
|
cmd/forceload_add |
x, z
|
cmd/forceload_remove |
x, z
|
cmd/item_modify |
player, slot, modifier
|
cmd/item_rename |
player, slot, modifier
|
cmd/display_name |
type, tag, name
|
cmd/as_player |
player, cmd
|
cmd/trigger_set |
player, objective, value
|
Dangerous commands (ban, ban_ip, engine disable) are routed through the Gate system.
Execute a list of commands in one call:
# Simple list
data modify storage macro:input list set value ["say Hello", "say World"]
function macro:api/cmd/other/multi_cmd/from_input
# Advanced: with conditions, priority, spread
data modify storage macro:input list set value [{cmd:"say A",priority:-1},{cmd:"say B",priority:1,condition:{tag:"vip"}}]
data modify storage macro:input options set value {priority_sort:1b,profile:1b}
function macro:api/cmd/other/multi_cmd/advanced/run_with_optionsAdvanced item format:
{
"cmd": "say Hello",
"func": "my_pack:some_func",
"priority": 0,
"condition": {
"tag": "vip",
"score": {"objective": "points", "min": 100, "max": 999},
"predicate": "my_pack:is_day",
"entity": "@a[tag=online]",
"storage": "macro:engine flags.pvp"
},
"pre_hook": "my_pack:before",
"post_hook": "my_pack:after"
}Options:
{
"priority_sort": true,
"spread_ticks": 0,
"error_mode": "continue",
"profile": true
}Scoreboard trigger-based events. Players must have the macro.admin tag to enable triggers.
# Register
data modify storage macro:input trigger set value "macro_run"
data modify storage macro:input func set value "my_pack:on_run"
function macro:api/trigger/register with storage macro:input {}
# Unbind all
function macro:api/trigger/unbind_allHook into built-in game events:
| Event | Trigger |
|---|---|
player_join |
Player joins server |
player_leave |
Player leaves server |
player_death |
Player dies in survival/adventure |
break_block |
Tool durability lost (item_durability_changed) |
placed_block |
Block placed |
entity_kill |
Player kills entity |
item_use |
Using item advancement |
eat |
consume_item advancement |
fish_caught |
Fishing rod hooked |
dimension_change |
Changed dimension |
trade |
Villager trade |
hero_of_the_village |
Hero of the village advancement |
killed_by_arrow |
Killed by arrow |
interact_anvil |
Anvil interaction |
interact_shulker_box |
Shulker box interaction |
sneak_start / sneak_stop
|
Sneak toggle |
sprint_start / sprint_stop
|
Sprint toggle |
elytra_start / elytra_stop
|
Elytra toggle |
jump |
Jump stat |
open_chest |
Open chest stat |
drop |
Drop stat |
target_hit |
Target hit stat |
level_up |
Level change |
death |
deathCount scoreboard |
# Bind a hook
data modify storage macro:input event set value "player_death"
data modify storage macro:input func set value "my_pack:on_death"
function macro:api/hook/bind with storage macro:input {}
# Unbind all hooks
function macro:api/hook/unbind_allCarrot-on-a-stick right-click detection:
data modify storage macro:input tag set value "my.wand"
data modify storage macro:input func set value "my_pack:on_wand_click"
function macro:api/wand/register with storage macro:input {}Bind attack/use interactions:
data modify storage macro:input type set value "attack"
data modify storage macro:input func set value "my_pack:on_attack"
function macro:api/interaction/bind_attack with storage macro:input {}# Set cooldown (ticks)
data modify storage macro:input player set value "Steve"
data modify storage macro:input key set value "my.ability"
data modify storage macro:input ticks set value 200
function macro:api/cooldown/set with storage macro:input {}
# Check cooldown — returns 1b if still active
function macro:api/cooldown/check with storage macro:input {}
# result in macro:output result1.21.5+ dialog system integration. Dialogs are registered and opened via AME's dialog subsystem.
# Open a dialog
data modify storage macro:input player set value "Steve"
data modify storage macro:input dialog set value "my_pack:my_dialog"
function macro:api/dialog/open with storage macro:input {}Inventory manipulation utilities.
All math functions read from macro:input and write to macro:output result unless noted.
| Function | Description |
|---|---|
math/abs |
Absolute value |
math/add |
Addition |
math/clamp |
Clamp to range |
math/ceil_div |
Ceiling division |
math/cos |
Cosine (scaled integer) |
math/sin |
Sine (scaled integer) |
math/atan2 |
Arctangent of y/x |
math/sqrt |
Integer square root |
math/pow |
Power |
math/mod |
Modulo |
math/divmod |
Division + remainder |
math/mul_div |
Multiply then divide |
math/log2 |
Base-2 logarithm |
math/gcd |
Greatest common divisor |
math/lcm |
Least common multiple |
math/factorial |
Factorial |
math/min |
Minimum of two values |
math/max |
Maximum of two values |
math/minmax |
Both min and max |
math/lerp |
Linear interpolation |
math/lerp_clamped |
Clamped lerp |
math/map |
Range remap |
math/sign |
Sign of value |
math/sign_nonzero |
Sign (never returns 0) |
math/round |
Round to nearest |
math/truncate |
Truncate decimal |
math/wrap |
Wrap value in range |
math/random |
Random integer in range |
math/weighted_random |
Weighted random selection |
math/sum3 |
Sum of three values |
math/average |
Average of array |
math/is_between |
Range membership check |
math/distance2d |
2D Euclidean distance |
math/distance3d |
3D Euclidean distance |
math/vec/* |
Vector math (add, scale, dot, cross, normalize, length) |
| Function | Description |
|---|---|
string/format_number |
Human-readable number (1,234,567) |
string/format_ticks |
Tick count → MM:SS |
string/ordinal |
Number → ordinal (1st, 2nd…) |
string/pluralize |
Conditional plural |
string/pad_left |
Left-pad with character |
string/truncate |
Truncate to max length |
string/announce |
Broadcast to all players |
string/announce_prefix |
Broadcast with prefix |
data modify storage macro:input sound set value "minecraft:entity.experience_orb.pickup"
data modify storage macro:input volume set value 1.0
data modify storage macro:input pitch set value 1.0
function macro:systems/sound/play with storage macro:input {}
# At position
function macro:systems/sound/play_at with storage macro:input {}Structured log with level filtering. Levels: 0=off 1=error 2=warn 3=info 4=debug.
scoreboard players set #ame.log_level ame.log_level 4 # enable debug
data modify storage macro:input level set value "AME"
data modify storage macro:input message set value "Something happened"
data modify storage macro:input color set value "green"
function macro:systems/log/add with storage macro:input {}
function macro:systems/log/info with storage macro:input {}
function macro:systems/log/warn with storage macro:input {}
function macro:systems/log/error with storage macro:input {}Step-by-step block/entity raycasting.
data modify storage macro:input max_distance set value 10
data modify storage macro:input step set value 0.5
data modify storage macro:input on_hit_block set value "my_pack:on_hit_block"
data modify storage macro:input on_hit_entity set value "my_pack:on_hit_entity"
function macro:systems/raycast/cast with storage macro:input {}Region membership and watch callbacks:
# Check if @s is inside a region
data modify storage macro:input x1 set value -10
data modify storage macro:input y1 set value 60
data modify storage macro:input z1 set value -10
data modify storage macro:input x2 set value 10
data modify storage macro:input y2 set value 80
data modify storage macro:input z2 set value 10
function macro:systems/geo/in_region with storage macro:input {}
# Register an enter/leave watch (must be called from #macro:init)
data modify storage macro:input region set value {x1:-10,y1:60,z1:-10,x2:10,y2:80,z2:10}
data modify storage macro:input on_enter set value "my_pack:on_enter"
data modify storage macro:input on_leave set value "my_pack:on_leave"
function macro:systems/geo/region_watch/register with storage macro:input {}Region watches are cleared on every reload. Re-register them in
#macro:init.
Internal hook dispatch. Use macro:api/hook/* for registration.
# Fire a named event
data modify storage macro:input event set value "my_pack:player_scored"
data modify storage macro:input context set value {player:"Steve",points:100}
function macro:fire with storage macro:input {}Deferred function calls:
data modify storage macro:input func set value "my_pack:delayed_action"
data modify storage macro:input delay set value 40
function macro:queue with storage macro:input {}Coroutine-like multi-tick execution:
data modify storage macro:input steps set value ["my_pack:step_a","my_pack:step_b","my_pack:step_c"]
data modify storage macro:input interval set value 20
function macro:core/lib/fiber with storage macro:input {}Process large lists across multiple ticks without lag:
data modify storage macro:input items set from storage macro:engine my_list
data modify storage macro:input per_tick set value 50
data modify storage macro:input func set value "my_pack:process_item"
function macro:core/lib/batch with storage macro:input {}Internal cooldown backing store. Epoch-based: persists across reloads. Use macro:api/cooldown/* for public access.
# Grant a permission to a player
data modify storage macro:input player set value "Steve"
data modify storage macro:input perm set value "my_pack.admin"
function macro:api/perm/grant with storage macro:input {}
# Check
function macro:api/perm/check with storage macro:input {}
# result in macro:output result (1b = has permission)
# Revoke
function macro:api/perm/revoke with storage macro:input {}Per-player state machine:
data modify storage macro:input player set value "Steve"
data modify storage macro:input state set value 2
function macro:api/state/set with storage macro:input {}Boolean engine flags:
data modify storage macro:input key set value "pvp"
data modify storage macro:input value set value 1b
function macro:api/flag/set with storage macro:input {}
function macro:api/flag/has with storage macro:input {}Rate-controlled per-system tick dispatch. All tick subscriptions survive reload as long as they are re-registered in #macro:init.
# Register a channel (call from #macro:init)
data modify storage macro:input func set value "my_pack:on_tick"
data modify storage macro:input interval set value 20
data modify storage macro:input key set value "my_pack.tick"
function macro:core/lib/schedule with storage macro:input {}Pause/resume the entire engine:
/function macro:core/tick/pause
/function macro:core/tick/resume
Stable UUID generation and caching:
function macro:systems/uuid/generate
# result in macro:output resultPlayer init runs automatically on join and on reload for players already online. Assigns a stable PID to each player via macro.pid objective.
data modify storage macro:input team set value "red"
data modify storage macro:input player set value "Steve"
function macro:api/team/add with storage macro:input {}Throttle any function call per player or globally:
data modify storage macro:input key set value "my_pack.shout"
data modify storage macro:input player set value "Steve"
data modify storage macro:input window set value 40
function macro:core/rate_limit/check with storage macro:input {}In sandbox mode, all destructive cmd/ calls are silently blocked and logged as WARN. Enable once — persists across reloads:
/data modify storage macro:engine sandbox set value 1b
/data modify storage macro:engine sandbox set value 0b
Blocked commands: ban, ban_ip, clear, clone, clone_masked, data_remove_block, data_remove_entity, deop, difficulty, fill, forceload_add, forceload_remove, gamemode, gamerule, kill, place_feature, place_structure, setblock, spreadplayers, summon, time_add, time_set, weather, whitelist.
For ban, ban_ip, and engine disable, AME requires a secondary confirmation:
# Trigger a ban via gate
data modify storage macro:engine pending_gate set value {type:"ban",player:"Griefer",reason:"Griefing"}
function ame_load:gate/requestThen confirm within 30 seconds:
/function ame_load:gate/yes
/function ame_load:gate/no
| Path | Type | Description |
|---|---|---|
macro:engine global |
compound | Engine global state (loaded, version, tick, epoch) |
macro:engine players |
compound | Per-player data keyed by UUID |
macro:engine cooldowns |
compound | Cooldown expiry map |
macro:engine queue |
list | Deferred function queue |
macro:engine events |
list | Pending event queue |
macro:engine flags |
compound | Boolean flag storage |
macro:engine states |
compound | Per-player state machine |
macro:engine permissions |
compound | Permission maps |
macro:engine hook_binds |
list | Registered hook callbacks |
macro:engine wand_binds |
list | Registered wand callbacks |
macro:engine trigger_binds |
list | Registered trigger callbacks |
macro:engine interaction_binds |
compound | {attack:[], use:[]} |
macro:engine fibers |
compound | Fiber coroutine state |
macro:engine batches |
compound | Batch job state |
macro:engine region_watches |
list | Registered region watches |
macro:engine once_per_player |
compound | Once-per-player tracking |
macro:engine wand_cooldowns |
compound | Wand-specific cooldowns |
macro:engine player_pids |
compound | Player name → PID map |
macro:engine rate_limit |
compound | Rate limit state |
macro:engine throttle |
compound | Throttle state |
macro:engine log_display |
list | Buffered log entries |
macro:engine sandbox |
byte | Sandbox mode flag |
macro:input |
compound | Shared call input namespace |
macro:output |
compound | Shared call output namespace |
| Objective | Criteria | Purpose |
|---|---|---|
macro.tmp |
dummy | General-purpose scratch |
macro.time |
dummy | Epoch / tick counter |
macro_menu |
trigger | Admin menu trigger |
macro_run |
trigger | Admin run trigger |
macro_action |
trigger | Admin action trigger |
macro.pid |
dummy | Per-player PID |
macro.tick |
dummy | Tick channel dispatch |
macro.Flags |
dummy | Engine flags |
macro.state |
dummy | Per-player state |
macro.config |
dummy | Fast integer config |
macro.rightClick |
minecraft.used:carrot_on_a_stick |
Wand click detection |
macro.hook_online |
dummy | Player online tracking |
macro.hook_deaths |
deathCount |
Death hook |
macro.hook_jump |
minecraft.custom:jump |
Jump hook |
macro.hook_open_chest |
minecraft.custom:open_chest |
Chest open hook |
macro.hook_drop |
minecraft.custom:drop |
Item drop hook |
macro.hook_target_hit |
minecraft.custom:target_hit |
Target hit hook |
macro.hook_sneak |
dummy | Sneak state |
macro.hook_sprint |
dummy | Sprint state |
macro.hook_elytra |
dummy | Elytra state |
macro.hook_lvl |
dummy | XP level tracking |
macro.hook_tool_used |
dummy | Block break (advancement) |
macro.hook_item_used |
dummy | Item use (advancement) |
macro.hook_entity_killed |
dummy | Entity kill (advancement) |
ame.pre_version |
dummy | Version scores (major/minor/patch/pre) |
ame.log_level |
dummy | Log level (0–4) |
load.status |
dummy | Lantern Load integration |
health |
health |
Player health display |
| Directory | Formats | MC Versions |
|---|---|---|
1_20_3 |
26 | 1.20.3–1.20.4 |
1_20_5 |
41–47 | 1.20.5–1.21.1 |
_pre_1_21_4 |
48–61 | 1.21–1.21.3 |
compat_1_21_4 |
48–61 | 1.21–1.21.3 |
1_21_5 |
71 | 1.21.5 |
1_21_6 |
80+ | 1.21.6+ |
26_1 |
101.1 | Snapshot 26.1 |
/function macro:debug
Shows full engine state: global, players, cooldowns, queue, events, config, flags, I/O.
Tag a player to receive debug output:
/tag @s add macro.debug
Dump specific subsystems:
/function macro:dump_cooldowns
/function macro:dump_events
/function macro:dump_players
/function macro:dump_schedules
| Tag | Effect |
|---|---|
macro.admin |
Enables triggers, receives debug and warn tellraw
|
macro.debug |
Receives all debug tellraw output |
- Gate system extracted to
ame_load:gate/*— separate from load gate - Dangerous commands (
ban,ban_ip, disable) routed through 30-second gate - Sandbox guard added to all destructive
cmd/functions -
cmd/console_meandcmd/console_sayremoved (security — intent detection unreliable) -
multi_cmdadvanced mode:priority_sort,spread_ticks,profile, pre/post hooks - New math:
weighted_random,distance2d,distance3d,vec/*suite - New string:
format_ticks,ordinal,pad_left,pluralize - Fiber, batch, region_watch modules finalized
- Rate limit module added
-
once_per_playertracking module - Lantern Load integration via
load.statusscoreboard -
macro.dialog_loadscoreboard for dialog subsystem - 1.21.6 overlay (
1_21_6) added - 26.1 overlay (
26_1) added - Version bumped to v4.0.5-pre1 (pack_format 88 base, overlays to 101.1)