Welcome to the Hangar Open Beta. Please report any issue you encounter on GitHub!
Avatar for leaf26

Off-tick random teleport engine with spatial memory

Report LeafRTP?

R

3.3.1

[3.3.1] - 2026-10-26

Added

  • Tune background cache refill automatically from server headroom and player demand (autoTune, ADR-087, ADR-123, ADR-124). advanced/performance.yml ships autoTune: true. While players teleport and the server has spare tick time, CPU and memory, regions refill on every tick within asyncAllottedTime, syncAllottedTime and activeChunkCap instead of waiting for period. When tick time, CPU, chunk-load latency or tenured heap usage rises, or when caches are already full, background refill scales down before minTPS, maxMSPT or maxHeapPercent trips, while players waiting for a teleport keep the full configured budgets; constrained refill is shared across regions by distinct active players (ADR-124), and on Folia tick-region shares are probed per cell group and background work prefers tick regions with headroom and fewer players up to a 60 s or 8-deferral aging bound (ADR-123). /rtp info shows effective budgets, per-region refill shares and top consumers, and /rtp test includes the compute-governor check for reduced or floor-held budgets and stale metrics; setting autoTune: false uses the fixed values and refills once per period.

  • Action and Claim addons report setup health through BIT (ADR-121). /rtp test action-setup identifies rejected definitions, command or trigger registration failures, missing batch scheduling and name collisions. On Bukkit-family servers, /rtp test claim-integrations reports disabled, absent, late-enabled and incompatible claim integrations. Each addon publishes a separate code catalog and stable identity lock; first-boot severity overrides for addon codes take effect after addon registration.

  • Refuse steep landing spots (ADR-119). linear and jump verts accept two new optional keys. maxSlope is the largest floor-height step, in blocks, allowed between the landing spot and the ground slopeRadius blocks away (default 2, range 1-8) to the north, south, east and west. Spots on cliff edges or steep hillsides are skipped and the search moves on to the next spot. The check follows the floor the player would stand on, so it also works in caves and the Nether. Regions without maxSlope behave as before and keep their saved region data. Setting or changing either key rebuilds that region's saved data once. Steep worlds with a low maxSlope reject more chunks. Not available on fixed, which places players in mid-air.

  • Keep players off mountainsides and cliff edges (ADR-120). linear and jump verts accept maxHillAngle, the steepest hill in degrees a player may land on. config.yml ships it as "off" under defaults.vert, and the config menu offers "off", 30, 45 and 60; any number from 0 to 89 also works. On a 26.3 test world, 30 refused about 1 in 5 land spots, 45 about 1 in 12 and 60 about 1 in 60. RTP checks the ground 16 blocks away in 8 directions and within 8 blocks of the spot, inside the 3x3 chunks around it, using blocks only, so it works the same with custom generators such as Iris and Terra and on every platform. The check itself loads no chunks: it reads region files during the background search, then rechecks the chunks the server already holds around the spot. Only spots that pass the other checks look at their surroundings, and only at the chunks needed to decide. With the check on, the background search does about 3 times the work per spot and tries more spots, because refused spots are picked again; spots rejected after the server has read their chunk add chunk loads. "off", -1 and a missing key behave as before and keep the region's saved data.

  • Action definitions report findings and support strict registration (ADR-121). Each finding logs its stable code, source file and YAML path, allowed values, and a suggestion when available. advanced/bit.yml ships strictActions: false, which logs structural action codes as warnings and keeps loading compatible; setting it to true prevents registration of an action with any effective ERROR, while other actions continue to load, and per-code overrides take precedence. Unknown ACTION: names are omitted, unknown trigger types are skipped instead of falling back to STEP_IN, and a missing trigger type still defaults to STEP_IN; the checks use the standalone bit-api module.

  • /rtp test reports registered BIT probe results (ADR-121). The SAFE all group includes api-compat, commands, scheduler, events, economy-isolation, disconnect-job, network and safety-verifier, and can be filtered with tier= or subsystem=. /rtp test status shows registered state without rerunning checks, and json=true selects machine-readable output. Chat starts with a component-count summary, then lists only distinct FAIL, WARN and INFO findings; repeated codes are counted, while PASS and SKIP components appear only in the summary. The server log keeps the full table with paths and messages. all is distinct from the Bukkit-only full sweep; existing probe summaries remain unchanged for automation.

  • /rtp test teleport checks the teleport pipeline without a real player (ADR-121). /rtp test teleport [region=<name>] [count=1-16] [json=true] (permission rtp.test.mutating) sends temporary rtp-bit-* test players through real location selection, including real chunk loading, and reports whether the teleport was reached, any left-over teleport state, and timeouts. Test players get no cooldowns, teleport history, usage-limit counts, economy charges, landing-heatmap entries or plugin events, and never appear in online-player lists. Every report says that the final teleport was simulated. The check runs only when named, never as part of all or tier=ibit.

  • Generate a mock teleport landing heatmap (/rtp test teleport-heatmap, ADR-121). Operators with rtp.test.mutating can sample a region with bounded mock teleports and export the landing coordinates and distribution as CSV and PNG files. The probe runs only when named and does not alter the existing landing heatmap.

  • Teleport probes report mock and player results through /rtp test (ADR-121). Stress, queue-starvation, disconnect-midflight, Folia ownership and the pipeline half of async-reply now run as registered BIT components using mock players or UUIDs. Stress and async-reply retain separate player=<name> components for live platform behavior; hologram remains player-only. Component findings are included in the BIT report, and every timeout records BIT_COMPONENT_TIMEOUT while existing [RTP test/<probe>] output remains unchanged.

  • RTP reports startup check health (ADR-121). After startup, RTP runs SAFE action-definition and region-file self-tests off-thread and logs one health summary. A missing optional host Zstandard runtime is informational and leaves the component healthy because RTP can use its safe live-load fallback; a present engine that fails its canary remains degraded.

  • Action runtime health is visible in BIT status (ADR-121). /rtp test status reports missing scoreboard objectives, gates that always or never pass, unresolved placeholders, unknown ACTION: commands, and sessions that remain active beyond their reaper window. advanced/bit.yml adds gateOutcomeSamples, which defaults to 200 evaluations.

  • A bad config no longer breaks a running server on /rtp reload (ADR-121).

    • What is checked. On startup, by /rtp test subsystem=config, and before every /rtp reload, editor Hot-Apply, /rtp config edit, /rtp config import or /rtp admin setup confirm, RTP checks every config file. It reports:
      • YAML that does not parse;
      • values outside the type, allowed values or range in the shipped comments;
      • @config/@economy/@safety references that do not resolve;
      • regions, worlds, schematics and effect groups that point at something missing;
      • impossible settings such as a radius that is not larger than centerRadius or a shrinkTo larger than initialSize;
      • message files with missing keys.
    • How findings are reported. Each finding names its file and key and suggests the closest valid value. The checks read files only and never load chunks.
    • What is rejected. If a reload, Hot-Apply, config command, import or setup confirm finds an error, nothing is applied and the server keeps its current configuration. The sender is told which file and key to fix (new reloadRejected and editorApplyRejected messages, translated in every bundled language).
    • New setting: strictConfig. Problems that earlier releases accepted are logged as warnings for now, so a reload is not rejected. Set strictConfig: true in advanced/bit.yml to treat them as errors. Broken YAML and impossible settings are always errors.
  • Publish condensed metric history across backends in network mode (ADR-040). Setting metrics.networkTimeSeries.publish: true in advanced/network.yml (default false) writes completed metric buckets (tier, default 24h@1m) to the shared SQL table rtp_metric_bucket or Redis sorted sets rtp:metric:<backend_id>:<metric_key> with (sample_count, mean, min, max, p95) and the active network generation. Writes are batched (perPassWriteCap, default 64 rows per pass) and swept per backend after retentionDays (default 7 days). Cross-backend chart snapshots include the (min, max) band alongside mean. When network mode is off and publish: true, RTP logs one warning at startup and stays dormant.

  • Choose whether bare /rtp opens the destination picker (openOnBareRtp). addons/guimenu.yml adds openOnBareRtp: true (also disabled when menuStyle is "none" or "off"). Setting openOnBareRtp: false makes bare /rtp teleport immediately in the player's current world while keeping /rtp gui (rtp.gui) and /rtp menu (rtp.menu) active to open the destination picker.

  • Set the region radius and bare-/rtp menu behavior in the setup wizard (/rtp admin setup, ADR-038). /rtp admin setup adds a region outer radius step (/rtp admin setup radius <distance>, with presets 2.5km, 5km, 10km, 25km, 4096b and 500c, plus a custom distance prompt) and an openGuiOnRtp toggle on the gameplay page (addons/guimenu.yml openOnBareRtp).

