Lua v4 Script Content Packs
Script bundles need a place for server-specific route filters, selectors, item names, and messages without turning them into global Hexis constants or hiding them in Lua code. Lua v4 uses typed, bundle-local content packs for that data.
This contract is implemented in the source foundation with focused tests.
Manifest schema 1 does not expose this surface, and these docs keep
hexis.content.pack non-executable until a named distributed build passes
controlled live acceptance.
Manifest schema 2
A schema 2 bundle adds a packs array:
{
"schemaVersion": 2,
"files": [
{
"path": "main.lua",
"sha256": "<lowercase 64-character SHA-256>"
}
],
"packs": [
{
"name": "workload",
"kind": "hexis.galatea_fig",
"schemaVersion": 5,
"path": "packs/workload.json",
"sha256": "<lowercase 64-character SHA-256>"
}
]
}
Each pack descriptor has exactly name, kind, schemaVersion, path, and
sha256:
namematches[a-z][a-z0-9_-]{0,63}and is unique inside the bundle.- The public loadable kinds are
hexis.galatea_fig,hexis.zealot_one_shot,hexis.sven_engage_acceptance,hexis.experiment_table_acceptance, andhexis.melody_acceptance. The runtime also reserveshexis.area_catalogfor official embedded bundles only. schemaVersionis exactly5forhexis.galatea_figand exactly1for the combat and GUI acceptance kinds andhexis.area_catalog.pathis a canonical relative path belowpacks/, ends in.json, and is unique across both the manifest's script files and packs.sha256is exactly 64 lowercase hexadecimal characters and authenticates the file bytes.
The Lua-readable Galatea pack JSON is limited to 64 KiB, a maximum nesting depth of 8, and at most 256 values. Each combat acceptance pack is limited to 32 KiB, the same maximum depth of 8, and at most 192 values. Each GUI acceptance pack is limited to 32 KiB, depth 8, and 256 values. The host verifies the descriptor, path, bytes, kind-specific JSON bounds, kind, schema version, and complete typed payload before executing Lua. Unknown descriptor fields, unknown pack fields, unknown nested fields, unsupported kinds, and unsupported schema versions reject the bundle before Lua runs.
There are no arbitrary pack paths, process-wide pack names, filesystem reads, or fallback to a similarly named pack. A script can load only the logical names declared by its own validated manifest.
An official embedded bundle may declare at most one hexis.area_catalog pack,
which has a tighter 32 KiB limit. It is validated into the semantic
hexis.area.enter action but is never exposed through hexis.content.pack.
Marketplace and development bundles cannot define this reserved kind, and
there is no process-wide area catalog. See
Lua v4 Area Transitions.
Lua access
The only content access call is:
local workload = hexis.content.pack({name = "workload"})
The request contains exactly the logical name. It requires no capability.
The call returns the payload table directly, without a metadata envelope. Each
call receives a fresh mutable Lua copy created from the host's validated
immutable payload, so changing one returned table cannot mutate the catalog or
another call's result.
Galatea workload
The hexis.galatea_fig version 5 payload has exactly these fields:
{
"tree_route": {
"kind": "mineable_blocks",
"entry_block_types": [
"Stripped Spruce Wood"
]
},
"azalea_route": {
"kind": "mineable_blocks",
"entry_block_types": [
"Flowering Azalea"
]
},
"axe": {
"name_patterns": [
"Treecapitator",
"Figstone Splitter",
"Fig Hew",
"Decent Axe"
]
},
"tree_selector": {
"priorities": {
"minecraft:stripped_spruce_wood": 100,
"minecraft:stripped_spruce_log": 95,
"minecraft:stripped_oak_wood": 90,
"minecraft:stripped_oak_log": 85
},
"connectivity": "faces_edges_corners"
},
"azalea_selector": {
"priorities": {
"minecraft:flowering_azalea": 100
},
"connectivity": "faces"
},
"tree_cooldown_seconds": 15,
"azalea_retry_cooldown_seconds": 15,
"fishing_net": {
"name_patterns": [
"Fishing Net"
]
},
"tadpole_query": {
"area": {
"kind": "radius",
"radius": 4.5
},
"selector": {
"type_ids": [
"minecraft:tadpole"
]
},
"limit": 8
},
"regeneration": {
"type": "chat.received",
"filter": {
"contains_any": [
"You cannot damage a tree while it is regenerating"
],
"case_sensitive": false
}
}
}
Both route filters contain exactly kind and entry_block_types; a workload
pack no longer contains a route ID. Both kinds are exactly mineable_blocks.
Their required entry_block_types contain 1 through 16 exact block display
strings of at most 80 characters. Route resolution filters to those entry
blocks before applying its result cap. The axe and fishing-net selectors
contain 1 through 16 nonblank name patterns of at most 80 characters. Each
block selector contains 1 through 16 exact namespaced IDs of at most 120
characters mapped to integer priorities from 1 through 1,000. Larger numbers
are preferred. Connectivity is exactly faces or
faces_edges_corners.
The version 5 pack has no azalea-count field. The manifest configuration's
validated max_azaleas value owns that customer policy, and the removed
max_azaleas_between_trees field is rejected as unknown. Both cooldowns are
integers from 1 through 300 seconds. The Tadpole query is fixed to a radius from
0.5 through 4.5, exact type minecraft:tadpole, and limit 1 through 8.
regeneration.type is exactly chat.received. Unknown nested fields reject the
bundle.
Lua can then compose validated data with implemented actions and events:
local workload = hexis.content.pack({name = "workload"})
local config = hexis.config.snapshot()
local arrival = hexis.await(hexis.area.enter({
destination = "hypixel.skyblock.galatea",
}), {timeout = 30})
if not arrival.ok then return arrival end
local regeneration = hexis.events.subscribe(workload.regeneration)
local route = hexis.routes.seeds({
route = config.route,
kind = workload.tree_route.kind,
entry_block_types = workload.tree_route.entry_block_types,
})
local harvest = hexis.mining.mine_connected({
world_generation = route.world_generation,
seeds = route.seeds,
blocks = workload.tree_selector,
held = workload.axe,
handoff = "confirmed",
navigation = {allow_ether_transmission = false},
})
local selected = hexis.select({harvest, regeneration}, {timeout = 600})
if selected.kind ~= "action" then
hexis.cancel(harvest)
end
This moves Galatea-specific selectors and scheduling data out of main.lua
without duplicating the customer-selected route. That route comes from the
strict configuration contract described in
Lua v4 Script Configuration. Mining
algorithms, budgets, retries, and vantage selection remain engine-owned. The
pack carries the fixed azalea selectors, cooldown, Tadpole query, and
regeneration filter consumed by the configurable scheduler described in
Lua v4 Galatea Workload. Adding another
workload requires a new explicit pack kind and schema rather than weakening
this boundary into generic JSON or global server data.
Reduced combat acceptance workloads
The official Zealot one-shot and Sven engagement bundles use strict schema 1
packs with kinds hexis.zealot_one_shot and
hexis.sven_engage_acceptance. These schemas carry only the fixed destination,
bounded entity query, exact targeting evidence, action parameters, and retry
timing needed by those reduced workloads. They are not generic combat
configuration, a server-wide target catalog, or a promise of Zealot Farmer or
Sven Slayer parity. Sven's flee_health is a strict manifest configuration
field, not workload-pack data. See
Lua v4 Combat Actions for their exact acceptance
scope and exclusions.
Reduced GUI acceptance workloads
The official Experiment Table and Melody bundles use strict schema 1 packs
with kinds hexis.experiment_table_acceptance and
hexis.melody_acceptance. The first carries fixed titles, layout slots, item
signatures, and click delay for its three reduced puzzle policies. The second
carries the Harp title and slot count, note and stack item IDs, score-chat
filter, and click delay. Strings are nonblank and bounded to 128 characters;
arrays are nonempty, unique, and bounded by their typed schema. Unknown fields
reject the bundle before Lua runs.
These packs do not expose raw click parameters, purchase policy, arbitrary screen rules, or timing control for unrelated scripts. They do not establish Experiment Table auto-renew or Melody perfect-score parity. See Lua v4 GUI Evidence and Actions for the precise transaction, event, workload, and live-acceptance boundaries.