COWMODSКаталог модов

ViewDistanceTweaks

Automatically adjusts view and simulation distance per world to match what your server can handle - more distance when there is headroom, less before players notice lag.

7,9 тыс.14обновлён 24 окт. 2026 г.
УправлениеОптимизацияУтилиты

Описание

Discord Release Downloads Servers License

Built with Java 21 Available for Paper Available for Purpur Available for Folia

Watch us on Youtube Chat with us on Discord Available on Codeberg

bStats

ViewDistanceTweaks

Sets view and simulation distance per world, on its own, based on what the server can handle at that moment.


The number in server.properties has to be safe enough for your worst minute, which means it's too low for every other minute. Ten people on at 3am and you're saving distance nobody asked you to save. Sixty people at an event and that same number is why the TPS meter is on the floor.

This moves it for you. It watches MSPT and how many chunks are actually loaded, gives distance back while there's headroom, and takes it away before players notice. Each world has its own floor and ceiling, so the Nether can sit at 6 while your main world runs at 16.

Drop the jar in and restart. The defaults do something sensible without any setup.


Requirements

  • Paper 1.21.x / 26.x or a fork (Purpur, Pufferfish, Leaves)
  • Folia works, tested on 1.21.11
  • PlaceholderAPI - optional, only if you want the placeholders
  • EssentialsX - optional, only to read AFK state if you turn AFK throttling on

Spigot and Bukkit are not supported: their API can read view and simulation distance but not change it, and changing it is what this plugin does.


How it decides

MSPT is sampled every tick. Every ticks-per-check (10 seconds by default) each world is looked at once and the answer is up, down, or leave it alone.

Four modes:

  • proactive - you give it a chunk budget (how many ticking and non-ticking chunks the server should carry in total) and it solves for the distance that fits
  • reactive - ignores chunk counts, just watches MSPT against two thresholds
  • mixed - runs both and takes whichever is more pessimistic. Right answer for most servers, and the default
  • off - never touches view or simulation distance. For servers that only want the pre-generation and pre-loading parts

On top of the mode itself:

It won't repeat an increase that already hurt. A linear regression over the last 30 minutes of chunk-count/MSPT pairs predicts what the next step up would cost. If that lands above the decrease threshold, the increase doesn't happen. That's what breaks the usual raise-lag-drop-raise loop.

It watches the spread, not just the average. A server can average a comfortable 30ms while single ticks bounce between 8 and 55, and nobody enjoys playing on that. Standard deviation across Paper's last 100 tick samples catches it, so above variance-threshold the server counts as overloaded even though the average looked fine.

Down can be faster than up. max-increase-step and max-decrease-step are separate. 1 and 4 is a common pair: climb one notch at a time, bail out in one go. revert-increase-if-overloaded also re-checks right after an increase and rolls it straight back if it hurt.

Simulation first, view second. With prioritize-simulation-distance on, view distance isn't touched until simulation distance is already at the world minimum. Simulation is the one that costs TPS, view is the one players see, so spend the cheap one first.

It can tell your worlds apart. The server publishes one MSPT figure for everything, so a single world melting down drags every other world's distance down with it - the quiet ones get punished for their neighbour. With per-world-mspt on, the tick is split between worlds and each is judged by the part it actually causes. Off by default; see below.


Per-world MSPT

One number for the whole server is the wrong shape for a per-world decision. If your nether farm is eating 30ms, the overworld didn't do anything wrong, and shrinking it doesn't help.

Turn on per-world-mspt.enabled and each world is judged by its own share of the tick instead:

fair share    = 1 / number of worlds with players
attribution   = this world's share / fair share      (clamped, 0.5x to 2.0x by default)
judged at     = server MSPT x attribution

So a world pulling exactly its weight is judged by the plain server figure, unchanged. A world pulling twice its weight is judged at twice the figure and shrinks first; a quiet one is judged at less and is left alone, or keeps growing while its neighbour gives ground.

Your thresholds keep meaning what they meant. This scales the figure the existing decrease-mspt-threshold is compared against - it does not replace it with a smaller per-world number. Nothing needs re-tuning, and on a single-world server the feature changes nothing at all.

Where the numbers come from depends on the platform:

  • Paper (and forks like Purpur) estimates. There's no per-world timing to read, so the tick is split by what each world made the server walk - entities, tickable block entities, loaded chunks. Reliable for ranking worlds; it will misjudge a world that's cheap by volume and expensive by content, like a few hundred hoppers feeding each other.
  • Folia measures region tick times directly, and that turns out to mean per-world MSPT does nothing there by default. A region that keeps up reports the tick rate itself, so every world reads the same and there is no split to act on; the figure only becomes informative once a region falls behind. Set prefer-exact-source: false to run the estimating proxy on Folia instead, which does tell worlds apart. A laggy region with no players near it isn't probed either way.

/vdt mspt shows the breakdown, which world is worst, and whether each figure is measured or estimated. /vdt simulate says so in its reason line when a world is being judged by an adjusted figure.

If the measurement is unavailable for any reason - still warming up, or the library failed to start - every world falls back to the plain server-wide figure, which is what the plugin did before this existed.


Placeholders

With PlaceholderAPI installed, everything the plugin knows is available on a scoreboard or in a chat format. The identifier is viewdistancetweaks - not vdt, which is the first thing everybody tries.

Server-wide

PlaceholderGives
%viewdistancetweaks_mspt%current MSPT, two decimals
%viewdistancetweaks_tps%current TPS, capped at 20
%viewdistancetweaks_mspt_stddev%how much recent ticks vary
%viewdistancetweaks_mode%the active adjustment mode
%viewdistancetweaks_enabled%whether the plugin is managing distances
%viewdistancetweaks_mspt_color%&a/&e/&c against your own thresholds
%viewdistancetweaks_tps_color%same idea for TPS
%viewdistancetweaks_mspt_stddev_color%same idea for the spread
%viewdistancetweaks_chunk_count%loaded chunks across every world
%viewdistancetweaks_ticking_chunk_count%ticking chunks across every world
%viewdistancetweaks_nonticking_chunk_count%non-ticking chunks across every world

Per world. Append the world name - %viewdistancetweaks_view_distance_world_nether%. Without a name, the server's first world is used.

PlaceholderGives
%viewdistancetweaks_sim_distance_<world>%current simulation distance
%viewdistancetweaks_view_distance_<world>%current view distance
%viewdistancetweaks_min_sim_distance_<world>%configured minimum
%viewdistancetweaks_max_sim_distance_<world>%configured maximum
%viewdistancetweaks_min_view_distance_<world>%configured minimum
%viewdistancetweaks_max_view_distance_<world>%configured maximum
%viewdistancetweaks_chunk_count_<world>%loaded chunks in that world
%viewdistancetweaks_ticking_chunk_count_<world>%ticking chunks in that world
%viewdistancetweaks_nonticking_chunk_count_<world>%non-ticking chunks in that world
%viewdistancetweaks_chunk_weight_<world>%configured chunk weight

Per-world MSPT. These need per-world-mspt switched on; without it they fall back to the server-wide figure or report that the feature is off, rather than failing.

PlaceholderGives
%viewdistancetweaks_worst_world%the world carrying the most of the tick
%viewdistancetweaks_worst_world_mspt%what that world costs, in ms
%viewdistancetweaks_world_mspt_<world>%that world's own contribution in ms
%viewdistancetweaks_world_mspt_share_<world>%its share of the tick, 0-100
%viewdistancetweaks_per_world_mspt_state%where the numbers come from, or why there are none

An unknown world reads as unknown rather than as a zero, so a typo in a scoreboard is visible instead of looking like a healthy server.


Safety nets

