<!-- https://minecraftdocs.dev/systems/items/contexts-and-predicates — this page as markdown. The book's index: https://minecraftdocs.dev/llms.txt; the whole book in one file: https://minecraftdocs.dev/llms-full.txt -->

# Contexts and predicates

> Verified against **Minecraft 26.3** · Part VII · A command asks *is this true, here, of this entity?* — and the machinery that answers is the same machinery that decides what a chest contains.

`/execute if predicate example:in_the_rain run say wet` is a question about
the world, and the world is not something a data-pack file may look at.
Before anything can be tested, the server has to turn *here* into something a
JSON file is allowed to interrogate: a position, maybe an entity, nothing
else. It does that by building a small typed map of parameters and
handing it to an object loaded out of a registry, which returns a boolean.
That machinery is usually called the loot system, because most of it lives
in `net/minecraft/world/level/storage/loot` — but the keys and the sets it
is built from live in `net/minecraft/util/context` and know nothing about
loot at all. **Seventeen of the thirty-one parameter sets never roll a loot
table**, and the set that is enforced is always the *caller's*: a loot
table's own declared *type* is read only by the load-time validator, once a
reload, and never consulted by a roll.

## Two packages, one machine

The machine is five classes in two packages, and which class sits in which
package is the fact the rest of the page hangs off.

```mermaid
flowchart TD
    Callers["block breaks, deaths, chests, commands, selectors, advancements, trades, enchantment effects, fuel, composters"]
    Client["SlotDisplayContext, on the client"]:::client
    subgraph U["util/context"]
        CK["ContextKey, an Identifier plus a static type"]
        CKS["ContextKeySet, the required keys and the allowed"]
        CMap["ContextMap, the checked bag of values"]
    end
    LPar["LootParams, the immutable inputs"]:::server
    LCtx["LootContext, one invocation"]:::server
    CK -->|"declared required or optional by ContextKeySet.Builder"| CKS
    CKS -->|"ContextMap.Builder.buildAndValidate validates against it"| CMap
    Callers -->|"each brings its own key set"| CKS
    Client -->|"builds a ContextMap of its own"| CMap
    CMap -->|"wrapped, with a ServerLevel beside it"| LPar
    LPar -->|"plus a random source and a resolver"| LCtx
```

*Every arrow leads down toward a checked map or the invocation built on it, and the box is the whole
of the general-purpose half. The three classes inside it name no item, block, entity
or loot table; the two below it are the loot package, and everything that
asks a question is outside on the right.*

The dividing line is the whole argument of this page. `ContextKey`,
`ContextKeySet` and `ContextMap` are three small general-purpose classes in
`net/minecraft/util/context` with no dependency on items, blocks, entities
or loot. Everything below them is in the loot package, and everything
*above* them is whoever wants a question answered. Whatever rolls a loot table is one such caller. The others are commands, entity selectors, advancement triggers,
villager trades, every conditional enchantment effect, a furnace's or brewing stand's fuel
and a composter's layers — and, on the *client*, `SlotDisplayContext`, which
builds a `ContextMap` of its own so a recipe book entry can resolve itself
into stacks. World generation builds one too, in `NoiseChunk`, with no key
set at all: it is how the blender and the beardifier reach the density
functions.

## The cast

| class | package | what it owns | when |
|---|---|---|---|
| `ContextKey` | *util/context* | one parameter's name and its Java type, and nothing else | — |
| `ContextKeySet` | *util/context* | which keys a call site must supply, and which it may | built once at class-init |
| `ContextMap` | *util/context* | the values, and the only place the contract is enforced | Server for loot; the Render thread builds its own for a recipe display, and world generation one per `NoiseChunk` |
| `LootParams` | *storage/loot* | the `ServerLevel`, the map, the dynamic-drop callbacks, the luck | Server |
| `LootContext` | *storage/loot* | one invocation: the random source, the reference resolver, the visited stack | Server |
| `LootItemCondition` | *storage/loot/predicates* | a predicate over a `LootContext` — the boolean answer | Server |
| `ContextFloatProvider` | *storage/loot/providers* | a float over a `LootContext` — the numeric answer, beside `ContextIntProvider` for an int | Server |
| `ValidationContext` | *storage/loot* | at load, whether an element asked for a key its set does not have | the worker pool |

## A key is a name with a type welded to it

