Skip to content

Structure

Pheno data is made of typed nodes. Most nodes are JSON objects with a type field, such as pheno:health, pheno:heal, or pheno:environment.

Each node belongs to a domain. A field that expects an action cannot accept a condition, and a field that expects a block action cannot accept an entity action.

DomainUsed For
ActionDoes something, including wrappers and control flow.
ConditionFilters or gates the current entity context by returning true or false.
Bi-entity conditionFilters or gates a relationship between an actor and a target.
Block actionActions at a block position.
Item actionActions against an item stack.
ValueRuntime numeric values.
CapabilityEffective flags and numeric modifiers resolved from registered sources.
GenePheno-backed gene nodes used inside Roots gene files. See Gene Nodes.

A condition is a filter: it does not choose a new target by itself, it decides whether the current context passes. A selector chooses one or more targets, blocks, item stacks, or places from the current context. An action can then run on the current context or on the selected results.

Pheno actions, conditions, selectors, and values all read context. The common context has an actor entity, sometimes another target entity, and sometimes a block or item focus. See Context for the full reference.

For example, an action can use on to select a new focus:

{
"type": "pheno:damage",
"amount": 4,
"on": {
"type": "pheno:ray",
"distance": 12
}
}

The ray selector chooses a target. The damage action then runs on that selected target, while the original actor remains available as context.

Context wrappers change where an inner action runs:

WrapperEffect
pheno:actor_actionRuns the inner action on the actor.
pheno:target_actionRuns the inner action on the other entity.
pheno:invertSwaps actor and target for the inner action.
pheno:block_actionBridges from an entity action to a block action.
pheno:equipped_item_actionRuns an item action on equipped gear.

Authoring shortcuts can lower into these wrappers. For example, a with block can target self, target, held_item, offhand, block_here, or block_below, then normalize to the matching canonical node.

Conditions usually appear under when or condition. Actions usually appear under do or action.

{
"when": {
"type": "pheno:health",
"max": 10
},
"do": {
"type": "pheno:heal",
"amount": 4
}
}

Here when filters the current context. If the condition passes, do runs the action.

Selectors choose things from the current context. Entity selectors choose living things, block selectors choose block positions, and item selectors choose item stacks. Selector fields often appear as on, blocks, or where, depending on the domain.

Values calculate numbers from the current context. A value can be a fixed number, or it can read the world at runtime, such as counting selected entities.

Readable units are accepted where a field schema supports them:

{
"cooldown": "3s",
"chance": "50%"
}

Durations normalize to ticks. Percentages normalize to fractions.

Pheno validation checks typed child slots against the live registries. Unknown action, condition, block-action, item-action, and bi-entity condition types are reported with a JSON path and a suggestion.

Field validation is driven by Townstead’s generated field metadata and is intentionally partial. Types without generated field metadata may still parse and run; they just do not yet have full generated field documentation.