MSPT isn't the only thing worth reacting to. Everything here except the memory and chunk generation safeguards is off by default.

  • Memory safeguard - free heap under min-free-percent blocks any increase, whatever MSPT says. A server can idle at 20ms and still be one ring of chunks away from spending every tick in GC. On by default at 15%.
  • Chunk generation safeguard - counts chunks genuinely being generated, not ones read off disk. Past a per-second rate (8 by default) it stops increases and clamps view distance to 8 until generation calms down. This is the someone-just-flew-an-elytra-into-fresh-terrain case. On by default since 2.14, after a benchmark showed the distance climbing while single ticks on fresh terrain took over a second.
  • AFK throttling - a player standing at spawn doesn't need 16 chunks. Their personal distances drop to the AFK values and what they free up goes back into the budget. Uses EssentialsX AFK state if it's installed so /afk counts immediately, otherwise Paper's idle timer.
  • Ping throttling - same idea, triggered by a bad connection instead of an idle one. A player whose ping stays above the threshold for a few checks in a row gets reduced personal distances too, so their packets stop queuing and everyone else's budget stops paying for it. If both throttles apply, the more restrictive distance wins.
  • Density scaling - twenty players at one farm load nearly the same chunks, but the proactive formula assumes twenty separate rings and starves the world for nothing. When enough players sit close together the world gets bonus distance, scaled by how much of its population is in that group.
  • Complexity weighting - an ocean chunk is free, a chunk with a 500-hopper sorter can eat a tick by itself, and (2d+1)² counts both as one. Samples a bounded number of chunks around players and derives an average multiplier, so a redstone-heavy world gets a smaller budget than one full of water.
  • Emergency relief - last resort. World is at minimum sim and view, MSPT is still over the line, nothing left to take. So it sheds thunderstorms and the daylight cycle instead. Both come back when MSPT recovers, on /vdt disable, and on shutdown. The world's original weather and gamerule state are remembered on the way in.
  • Client view distance cap - nobody sees further than their own client draws. If the highest setting among a world's players is 8, a server view distance of 16 pays for rings of chunks nobody receives. With client-view-distance-cap on, a world is capped at the highest reported client value plus a small headroom, never below its minimum. Off by default.
  • Conflict detection - if another plugin keeps overwriting a world's distances, the two would fight forever. After a few cycles of that, ViewDistanceTweaks stops managing that world, says so once in the console, and names the installed plugins that could be doing it. /vdt doctor shows it too. A manual /vdt viewdistance on that world takes it back.
  • Startup grace - holds a low distance for the first few minutes after a restart. Keeps a cold server from getting hit at max distance while it's still finding its feet.

Per-player distances

Two permission families set a distance for one player without touching the world:

viewdistancetweaks.fixed.<n>      view distance
viewdistancetweaks.simfixed.<n>   simulation distance

Values 2 to 32, highest wins if someone holds several, and taking the permission away hands them back to the world value without a relog. Both have to be switched on in the config first. They need different prefixes, otherwise one node would set both at once.

The view distance one is client-side and costs the server nothing. The simulation one genuinely does cost, so keep it for staff instead of selling it as a donor perk.

/vdt status --fixed shows who currently holds what, and whether it came from a permission, the AFK throttle or the ping throttle.


Presets and profiles

Two different things with annoyingly similar names, sorry about that.

/vdt preset <small-server|large-network|performance-first> writes into your config.yml. It's a starting point if you don't want to tune forty values by hand, not a final answer.

/vdt profile <name> lays a temporary overlay over whatever is configured, defined under profiles: in the config. Nothing is written to disk and normal puts it all back. It's there so you can move to event settings for two hours without editing config.yml in the middle of an event. max-view-distance-cap and max-simulation-distance-cap are hard ceilings applied after every other rule, so a cap of 8 really is 8.


Pre-generating terrain

Generating a chunk is the most expensive thing a server does, and the one everything else here can only react to. Building the terrain in advance removes the cause: what already exists gets read from disk, which is cheap, and the chunk-generation safeguard never has to trip.

Turn on idle-pregeneration and it runs whenever the last player logs off, pausing the moment somebody joins. Or drive it yourself:

/vdt pregen start world 500              centred on the world spawn
/vdt pregen start world 500 --here       centred on where you're standing
/vdt pregen schedule world 500 04:00     start daily at 4 AM server time, even with players on
/vdt pregen schedule cancel              drop the scheduled run
/vdt pregen status                       progress, rate and ETA
/vdt pregen stop                         pause for good, progress kept
/vdt pregen cancel --confirm             throw the progress away

schedule is for a maintenance window rather than an empty server: the START trigger switches from "whenever it's empty" to "at this clock time," but the run itself still answers to pause-above-mspt, min-free-memory-percent and pause-when-players-online once it's going, same as any other automatic run. It recurs daily until cancelled, and - like other command-driven state in this plugin - is not written to config.yml, so it needs re-arming after a restart.

Three things keep it from becoming the problem it solves. It throttles against the same rolling MSPT average the distance engine uses, so the two never disagree about whether the server is busy. It stops rather than slows when free heap runs low, because a slower path to an OutOfMemoryError is still an OutOfMemoryError. And it writes progress to disk, so a crash or a nightly reboot picks up where it left off.

It also excludes its own chunks from the chunk-generation safeguard. Without that, starting a run would make the plugin think players were outrunning the generator and clamp everyone's view distance. The plugin fighting itself.

Watch the radius. The workload is (2*radius+1)², so 250 is about 251,000 chunks and 1000 is over four million. If a world border is set, a radius that would reach past it is clamped down automatically (respect-world-border in config, on by default) - so entering something too big costs a log line, not four million wasted chunks nobody inside the border can reach.


Predictive pre-loading

Loads chunks along the path of a fast-moving player so arriving somewhere doesn't stall the tick.

Worth being clear about what this is: it makes chunks ready server-side. Nobody sees further, because the client still only receives what its own view distance covers. What you notice is the absence of a hitch, not a wider horizon.

It follows the movement vector rather than where the player is looking. During elytra flight the view swings around constantly while the flight path stays straight, and it's the path that decides which chunks the server will need. Look direction can be blended in at half weight, but it's off by default.

Generation is off by default too and should stay that way. With it on, this stops being a loader and becomes a second, uncontrolled terrain generator driven by whoever is flying fastest, which is the exact load spike the rest of the plugin exists to contain. Unexplored terrain is what pre-generation is for.


Configuration

Click to expand the full config.yml
# ============================================================
#   ViewDistanceTweaks - LucasTHCR Edition
#   Compatible with Paper 1.21.* - 26.*+
# ============================================================

# Plugin version - DO NOT CHANGE
version: 4

# Master switch. The plugin manages sim/view distance out of the box with the
# defaults below; set this to false if you want to configure everything first
# (or use /vdt disable in-game).
enabled: true

# ============================================================
#   UPDATES
# ============================================================
# Tell you when a newer release exists? One async request on startup, it never
# blocks the server, and nothing is downloaded. Turn it off if the machine has
# no outbound internet access. /vdt update always checks on demand regardless.
# (This was called update-checker before 2.8.3; the old name still works.)
update-notify: true

# Installs new releases on its own. OFF by default, you decide each update.
# Set enabled to true if you would rather not think about it again.
#
# This only ever touches ViewDistanceTweaks. No other plugin is looked at, let
# alone replaced: the only file it can write is named after this plugin's own
# jar.
#
# The running jar is never modified. The download goes into Bukkit's update
# folder (plugins/update/ by default, see update-folder in bukkit.yml) and the
# server installs it on the next START. So: downloaded now, active after your
# next restart. No plugin can safely swap its own jar underneath a running
# server, and this one does not pretend otherwise.
#
# Before anything is written, the download is verified against the SHA-512 hash
# Modrinth publishes for that file. On a mismatch it is discarded, not installed.
#
# Needs update-notify above to stay true, since this acts on its result.
# You can always fetch an update on demand with /vdt update download, whatever
# this is set to.
auto-update:
  enabled: false

  # Only accept releases that list the Minecraft version this server runs.
  # Leaving this true is strongly recommended. false lets the plugin install a
  # build that was never tested against your server version.
  require-matching-game-version: true

  # Which Modrinth release channels may be installed: release, beta, alpha.
  # Add "beta" if you want fixes early and accept the risk that comes with it.
  accepted-release-types:
    - release