`ContextKey` is an `Identifier` and a phantom type parameter. It has no
value, no default, no validation and no registry — `ContextKey.vanilla`
just makes one in the *minecraft* namespace, and only twenty-one exist: the
sixteen static fields of `LootContextParams`, the one on `SlotDisplayContext`
that lets a client draw a recipe, and four that world generation declares on
`Blender` and `Beardifier`. The type parameter is what
makes the rest of the system safe: `LootContextParams.ORIGIN` is a key of
`Vec3`, `LootContextParams.TOOL` a key of `ItemInstance` (the read-only
item view), `LootContextParams.ENCHANTMENT_LEVEL` a key of a boxed *int*, and
a reader gets that type back without a cast.

Those twenty-one keys are Java, and a data-pack author never types one of
their names. What a JSON file writes instead is a *target* — *this*,
*attacker*, *target_entity*, *tool*, *block_entity* — and `LootContextArg` is
the small translator between the two, resolving a target to a key out of
three enums nested in `LootContext`: `LootContext.EntityTarget` with six
entity keys, `LootContext.BlockEntityTarget` and
`LootContext.ItemStackTarget` with one each. One slot source,
`RangeSlotSource`, adds a target outside them, *container*, for
`LootContextParams.CONTAINER`.

All three enums resolve through `LootContextArg.SimpleGetter`, which reads the map
with `LootContext.getOptional`, the one way a context hands out a parameter's value. A target the
current set does not carry therefore evaluates to nothing instead of taking
the tick down — which is the second of the three ways a parameter can be
missing, two sections on.

## A set is a contract, and the caller signs it

`ContextKeySet` holds two sets: `ContextKeySet.required` and
`ContextKeySet.allowed`, the second the union of required and optional, and
its `ContextKeySet.Builder` refuses to make one key both in either order.
`LootContextParamSets` registers thirty-one of them into the built-in
registry `BuiltInRegistries.CONTEXT_KEY_SET`, which is what
`LootContextParamSets.CODEC` reads when a data pack names a set by id — and
the ids do not always match the field names:
`LootContextParamSets.PIGLIN_BARTER` is *barter* and
`LootContextParamSets.ALL_PARAMS` is *generic*. Every set's keys are
tabulated in [Loot context parameter
sets](../../reference/loot-context-params).

`LootContextParamSets.ALL_PARAMS` deserves its own warning, because it is
the default a loot table with no declared *type* gets
(`LootTable.DEFAULT_PARAM_SET`) and the set every standalone predicate, item
modifier, slot source and number provider file is validated against — and it
**is all of them**. It requires all sixteen keys, and
`LootContextParamSets.validate` fails the bootstrap if any other set allows a
key it does not require. The practical consequence: a standalone predicate
file is never flagged at load for a key it reads, so one that asks about a
block state or a damage source loads clean even though
`LootContextParamSets.COMMAND` — the set `/execute if predicate` builds —
carries neither.

## Three ways a parameter can be missing

A mismatch between what a call site has and what an element wants is caught
at three different moments, with three different costs, and the three are not
alternatives — an element can pass the load-time check and still come back empty at read time. `ContextMap.Builder.buildAndValidate` is where the contract is enforced,
and it is the only place: it throws if the values collected include a key the set
does not allow, and again if the set requires a key that is absent. Note
what it compares — the keys the **caller** supplied against the set the
**caller** named. Nothing on this path ever sees the loot table.

1. **At build time.** `ContextMap.Builder.buildAndValidate` throws, naming the
   offending keys. That is a programming error rather than a data one, and on a tick it takes
   the tick down with it (a command catches it and fails).
