Config Comment Style¶
Conventions for comments that document options in shipped YAML config files
(e.g. config.yml, safety.yml, performance.yml, economy.yml,
logging.yml, messages.yml, per-region and per-world configs, and the
lite variants under rtp-plugin/src/lite/resources/).
These rules apply to admin-facing config resources only. Internal Java/Kotlin code comments and KDoc are unaffected.
The governing decision is recorded in ADR-064; this document is its canonical, example-rich style guide. The key architectural constraint: the first comment line of each option doubles as the option's hover tooltip in the config menu (ADR-035 / ADR-044), so it must read as a standalone summary.
Rule (the pattern)¶
Every documented option shall be preceded by a comment block with two parts, in this order:
- Summary line — exactly one line, starting with a capital letter, stating what the option does. No trailing period required. Aim for under ~80 characters.
- Details block — zero or more follow-up comment lines giving the information an admin needs to actually set the value. Required content when applicable:
- Valid options — enumerate them (
"yaml","sqlite","mysql","postgresql"), give the type and range (integer, >= 0,seconds, 0 disables), or point at the authoritative list (tag resolver, Bukkit Material enum, etc.). - Default — only if it differs from the shipped value on the next line, or if the shipped value is platform-conditional.
- Units — seconds, blocks, ticks, bytes, percent, etc.
- Side effects / dependencies — other options this interacts with, S-00x prohibitions it touches, or admin docs to read first.
If an option is fully self-explanatory from its key name and a single sentence, the details block may be omitted — the summary line alone is enough.
Machine-readable enumeration tags (for the menu system)¶
Admin-facing menus (the generalized menu framework, ADR-035 / ADR-044) need
to programmatically discover the valid values, type, and range of each
option without re-parsing English prose. To support this, the details
block may include one or more structured directive lines. Each
directive lives on its own comment line, starts with # @, uses
key: value form, and the value is YAML-flow syntax (so the existing
SnakeYAML parser can consume it directly).
Reserved directive keys:
@type— one ofenum,integer,number,boolean,string,material,biome,world,tag, or alist<…>of any of the preceding (e.g.list<material>,list<string>). Required when any other directive is present.@options— exhaustive YAML-flow list of valid scalar values forenum-typed options. Strings are quoted in the list exactly as they must appear in the YAML. Example:# @options: ["yaml", "sqlite", "mysql", "postgresql"].@range—[min, max]forinteger/number. Either bound may benullto denote open-ended. Example:# @range: [0, null].@unit— short token:seconds,ticks,blocks,chunks,percent,bytes,ms. Free-form prose units stay in the prose details block, not here.@default— the canonical default value (YAML scalar). Only emit when the shipped value differs from the default or the default is platform-conditional.@source— when the valid values come from a runtime registry rather than a fixed enumeration, name the registry:material→ BukkitMaterialenum,biome→ BukkitBiomeregistry,world→ loaded worlds (RTP.serverAccessor.getRTPWorlds()),region→ loaded RTP regions (RTP.selectionAPI.regionNames()),tag→#minecraft:<tag>resolver,shape→ registered RTP shape factories (ShapeParameter.values()),vert→ registered RTP vertical-adjustor factories (VertParameter.values()). Mutually exclusive with@options. Prefer@sourceover a hardcoded@optionslist for any discriminator whose valid values come from a live registry — shape/vert type discriminators, and server-derived values that change at runtime but are not authored by this plugin such asworld/region— so the menu stays authoritative against the registry and cannot drift.
Rules:
- Directive lines shall appear after the prose summary line and before the key they document. They may be interleaved with prose detail lines; menus ignore prose, prose readers ignore directives.
- Directive values shall be valid YAML-flow expressions so that
parsing the substring after
:with a YAML loader yields the intended Java value. Do not invent ad-hoc syntax. - An option without directives is treated by the menu as a free-form
text field — acceptable for genuinely unconstrained strings, but
prefer to add
@type+ (@options|@range|@source) for anything an admin might mis-type. - Do not duplicate prose: if
@options: ["yaml", "sqlite", "mysql", "postgresql"]is present, the prose may omit the enumeration and just describe semantics ("file-backed vs. networked", etc.).
Examples¶
Enum-valued:
# Database backend used for persistence.
# yaml/sqlite are file-backed and require no extra config; mysql and
# postgresql use the host/port/name/username/password fields below.
# @type: enum
# @options: ["yaml", "sqlite", "mysql", "postgresql"]
# @default: "sqlite"
database:
type: "sqlite"
Bounded integer with unit:
# Wait time before a queued teleport executes.
# 0 teleports immediately (skips the cancel-on-move window).
# Interacts with cancelDistance below.
# @type: integer
# @range: [0, null]
# @unit: seconds
# @default: 2
teleportDelay: 2
Boolean:
# Refill the region cache immediately after a successful teleport.
# @type: boolean
# @default: false
postTeleportQueueing: false
Registry-sourced scalar:
# Material used for the emergency landing platform.
# @type: material
# @source: material
platformMaterial: GLASS
Registry-sourced list (with optional tag references):
# Blocks treated as passable air for landing-safety checks.
# Accepts Material names and #minecraft:<tag> references.
# @type: list<material>
# @source: material
airBlocks:
- AIR
- CAVE_AIR
Bounded fraction:
# Probability of rejecting an ungenerated chunk per selection attempt.
# 0.0 = no bias, 1.0 = strictly avoid ungenerated land. Generated
# chunks always pass.
# @type: number
# @range: [0.0, 1.0]
# @default: 0.0
pregeneratedPreference: 0.0
Parsing contract¶
The menu adapter shall treat the directive grammar as the single source of truth:
- Collect contiguous
#-prefixed lines immediately above a key. - For each line matching
^#\s*@(\w+):\s*(.*)$, parse the captured value with a YAML scalar/flow loader; reject (log + skip the option for the menu) on parse failure. - Validate consistency:
@optionsrequires@type: enum(orlist<enum>);@rangerequires@type: integerornumber;@sourceand@optionsare mutually exclusive. - Prose lines (non-directive
#lines) are concatenated into a tooltip string in source order and surfaced to the admin verbatim.
Directives are intentionally minimal so the same grammar can be reused
by future tooling (config validators, /rtp config set autocompletion,
docs generators) without further extension.
Layout¶
- Put the comment block immediately above the key it documents, with no blank line between the last comment line and the key.
- Separate adjacent documented options with a single blank line; this prevents the previous option's details from visually bleeding into the next option's summary.
- For grouped/nested keys, comment the parent map with a summary, then comment each child key the same way. Do not document children only via a single block above the parent.
- For list-valued options (
airBlocks:,unsafeBlocks:,biomes:), the comment block goes above the key. Inline# notecomments on individual list entries are allowed for entry-specific caveats (e.g. why a tag was excluded), but the option's own summary + details belong above the key.
Examples¶
Good — summary + details + valid options¶
# Database backend used for persistence.
# Valid options: "yaml", "sqlite", "mysql", "postgresql".
# yaml/sqlite are file-backed and require no extra config; mysql/postgresql
# use the host/port/name/username/password fields below.
database:
type: "sqlite"
Good — summary + units + range¶
# Wait time before a queued teleport executes.
# Units: seconds. Integer >= 0. 0 teleports immediately (skips the
# cancel-on-move window). Interacts with cancelDistance below.
teleportDelay: 2
Good — summary only (self-explanatory)¶
# Material used for the emergency landing platform.
platformMaterial: GLASS
Good — list option with inline note on a specific entry¶
# Blocks treated as passable air for landing-safety checks.
# Accepts Bukkit Material names and #minecraft:<tag> tag references.
airBlocks:
- AIR
- CAVE_AIR
# Note: #minecraft:tall_flowers is an item-only tag in vanilla; its
# members are already covered by #minecraft:flowers above.
- "#minecraft:flowers"
Bad — terse one-liner with no valid options¶
# database type
type: "sqlite"
Bad — details block with no summary line¶
# Valid options: "yaml", "sqlite", "mysql", "postgresql". yaml/sqlite are
# file-backed; mysql/postgresql require the host/port fields below.
database:
type: "sqlite"
Bad — blank line between comment and key¶
# Wait time before a queued teleport executes.
# Units: seconds.
teleportDelay: 2
File header¶
The first comment block of a config file is a file-level header, not an option comment. It shall contain:
- A one-line title (
# --- RTP Safety Configuration ---). - A link to the admin docs (
# Documentation: …/docs/admin/SAFETY.md).
The file-level header is separate from the first option's summary line.
Version sentinel¶
The version: key at the bottom of each config file is reserved for the
config-migration system. Its existing # DO NOT TOUCH VERSION NUMBER
comment is the canonical form; do not reword it.
When updating existing files¶
- Touching an option's value is not a license to rewrite its comment; apply this style only when you are already editing that option's lines, introducing a new option, or the existing comment is actively misleading.
- Bulk reformat passes across a whole config file should be a dedicated
change, not bundled with a behavior change. See Stay-On-Task Policy in
.junie/AGENTS.md. For the priority order in which files should be brought into this format with minimal translation cost, seeCONFIG_COMMENT_MINIMIZATION.md. - When in doubt about valid options, link to the relevant admin doc
(
docs/admin/CORE_CONFIG.md,docs/admin/SAFETY.md, etc.) rather than duplicating an enumeration that will drift.
Encoding¶
Config files are UTF-8, no BOM, LF line endings — same as markdown. See
Markdown Encoding Hygiene in .junie/AGENTS.md for the mojibake rules;
they apply identically to YAML comments.