Per-world view and simulation distance, adjusted automatically from MSPT and chunk load.
ViewDistanceTweaks v2.9.1-BETA
Dynamic view distance and simulation distance adjustment per world, driven by what your server can actually carry at that moment.
Bugfix release for the 2.9.0 subsystems. If you run 2.9.0-BETA or 2.9.0-BETA2 with predictive pre-loading or idle pre-generation enabled, update. Two of these can take the plugin, or a long pre-generation run, out entirely.
Fixed
Predictive pre-loading could stop the whole engine. A
Locationholds only a weak reference to its world, and reading that world back throws once the reference is cleared. The pre-loader read it off the sample it had stored for each player, so any player whose last-known world had since been unloaded — a minigame arena, a plot world — threw out of the tick handler and took everything after it with it: temporary override expiry, per-player overrides and every world check, on every tick, for the rest of the session. The only sign was a stack trace.forgetWorld()was written for exactly this case but clears the engine's per-world maps, and this one is keyed by player.A failed chunk request deleted an entire pre-generation run. Any error from the async chunk request called
cancel(), andcancel()deletes the progress file outright — hours of generation on a large radius, gone, with a log line blaming the server jar whatever the real cause had been. Folia is the likely trigger, sincegetChunkAtAsynccan refuse a call issued from the global region scheduler and that is where this runs. It now stops and keeps the progress, so/vdt pregen resumepicks the run back up.adjustment-mode: offplusstartup-gracepinned distances permanently. Grace forces distances down and relies on the normal check cycle to raise them again; underoffthat cycle returns before it computes anything, so nothing ever did. A server running both stayed at the grace values for the rest of its uptime. Grace is part of distance management, sooffnow skips it and says so in the log.A diagonal flight paid for the same chunk twice. Rounding a normalised movement vector lands consecutive steps on one chunk for any path that is not axis-aligned, and the duplicate could not be caught by the "already loaded" check because the first request had not completed yet. At 45° roughly a quarter of the lookahead budget went on chunks that were already on their way.
One refused chunk request no longer disables pre-loading for the session. That branch is now reserved for a genuinely missing API; anything else drops the current path and tries again next cycle.
Under the hood
The pre-loader's path has tests now. Both fail against the previous code: the diagonal case requested eight chunks for six distinct ones, and the unload case requested eight chunks for a world the server no longer had. That is the gap the earlier suite left — it drove pure arithmetic, and neither of these appears until the real method runs against a world.
Dependencies
- Paper 1.21.x / 26.x — required
- PlaceholderAPI — optional
- EssentialsX — optional, only for AFK detection
Support
Join our Discord: dc.gg/paperstream
Author: LucasTHCR