Changed

  • BIT codes now have namespace-local identities (ADR-121). The stable identity is (namespace, id, key), so separate code owners with distinct prefixes can use the same number without reserving global ranges. The log table prints namespace:id, JSON includes ns while retaining schema 1 for its first release, and a committed release lock prevents renames, renumbering, reuse or unreviewed default-severity changes; retired codes remain documented. A new startup check, bit-namespaces, reports BIT_NAMESPACE_CONFLICT when two plugins reserve the same code prefix.

  • Runtime-read duration settings accept explicit units. Values such as 30s, 5m, 2h, 1d12h, 40t and 500ms work in safety.yml, advanced/performance.yml, advanced/network.yml and proxy network-proxy.yml; bare numbers retain each setting's existing unit. Invalid backend values use their documented fallback with a warning, while invalid proxy network durations reject the configuration.

  • Both jars share one version number (ADR-117). The separate liteVersion line is retired; full and Lite builds report the same version.

  • For addon developers (ADR-115, ADR-116, ADR-040, ADR-120, ADR-121). The common server bridge and platform-family enum are now available from the standalone server-api artifact in io.github.dailystruggle.server.api (RTPServerAccessor extends ServerAccessor and RTPScheduler extends TaskScheduler), and rtp-api re-exports server-api, menu-api, units-api and tags-api alongside the standalone bit-api, config-bit-api and predict-api modules (ConfigParser, MultiConfigParser, LanguageBootstrap, Factory and FactoryValue also live in yaml-api under their existing packages). Update PlatformFamily imports from io.github.dailystruggle.rtp.api.server and rebuild binaries compiled against the old enum package. Built-in effects now route through ServerAccessors (wrapEffectPlayer, wrapEffectLocation, resolveEffectPlayerAt, dispatchConsoleCommand), HandleRegistry and HandleProvider in io.github.dailystruggle.effectsapi.common.spi are deprecated (@Deprecated(forRemoval = true)) as forwarding shims over ServerAccessors, and the Bukkit effect classes (io.github.dailystruggle.effectsapi.bukkit.* and io.github.dailystruggle.effectsapi.EffectsAPI) have moved from effects-api into :rtp-bukkit:rtp-bukkit-common so effects-api carries no platform code. RTPServerAccessor provides the default Optional<Boolean> hasScoreboardObjective(String) method, RTPScheduler adds isGenerationSaturated(RTPWorld), RTPWorld adds probeChunkSquare for off-thread same-region-file square probes, and rtp-api adds @PublicApi MetricTimeSeriesPublisher and MetricBucketRow in io.github.dailystruggle.rtp.api.metrics.