# ============================================================
#   IDLE PRE-GENERATION (optional, off by default)
# ============================================================
# Builds terrain ahead of time, so players never wait for it. Generating a chunk
# is the most expensive thing a server does and the one this plugin can otherwise
# only react to. Terrain that already exists is read from disk instead, which is
# cheap, and the chunk-generation safeguard never has to trip at all.
#
# Three rules keep it from becoming the problem it is meant to solve:
#   * It throttles against the same rolling MSPT average the distance engine uses,
#     not an instant reading, so the two never disagree about whether the server
#     is busy.
#   * It STOPS on low memory rather than slowing down. A slower path to an
#     OutOfMemoryError is still an OutOfMemoryError.
#   * It writes progress to disk, so a crash or a nightly reboot resumes exactly
#     where it left off instead of silently losing hours of work.
#
# It also excludes its own chunks from the chunk-generation safeguard. Without
# that, starting a run would make the plugin think players were outrunning the
# generator and clamp everyone's view distance.
idle-pregeneration:
  enabled: false

  # Start automatically once the last player logs off. Set "world" to the world
  # you want built out; leave it empty and nothing starts on its own, but
  # /vdt pregen still works. For a fixed clock time instead of "whenever it's
  # empty", use /vdt pregen schedule <world> <radius> <HH:mm> - see /vdt pregen.
  start-when-empty: true
  world: ""
  # Radius around the world spawn, in chunks. 250 chunks is a 4000-block radius.
  # Mind the squaring: the workload is (2*radius+1)^2 chunks, so 250 is about
  # 251,000 chunks and 1000 is over four million. Match this to your world border
  # rather than picking a round number.
  radius: 250

  # Refuses any /vdt pregen start above this, so a mistyped radius cannot queue
  # a run that would take weeks.
  max-radius: 5000

  # How many chunk requests may be in flight at once, and how many ticks to wait
  # between batches. Higher = faster and heavier. The defaults are deliberately
  # gentle; raise them on a machine with headroom.
  chunks-per-batch: 4
  tick-interval: 5

  # Pause while the server is above this MSPT. Well below decrease-mspt-threshold
  # on purpose: pre-generation is optional work and should yield long before the
  # distance engine has to start defending TPS.
  pause-above-mspt: 35.0

  # Stop entirely while free heap is under this percentage. Higher than
  # memory-safeguard's own floor because mass generation allocates far faster
  # than a distance increase does.
  min-free-memory-percent: 30.0

  # Pause an AUTOMATIC run as soon as anyone logs in, and continue when the server
  # empties again.
  #
  # This does not apply to a run started with /vdt pregen: somebody who typed the
  # command while standing in the world is not asking to be told to log off first.
  # Manual runs stay throttled by pause-above-mspt and min-free-memory-percent, so
  # they still cannot run the server into the ground.
  pause-when-players-online: true

  # Clamp the radius to whatever the world border still allows around the chosen
  # centre, instead of generating chunks nobody inside the border can reach. Only
  # matters once a border smaller than the default (60,000,000 blocks) is set;
  # turn this off if you plan to widen the border later and want the terrain
  # ready ahead of time.
  respect-world-border: true

# ============================================================
#   PREDICTIVE PRE-LOADING (optional, off by default)
# ============================================================
# Loads chunks along the path of a fast-moving player, so arriving somewhere does
# not stall the tick.
#
# To be clear about what this is: it makes chunks ready SERVER-side. It does not
# let anyone see further. The client still receives only what its own view
# distance covers. The visible result is the absence of a hitch, not a wider
# horizon.
#
# Prediction follows the movement vector, not the look direction. During elytra
# flight the view swings around constantly while the flight path stays straight,
# and it is the path that decides which chunks the server will need.
predictive-preloading:
  enabled: false

  # Ticks between passes, and the speed a player must sustain to qualify.
  # 0.8 blocks per tick is roughly sprint speed; elytra flight is far above it.
  tick-interval: 10
  min-speed-blocks-per-tick: 0.8

  # How far along the path to look, and the cap on chunk requests per pass across
  # all players together.
  lookahead-chunks: 4
  max-chunks-per-cycle: 8

  # Skip a pass while the server is above this MSPT. Pre-loading is a comfort
  # feature and must be the first thing to go under pressure.
  pause-above-mspt: 40.0

  # Mix the look direction into the prediction at half weight. Helps when players
  # are about to turn, adds noise during sustained travel. Off by default.
  blend-look-direction: false

  # Allow pre-loading to GENERATE terrain that does not exist yet.
  # Leave this false. With it on, this stops being a loader and becomes a second,
  # uncontrolled generator driven by whoever is flying fastest, the exact load
  # spike the rest of the plugin exists to contain. Use idle-pregeneration for
  # unexplored terrain instead.
  allow-generation: false

# ============================================================
#   ADJUSTMENT
# ============================================================
# Adjustment mode:
#   proactive - Adjusts distances before performance suffers
#               (based on chunk count targets)
#   reactive  - Reacts to MSPT changes
#   mixed     - Combines both; prioritises reduction when overloaded (recommended)
#   off       - Disables automatic sim/view distance management entirely. Sim/view
#               distance is left exactly as-is; only /vdt simulationdistance|viewdistance
#               (temporary overrides) can still change it. Everything else keeps working
#               independently: idle pre-generation, predictive pre-loading, AFK
#               throttling, per-player fixed distances, MSPT tracking. Use this if you
#               only want the pre-generation/pre-loading subsystems and nothing else.
adjustment-mode: mixed

# How many ticks after plugin start should be waited before the first check runs?
# 2400 = 2 minutes, useful to let the server stabilise after a restart.
start-delay: 2400

# How many ticks between checks for whether distances need to be adjusted?
# 200 = every 10 seconds. A short interval mostly buys a faster decrease:
# growing is still held back by passed-checks-for-increase below.
ticks-per-check: 200

# How many consecutive checks must confirm an increase before it is applied?
#
# This is the main brake on how fast distances recover. With ticks-per-check at
# 200 (10s), each confirmation costs ten seconds before anything grows, and it
# resets on any check that is not healthy.
#
# 9 confirmations and max-increase-step 2 means roughly +2 chunks every 90
# seconds, so a world walks 4 -> 16 in about nine minutes of good health.
# If you change ticks-per-check, scale this with it to keep the same pace.
# Earlier versions shipped 10 here with a step of 1, which is five minutes per
# single chunk and an hour for that same climb - safe, but slow enough that
# admins reasonably thought the plugin had stopped working.
#
# Raise it if your MSPT is spiky and you would rather be sure before growing;
# lower it only if you also trust mspt-prediction and revert-increase to catch
# a bad decision.
passed-checks-for-increase: 9

# How many consecutive checks must confirm a decrease?
# 1 = immediate reaction when overloaded (recommended)
passed-checks-for-decrease: 1

# Should a line be logged to the console when distances are changed?
log-changes: true

# Should a message be sent to players with the permission viewdistancetweaks.notify?
# Useful for admins who want to follow changes live.
announce-changes-in-chat: false

# Format of the announce message. Placeholders:
#   {world}   - world name
#   {oldSim}  - old simulation distance
#   {newSim}  - new simulation distance
#   {oldView} - old view distance
#   {newView} - new view distance
# Colours with & are supported.
announce-format: "&7[VDT] &f{world}: Sim &e{oldSim}&7→&a{newSim} &f| View &e{oldView}&7→&a{newView}"