2. **At read time.** `LootContext.getOptional` is the one way a context hands out a
   parameter's value (`LootContext.hasParameter` only asks whether one is there),
   and it returns nothing for a missing key, so the conditions and
   functions degrade quietly rather than fail — `LocationCheck`, `MatchBlock`
   and `EnchantmentActiveCheck` all answer **false**. So the standalone-file
   validator's silence about a block state is survivable: from `/execute if
   predicate` such a predicate is quietly false, not fatal.
3. **At load time.** `ValidationContext.validateContextUsage` compares
   what an element declares it reads —
   `LootContextUser.getReferencedContextParams`, overridden by
   twenty-seven classes — against `ContextKeySet.allowed`, and reports the
   difference.

### The load-time check is the loose one

It checks against *allowed*, not
*required*, so an element that reads an optional key passes validation and
can still take path 2 at runtime. And what
`ReloadableServerRegistries.validateLootRegistries` does with the collected
problems is **log them as warnings** and fail the reload only on a reference
cycle: a predicate that asks for a parameter it cannot have loads fine and
misbehaves later. The same validation is a
hard error in exactly two places, both applied by a codec —
`Validatable.validatorForContext` for `VillagerTrade`, and its list form
`Validatable.listValidatorForContext` for every conditional effect in
`EnchantmentEffectComponents`. Neither a trade nor an enchantment effect can
name a predicate by id: both are decoded with the world's registries, before
the predicate registry is loaded, so `RegistryFileCodec` rejects the
reference outright.

## Inputs, then one invocation

`LootParams` is the immutable half: a `ServerLevel`, the `ContextMap`, a
map of `LootParams.DynamicDrop` callbacks keyed by `Identifier`, and a
float of luck. The `ServerLevel` is the mechanical guarantee that no loot context is built on the client — `LootParams.Builder` takes one in its
constructor and `LootContext.Builder.create` dereferences the server off it
for the registries, so a `ClientLevel` cannot produce a context at all.

`LootContext` is the per-invocation half, and it adds three things
`LootParams` does not have: the chosen `RandomSource`, a
`HolderGetter.Provider` that resolves references to other loaded elements,
and a set of `LootContext.VisitedEntry` used as a recursion guard.
`LootContext.pushVisitedElement` returns false when the element is already
present, which is how `LootTable.getRandomItemsRaw` refuses a table already
rolling — it logs an infinite loop and rolls nothing. The guard is a **stack, not a history**: `LootContext.popVisitedElement` takes the entry off again on
the way out, so rolling the same table twice in one evaluation is fine and
only genuine re-entrancy trips it. Both of the command call sites below —
`/execute if predicate` and the selector's *predicate* option — seed it with
the top-level predicate before testing, but no predicate reads it back: one
that references itself by name never loads, because `Validatable.validateHolder`
reports the cycle as a fatal `ValidationContext.RecursiveElementReferenceProblem`.

**Named random sequences belong to the context, not to the table.**
`LootContext.Builder.create` takes an optional `Identifier` and picks a
random source three ways, in order: an explicit source or a **non-zero** seed
handed to `LootContext.Builder.withOptionalRandomSeed`, else
`MinecraftServer.getRandomSequence` for the named sequence, else
`Level.getRandom`. `RandomSequences` is a `SavedData` ([level data and
rules](../../reference/level-data-and-rules)) that derives each sequence's
seed from the world seed, a salt and the sequence id, which is what makes a
named sequence reproducible across restarts. A loot table supplies that
identifier from its own field — and so does `TradeSet.randomSequence`, read
by `AbstractVillager.addOffersFromTradeSet`, which is why a villager's trade
selection is reproducible by the same mechanism and has nothing to do with
loot. What a zero seed in that order means for a chest belongs to [loot
tables](loot-tables#where-the-randomness-comes-from).

## What reads a context

`LootContextUser` — *what did you read out of the map* — is extended by five
data-driven types: `LootItemCondition`, `LootItemFunction`, `NbtProvider`,
`ScoreboardNameProvider` and `SlotSource`. The number providers read the same
map through two interfaces of their own, `ContextFloatProvider` and
`ContextIntProvider`. Each of the seven has its own registry of kinds
([data-driven types](../foundations/data-driven-types#the-idea-stated-once)),
and three of them carry the traffic. `LootItemCondition` is a predicate over a
`LootContext` with twenty types registered in `LootItemConditionTypes`, from
`LootItemEntityPropertyCondition` and `LocationCheck` to
`EnchantmentActiveCheck` and `MatchBlock`; `ContextFloatProvider` returns a
float and has twenty-eight, from `ConstantValue` and `UniformGenerator` to
`EnchantmentLevelProvider`, and `ContextIntProvider` returns an int and has
twenty-three. Their codecs are forgiving in the same shape:
`LootItemCondition.CODEC`, `ContextFloatProviders.CODEC` and
`ContextIntProviders.CODEC` each take a bare id as a reference to an element
of their own registry, and the two number codecs take a bare number as a
`ConstantValue`. `NbtProvider` and `ScoreboardNameProvider` are the two small ones — a tag out
of an entity, a block entity or command storage, and a scoreboard name, fixed or out of a context target — and `LootItemFunction` belongs to [loot
tables](loot-tables#one-roll-drawn). One of the seven lives outside the loot
package altogether: `SlotSource`, in `net/minecraft/world/item/slot`, answers
a `SlotCollection` rather than a boolean or a number, and its six registered
kinds compose — `GroupSlotSource`, `FilteredSlotSource`, `RangeSlotSource`,
`LimitSlotSource`, `ContentsSlotSource` and `EmptySlotSource`. Its consumers
are the `SlotLoot` entry, which is how a loot table names a slot of the entity
it is rolling for, and `SlotSourceArgument`, the *slots* argument of `/item`
and `/execute if items`.

The advancement system tests conditions directly: the *player* half of every trigger but `ImpossibleTrigger`,
`SimpleCriterionTrigger.SimpleInstance.player`, is one
`LootItemCondition` in a `Holder`, named by id or written inline, and
`EntityPredicate.wrap` folds an `EntityPredicate` into a
`LootItemEntityPropertyCondition` to make one. The rest of
`net/minecraft/advancements/predicates` need not touch a context: a trigger
instance can hold an `ItemPredicate` or a `LocationPredicate` outright and
test it with no context at all, which `ConsumeItemTrigger` and
`DistanceTrigger` both do.

## Who asks, and with which set

Twenty-eight callers. The six in **bold** ask a question with no loot table
anywhere in sight, and six more roll no table either; read the six and skim the
rest, which are here as the evidence for the count at the end of the section.

| caller | set | when |
|---|---|---|
| `BlockBehaviour.getDrops` | `LootContextParamSets.BLOCK` | any block break ([block breaking](../blocks/block-breaking#remove-damage-roll-drop)) |
| `Block.dropFromBlockInteractLootTable` | `LootContextParamSets.BLOCK_INTERACT` | beehives, cave vines, carving a pumpkin, sweet berries |
| `LivingEntity.dropFromLootTable` | `LootContextParamSets.ENTITY` | death ([damage and death](../entities/damage-and-death#death-or-not)) |
| `LivingEntity.dropFromShearingLootTable` | `LootContextParamSets.SHEARING` | sheep, mooshrooms, snow golems, bogged |
| `LivingEntity.dropFromGiftLootTable` | `LootContextParamSets.GIFT` | hero gifts, cat gifts, chicken eggs, sniffer digs |
| `LivingEntity.dropFromEntityInteractLootTable` | `LootContextParamSets.ENTITY_INTERACT` | brushing an armadillo |
| `RandomizableContainer.unpackLootTable` | `LootContextParamSets.CHEST` | first touch of a structure container |
| `ContainerEntity.unpackChestVehicleLootTable` | `LootContextParamSets.CHEST` | first touch of a chest minecart or chest boat |
| `FishingHook.retrieve` | `LootContextParamSets.FISHING` | reeling in — luck is the hook's plus the owner's |
| `BrushableBlockEntity` | `LootContextParamSets.ARCHAEOLOGY` | brushing suspicious sand or gravel |
| `PiglinAi.getBarterResponseItems` | `LootContextParamSets.PIGLIN_BARTER` | bartering |
| `Mob.createEquipmentParams` | `LootContextParamSets.EQUIPMENT` | the `EquipmentUser.equip` path, for a spawner's mob |
| `VaultBlockEntity` | `LootContextParamSets.VAULT` | a trial chamber vault's display item and its reward |
| `TrialSpawner.ejectReward`, `TrialSpawnerStateData.getDispensingItems` | `LootContextParamSets.EMPTY` | a trial spawner's reward and its dispensed items |
| `AdvancementRewards.grant` | `LootContextParamSets.ADVANCEMENT_REWARD` | advancement loot |
| `Enchantment.damageContext` and its four siblings | the four enchanted sets plus `LootContextParamSets.HIT_BLOCK` | [an enchantment effect's condition](enchantments#how-one-hook-fires) |
| `BaseContainerBlockEntity.getLootContext` | `LootContextParamSets.CONTAINER_PROCESS` | a furnace's or brewing stand's fuel |
| `ComposterBlock.addLayer` | `LootContextParamSets.BLOCK_INTERACT` | how many layers an item adds to a composter |
| `LootCommand` | block, entity, chest or fishing | `/loot` |
| `ItemCommands.applyModifier` | `LootContextParamSets.COMMAND` | `/item … modify` and the *from … modifier* forms |
| `ItemCommands.getSlotsFromProvider` | `LootContextParamSets.COMMAND_SLOT_SOURCE` | the *slots* of `/item` and `/execute if items` |
| `LootContextSources` | the three *command_compute* sets | `/compute` and `/data modify … compute` |
| **`ExecuteCommand`** | `LootContextParamSets.COMMAND` | **`/execute if predicate`** |
| **`EntitySelectorOptions`** | `LootContextParamSets.SELECTOR` | **a selector's *predicate* argument** |
| **`EntityPredicate.createContext`** | `LootContextParamSets.ADVANCEMENT_ENTITY` | **every advancement trigger that tests an entity** |
| **`ItemUsedOnLocationTrigger`, `AnyBlockInteractionTrigger`** | `LootContextParamSets.ADVANCEMENT_LOCATION` | **placing or using an item on a block** |
| **`DefaultBlockInteractionTrigger`** | `LootContextParamSets.BLOCK_USE` | **right-clicking a block, for an advancement** |
| **`AbstractVillager.addOffersFromTradeSet`** | `LootContextParamSets.VILLAGER_TRADE` | **rolling and filtering a villager's offers** |

### Fourteen roll a table; seventeen never do

The bold rows have no loot table anywhere in sight: a boolean, or in the
villager's case a `MerchantOffers`, is the whole output.
`ValidationContextSource` even keeps a cached
`LootContextParamSets.ADVANCEMENT_ENTITY` context around, because so much
of the advancement tree validates against it.

Count *sets* rather than rows and the picture is starker. Fourteen of the
thirty-one are named above by a caller that goes on to roll a `LootTable`.
**The other seventeen never do.** Six are the bold rows —
`LootContextParamSets.COMMAND` counts among them, because its other caller,
`/item`'s modifier forms, applies an item modifier rather than a table. Five are the
enchantment sets, built only by `Enchantment` to decide whether an effect
fires. Five more are built for a number or a set of slots: the three
*command_compute* sets, `LootContextParamSets.COMMAND_SLOT_SOURCE` and
`LootContextParamSets.CONTAINER_PROCESS`. The seventeenth is
`LootContextParamSets.ALL_PARAMS`, which is never used to build a
`ContextMap` at all: it exists solely as a validation
context and as `LootTable.DEFAULT_PARAM_SET`. That is why this page is not
called *loot tables*.

## Four facts about a question with two keys in it

`/execute if predicate` is a short complete use of the machine: one
command, one `ContextMap`, one predicate, and no loot table anywhere in it.

```mermaid
sequenceDiagram
    participant ExecC as ExecuteCommand
    participant LootP as LootParams
    participant CMap as ContextMap
    participant LootC as LootContext
    participant LIC as LootItemCondition

    Note over ExecC: the argument already holds a Holder, resolved at parse time
    ExecC->>LootP: LootParams.Builder on the level, ORIGIN required, THIS_ENTITY optional
    LootP->>CMap: ContextMap.Builder.<br/>buildAndValidate against LootContextParamSets.COMMAND
    CMap-->>LootP: the checked map, or a throw on a bad key
    ExecC->>LootC: LootContext.Builder.create with no random sequence
    Note over LootC: the random source is Level.getRandom, the resolver is the reloadable registries
    ExecC->>LootC: pushVisitedElement, seeding the recursion guard with this predicate
    ExecC->>LIC: test
    LIC->>LootC: getOptional, the one way to a parameter, null for a missing key
    LIC-->>ExecC: a boolean, and the branch is taken or not
