Configuration load and reload¶
Scope of this diagram. This chart covers the configuration data flow — how the YAML files under plugins/RTP/ become the in-memory ConfigParser / MultiConfigParser objects that every runtime path reads from, and what happens during /rtp reload. This is the single most error-prone surface (most "bug reports" are misread config), so this diagram is the one to open first when a key appears to have no effect. Related-but-separate behavior paths are intentionally out of scope:
- Plugin enable ordering (when
reloadActionis first called) — see diagram 06. - How a runtime task reads a value (
getWorldParserValuevs. directConfigParser.getConfigValue) — see diagrams 01 / 08 / 09 andCODE_TOUR.md§11. - Message routing (
messages.ymlkeys → player feedback) — seeCODE_TOUR.md§7 and ADR-020 (locale resolution lives inLanguageBootstrap+ locale-awareConfigParser). - Persistent storage of player/teleport state (
YamlFileDatabase) — seeLESSONS_LEARNED.mdand diagram 02.
Companion walkthrough:
CODE_TOUR.md§13 — Configuration load and reload.
flowchart TD
%% Color legend: green = live-parser swap (new readers see new values), red = in-flight cancel / region shutdown, blue = disk I/O + async shape selection, yellow = config data / snapshot
Trigger{{First enable<br/>or /rtp reload}}:::data
Bootstrap[LanguageBootstrap reads<br/>language.yml<br/>ADR-020]:::async
FlushDB[fileDatabase.processQueries MAX<br/>then connect]:::async
CancelTasks[ScanTask.kill<br/>processingPlayers.clear<br/>cancel in-flight RTPTeleportCancel]:::fail
subgraph NewParsers [Build new parser maps off to the side]
direction TB
P1[logging.yml]:::async
P2[config.yml]:::async
P3[messages.yml<br/>locale-aware ConfigParser<br/>ADR-020 / REQ-RTP-F-013]:::async
P4[economy.yml]:::async
P5[performance.yml]:::async
P6[safety/*.yml]:::async
P7[regions/*.yml<br/>MultiConfigParser]:::async
P8[worlds/*.yml<br/>one per RTPWorld]:::async
end
Swap[[Atomic swap<br/>configParserMap = new<br/>multiConfigParserMap = new]]:::success
InFlightNote[/In-flight tasks hold<br/>their old parser snapshot<br/>until they complete/]:::data
ShutRegions[Region.shutDown each<br/>permRegionLookup.clear<br/>tempRegions.clear]:::fail
BuildRegions[For each regions/*.yml:<br/>RegionConfigLoader.load -> RegionSettings]:::async
Dormant{World loaded?}:::data
LiveRegion[new Region world bound<br/>log success]:::success
DormantRegion[new Region world=null<br/>log 'dormant'<br/>OnWorldLoadUnload will rebind]:::data
ShapePick[miscAsyncTasks: region.getShape.select<br/>skipped if dormant or null shape]:::async
OnReload[onReload callbacks<br/>e.g. integrations reattach]:::success
Done([Ready — every new read<br/>sees new values]):::success
Trigger ==> Bootstrap
Bootstrap --> FlushDB
FlushDB --> CancelTasks
CancelTasks --> NewParsers
NewParsers --> Swap
Swap -.-> InFlightNote
Swap --> ShutRegions
ShutRegions --> BuildRegions
BuildRegions --> Dormant
Dormant -- Yes --> LiveRegion
Dormant -- No --> DormantRegion
LiveRegion --> ShapePick
DormantRegion --> ShapePick
ShapePick ==> OnReload
OnReload ==> Done
classDef success fill:#b7e4b7,stroke:#1f6b1f,stroke-width:2px,color:#0b2a0b;
classDef fail fill:#f4b7b7,stroke:#8a1f1f,color:#3a0b0b;
classDef async fill:#cfe2ff,stroke:#1f4e8a,color:#0b1f3a;
classDef data fill:#fff2b3,stroke:#8a6d1f,color:#3a2f0b;
How to read this chart¶
- Single accepting state:
Done. Every other node is either preparatory I/O (blue), destructive bookkeeping (red), a data/decision point (yellow), or the atomic swap (green). - The reload is not in-place. New
ConfigParser/MultiConfigParserobjects are built in fresh maps, then theconfigParserMap/multiConfigParserMapfields are replaced atomically. Any task already holding a reference to the old parser continues to see the old values — this is why mid-teleport reloads are safe but a key change "doesn't apply" until the player's current teleport finishes. - Dormant regions are normal. If a region's configured world isn't loaded yet (common with Multiverse-style lazy world loaders), the
Regionis built with anullworld and rebinds onWorldLoadEventviaOnWorldLoadUnload.rebindWorld. Shape selection is deferred until the rebind completes. - Override resolution is not shown here. The per-world / per-region override chain (
requirePermission,override, cycle-guardworldsAttempted/regionsAttempted) lives in diagram 07; this chart only covers how the backing data gets into memory.
Common repair lenses¶
- "Changed a value, didn't take effect." Either (a) an in-flight task is still holding the old snapshot — wait one teleport cycle, or (b) the value lives in a per-region/per-world file and the caller is reading the global
ConfigKeysparser — checkgetWorldParserValuevs.getParser(ConfigKeys.class). - "Reload duplicates regions / leaks regions."
reloadRegionscallsRegion.shutDownon every entry before clearing the lookup maps — if a region lingers, itsshutDownthrew or a third party added topermRegionLookupafter the swap. - "Messages are in English despite the configured locale." The active locale is read from
plugins/RTP/language.ymlbefore any parser is built (ADR-020); editinglanguageinconfig.ymlhas no effect (the key was removed). Verifylanguage.ymlis present and contains a known locale, then confirm the correspondinglang/<locale>/messages.ymlships in the jar or exists on disk. - "Teleport mid-reload crashed."
reloadConfigscancels in-flight teleports viaRTPTeleportCanceland clearsprocessingPlayersbefore the parser swap, so tasks don't straddle two parser generations. If a crash reaches the pipeline, the cancel path was skipped (custom entry point bypassingConfigs.reload). - "Dormant region never activates."
OnWorldLoadUnloadmust fireWorldLoadEvent— check that the world is actually being loaded (not just referenced), and thatRegionConfigLoader.detectFallbackConfiguredWorldreturned the correct name. - "First-enable differs from reload." There is no distinction in this code path: plugin enable calls
reloadActionthe same way/rtp reloaddoes. diagram 06 shows when that call happens during enable.
Source anchors¶
rtp-core/.../configuration/Configs.java—reload,reloadConfigs,reloadRegions,reloadAction,getWorldParser,getWorldParserValue.rtp-core/.../configuration/ConfigParser.java— single-file parser.rtp-core/.../configuration/MultiConfigParser.java— directory-of-files parser (regions, worlds).rtp-core/.../configuration/LanguageBootstrap.java— readslanguage.ymlbefore any parser is constructed (ADR-020).rtp-core/.../configuration/enums/*.java— one enum per config category; adding a key = adding an enum constant plus a default in the YAML template.rtp-core/.../selection/region/RegionConfigLoader.java—load+detectFallbackConfiguredWorld(dormant detection).