# ============================================================
#   PROACTIVE MODE
# ============================================================
proactive-mode-settings:

  # Maximum number of ticking chunks globally (across all worlds).
  # Formula: (2*sim+1)^2 * number of players
  # Example: 20 players, Sim 8 -> (17)^2 * 20 = 5780
  global-ticking-chunk-count-target: 5780

  # Maximum number of non-ticking chunks globally (View minus Sim).
  # Formula: ((2*view+1)^2 - (2*sim+1)^2) * number of players
  # Example: 20 players, View 12, Sim 8 -> (625 - 289) * 20 = 6720
  global-non-ticking-chunk-count-target: 6720

  # NEW in 2.6: what a world with ZERO players should be driven to.
  #   min  - drop it to its configured minimum (recommended, default)
  #   max  - drive it to its configured maximum (behaviour before 2.6)
  #   keep - leave whatever it currently has
  # No chunks tick while a world is empty, so "max" costs nothing right up until
  # someone walks in, at which point they land on a fully maxed-out world and
  # max-decrease-step can only walk it back down one notch per check. That is the
  # exact load spike startup-grace exists to prevent, hence "min" as the default.
  empty-world-target: min

  # NEW in 2.7: weigh chunks by what is actually IN them instead of counting
  # them all the same. An ocean chunk costs almost nothing; a chunk holding a
  # 500-hopper sorting system can dominate a tick on its own, yet the plain
  # (2*d+1)^2 formula treats both as one unit, so a redstone-heavy world gets
  # the same budget as a world full of water.
  #
  # Inspecting chunks is itself work, so this SAMPLES a bounded number of
  # loaded chunks per world (round-robin) and derives an average multiplier,
  # refreshed once per ticks-per-check. It never scans every chunk.
  use-complexity-weighting: false

  # How many loaded chunks to sample per world per refresh. Higher = more
  # accurate but more work. 40 is plenty for a stable average.
  complexity-sample-chunks: 40

  # Base cost of an ordinary chunk before any tile entities are counted.
  complexity-default-weight: 1.0

  # Surcharge per tile entity of that material. Names are Bukkit Material
  # names. Anything not listed adds nothing.
  complexity-weights:
    HOPPER: 0.5
    SPAWNER: 2.0
    CHEST: 0.05
    TRAPPED_CHEST: 0.05
    BARREL: 0.05
    FURNACE: 0.1
    BLAST_FURNACE: 0.1
    SMOKER: 0.1
    BREWING_STAND: 0.1
    BEACON: 0.5
    CONDUIT: 0.5
    PISTON: 0.1
    STICKY_PISTON: 0.1

# ============================================================
#   REACTIVE MODE
# ============================================================
reactive-mode-settings:

  # Below which MSPT should an increase of the distance be considered?
  increase-mspt-threshold: 40.0

  # Above which MSPT should a decrease of the distance be considered?
  # A tick lasts at most 50ms (= 20 TPS); players notice lag from ~47ms.
  decrease-mspt-threshold: 47.0

  # If true: when the server is overloaded, simulation distance is reduced FIRST.
  # View distance is only reduced once simulation distance has already hit its
  # configured minimum for that world. Simulation distance has a bigger impact
  # on TPS, while reducing view distance causes visible chunk flicker for
  # players, so this avoids touching view distance unless it's really needed.
  # If false: simulation and view distance are reduced together (old behavior).
  # Default: false
  prioritize-simulation-distance: false

  # Maximum number of steps simulation/view distance may change by in a single
  # check cycle, in EACH direction. Setting both to 1 gives the old behaviour of
  # one chunk at a time.
  #   max-increase-step - limits how much distance can grow in one check
  #   max-decrease-step - limits how much distance can shrink in one check
  #
  # These are deliberately not the same. Growing is a comfort: two chunks at a
  # time is quick enough that recovery is visible within minutes, and a step that
  # turns out to be wrong is undone by revert-increase-if-overloaded on the very
  # next check. Shrinking is a defence, and four lets it bail out in one move
  # when the server is genuinely in trouble rather than crawling down while
  # players sit through it.
  #
  # Default: 2 up, 4 down
  max-increase-step: 2
  max-decrease-step: 4

  # After increasing simulation/view distance, re-check MSPT shortly after
  # (see below). If the server is immediately overloaded as a result, the
  # increase is rolled back on the next check instead of waiting through the
  # normal passed-checks-for-decrease delay. This prevents the "jump straight
  # to max, then crawl back down one step at a time" problem.
  revert-increase-if-overloaded: true

  mspt-tracker-settings:

    # Over how many ticks is the MSPT average calculated?
    # 200 = 10 seconds, one check interval. Higher = smoother but slower to react:
    # a one-minute average hides a second-long freeze almost completely.
    collection-period: 200

    # MSPT prediction: Prevents increasing distances
    # even though we know from history that this would cause lag.
    mspt-prediction:
      enabled: true

      # How many minutes of history should be stored for the prediction?
      history-length: 30

      # Minimum number of data points before the prediction takes effect.
      # Prevents wrong decisions immediately after server start.
      min-samples: 5

    # MSPT VARIANCE: a server can have a perfectly fine *average* MSPT while
    # still spiking badly tick-to-tick (e.g. redstone clocks, chunk generation
    # bursts, plugin schedulers). Average-only checks miss this. This tracks
    # how spread out the recent tick times are (standard deviation) and can
    # treat a high-variance server as if it were overloaded, even if the
    # average MSPT is still below decrease-mspt-threshold.
    mspt-variance:
      enabled: true

      # How many of the most recent tick samples (from Paper's getTickTimes())
      # are used to compute the standard deviation. getTickTimes() holds up to
      # 100 samples (~5s at 20 TPS); this just controls how many of those are used.
      sample-window: 100

      # Standard deviation (in ms) above which the server is considered
      # "unstable" and treated as overloaded for decrease purposes, even if
      # average MSPT is fine. Typical stable servers sit around 1-4ms stddev;
      # noticeable stutter usually starts around 8-10ms+.
      variance-threshold: 8.0

      # Minimum number of samples required before variance is evaluated at all.
      # Prevents false positives right after server start.
      min-samples: 20

      # If true, high variance ALSO blocks increases (in addition to forcing
      # decreases), even if average MSPT looks fine. Recommended: true.
      block-increase-on-high-variance: true

      # Standard deviation is symmetric. It measures how spread out recent ticks
      # are around the average, regardless of direction. A server bouncing between
      # 4ms and 18ms (avg ~10ms, still totally fine) can trip the same stddev
      # threshold as one bouncing between 40ms and 55ms (avg ~47ms, actually
      # struggling). Variance is only treated as overload once the average MSPT
      # is at least this high. Below it, variance is ignored even if it exceeds
      # variance-threshold above.
      min-avg-mspt-to-trigger: 25.0

# ============================================================
#   PER-PLAYER FIXED VIEW DISTANCE (optional)
# ============================================================
# Lets specific players (e.g. mods, streamers) keep a fixed CLIENT-SIDE view
# distance regardless of what the plugin sets for the world. This only affects
# what that individual player receives. It does NOT change the world's
# server-side view distance or the chunk budget the rest of this plugin manages.
#
# Grant a permission "<permission-prefix><value>" to set that player's fixed
# view distance, e.g. with permission-prefix "viewdistancetweaks.fixed." :
#   viewdistancetweaks.fixed.20   -> that player always gets view distance 20
# If a player has multiple such permissions, the highest value is used.
# Valid values are 2-32; anything higher is clamped to 32. Note that a player
# never sees more chunks than their own client render-distance setting allows.
# Taking the permission away again hands the player back to their world's
# normal, plugin-managed view distance, no relog needed.
# ---------------------------------------------------------------------------
# PER-WORLD MSPT
# ---------------------------------------------------------------------------
# The server reports one MSPT figure for everything. When a single world is
# responsible for the load, that one number drags every world down with it and
# all of them get throttled - including the quiet ones that were not the
# problem.
#
# With this on, the plugin splits the server tick between worlds and judges
# each world by its own share. The world causing the lag shrinks first; the
# quiet ones are left alone, or may even keep growing.
#
# IMPORTANT: this does NOT change what the thresholds above mean. A world
# carrying exactly its fair share of the tick is still judged against the same
# decrease-mspt-threshold as before. Only worlds that pull more (or less) than
# their share see an adjusted figure, so nothing has to be re-tuned.
# On a single-world server this feature changes nothing at all.
per-world-mspt:

  # Default: false. Turning this on changes which world gets throttled first.
  enabled: false

  # How many ticks between per-world cost readings. The server tick time itself
  # is read every tick regardless, so raising this does not make the plugin
  # slower to notice lag spikes - it only makes the split between worlds
  # refresh less often. Raise it on servers with very many worlds.
  # Default: 20 (once per second)
  sample-interval: 20

  # On Folia, measure region tick times directly instead of estimating from
  # world contents. Ignored on Paper, which has no per-region timing to read.
  #
  # Note what this costs: a measured Folia figure is a region's tick PERIOD, and
  # every region that is keeping up reports the tick rate itself. So the per-world
  # split comes out even no matter which world is busy, and there is nothing to
  # attribute - with this on, per-world MSPT has no effect on Folia until regions
  # actually fall behind. Set it to false to use the estimating proxy on Folia too,
  # which is less precise but can tell a busy world from an idle one.
  # Default: true
  prefer-exact-source: true

  # How far a world's figure may be scaled away from the server-wide one.
  # A factor of 1.0 means "this world carries exactly its fair share".
  #   min - floor, so a quiet world on a struggling server is not told
  #         everything is fine and allowed to grow without limit
  #   max - ceiling, so one world briefly holding the whole tick does not get
  #         slammed to its minimum distance over a momentary spike
  # Default: 0.5 and 2.0
  min-attribution-factor: 0.5
  max-attribution-factor: 2.0

  # Log a line whenever a world is judged by an adjusted figure. Useful when
  # first turning this on to see what it is actually doing; noisy afterwards.
  # Default: false
  log-attribution: false

