Block Predicates

A block predicate is a test on the state of the block at a given position. Placed feature placement modifiers, many configured features and the enchantment effects all use them to decide whether something may generate at a position.

Reference: Block predicate

Writing a Predicate

Every field taking a block predicate exposes a builder block named after it. Inside that block a single predicate is used as-is, and several predicates are combined into an all_of:

placedFeature("my_flower", flowerFeature) {
	blockPredicateFilter {
		// One predicate: used directly.
		predicate { solid { offset(0, -1, 0) } }
	}

	blockPredicateFilter {
		// Several predicates: wrapped in an `all_of`.
		predicate {
			solid { offset(0, -1, 0) }
			not { matchingFluids(Fluids.WATER) }
		}
	}
}
Kotlin

Wrap the body in anyOf { } to combine the predicates with an or instead:

blockPredicateFilter {
	predicate {
		anyOf {
			matchingBlocks(Blocks.STONE)
			matchingBlocks(Blocks.DEEPSLATE)
		}
	}
}
Kotlin

The builders are scoped: they only resolve inside a block that accepts a block predicate, so they never show up in the global completion list. The same field also accepts a value directly, which is handy to reuse a predicate across several features:

blockPredicateFilter {
	predicate = allOf {
		solid()
		insideWorldBounds()
	}
}
Kotlin

Offsets

Every predicate testing a single block accepts an offset, applied to the position being placed. Each component has to be between -16 and 16:

predicate {
	// Tests the block one below the position.
	solid { offset(0, -1, 0) }
}
Kotlin

all_of, any_of, height_range, matching_biomes, not, true and volume_match have no offset - they either combine other predicates or test the position itself. volume_match tests the box between its own min and max corners, each given as an offset from the position.

Predicate Types

Builder Passes when
allOf { } Every child predicate passes
alwaysTrue() Always
anyOf { } At least one child predicate passes
hasSturdyFace(direction) The block has a full supporting surface on that face
heightRange(min, max) The Y level is between both vertical anchors, included
insideWorldBounds() The position is inside the height limits of the world
matchingBiomes(biomes) The biome is one of the given biomes or in the given biome tag
matchingBlockTag(tag) The block is in the given block tag
matchingBlocks(blocks) The block is one of the given blocks or in the given block tag
matchingFluids(fluids) The fluid is one of the given fluids or in the given fluid tag
not { } The child predicate does not pass
replaceable() The block can be replaced by a placed block (air, water, grass)
solid() The block is solid
unobstructed() No entity occupies the space of the block
volumeMatch(min, max) { } Every block of the box between both corner offsets passes
wouldSurvive(state) The given block state is a valid placement there

Blocks, Fluids and Biomes

matchingBlocks, matchingFluids and matchingBiomes accept several entries or a tag, and serialize a lone entry as a bare string:

predicate {
	matchingBlocks(Blocks.STONE, Blocks.DEEPSLATE)   // "blocks": ["minecraft:stone", "minecraft:deepslate"]
}

predicate {
	matchingBlocks(Tags.Block.LOGS)                  // "blocks": "#minecraft:logs"
}

predicate {
	matchingBiomes(Tags.Worldgen.Biome.IS_SAVANNA)   // "biomes": "#minecraft:is_savanna"
}
Kotlin

matchingBlockTag is the separate matching_block_tag type, which writes the tag without its # prefix.

Volume Match

volumeMatch tests every block of a box, given by two corner offsets from the tested position, against the predicate built in its block. Each component has to be between -16 and 16. This is the desert well check, which requires no air under the whole area (water or any other non-air block passes):

blockPredicateFilter {
	predicate {
		volumeMatch(Triple(-2, -2, -2), Triple(2, -1, 2)) { not { matchingBlockTag(Tags.Block.AIR) } }
	}
}
Kotlin
{
	"type": "minecraft:volume_match",
	"match": {
		"type": "minecraft:not",
		"predicate": {
			"type": "minecraft:matching_block_tag",
			"tag": "minecraft:air"
		}
	},
	"max": [2, -1, 2],
	"min": [-2, -2, -2]
}
JSON

Would Survive

wouldSurvive tests a block state as if a player had placed it, which is the reliable way to check that a plant has valid ground:

blockPredicateFilter {
	predicate { wouldSurvive(blockState(Blocks.OAK_SAPLING)) }
}
Kotlin

Where Predicates Are Used

Field Purpose
blockPredicateFilter { predicate { } } Discards the placement positions failing it
environmentScan { targetCondition { } } Stops the scan on the first block passing it
environmentScan { allowedSearchCondition { } } Restricts the blocks the scan may walk through
blockBlob / hugeBrownMushroom / hugeRedMushroom / spike { canPlaceOn { } } Ground the feature may grow on
blockColumn { allowedPlacement { } } Blocks the column may be placed in
disk { target { } } Blocks the disk replaces
hugeFungus { replaceableBlocks { } } Blocks the fungus may grow through
lake { canPlaceFeature / canReplaceWithAirOrFluid / canReplaceWithBarrier { } } Lake carving rules
rootSystem { allowedTreePosition { } } Positions the tree may be placed at
spike { canReplace { } } Blocks the spike may grow through
ruleBasedStateProvider { rule(provider) { } } Condition of a block state provider rule

See Also

  • Features - the placement modifiers and providers taking predicates
  • Structures - the separate rule tests used by processors
  • World Generation - overview of the worldgen system