Chunksmith
4.3.6+26.x-pluginPre-generates chunks fast, and safely: an adaptive throttle paces generation against server tick-health so it can run with players online. Builds Distant Horizons / voxy LOD data as it goes and serves
4.3.6+26.x-pluginlatest4 weeks ago - Big modpacks no longer see the world-enter pre-gen speed up and slow down over and over: cached chunks are released as soon as memory runs short (mod_support #37). - New debug settingdebugWorldEnterSkipLod(off by default) skips LOD building during the world-enter pre-gen.4.3.6+1.21.x-plugin4 weeks ago - Big modpacks no longer see the world-enter pre-gen speed up and slow down over and over: cached chunks are released as soon as memory runs short (mod_support #37). - New debug settingdebugWorldEnterSkipLod(off by default) skips LOD building during the world-enter pre-gen.4.3.6+1.20.x-plugin4 weeks ago - Big modpacks no longer see the world-enter pre-gen speed up and slow down over and over: cached chunks are released as soon as memory runs short (mod_support #37). - New debug settingdebugWorldEnterSkipLod(off by default) skips LOD building during the world-enter pre-gen.4.3.5+26.x-plugin4 weeks ago - Fixed the world-enter pre-gen slowing to a crawl after about an hour: finished chunks now unload while the world is frozen instead of piling up in memory, and generation is faster (mod_support #37).4.3.5+1.21.x-plugin4 weeks ago - Fixed the world-enter pre-gen slowing to a crawl after about an hour: finished chunks now unload while the world is frozen instead of piling up in memory, and generation is faster (mod_support #37).4.3.5+1.20.x-plugin4 weeks ago - Fixed the world-enter pre-gen slowing to a crawl after about an hour: finished chunks now unload while the world is frozen instead of piling up in memory, and generation is faster (mod_support #37).4.3.4+26.x-pluginSep 24, 2026 - Fixed a pre-gen that could stop for good while the world was frozen, until you entered the world (mod_support #37). - The auto-pause warning now only appears when an auto-pause can actually happen. - Singleplayer no longer warns about opening a network port. - Forge jars no longer list Minecraft versions Forge cannot run (1.20.5, 1.21.2, 1.21.9). - Built against NeoForge 26.3.0.16-beta and Forge 1.21.5-55.1.14.4.3.4+1.21.x-pluginSep 24, 2026 - Fixed a pre-gen that could stop for good while the world was frozen, until you entered the world (mod_support #37). - The auto-pause warning now only appears when an auto-pause can actually happen. - Singleplayer no longer warns about opening a network port. - Forge jars no longer list Minecraft versions Forge cannot run (1.20.5, 1.21.2, 1.21.9). - Built against NeoForge 26.3.0.16-beta and Forge 1.21.5-55.1.14.4.3.4+1.20.x-pluginSep 24, 2026 - Fixed a pre-gen that could stop for good while the world was frozen, until you entered the world (mod_support #37). - The auto-pause warning now only appears when an auto-pause can actually happen. - Singleplayer no longer warns about opening a network port. - Forge jars no longer list Minecraft versions Forge cannot run (1.20.5, 1.21.2, 1.21.9). - Built against NeoForge 26.3.0.16-beta and Forge 1.21.5-55.1.14.4.3.3+26.x-pluginSep 20, 2026 4.3.2 stopped the pre-gen latching forever. It did not stop it pausing OFTEN, and on a two-core client the run settled into a fixed-period pause/resume/fail cycle instead. Reported on mod_support #36 by the reporter of #33, who confirmed the latch is gone and that the run now "pauses too often. Thus slowing down pregeneration." A resumed run kept its narrow start for about one sample. It came back below the width that failed, as intended -- and then reset its slow-start threshold to the CONFIGURED CEILING, which is the value that decides how fast it is allowed to widen again. Below that threshold the recovery path may climb eight steps per sample, so a run resumed at a width of 1 was permitted to burst straight back toward a ceiling of 200 and into the wall that had just stopped it. Resuming narrow bought nothing. A resumed run now inherits the width that FAILED as its threshold, so the climb stops where the evidence stops. The resume grace no longer answers the third failure the same way it answered the first. It was a flat five seconds, which is the right answer to a passing autosave and the wrong answer to a machine that has already failed at this repeatedly -- it is what let the oscillation sustain itself. It now doubles on each consecutive auto-pause, bounded by the pause-side grace and by 60 seconds. Only a width HELD healthily clears the escalation: coming back is not success, staying back is. Two log lines were stating the wrong number. The auto-pause notice and the auto-resume notice both printed the PAUSE grace where they meant the RESUME grace -- so a run that came back after five seconds announced it had waited two minutes. Both now print what they actually waited, and the pause notice says which repeat it is. The below-floor clock was decoupled from the resume clock. It had been read off the resume grace doubled, which was harmless while that was a constant and would have become a trap the moment it started escalating: being more patient about resuming would silently have made the controller slower to narrow.4.3.3+1.21.x-pluginSep 20, 2026 4.3.2 stopped the pre-gen latching forever. It did not stop it pausing OFTEN, and on a two-core client the run settled into a fixed-period pause/resume/fail cycle instead. Reported on mod_support #36 by the reporter of #33, who confirmed the latch is gone and that the run now "pauses too often. Thus slowing down pregeneration." A resumed run kept its narrow start for about one sample. It came back below the width that failed, as intended -- and then reset its slow-start threshold to the CONFIGURED CEILING, which is the value that decides how fast it is allowed to widen again. Below that threshold the recovery path may climb eight steps per sample, so a run resumed at a width of 1 was permitted to burst straight back toward a ceiling of 200 and into the wall that had just stopped it. Resuming narrow bought nothing. A resumed run now inherits the width that FAILED as its threshold, so the climb stops where the evidence stops. The resume grace no longer answers the third failure the same way it answered the first. It was a flat five seconds, which is the right answer to a passing autosave and the wrong answer to a machine that has already failed at this repeatedly -- it is what let the oscillation sustain itself. It now doubles on each consecutive auto-pause, bounded by the pause-side grace and by 60 seconds. Only a width HELD healthily clears the escalation: coming back is not success, staying back is. Two log lines were stating the wrong number. The auto-pause notice and the auto-resume notice both printed the PAUSE grace where they meant the RESUME grace -- so a run that came back after five seconds announced it had waited two minutes. Both now print what they actually waited, and the pause notice says which repeat it is. The below-floor clock was decoupled from the resume clock. It had been read off the resume grace doubled, which was harmless while that was a constant and would have become a trap the moment it started escalating: being more patient about resuming would silently have made the controller slower to narrow.4.3.3+1.20.x-pluginSep 20, 2026 4.3.2 stopped the pre-gen latching forever. It did not stop it pausing OFTEN, and on a two-core client the run settled into a fixed-period pause/resume/fail cycle instead. Reported on mod_support #36 by the reporter of #33, who confirmed the latch is gone and that the run now "pauses too often. Thus slowing down pregeneration." A resumed run kept its narrow start for about one sample. It came back below the width that failed, as intended -- and then reset its slow-start threshold to the CONFIGURED CEILING, which is the value that decides how fast it is allowed to widen again. Below that threshold the recovery path may climb eight steps per sample, so a run resumed at a width of 1 was permitted to burst straight back toward a ceiling of 200 and into the wall that had just stopped it. Resuming narrow bought nothing. A resumed run now inherits the width that FAILED as its threshold, so the climb stops where the evidence stops. The resume grace no longer answers the third failure the same way it answered the first. It was a flat five seconds, which is the right answer to a passing autosave and the wrong answer to a machine that has already failed at this repeatedly -- it is what let the oscillation sustain itself. It now doubles on each consecutive auto-pause, bounded by the pause-side grace and by 60 seconds. Only a width HELD healthily clears the escalation: coming back is not success, staying back is. Two log lines were stating the wrong number. The auto-pause notice and the auto-resume notice both printed the PAUSE grace where they meant the RESUME grace -- so a run that came back after five seconds announced it had waited two minutes. Both now print what they actually waited, and the pause notice says which repeat it is. The below-floor clock was decoupled from the resume clock. It had been read off the resume grace doubled, which was harmless while that was a constant and would have become a trap the moment it started escalating: being more patient about resuming would silently have made the controller slower to narrow.4.3.2+26.x-pluginSep 20, 2026 A pre-gen that auto-paused could never start again on a modest machine, and said nothing at all while it sat there. Reported on mod_support #33: a run stopped at 5.08% with the CPU idle and "no warnings, no errors, nothing" in the log. 4.3.1 fixed a different bug in the same area -- it stopped a stopped run being RECORDED as finished -- and did not touch the stop itself. **Server operators: two of these change behaviour on a healthy dedicated server too, not only on a weak client.** An auto-pause now ends in seconds rather than minutes, and a struggling run narrows its dispatch width below 8 where it previously stopped instead.Fixed
- A paused pre-gen could not resume on a machine whose tick cost exceeds 55ms. The resume test was two hard-coded numbers --mspt <= 55andheap < 70-- while the PAUSE side is entirely relative: heap fromthrottleMaxHeapPercent, and tick from the adaptiveTickBudgettarget, which is allowed as high as the 150ms ceiling. The two sides were answering different questions, so on any machine whose own baseline tick cost is above ~55ms the resume condition was unreachable by construction. Stopping even made it LOOK further away than it was: once dispatch halts, the baseline re-learns what the machine costs on its own and the effective target rises to meet it -- the run has become sustainable -- while the fixed 55ms test keeps asking the machine to be faster than it has ever been. Both arms now use the pause side's own references. - A pause could not be short even in principle. Pausing and resuming shared one grace setting, 120 seconds by default. That patience is right on the way IN, where it stops an autosave killing a healthy run, and wrong on the way OUT, where it costs the whole run. The resume side now has its own grace, capped at 5 seconds. - Auto-pause fired while there was still room to simply slow down. It triggered on elapsed time alone, with no test for whether narrowing had been tried. It now requires the dispatch width to be at its minimum first, and the width can fall below the comfort floor of 8, one step at a time, before stopping is considered at all. A resumed run reopens at half the width that failed rather than climbing straight back into the wall it was stopped by. - The whole mechanism was silent. Every notice auto-pause had went to the console sender -- a chat channel, not the log -- so on a client-hosted world nothing was written down anywhere, and a stop was indistinguishable from a hang. It now logs the countdown starting, the countdown being cancelled by a recovery, the pause (with the condition that tripped it, the tick and heap numbers behind the decision, and the percentage it stopped at), and the resume.Changed
- The LOD auto-enable notice was telling operators its cost was zero. It printed "~5.8 KB/chunk; measured cost to pregen speed: none". Measured on one machine, same heap, same radius, virgin ground per arm: 108.5 chunks/sec with LOD off against 50.6 with it on, and about 12 KB/chunk of store rather than 5.8. LOD generation roughly halves pre-gen throughput. The notice now says so. Nothing about LOD itself changed -- only the claim made about it. This also explains why a dedicated server pre-gens slower than a client: LOD auto-enables on a dedicated server and stays off on a client.4.3.2+1.21.x-pluginSep 20, 2026 A pre-gen that auto-paused could never start again on a modest machine, and said nothing at all while it sat there. Reported on mod_support #33: a run stopped at 5.08% with the CPU idle and "no warnings, no errors, nothing" in the log. 4.3.1 fixed a different bug in the same area -- it stopped a stopped run being RECORDED as finished -- and did not touch the stop itself. **Server operators: two of these change behaviour on a healthy dedicated server too, not only on a weak client.** An auto-pause now ends in seconds rather than minutes, and a struggling run narrows its dispatch width below 8 where it previously stopped instead.Fixed
- A paused pre-gen could not resume on a machine whose tick cost exceeds 55ms. The resume test was two hard-coded numbers --mspt <= 55andheap < 70-- while the PAUSE side is entirely relative: heap fromthrottleMaxHeapPercent, and tick from the adaptiveTickBudgettarget, which is allowed as high as the 150ms ceiling. The two sides were answering different questions, so on any machine whose own baseline tick cost is above ~55ms the resume condition was unreachable by construction. Stopping even made it LOOK further away than it was: once dispatch halts, the baseline re-learns what the machine costs on its own and the effective target rises to meet it -- the run has become sustainable -- while the fixed 55ms test keeps asking the machine to be faster than it has ever been. Both arms now use the pause side's own references. - A pause could not be short even in principle. Pausing and resuming shared one grace setting, 120 seconds by default. That patience is right on the way IN, where it stops an autosave killing a healthy run, and wrong on the way OUT, where it costs the whole run. The resume side now has its own grace, capped at 5 seconds. - Auto-pause fired while there was still room to simply slow down. It triggered on elapsed time alone, with no test for whether narrowing had been tried. It now requires the dispatch width to be at its minimum first, and the width can fall below the comfort floor of 8, one step at a time, before stopping is considered at all. A resumed run reopens at half the width that failed rather than climbing straight back into the wall it was stopped by. - The whole mechanism was silent. Every notice auto-pause had went to the console sender -- a chat channel, not the log -- so on a client-hosted world nothing was written down anywhere, and a stop was indistinguishable from a hang. It now logs the countdown starting, the countdown being cancelled by a recovery, the pause (with the condition that tripped it, the tick and heap numbers behind the decision, and the percentage it stopped at), and the resume.Changed
- The LOD auto-enable notice was telling operators its cost was zero. It printed "~5.8 KB/chunk; measured cost to pregen speed: none". Measured on one machine, same heap, same radius, virgin ground per arm: 108.5 chunks/sec with LOD off against 50.6 with it on, and about 12 KB/chunk of store rather than 5.8. LOD generation roughly halves pre-gen throughput. The notice now says so. Nothing about LOD itself changed -- only the claim made about it. This also explains why a dedicated server pre-gens slower than a client: LOD auto-enables on a dedicated server and stays off on a client.4.3.2+1.20.x-pluginSep 20, 2026 A pre-gen that auto-paused could never start again on a modest machine, and said nothing at all while it sat there. Reported on mod_support #33: a run stopped at 5.08% with the CPU idle and "no warnings, no errors, nothing" in the log. 4.3.1 fixed a different bug in the same area -- it stopped a stopped run being RECORDED as finished -- and did not touch the stop itself. **Server operators: two of these change behaviour on a healthy dedicated server too, not only on a weak client.** An auto-pause now ends in seconds rather than minutes, and a struggling run narrows its dispatch width below 8 where it previously stopped instead.Fixed
- A paused pre-gen could not resume on a machine whose tick cost exceeds 55ms. The resume test was two hard-coded numbers --mspt <= 55andheap < 70-- while the PAUSE side is entirely relative: heap fromthrottleMaxHeapPercent, and tick from the adaptiveTickBudgettarget, which is allowed as high as the 150ms ceiling. The two sides were answering different questions, so on any machine whose own baseline tick cost is above ~55ms the resume condition was unreachable by construction. Stopping even made it LOOK further away than it was: once dispatch halts, the baseline re-learns what the machine costs on its own and the effective target rises to meet it -- the run has become sustainable -- while the fixed 55ms test keeps asking the machine to be faster than it has ever been. Both arms now use the pause side's own references. - A pause could not be short even in principle. Pausing and resuming shared one grace setting, 120 seconds by default. That patience is right on the way IN, where it stops an autosave killing a healthy run, and wrong on the way OUT, where it costs the whole run. The resume side now has its own grace, capped at 5 seconds. - Auto-pause fired while there was still room to simply slow down. It triggered on elapsed time alone, with no test for whether narrowing had been tried. It now requires the dispatch width to be at its minimum first, and the width can fall below the comfort floor of 8, one step at a time, before stopping is considered at all. A resumed run reopens at half the width that failed rather than climbing straight back into the wall it was stopped by. - The whole mechanism was silent. Every notice auto-pause had went to the console sender -- a chat channel, not the log -- so on a client-hosted world nothing was written down anywhere, and a stop was indistinguishable from a hang. It now logs the countdown starting, the countdown being cancelled by a recovery, the pause (with the condition that tripped it, the tick and heap numbers behind the decision, and the percentage it stopped at), and the resume.Changed
- The LOD auto-enable notice was telling operators its cost was zero. It printed "~5.8 KB/chunk; measured cost to pregen speed: none". Measured on one machine, same heap, same radius, virgin ground per arm: 108.5 chunks/sec with LOD off against 50.6 with it on, and about 12 KB/chunk of store rather than 5.8. LOD generation roughly halves pre-gen throughput. The notice now says so. Nothing about LOD itself changed -- only the claim made about it. This also explains why a dedicated server pre-gens slower than a client: LOD auto-enables on a dedicated server and stays off on a client.4.3.1+26.x-pluginSep 19, 2026 A world-enter pregen that stopped early was recorded as having finished, and the world was then skipped forever. Reported on mod_support #35: a 5000-block radius produced a partial area, and on re-entry Chunksmith announced the world was already pre-generated and refused to run again. The resume-on-re-entry behaviour that makes a large radius workable at all was the exact thing being destroyed -- a 5000-block radius is about 306,000 chunks, which nobody finishes in one sitting.Fixed
- The world-enter pregen treated "the task ended" as "the work finished". It recorded completion fromGenerationCompleteEvent, whichGenerationTaskfires from the single end-of-task path that a genuine exhaustion of the iterator, a cancel, a pause and an auto-pause all reach. The task's own comment beside that line already said it: *"Ending a task is not the same as finishing the work."* Auto-pause is the likely trigger in the wild -- when the server cannot keep up,GenerationTaskdeliberately stops rather than stutter and expects the resume watcher to pick the run back up, which is correct behaviour and is not being changed here. What was wrong is that stopping made Chunksmith writeworldenter-done.jsonwith the configured radius, describing a run that had covered a fraction of it.WorldEnterDone.satisfies()then did its job perfectly and skipped that world on every subsequent load. - Completion is now recorded only when the task itself reports the selection covered. The progress event already carries that verdict (GenerationTask.update()setscompleteonly whenchunkIterator.total() - finishedChunks == 0), so the number being trusted is the task's own iterator total rather than this feature'sestimateChunks()circle-area approximation -- which is documented as inexact and has no business deciding whether a permanent record gets written. - The world is released either way. Whatever ended the task, the player is behind a frozen world and a progress screen, and leaving them there is the one outcome that is never acceptable. Only the permanent record is now conditional. - The log stops lying. A run that ends short says how far it got, that it is deliberately not being recorded, that it will resume on the next load, and that an auto-pause above is the usual reason. It previously said "world-enter pregen finished; releasing the world. It will not run again on this world." on exactly this path, with aTask stoppedline immediately above it.Notes
- If a world is already stuck, it stays stuck until the record is removed -- this build cannot un-write what a previous one recorded. Delete<world>/chunksmith/worldenter-done.json, or raiseworldEnterPregenRadiusabove the recorded value, and the feature re-arms. - No change to auto-pause, to the radius, to the shape, or to the selection. The reported symptom of a square area is what a partial concentric run looks like: the pattern walks square rings outward from the centre, so a run that stops early leaves a filled square well inside the circular selection. That part was working as designed and only looked wrong because it had been declared finished.4.3.1+1.21.x-pluginSep 19, 2026 A world-enter pregen that stopped early was recorded as having finished, and the world was then skipped forever. Reported on mod_support #35: a 5000-block radius produced a partial area, and on re-entry Chunksmith announced the world was already pre-generated and refused to run again. The resume-on-re-entry behaviour that makes a large radius workable at all was the exact thing being destroyed -- a 5000-block radius is about 306,000 chunks, which nobody finishes in one sitting.Fixed
- The world-enter pregen treated "the task ended" as "the work finished". It recorded completion fromGenerationCompleteEvent, whichGenerationTaskfires from the single end-of-task path that a genuine exhaustion of the iterator, a cancel, a pause and an auto-pause all reach. The task's own comment beside that line already said it: *"Ending a task is not the same as finishing the work."* Auto-pause is the likely trigger in the wild -- when the server cannot keep up,GenerationTaskdeliberately stops rather than stutter and expects the resume watcher to pick the run back up, which is correct behaviour and is not being changed here. What was wrong is that stopping made Chunksmith writeworldenter-done.jsonwith the configured radius, describing a run that had covered a fraction of it.WorldEnterDone.satisfies()then did its job perfectly and skipped that world on every subsequent load. - Completion is now recorded only when the task itself reports the selection covered. The progress event already carries that verdict (GenerationTask.update()setscompleteonly whenchunkIterator.total() - finishedChunks == 0), so the number being trusted is the task's own iterator total rather than this feature'sestimateChunks()circle-area approximation -- which is documented as inexact and has no business deciding whether a permanent record gets written. - The world is released either way. Whatever ended the task, the player is behind a frozen world and a progress screen, and leaving them there is the one outcome that is never acceptable. Only the permanent record is now conditional. - The log stops lying. A run that ends short says how far it got, that it is deliberately not being recorded, that it will resume on the next load, and that an auto-pause above is the usual reason. It previously said "world-enter pregen finished; releasing the world. It will not run again on this world." on exactly this path, with aTask stoppedline immediately above it.Notes
- If a world is already stuck, it stays stuck until the record is removed -- this build cannot un-write what a previous one recorded. Delete<world>/chunksmith/worldenter-done.json, or raiseworldEnterPregenRadiusabove the recorded value, and the feature re-arms. - No change to auto-pause, to the radius, to the shape, or to the selection. The reported symptom of a square area is what a partial concentric run looks like: the pattern walks square rings outward from the centre, so a run that stops early leaves a filled square well inside the circular selection. That part was working as designed and only looked wrong because it had been declared finished.4.3.1+1.20.x-pluginSep 19, 2026 A world-enter pregen that stopped early was recorded as having finished, and the world was then skipped forever. Reported on mod_support #35: a 5000-block radius produced a partial area, and on re-entry Chunksmith announced the world was already pre-generated and refused to run again. The resume-on-re-entry behaviour that makes a large radius workable at all was the exact thing being destroyed -- a 5000-block radius is about 306,000 chunks, which nobody finishes in one sitting.Fixed
- The world-enter pregen treated "the task ended" as "the work finished". It recorded completion fromGenerationCompleteEvent, whichGenerationTaskfires from the single end-of-task path that a genuine exhaustion of the iterator, a cancel, a pause and an auto-pause all reach. The task's own comment beside that line already said it: *"Ending a task is not the same as finishing the work."* Auto-pause is the likely trigger in the wild -- when the server cannot keep up,GenerationTaskdeliberately stops rather than stutter and expects the resume watcher to pick the run back up, which is correct behaviour and is not being changed here. What was wrong is that stopping made Chunksmith writeworldenter-done.jsonwith the configured radius, describing a run that had covered a fraction of it.WorldEnterDone.satisfies()then did its job perfectly and skipped that world on every subsequent load. - Completion is now recorded only when the task itself reports the selection covered. The progress event already carries that verdict (GenerationTask.update()setscompleteonly whenchunkIterator.total() - finishedChunks == 0), so the number being trusted is the task's own iterator total rather than this feature'sestimateChunks()circle-area approximation -- which is documented as inexact and has no business deciding whether a permanent record gets written. - The world is released either way. Whatever ended the task, the player is behind a frozen world and a progress screen, and leaving them there is the one outcome that is never acceptable. Only the permanent record is now conditional. - The log stops lying. A run that ends short says how far it got, that it is deliberately not being recorded, that it will resume on the next load, and that an auto-pause above is the usual reason. It previously said "world-enter pregen finished; releasing the world. It will not run again on this world." on exactly this path, with aTask stoppedline immediately above it.Notes
- If a world is already stuck, it stays stuck until the record is removed -- this build cannot un-write what a previous one recorded. Delete<world>/chunksmith/worldenter-done.json, or raiseworldEnterPregenRadiusabove the recorded value, and the feature re-arms. - No change to auto-pause, to the radius, to the shape, or to the selection. The reported symptom of a square area is what a partial concentric run looks like: the pattern walks square rings outward from the centre, so a run that stops early leaves a filled square well inside the circular selection. That part was working as designed and only looked wrong because it had been declared finished.4.3.0+26.x-pluginSep 18, 2026 The world-enter pregen always centred on (0, 0). Any mod that moves world spawn -- and plenty do -- therefore had it pregenerate the wrong part of the world: the player waits behind a progress screen while terrain nobody is going to stand on is built, and the terrain around them is generated on foot afterwards anyway. Reported on mod_support #34.Added
- `worldEnterPregenCenter` -- where the world-enter pregen is centred.origin(the default, and what every existing world already did),spawnto follow the world's spawn point, or an explicitx,z. Settable inconfig/chunksmith/config.jsonor with/cs set worldEnterPregenCenter spawn. In a command the coordinate form needs quotes --/cs set worldEnterPregenCenter "512,-64"-- because an unquoted command argument cannot contain a comma.originandspawnneed no quotes, and the config file takes the bare form either way. All three were checked on a live server, not assumed: the unquoted pair is the one thing that does not parse, and it fails loudly rather than storing something nobody asked for. - The server now tells you when no client has ever reached the LOD backchannel. It has always logged the port at startup and said to open it; three separate operators have now missed that line in a modded server's boot spam and reported the symptom instead. The server can tell the difference on its own -- a client is connected, a download credential was issued, and yet nothing has served AND nothing has been rejected, which together mean no request ever arrived -- so it says so, once, to the operator, at the moment it matters rather than at boot. Throttled to one message per player every ten minutes. The consequence differs by platform and the message says which applies to you: on the mod the LOD falls back to the game connection, so it still arrives, just slowly. **The plugin has no such fallback, so an unreachable backchannel there means no LOD at all** -- which makes the plugin the side that needed this notice most, and the side that did not have it until now. The notice now also names the cause it used to leave out.lodBackchannelBindAddressdefaults to empty, which means "bind wherever the game bound" -- that is, whateverserver-ip=says in server.properties. Unset, which is the normal case, that is every interface and all is well. But a hosted panel behind a proxy routinely setsserver-ip=127.0.0.1, and the backchannel then binds loopback only: unreachable however carefully the port is forwarded, and producing exactly the signature this notice fires on. It now says so, and gives the override --/cs set lodBackchannelBindAddress 0.0.0.0. - `/cs set` names the accepted forms when it refuses a value. A rejected setting used to say only that the value was invalid, leaving you to guess the shape it wanted.Fixed
- `/cs status` and `/cs progress` could answer with silence while a pregen was running. Both read the list of tasks, then printed only those whose world matched one the server currently listed -- and when none matched they printed nothing at all, not even "no tasks", because there were tasks. A player watching chunks generate could ask what was running and be told nothing, in two different ways. Both now report every task they hold; each line already named its own world, so the filtering was never buying anything. Reported on mod_support #33. - The world-enter estimate no longer swings by an hour between redraws. Reported from real play: "time remaining" jumping from 1-2 hours down to 30 minutes, several times a second. The estimate is measured over a window of eight samples, which was written for samples about a second apart -- but it is fedGenerationProgressEvent, which fires once per finished chunk, throttled to ten a second rather than to one. Eight of those is under a second of history, so on a bursty run the "rate" was whichever side of a burst it happened to catch. Samples closer together than a second are now ignored, so the window really is the few seconds it claims to be. Nothing about the window length or the arithmetic was wrong; the samples were simply arriving an order of magnitude faster than the code consuming them assumed. A rate is only as meaningful as the interval it is measured over.Changed
- Every cell was rebuilt against a current loader and a current fabric-api. This is not a behaviour change; it is a coverage one. The pins had drifted -- NeoForge 26.3 was three betas behind, 26.2 four builds, and several pre-26 cells more -- and because the declared ranges are deliberately wider than the build pins, nothing was ever broken by it: the jars loaded on the newer loaders perfectly well. What had drifted was that the jars players run were not the jars that were tested. NeoForge is now 26.126.1.2.109/ 26.226.2.0.88/ 26.326.3.0.4-beta, fabric-api 26.10.155.3/ 26.20.160.0/ 26.30.160.7, and the pre-26 Forge and NeoForge cells are current too. Forge 1.21.11 is the one exception and stays at `61.1.0`: newer builds on that line cannot be built here at all, because ForgeGradle 6 throwsduplicate entry: mcp/client/Start.classwhile assembling the mapped artifact. The published Forge bundles are not at fault -- they carry no duplicate -- and61.1.0succeeds only because its artifact was derived months ago and is still cached. That jar declares[61,)with an open upper bound, so it loads on newer 61.x regardless. - The completion record now stores the centre as well as the radius. It already stored the radius so that raisingworldEnterPregenRadiuscould re-arm a world that had been finished at a smaller one. The centre needs the same treatment for the same reason: without it, changing the centre on a world already recorded as done would be silently ignored forever, which is the exact failure the stored radius exists to prevent.4.3.0+1.21.x-pluginSep 18, 2026 The world-enter pregen always centred on (0, 0). Any mod that moves world spawn -- and plenty do -- therefore had it pregenerate the wrong part of the world: the player waits behind a progress screen while terrain nobody is going to stand on is built, and the terrain around them is generated on foot afterwards anyway. Reported on mod_support #34.Added
- `worldEnterPregenCenter` -- where the world-enter pregen is centred.origin(the default, and what every existing world already did),spawnto follow the world's spawn point, or an explicitx,z. Settable inconfig/chunksmith/config.jsonor with/cs set worldEnterPregenCenter spawn. In a command the coordinate form needs quotes --/cs set worldEnterPregenCenter "512,-64"-- because an unquoted command argument cannot contain a comma.originandspawnneed no quotes, and the config file takes the bare form either way. All three were checked on a live server, not assumed: the unquoted pair is the one thing that does not parse, and it fails loudly rather than storing something nobody asked for. - The server now tells you when no client has ever reached the LOD backchannel. It has always logged the port at startup and said to open it; three separate operators have now missed that line in a modded server's boot spam and reported the symptom instead. The server can tell the difference on its own -- a client is connected, a download credential was issued, and yet nothing has served AND nothing has been rejected, which together mean no request ever arrived -- so it says so, once, to the operator, at the moment it matters rather than at boot. Throttled to one message per player every ten minutes. The consequence differs by platform and the message says which applies to you: on the mod the LOD falls back to the game connection, so it still arrives, just slowly. **The plugin has no such fallback, so an unreachable backchannel there means no LOD at all** -- which makes the plugin the side that needed this notice most, and the side that did not have it until now. The notice now also names the cause it used to leave out.lodBackchannelBindAddressdefaults to empty, which means "bind wherever the game bound" -- that is, whateverserver-ip=says in server.properties. Unset, which is the normal case, that is every interface and all is well. But a hosted panel behind a proxy routinely setsserver-ip=127.0.0.1, and the backchannel then binds loopback only: unreachable however carefully the port is forwarded, and producing exactly the signature this notice fires on. It now says so, and gives the override --/cs set lodBackchannelBindAddress 0.0.0.0. - `/cs set` names the accepted forms when it refuses a value. A rejected setting used to say only that the value was invalid, leaving you to guess the shape it wanted.Fixed
- `/cs status` and `/cs progress` could answer with silence while a pregen was running. Both read the list of tasks, then printed only those whose world matched one the server currently listed -- and when none matched they printed nothing at all, not even "no tasks", because there were tasks. A player watching chunks generate could ask what was running and be told nothing, in two different ways. Both now report every task they hold; each line already named its own world, so the filtering was never buying anything. Reported on mod_support #33. - The world-enter estimate no longer swings by an hour between redraws. Reported from real play: "time remaining" jumping from 1-2 hours down to 30 minutes, several times a second. The estimate is measured over a window of eight samples, which was written for samples about a second apart -- but it is fedGenerationProgressEvent, which fires once per finished chunk, throttled to ten a second rather than to one. Eight of those is under a second of history, so on a bursty run the "rate" was whichever side of a burst it happened to catch. Samples closer together than a second are now ignored, so the window really is the few seconds it claims to be. Nothing about the window length or the arithmetic was wrong; the samples were simply arriving an order of magnitude faster than the code consuming them assumed. A rate is only as meaningful as the interval it is measured over.Changed
- Every cell was rebuilt against a current loader and a current fabric-api. This is not a behaviour change; it is a coverage one. The pins had drifted -- NeoForge 26.3 was three betas behind, 26.2 four builds, and several pre-26 cells more -- and because the declared ranges are deliberately wider than the build pins, nothing was ever broken by it: the jars loaded on the newer loaders perfectly well. What had drifted was that the jars players run were not the jars that were tested. NeoForge is now 26.126.1.2.109/ 26.226.2.0.88/ 26.326.3.0.4-beta, fabric-api 26.10.155.3/ 26.20.160.0/ 26.30.160.7, and the pre-26 Forge and NeoForge cells are current too. Forge 1.21.11 is the one exception and stays at `61.1.0`: newer builds on that line cannot be built here at all, because ForgeGradle 6 throwsduplicate entry: mcp/client/Start.classwhile assembling the mapped artifact. The published Forge bundles are not at fault -- they carry no duplicate -- and61.1.0succeeds only because its artifact was derived months ago and is still cached. That jar declares[61,)with an open upper bound, so it loads on newer 61.x regardless. - The completion record now stores the centre as well as the radius. It already stored the radius so that raisingworldEnterPregenRadiuscould re-arm a world that had been finished at a smaller one. The centre needs the same treatment for the same reason: without it, changing the centre on a world already recorded as done would be silently ignored forever, which is the exact failure the stored radius exists to prevent.4.3.0+1.20.x-pluginSep 18, 2026 The world-enter pregen always centred on (0, 0). Any mod that moves world spawn -- and plenty do -- therefore had it pregenerate the wrong part of the world: the player waits behind a progress screen while terrain nobody is going to stand on is built, and the terrain around them is generated on foot afterwards anyway. Reported on mod_support #34.Added
- `worldEnterPregenCenter` -- where the world-enter pregen is centred.origin(the default, and what every existing world already did),spawnto follow the world's spawn point, or an explicitx,z. Settable inconfig/chunksmith/config.jsonor with/cs set worldEnterPregenCenter spawn. In a command the coordinate form needs quotes --/cs set worldEnterPregenCenter "512,-64"-- because an unquoted command argument cannot contain a comma.originandspawnneed no quotes, and the config file takes the bare form either way. All three were checked on a live server, not assumed: the unquoted pair is the one thing that does not parse, and it fails loudly rather than storing something nobody asked for. - The server now tells you when no client has ever reached the LOD backchannel. It has always logged the port at startup and said to open it; three separate operators have now missed that line in a modded server's boot spam and reported the symptom instead. The server can tell the difference on its own -- a client is connected, a download credential was issued, and yet nothing has served AND nothing has been rejected, which together mean no request ever arrived -- so it says so, once, to the operator, at the moment it matters rather than at boot. Throttled to one message per player every ten minutes. The consequence differs by platform and the message says which applies to you: on the mod the LOD falls back to the game connection, so it still arrives, just slowly. **The plugin has no such fallback, so an unreachable backchannel there means no LOD at all** -- which makes the plugin the side that needed this notice most, and the side that did not have it until now. The notice now also names the cause it used to leave out.lodBackchannelBindAddressdefaults to empty, which means "bind wherever the game bound" -- that is, whateverserver-ip=says in server.properties. Unset, which is the normal case, that is every interface and all is well. But a hosted panel behind a proxy routinely setsserver-ip=127.0.0.1, and the backchannel then binds loopback only: unreachable however carefully the port is forwarded, and producing exactly the signature this notice fires on. It now says so, and gives the override --/cs set lodBackchannelBindAddress 0.0.0.0. - `/cs set` names the accepted forms when it refuses a value. A rejected setting used to say only that the value was invalid, leaving you to guess the shape it wanted.Fixed
- `/cs status` and `/cs progress` could answer with silence while a pregen was running. Both read the list of tasks, then printed only those whose world matched one the server currently listed -- and when none matched they printed nothing at all, not even "no tasks", because there were tasks. A player watching chunks generate could ask what was running and be told nothing, in two different ways. Both now report every task they hold; each line already named its own world, so the filtering was never buying anything. Reported on mod_support #33. - The world-enter estimate no longer swings by an hour between redraws. Reported from real play: "time remaining" jumping from 1-2 hours down to 30 minutes, several times a second. The estimate is measured over a window of eight samples, which was written for samples about a second apart -- but it is fedGenerationProgressEvent, which fires once per finished chunk, throttled to ten a second rather than to one. Eight of those is under a second of history, so on a bursty run the "rate" was whichever side of a burst it happened to catch. Samples closer together than a second are now ignored, so the window really is the few seconds it claims to be. Nothing about the window length or the arithmetic was wrong; the samples were simply arriving an order of magnitude faster than the code consuming them assumed. A rate is only as meaningful as the interval it is measured over.Changed
- Every cell was rebuilt against a current loader and a current fabric-api. This is not a behaviour change; it is a coverage one. The pins had drifted -- NeoForge 26.3 was three betas behind, 26.2 four builds, and several pre-26 cells more -- and because the declared ranges are deliberately wider than the build pins, nothing was ever broken by it: the jars loaded on the newer loaders perfectly well. What had drifted was that the jars players run were not the jars that were tested. NeoForge is now 26.126.1.2.109/ 26.226.2.0.88/ 26.326.3.0.4-beta, fabric-api 26.10.155.3/ 26.20.160.0/ 26.30.160.7, and the pre-26 Forge and NeoForge cells are current too. Forge 1.21.11 is the one exception and stays at `61.1.0`: newer builds on that line cannot be built here at all, because ForgeGradle 6 throwsduplicate entry: mcp/client/Start.classwhile assembling the mapped artifact. The published Forge bundles are not at fault -- they carry no duplicate -- and61.1.0succeeds only because its artifact was derived months ago and is still cached. That jar declares[61,)with an open upper bound, so it loads on newer 61.x regardless. - The completion record now stores the centre as well as the radius. It already stored the radius so that raisingworldEnterPregenRadiuscould re-arm a world that had been finished at a smaller one. The centre needs the same treatment for the same reason: without it, changing the centre on a world already recorded as done would be silently ignored forever, which is the exact failure the stored radius exists to prevent.4.2.0+26.x-pluginSep 17, 2026 Minecraft 26.3 shipped stable on 15 September. The 26.3 jar that was live before this release could not load on it at all -- not degraded, absent -- because every 26.3 pre-release moved the resource pack format, so that jar was pinned to exactly one build and 26.3 stable was a different one. This release ends that: 26.3 is a settled line now and takes the same closed range every other 26.X line has, so one jar serves 26.3 and everything after it up to 26.4.Added
- NeoForge on 26.3. The first NeoForge build Chunksmith has ever shipped for a 26.3 line -- NeoForge only published a 26.3 loader (26.3.0.1-beta) this week, which is why the line was Fabric-only until now. Requires NeoForge 26.3.0-alpha or newer.Changed
- The Fabric 26.3 jar now declares `>=26.3- <26.4` instead of a single exact build. It is the same range shape 26.1 and 26.2 have carried since they settled. Nothing about the mod changed between 26.3-rc-1 and 26.3 stable; the eight files Mojang touched are window handling, the multiplayer screen and version stamps. - The Bukkit / Paper / Spigot plugin now claims 26.3. One plugin jar already covered the whole 26 line; this is the metadata catching up so the 26.3 build is listed for it.4.1.0+26.x-pluginSep 16, 2026 Pregen throughput. The default pipeline width was wrong on every machine that was not an 8-core dedicated server, and on the Bukkit plugin it was wrong everywhere.Changed
- **dispatchMaxConcurrentnow defaults to 200 on every platform, and no longer scales with core count.* It used to be `cores 25`, which reads like protecting a small machine and does the opposite. Benched on a 2-core server (625 chunks, every JVM thread pinned): 8 -> 15.6 cps, 16 -> 17.7, 24 -> 19.5, 50 -> 16.9, 100 -> 21.5, 200 -> 29.8, 400 -> about 25 and stalling. The 8-core bench behind the old default agrees: 50 -> 31.6, 200 -> 43.9, 600 -> 42.4. Two machines four core-counts apart, the same knee -- because a chunk request spends almost all of its life waiting on vanilla walking it up its statuses, so width buys concurrency against latency, and latency does not shrink when you remove cores. On two cores the old formula gave 50 and cost that machine 43 percent of its throughput. - The Paper / Spigot plugin gets the same default for the first time.BukkitConfigcarried its own hard-coded 50, separate from the mod's, so no plugin server ever saw any dispatch tuning -- old or new. Both platforms now read one constant. - Single-player gets the same 200 as a dedicated server, and that was measured too. On a 4-core client with voxy and Sodium (16640 chunks, interleaved arms), width 200 took 275s and 298s with a worst pause of 6.0s; width 16 took 458s and 379s with worst pauses of 20.9s and 16.4s. Narrowing the pipeline costs throughput AND makes the longest stall worse; it does not trade one for the other.Fixed
- The dispatch controller converges instead of oscillating. It backed off one slot at a time and then climbed all the way back to the ceiling, so a machine that could not sustain the ceiling re-entered overload every time it recovered -- generate, pause, generate. A sustained overload now halves the width instead of stepping, and the controller remembers the widest setting that ran healthily and will not burst past it. Reported on mod_support #20 and #33.Added
- `/cs debug` reports the dispatch pipeline, and/cs diagis a new alias for it. The width the controller settled on only ever appeared in a throttle notice and the threshold it steers against appeared nowhere, so "the pregen keeps pausing" could not be answered by looking. Requested on mod_support #32.Changed (diagnostics)
- `/csclient status` no longer describes multiplayer when there is no server. Transport, token, injected, download and the store counters are the multiplayer client path and are inert on an integrated server; printed unconditionally they read as a broken feature. It now leads with the mode and omits what does not apply.4.1.0+1.21.x-pluginSep 16, 2026 Pregen throughput. The default pipeline width was wrong on every machine that was not an 8-core dedicated server, and on the Bukkit plugin it was wrong everywhere.Changed
- **dispatchMaxConcurrentnow defaults to 200 on every platform, and no longer scales with core count.* It used to be `cores 25`, which reads like protecting a small machine and does the opposite. Benched on a 2-core server (625 chunks, every JVM thread pinned): 8 -> 15.6 cps, 16 -> 17.7, 24 -> 19.5, 50 -> 16.9, 100 -> 21.5, 200 -> 29.8, 400 -> about 25 and stalling. The 8-core bench behind the old default agrees: 50 -> 31.6, 200 -> 43.9, 600 -> 42.4. Two machines four core-counts apart, the same knee -- because a chunk request spends almost all of its life waiting on vanilla walking it up its statuses, so width buys concurrency against latency, and latency does not shrink when you remove cores. On two cores the old formula gave 50 and cost that machine 43 percent of its throughput. - The Paper / Spigot plugin gets the same default for the first time.BukkitConfigcarried its own hard-coded 50, separate from the mod's, so no plugin server ever saw any dispatch tuning -- old or new. Both platforms now read one constant. - Single-player gets the same 200 as a dedicated server, and that was measured too. On a 4-core client with voxy and Sodium (16640 chunks, interleaved arms), width 200 took 275s and 298s with a worst pause of 6.0s; width 16 took 458s and 379s with worst pauses of 20.9s and 16.4s. Narrowing the pipeline costs throughput AND makes the longest stall worse; it does not trade one for the other.Fixed
- The dispatch controller converges instead of oscillating. It backed off one slot at a time and then climbed all the way back to the ceiling, so a machine that could not sustain the ceiling re-entered overload every time it recovered -- generate, pause, generate. A sustained overload now halves the width instead of stepping, and the controller remembers the widest setting that ran healthily and will not burst past it. Reported on mod_support #20 and #33.Added
- `/cs debug` reports the dispatch pipeline, and/cs diagis a new alias for it. The width the controller settled on only ever appeared in a throttle notice and the threshold it steers against appeared nowhere, so "the pregen keeps pausing" could not be answered by looking. Requested on mod_support #32.Changed (diagnostics)
- `/csclient status` no longer describes multiplayer when there is no server. Transport, token, injected, download and the store counters are the multiplayer client path and are inert on an integrated server; printed unconditionally they read as a broken feature. It now leads with the mode and omits what does not apply.4.1.0+1.20.x-pluginSep 16, 2026 Pregen throughput. The default pipeline width was wrong on every machine that was not an 8-core dedicated server, and on the Bukkit plugin it was wrong everywhere.Changed
- **dispatchMaxConcurrentnow defaults to 200 on every platform, and no longer scales with core count.* It used to be `cores 25`, which reads like protecting a small machine and does the opposite. Benched on a 2-core server (625 chunks, every JVM thread pinned): 8 -> 15.6 cps, 16 -> 17.7, 24 -> 19.5, 50 -> 16.9, 100 -> 21.5, 200 -> 29.8, 400 -> about 25 and stalling. The 8-core bench behind the old default agrees: 50 -> 31.6, 200 -> 43.9, 600 -> 42.4. Two machines four core-counts apart, the same knee -- because a chunk request spends almost all of its life waiting on vanilla walking it up its statuses, so width buys concurrency against latency, and latency does not shrink when you remove cores. On two cores the old formula gave 50 and cost that machine 43 percent of its throughput. - The Paper / Spigot plugin gets the same default for the first time.BukkitConfigcarried its own hard-coded 50, separate from the mod's, so no plugin server ever saw any dispatch tuning -- old or new. Both platforms now read one constant. - Single-player gets the same 200 as a dedicated server, and that was measured too. On a 4-core client with voxy and Sodium (16640 chunks, interleaved arms), width 200 took 275s and 298s with a worst pause of 6.0s; width 16 took 458s and 379s with worst pauses of 20.9s and 16.4s. Narrowing the pipeline costs throughput AND makes the longest stall worse; it does not trade one for the other.Fixed
- The dispatch controller converges instead of oscillating. It backed off one slot at a time and then climbed all the way back to the ceiling, so a machine that could not sustain the ceiling re-entered overload every time it recovered -- generate, pause, generate. A sustained overload now halves the width instead of stepping, and the controller remembers the widest setting that ran healthily and will not burst past it. Reported on mod_support #20 and #33.Added
- `/cs debug` reports the dispatch pipeline, and/cs diagis a new alias for it. The width the controller settled on only ever appeared in a throttle notice and the threshold it steers against appeared nowhere, so "the pregen keeps pausing" could not be answered by looking. Requested on mod_support #32.Changed (diagnostics)
- `/csclient status` no longer describes multiplayer when there is no server. Transport, token, injected, download and the store counters are the multiplayer client path and are inert on an integrated server; printed unconditionally they read as a broken feature. It now leads with the mode and omits what does not apply.4.0.0+26.x-pluginSep 13, 2026 Breaking. The command surface is reorganised by who can run a command and where it executes, and/cslodis retired. Protocol version moves to 4.Changed
- Commands are split by audience, not by feature./cslodgrouped things by subsystem, which put three client-side operations behind a server permission gate and gave the client's own state no readout at all. Server operator commands now live under the existing/csroot, which already carries the permission gate; everything a player runs for their own client lives under a new/csclient. | was | now | |---|---| |/cslod status|/cs lod status| |/cslod token <player>|/cs lod token <player>| |/cslod set|/csclient set| |/cslod inject|/csclient inject_voxy| |/cslod dhpush|/csclient inject_dh| - `/csclient` is a real client command, registered through Fabric'sClientCommandRegistrationCallbackand NeoForge/Forge'sRegisterClientCommandsEvent. It therefore works when connected to a server that has never heard of Chunksmith, which is exactly when you want to ask why no LODs are arriving. It does not exist on the Bukkit plugin; there is no client there. - `inject` and `dhpush` became `inject_voxy` and `inject_dh`. One was named for its verb and the other for its target, so neither said what it did. - Both status commands print one value per line instead of a single packed line. - The per-subcommand operator gates are gone./csgates at its root, and/csclientneeds no gate. - The client store is keyed to the WORLD, not the server address. A client used to file LOD under the host it connected to, so a world that changed address looked brand new and was downloaded again, while two unrelated worlds behind one address shared a store and overwrote each other. The server now mints a stable id per world and the client files under that. Stores from before 4.0 are left alone, listed by/csclient statusaspre-4.0 stores, and cleared by/csclient resetwhen you want the space back. Against a 3.x server the client falls back to the old host key, because that server has no id to give.Added
- `/csclient reset` returns the client to the state it was in before it first connected: the store for that server is deleted across every dimension, the injected-region bookkeeping is cleared, and the handshake runs again, all without a relog. Until now the only way out of a bad client store was to disconnect and delete the directory by hand. It cannot give you a clean slate on its own, and says so when it runs. Distant Horizons and Voxy keep their own databases, which Chunksmith does not touch by design, so a world that was regenerated server-side may still render its old terrain out of the renderer's copy. - `/csclient status` reports the client store: which server it is keyed to, the path, per-dimension region counts, transport, renderers, injection progress, and the settings in force. It also reports the renderer queue depth -- the numberthrottleLodDrainTobelow is measured against. Without it there was no way to tell whether that setting could ever engage on your machine. - `max-disk-mb` (client) caps what Chunksmith keeps on disk for a world, in megabytes. **Default 0, meaning no cap**, which is the behaviour every earlier release had: how much a client wrote was decided entirely by the server's index budget, a number the client cannot see and was never told. Nearest terrain is kept first. Declining regions does not put the client into a permanent re-download loop. The summary the two sides compare is an XOR aggregate, which is its own inverse, so declined regions fold back out of the server's number exactly and a capped client settles at "I have everything I intend to have". - `throttleLodDrainTo` (server) makes the LOD governor a barrier: stop dispatching entirely and let the renderer drain to that depth before resuming, rather than merely slowing down. **Default 0, meaning off, and it should stay off unless you have measured your own machine.** It is off by default because the measurement argues against it. On a four-core client with voxy the barrier ran about 11% SLOWER than the existing governor and did not change how often the run paused. It is here because alternating should beat competing on a machine with no cores to spare -- but that has not been demonstrated, and guessing the threshold is how a throttle ends up tuned for one box.Removed
- `/cslod` is gone, and a 4.x client does not register it under any name. See Compatibility. - TheSETTING_LIST/SETTING_SHOW/SETTING_SETrelay. A client command reads and writesconfig/chunksmith-lod.propertiesdirectly, so the server no longer has to ask the client on the player's behalf.Plugin (Paper / Spigot)
- `/cs lod status` and `/cs lod token <player>` work on the plugin too. Status is reported per WORLD rather than per dimension, because that is the shape a Bukkit server actually has: the mod keeps one save folder with its dimensions nested inside, Bukkit gives each world its own folder and therefore its own store. It answers from the console for the same reason. - There is no/csclienton the plugin and there will not be. That command runs on a client, and a Bukkit server does not have one. - The plugin serves the new world id, anchored to the primary world -- the onelevel-namenames and the one the others are derived from, so it is the folder whose replacement really does mean "this is a different world now". - Folia is no longer declared supported.folia-supportedis gone fromplugin.yml, so Folia will refuse to load the plugin rather than running it untested. This was announced in 3.3.0 and a major release is where it lands. Nothing changes for Paper or Spigot. The reasoning is not that Folia is broken -- it is that the Folia harness could not be kept working, and a platform nobody tests is an unverifiable claim, which is worse than an absent one. The region-scheduler code paths and thefolia-apicompile dependency are still in the tree and come out separately; removing them means moving three cells ontopaper-apiand unwinding the JVM-version workaroundsfolia-apiforces, which is its own change and does not belong in this one.Compatibility
CsLodProtocol.VERSIONgoes from 2 to 4, matching the major version from here on. There was never a protocol 3. 4.0.0 is a coordinated upgrade: move the server and the client together. The two protocols do not interoperate, so a mixed 3.x/4.x pair turns LOD off in BOTH directions -- the client will not fetch and the server will not serve. Everything else in Chunksmith keeps working; what stops arriving is the distant terrain. This is worth saying plainly because a launcher will offer 4.0.0 to anyone running 3.x, so a client can be updated into the mismatch without the server being touched by anyone. A 4.x client that lands on a 3.x server now says so in chat on join, rather than leaving you to work out why the horizon went empty. - 4.x server, 4.x client./csloddoes not exist on either side. - 3.x server, 4.x client. The client registers no/cslod, so the server's own still arrives in the command tree and/cslod setstill reaches this client's settings. LOD data does not transfer. - 4.x server, 3.x client./cslodanswers "update your cs client" and does nothing else. All of that lives in onelegacypackage and comes out in 5.x.4.0.0+1.21.x-pluginSep 13, 2026 Breaking. The command surface is reorganised by who can run a command and where it executes, and/cslodis retired. Protocol version moves to 4.Changed
- Commands are split by audience, not by feature./cslodgrouped things by subsystem, which put three client-side operations behind a server permission gate and gave the client's own state no readout at all. Server operator commands now live under the existing/csroot, which already carries the permission gate; everything a player runs for their own client lives under a new/csclient. | was | now | |---|---| |/cslod status|/cs lod status| |/cslod token <player>|/cs lod token <player>| |/cslod set|/csclient set| |/cslod inject|/csclient inject_voxy| |/cslod dhpush|/csclient inject_dh| - `/csclient` is a real client command, registered through Fabric'sClientCommandRegistrationCallbackand NeoForge/Forge'sRegisterClientCommandsEvent. It therefore works when connected to a server that has never heard of Chunksmith, which is exactly when you want to ask why no LODs are arriving. It does not exist on the Bukkit plugin; there is no client there. - `inject` and `dhpush` became `inject_voxy` and `inject_dh`. One was named for its verb and the other for its target, so neither said what it did. - Both status commands print one value per line instead of a single packed line. - The per-subcommand operator gates are gone./csgates at its root, and/csclientneeds no gate. - The client store is keyed to the WORLD, not the server address. A client used to file LOD under the host it connected to, so a world that changed address looked brand new and was downloaded again, while two unrelated worlds behind one address shared a store and overwrote each other. The server now mints a stable id per world and the client files under that. Stores from before 4.0 are left alone, listed by/csclient statusaspre-4.0 stores, and cleared by/csclient resetwhen you want the space back. Against a 3.x server the client falls back to the old host key, because that server has no id to give.Added
- `/csclient reset` returns the client to the state it was in before it first connected: the store for that server is deleted across every dimension, the injected-region bookkeeping is cleared, and the handshake runs again, all without a relog. Until now the only way out of a bad client store was to disconnect and delete the directory by hand. It cannot give you a clean slate on its own, and says so when it runs. Distant Horizons and Voxy keep their own databases, which Chunksmith does not touch by design, so a world that was regenerated server-side may still render its old terrain out of the renderer's copy. - `/csclient status` reports the client store: which server it is keyed to, the path, per-dimension region counts, transport, renderers, injection progress, and the settings in force. It also reports the renderer queue depth -- the numberthrottleLodDrainTobelow is measured against. Without it there was no way to tell whether that setting could ever engage on your machine. - `max-disk-mb` (client) caps what Chunksmith keeps on disk for a world, in megabytes. **Default 0, meaning no cap**, which is the behaviour every earlier release had: how much a client wrote was decided entirely by the server's index budget, a number the client cannot see and was never told. Nearest terrain is kept first. Declining regions does not put the client into a permanent re-download loop. The summary the two sides compare is an XOR aggregate, which is its own inverse, so declined regions fold back out of the server's number exactly and a capped client settles at "I have everything I intend to have". - `throttleLodDrainTo` (server) makes the LOD governor a barrier: stop dispatching entirely and let the renderer drain to that depth before resuming, rather than merely slowing down. **Default 0, meaning off, and it should stay off unless you have measured your own machine.** It is off by default because the measurement argues against it. On a four-core client with voxy the barrier ran about 11% SLOWER than the existing governor and did not change how often the run paused. It is here because alternating should beat competing on a machine with no cores to spare -- but that has not been demonstrated, and guessing the threshold is how a throttle ends up tuned for one box.Removed
- `/cslod` is gone, and a 4.x client does not register it under any name. See Compatibility. - TheSETTING_LIST/SETTING_SHOW/SETTING_SETrelay. A client command reads and writesconfig/chunksmith-lod.propertiesdirectly, so the server no longer has to ask the client on the player's behalf.Plugin (Paper / Spigot)
- `/cs lod status` and `/cs lod token <player>` work on the plugin too. Status is reported per WORLD rather than per dimension, because that is the shape a Bukkit server actually has: the mod keeps one save folder with its dimensions nested inside, Bukkit gives each world its own folder and therefore its own store. It answers from the console for the same reason. - There is no/csclienton the plugin and there will not be. That command runs on a client, and a Bukkit server does not have one. - The plugin serves the new world id, anchored to the primary world -- the onelevel-namenames and the one the others are derived from, so it is the folder whose replacement really does mean "this is a different world now". - Folia is no longer declared supported.folia-supportedis gone fromplugin.yml, so Folia will refuse to load the plugin rather than running it untested. This was announced in 3.3.0 and a major release is where it lands. Nothing changes for Paper or Spigot. The reasoning is not that Folia is broken -- it is that the Folia harness could not be kept working, and a platform nobody tests is an unverifiable claim, which is worse than an absent one. The region-scheduler code paths and thefolia-apicompile dependency are still in the tree and come out separately; removing them means moving three cells ontopaper-apiand unwinding the JVM-version workaroundsfolia-apiforces, which is its own change and does not belong in this one.Compatibility
CsLodProtocol.VERSIONgoes from 2 to 4, matching the major version from here on. There was never a protocol 3. 4.0.0 is a coordinated upgrade: move the server and the client together. The two protocols do not interoperate, so a mixed 3.x/4.x pair turns LOD off in BOTH directions -- the client will not fetch and the server will not serve. Everything else in Chunksmith keeps working; what stops arriving is the distant terrain. This is worth saying plainly because a launcher will offer 4.0.0 to anyone running 3.x, so a client can be updated into the mismatch without the server being touched by anyone. A 4.x client that lands on a 3.x server now says so in chat on join, rather than leaving you to work out why the horizon went empty. - 4.x server, 4.x client./csloddoes not exist on either side. - 3.x server, 4.x client. The client registers no/cslod, so the server's own still arrives in the command tree and/cslod setstill reaches this client's settings. LOD data does not transfer. - 4.x server, 3.x client./cslodanswers "update your cs client" and does nothing else. All of that lives in onelegacypackage and comes out in 5.x.4.0.0+1.20.x-pluginSep 13, 2026 Breaking. The command surface is reorganised by who can run a command and where it executes, and/cslodis retired. Protocol version moves to 4.Changed
- Commands are split by audience, not by feature./cslodgrouped things by subsystem, which put three client-side operations behind a server permission gate and gave the client's own state no readout at all. Server operator commands now live under the existing/csroot, which already carries the permission gate; everything a player runs for their own client lives under a new/csclient. | was | now | |---|---| |/cslod status|/cs lod status| |/cslod token <player>|/cs lod token <player>| |/cslod set|/csclient set| |/cslod inject|/csclient inject_voxy| |/cslod dhpush|/csclient inject_dh| - `/csclient` is a real client command, registered through Fabric'sClientCommandRegistrationCallbackand NeoForge/Forge'sRegisterClientCommandsEvent. It therefore works when connected to a server that has never heard of Chunksmith, which is exactly when you want to ask why no LODs are arriving. It does not exist on the Bukkit plugin; there is no client there. - `inject` and `dhpush` became `inject_voxy` and `inject_dh`. One was named for its verb and the other for its target, so neither said what it did. - Both status commands print one value per line instead of a single packed line. - The per-subcommand operator gates are gone./csgates at its root, and/csclientneeds no gate. - The client store is keyed to the WORLD, not the server address. A client used to file LOD under the host it connected to, so a world that changed address looked brand new and was downloaded again, while two unrelated worlds behind one address shared a store and overwrote each other. The server now mints a stable id per world and the client files under that. Stores from before 4.0 are left alone, listed by/csclient statusaspre-4.0 stores, and cleared by/csclient resetwhen you want the space back. Against a 3.x server the client falls back to the old host key, because that server has no id to give.Added
- `/csclient reset` returns the client to the state it was in before it first connected: the store for that server is deleted across every dimension, the injected-region bookkeeping is cleared, and the handshake runs again, all without a relog. Until now the only way out of a bad client store was to disconnect and delete the directory by hand. It cannot give you a clean slate on its own, and says so when it runs. Distant Horizons and Voxy keep their own databases, which Chunksmith does not touch by design, so a world that was regenerated server-side may still render its old terrain out of the renderer's copy. - `/csclient status` reports the client store: which server it is keyed to, the path, per-dimension region counts, transport, renderers, injection progress, and the settings in force. It also reports the renderer queue depth -- the numberthrottleLodDrainTobelow is measured against. Without it there was no way to tell whether that setting could ever engage on your machine. - `max-disk-mb` (client) caps what Chunksmith keeps on disk for a world, in megabytes. **Default 0, meaning no cap**, which is the behaviour every earlier release had: how much a client wrote was decided entirely by the server's index budget, a number the client cannot see and was never told. Nearest terrain is kept first. Declining regions does not put the client into a permanent re-download loop. The summary the two sides compare is an XOR aggregate, which is its own inverse, so declined regions fold back out of the server's number exactly and a capped client settles at "I have everything I intend to have". - `throttleLodDrainTo` (server) makes the LOD governor a barrier: stop dispatching entirely and let the renderer drain to that depth before resuming, rather than merely slowing down. **Default 0, meaning off, and it should stay off unless you have measured your own machine.** It is off by default because the measurement argues against it. On a four-core client with voxy the barrier ran about 11% SLOWER than the existing governor and did not change how often the run paused. It is here because alternating should beat competing on a machine with no cores to spare -- but that has not been demonstrated, and guessing the threshold is how a throttle ends up tuned for one box.Removed
- `/cslod` is gone, and a 4.x client does not register it under any name. See Compatibility. - TheSETTING_LIST/SETTING_SHOW/SETTING_SETrelay. A client command reads and writesconfig/chunksmith-lod.propertiesdirectly, so the server no longer has to ask the client on the player's behalf.Plugin (Paper / Spigot)
- `/cs lod status` and `/cs lod token <player>` work on the plugin too. Status is reported per WORLD rather than per dimension, because that is the shape a Bukkit server actually has: the mod keeps one save folder with its dimensions nested inside, Bukkit gives each world its own folder and therefore its own store. It answers from the console for the same reason. - There is no/csclienton the plugin and there will not be. That command runs on a client, and a Bukkit server does not have one. - The plugin serves the new world id, anchored to the primary world -- the onelevel-namenames and the one the others are derived from, so it is the folder whose replacement really does mean "this is a different world now". - Folia is no longer declared supported.folia-supportedis gone fromplugin.yml, so Folia will refuse to load the plugin rather than running it untested. This was announced in 3.3.0 and a major release is where it lands. Nothing changes for Paper or Spigot. The reasoning is not that Folia is broken -- it is that the Folia harness could not be kept working, and a platform nobody tests is an unverifiable claim, which is worse than an absent one. The region-scheduler code paths and thefolia-apicompile dependency are still in the tree and come out separately; removing them means moving three cells ontopaper-apiand unwinding the JVM-version workaroundsfolia-apiforces, which is its own change and does not belong in this one.Compatibility
CsLodProtocol.VERSIONgoes from 2 to 4, matching the major version from here on. There was never a protocol 3. 4.0.0 is a coordinated upgrade: move the server and the client together. The two protocols do not interoperate, so a mixed 3.x/4.x pair turns LOD off in BOTH directions -- the client will not fetch and the server will not serve. Everything else in Chunksmith keeps working; what stops arriving is the distant terrain. This is worth saying plainly because a launcher will offer 4.0.0 to anyone running 3.x, so a client can be updated into the mismatch without the server being touched by anyone. A 4.x client that lands on a 3.x server now says so in chat on join, rather than leaving you to work out why the horizon went empty. - 4.x server, 4.x client./csloddoes not exist on either side. - 3.x server, 4.x client. The client registers no/cslod, so the server's own still arrives in the command tree and/cslod setstill reaches this client's settings. LOD data does not transfer. - 4.x server, 3.x client./cslodanswers "update your cs client" and does nothing else. All of that lives in onelegacypackage and comes out in 5.x.3.18.0+26.x-pluginSep 5, 2026 Added
- World-enter pre-generation comes to Minecraft 1.20 through 1.21.11. The feature that shipped in 3.17.0 for 26.x only -- your single-player world pre-generates itself behind a progress screen before you start playing it, and the world (you included) is held still while it runs -- now works all the way down to 1.20. Same settings, same behaviour:worldEnterPregento turn it off,worldEnterPregenRadiusto size it. Covered: every 1.21 release, 1.21 through 1.21.11, and 1.20 through 1.20.6, on Fabric, NeoForge and Forge wherever each loader exists there. The gaps are the loaders' own, not the feature's -- Forge never shipped a 1.21.2 or 1.20.3 build, and Forge 1.21.9 is unsupported everywhere. Below 1.20.5, Chunksmith supplies the freeze itself. Minecraft gained a tick freeze in 1.20.3; before that there was nothing to borrow. Rather than leave those versions out, Chunksmith re-adds the same guards Minecraft's own freeze uses, so the world is held exactly as it is everywhere else -- and pre-generation keeps running behind the screen, which is the whole point. Otherwise very little changed to get here. The tick freeze is identical from 1.20.3 to the current snapshots, so holding the world needed no per-version work at all. What genuinely differs is small: 26.1 renamed the screen's render entry point and its centred-text call, 1.21.11 moved the time-advance game rule to a new package and changed how it is both read and written, and older Forge builds report a client tick differently. Those are the seams; the rest is one shared source.3.18.0+1.21.x-pluginSep 5, 2026 Added
- World-enter pre-generation comes to Minecraft 1.20 through 1.21.11. The feature that shipped in 3.17.0 for 26.x only -- your single-player world pre-generates itself behind a progress screen before you start playing it, and the world (you included) is held still while it runs -- now works all the way down to 1.20. Same settings, same behaviour:worldEnterPregento turn it off,worldEnterPregenRadiusto size it. Covered: every 1.21 release, 1.21 through 1.21.11, and 1.20 through 1.20.6, on Fabric, NeoForge and Forge wherever each loader exists there. The gaps are the loaders' own, not the feature's -- Forge never shipped a 1.21.2 or 1.20.3 build, and Forge 1.21.9 is unsupported everywhere. Below 1.20.5, Chunksmith supplies the freeze itself. Minecraft gained a tick freeze in 1.20.3; before that there was nothing to borrow. Rather than leave those versions out, Chunksmith re-adds the same guards Minecraft's own freeze uses, so the world is held exactly as it is everywhere else -- and pre-generation keeps running behind the screen, which is the whole point. Otherwise very little changed to get here. The tick freeze is identical from 1.20.3 to the current snapshots, so holding the world needed no per-version work at all. What genuinely differs is small: 26.1 renamed the screen's render entry point and its centred-text call, 1.21.11 moved the time-advance game rule to a new package and changed how it is both read and written, and older Forge builds report a client tick differently. Those are the seams; the rest is one shared source.3.18.0+1.20.x-pluginSep 5, 2026 Added
- World-enter pre-generation comes to Minecraft 1.20 through 1.21.11. The feature that shipped in 3.17.0 for 26.x only -- your single-player world pre-generates itself behind a progress screen before you start playing it, and the world (you included) is held still while it runs -- now works all the way down to 1.20. Same settings, same behaviour:worldEnterPregento turn it off,worldEnterPregenRadiusto size it. Covered: every 1.21 release, 1.21 through 1.21.11, and 1.20 through 1.20.6, on Fabric, NeoForge and Forge wherever each loader exists there. The gaps are the loaders' own, not the feature's -- Forge never shipped a 1.21.2 or 1.20.3 build, and Forge 1.21.9 is unsupported everywhere. Below 1.20.5, Chunksmith supplies the freeze itself. Minecraft gained a tick freeze in 1.20.3; before that there was nothing to borrow. Rather than leave those versions out, Chunksmith re-adds the same guards Minecraft's own freeze uses, so the world is held exactly as it is everywhere else -- and pre-generation keeps running behind the screen, which is the whole point. Otherwise very little changed to get here. The tick freeze is identical from 1.20.3 to the current snapshots, so holding the world needed no per-version work at all. What genuinely differs is small: 26.1 renamed the screen's render entry point and its centred-text call, 1.21.11 moved the time-advance game rule to a new package and changed how it is both read and written, and older Forge builds report a client tick differently. Those are the seams; the rest is one shared source.3.17.0+26.x-pluginSep 3, 2026 Added
- Your world can pre-generate itself before you start playing it. On a single-player world, Chunksmith now freezes the world on entry and pre-generates a 4096-block radius behind a progress screen, with a filling bar, a live estimate of the time remaining, and an Enter World Now button. Pressing it hands the world straight back to you -- it does not stop the run. Generation carries on in the background and yields to you from then on. Freezing does not make generation faster. It stops the world moving while it runs, so nothing ages, wanders off or starves while you wait. Once a world has finished, it never does this again. A completed run is recorded, so loading that world afterwards goes straight in. Leaving early with the button records nothing, so the next load simply continues where it stopped, and raisingworldEnterPregenRadiusasks for more world and starts it again. It works in a world created without cheats -- the settings are changed directly rather than through the command interpreter -- and everything it borrows is written down before it is touched, so a crash mid-freeze is put back on the next start rather than leaving your world frozen. On by default, MC 26+ on Fabric and NeoForge, single-player only. Turn it off withworldEnterPregen, or size it withworldEnterPregenRadius(default 4096). (mod_support #20)Fixed
- An IPv6 address can now actually be set with `/cs set`. Quoting it -- the obvious thing to try once the bare form is refused by Minecraft's command parser -- used to fail too: the quotes were arriving as part of the value, so"2001:db8::1"was rejected as malformed. Both routes were closed on a setting whose whole job is naming an address. Quoted values now work everywhere, on every loader and the plugin. (Bare IPv6 still cannot work -- Minecraft's parser stops at the first colon -- so quote it:/cs set lodBackchannelHost "2001:db8::1".) - Impossible addresses are refused instead of stored.256.1.1.1was accepted and kept: four numeric labels satisfy every ordinary hostname rule, so the setting held an address that could never resolve and the only symptom was a backchannel that quietly did not work. Also refused now:1.1.1.999,1.2.3,1.2.3.4.5,010.1.1.1(a leading zero means octal to some resolvers and decimal to others) andexample.123. Fully-qualified names ending in a dot, likeexample.com., are accepted -- they were being refused. - `0.0.0.0` is no longer accepted as the address to advertise to clients. It is exactly right forlodBackchannelBindAddress(listen on every interface) and meaningless forlodBackchannelHost: a client told to connect to0.0.0.0has been told nothing. Leave that key empty if you want each client to use the address it connected on. - A server whose hostname contains an underscore can now serve LOD over the backchannel.myserver_minecraft.example.combroke it in two places at once: the address was rejected outright by the config, solodBackchannelHostsilently reset to empty and could not be set at all; and the download itself failed on every region without ever falling back to the slower in-band channel, so it looked like the mod had simply stopped. Both are fixed -- such a host is now accepted, and the downloader resolves it and reports plainly in the log what it did. If a host genuinely cannot be reached, it now says so and falls back instead of going quiet. (mod_support #26, reported by arsenelupin0)Removed
- The standalone Chunksmith-Client mod is gone -- the project has been retired and its repository deleted -- so everything that referenced it has come out: thechunksmithclientincompatibility declarations from the Fabric and NeoForge manifests, and the startup check that warned when both were installed. If you still have an old Chunksmith-Client jar installed, remove it. Chunksmith no longer refuses to start alongside it; both mods register the samechunksmith:lodchannel, so having both is now a duplicate registration rather than a clear error message. Its multiplayer LOD job has been built into Chunksmith itself since 3.1.0 -- you lose nothing by deleting it.3.17.0+1.21.x-pluginSep 3, 2026 Added
- Your world can pre-generate itself before you start playing it. On a single-player world, Chunksmith now freezes the world on entry and pre-generates a 4096-block radius behind a progress screen, with a filling bar, a live estimate of the time remaining, and an Enter World Now button. Pressing it hands the world straight back to you -- it does not stop the run. Generation carries on in the background and yields to you from then on. Freezing does not make generation faster. It stops the world moving while it runs, so nothing ages, wanders off or starves while you wait. Once a world has finished, it never does this again. A completed run is recorded, so loading that world afterwards goes straight in. Leaving early with the button records nothing, so the next load simply continues where it stopped, and raisingworldEnterPregenRadiusasks for more world and starts it again. It works in a world created without cheats -- the settings are changed directly rather than through the command interpreter -- and everything it borrows is written down before it is touched, so a crash mid-freeze is put back on the next start rather than leaving your world frozen. On by default, MC 26+ on Fabric and NeoForge, single-player only. Turn it off withworldEnterPregen, or size it withworldEnterPregenRadius(default 4096). (mod_support #20)Fixed
- An IPv6 address can now actually be set with `/cs set`. Quoting it -- the obvious thing to try once the bare form is refused by Minecraft's command parser -- used to fail too: the quotes were arriving as part of the value, so"2001:db8::1"was rejected as malformed. Both routes were closed on a setting whose whole job is naming an address. Quoted values now work everywhere, on every loader and the plugin. (Bare IPv6 still cannot work -- Minecraft's parser stops at the first colon -- so quote it:/cs set lodBackchannelHost "2001:db8::1".) - Impossible addresses are refused instead of stored.256.1.1.1was accepted and kept: four numeric labels satisfy every ordinary hostname rule, so the setting held an address that could never resolve and the only symptom was a backchannel that quietly did not work. Also refused now:1.1.1.999,1.2.3,1.2.3.4.5,010.1.1.1(a leading zero means octal to some resolvers and decimal to others) andexample.123. Fully-qualified names ending in a dot, likeexample.com., are accepted -- they were being refused. - `0.0.0.0` is no longer accepted as the address to advertise to clients. It is exactly right forlodBackchannelBindAddress(listen on every interface) and meaningless forlodBackchannelHost: a client told to connect to0.0.0.0has been told nothing. Leave that key empty if you want each client to use the address it connected on. - A server whose hostname contains an underscore can now serve LOD over the backchannel.myserver_minecraft.example.combroke it in two places at once: the address was rejected outright by the config, solodBackchannelHostsilently reset to empty and could not be set at all; and the download itself failed on every region without ever falling back to the slower in-band channel, so it looked like the mod had simply stopped. Both are fixed -- such a host is now accepted, and the downloader resolves it and reports plainly in the log what it did. If a host genuinely cannot be reached, it now says so and falls back instead of going quiet. (mod_support #26, reported by arsenelupin0)Removed
- The standalone Chunksmith-Client mod is gone -- the project has been retired and its repository deleted -- so everything that referenced it has come out: thechunksmithclientincompatibility declarations from the Fabric and NeoForge manifests, and the startup check that warned when both were installed. If you still have an old Chunksmith-Client jar installed, remove it. Chunksmith no longer refuses to start alongside it; both mods register the samechunksmith:lodchannel, so having both is now a duplicate registration rather than a clear error message. Its multiplayer LOD job has been built into Chunksmith itself since 3.1.0 -- you lose nothing by deleting it.3.17.0+1.20.x-pluginSep 3, 2026 Added
- Your world can pre-generate itself before you start playing it. On a single-player world, Chunksmith now freezes the world on entry and pre-generates a 4096-block radius behind a progress screen, with a filling bar, a live estimate of the time remaining, and an Enter World Now button. Pressing it hands the world straight back to you -- it does not stop the run. Generation carries on in the background and yields to you from then on. Freezing does not make generation faster. It stops the world moving while it runs, so nothing ages, wanders off or starves while you wait. Once a world has finished, it never does this again. A completed run is recorded, so loading that world afterwards goes straight in. Leaving early with the button records nothing, so the next load simply continues where it stopped, and raisingworldEnterPregenRadiusasks for more world and starts it again. It works in a world created without cheats -- the settings are changed directly rather than through the command interpreter -- and everything it borrows is written down before it is touched, so a crash mid-freeze is put back on the next start rather than leaving your world frozen. On by default, MC 26+ on Fabric and NeoForge, single-player only. Turn it off withworldEnterPregen, or size it withworldEnterPregenRadius(default 4096). (mod_support #20)Fixed
- An IPv6 address can now actually be set with `/cs set`. Quoting it -- the obvious thing to try once the bare form is refused by Minecraft's command parser -- used to fail too: the quotes were arriving as part of the value, so"2001:db8::1"was rejected as malformed. Both routes were closed on a setting whose whole job is naming an address. Quoted values now work everywhere, on every loader and the plugin. (Bare IPv6 still cannot work -- Minecraft's parser stops at the first colon -- so quote it:/cs set lodBackchannelHost "2001:db8::1".) - Impossible addresses are refused instead of stored.256.1.1.1was accepted and kept: four numeric labels satisfy every ordinary hostname rule, so the setting held an address that could never resolve and the only symptom was a backchannel that quietly did not work. Also refused now:1.1.1.999,1.2.3,1.2.3.4.5,010.1.1.1(a leading zero means octal to some resolvers and decimal to others) andexample.123. Fully-qualified names ending in a dot, likeexample.com., are accepted -- they were being refused. - `0.0.0.0` is no longer accepted as the address to advertise to clients. It is exactly right forlodBackchannelBindAddress(listen on every interface) and meaningless forlodBackchannelHost: a client told to connect to0.0.0.0has been told nothing. Leave that key empty if you want each client to use the address it connected on. - A server whose hostname contains an underscore can now serve LOD over the backchannel.myserver_minecraft.example.combroke it in two places at once: the address was rejected outright by the config, solodBackchannelHostsilently reset to empty and could not be set at all; and the download itself failed on every region without ever falling back to the slower in-band channel, so it looked like the mod had simply stopped. Both are fixed -- such a host is now accepted, and the downloader resolves it and reports plainly in the log what it did. If a host genuinely cannot be reached, it now says so and falls back instead of going quiet. (mod_support #26, reported by arsenelupin0)Removed
- The standalone Chunksmith-Client mod is gone -- the project has been retired and its repository deleted -- so everything that referenced it has come out: thechunksmithclientincompatibility declarations from the Fabric and NeoForge manifests, and the startup check that warned when both were installed. If you still have an old Chunksmith-Client jar installed, remove it. Chunksmith no longer refuses to start alongside it; both mods register the samechunksmith:lodchannel, so having both is now a duplicate registration rather than a clear error message. Its multiplayer LOD job has been built into Chunksmith itself since 3.1.0 -- you lose nothing by deleting it.3.16.0+26.x-pluginSep 2, 2026 Changed
- The 2 GB ceiling on a LOD index answer is a setting now, instead of a number compiled into the jar. A server answers "here is what is in range" by listing regions nearest-first until it has named two gigabytes of them, and then stops. **That default has not changed, so upgrading changes no server's behaviour.** What changed is that you can raise it, and that the log now tells you it happened and why (mod_support #23). Why it matters: the budget does not scale with how far a client says it can draw, so it binds at the same distance on every answer. At a Distant Horizons radius of 8192, roughly 800 regions are in range at about 5 MB each -- a little over 4 GB -- and 2 GB allows about 395 of them. Terrain past that ring never arrives at all for a player standing still. At radius 4096 the same world needs about 1.5 GB and never reaches the ceiling, which is why this only ever looks like a problem at large radii. If your players run large render distances, raise `lodIndexBudgetMb` or set it to 0. 2048 is a bandwidth default, not a safety limit -- nothing downstream requires it. The index message has its own region cap, the backchannel serves over HTTP at the client's pace, and the in-band path drips fixed 24 KB slices four to a tick rather than sending a total. - The "capped at N of M regions" warning stopped promising that travelling would fix it. It only appears now when the region cap actually binds, it says whether moving will help, and it is logged once per player per ten minutes instead of once per scan.Added
-lodBackchannelBindAddress(lod-backchannel-bind-address) andlodBackchannelHost(lod-backchannel-host): the backchannel's address is settable now, not only its port (mod_support #24). Two keys, because they answer two different questions. The bind address is where the socket LISTENS, and it exists because the backchannel followed whatever the game bound: a host that setsserver-ipto127.0.0.1, which is normal behind a proxy, got a backchannel on loopback that no player could reach, and the only symptom was every client quietly falling back to the slow in-band channel while the log saidlistening on /127.0.0.1:25566. Set0.0.0.0to listen everywhere regardless. Binding everywhere does not finish the job, though, which is why there is a second key. The client has always worked out where to fetch from by reusing the address it connected to, and that is a better answer than anything the server can guess -- it is an address that demonstrably reaches this server from where that player is sitting. It is wrong in one shape: the backchannel reachable at a different address from the game port.lodBackchannelHostis how a server says so. Both rebind and re-advertise on the spot, the waylodBackchannelPortdoes. An address key that waited for a restart would be no use to the operator it is for. Set either tononeto clear it. No protocol version change, and no upgrade order to worry about. The host rides after the last field a 3.15.0 client reads, so an old client never sees it, and a 3.16.0 client talking to an old server just finds nothing there and carries on using the connect address. -lodIndexBudgetMb(lod-index-budget-mbin the plugin'sconfig.yml): the ceiling in megabytes on how much LOD one answer may offer a client. Default `2048`, which is exactly what the old hard-coded constant was, so nothing moves on upgrade.0means no limit. Settable live with/cs set lodIndexBudgetMb. See the note above on when to raise it -- roughly, a Distant Horizons radius of 4096 fits inside 2 GB and a radius of 8192 does not.Note
- The budget is what limits a client's LOD download, and there is deliberately no client-side disk limit: the server admin sets the ceiling, and 2048 MB per dimension is what a client accumulates by default. RaisinglodIndexBudgetMbraises that too -- a server set to0hands a radius-8192 client roughly 4 GB per dimension. Worth knowing before setting it.3.16.0+1.21.x-pluginSep 2, 2026 Changed
- The 2 GB ceiling on a LOD index answer is a setting now, instead of a number compiled into the jar. A server answers "here is what is in range" by listing regions nearest-first until it has named two gigabytes of them, and then stops. **That default has not changed, so upgrading changes no server's behaviour.** What changed is that you can raise it, and that the log now tells you it happened and why (mod_support #23). Why it matters: the budget does not scale with how far a client says it can draw, so it binds at the same distance on every answer. At a Distant Horizons radius of 8192, roughly 800 regions are in range at about 5 MB each -- a little over 4 GB -- and 2 GB allows about 395 of them. Terrain past that ring never arrives at all for a player standing still. At radius 4096 the same world needs about 1.5 GB and never reaches the ceiling, which is why this only ever looks like a problem at large radii. If your players run large render distances, raise `lodIndexBudgetMb` or set it to 0. 2048 is a bandwidth default, not a safety limit -- nothing downstream requires it. The index message has its own region cap, the backchannel serves over HTTP at the client's pace, and the in-band path drips fixed 24 KB slices four to a tick rather than sending a total. - The "capped at N of M regions" warning stopped promising that travelling would fix it. It only appears now when the region cap actually binds, it says whether moving will help, and it is logged once per player per ten minutes instead of once per scan.Added
-lodBackchannelBindAddress(lod-backchannel-bind-address) andlodBackchannelHost(lod-backchannel-host): the backchannel's address is settable now, not only its port (mod_support #24). Two keys, because they answer two different questions. The bind address is where the socket LISTENS, and it exists because the backchannel followed whatever the game bound: a host that setsserver-ipto127.0.0.1, which is normal behind a proxy, got a backchannel on loopback that no player could reach, and the only symptom was every client quietly falling back to the slow in-band channel while the log saidlistening on /127.0.0.1:25566. Set0.0.0.0to listen everywhere regardless. Binding everywhere does not finish the job, though, which is why there is a second key. The client has always worked out where to fetch from by reusing the address it connected to, and that is a better answer than anything the server can guess -- it is an address that demonstrably reaches this server from where that player is sitting. It is wrong in one shape: the backchannel reachable at a different address from the game port.lodBackchannelHostis how a server says so. Both rebind and re-advertise on the spot, the waylodBackchannelPortdoes. An address key that waited for a restart would be no use to the operator it is for. Set either tononeto clear it. No protocol version change, and no upgrade order to worry about. The host rides after the last field a 3.15.0 client reads, so an old client never sees it, and a 3.16.0 client talking to an old server just finds nothing there and carries on using the connect address. -lodIndexBudgetMb(lod-index-budget-mbin the plugin'sconfig.yml): the ceiling in megabytes on how much LOD one answer may offer a client. Default `2048`, which is exactly what the old hard-coded constant was, so nothing moves on upgrade.0means no limit. Settable live with/cs set lodIndexBudgetMb. See the note above on when to raise it -- roughly, a Distant Horizons radius of 4096 fits inside 2 GB and a radius of 8192 does not.Note
- The budget is what limits a client's LOD download, and there is deliberately no client-side disk limit: the server admin sets the ceiling, and 2048 MB per dimension is what a client accumulates by default. RaisinglodIndexBudgetMbraises that too -- a server set to0hands a radius-8192 client roughly 4 GB per dimension. Worth knowing before setting it.3.16.0+1.20.x-pluginSep 2, 2026 Changed
- The 2 GB ceiling on a LOD index answer is a setting now, instead of a number compiled into the jar. A server answers "here is what is in range" by listing regions nearest-first until it has named two gigabytes of them, and then stops. **That default has not changed, so upgrading changes no server's behaviour.** What changed is that you can raise it, and that the log now tells you it happened and why (mod_support #23). Why it matters: the budget does not scale with how far a client says it can draw, so it binds at the same distance on every answer. At a Distant Horizons radius of 8192, roughly 800 regions are in range at about 5 MB each -- a little over 4 GB -- and 2 GB allows about 395 of them. Terrain past that ring never arrives at all for a player standing still. At radius 4096 the same world needs about 1.5 GB and never reaches the ceiling, which is why this only ever looks like a problem at large radii. If your players run large render distances, raise `lodIndexBudgetMb` or set it to 0. 2048 is a bandwidth default, not a safety limit -- nothing downstream requires it. The index message has its own region cap, the backchannel serves over HTTP at the client's pace, and the in-band path drips fixed 24 KB slices four to a tick rather than sending a total. - The "capped at N of M regions" warning stopped promising that travelling would fix it. It only appears now when the region cap actually binds, it says whether moving will help, and it is logged once per player per ten minutes instead of once per scan.Added
-lodBackchannelBindAddress(lod-backchannel-bind-address) andlodBackchannelHost(lod-backchannel-host): the backchannel's address is settable now, not only its port (mod_support #24). Two keys, because they answer two different questions. The bind address is where the socket LISTENS, and it exists because the backchannel followed whatever the game bound: a host that setsserver-ipto127.0.0.1, which is normal behind a proxy, got a backchannel on loopback that no player could reach, and the only symptom was every client quietly falling back to the slow in-band channel while the log saidlistening on /127.0.0.1:25566. Set0.0.0.0to listen everywhere regardless. Binding everywhere does not finish the job, though, which is why there is a second key. The client has always worked out where to fetch from by reusing the address it connected to, and that is a better answer than anything the server can guess -- it is an address that demonstrably reaches this server from where that player is sitting. It is wrong in one shape: the backchannel reachable at a different address from the game port.lodBackchannelHostis how a server says so. Both rebind and re-advertise on the spot, the waylodBackchannelPortdoes. An address key that waited for a restart would be no use to the operator it is for. Set either tononeto clear it. No protocol version change, and no upgrade order to worry about. The host rides after the last field a 3.15.0 client reads, so an old client never sees it, and a 3.16.0 client talking to an old server just finds nothing there and carries on using the connect address. -lodIndexBudgetMb(lod-index-budget-mbin the plugin'sconfig.yml): the ceiling in megabytes on how much LOD one answer may offer a client. Default `2048`, which is exactly what the old hard-coded constant was, so nothing moves on upgrade.0means no limit. Settable live with/cs set lodIndexBudgetMb. See the note above on when to raise it -- roughly, a Distant Horizons radius of 4096 fits inside 2 GB and a radius of 8192 does not.Note
- The budget is what limits a client's LOD download, and there is deliberately no client-side disk limit: the server admin sets the ceiling, and 2048 MB per dimension is what a client accumulates by default. RaisinglodIndexBudgetMbraises that too -- a server set to0hands a radius-8192 client roughly 4 GB per dimension. Worth knowing before setting it.3.15.0+1.20.x-pluginAug 27, 2026 Added
- The Bukkit/Paper plugin can now send LOD to players. Until today it generated the data and had no way to deliver it, so anyone running the plugin got a store on disk and players who saw nothing -- and no combination of client mods could change that (mod_support #18). The awkward part of that story: every piece of the machinery had been shipping inside the plugin jar since 3.2.0, because it lives in the shared code. The wire format, the token store, the HTTP backchannel -- all present, all unreachable, because nothing registered a channel or started the server. This release is the connection that was missing. Nothing to configure. If LOD is on, the plugin registers the channel, opens the backchannel port and answers clients exactly as the mod does.lod-backchannel-portinconfig.ymlworks the same way it does on the mod, and the startup line tells you which port your players need to reach. One honest limitation: the mod falls back to streaming LOD down the game connection when the backchannel port is unreachable. The plugin does not do that yet -- if the port is blocked, players get nothing rather than something slow. The log says so plainly instead of going quiet, and the fix is to open the port or set one your host allows. - A client on a Paper server now actually receives LOD -- measured, not inferred. The first cut of the above answered the client's hello and stopped there, which looks exactly like working: the server logs the greeting, opens the port, mints a download credential, and serves nothing at all, because the client is waiting on a region index that never comes. Two things were missing. The index and sync requests are answered. The hello is only the introduction. The client then asks what is near it, compares that against what it already has, and downloads the difference -- and it asks again every few minutes as it travels. The plugin answers both now, off the main thread, filtered to the draw distance the client actually reported. Bukkit is told to accept the reply. A Bukkit server only delivers a plugin message on a channel the client announced withminecraft:register, and drops everything else without a word -- no exception, no log line, no packet. A modern Fabric client never makes that announcement, so the server could hear the client perfectly while the client heard nothing back. The plugin now registers the channel for a player who has already spoken to it on that channel, which is proof enough that they speak it. Measured on Paper 26.2 with a Fabric client and voxy: 16 regions, 27 MB, 5928 chunks handed to the renderer. The symptom this replaces was0 files, 0 byteswith a live token beside it.Changed
- The plugin's startup message no longer says it cannot serve LOD, because it can. - One region scan, shared by every platform (CsLodIndexScan). "Which regions can this player see?" has to give the same answer on a Fabric server and a Paper server, and a second copy of that rule would have drifted with nothing to catch it -- the symptom being a client that fetches the wrong regions on one platform only. The loaders and the plugin now call the same code, and sixteen tests pin the range, settle, ordering and cap behaviour.3.15.0+26.x-pluginAug 27, 2026 Added
- The Bukkit/Paper plugin can now send LOD to players. Until today it generated the data and had no way to deliver it, so anyone running the plugin got a store on disk and players who saw nothing -- and no combination of client mods could change that (mod_support #18). The awkward part of that story: every piece of the machinery had been shipping inside the plugin jar since 3.2.0, because it lives in the shared code. The wire format, the token store, the HTTP backchannel -- all present, all unreachable, because nothing registered a channel or started the server. This release is the connection that was missing. Nothing to configure. If LOD is on, the plugin registers the channel, opens the backchannel port and answers clients exactly as the mod does.lod-backchannel-portinconfig.ymlworks the same way it does on the mod, and the startup line tells you which port your players need to reach. One honest limitation: the mod falls back to streaming LOD down the game connection when the backchannel port is unreachable. The plugin does not do that yet -- if the port is blocked, players get nothing rather than something slow. The log says so plainly instead of going quiet, and the fix is to open the port or set one your host allows. - A client on a Paper server now actually receives LOD -- measured, not inferred. The first cut of the above answered the client's hello and stopped there, which looks exactly like working: the server logs the greeting, opens the port, mints a download credential, and serves nothing at all, because the client is waiting on a region index that never comes. Two things were missing. The index and sync requests are answered. The hello is only the introduction. The client then asks what is near it, compares that against what it already has, and downloads the difference -- and it asks again every few minutes as it travels. The plugin answers both now, off the main thread, filtered to the draw distance the client actually reported. Bukkit is told to accept the reply. A Bukkit server only delivers a plugin message on a channel the client announced withminecraft:register, and drops everything else without a word -- no exception, no log line, no packet. A modern Fabric client never makes that announcement, so the server could hear the client perfectly while the client heard nothing back. The plugin now registers the channel for a player who has already spoken to it on that channel, which is proof enough that they speak it. Measured on Paper 26.2 with a Fabric client and voxy: 16 regions, 27 MB, 5928 chunks handed to the renderer. The symptom this replaces was0 files, 0 byteswith a live token beside it.Changed
- The plugin's startup message no longer says it cannot serve LOD, because it can. - One region scan, shared by every platform (CsLodIndexScan). "Which regions can this player see?" has to give the same answer on a Fabric server and a Paper server, and a second copy of that rule would have drifted with nothing to catch it -- the symptom being a client that fetches the wrong regions on one platform only. The loaders and the plugin now call the same code, and sixteen tests pin the range, settle, ordering and cap behaviour.3.15.0+1.21.x-pluginAug 27, 2026 Added
- The Bukkit/Paper plugin can now send LOD to players. Until today it generated the data and had no way to deliver it, so anyone running the plugin got a store on disk and players who saw nothing -- and no combination of client mods could change that (mod_support #18). The awkward part of that story: every piece of the machinery had been shipping inside the plugin jar since 3.2.0, because it lives in the shared code. The wire format, the token store, the HTTP backchannel -- all present, all unreachable, because nothing registered a channel or started the server. This release is the connection that was missing. Nothing to configure. If LOD is on, the plugin registers the channel, opens the backchannel port and answers clients exactly as the mod does.lod-backchannel-portinconfig.ymlworks the same way it does on the mod, and the startup line tells you which port your players need to reach. One honest limitation: the mod falls back to streaming LOD down the game connection when the backchannel port is unreachable. The plugin does not do that yet -- if the port is blocked, players get nothing rather than something slow. The log says so plainly instead of going quiet, and the fix is to open the port or set one your host allows. - A client on a Paper server now actually receives LOD -- measured, not inferred. The first cut of the above answered the client's hello and stopped there, which looks exactly like working: the server logs the greeting, opens the port, mints a download credential, and serves nothing at all, because the client is waiting on a region index that never comes. Two things were missing. The index and sync requests are answered. The hello is only the introduction. The client then asks what is near it, compares that against what it already has, and downloads the difference -- and it asks again every few minutes as it travels. The plugin answers both now, off the main thread, filtered to the draw distance the client actually reported. Bukkit is told to accept the reply. A Bukkit server only delivers a plugin message on a channel the client announced withminecraft:register, and drops everything else without a word -- no exception, no log line, no packet. A modern Fabric client never makes that announcement, so the server could hear the client perfectly while the client heard nothing back. The plugin now registers the channel for a player who has already spoken to it on that channel, which is proof enough that they speak it. Measured on Paper 26.2 with a Fabric client and voxy: 16 regions, 27 MB, 5928 chunks handed to the renderer. The symptom this replaces was0 files, 0 byteswith a live token beside it.Changed
- The plugin's startup message no longer says it cannot serve LOD, because it can. - One region scan, shared by every platform (CsLodIndexScan). "Which regions can this player see?" has to give the same answer on a Fabric server and a Paper server, and a second copy of that rule would have drifted with nothing to catch it -- the symptom being a client that fetches the wrong regions on one platform only. The loaders and the plugin now call the same code, and sixteen tests pin the range, settle, ordering and cap behaviour.
Similar projects
Plugin →VeinMiner
Mine the whole vein on mining a single ore/block. Make the tedious mining experience to something satisfying and fun! FTB Ultimine alternative
99.3MSueta
Simple Voice Chat
A working voice chat in Minecraft!
76.8MSueta
Let Me Despawn
Improves performance by tweaking mob despawn rules. Say bye to pesky unintentional persistent mobs.
25MSueta
Chunky
Pre-generates chunks, quickly and efficiently
18.4MSueta
VeinMiner Enchantment
Veinminer Addon - Adds vineminer enchantment to enchanting tables. Only tools with the enchantment can veinmine
18MSueta
JourneyMap
Real-time map used for mapping in-game or your browser as you explore.
14.7MSueta