per-player-fixed-view-distance:
  # Must be true for the viewdistancetweaks.fixed.<value> permissions to do
  # anything. Works independently of the "enabled" master switch at the top.
  enabled: false
  # Must be lowercase-safe; a trailing "." is added automatically if missing.
  permission-prefix: "viewdistancetweaks.fixed."

# ============================================================
#   PER-PLAYER FIXED SIMULATION DISTANCE (optional, NEW in 2.6)
# ============================================================
# Exactly the same idea as the fixed view distance above, but for simulation
# distance (Paper's Player#setSimulationDistance). Simulation distance controls
# how far around that player the world actually TICKS: mobs, redstone, crops.
#
# Careful: unlike view distance this genuinely costs server performance, so
# handing it out widely will hurt. It is meant for a handful of staff members,
# not for a donor rank.
#
#   viewdistancetweaks.simfixed.8   -> that player always gets simulation distance 8
#
# Valid values are 2-32; anything higher is clamped to 32. If a player holds
# several such permissions, the highest value is used. Taking the permission
# away hands the player back to their world's normal distance, no relog needed.
# Use a DIFFERENT permission-prefix than the view-distance feature above,
# otherwise a single permission would set both values at once.
per-player-fixed-simulation-distance:
  enabled: false
  permission-prefix: "viewdistancetweaks.simfixed."

# ============================================================
#   AFK PLAYER THROTTLING (optional, NEW in 2.7)
# ============================================================
# A player standing still at spawn does not need the same distances as one
# flying an elytra. When they go AFK their personal distances drop to the
# values below, and the chunks they free up go straight back into the global
# budget for players who are actually playing.
#
# AFK state comes from Paper's own idle timer. If EssentialsX is installed its
# AFK state is used instead, so someone who typed /afk counts immediately
# instead of having to wait out afk-time-minutes.
#
# Note: an explicit viewdistancetweaks.fixed.<n> permission WINS over this
# throttle. If you want staff throttled while AFK too, don't give them that
# permission.
afk-player-throttling:
  enabled: false
  afk-time-minutes: 5
  afk-simulation-distance: 4
  afk-view-distance: 6
  use-essentials-if-present: true

# ============================================================
#   PING THROTTLING (optional, NEW in 2.11)
# ============================================================
# A player with a bad connection cannot keep up with the chunks their distance
# already sends them - packets queue, the client falls further behind, and
# raising anyone else's distance only adds to what that connection has to
# carry. Reduced personal distances free the budget for players whose
# connection can actually use it. Same mechanism as afk-player-throttling:
# personal distances only, applied through Player#setViewDistance /
# #setSimulationDistance.
#
# A single high reading does not trip this. Checks run on the same ~5-second
# cadence as afk-player-throttling and the fixed-view overrides, and the
# threshold has to hold for checks-before-throttle of them in a row before
# anyone is throttled - so the default of 3 is about 15 seconds of sustained
# bad ping. Recovery is immediate: the next good sample lifts the throttle.
#
# If both this and afk-player-throttling apply to the same player, the smaller
# (more restrictive) distance wins - enabling one never raises what the other
# already set.
#
# Note: an explicit viewdistancetweaks.fixed.<n> permission WINS over this
# throttle, exactly like afk-player-throttling.
ping-throttling:
  enabled: false
  ping-threshold-ms: 200
  checks-before-throttle: 3
  ping-simulation-distance: 4
  ping-view-distance: 6

# ============================================================
#   CHUNK GENERATION SAFEGUARD (on by default since 2.14)
# ============================================================
# mspt-variance notices the stutter that terrain generation causes, but not the
# cause. This counts chunks that are genuinely being GENERATED (not merely read
# from disk) and reacts to the cause directly.
#
# Generating a chunk runs the whole terrain pipeline and is what actually
# freezes the main thread when someone crosses unexplored terrain at speed.
chunk-generation-safeguard:
  enabled: true

  # Newly generated chunks per second, per world, above which the safeguard trips.
  # 8 catches elytra and horse travel through new terrain; someone walking into
  # new land generates fewer and is left alone.
  chunks-per-second-threshold: 8

  # Block distance increases while generation is running. Growing view distance
  # mid-generation feeds the exact thing that is stalling the server and causes
  # the rubber-banding this is meant to avoid.
  lock-increase-during-gen: true

  # Additionally clamp view distance to this value while generating.
  # -1 disables the hard clamp and only uses lock-increase-during-gen above.
  # Never goes below the world's min-view-distance.
  emergency-view-distance: 8

# ============================================================
#   DENSITY-BASED SCALING (optional, NEW in 2.7)
# ============================================================
# 20 players scattered across a world load 20 separate rings of chunks.
# 20 players standing around the same community farm load almost the SAME
# chunks. The proactive formula assumes the first case and therefore starves a
# clustered world of view distance it could easily afford.
#
# When enough players sit within cluster-radius chunks of each other, this
# grants bonus distance proportional to how much of the world's population is
# in that cluster.
# ============================================================
#   CLIENT VIEW DISTANCE CAP
# ============================================================
# Nobody sees further than their own client draws. If the highest client setting
# in a world is 8, a server view distance of 16 loads, ticks and pays for rings
# of chunks that are never sent to anyone.
#
# With this on, a world's view distance is capped at the largest value its
# players' clients report, plus the headroom below. Never below that world's
# min-view-distance, and never applied to an empty world or to players whose
# client did not report a value.
#
# Off by default: it only helps if your players actually run low settings, and
# on a server where everyone uses 16+ it changes nothing at all.
client-view-distance-cap:
  enabled: false

  # Chunks on top of the highest reported setting. 1 means a player who raises
  # their slider one notch is not left staring at ungenerated terrain until the
  # next check. 0 caps exactly.
  headroom-chunks: 1

density-based-scaling:
  enabled: false
  # Radius in chunks within which players count as "together"
  cluster-radius: 8
  # Minimum players in one cluster before any bonus is granted
  cluster-player-threshold: 5
  # Maximum bonus distance, reached when everybody is in the same cluster
  max-bonus: 4

# ============================================================
#   EMERGENCY RELIEF (optional, NEW in 2.7)
# ============================================================
# Last resort. When a world already sits at its MINIMUM simulation and view
# distance and the server is STILL over decrease-mspt-threshold, there is
# nothing left to take away from distances. Rather than let the server keep
# sinking, shed two cheaper-to-lose sources of load instead: thunderstorms
# (extra light and weather updates) and the day/night cycle.
#
# Both are restored automatically once MSPT drops below recover-below-mspt,
# and on plugin disable. The world's ORIGINAL weather and doDaylightCycle
# setting are remembered, so a world that deliberately had the cycle off
# keeps it off afterwards.
emergency-relief:
  enabled: false
  clear-weather: true
  freeze-time: true
  # Deliberately lower than decrease-mspt-threshold, otherwise relief would
  # flap on and off around the same value that triggered it.
  recover-below-mspt: 40.0

