Placement Profiles (generators/*.yml)
Previous: Trap System (Triggers × Actions) · Next: Natural Generation and Pre-loading (Generation Director / Density / Regen) Related: Ruin Template · Procedural Generation · Built-in Content List
A Placement Profile is a reusable rule pack that answers "where does this ruin generate": dimension / world / biome filtering, generation layer, flatness, minimum spacing, landing-spot checks, probability… One profile is a single file at plugins/QinhRuins/generators/<name>.yml. Multiple templates can share the same profile (generation.profile: surface_overworld), and each template can also locally override any field. The plugin ships 17 built-in profiles, covering all common landscapes across the three dimensions.
Tip
Division of labor in one line: the profile handles "site-selection rules"; the template handles "identity and gameplay." A template references a profile via generation.profile to inherit a full set of defaults, then only writes the fields it wants to change.
🖼️ [Image placeholder] A diagram of "template generation.profile → profile generators/*.yml → landing-spot validation chain" · suggested
assets/profile-flow.png
1. Profile vs Template Override: the Inheritance Relationship (key)
A placement profile and a template's generation section use the same set of fields. The load order is:
built-in fallback (DEFAULT) → referenced profile → fields written in the template's generation section
each layer only overrides "the keys it explicitly writes"; unwritten keys inherit from the layer above- The template writes
generation.profile: surface_overworld→ first the wholesurface_overworldprofile is taken as the base; - any field the template then writes in its
generationsection (biomes/y/flatness/min-distance-same…) overrides the same-named item in the profile key by key; - unwritten keys keep using the profile's values.
⚙ Key-by-key override, not whole-section replacement: writing only
biomes: [PLAINS]in a template will not wipe out the profile'slayer/min-distance-othersalong with it—it only overrides the singlebiomeskey, the rest stay as is. So "reference a profile + write only two or three override lines" is the recommended style.
Caution
Referencing a non-existent profile: it automatically falls back to the built-in default profile and warns in the console; an unrecognizable y (generation layer) value → falls back to surface and warns.
For the full template-side generation section syntax, see Ruin Template §5. This page focuses solely on all the fields of the profile file itself.
2. Full Field Table
The table below lists all fields of generators/*.yml (the template generation section can write the same ones). Bold ones are the most commonly configured.
| YAML Key | Type | Default | Meaning |
|---|---|---|---|
enabled | Bool | false | Whether the profile is usable (generally write true). The template-side generation.enabled is the real switch for "does this ruin take part in natural generation." |
layer (or y) | String | surface | Generation layer: surface / underground / sky / sea surface / seabed / fixed Y / relative to surface. See §4. |
environments | List | empty | Dimension environment: NORMAL (Overworld) / NETHER (Nether) / THE_END (End); empty = no restriction. |
worlds | List | empty | Further narrow by world name (empty = all worlds in that environment). |
biomes | List | empty | Restrict biomes; empty = no restriction. See §3. |
probability | section | 1/1000 | { numerator, denominator }, used for each profile's own roll only when the generation director is off. See §5. |
priority | Int | 0 | Priority: the smaller the number, the higher the priority; at a single candidate spot, only the batch with the highest priority takes part in the weighted draw. |
spawn-chance | Double | 1.0 | Absolute rarity: after being drawn, an independent dice roll is made again; only <1.0 is truly rare. |
min-distance-others | Int | 0 | Minimum spacing (blocks) from any ruin. |
min-distance-same | Int | 0 | Minimum spacing (blocks) from the same kind of ruin, to prevent clustering of the same type. |
flatness | section | — | Site flatness check { radius, max-variance, max-errors }. See §6. |
whitelist-ground | List | empty | Only allow landing on these ground blocks. |
blacklist-ground | List | empty | Forbid landing on these ground blocks. |
spawn-in-water | Bool | true | false = not allowed to land on water-surface blocks. |
spawn-in-lava | Bool | false | true = allow landing on lava surfaces (Nether lava-sea themes). |
spawn-in-void | Bool | true | false = force landing on solid ground (reject overhanging the feet over air). |
heightmap | String? | none | Heightmap algorithm for the surface layer. See §4. |
y-band | section | — | Random depth / height range { min, max } for underground / sky. |
y-offset | Int | 0 | Vertical fine-tune (the final Y is shifted ±N again; the sea surface auto-aligns to the waterline, so generally leave at 0). |
spawn-region | section | none | Coordinate-box restriction { min-x, min-z, max-x, max-z, exclude }. See §7. |
Note
layer and y are two names for the same field (layer takes precedence). In profile files it's conventional to write layer; in the template generation section it's conventional to write y. The effect is exactly the same.
3. Dimension / World / Biome Filtering
environments: [NORMAL] # dimension: NORMAL(Overworld)/NETHER(Nether)/THE_END(End); empty = no restriction
worlds: [] # further narrow by world name (empty = all worlds in that environment)
biomes: # restrict biomes (empty = no restriction)
- PLAINS
- FORESTenvironmentsrecognizesNORMAL/OVERWORLD(both equal the Overworld),NETHER/THE_NETHER, andEND/THE_END. To support custom Overworld dimensions, you can also addCUSTOM.worldsnarrows further, on top ofenvironments, to specific world names (case-insensitive). Empty = all worlds in that environment are fine.biomestakes the vanilla biome enum names (e.g.PLAINS/DESERT/LUSH_CAVES). The match rule recognizes both the "namespaced key" and the "enum name"; writing or omitting theminecraft:prefix both work; empty = no biome restriction.
⚙ The biome decision reads the actual biome of the block at the landing spot. Seabed / underground profiles land underwater / underground, and the biome is still read by that coordinate, so for
OCEAN/DRIPSTONE_CAVESand the like you must write the corresponding cave / ocean biomes.
4. Generation Layer and Height (layer / y-band / y-offset / heightmap)
layer (= y) decides which layer the structure lands on. Values:
layer / y value | Meaning |
|---|---|
surface (ground / top) | Surface. Intelligently skips tree canopy / leaves to land on the real ground. |
underground (cave / buried) | Underground, buried downward. Pair with y-band to set the depth range (default 8–40). |
sky (floating / air) | Sky, floating upward. Pair with y-band to set the height range (default 30–70). |
ocean-surface (sea-surface / water-surface) | Sea surface, auto-aligned to the waterline; if that column has no water, pick another spot. |
seabed (ocean-floor / underwater) | Seabed (solid sea-floor surface); if there's no water, pick another spot. |
Fixed number (e.g. 64) | Fixed Y coordinate. |
+8 / -5 | 8 blocks above / 5 blocks below the surface. |
+[3;12] / -[2;6] | A random 3–12 blocks above / random 2–6 blocks below the surface. |
layer: underground
y-band: { min: 10, max: 35 } # random burial depth 10~35 blocks below the surface
# y-offset: 0 # the final Y is fine-tuned ±N again
# heightmap: world-surface # surface layer only: where "the surface" is computedy-band: only takes effect forunderground/sky—undergroundis "a random[min,max]blocks below the surface,"skyis "a random[min,max]blocks above the surface."y-offset: adds a fixed offset on top of the computed final Y, for an overall fine-tune.heightmap(surface only): controls which heightmap "the surface" is computed against—world-surface/motion-blocking/motion-blocking-no-leaves(=no-leaves) /ocean-floor. Leave empty = intelligently skip tree canopy / leaves / snow / vines and land on the real ground (recommended).
⚙ The Nether's "surface" is a special algorithm: the Nether's top is a bedrock ceiling, so QR scans downward from Y≈120, finding the first block where "the block below is solid (non-lava) + the current and above blocks are both air" as the landing spot, automatically avoiding the bedrock ceiling. So a Nether profile can just write
layer: surfaceto land on the terrain's top surface.
Caution
Sea-surface / seabed profiles rely on water to decide the landing spot: if that column has no water below sea level, the spot is abandoned and re-picked. For underwater structures, make sure the schematic comes with a sealed outer shell, otherwise the interior floods.
5. Probability (probability) —— Only When the Generation Director Is Off
probability: { numerator: 1, denominator: 700 } # 1/700: each profile rolls by this only when the director is off- When the generation director is on:
probabilityis ignored, and all ruins switch to "weighted competitive draw + global density." Each template'sgeneration.weight(or, when left blank, the weight auto-converted fromprobability) takes part in the draw. - When the generation director is off (backward-compatible old logic): it falls back to "each template rolls independently by its own
probability"—every candidate spot rolls dice bynumerator/denominatorto decide whether to generate.
Note
Built-in profiles generally have a denominator of 500–900 (underground caves denser, sky / ocean sparser), a rarity baseline of "on average one per this many candidate spots." Once the generation director is on, these values no longer take effect directly, but when director.weights is left blank they get converted into draw weights, so they still carry relative-rarity meaning. For the generation director see Natural Generation and Pre-loading.
6. Flatness and Landing-Spot Checks
flatness: { radius: 4, max-variance: 4, max-errors: 0 }
whitelist-ground: [GRASS_BLOCK, DIRT] # only allow landing on these ground blocks
blacklist-ground: [SAND, WATER] # forbid landing on these ground blocks
spawn-in-water: true
spawn-in-lava: false
spawn-in-void: trueFlatness flatness: samples a ring of ground heights centered on the landing spot to judge whether the ground is flat enough.
| Field | Default | Description |
|---|---|---|
radius | — | Detection radius (blocks). 0 or max-variance:0 = no check (sky / ocean / underground profiles all turn it off). |
max-variance | — | Maximum allowed height difference. A sample point rising more than this above the lowest point counts as one "bump." |
max-errors | 0 | How many bump sample points are allowed. 0 = none at all (strictest, the ground must be very flat). |
⚙ Sampling implementation: when
radius<=4it samples every block, larger than that it samples every 2 blocks; it takes the minimum of all sampled heights as the baseline, counts the points "rising abovemax-variance," and if that exceedsmax-errorsit judges the ground uneven and abandons the spot. The flatter the ground the stricter; the more bumps the more likely to be rejected.
Landing-spot block checks (check the block directly below the landing spot, y-1):
| Field | Behavior |
|---|---|
whitelist-ground | When non-empty, the ground block must be in the whitelist (e.g. the desert profile's [SAND, SANDSTONE, RED_SAND]). |
blacklist-ground | Reject if the ground block is in the blacklist. |
spawn-in-water | false = reject if the block directly below is water. |
spawn-in-lava | false (default) = reject if the block directly below is lava; true is used for Nether lava-sea themes. |
spawn-in-void | false = reject if the block directly below is air (overhanging over the void), forcing a solid landing spot. |
7. Coordinate-Box Restriction (spawn-region)
Restrict / exclude generation within a rectangular XZ box (e.g. "no ruins in the spawn protection area").
spawn-region:
min-x: -2000
min-z: -2000
max-x: 2000
max-z: 2000
exclude: true # true = only spawn outside the box (none near spawn); false = only spawn inside the box| Field | Description |
|---|---|
min-x / min-z / max-x / max-z | The rectangular XZ range. |
exclude | false (default) = generate only inside the box; true = generate only outside the box. |
Tip
Spawn protection: exclude: true + a box enclosing the spawn point, and the newbie zone will never sprout a ruin.
8. The 17 Built-in Profiles List
The plugin ships 17 profiles under generators/, divided by dimension × landscape. A template just references one via generation.profile: <name>.
Overworld (NORMAL)
| Profile Name | Layer | Biome Range | Notes |
|---|---|---|---|
surface_overworld | surface | no biome restriction | general surface fallback, the most used |
surface_grassland | surface | plains / forest / taiga / swamp / jungle / meadow and other vegetated zones | flatness is stricter |
surface_desert | surface | desert | whitelist-ground: [SAND, SANDSTONE, RED_SAND] |
surface_snowy | surface | snowy plains / snowy taiga / ice spikes / frozen peaks / grove and other snow-ice zones | — |
surface_barren | surface | badlands / savanna / mushroom island / stony peaks and other wastelands | — |
underground_overworld | underground | no biome restriction | general crypt / tomb, y-band 10~35 |
underground_lush | underground | lush caves | y-band 6~24 |
underground_dripstone | underground | dripstone caves | y-band 8~30 |
sky_overworld | sky | no biome restriction | floating sky island, y-band 35~75 |
ocean_overworld | ocean-surface | various ocean biomes | shipwreck / floating platform, floats on the sea surface |
seabed_overworld | seabed | various ocean biomes | underwater ruin, needs its own sealed outer shell |
Nether (NETHER)
| Profile Name | Layer | Notes |
|---|---|---|
surface_nether | surface | sits on the terrain's top surface, already avoids the bedrock ceiling |
underground_nether | underground | buried in the netherrack layer, y-band 8~24 |
sky_nether | sky | floats above the lava sea, y-band 18~38 (the top is bedrock, don't set it too high) |
End (THE_END)
| Profile Name | Layer | Notes |
|---|---|---|
surface_end | surface | sits on the surface of End islands |
underground_end | underground | buried inside End-stone islands, y-band 6~18 |
sky_end | sky | floats above End islands, y-band 25~60 |
For the complete field values of the built-in profiles, see Built-in Content List.
9. Full Annotated Example
A custom "vegetated-zone surface" profile (can be dropped straight into generators/my_surface.yml):
# placement profile · custom vegetated-zone surface
enabled: true
layer: surface # generation layer: surface
environments: [NORMAL] # Overworld only
worlds: [] # no world restriction
biomes: [PLAINS, FOREST, TAIGA] # restrict biomes
probability: { numerator: 1, denominator: 600 } # each profile rolls by this only when the director is off
min-distance-others: 80 # ≥80 blocks from any ruin
min-distance-same: 320 # ≥320 blocks from the same kind of ruin
flatness: { radius: 5, max-variance: 3, max-errors: 1 } # require fairly flat ground
whitelist-ground: [] # no ground-block restriction
blacklist-ground: [WATER, LAVA]
spawn-in-water: false # don't land on water surface
spawn-in-void: false # don't overhang the void
y-offset: 0
# spawn-region: # optional: spawn protection
# min-x: -1500
# min-z: -1500
# max-x: 1500
# max-z: 1500
# exclude: true # only spawn outside this boxReference it in a template, overriding only two lines:
# template.yml fragment
generation:
profile: my_surface # reference the profile above
enabled: true
weight: 20 # draw weight
biomes: [PLAINS] # override only biomes: narrow to plains only (other fields inherit from the profile)🖼️ [Image placeholder] A comparison of the same profile referenced by three different ruin templates, each overriding only a few fields · suggested
assets/profile-shared.png
10. After You're Done
- Changed
generators/*.ymlor a template'sgenerationsection →/qr reload. - Want to confirm "can a template generate under my feet, and where does it get stuck" →
/qr why <template>(lists the pass / fail of each check one by one). - Want to see the generation director's actual hit rate nearby →
/qr gentest. - Want to immediately blanket an area within a radius to see the effect →
/qr scatter <radius> <amount>.
For details see Natural Generation and Pre-loading and Diagnostics and Troubleshooting.
Next Steps
- Generation director, density, fade-and-regen → Natural Generation and Pre-loading
- How to write the template-side
generationsection → Ruin Template §5 - Sub-structure variants / palette stitching → Procedural Generation
- All built-in profile field values → Built-in Content List