diff --git a/datapacks/macroEngine/1_20_5/data/macroengine_load/functions/init.mcfunction b/datapacks/macroEngine/1_20_5/data/macroengine_load/functions/init.mcfunction new file mode 100644 index 0000000..bfd47e4 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/macroengine_load/functions/init.mcfunction @@ -0,0 +1 @@ +data modify storage runtoolkit:tmp seed set value [{name:"macroengine",load_fn:"macroengine_load:main",tick_fn:"macroengine.main:macroengine/tick",disable_fn:"macroengine:disable",version_score:"#runtoolkit.packs.macroengine.version"}] \ No newline at end of file diff --git a/datapacks/macroEngine/1_20_5/data/macroengine_load/functions/load/final.mcfunction b/datapacks/macroEngine/1_20_5/data/macroengine_load/functions/load/final.mcfunction index e996718..c5303e6 100644 --- a/datapacks/macroEngine/1_20_5/data/macroengine_load/functions/load/final.mcfunction +++ b/datapacks/macroEngine/1_20_5/data/macroengine_load/functions/load/final.mcfunction @@ -1,5 +1,5 @@ data modify storage macroengine:engine global.version set value "v6.0.2" - +function #load:_private/load scoreboard players set #runtoolkit.packs.macroengine.version macroengine.meta 602 -tellraw @a ["",{"text":"[MACROENGINE] ","color":"#00AAAA","bold":true},{"text":"macroEngine v6.0.2 loaded.","color":"green"}] +tellraw @a ["",{"text":"[MACROENGINE] ","color":"#00AAAA","bold":true},{"text":"macroEngine v6.0.2 loaded.","color":"green"}] \ No newline at end of file diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status.mcfunction new file mode 100644 index 0000000..9fced43 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status.mcfunction @@ -0,0 +1,14 @@ +# runtoolkit:diagnostics/status +# Reports live loaded/disabled state for every registered subsystem, +# read straight from each subsystem's "#runtoolkit.packs..version" +# score — not from the registry snapshot, so this reflects reality even +# if a subsystem was disabled after registering (e.g. via its own +# disable command) without re-registering. + +execute unless data storage runtoolkit:engine registry.subsystems[0] run tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"no subsystems registered — nothing to report.","color":"gray"}] +execute unless data storage runtoolkit:engine registry.subsystems[0] run return 0 + +tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"subsystem status:","color":"aqua"}] +data modify storage runtoolkit:tmp _walk set from storage runtoolkit:engine registry.subsystems +function runtoolkit:diagnostics/status_step +data remove storage runtoolkit:tmp _walk diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status_line.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status_line.mcfunction new file mode 100644 index 0000000..2fa32f9 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status_line.mcfunction @@ -0,0 +1,11 @@ +# runtoolkit:diagnostics/status_line +# MACRO INPUT (from a registry.subsystems[n] entry): +# $(name) -> subsystem id, used to build the score holder "#runtoolkit.packs.$(name).version" +# $(version) -> the version recorded at registration time (may be stale vs. live score) +# +# Score holder names accept macro substitution directly (no string concat needed). + +$execute store result score $diag_ver runtoolkit.tmp run scoreboard players get #runtoolkit.packs.$(name).version macroengine.meta + +execute if score $diag_ver runtoolkit.tmp matches 1.. run tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_diag_call.name","storage":"runtoolkit:tmp","color":"white"},{"text":" — ","color":"#555555"},{"text":"loaded","color":"green"},{"text":" (v","color":"#555555"},{"score":{"name":"$diag_ver","objective":"runtoolkit.tmp"},"color":"aqua"},{"text":")","color":"#555555"}] +execute if score $diag_ver runtoolkit.tmp matches ..0 run tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_diag_call.name","storage":"runtoolkit:tmp","color":"white"},{"text":" — ","color":"#555555"},{"text":"disabled","color":"red"}] diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status_step.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status_step.mcfunction new file mode 100644 index 0000000..8be89d1 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/diagnostics/status_step.mcfunction @@ -0,0 +1,19 @@ +# runtoolkit:diagnostics/status_step +# Internal recursive walker for diagnostics/status. For each registered +# subsystem, reads its live "#runtoolkit.packs..version" score +# (0 = disabled/not loaded, matches core/internal/disable/apply.mcfunction's +# convention) and prints one status line. Reads runtoolkit:tmp _walk[0] +# and pops it. +# +# NOTE: deliberately does not depend on macroengine_string (StringLib) — +# runtoolkit sits above individual subsystems and should not require any +# one subsystem's internal libraries to function. The scoreboard holder +# name is built directly via macro substitution instead of string concat. + +execute unless data storage runtoolkit:tmp _walk[0] run return 0 + +data modify storage runtoolkit:tmp _diag_call set from storage runtoolkit:tmp _walk[0] +function runtoolkit:diagnostics/status_line with storage runtoolkit:tmp _diag_call + +data remove storage runtoolkit:tmp _walk[0] +function runtoolkit:diagnostics/status_step diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all.mcfunction new file mode 100644 index 0000000..d3b8aac --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all.mcfunction @@ -0,0 +1,20 @@ +# runtoolkit:killswitch/all +# Global emergency stop: disables every registered subsystem via its own +# public disable entry point (respecting each subsystem's own gate/ +# confirmation behavior — this is a supervised shutdown, not a raw +# `datapack disable` sweep). Intended for admin use when something is +# misbehaving and you don't have time to disable subsystems one by one. +# +# Requires op / permission level enforced by the command tree this is +# wired into (not enforced here — see macroengine's own security.* config +# for the pattern this project follows: gating lives at the command-tree +# layer, not duplicated inside every function). + +execute unless data storage runtoolkit:engine registry.subsystems[0] run tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"no subsystems registered — nothing to stop.","color":"gray"}] +execute unless data storage runtoolkit:engine registry.subsystems[0] run return 0 + +tellraw @a ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"KILLSWITCH — disabling all registered subsystems.","color":"red","bold":true}] +data modify storage runtoolkit:tmp _walk set from storage runtoolkit:engine registry.subsystems +function runtoolkit:killswitch/all_step +data remove storage runtoolkit:tmp _walk +tellraw @a ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"killswitch complete.","color":"red"}] diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_dispatch.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_dispatch.mcfunction new file mode 100644 index 0000000..1a5846c --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_dispatch.mcfunction @@ -0,0 +1,9 @@ +# runtoolkit:killswitch/all_dispatch +# MACRO INPUT (from a registry entry, via "with"): +# $(name) -> subsystem id, for the status line +# $(disable_fn) -> function id to call, e.g. "macroengine:disable" +# The subsystem's own disable_fn handles its gate/confirmation/cleanup; +# this just triggers it and reports. + +tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_ks_call.name","storage":"runtoolkit:tmp","color":"white"},{"text":" — ","color":"#555555"},{"text":"disabling…","color":"gold"}] +$function $(disable_fn) diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_read_version.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_read_version.mcfunction new file mode 100644 index 0000000..0bf6e20 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_read_version.mcfunction @@ -0,0 +1,4 @@ +# runtoolkit:killswitch/all_read_version +# MACRO INPUT: $(name) -> subsystem id +# Reads "#runtoolkit.packs.$(name).version" into score $ks_ver runtoolkit.tmp. +$execute store result score $ks_ver runtoolkit.tmp run scoreboard players get #runtoolkit.packs.$(name).version macroengine.meta diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_step.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_step.mcfunction new file mode 100644 index 0000000..74376e9 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/killswitch/all_step.mcfunction @@ -0,0 +1,17 @@ +# runtoolkit:killswitch/all_step +# Internal recursive walker for killswitch/all. Calls each registered +# subsystem's own disable_fn (its normal, gated /disable entry point) — +# does not force-disable via `datapack disable` directly, so each +# subsystem's own confirmation/sandbox/cleanup logic still runs. +# Already-disabled subsystems (version score 0) are skipped. + +execute unless data storage runtoolkit:tmp _walk[0] run return 0 + +data modify storage runtoolkit:tmp _ks_call set from storage runtoolkit:tmp _walk[0] +function runtoolkit:killswitch/all_read_version with storage runtoolkit:tmp _ks_call + +execute if score $ks_ver runtoolkit.tmp matches 1.. run function runtoolkit:killswitch/all_dispatch with storage runtoolkit:tmp _ks_call +execute if score $ks_ver runtoolkit.tmp matches ..0 run tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_walk[0].name","storage":"runtoolkit:tmp","color":"gray"},{"text":" — already disabled, skipped","color":"#555555"}] + +data remove storage runtoolkit:tmp _walk[0] +function runtoolkit:killswitch/all_step diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/load.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/load.mcfunction index 3c5271f..a4d2033 100644 --- a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/load.mcfunction +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/load.mcfunction @@ -1,7 +1,12 @@ # runtoolkit global entry point — load -# Dispatches to the macroengine subsystem's own load chain. -function macroengine_load:main +# Dispatches to every subsystem listed in runtoolkit:registry/seed (a +# static, hand-maintained list — this is the ONLY place a subsystem's +# load_fn is hardcoded now; see registry/seed.mcfunction to add one). -execute unless data storage macroengine:engine global.loaded run return 0 -execute if data storage macroengine:engine global{loaded:0b} run return 0 -execute if data storage macroengine:engine global{loaded:1b} run return 1 \ No newline at end of file +# Ensure runtoolkit's own scratch objective exists. Missing this made every +# runtoolkit:* function that reads/writes "runtoolkit.tmp" fail silently +# (score get/store on a nonexistent objective does nothing, no error) — +# this is what broke registry/list, diagnostics/status and killswitch/all. +scoreboard objectives add runtoolkit.tmp dummy + +function runtoolkit:registry/load_all \ No newline at end of file diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/list.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/list.mcfunction new file mode 100644 index 0000000..3a150db --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/list.mcfunction @@ -0,0 +1,22 @@ +# runtoolkit:registry/list +# Reports the subsystems currently registered with runtoolkit's global +# load/tick dispatcher. Registration happens via runtoolkit:registry/register +# (called once per subsystem, e.g. from macroengine's own load chain) — +# this function only reads and prints what is already in storage. +# +# Storage shape (runtoolkit:engine): +# registry.subsystems = [ +# {name:"macroengine", version:602, load_fn:"macroengine_load:main", tick_fn:"macroengine.main:macroengine/tick"}, +# ... +# ] + +execute unless data storage runtoolkit:engine registry run data modify storage runtoolkit:engine registry set value {} +execute unless data storage runtoolkit:engine registry.subsystems run data modify storage runtoolkit:engine registry.subsystems set value [] + +execute unless data storage runtoolkit:engine registry.subsystems[0] run tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"registry is empty — no subsystems registered.","color":"gray"}] +execute unless data storage runtoolkit:engine registry.subsystems[0] run return 0 + +tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"registered subsystems:","color":"aqua"}] +data modify storage runtoolkit:tmp _walk set from storage runtoolkit:engine registry.subsystems +function runtoolkit:registry/list_step +data remove storage runtoolkit:tmp _walk diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/list_step.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/list_step.mcfunction new file mode 100644 index 0000000..335e239 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/list_step.mcfunction @@ -0,0 +1,13 @@ +# runtoolkit:registry/list_step +# Internal recursive walker for registry/list. Pops entries off +# runtoolkit:tmp _walk (a scratch copy) one at a time so the source +# registry.subsystems list is never mutated by listing it. + +execute unless data storage runtoolkit:tmp _walk[0] run return 0 + +execute store result score $reg_ver runtoolkit.tmp run data get storage runtoolkit:tmp _walk[0].version +execute if score $reg_ver runtoolkit.tmp matches 1.. run tellraw @s ["",{"text":" - ","color":"#555555"},{"nbt":"_walk[0].name","storage":"runtoolkit:tmp","color":"white"},{"text":" (v","color":"#555555"},{"nbt":"_walk[0].version","storage":"runtoolkit:tmp","color":"green"},{"text":")","color":"#555555"}] +execute if score $reg_ver runtoolkit.tmp matches ..0 run tellraw @s ["",{"text":" - ","color":"#555555"},{"nbt":"_walk[0].name","storage":"runtoolkit:tmp","color":"gray"},{"text":" (disabled)","color":"red"}] + +data remove storage runtoolkit:tmp _walk[0] +function runtoolkit:registry/list_step diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all.mcfunction new file mode 100644 index 0000000..73af3b1 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all.mcfunction @@ -0,0 +1,11 @@ +# runtoolkit:registry/load_all +# Called from runtoolkit:load. Walks the static seed (registry/seed), +# calling each subsystem's load_fn and then registering it with the live +# registry — replacing the old hardcoded "function macroengine_load:main" +# + duplicate load_fn string that used to live directly in load.mcfunction. + +function runtoolkit:registry/seed +data modify storage runtoolkit:tmp _load_walk set from storage runtoolkit:tmp seed +data remove storage runtoolkit:tmp seed +function runtoolkit:registry/load_all_step +data remove storage runtoolkit:tmp _load_walk diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all_dispatch.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all_dispatch.mcfunction new file mode 100644 index 0000000..b1e6723 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all_dispatch.mcfunction @@ -0,0 +1,18 @@ +# runtoolkit:registry/load_all_dispatch +# MACRO INPUT (one seed entry, via "with"): +# $(name), $(load_fn), $(tick_fn), $(disable_fn), $(version_score) +# +# Calls load_fn, reads the resulting live version, then registers. +# version_score is a dynamic scoreboard holder name (e.g. +# "#runtoolkit.packs.macroengine.version") — score holders accept macro +# substitution directly, same pattern as diagnostics/status_line. + +$function $(load_fn) + +$execute store result score $rt_reg_ver runtoolkit.tmp run scoreboard players get $(version_score) macroengine.meta + +data modify storage runtoolkit:tmp _reg set from storage runtoolkit:tmp _load_entry +data remove storage runtoolkit:tmp _reg.version_score +execute store result storage runtoolkit:tmp _reg.version int 1 run scoreboard players get $rt_reg_ver runtoolkit.tmp +function runtoolkit:registry/register with storage runtoolkit:tmp _reg +data remove storage runtoolkit:tmp _reg diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all_step.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all_step.mcfunction new file mode 100644 index 0000000..580f94f --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/load_all_step.mcfunction @@ -0,0 +1,17 @@ +# runtoolkit:registry/load_all_step +# Internal recursive walker for registry/load_all. For each seed entry: +# 1. Call its load_fn (the subsystem's own load chain). +# 2. Read its live version score (only valid AFTER step 1 — the +# subsystem's own load chain is what sets that score, e.g. +# macroengine:config sets #runtoolkit.packs.macroengine.version). +# 3. Call registry/register with that live version, so the registry +# entry is never stale by construction. + +execute unless data storage runtoolkit:tmp _load_walk[0] run return 0 + +data modify storage runtoolkit:tmp _load_entry set from storage runtoolkit:tmp _load_walk[0] +function runtoolkit:registry/load_all_dispatch with storage runtoolkit:tmp _load_entry +data remove storage runtoolkit:tmp _load_entry + +data remove storage runtoolkit:tmp _load_walk[0] +function runtoolkit:registry/load_all_step diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/register.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/register.mcfunction new file mode 100644 index 0000000..408d60d --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/register.mcfunction @@ -0,0 +1,32 @@ +# runtoolkit:registry/register +# Called once by a subsystem (e.g. macroengine_load:main) to announce itself +# to runtoolkit's dispatcher. Idempotent: re-running with the same name +# overwrites that entry instead of duplicating it, so a /reload doesn't +# grow the list. +# +# MACRO INPUT: +# $(name) -> subsystem id, e.g. "macroengine" +# $(version) -> int, mirrors #runtoolkit.packs..version +# $(load_fn) -> function id dispatched on minecraft:load, e.g. "macroengine_load:main" +# $(tick_fn) -> function id dispatched on minecraft:tick, e.g. "macroengine.main:macroengine/tick" +# $(disable_fn) -> function id that cleanly disables this subsystem, e.g. "macroengine:disable" +# (used by runtoolkit:killswitch/all — must be the subsystem's public, +# gated entry point, not an internal /apply function, so the +# subsystem's own confirmation/sandbox behavior is respected) +# +# NOTE: this only records metadata for registry/list and diagnostics/status. +# It does NOT hook the subsystem into minecraft:load / minecraft:tick — +# that still happens via data/minecraft/tags/function/{load,tick}.json, +# same as today. Registration is descriptive, not wiring. + +execute unless data storage runtoolkit:engine registry run data modify storage runtoolkit:engine registry set value {} +execute unless data storage runtoolkit:engine registry.subsystems run data modify storage runtoolkit:engine registry.subsystems set value [] + +$data modify storage runtoolkit:tmp entry set value {name:"$(name)",version:$(version),load_fn:"$(load_fn)",tick_fn:"$(tick_fn)",disable_fn:"$(disable_fn)"} + +# Remove any existing entry with this name (re-registration on reload), then append fresh. +$data remove storage runtoolkit:engine registry.subsystems[{name:"$(name)"}] +data modify storage runtoolkit:engine registry.subsystems append from storage runtoolkit:tmp entry +data remove storage runtoolkit:tmp entry + +$tellraw @a[tag=macroengine.debug] ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"registry/register ","color":"aqua"},{"text":"→ ","color":"#555555"},{"text":"$(name)","color":"white"},{"text":" v","color":"#555555"},{"text":"$(version)","color":"green"}] diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/seed.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/seed.mcfunction new file mode 100644 index 0000000..6591ed6 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/registry/seed.mcfunction @@ -0,0 +1 @@ +function #runtoolkit:register \ No newline at end of file diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/version.mcfunction b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/version.mcfunction new file mode 100644 index 0000000..9f35cf8 --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/functions/version.mcfunction @@ -0,0 +1,14 @@ +# runtoolkit:version +# Reports runtoolkit's own dispatcher-layer version — NOT any individual +# subsystem's version (use runtoolkit:diagnostics/status for that). +# This tracks the runtoolkit: namespace itself (load/tick entry points, +# registry, diagnostics, killswitch) as a unit, independent of which +# subsystems happen to be registered under it. +# +# Storage: runtoolkit:engine meta.version — set once here on every call +# (idempotent) rather than only at load, so it stays correct even if this +# file is edited and the datapack reloaded without a full load-tag pass. + +data modify storage runtoolkit:engine meta.version set value "1.0.0" + +tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"dispatcher v","color":"aqua"},{"nbt":"meta.version","storage":"runtoolkit:engine","color":"white"}] diff --git a/datapacks/macroEngine/1_20_5/data/runtoolkit/tags/functions/register.json b/datapacks/macroEngine/1_20_5/data/runtoolkit/tags/functions/register.json new file mode 100644 index 0000000..61fc24c --- /dev/null +++ b/datapacks/macroEngine/1_20_5/data/runtoolkit/tags/functions/register.json @@ -0,0 +1,5 @@ +{ + "values": [ + "macroengine_load:init" + ] +} diff --git a/datapacks/macroEngine/data/macroengine_load/function/init.mcfunction b/datapacks/macroEngine/data/macroengine_load/function/init.mcfunction new file mode 100644 index 0000000..bfd47e4 --- /dev/null +++ b/datapacks/macroEngine/data/macroengine_load/function/init.mcfunction @@ -0,0 +1 @@ +data modify storage runtoolkit:tmp seed set value [{name:"macroengine",load_fn:"macroengine_load:main",tick_fn:"macroengine.main:macroengine/tick",disable_fn:"macroengine:disable",version_score:"#runtoolkit.packs.macroengine.version"}] \ No newline at end of file diff --git a/datapacks/macroEngine/data/macroengine_load/function/load/final.mcfunction b/datapacks/macroEngine/data/macroengine_load/function/load/final.mcfunction index e996718..eb6c422 100644 --- a/datapacks/macroEngine/data/macroengine_load/function/load/final.mcfunction +++ b/datapacks/macroEngine/data/macroengine_load/function/load/final.mcfunction @@ -1,5 +1,5 @@ data modify storage macroengine:engine global.version set value "v6.0.2" - +function #load:_private/load scoreboard players set #runtoolkit.packs.macroengine.version macroengine.meta 602 tellraw @a ["",{"text":"[MACROENGINE] ","color":"#00AAAA","bold":true},{"text":"macroEngine v6.0.2 loaded.","color":"green"}] diff --git a/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status.mcfunction new file mode 100644 index 0000000..9fced43 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status.mcfunction @@ -0,0 +1,14 @@ +# runtoolkit:diagnostics/status +# Reports live loaded/disabled state for every registered subsystem, +# read straight from each subsystem's "#runtoolkit.packs..version" +# score — not from the registry snapshot, so this reflects reality even +# if a subsystem was disabled after registering (e.g. via its own +# disable command) without re-registering. + +execute unless data storage runtoolkit:engine registry.subsystems[0] run tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"no subsystems registered — nothing to report.","color":"gray"}] +execute unless data storage runtoolkit:engine registry.subsystems[0] run return 0 + +tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"subsystem status:","color":"aqua"}] +data modify storage runtoolkit:tmp _walk set from storage runtoolkit:engine registry.subsystems +function runtoolkit:diagnostics/status_step +data remove storage runtoolkit:tmp _walk diff --git a/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status_line.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status_line.mcfunction new file mode 100644 index 0000000..2fa32f9 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status_line.mcfunction @@ -0,0 +1,11 @@ +# runtoolkit:diagnostics/status_line +# MACRO INPUT (from a registry.subsystems[n] entry): +# $(name) -> subsystem id, used to build the score holder "#runtoolkit.packs.$(name).version" +# $(version) -> the version recorded at registration time (may be stale vs. live score) +# +# Score holder names accept macro substitution directly (no string concat needed). + +$execute store result score $diag_ver runtoolkit.tmp run scoreboard players get #runtoolkit.packs.$(name).version macroengine.meta + +execute if score $diag_ver runtoolkit.tmp matches 1.. run tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_diag_call.name","storage":"runtoolkit:tmp","color":"white"},{"text":" — ","color":"#555555"},{"text":"loaded","color":"green"},{"text":" (v","color":"#555555"},{"score":{"name":"$diag_ver","objective":"runtoolkit.tmp"},"color":"aqua"},{"text":")","color":"#555555"}] +execute if score $diag_ver runtoolkit.tmp matches ..0 run tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_diag_call.name","storage":"runtoolkit:tmp","color":"white"},{"text":" — ","color":"#555555"},{"text":"disabled","color":"red"}] diff --git a/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status_step.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status_step.mcfunction new file mode 100644 index 0000000..8be89d1 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/diagnostics/status_step.mcfunction @@ -0,0 +1,19 @@ +# runtoolkit:diagnostics/status_step +# Internal recursive walker for diagnostics/status. For each registered +# subsystem, reads its live "#runtoolkit.packs..version" score +# (0 = disabled/not loaded, matches core/internal/disable/apply.mcfunction's +# convention) and prints one status line. Reads runtoolkit:tmp _walk[0] +# and pops it. +# +# NOTE: deliberately does not depend on macroengine_string (StringLib) — +# runtoolkit sits above individual subsystems and should not require any +# one subsystem's internal libraries to function. The scoreboard holder +# name is built directly via macro substitution instead of string concat. + +execute unless data storage runtoolkit:tmp _walk[0] run return 0 + +data modify storage runtoolkit:tmp _diag_call set from storage runtoolkit:tmp _walk[0] +function runtoolkit:diagnostics/status_line with storage runtoolkit:tmp _diag_call + +data remove storage runtoolkit:tmp _walk[0] +function runtoolkit:diagnostics/status_step diff --git a/datapacks/macroEngine/data/runtoolkit/function/killswitch/all.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all.mcfunction new file mode 100644 index 0000000..d3b8aac --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all.mcfunction @@ -0,0 +1,20 @@ +# runtoolkit:killswitch/all +# Global emergency stop: disables every registered subsystem via its own +# public disable entry point (respecting each subsystem's own gate/ +# confirmation behavior — this is a supervised shutdown, not a raw +# `datapack disable` sweep). Intended for admin use when something is +# misbehaving and you don't have time to disable subsystems one by one. +# +# Requires op / permission level enforced by the command tree this is +# wired into (not enforced here — see macroengine's own security.* config +# for the pattern this project follows: gating lives at the command-tree +# layer, not duplicated inside every function). + +execute unless data storage runtoolkit:engine registry.subsystems[0] run tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"no subsystems registered — nothing to stop.","color":"gray"}] +execute unless data storage runtoolkit:engine registry.subsystems[0] run return 0 + +tellraw @a ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"KILLSWITCH — disabling all registered subsystems.","color":"red","bold":true}] +data modify storage runtoolkit:tmp _walk set from storage runtoolkit:engine registry.subsystems +function runtoolkit:killswitch/all_step +data remove storage runtoolkit:tmp _walk +tellraw @a ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"killswitch complete.","color":"red"}] diff --git a/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_dispatch.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_dispatch.mcfunction new file mode 100644 index 0000000..1a5846c --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_dispatch.mcfunction @@ -0,0 +1,9 @@ +# runtoolkit:killswitch/all_dispatch +# MACRO INPUT (from a registry entry, via "with"): +# $(name) -> subsystem id, for the status line +# $(disable_fn) -> function id to call, e.g. "macroengine:disable" +# The subsystem's own disable_fn handles its gate/confirmation/cleanup; +# this just triggers it and reports. + +tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_ks_call.name","storage":"runtoolkit:tmp","color":"white"},{"text":" — ","color":"#555555"},{"text":"disabling…","color":"gold"}] +$function $(disable_fn) diff --git a/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_read_version.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_read_version.mcfunction new file mode 100644 index 0000000..0bf6e20 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_read_version.mcfunction @@ -0,0 +1,4 @@ +# runtoolkit:killswitch/all_read_version +# MACRO INPUT: $(name) -> subsystem id +# Reads "#runtoolkit.packs.$(name).version" into score $ks_ver runtoolkit.tmp. +$execute store result score $ks_ver runtoolkit.tmp run scoreboard players get #runtoolkit.packs.$(name).version macroengine.meta diff --git a/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_step.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_step.mcfunction new file mode 100644 index 0000000..74376e9 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/killswitch/all_step.mcfunction @@ -0,0 +1,17 @@ +# runtoolkit:killswitch/all_step +# Internal recursive walker for killswitch/all. Calls each registered +# subsystem's own disable_fn (its normal, gated /disable entry point) — +# does not force-disable via `datapack disable` directly, so each +# subsystem's own confirmation/sandbox/cleanup logic still runs. +# Already-disabled subsystems (version score 0) are skipped. + +execute unless data storage runtoolkit:tmp _walk[0] run return 0 + +data modify storage runtoolkit:tmp _ks_call set from storage runtoolkit:tmp _walk[0] +function runtoolkit:killswitch/all_read_version with storage runtoolkit:tmp _ks_call + +execute if score $ks_ver runtoolkit.tmp matches 1.. run function runtoolkit:killswitch/all_dispatch with storage runtoolkit:tmp _ks_call +execute if score $ks_ver runtoolkit.tmp matches ..0 run tellraw @s ["",{"text":" ","color":"#555555"},{"nbt":"_walk[0].name","storage":"runtoolkit:tmp","color":"gray"},{"text":" — already disabled, skipped","color":"#555555"}] + +data remove storage runtoolkit:tmp _walk[0] +function runtoolkit:killswitch/all_step diff --git a/datapacks/macroEngine/data/runtoolkit/function/load.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/load.mcfunction index 3c5271f..a4d2033 100644 --- a/datapacks/macroEngine/data/runtoolkit/function/load.mcfunction +++ b/datapacks/macroEngine/data/runtoolkit/function/load.mcfunction @@ -1,7 +1,12 @@ # runtoolkit global entry point — load -# Dispatches to the macroengine subsystem's own load chain. -function macroengine_load:main +# Dispatches to every subsystem listed in runtoolkit:registry/seed (a +# static, hand-maintained list — this is the ONLY place a subsystem's +# load_fn is hardcoded now; see registry/seed.mcfunction to add one). -execute unless data storage macroengine:engine global.loaded run return 0 -execute if data storage macroengine:engine global{loaded:0b} run return 0 -execute if data storage macroengine:engine global{loaded:1b} run return 1 \ No newline at end of file +# Ensure runtoolkit's own scratch objective exists. Missing this made every +# runtoolkit:* function that reads/writes "runtoolkit.tmp" fail silently +# (score get/store on a nonexistent objective does nothing, no error) — +# this is what broke registry/list, diagnostics/status and killswitch/all. +scoreboard objectives add runtoolkit.tmp dummy + +function runtoolkit:registry/load_all \ No newline at end of file diff --git a/datapacks/macroEngine/data/runtoolkit/function/registry/list.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/registry/list.mcfunction new file mode 100644 index 0000000..3a150db --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/registry/list.mcfunction @@ -0,0 +1,22 @@ +# runtoolkit:registry/list +# Reports the subsystems currently registered with runtoolkit's global +# load/tick dispatcher. Registration happens via runtoolkit:registry/register +# (called once per subsystem, e.g. from macroengine's own load chain) — +# this function only reads and prints what is already in storage. +# +# Storage shape (runtoolkit:engine): +# registry.subsystems = [ +# {name:"macroengine", version:602, load_fn:"macroengine_load:main", tick_fn:"macroengine.main:macroengine/tick"}, +# ... +# ] + +execute unless data storage runtoolkit:engine registry run data modify storage runtoolkit:engine registry set value {} +execute unless data storage runtoolkit:engine registry.subsystems run data modify storage runtoolkit:engine registry.subsystems set value [] + +execute unless data storage runtoolkit:engine registry.subsystems[0] run tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"registry is empty — no subsystems registered.","color":"gray"}] +execute unless data storage runtoolkit:engine registry.subsystems[0] run return 0 + +tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"registered subsystems:","color":"aqua"}] +data modify storage runtoolkit:tmp _walk set from storage runtoolkit:engine registry.subsystems +function runtoolkit:registry/list_step +data remove storage runtoolkit:tmp _walk diff --git a/datapacks/macroEngine/data/runtoolkit/function/registry/list_step.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/registry/list_step.mcfunction new file mode 100644 index 0000000..335e239 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/registry/list_step.mcfunction @@ -0,0 +1,13 @@ +# runtoolkit:registry/list_step +# Internal recursive walker for registry/list. Pops entries off +# runtoolkit:tmp _walk (a scratch copy) one at a time so the source +# registry.subsystems list is never mutated by listing it. + +execute unless data storage runtoolkit:tmp _walk[0] run return 0 + +execute store result score $reg_ver runtoolkit.tmp run data get storage runtoolkit:tmp _walk[0].version +execute if score $reg_ver runtoolkit.tmp matches 1.. run tellraw @s ["",{"text":" - ","color":"#555555"},{"nbt":"_walk[0].name","storage":"runtoolkit:tmp","color":"white"},{"text":" (v","color":"#555555"},{"nbt":"_walk[0].version","storage":"runtoolkit:tmp","color":"green"},{"text":")","color":"#555555"}] +execute if score $reg_ver runtoolkit.tmp matches ..0 run tellraw @s ["",{"text":" - ","color":"#555555"},{"nbt":"_walk[0].name","storage":"runtoolkit:tmp","color":"gray"},{"text":" (disabled)","color":"red"}] + +data remove storage runtoolkit:tmp _walk[0] +function runtoolkit:registry/list_step diff --git a/datapacks/macroEngine/data/runtoolkit/function/registry/load_all.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/registry/load_all.mcfunction new file mode 100644 index 0000000..73af3b1 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/registry/load_all.mcfunction @@ -0,0 +1,11 @@ +# runtoolkit:registry/load_all +# Called from runtoolkit:load. Walks the static seed (registry/seed), +# calling each subsystem's load_fn and then registering it with the live +# registry — replacing the old hardcoded "function macroengine_load:main" +# + duplicate load_fn string that used to live directly in load.mcfunction. + +function runtoolkit:registry/seed +data modify storage runtoolkit:tmp _load_walk set from storage runtoolkit:tmp seed +data remove storage runtoolkit:tmp seed +function runtoolkit:registry/load_all_step +data remove storage runtoolkit:tmp _load_walk diff --git a/datapacks/macroEngine/data/runtoolkit/function/registry/load_all_dispatch.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/registry/load_all_dispatch.mcfunction new file mode 100644 index 0000000..b1e6723 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/registry/load_all_dispatch.mcfunction @@ -0,0 +1,18 @@ +# runtoolkit:registry/load_all_dispatch +# MACRO INPUT (one seed entry, via "with"): +# $(name), $(load_fn), $(tick_fn), $(disable_fn), $(version_score) +# +# Calls load_fn, reads the resulting live version, then registers. +# version_score is a dynamic scoreboard holder name (e.g. +# "#runtoolkit.packs.macroengine.version") — score holders accept macro +# substitution directly, same pattern as diagnostics/status_line. + +$function $(load_fn) + +$execute store result score $rt_reg_ver runtoolkit.tmp run scoreboard players get $(version_score) macroengine.meta + +data modify storage runtoolkit:tmp _reg set from storage runtoolkit:tmp _load_entry +data remove storage runtoolkit:tmp _reg.version_score +execute store result storage runtoolkit:tmp _reg.version int 1 run scoreboard players get $rt_reg_ver runtoolkit.tmp +function runtoolkit:registry/register with storage runtoolkit:tmp _reg +data remove storage runtoolkit:tmp _reg diff --git a/datapacks/macroEngine/data/runtoolkit/function/registry/load_all_step.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/registry/load_all_step.mcfunction new file mode 100644 index 0000000..580f94f --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/registry/load_all_step.mcfunction @@ -0,0 +1,17 @@ +# runtoolkit:registry/load_all_step +# Internal recursive walker for registry/load_all. For each seed entry: +# 1. Call its load_fn (the subsystem's own load chain). +# 2. Read its live version score (only valid AFTER step 1 — the +# subsystem's own load chain is what sets that score, e.g. +# macroengine:config sets #runtoolkit.packs.macroengine.version). +# 3. Call registry/register with that live version, so the registry +# entry is never stale by construction. + +execute unless data storage runtoolkit:tmp _load_walk[0] run return 0 + +data modify storage runtoolkit:tmp _load_entry set from storage runtoolkit:tmp _load_walk[0] +function runtoolkit:registry/load_all_dispatch with storage runtoolkit:tmp _load_entry +data remove storage runtoolkit:tmp _load_entry + +data remove storage runtoolkit:tmp _load_walk[0] +function runtoolkit:registry/load_all_step diff --git a/datapacks/macroEngine/data/runtoolkit/function/registry/register.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/registry/register.mcfunction new file mode 100644 index 0000000..408d60d --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/registry/register.mcfunction @@ -0,0 +1,32 @@ +# runtoolkit:registry/register +# Called once by a subsystem (e.g. macroengine_load:main) to announce itself +# to runtoolkit's dispatcher. Idempotent: re-running with the same name +# overwrites that entry instead of duplicating it, so a /reload doesn't +# grow the list. +# +# MACRO INPUT: +# $(name) -> subsystem id, e.g. "macroengine" +# $(version) -> int, mirrors #runtoolkit.packs..version +# $(load_fn) -> function id dispatched on minecraft:load, e.g. "macroengine_load:main" +# $(tick_fn) -> function id dispatched on minecraft:tick, e.g. "macroengine.main:macroengine/tick" +# $(disable_fn) -> function id that cleanly disables this subsystem, e.g. "macroengine:disable" +# (used by runtoolkit:killswitch/all — must be the subsystem's public, +# gated entry point, not an internal /apply function, so the +# subsystem's own confirmation/sandbox behavior is respected) +# +# NOTE: this only records metadata for registry/list and diagnostics/status. +# It does NOT hook the subsystem into minecraft:load / minecraft:tick — +# that still happens via data/minecraft/tags/function/{load,tick}.json, +# same as today. Registration is descriptive, not wiring. + +execute unless data storage runtoolkit:engine registry run data modify storage runtoolkit:engine registry set value {} +execute unless data storage runtoolkit:engine registry.subsystems run data modify storage runtoolkit:engine registry.subsystems set value [] + +$data modify storage runtoolkit:tmp entry set value {name:"$(name)",version:$(version),load_fn:"$(load_fn)",tick_fn:"$(tick_fn)",disable_fn:"$(disable_fn)"} + +# Remove any existing entry with this name (re-registration on reload), then append fresh. +$data remove storage runtoolkit:engine registry.subsystems[{name:"$(name)"}] +data modify storage runtoolkit:engine registry.subsystems append from storage runtoolkit:tmp entry +data remove storage runtoolkit:tmp entry + +$tellraw @a[tag=macroengine.debug] ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"registry/register ","color":"aqua"},{"text":"→ ","color":"#555555"},{"text":"$(name)","color":"white"},{"text":" v","color":"#555555"},{"text":"$(version)","color":"green"}] diff --git a/datapacks/macroEngine/data/runtoolkit/function/registry/seed.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/registry/seed.mcfunction new file mode 100644 index 0000000..6591ed6 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/registry/seed.mcfunction @@ -0,0 +1 @@ +function #runtoolkit:register \ No newline at end of file diff --git a/datapacks/macroEngine/data/runtoolkit/function/version.mcfunction b/datapacks/macroEngine/data/runtoolkit/function/version.mcfunction new file mode 100644 index 0000000..9f35cf8 --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/function/version.mcfunction @@ -0,0 +1,14 @@ +# runtoolkit:version +# Reports runtoolkit's own dispatcher-layer version — NOT any individual +# subsystem's version (use runtoolkit:diagnostics/status for that). +# This tracks the runtoolkit: namespace itself (load/tick entry points, +# registry, diagnostics, killswitch) as a unit, independent of which +# subsystems happen to be registered under it. +# +# Storage: runtoolkit:engine meta.version — set once here on every call +# (idempotent) rather than only at load, so it stays correct even if this +# file is edited and the datapack reloaded without a full load-tag pass. + +data modify storage runtoolkit:engine meta.version set value "1.0.0" + +tellraw @s ["",{"text":"[RUNTOOLKIT] ","color":"#00AAAA","bold":true},{"text":"dispatcher v","color":"aqua"},{"nbt":"meta.version","storage":"runtoolkit:engine","color":"white"}] diff --git a/datapacks/macroEngine/data/runtoolkit/tags/function/register.json b/datapacks/macroEngine/data/runtoolkit/tags/function/register.json new file mode 100644 index 0000000..61fc24c --- /dev/null +++ b/datapacks/macroEngine/data/runtoolkit/tags/function/register.json @@ -0,0 +1,5 @@ +{ + "values": [ + "macroengine_load:init" + ] +} diff --git a/spyglass.json b/datapacks/macroEngine/spyglass.json similarity index 98% rename from spyglass.json rename to datapacks/macroEngine/spyglass.json index 8113c99..46a97ba 100644 --- a/spyglass.json +++ b/datapacks/macroEngine/spyglass.json @@ -24,7 +24,7 @@ }, "gameVersion": "Auto", "language": "Default", - "permissionLevel": 2, + "permissionLevel": 3, "plugins": [], "mcmetaSummaryOverrides": {} }, @@ -91,4 +91,4 @@ "executeIfScoreSet": "execute if score ${1:score_holder} ${2:objective} = ${1:score_holder} ${2:objective} $0", "summonAec": "summon minecraft:area_effect_cloud ~ ~ ~ {Age: -2147483648, Duration: -1, WaitTime: -2147483648, Tags: [\"${1:tag}\"]}" } -} \ No newline at end of file +}