# ============================================================
#   MEMORY SAFEGUARD (NEW in 2.7)
# ============================================================
# Distances don't only cost CPU. Every extra ring of chunks stays resident in
# the heap. A server can sit at a perfect 20ms MSPT and still be one increase
# away from spending every tick in garbage collection, at which point MSPT
# reacts far too late to be useful as the only signal.
#
# While free heap is below min-free-percent, ALL increases are blocked
# regardless of MSPT. Decreases always stay allowed.
#
# "Free" means free of LIVE data, measured against the -Xmx ceiling. It is the
# lowest heap usage seen in the last minute, not the usage right now: every
# collector deliberately lets garbage pile up before reclaiming it, so a single
# reading says more about where the GC cycle happens to be than about how much
# memory the server actually needs. Right after a collection, usage IS the live
# set, and that is what this compares against.
#
# FIXED in 2.11.1: the old reading also credited whatever the JVM was still
# allowed to grow by. Start with -Xms equal to -Xmx - what Aikar's flags and
# every hosting panel recommend - and the heap is committed up front, that
# credit is permanently zero, and the reading collapses to raw occupancy. On
# ZGC that blocked increases outright; on G1 it started once live data passed
# roughly half the heap. If you lowered min-free-percent to work around it,
# you can put it back.
memory-safeguard:
  enabled: true
  min-free-percent: 15.0

# ============================================================
#   PROFILES (optional, NEW in 2.7)
# ============================================================
# Named overlays for a handful of tuning values, switchable in-game with
# /vdt profile <name>, no config editing mid-event. "normal" is always
# available and means "the values configured above".
#
# Supported keys inside a profile:
#   decrease-mspt-threshold, increase-mspt-threshold,
#   max-increase-step, max-decrease-step,
#   passed-checks-for-increase, passed-checks-for-decrease,
#   global-ticking-chunk-count-target, global-non-ticking-chunk-count-target,
#   max-view-distance-cap, max-simulation-distance-cap
#
# The two *-cap keys are hard caps applied AFTER every other rule, so a cap of
# 8 genuinely means 8 and cannot be undone by never-reduce-below-players.
profiles:
  event-mode:
    decrease-mspt-threshold: 42.0   # react to load much earlier
    max-view-distance-cap: 8        # hard ceiling for the duration of the event
    passed-checks-for-increase: 60  # and be very reluctant to grow again

  night-mode:
    increase-mspt-threshold: 45.0   # be generous while the server is quiet
    max-increase-step: 2

# ============================================================
#   STARTUP GRACE PERIOD (optional)
# ============================================================
# If enabled, the plugin forces a low, fixed sim/view distance immediately when
# the plugin starts (before start-delay/ticks-per-check even apply), instead of
# whatever distance the world already had (which could be near max after a
# config change or a manual override, and cause instant overload/crash on a
# cold-started server). Once duration-ticks has passed, normal proactive/
# reactive/mixed adjustment takes back over as usual, and max-increase-step
# still limits how fast it's then allowed to climb back up.
startup-grace:
  enabled: false
  simulation-distance: 4
  view-distance: 6
  # 6000 ticks = 5 minutes
  duration-ticks: 6000

# ============================================================
#   WORLD SETTINGS
# ============================================================
# Any worlds not listed here inherit the "default" settings.
# You can override each world with its exact name.

world-settings:

  default:
    simulation-distance:
      # Exclude the world completely from management?
      # Chunks are still counted for global calculations (unless chunk-weight: 0).
      exclude: false
      min-simulation-distance: 4
      max-simulation-distance: 12

    view-distance:
      exclude: false
      min-view-distance: 6
      max-view-distance: 16

    # How much chunk "budget" does this world weigh?
    # 1.0 = normal. 0.5 = half as heavy (e.g. End, many empty chunks).
    # 0.0 = world has no influence on global calculations.
    chunk-weight: 1.0

    # NEW: Override how often THIS world is checked, independent of the global
    # ticks-per-check above. Leave unset (or <= 0) to inherit the global value.
    # Useful for a busy overworld that needs quick reactions vs. a quiet, mostly
    # empty nether/end that doesn't need checking every 30 seconds.
    # ticks-per-check: 200

    # NEW: Never lower the distance below the current player count in this world.
    # Useful for small servers with few players.
    never-reduce-below-players: false

    # NEW: This world gets 50% more chunk budget in proactive calculations.
    # Useful for the main world on servers with multiple dimensions.
    priority-world: false

  # Example: Nether world
  # world_nether:
  #   simulation-distance:
  #     min-simulation-distance: 4
  #     max-simulation-distance: 8
  #   view-distance:
  #     min-view-distance: 4
  #     max-view-distance: 10
  #   chunk-weight: 0.8
  #   priority-world: false

  # Example: End world (many empty chunks -> lower weight)
  # world_the_end:
  #   simulation-distance:
  #     min-simulation-distance: 4
  #     max-simulation-distance: 10
  #   view-distance:
  #     min-view-distance: 6
  #     max-view-distance: 14
  #   chunk-weight: 0.5

  # Example: Main world with priority
  # world:
  #   simulation-distance:
  #     min-simulation-distance: 6
  #     max-simulation-distance: 12
  #   view-distance:
  #     min-view-distance: 8
  #     max-view-distance: 16
  #   chunk-weight: 1.0
  #   priority-world: true

messages.yml has every string players and staff see, with & colours and {placeholder} substitution. It's copied into the data folder on first start. Every key also has a fallback inside the jar, so an older messages.yml keeps working instead of rendering blank lines, and anything missing gets listed in the console once at load.

Distances are in chunks, timings are in ticks, so ticks-per-check: 200 is 10 seconds. The --duration flag on the two override commands is the exception, that one takes minutes.

An older config.yml gets topped up on start with whatever a newer build added, and your previous file is kept as config.yml.bak. Nothing existing is rewritten.


Commands

CommandWhat it does
/vdt status [--weight] [--fixed]Live state per world: distances, chunk counts, MSPT, variance, plus a line for each subsystem that is actually switched on. --weight adds chunk weight and complexity multiplier, --fixed lists per-player overrides
/vdt simulate [world]Dry run. Shows what the next check would decide and the reason for it, without changing anything
/vdt historyThe last 20 applied changes, each with the reason it was made. Answers "why is view distance 6 right now" after the fact
/vdt analyzeSuggestions from this server's own history, e.g. a threshold that is never reached. Changes nothing
/vdt doctorOne check of everything that commonly goes wrong: platform, thresholds, world limits, other plugins overwriting distances, per-world MSPT, free memory, updates. Paste it into a bug report
/vdt mspt [debug]MSPT, TPS and standard deviation. debug adds the raw Paper tick samples
/vdt viewdistance <n> [world] [--duration <min>]Manual override. Without --duration it holds until the next reload
/vdt simulationdistance <n> [world] [--duration <min>]Same, for simulation distance
/vdt profile [name]Switch tuning overlay, or show which one is active
/vdt preset <name>Write one of the bundled presets into config.yml
/vdt pregen <start|pause|resume|stop|cancel|schedule|status>Pre-generate terrain. start <world> [radius] [--here]; schedule <world> <radius> <HH:mm> or schedule cancel; stop keeps progress, cancel --confirm discards it
/vdt enable / /vdt disableMaster switch without editing the config file
/vdt reloadRe-read config.yml and messages.yml, drop manual overrides
/vdt updateAsk Modrinth whether there is a newer version

Permissions

Everything defaults to OP, except the two numeric families at the bottom, which are never granted automatically.