```

*The whole machine, once, with no loot in it. Read the two dashed
returns — the first is the only place the contract is enforced, and the last
is the only thing the caller gets back.*

Three details in that picture are worth pulling out, and a fourth about the
call site it does not draw.

**The predicate is resolved before the command runs.** The argument type is
`ResourceOrIdArgument.LootPredicateArgument`, which accepts *either* a
registry id *or* an inline SNBT object and hands back a `Holder` — a
reference in the first case, a direct holder over a freshly parsed
condition in the second. An unknown id fails at parse time, as a command
syntax error, not at execution.

**`LootContextParamSets.COMMAND` is thin.** It requires
`LootContextParams.ORIGIN` and optionally allows
`LootContextParams.THIS_ENTITY`, and that is all: a predicate run from
`/execute` cannot see a block state, a damage source or a tool, whatever
the standalone-file validator let through. The selector's version,
`LootContextParamSets.SELECTOR`, differs in exactly one way — it makes the
entity *required*, because a selector always has one.

**There is no random sequence.** `ExecuteCommand` passes an empty optional,
so `Level.getRandom` is what a `LootItemRandomChanceCondition` inside the
predicate draws from — not correlated between runs, not reproducible across
restarts.

**The selector path is the same code, and it is not in the diagram.**
`EntitySelectorOptions` builds its context *per candidate entity*, inside
the predicate it hands the parser, and looks the condition up itself
through the reloadable registries rather than through the argument type —
so a missing predicate there is a silent false, not a syntax error.

## Six registries, rebuilt on `/reload`, and none of them networkable

`LootDataType` is the six loot registries expressed as data:
`LootDataType.TABLE` over `Registries.LOOT_TABLE`,
`LootDataType.PREDICATE` over `Registries.PREDICATE`,
`LootDataType.MODIFIER` over `Registries.ITEM_MODIFIER`,
`LootDataType.SLOT_SOURCE` over `Registries.SLOT_SOURCE`, and
`LootDataType.FLOAT_PROVIDER` and `LootDataType.INT_PROVIDER` over
`Registries.CONTEXT_FLOAT_PROVIDER` and `Registries.CONTEXT_INT_PROVIDER`.
Each pairs a registry key with a `LootDataType.ContextGetter` — the function
that says which `ContextKeySet` an element of that type is validated
against. Every type but tables gets the constant
`LootContextParamSets.ALL_PARAMS`; tables get `LootTable.getParamSet`, and that
context getter is its only caller in the game. That is the sense in which a
table's declared type is never checked at runtime.

### Reloadable, and never networkable

All six live in `RegistryLayer.RELOADABLE` and are rebuilt by every reload
([the resource
system](../foundations/resource-system#reload-the-same-pipeline-on-the-server)),
which is what makes them the reachable half of the data-driven game: a
predicate a pack changed is live after `/reload`. One step of that rebuild matters here — **a predicate names its tags against the
ones this reload has just read**, so a tag a pack added in the same reload
resolves, though what it holds is bound only when the reload is applied. None
of the six appears in `RegistryDataLoader.SYNCHRONIZED_REGISTRIES`, the
list `RegistrySynchronization.isNetworkable` tests, so none is ever packed
for a client. What crosses the wire is only the *result* — a container
packet, an item entity, a command's success.

Both dependants outside this part are Part XIII's: its commands — this page
owns `/execute if predicate` itself, and what Part XIII owns is the engine it
runs in and the [selector
argument](../commands/entity-selectors) whose *predicate* option is the
other caller — and [the advancement
system](../commands/advancements), whose triggers build a context per tested entity or interaction.

> **For a 1.21-era reader.** *LootContextParam* is `ContextKey` and
> *LootContextParamSet* is `ContextKeySet`, both moved out of the loot package
> to `net/minecraft/util/context`. The predicate library that consumes them
> has left the misspelled *critereon* package for
> `net/minecraft/advancements/predicates` and `net/minecraft/advancements/triggers`.
> *NumberProvider* is now `ContextFloatProvider` and `ContextIntProvider`, and
> *ConditionReference* and *ContextAwarePredicate* are gone: a `Holder` does their work.
> [The drift table](../../reference/naming-drift) has the rest.

## Where to look

Three files, in this order, are the whole argument: `ContextKey`,
`ContextKeySet` and `ContextMap`, in `net/minecraft/util/context`. They are
short, they import nothing from the loot package, and reading them is the
fastest way to see that the loot system's foundation is not about loot.

Then `LootContextParams` and `LootContextParamSets` for the sixteen loot keys
and the thirty-one sets — the second is one long list of builders and repays
skimming rather than reading. `LootParams` and `LootContext` above them are
the two halves of one invocation, and `LootContext.Builder.create` is where
the random source is chosen three ways.

`LootItemCondition` is the interface with twenty implementations; open two of
them, `LocationCheck` for the ordinary shape and `InvertedLootItemCondition`
for one that holds another in a `Holder`, and then `Validatable.validateHolder`
for the load-time cycle check in use. `ValidationContext.validateContextUsage` is the
load-time check, and `LootDataType` is where it is told which set to check
against.

For the callers, `ExecuteCommand` and `EntitySelectorOptions` are two small complete examples of building a context by hand.

---

*Rules: names, never code · how the system works, not how the code reads ·
newest version only · every backticked name passes `tools/verify_names.py`.*
