Skip to content

Architecture Decision Records

This directory contains Architecture Decision Records (ADRs) for the RTP project.

An ADR captures a significant architectural decision: the context that forced it, the decision made, the alternatives considered, and the consequences. They are numbered sequentially and never deleted — superseded records are marked as such.

Index

# Title Status
ADR-000 Development Workflow (meta: how a developer ought to work in this repo and why - full lifecycle from intake through self-maintenance, D-005 guard rail, divergence handling, optional AI tooling) Accepted
ADR-001 Archimedean Spiral 1D Mapping for Location Selection Accepted
ADR-002 H2/SQLite for Spatial Memory Persistence Over Flat-File Cache Accepted
ADR-003 rtp-plugin as a Separate Bridge Module from rtp-core Accepted
ADR-004 CountBoundTaskPipe Instead of TimeBoundTaskPipe on Folia Regional Threads Accepted
ADR-005 Removal of PaperLib in Favour of Native Paper APIs Accepted
ADR-006 Async Queue Pre-Generation Over On-Demand Async Selection Accepted
ADR-007 Per-User Isolated Queues Alongside the Global Queue Accepted (operational details superseded by ADR-043)
ADR-008 MemoryTracker as Active Task GC with WeakReference Deallocation Accepted
ADR-009 Configurable Spatial Distributions: Flat, Normal, Exponential Accepted
ADR-010 Versioned Platform Adapter Submodules Accepted
ADR-011 rtp-api as a Separately Published Addon Interface Accepted
ADR-012 ChunkReservation as an Internal Chunk Ticket Abstraction Accepted
ADR-013 Addons as External Gradle Projects Rather Than Built-In Optional Modules Accepted (partially superseded by ADR-019)
ADR-015 Stale-Chunk Guard for Count-Bound Pipes Accepted
ADR-016 Anvil Read-Only Subsystem (Prefilter, Backed Chunk View, Shared Module) Accepted
ADR-017 Block Tags and Block-State Predicates in Safety Lists Accepted
ADR-018 AGENTS.md Public Release Structure: Thin Router + Canonical Sources Accepted
ADR-019 Claim-Plugin Integrations Folded Into rtp-plugin; Example Addon Retained Accepted
ADR-020 Language Bootstrap and Locale-Aware ConfigParser Accepted
ADR-021 Legacy Minecraft and Java Support Are Out of Scope Accepted
ADR-022 Region Shape Cache Key: Seed + Canonical Config Hash Accepted
ADR-023 Login Reserve Cache for Join-Time RTP Accepted
ADR-024 RTP Lite Assembly Variant Accepted
ADR-025 Replace SimpleYaml with an Internal SnakeYAML-Backed YAML Wrapper Proposed
ADR-026 External Hook API Surface Accepted
ADR-028 L3 Backlog Cache (backlogLocations) Accepted
ADR-032 Teleport Pipeline Latency Histogram: 256-Sample Wait-Free Ring, Never Reset Proposed
ADR-034 Memory Shape Catalog and Polygon Shape Accepted
ADR-035 Interactive Menus via Written Book (Book-First, Chat Fallback) Proposed
ADR-036 Network Mode: Multi-Server, Multi-Proxy RTP Accepted (2026-05-14)
ADR-037 Harden RTP Config Commands (Prerequisite for /rtpadmin Setup Wizards) Accepted
ADR-038 /rtpadmin Setup Wizards (Book-Menu Driven, Config-Transaction Backed) Proposed
ADR-039 /rtpadmin Diagnostic Surfaces (Biome Map, Bad-Selection Heatmap, Metrics Readouts) Proposed
ADR-040 Cross-Backend Metric Time-Series Publication via MemoryTracker Tier Promotion Proposed
ADR-041 /rtp config Command and Save Mechanics: Implementation Strategy (companion to ADR-037) Proposed
ADR-043 rtp.personalqueue Permission Semantics: Bucket-Only Opt-In (supersedes operational details of ADR-007) Accepted
ADR-046 maps-api Module for Runtime Cartography Chart Generation Accepted
ADR-047 Declarative Chart Composition Bridge (ChartSpec + ChartSpecResolver + MapDispatch) Accepted
ADR-048 Move menu page builders into rtp-api behind RTPServerAccessor (four default methods + MenuPlatformView snapshot record; no new Gradle module) Proposed
ADR-049 Lift network-mode plumbing (NetworkModeBootstrap + 12 helpers) from rtp-plugin/bukkit/network/ to rtp-core; new PlayerLifecycleHook SPI on RTPServerAccessor; supersedes rtp-fabric-ADR-013 Accepted
ADR-053 Pipeline Latency Percentiles and Slow-Teleport Audit (extends ADR-032; /rtp info readout) Accepted
ADR-054 RTPRunnable Self-Scheduling Thread Routing (target/location + schedule() entity/region/async dispatch) Accepted
ADR-057 Platform-agnostic addon SPI (RTPAddon + AddonRegistry ServiceLoader discovery; replaces Bukkit JavaPlugin addon loading) Accepted
ADR-058 Region-Specific Schematic (.schem) Paste at the Arrival Location (SchematicPaster SPI + swappable per-adapter getter; load-async/paste-on-region-thread) Accepted
ADR-059 Relative Ground-Distance Safety Predicate (synthetic _groundDistance block-state property consumed by the ADR-017 numeric-range grammar; ground leaves/roots safe, tall-tree canopy unsafe) Proposed
ADR-060 Emergency-Platform Block-Restoration Timeout (safety.yml platformRestoreSeconds, -1 disables; per-coordinate diff capture; DB-persisted, chunk-loaded countdown reaper; row removed on completion) Accepted
ADR-061 Open-Core Dual Licensing (MIT for rtp-api, rtp-core, and the RTP lite binary; PolyForm Noncommercial for Pro-only source) Accepted
ADR-062 Biome-Probability Weighting for Location Selection (Anvil-sourced per-region biome occupancy map + bounded weighted draw; steering distinct from existing bad-sector avoidance) Accepted
ADR-063 Biome-First Menu with Auto-Region Selection by Biome Availability (observed-biome list from MemoryShape.getObservedBiomes(), BiomeColorSource row coloring, shared /rtp biome:<x> auto-region for CLI/menu parity, no player-controlled disk writes) Accepted
ADR-064 Config-Comment Format: Summary Line as Menu Hover Text (fixed two-part template — standalone first-line summary + prose + @type/@options/@range/@unit/@default/@source directives; canonical style guide docs/dev/CONFIG_COMMENT_STYLE.md) Accepted
ADR-065 World-Override Regions and the /rtp World Menu (shared world:<x> override builds a cached <region>_<world> region so rtp world:nether and rtp region:r world:nether actually land in the target world; adds the front-page world picker row) Accepted
ADR-066 Foreign Config Importer (rtp config import <plugin>: one-shot, non-destructive, dry-run/confirm migration aid; generic ConfigImporter seam in rtp-core reading competitor YAML via the in-house parser; BetterRTP/EzRTP/JakesRTP sources; MAPPED/APPROXIMATED/DEFERRED/DROPPED classification; SetAsRespawn/LockAfter deferred until parity lands) Accepted
ADR-067 Automatic PRESCAN, Adaptive Scan Rate Control, and .mca-Header Generation Check (three disk-/generation-neutral safety-map tiers: scheduled PRESCAN-only auto-scan that never promotes to FULLSCAN, opportunistic bounded on-load PRESCAN clipped to region boundaries, and live verification fallback; two-axis MSPT-headroom + queue-pressure per-tick budget; check-then-allocate predictive bound using per-class ChunkLoadProfile floors; Option B per-chunk generated/ungenerated read from the cached region-file sector-offset table via an anvil-api helper, reusing ScanTask's existing region-file binning; all behaviour configurable via performance.yml keys, off by default) Proposed
ADR-068 Cross-Server Persisted Teleport Limits (two orthogonal axes: durability local always-on + optional proxy durable store, file-backed YAML/JSON in lite and Redis/SQL in Pro; swappable transport reusing NetworkTransport; push-on-connect snapshot instead of poll-per-teleport; relative-duration wire format to neutralize clock skew; usage-cap persistence parity with the already-persisted cooldown; fail-open-to-local) Accepted
ADR-070 Platform-neutral /rtp command root (CoreRtpRoot) for Brigadier-bridged platforms (collapses the duplicated Fabric / NeoForge roots into thin subclasses of one rtp-core root; accessor-backed ServerAccessorCommandParameters for player/world; new default RTPServerAccessor.getOnlinePlayerNames() SPI; Bukkit root left bespoke) Accepted
ADR-071 Config Organization and Discoverability (keep split-by-concern files; virtual Teleport/Safety/Economy/... grouping in menu+docs rather than physical YAML merges; relevance ordering of keys; staged messages.yml plan: section refinement now, planned messages/-directory split later via a merge-loader that keeps the closed MessagesKeys enum + legacy flat-file fallback; read-legacy-warn-prefer-new migration on key moves; first action de-duplicates config.yml's network.redis against the authoritative network.yml) Proposed
ADR-072 Teleport View-Distance Clamp and Steady Restore (per-player delivery view distance clamped to the viewDistanceTeleport preload radius, floored at MIN_VD=2, on arrival; one new performance.yml#viewDistanceRestoreInterval total-time ramp key, default 200 ticks, 0 disables; single-chunk increments deferring to any larger concurrent view distance; platform-neutral getViewDistance/setViewDistance SPI; RTP.scheduler-driven, session-scoped, no DB persistence) Accepted
ADR-073 Config Default Inheritance via @<file> References (region/world settings may resolve to a global default owned by a named file instead of a literal; the @<file> token names the owning file so each default stays in its concern file - price -> @economy, shape/vert/cache caps/spatialResolution/world requirePermission -> @config#defaults; type-bearing shape/vert inherit as whole named blocks, type-free scalars inherit individually; shipped regions/worlds defaults use the reference; read-time fail-safe resolution with warn-on-missing/unknown-file; non-rewriting opt-in migration + version bumps; menu inherit/override toggle; extends ADR-071, builds on the ADR-034 shape catalog) Proposed
ADR-074 Operator-Facing RTP Throughput and Cost Metrics (end-to-end command latency + cost-per-valid-location reusing the ADR-032 ring; always-paired usage/refill EWMA rates over a shared named window with backlog fill %/state label to disambiguate hysteresis-driven zero refill; usage/refill ratio headline; green/amber/red color coding via the ADR-053 threshold mechanism; extends ADR-032/ADR-053) Proposed
ADR-075 Platform-Neutral Player-Move Event SPI (normalized block-granularity move signal in rtp-api, dispatched by rtp-core, implemented per adapter - Bukkit PlayerMoveEvent, Fabric/NeoForge server-tick position diff; opt-in per-player subscription so cost scales with watched players not total; enables cross-platform region confinement/tether and future move-driven features without a WorldGuard dependency) Accepted (2026-07-25)
ADR-076 Config Folder Consolidation (reduce the operator-facing top level from 12 to a small tiered surface: everyday YAMLs at root + addons/ + definitions/ grouping the MultiConfigParser sets regions/worlds/effects + one advanced/ door absorbing schematics/messages alongside the tuning YAMLs; the lang/ locale value tree stays at root, and rename-maps become co-located dotfile siblings mirroring the default tree; database/ stays at root as runtime state; supersedes ADR-071's top-level layout only, all other ADR-071 rules retained; read-legacy folder-relocation migration + version bumps) Accepted (2026-07-26)

Subproject ADRs

ADRs whose scope is confined to a single subproject (module / addon) live next to that subproject's source under <subproject>/docs/adr/ rather than in this directory. They follow the same numbering sequence and template as the project-wide ADRs above. Catalog of known subproject ADR directories:

Subproject Path ADRs
LeafRTPPartyAddon addons/LeafRTPPartyAddon/docs/adr/ leafrtp-party-addon-ADR-001 Party Teleport via Shared Prepared Destination (reuse the supply pipeline, do not search per member) (Proposed)
LeafRTPTetherAddon addons/LeafRTPTetherAddon/docs/adr/ leafrtp-tether-addon-ADR-001 Tether: Cross-Platform Region Confinement Composed From RTP Primitives (No WorldGuard Trap) (Proposed)
commands-api api/commands-api/docs/adr/ commands-api-ADR-001 Brigadier Bridge via commands-api Adapter Layer (Proposed); commands-api-ADR-002 Message-delivery seam via a MessageSink SPI (Accepted); commands-api-ADR-003 Registration seam via a CommandRegistrar (Bukkit), neutral command roots (Accepted)
effects-api api/effects-api/docs/adr/ effects-api-ADR-001 Glide Effect in effects-api (Proposed); effects-api-ADR-002 Type-Driven Adaptive Reading Order (Accepted; amended by ADR-004); effects-api-ADR-003 Platform Split Bukkit/Fabric (Accepted); effects-api-ADR-004 ValueCoercer SPI: Per-Platform Type Binding for the Adaptive Reading Order (Accepted)
rtp-fabric platforms/rtp-fabric/docs/adr/ rtp-fabric-ADR-001 Fabric Multiversion Submodule Layout (Accepted); rtp-fabric-ADR-002 Fabric Platform Is In Scope (Accepted; renumbered from ADR-022 on 2026-05-05 to resolve a numbering collision); rtp-fabric-ADR-003 Non-persistent chunk tickets via DistanceManager.addRegionTicket (Accepted); rtp-fabric-ADR-004 DistanceManager API split at MC 1.21.5 (Accepted); rtp-fabric-ADR-005 Fabric anvil pre-filter parity (Accepted); rtp-fabric-ADR-006 Chunk-ticket radius is 3, not 31 (Accepted); rtp-fabric-ADR-007 Decouple FabricVersionAdapter from Mojmap type names (Accepted); rtp-fabric-ADR-008 Non-blocking chunk generation via ServerChunkCache#getChunkFuture (Accepted); rtp-fabric-ADR-009 Obf/unobf common module split (Accepted); rtp-fabric-ADR-010 Typed block-tag snapshot via per-version SPI; reflection demoted to fallback (Accepted); rtp-fabric-ADR-011 Effective-permission enumeration on Fabric (LuckPerms-Fabric primary, registry-probe fallback; covers rtp.effect.* + rtp.onevent.* + numeric tails) (Accepted 2026-05-22); rtp-fabric-ADR-012 Menu renderer parity on Fabric (chat-first via obf/unobf carrier split; book renderer deferred; PromptAnvilInput substituted by chat-prompt callback) (Proposed 2026-05-22); rtp-fabric-ADR-013 Network-mode backend parity on Fabric (reimplementation as FabricNetworkModeBootstrap + FabricJoinTriggerSource; pulls pure-I/O helpers up to a shared utility; reuses ADR-011 resolver for reservation-token auth) (Proposed 2026-05-22); rtp-fabric-ADR-014 Early/experimental MC 26.2 pre-release adapter (rtp-fabric-v26_2_R1, cloned from v26_1_R1; deobf/JDK-25; startsWith("26.2") dispatch) (Accepted 2026-05-31); rtp-fabric-ADR-015 Maps API parity (vanilla filled-map path; FabricMapBinding + FabricVersionAdapter.renderMapChart seam, 26.2_R1 carrier) (Accepted 2026-05-31)
maps-api api/maps-api/docs/adr/ maps-api-ADR-001 Module Bootstrap, Package Layout, and Palette Policy (Accepted); maps-api-ADR-002 GUI-Slot Map Delivery and a Future Off-Main Raw-Packet Render Path (Proposed)
metrics-api api/metrics-api/docs/adr/ metrics-api-ADR-001 Module Extraction from rtp-core (Accepted)
rtp-neoforge platforms/rtp-neoforge/docs/adr/ rtp-neoforge-ADR-001 NeoForge Platform Is In Scope (Per-MC-Version Submodule Layout, Mojmap-at-Runtime) (Accepted 2026-06-01)
rtp-proxy platforms/rtp-proxy/docs/adr/ See subdirectory index. Highlights: rtp-proxy-ADR-001 SPI Shape (Proposed); rtp-proxy-ADR-002 network.yml Schema (Accepted 2026-05-14, amended 2026-05-18); rtp-proxy-ADR-003 In-Memory Binding (Proposed); rtp-proxy-ADR-004 Weighted-Average Selector (Proposed); rtp-proxy-ADR-005 Redis Binding (Accepted 2026-05-18); rtp-proxy-ADR-006 Velocity Bootstrap (Accepted 2026-05-18); rtp-proxy-ADR-007 Postgres Binding (Proposed, superseded-sketch by ADR-011); rtp-proxy-ADR-008 Bungee Bootstrap (Proposed); rtp-proxy-ADR-009 Generic SQL Binding (Proposed, superseded-sketch by ADR-011); rtp-proxy-ADR-010 Security Hardening (Accepted 2026-05-18); rtp-proxy-ADR-011 SQL Network State Binding (Accepted 2026-05-18); rtp-proxy-ADR-012 Proxy Role: Participant Default (Proposed); rtp-proxy-ADR-013 RTPProxyAccessor Registration (Proposed); rtp-proxy-ADR-014 Backend-Owned /rtp with Network Wait-Queue (L6) (Accepted 2026-05-21, supersedes rtp-proxy-ADR-006 Command Hosting); rtp-proxy-ADR-015 Shared Network Waitlist and Dynamic Batched Dispatch (Proposed 2026-05-21); rtp-proxy-ADR-016 Plugin-Message Default Transport (tier-1, non-durable, ships in lite; amends ADR-036) (Accepted 2026-06-12)

When adding a new subproject ADR, also add a row here so the global index remains a one-stop catalog.

Template

Use ADR-TEMPLATE.md when recording a new decision.