Fixed

  • Moving during the /rtp warmup now cancels the teleport. Walking farther than cancelDistance during teleportDelay was ignored for /rtp, because the player's starting position was never recorded, so the teleport went ahead anyway.

  • Plain-number teleportCooldown and teleportDelay values were treated as milliseconds instead of seconds. Bare numbers such as teleportCooldown: 300 or teleportDelay: 5 were read as milliseconds after duration-unit parsing landed, and teleportDelay was skipped when all arrival chunks were already loaded. Bare numbers now mean seconds again, and the warmup runs even when no chunks need loading.

  • Per-region cooldown overrides were blocked by a longer global teleportCooldown. Naming a region with /rtp region:<name> now uses that region's cooldown override on its own, and a bare /rtp into a world's default region passes once either the global cooldown or the region's override has elapsed.

  • Walk-in trigger batchInterval waves never fired (ADR-093). The wave timer was registered before the platform scheduler was set on startup, so players waiting in a wave trigger zone were never teleported. The timer now starts when RTP enables and stops on disable.

  • Countdown boss bars stayed on screen after a cancelled teleport. Cancelling a teleport with /rtp cancel or by moving during warmup left the countdown addon's queue or warmup bar running until it reached zero. Both bars are now cleared immediately on cancel.

  • minePlots claim check now detects plots. With rerollMinePlots: true, the check never found a plot, so players could land inside minePlots plots. It looked minePlots up under the wrong plugin name and guessed at its classes. It is now built against minePlots' published API (plugin-api 4.6.2, PlotServiceApi.getPlot from the Bukkit ServicesManager) instead of looking classes up by name, and rejects the spot if minePlots is enabled but that service is missing or the lookup fails. It is tested against the published API, not yet on a live minePlots server, so treat it as best effort.

  • UltimateClaims, PlotSquared, HuskClaims and KingdomsX claim checks fixed. UltimateClaims claims were never found: the check called a lookup UltimateClaims does not have, and could load a chunk off the main thread. On PlotSquared worlds every unclaimed plot was rejected; now owned plots and roads are rejected and unclaimed plots are allowed. The HuskClaims and KingdomsX checks could pick the wrong method depending on the server and then reject everything or nothing. Residence, CrashClaim, HuskTowns, SaberFactions/FactionsUUID and FactionsBridge were checked against their plugins' source and now look methods up by exact signature. These checks are tested against copies of each plugin's API, not on live servers, so treat them as best effort.

  • Claim checks no longer switch themselves off (ADR-118). If a claim plugin is enabled but its API doesn't match what the claim addon expects, every destination is now rejected and one error is logged, instead of the integration turning off and letting players land in claims. Update the claim plugin or the addon, or turn the integration's integrations.yml flag off, to resume teleports.

  • A deleted Rift demo group no longer comes back after a restart. The Rift addon wrote its demo group to the old effects/ folder, and every start moved that copy into definitions/effects/, so deleting definitions/effects/rift.yml while the server was stopped brought it back on the next start, even with the addon removed. The addon now writes definitions/effects/rift.yml directly and deletes an unedited effects/rift.yml left by an earlier version.

  • The Rift effect no longer cancels /rtp or buries the player. The fall into the rift counted as moving and tripped cancelDistance, so every delayed /rtp with RIFT cancelled itself. While the rift is open, only sideways movement now counts, so walking away still cancels. When the rift closes, a player still inside it (teleport cancelled, or the rift's seconds shorter than teleportDelay) is put back on the block they stood on instead of being left inside the restored terrain.

  • Built-in effects that were missing on some platforms are now registered there. TITLE now works on Paper, Spigot and Folia. GLIDE now works on Fabric 26.x and NeoForge. DROP_INVENTORY and DROP_EXP / DROP_EXPERIENCE now work on NeoForge. Before, these tokens were skipped without a message. FIREWORK and NOTE are still Bukkit-family only.

  • GLIDE on Fabric no longer drops the player. Without an elytra the game ended the glide on the next tick, so the player was lifted and then fell, taking fall damage. The glide is now kept going until the player lands, and LANDINGTIMEOUT still forces a landing. Fabric and NeoForge don't yet place players who are still gliding when the server stops.

  • TITLE shows the configured text. Text arguments were replaced by their empty defaults while the effect was built, so TITLE.<title>.<subtitle> showed a blank title on every platform. The same applied to text arguments of addon effects.

  • /rtp config language only tab-completed 5 of the 12 bundled locales. It now suggests all 12 (en, de, es, fr, it, ja, ko, nl, pl, pt, ru, zh).

  • RECTANGLE regions with rotation: 90 mapped locations to the wrong coordinates, and setBiomeGetter overrides on Fabric and NeoForge were ignored. Rotated rectangles now round-trip coordinates and heights, and biome checks on Fabric and NeoForge read the registered setBiomeGetter override first.

  • Background cache fill on NeoForge 1.21.1 could stall player joins. Login-cache promotions and startup ticket re-validation could start unbounded chunk generations at once, and non-hill chunk tickets held a 3x3 radius instead of a single chunk. Generation-causing loads now share a bounded budget, and single-chunk tickets use radius 0 unless maxHillAngle needs the 3x3 square.

Information

Published
October 27, 2026
Author
4Downloads

Platforms

Paper
Paper
1.18–26.3
Velocity
Velocity
3.3–4.3.0

Dependencies

PaperPaper

Dependencies: Paper

Plugins and libraries a server needs for this version to run.

No dependencies

Add anything a server has to install alongside this version.