[3.1.0] - 2026-05-31
Added
- German (
de) locale shipped across all config/message files; full locale parity maintained. - Region-specific schematic paste platforms (ADR-058) with new
PasteOptionsAPI andRegionVerifierRegistryfootprint claim checks (S-003). New prefabs updated to use it (skyblock,oneblock,high-performance,multi-world). - Pluggable bare-
/rtproot action (ADR-056, REQ-API-F-006). NewRootActionRegistrySPI (RTPAPI.hooks().rootAction()) lets an addon take over a bare/rtp(e.g. open a GUI menu) instead of teleporting; subcommands are never routed through it. Shipped with an example menu addon. - Platform-agnostic addon SPI (ADR-057). New
RTPAddonlifecycle interface +AddonRegistry(RTP.addons, ServiceLoader-based) so an addon jar runs unchanged on Bukkit/Paper/Folia, Fabric, and proxy JVMs.RTP_ExampleAddonported with zeroorg.bukkit.*imports. - Optional PvP / combat-tag gate (ADR-055). Off by default (
safety.yml#pvpCheckEnabled=false). When enabled,/rtpis refused for a player currently in combat, using either a boundPvPCombatStateRegistryprovider (combat-tag plugins such as PvPManager / SimpleCombatLog / CombatLogX) or RTP's built-in native damage tracker. The native tracker is now fed on every supported platform: Bukkit/Paper/Folia via anEntityDamageByEntityEventlistener and Fabric viaServerLivingEntityEvents.AFTER_DAMAGE(both resolve the projectile shooter / primed-TNT igniter as the aggressor and stamp victim/aggressor perpvpTagVictim/pvpTagAggressor). The gate is consulted at the/rtppre-dispatch surface before the player is enrolled, fails open (a broken external provider never blocks a teleport), audits every refusal at WARNING (REQ-RTP-S-004), and uses the new configurablemessages.yml#pvpInCombatstring (REQ-RTP-F-013). Sixsafety.ymlknobs:pvpCheckEnabled,pvpCombatTagSeconds,pvpOnCombat,pvpSource,pvpTagVictim,pvpTagAggressor. - Bundled combat-tag plugin integrations for the PvP gate (ADR-055). New reflection-based soft-depend adapters for PvPManager, CombatLogX, and Simple Combat Log (
rtp-plugin/.../softdepends/pvp/);PvPIntegrations.setupbinds the first enabled plugin (priority PvPManager, then CombatLogX, then Simple Combat Log) toPvPCombatStateRegistryviaRTPAPI.hooks().pvpCombatState(), gated onisPluginEnabled(...)like the claim integrations. When none is installed (orpvpSource: NATIVE), the native combat tracker answers; a reflective/API-version failure disables the adapter for the session and treats the player as not-in-combat (REQ-RTP-S-004). Wired in both the full and rtp-lite bootstraps. Covered byPvPCombatAdapterTest. uniquePlacementsis now an integer chunk radius (was boolean; defaults to0= off).N >= 1clears a(2N-1)x(2N-1)chunk square around each used spot so placements spread out; legacytrue/falsestill coerce to1/0. Retired spots tagged with a dedicateduniquePlacementfail cause.- Config getters tolerate boolean<->int cross-typing, so a legacy
true/falseon a now-numeric knob (or0/1on a boolean knob) resolves instead of throwing. - Optional emergency-platform block-restoration timeout (ADR-060). New
safety.ymlknobplatformRestoreSeconds(-1= disabled default;0= restore on first loaded pulse;> 0= after that many seconds). Restores are chunk-load-aware (never force-loads, S-005), Folia-safe, and persisted across restarts. /rtp infonow surfaces generation outcomes (REQ-RTP-OBS-007, ADR-052): success/failure rate and a per-cause rejection breakdown, via six new placeholders and threemessages.ymllines.- Live-updating bad-locations map during a world scan: the admin "Region shape" chart now re-renders ~1 Hz from the in-memory bad-keys cache so scan progress is visible without re-issuing the command.
- New bStats charts:
language_selection, MSPT-p99 by platform/game-version/plugin-version, and aggregate generation-outcome (success rate + top failure cause). All privacy-safe (bucketised / whitelisted categories). /rtp clearcacheadmin command (permissionrtp.admin). Clears the L1 (kept), L2 (unkept), and L3 (backlog) location caches for every region across the board in one shot, releasing any held chunk reservations and dropping the associated persisted rows; the scan/queue machinery refills the caches afterwards. Backed by a newRegionQueueManager.clearCaches().rtp.adminpermission node declared inplugin.yml(both full and lite), gating/rtp clearcacheand grouping the existing admin tooling permissions (rtp.reload,rtp.config,rtp.scan,rtp.info) as children so a single grant covers all admin commands.- (Pro) Numeric range predicates in the safety-list grammar (ADR-017 amendment).
safety.yml::unsafeBlocks/airBlocksnow accept block-state comparisons (LAVA[level<=3],FIRE[age>=10],*[level>=8]); multiple bounds AND together. rtp-lite ignores tag/predicate tokens.
Changed
- Region biome visualization now sources its pixels from saved region biome data only.
RegionBiomesResolverno longer reads on-disk.mcapalettes viaRTPWorld.readBiomesInRegionFile; it classifies each in-disk pixel through the newMemoryShape.biomeAt(int, int)/biomeAt(long), a floor-search over the persistedbiomeKeysCache/biomePrefixSumsCacheaccumulated by the scan pipeline (no chunk I/O, S-005-clean). Pixels with no recorded biome render as unsampled (BLACK), so the chart reflects what the scan has actually saved for the region.
transferring from spigotmc resource https://www.spigotmc.org/resources/rtp.94812/
runs on paper and fabric, a few things left to implement on the fabric side of things but the core functionality works.