NodeGrants
viewdistancetweaks.command.vdtAccess to /vdt at all
viewdistancetweaks.vdt.command.status/vdt status, /vdt history, /vdt mspt, /vdt analyze and /vdt doctor
viewdistancetweaks.vdt.command.simulate/vdt simulate
viewdistancetweaks.vdt.command.viewdistance/vdt viewdistance
viewdistancetweaks.vdt.command.simulationdistance/vdt simulationdistance
viewdistancetweaks.vdt.command.preset/vdt preset
viewdistancetweaks.vdt.command.profile/vdt profile
viewdistancetweaks.vdt.command.pregen/vdt pregen
viewdistancetweaks.vdt.command.reload/vdt reload, enable, disable, update
viewdistancetweaks.notifyReceives the in-chat announcement when a distance changes
viewdistancetweaks.fixed.<n>Fixed view distance for that player
viewdistancetweaks.simfixed.<n>Fixed simulation distance for that player

Support

Made and maintained by LucasTHCR.

Questions, bug reports and feature ideas go to dc.gg/paperstream. I read everything there, and a bug report with your config.yml and the output of /vdt status saves us both a round of guessing.


License

Copyright (C) 2026 LucasTHCR

ViewDistanceTweaks is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.

Short version: use it, study it, change it, pass it on. Anything you distribute that's built on it has to be GPLv3 too and has to ship its source.

Releases up to and including 2.6-RELEASE were published under the MIT License; copies obtained under those terms stay governed by them.

Последние версии

Все версии →
release

ViewDistanceTweaks 2.15.0

2.15.0-RELEASE
24 окт. 2026 г.416Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
### New: diagnostics mode `/vdt diagnose on` writes down what the plugin sees and decides, so a problem can be looked at afterwards instead of only while it happens. One file per day in `plugins/ViewDistanceTweaks/diagnostics`, one JSON line per entry, no player names. - A sample every `interval-seconds` (60): MSPT, TPS, tick variance, free heap, players, and per world the distances, loaded chunks, players, the highest client view distance, terrain generation and the density bonus. On Folia also the MSPT of every player's region. - Every distance change with the rule behind it, the settings at start and after every `/vdt reload`. - `extra-sample-above-mspt`: an extra sample whenever MSPT goes above this value, at most every 10 seconds, so a short lag spike between two samples is not missed. Off by default. - `/vdt diagnose note <text>` adds your own line with a timestamp, for example when players report lag. `/vdt diagnose status` shows today's file and how much was written. - Switches for samples and changes, a world filter, a daily size limit, old days packed as `.jsonl.gz` and deleted after `keep-days`. - Off by default. `/vdt diagnose on|off` lasts until the next restart, `diagnostics.enabled` records from startup. Send the folder along with a bug report. ### Changed - **Decrease reasons name the rule that caused them.** `/vdt history`, the console line and the diagnostics file used to say `decrease (mspt=11.9, mode=mixed)` even when MSPT had nothing to do with it. They now say what it was, for example `decrease: client view cap (highest client 12 + 1 headroom)` or `decrease: MSPT above 47.0 + chunk budget`. - **The client view distance cap no longer pulls the simulation distance down.** Because view distance may never be lower than simulation distance, one player with a low render distance used to slow down farms and redstone for everyone in that world. The cap now stops at the current simulation distance and only holds back increases above it. - **The highest client view distance is held for three minutes.** A player switching dimensions no longer makes a world jump down and back up. ### Config update Existing config files get the new `diagnostics` block added on the first start (config version 5), switched off. Nothing else needs to change. ### Tested Folia 1.21.11 with bots rendering 6 and 12 chunks: the cap lowered only the view distance, kept the simulation distance, held the higher value for three minutes after that bot left, and every change carried the right reason. Paper 26.3: config upgrade, all diagnostics options, notes, status, the world filter and the packing of old files. 247 automated tests.
release

ViewDistanceTweaks 2.14.1

2.14.1-RELEASE
23 окт. 2026 г.182Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
### Fixed - **Folia: MSPT and TPS now come from the regions your players are in.** Folia has no single server tick, and its MSPT and TPS methods answer for whichever region the calling thread belongs to. The plugin runs its checks on Folia's global region, which never carries players, so it saw a server that was always fast and the MSPT thresholds practically never fired. Distances on Folia were only steered by the chunk budget, the chunk generation safeguard and the memory safeguard. Now every online player's region is asked for its own MSPT and TPS every 5 seconds, on that region's thread, and the slowest region counts for the server. `/vdt doctor` shows where the figure comes from. Folia still offers no per tick timing, so the variance check stays off there. On Paper, Purpur and Spigot the MSPT reading is unchanged. - `/vdt doctor` and the `analyze` and `doctor` lines of `/vdt help` printed raw key names (`doctor.header`, `help.doctor`, ...) instead of text since 2.13.0. A test now checks that every key in `messages.yml` is actually loaded. ### Tested - Folia 1.21.11 with 8 bots and a deliberately overloaded region: the plugin read the same MSPT as Folia's own `/tps` report and lowered the distances. AFK throttling and density scaling were checked in the same run. - Paper 26.3: clean start, `/vdt doctor`, `/vdt help` and `/vdt mspt` correct. No config changes.
release

ViewDistanceTweaks 2.14.0

2.14.0-RELEASE
20 окт. 2026 г.432Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
### Changed - New defaults for how fast the plugin reacts. A benchmark on fresh terrain (players flying into land nobody had generated yet) showed the old defaults raising the view distance to 16 while single ticks took over a second, and taking about two minutes to back off. The cause: MSPT was averaged over a full minute, which hides a one-second freeze almost completely, and the chunk generation safeguard was off. - `ticks-per-check` 600 -> 200: worlds are checked every 10 seconds instead of 30. - `passed-checks-for-increase` 3 -> 9: growing stays exactly as fast as before (about +2 chunks every 90 seconds), only reacting to load got faster. - `collection-period` 1200 -> 200: MSPT is averaged over 10 seconds instead of a minute. - `chunk-generation-safeguard` is now on, trips at 8 newly generated chunks per second instead of 15, and caps view distance at 8 while it is tripped (`emergency-view-distance` -1 -> 8). Walking into new land stays below that; elytra and horse travel does not. - The `event-mode` profile's `passed-checks-for-increase` 20 -> 60, so it keeps the same pace. With these values, on fresh terrain the p99 tick time went from 242 / 406 ms to 58 / 48 ms and ticks over 100 ms from 485 / 733 to 107 / 114 (two runs each, same bot routes). On pre-generated terrain nothing got worse: the plugin still holds about 14.5 view distance at the stutter level of a fixed 12. ### Config update Existing config files are updated on the first start. A value is only changed if it still has the old default; anything you set yourself stays as it is, and a backup is kept as `config.yml.bak`. Each changed line gets a short note with its old value. If your `ticks-per-check` was still 600, every `passed-checks-for-increase` in the file (profiles included) is tripled with it, so the climbing pace you chose stays the same. The console lists every setting it changed.
release

2.13.0-RELEASE

2.13.0-RELEASE
12 окт. 2026 г.988Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
### Added - `/vdt doctor`. One look at everything that commonly goes wrong, in a single list: platform and scheduler, whether the plugin is enabled, MSPT thresholds that leave no gap, worlds with a minimum above their maximum, worlds that are configured but not loaded, other plugins that keep overwriting a world's distances (with the likely culprits), the per-world MSPT state, free heap, PlaceholderAPI and whether an update is out. It reads only and changes nothing. Pasting its output into a bug report answers most of the first questions. Permission: the same as `/vdt status`. - `/vdt analyze` and `/vdt doctor` are listed in `/vdt` help. ### Changed - The readme and the project page now describe the client view distance cap and the conflict detection from the 2.11 and 2.12 releases, and list the placeholders only once. No config changes. messages.yml gains a `doctor` section; an existing file keeps working, the new lines fall back to the bundled English text.
release

ViewDistanceTweaks 2.12.0

