Skip to content

Ruin Template (full template.yml fields)

Previous: Server Owner Guide Overview · Next: Structure Files (.nbt / .schem / marker blocks / terrain blending)

This is QR's most central chapter: how to write template.yml, the ID card of a ruin. After reading it you'll be able to understand and write ruin templates of any complexity.

📦 Want a ready-made template to copy? The plugin ships with templates/_example/template.yml (heavily commented; starting with _ it won't be loaded as a real ruin). Copy it, rename it, and you're off.

🩺 Configured a ruin but it won't generate? See /qr why in Diagnostics & Troubleshooting.


1. File Layout: One Ruin = One Folder

Each ruin is a folder under plugins/QinhRuins/templates/<id>/, usually with a three-piece set inside:

text
templates/
└── ancient_tower/           ← folder name (used as the ruin ID when no id is written)
    ├── template.yml         ← the template definition itself (the star of this chapter)
    ├── structure.nbt        ← the ruin's block body (structure file)
    └── blueprint.yml        ← the gameplay layer (spawn points / objectives / mechanisms / core)

Caution

⚠️ Folders starting with _ or . are ignored (e.g. _example) and not loaded as real ruins. A folder must contain template.yml to be recognized, otherwise it's skipped. Where structure files come from and how they blend into terrain is covered in Structure Files; how to configure blueprints is in Blueprint & Objectives.

After editing template.yml/qr reload to reload.


2. Top-Level Field Reference Table

The table below lists every top-level section of template.yml and its purpose. Bold = most commonly used.

YAML keyTypeDefaultMeaning
idStringfolder nameUnique ruin ID (blank = use folder name)
displayString= idDisplay name, supports & and § color codes
iconStringFILLED_MAPIcon material name shown in the codex
respawnduration0 (no reset)Spawn reset interval (30s/10m/1h/2d)
structuresectionrequiredStructure file reference + placement method (see §4)
generationsectionWhere it generates (references a placement profile + local overrides, see §5)
lootsectionContainer loot (what the chests in the structure roll, see §6)
rewardsectionClear reward table (see §7)
entrysectionEntry requirements (soft gate, see §8)
foundationsectionoffFoundation fill / terrain blending (see §9)
titlessectionbuilt-in textEnter / clear screen titles (see §10)
guide_item / guide-itemself-built compassGuide item (see §11)
sessionsectionbuilt-inSession mode / time limit / empty cleanup (see §12)

Each section is detailed below. Each gives "field descriptions + example + common usage."


3. Basic Identity (id / display / icon / respawn)

yaml
id: example_ruin                 # Unique ruin ID (blank = use folder name). Everything else (commands/loot/guides) references it
display: "§6Example Ruin"        # Display name, supports & and § color codes, shown in titles/bossbar/codex
icon: FILLED_MAP                 # Codex icon material (e.g. OAK_BOAT / ELYTRA / FILLED_MAP)
respawn: 30m                     # Spawn reset interval
FieldDescription
idAll lowercase, alphanumeric + underscores. Blank takes the folder name. Changing the ID is equivalent to a different ruin; already-generated old anchors will fail to find their template.
displayPlayer-visible name. §6 = gold, &a = green, etc.; both color-code styles are recognized.
iconAny vanilla Material name, used for codex cards and the GUI.
respawnThe reset cycle for the anchor's spawns. 0 or omitted = no reset after clearing (more like a one-time landmark). Duration format: 30s / 10m / 1h / 2d; a bare number = seconds.

4. structure Section (Core)

structure decides which block file, how it's rotated, and how it blends into terrain. This is the template's only entry point for dealing with the "structure body."

yaml
structure:
  file: structure.nbt            # Structure file name (placed in this folder, native Bukkit .nbt)
  rotation: none                 # none / random (markerless structures can have random orientation)
  # target-mask: [AIR]           # Mask paste: only place where the world has these blocks = blend into terrain without bulldozing
  # source-skip: [AIR]           # Source block blacklist: skip these types, don't place them
  # source-mask: [STONE, DEEPSLATE]  # Source block whitelist: only place these types
  # replace-blocks:              # Batch block swap after pasting
  #   STONE: AIR
  #   OAK_PLANKS: DARK_OAK_PLANKS
  # palette: my_tile_palette     # Procedural tiling palette (advanced, see Procedural Generation)
FieldTypeDefaultDescription
fileStringstructure.nbtStructure file name, relative to this ruin folder. QR uses native Bukkit .nbt; .schem must first be converted with /qr import.
rotationStringnonenone = fixed orientation; random = one of four directions chosen randomly each generation. Also supports fixed angles like fixed:90.
target-maskListemptyTarget mask: only place where the world hits these blocks → the structure blends into terrain instead of bulldozing the whole footprint.
source-skipListemptySource block blacklist: don't place these types from the structure (e.g. don't place air boxes).
source-maskListemptySource block whitelist: only place these types, skip everything else.
replace-blocksMapemptyBatch block swap after pasting (frame-spread, doesn't lag the server), for themed skin variants.
paletteString?noneProcedural tiling palette ID (advanced usage).

Caution

⚠️ The full rules for masks / marker blocks / rotation / frame-spread placement are extensive and get their own chapter — see Structure Files. Here we only list field positions; the specifics of how to blend terrain, the REPLACEABLE and !exclude syntax, and marker blocks (barrier → hollow / bedrock → terrain show-through) are all in that chapter.


5. generation Section (Where It Appears)

generation answers "where in the world and with what probability this ruin generates naturally." The core approach: reference a placement profile, then only write the fields you want to override.

yaml
generation:
  profile: surface_overworld     # Reference a placement profile (17 built-in, see generators/)
  enabled: true                  # Whether it participates in natural generation
  weight: 20                     # Director draw weight (higher = more common)
  # priority: 0                  # Priority: lower number = higher priority; among competitors at one spot, only the highest-priority batch enters the draw
  # spawn-chance: 1.0            # Absolute rarity: after being drawn, roll an independent die; only <1.0 is truly rare
  biomes: [PLAINS, FOREST]       # Restrict to biomes; empty = unrestricted
  y: surface                     # Generation layer
  flatness: { radius: 4, max-variance: 4, max-errors: 0 }
  min-distance-others: 64        # Minimum spacing from any ruin
  min-distance-same: 256         # Minimum spacing from same-kind ruins

5.1 The Three Core Fields

FieldDefaultDescription
profilenoneReferences a generators/<name>.yml placement profile, inheriting all its defaults. Strongly recommended; below, only write what you want to change. See Placement Profiles.
enabledtrue to participate in natural generation; false = only manual deployment via /qr spawn / /qr stage.
weight0Director draw weight, higher = more common. Multiple ruins compete for one slot by weight. See Natural Generation & Pre-load.

5.2 Site Range Overrides (override the profile's same-named items)

FieldDescription
environmentsDimension NORMAL / NETHER / THE_END; empty = unrestricted.
worldsRestrict to world names; empty = all worlds in that dimension.
biomesRestrict to biomes (e.g. [PLAINS, FOREST]); empty = unrestricted.
spawn-regionCoordinate-box restriction: { min-x, min-z, max-x, max-z, exclude }. exclude:false = only inside the box; exclude:true = only outside the box (e.g. "don't spawn near spawn point").

5.3 Generation Layer and Height

yaml
  y: surface                     # Generation layer
  # y-band: { min: 10, max: 35 } # Random depth/height for underground/sky
  # y-offset: 0                  # Vertical fine-tune (sea surface already auto-aligns to the water line, usually leave 0)
  # heightmap: world-surface     # Heightmap for the surface layer
y valueMeaning
surfaceGround surface
undergroundUnderground (pair with y-band for the depth band)
skySky (pair with y-band for the height band)
ocean-surfaceSea surface (auto-aligns to the water line)
seabedSea floor
top (= ground)Ground surface (alias of surface, identical effect)
fixed number (e.g. 64)Fixed Y
+8 / -58 blocks above / 5 blocks below the surface
+[3;12] / -[2;6]Random 3–12 blocks above / random 2–6 blocks below the surface

heightmap is only used by the surface layer, controlling where "ground surface" is computed: world-surface / motion-blocking / motion-blocking-no-leaves / ocean-floor. Leave empty = intelligently skip tree canopy and land on the true ground (recommended).

5.4 Landing Detection

FieldDefaultDescription
whitelist-groundemptyOnly allow landing on these ground blocks (e.g. [GRASS_BLOCK, DIRT]).
blacklist-groundemptyForbid landing on these ground blocks (e.g. [SAND, WATER]).
flatnessradius:4 etc.Site flatness check: radius = detection radius (0 = no check); max-variance = allowed height difference; max-errors = how many bumpy sample points are allowed. The flatter the terrain, the stricter.
spawn-in-watertruefalse = don't allow landing on water-surface blocks.
spawn-in-lavafalsetrue = allow landing on a lava surface (Nether lava-sea theme).
spawn-in-voidtruefalse = force landing on solid ground (reject hanging in the air).

5.5 Density and Rarity

FieldDefaultDescription
min-distance-othersMinimum spacing from any ruin (blocks). If set, it's used (may go below the global fallback); if not set (0), use the global density.min-spacing.
min-distance-sameMinimum spacing from same-kind ruins (blocks), to prevent clustering of the same type.
priority0Priority: lower number = higher priority. At one candidate spot, only the highest-priority (smallest value) batch enters the weighted draw. All-0 by default = purely by weight.
spawn-chance1.0Absolute rarity: after being drawn, roll an independent die once more; only <1.0 truly makes it rare (e.g. 0.1 = even when selected, only a 10% chance to actually generate, for rare landmarks).

Tip

💡 Common usage: most ruins only need profile + enabled + weight + biomes + y. Rare boss ruins additionally add spawn-chance: 0.1 and a high min-distance-same.


6. loot Container Loot Section

Place vanilla chests / barrels and other containers in the structure; when a player opens one, it rolls rewards from the loot table specified here.

yaml
loot:
  mode: per-player               # per-player: a separate copy per player / shared: one real server-wide container
  container-table: vault         # loottables/vault.yml (single table, shared by all containers)
  # container-tables:            # or split tables by container type (takes priority over the single table above):
  #   CHEST: vault
  #   BARREL: default
FieldDefaultDescription
modeper-playerLoot mode (see table below).
container-tablenoneA single loot table shared by all containers (loottables/<name>.yml).
container-tablesemptySplit tables by container type, takes priority over container-table. The key is the container material name.

The two mode values:

ModeBehavior
per-playerEach player gets their own copy the first time they open a container (preserving the mystery), scaled by their individual growth.
sharedA real server-wide shared container (first come, first served; once taken, it's gone); furnaces / brewing stands fill real slots. Loot is neutral: no growth scaling, no min-growth gate, everyone gets the same copy.

Caution

⚠️ Structure has a lot of decorative containers (e.g. barrels in a ship hull)? Go to the loot table's containers field and declare only [CHEST], to avoid turning every barrel into treasure. The container-loot master switch and interface row count are in the vessel section of config.yml. The full loot-table syntax is in Loot System.


7. reward Clear Reward Section

The reward table handed out after a player completes all kill objectives.

yaml
reward:
  clear-table: realm             # loottables/realm.yml
FieldDescription
clear-tableThe clear-reward loot table name (loottables/<name>.yml).

This is the "one-time payout for clearing the ruin" reward; it's a different thing from the realm's purge reward (the exclusive loot of the keystone endgame), which is configured under realm.reward in config.yml — see Realms & Keystones.


8. entry Entry Requirements Section

QR does not pull players into a separate world, so this isn't a "dungeon gate" but a soft gate for "whether you're qualified to operate in this ruin."

yaml
entry:
  min-players: 1
  max-players: 10
  # required-classes: [warrior]  # Classes that must be present (QinhClass)
  min-growth: 0.0                # Minimum growth
  # cost: "100"                  # Entry cost (economy)
  cooldown: 0s
FieldDefaultDescription
min-players1Minimum number of players present.
max-players10Maximum number of players present.
required-classesemptyClasses that must be present (integrates with QinhClass).
min-growth0.0Minimum growth gate (prevents low-power players from forcing their way into high-level ruins).
costemptyEntry cost (requires an economy plugin).
cooldown0sCooldown before the same player can re-enter. Duration format same as respawn.

9. foundation Foundation / Terrain Blending Section

Makes the ruin grow a foundation downward to avoid floating or cliff edges, "planting" the structure into the terrain.

yaml
foundation:
  enabled: true
  max-depth: 16                  # Max blocks to fill downward
  ignore-water: true
  blend-radius: 4                # Outward edge taper of N blocks to blend into terrain
  materials:                     # Swap foundation material by biome
    default: STONE
    "DESERT,BADLANDS": SANDSTONE
FieldDefaultDescription
enabledfalseMaster switch.
max-depth16Max blocks to fill downward (1–256). Stops on hitting solid ground.
ignore-watertruetrue = treat water as fillable too (foundation passes through water bodies).
blend-radius0Outward edge taper of N blocks to blend into terrain (0 = fill only directly below, may leave a cliff). The larger, the more natural the edges.
materialsemptySwap foundation material by biome. default is the fallback; a key can be comma-separated to share one material across multiple biomes (e.g. "DESERT,BADLANDS": SANDSTONE).

Tip

💡 Both foundation fill and edge taper are frame-spread background tasks, no server lag. The full mechanics (how biome materials are matched, how it coordinates with masks) are in the foundation section of Structure Files.


10. titles Section

The large on-screen title that pops when a player enters / clears. The placeholder {ruin} = display name.

yaml
titles:
  enter-new: "§6⚔ You have entered {ruin}"
  clear: "§aYou have passed the trial of {ruin}"
  enter-explored: "§7A step too late — only the chests are left to rummage"
FieldTrigger
enter-newFirst entering an unexplored ruin.
clearCompleting kill objectives, clearing.
enter-exploredEntering a ruin already explored / cleared by someone else.

If omitted, the built-in text from lang/<language>/*.yml is used. To unify server-wide text, edit the language file; for special text on a single ruin, write it here.


11. Guide Item (guide_item / guide-item)

A player holding the guide item right-clicks → confirmation GUI → starts guidance (compass points to the nearest ruin of this kind); on arrival it's permanently consumed.

yaml
guide_item: ''                   # Guide item reference: blank = use the guide-item section below to self-build a simple compass
guide-item:                      # Fallback appearance when guide_item is blank (self-built simple compass)
  material: COMPASS
  name: "§bRuin Compass"
  lore: ["§7Hold and right-click to start guidance"]
  consumable: false

Two ways to use it:

① Use an existing item as the guide item —— give guide_item an item-source reference:

yaml
guide_item: "qi:ruin_compass"    # Also accepts mi:type:id / ia:xxx / ce:xxx / mm:xxx / a vanilla material name (e.g. COMPASS)

② Leave it blank and let QR self-build a simple compass —— define the appearance with the guide-item section:

FieldDescription
materialItem material (default COMPASS).
nameItem name.
loreList of description lines.
model-dataCustom model data.
consumabletrue = consumed after reaching the target.

Caution

⚠️ QR has no built-in command to "hand out a guide item." A guide item can only be given by an item-source plugin / loot / shop, referencing this ruin's qinhruins:guide_<this ruin id>. The full guidance gameplay, HUD placeholders, and confirmation GUI config are in Guide & Codex and the guide section of config.yml full configuration.


12. session Section

Controls enter / leave session behavior. Usually fine left at defaults.

yaml
session:
  mode: shared-anchor            # Session mode
  time-limit: 30m                # Session time limit
  cleanup-on-empty: 60s          # How long after everyone leaves before the session is cleaned up
FieldDefaultDescription
modeshared-anchorSession mode (shared per anchor).
time-limit30mSession time limit. Note QR is not a dungeon; this isn't a clear countdown, just the duration of the session state.
cleanup-on-empty60sHow long after everyone leaves the activation range before the session state is cleaned up.

Enter/leave prompts, bossbar, and party-shared progress are detailed in Party & Session; bossbar color / style is in the session section of config.yml.


13. Fully Annotated Example

A real ruin (surface ancient-tower style) with all the above sections put together:

yaml
id: ancient_tower                # Unique ruin ID
display: "§6Ancient Tower"       # Display name
icon: STONE_BRICKS               # Codex icon
respawn: 1h                      # Spawns reset hourly

structure:
  file: structure.nbt            # Block body
  rotation: random               # Random orientation (only recommended for markerless structures)
  target-mask: [REPLACEABLE]     # Blend into terrain: only place at air/water/vegetation/snow/leaves

generation:
  profile: surface_overworld     # Reference the surface overworld profile
  enabled: true
  weight: 20                     # Draw weight
  biomes: [PLAINS, FOREST, TAIGA]
  y: surface
  flatness: { radius: 5, max-variance: 3, max-errors: 1 }
  min-distance-others: 80
  min-distance-same: 320

loot:
  mode: per-player               # Per-player container opening
  container-tables:
    CHEST: vault                 # Chests use the vault table
    BARREL: default              # Barrels use the default table

reward:
  clear-table: tower_clear       # Clear reward table

entry:
  min-players: 1
  max-players: 8
  min-growth: 0.0
  cooldown: 0s

foundation:
  enabled: true
  max-depth: 16
  blend-radius: 4                # 4-block edge taper to blend into terrain
  materials:
    default: STONE_BRICKS
    "DESERT,BADLANDS": SMOOTH_SANDSTONE

titles:
  enter-new: "§6⚔ You have set foot in the Ancient Tower"
  clear: "§aThe guardians of the Ancient Tower have been cleared"
  enter-explored: "§7The tower is in ruins — it seems you arrived too late"

guide_item: ''                   # Use the self-built compass
guide-item:
  material: COMPASS
  name: "§bAncient Tower · Guide Compass"
  lore: ["§7Hold and right-click to point to the nearest Ancient Tower"]
  consumable: false

🖼️ [Image placeholder] A screenshot of the above Ancient Tower naturally generated in the world, with foundation taper blending it into the plains · suggested assets/template-anatomy.png


14. After Editing

  • Edit template.yml/qr reload to reload all templates.
  • Referenced a nonexistent profile → automatically falls back to the default profile and warns in the console.
  • An unrecognized y value → falls back to surface and warns.
  • To confirm whether it can generate where you stand → /qr why <id>; to deploy it manually right away and see the effect → /qr stage start <id> (ghost preview, see Selection & Saving) or /qr spawn <id>.

Next Step