-
Notifications
You must be signed in to change notification settings - Fork 0
Storage Architecture
← Home
All macroEngine communication uses three NBT storage namespaces:
| Storage | Purpose |
|---|---|
macro:input |
Send arguments to a function |
macro:output |
Receive results from a function |
macro:engine |
Persistent engine state |
macro:engine
├── global
│ ├── version: "v4.0.1"
│ └── tick: <int>
│
├── players
│ └── Steve { coins:150, level:5, xp:2300, online:1b, ... }
│
├── player_pids
│ └── { Steve: 1, Alex: 2, ... } ← PID map (name → int)
│
├── _pid_seq ← monotonic counter
│
├── cooldowns
│ └── Steve { fireball: 2460, dash: 1870 } ← expiry ticks
│
├── events
│ └── on_join: [{func:"mypack:welcome"}, {func:"mypack:xp_bonus"}]
│
├── queue
│ └── [{func:"mypack:event/end", delay:100}]
│
├── schedules
│ └── [{key:"my_timer", func:"mypack:tick_fn", interval:20, next:3840}]
│
├── hook_binds
│ └── [{event:"on_break", func:"mypack:on_break_handler"}]
│
├── interaction_binds
│ └── [{tag:"my_button", type:"use", func:"mypack:on_click"}]
│
├── wand_binds
│ └── [{tag:"my_wand", func:"mypack:on_right_click"}]
│
├── perm_triggers
│ └── my_trigger: [{value:1, func:"mypack:action", perm:"mypack.action"}]
│
├── perm_trigger_names
│ └── [{name:"my_trigger"}]
│
├── permissions
│ └── Steve: ["mypack.action", "mypack.admin"]
│
├── flags
│ └── { my_flag: 1b, other_flag: 0b }
│
├── config
│ └── { max_players: 10, spawn_rate: 5 }
│
├── log_display ← circular buffer (max 30)
│ └── [{level:"INFO", message:"...", color:"green"}]
│
├── region_watches
│ └── [{id:"spawn", x1:0,y1:0,z1:0, x2:100,y2:100,z2:100, func:"mypack:on_enter"}]
│
├── batches
│ └── [{id:"my_batch", items:[...], index:0}]
│
├── uuid_cache
│ └── { spawn_marker: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
│
├── dialog
│ └── { DIALOG: "mypack:my_dialog" }
│
├── fibers
│ └── { fiber_id: {func:"mypack:step", state:{...}} }
│
└── _dispatch ← internal; written by dispatch sites
└── func: "namespace:path/to/function" ← consumed by core/dispatch/exec
⚠️ macro:engine._dispatchis internal. Do not read or write it from your own functions. It is overwritten on every dispatch call.
Before calling any macroEngine function, write your arguments to macro:input:
data modify storage macro:input player set value "Steve"
data modify storage macro:input key set value "fireball"
data modify storage macro:input duration set value 100
function macro:core/cooldown/set with storage macro:input {}Note: Always use
set(notappend) onmacro:inputpaths to avoid accumulation from previous calls.
If you need to call a function inside another function without clobbering macro:input:
function macro:core/lib/input_push # save current macro:input
data modify storage macro:input value set value 144
function macro:systems/math/sqrt with storage macro:input {}
# output.result → 12
function macro:core/lib/input_pop # restore macro:inputAfter calling a function, read results from macro:output:
function macro:core/cooldown/check with storage macro:input {}
execute if data storage macro:output {result:1b} run function mypack:ability/use
execute if data storage macro:output {result:0b} run function mypack:ability/busyCommon output fields:
| Field | Type | Used by |
|---|---|---|
result |
1b/0b or int |
most check/query functions |
found |
1b/0b
|
player queries |
string.result |
string | lib/string/* |
inputs |
compound | tools/utils/input_check |
AME centralises all callback dispatch behind a single gateway. This is relevant only if you are extending AME or implementing a custom overlay:
call site
└─ $data modify storage macro:engine _dispatch.func set value "$(func)"
└─ function #macro:internal/dispatch
└─ macro:core/dispatch/run ← reads _dispatch from storage
└─ macro:core/dispatch/exec ← THE ONLY $function $(func) in AME
Override point: Replace #macro:internal/dispatch in your overlay to intercept every callback dispatch — e.g. to validate namespaces, add audit logging, or sandbox untrusted packs:
// mypack/data/macro/tags/function/internal/dispatch.json
{
"replace": true,
"values": [
"mypack:dispatch/validate",
"macro:core/dispatch/run"
]
}# mypack:dispatch/validate — runs BEFORE the actual function
# macro:engine._dispatch.func is already set by the call site
execute if data storage macro:engine _dispatch{func:"macro:"} run return 0
execute if data storage macro:engine _dispatch{func:"mypack:"} run return 0
# else: blocked — log and skip
tellraw @a[tag=macro.admin] {"text":"[BLOCKED] Untrusted dispatch attempted.","color":"red"}The three intentional exceptions that do not use this gateway:
core/engine/call/execute_validated/run— pre-validated; needswith storage macro:input {}pass-through.api/cmd/other/multi_cmd/*— list-based multi-command queue; excluded by design.debug/tools/trigger/internal/exec_func— constructs function path from$(ns):$(path); admin-debug only.
Lines beginning with $ and containing $(var) receive runtime substitution:
# In a macro function file:
$scoreboard players set $(player) macro.some_obj $(value)# Called as:
function macro:some/fn with storage macro:input {}
# macro:input must contain: { player: "Steve", value: 5 }
⚠️ The$prefix is only valid on lines that contain at least one$(var). Using$on a line with no variables causes aNo variables in macroerror.
⚠️ execute functionsubcommands cannot pass macro arguments. Usewith storage macro:input {}on a top-levelfunctioncall instead.