2.12.0-RELEASE
29 сент. 2026 г.957Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
### Cap view distance at what the clients actually render Nobody sees further than their own client draws. If the highest client setting in a world is 8, a server view distance of 16 loads, ticks and pays for rings of chunks that are never sent to anyone. The new `client-view-distance-cap` section caps a world's view distance at the largest value its players' clients report, plus a small headroom. It never goes below that world's `min-view-distance`, simulation distance follows so `view >= sim` still holds, and an empty world is left alone. A client that never reported a value counts as unknown rather than as a cap of zero. Off by default. It only pays on servers whose players run low settings, and changes nothing where everyone uses 16 or more. `/vdt status` shows the highest client value per world when it is on. ### A config upgrade that quietly did nothing Found while building the above, and it would have affected every future option: the upgrader keeps a hand-maintained list of the sections it knows. A section missing from that list was never added to an existing config, while the config version marker was raised anyway, after which the upgrader stayed silent about it for good. The option then ran on its code default and nobody could find it in their file. There is now a test comparing that list against the shipped config, so a new section cannot slip through again. ### Shorter comments Roughly 1700 lines of explanatory comment came out of the source. The reasoning behind each fix lives in the commit that made it; what stays in the code is the short note that keeps a line from being rewritten wrongly. No behaviour changed. ### Upgrading Replace the jar and restart. The new section is added to your existing `config.yml` automatically, switched off.
release

ViewDistanceTweaks 2.11.7

2.11.7-RELEASE
19 сент. 2026 г.365Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
A follow-up to 2.11.6, from the same report. ### The warning now names the plugins that could be responsible 2.11.6 started saying when something else on the server overwrites view or simulation distance. Useful, but it left the obvious question open: which plugin? On the server this came from, answering that meant going through forty plugins by hand. There is no way to catch the writer in the act, since Bukkit has no event for it and the call is long gone by the time the next check notices. What can be answered is which plugins are even able to do it: a call to `setViewDistance` leaves the method name in the calling class, and Bukkit API names survive obfuscation. So the warning is now followed by a second line: ``` Plugins installed here that CAN write view or simulation distance: ClearLag. This lists what is capable of it, not what did it - a plugin whose feature is turned off still appears, and so does one that only changes it per player. Check their configs for a view-distance option before changing anything, and do not remove a plugin on the strength of this line. ``` The wording is deliberate. The scan proves capability, never guilt: a plugin with the feature switched off still matches, and `Player#setViewDistance` is spelled the same as the world method, so per-player plugins match without ever touching a world. It exists to turn forty plugins into two worth checking, not to pick one out. If nothing matches, it says so too, and points at server.properties and proxies instead. The scan reads the jars once per server start, on a background thread, and only after a conflict has actually been detected. Servers that never hit one never pay for it. ### Upgrading No config changes and no new keys. Replace the jar and restart.
release

ViewDistanceTweaks 2.11.6

2.11.6-RELEASE
17 сент. 2026 г.143Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
One fix, from a live server report. ### The plugin now notices when another plugin overwrites it If something else on the server also writes view or simulation distance, the plugin never knew. Every cycle it read the foreign value as the current state, wrote its own over it, logged an honest change, and did the same thing again 30 seconds later. On the server this was reported from, that meant twenty worlds producing the same log line every 30 seconds, forever, and players reloading chunks on a timer because the value kept moving. Nothing in the log suggested the plugin was being overruled rather than simply doing its job, so finding the cause took hours. It turned out to be a lag-management plugin with its own view distance feature. The plugin now remembers what it last set. If a world comes back changed three checks in a row, it says so once: ``` 'world_nether': view distance set to 12 but found at 20 on the next check, 3 times in a row. Something else on this server writes these values too ... Leaving this world alone. Check your other plugins for a view-distance setting, then /vdt reload to resume managing it. ``` Then it stops managing that world, which ends both the log spam and the chunk reloading. `/vdt status` marks the world so the state is visible after the warning has scrolled away. A reload, or setting that world by hand, resumes management. Three checks rather than one on purpose: a single mismatch is an admin running a command or a world reloading, not a second plugin. ### Upgrading No config changes and no new keys. Replace the jar and restart.
release

ViewDistanceTweaks 2.11.5

2.11.5-RELEASE
16 сент. 2026 г.63Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
One fix, found while testing against Paper 26.3. ### An ampersand that is not a colour code keeps its ampersand Colour codes are written with `&`, and every `&` in a message was turned into the section sign the client renders colours with, whether or not a colour code followed it. An ampersand written as a word therefore ate itself and left behind a character the client cannot resolve. The built-in help showed it: `/vdt mspt` was described as "Show MSPT, TPS § variance". The same happened to any `&` you wrote in your own `messages.yml` or in `announce-format`. Nothing ever reported this, because there is nothing to report. A stray section sign is not an error at runtime, it simply renders as a stray character. Only `&` directly followed by a real code is translated now, which is what Bukkit itself does. One limit is unchanged and cannot be removed: a code letter is a code letter, so `&d` is light purple whether or not you meant to write "R&D". ### Paper 26.3 Tested against build 5 under Java 25. Clean start, no deprecation warnings, every command behaving correctly, and the distance engine climbing 10 to 12 across three worlds in three confirmations, exactly as the defaults intend. ### Upgrading No config changes and no new keys. Replace the jar and restart.
release

ViewDistanceTweaks 2.11.4

2.11.4-RELEASE
8 сент. 2026 г.244Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Скачать
Что нового
One fix, found by reading the code rather than from a report. ### An operator pause on a pre-generation run undid itself `/vdt pregen pause` and `/vdt pregen stop` both worked, reported success, and were then quietly reversed. The per-tick driver tracks two things: whether a run is paused, and whether the plugin paused it itself. Anything that blocks generation - a player logging in, an MSPT spike, a dip in free heap - wrote both. So the first blocker to come along relabelled an operator's pause as the plugin's own, and the release that follows lifted it as soon as that blocker cleared. The run carried on generating terrain nobody had asked it to resume, and `/vdt pregen status` showed the blocker as the reason instead of the command that actually paused it. The failure path is the worse half. When a chunk request is refused, the run stops rather than cancels, specifically so the request is not retried in a loop and the progress survives until someone looks at the cause. That containment ran through the same operator pause, so it did not hold: the run came back on its own and asked for the same failing chunk again. An operator pause is now settled before any blocker is looked at. ### Upgrading No config changes and no new keys. Replace the jar and restart.
release

ViewDistanceTweaks 2.11.3

2.11.3-RELEASE
7 сент. 2026 г.69Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2folia, paper, purpur
Скачать
Что нового
Four fixes from an error-analysis pass over the whole plugin. Nothing here was reported from outside; all four came out of reading the code, and each one is covered by a test that was checked against the unfixed build first. ### The memory safeguard could go blind after a clock jump 2.11.1 rewrote this to judge free heap by the lowest usage seen in the last minute, which is the right measurement. It timed that window with `System.currentTimeMillis()`, which is a wall clock and can step in both directions: an NTP correction, a resumed VM, a host clock sync. A backwards step is the dangerous one. The window stops accepting new samples and keeps only the branch that revises the current reading downwards, so it freezes holding an old trough that can fall but never rise. For the length of the jump the plugin reports free memory the server no longer has, and distance increases are allowed into a filling heap. Every reading in there is a duration, never a date, so it now uses `System.nanoTime()`, which is monotonic within a JVM. The condition cannot arise. ### A release was invisible to the pre-release that shared its number Version comparison read the numbers and stopped, so `2.11.0-RELEASE` and `2.11.0-ALPHA` came out equal. Anyone running an alpha or a beta was never told the finished version existed, and auto-update never staged it. Ties now break the way semantic versioning breaks them: a pre-release ranks below the release with the same numbers. Anything unrecognised counts as a release, so this can only ever withhold an update, never invent one. ### Two quieter ones `chunk-generation-safeguard` kept a counter per world and nothing removed it when a world was unloaded. Servers that create and discard worlds at runtime, minigame arenas and per-player plots, accumulated one entry per world for the lifetime of the process. On Folia, a refused scheduler dispatch was logged and otherwise swallowed. The complexity sampler decides who publishes its result by counting outstanding work, so a task that never ran left it waiting forever and every world kept the multiplier it already had, which is `1.00x`. With `use-complexity-weighting` on, the feature would have done nothing at all, without a line anywhere to say so. ### Upgrading No config changes and no new keys. Replace the jar and restart.