
Replenish++
Auto-replant crops on Paper/Purpur servers, inspired by Hypixel SkyBlock's Replenish enchantment. Break a crop and it replants itself. Supports wheat, carrots, potatoes, nether wart, cocoa and beetroot, with direct pickup and lag-friendly replanting.
Tags
Creators
Details
7.0.1-26.3
Compatibility
Changes
ReplenishPlusPlus v7.0.1 - "Rebuilt From the Build Up"
Release Date: 2026-10-05
A big maintenance release rather than a feature drop: the build system moved from Maven to Gradle, the update checker learned to read Modrinth first, dev mode's growth feature was redesigned around events, and Teleport Pads got a hardening pass that closes every hole found in a full adversarial audit. The harvest pipeline itself behaves the same as 7.0.0 for players; if you never touch pads or dev mode, this is a drop-in jar swap.
⚠️ Before You Upgrade
- Changed behavior: update checks now query Modrinth first and only fall back to GitHub. In dev mode, instant growth now only affects crops a dev player places themselves, and the inventory clear no longer runs while you're dead or spectating. Placing a pad on a spot that already holds one is now refused with a message instead of misbehaving.
🎵 What's New
- Modrinth update checks: the startup check now asks Modrinth for the newest release matching your exact Minecraft version (or anything on the same 26.3 line, so a 26.3.2 server still matches versions tagged just 26.3). If Modrinth is unreachable it quietly falls back to GitHub releases, and in-game download links point at the Modrinth page of the version it found.
- Dev-mode instant growth, redesigned (work in progress, ops only): crops a dev player places pop in fully grown, and any crop that vanilla grows within 12 blocks of a dev player snaps to max age the moment it grows. Farmer-villager farms far away stay vanilla until a dev player walks near, which is the honest tradeoff for the old scanner being removed.
- Dev-mode no-trample: a new seventh dev toggle. Farmland can't be trampled back to dirt while dev is on, so sprint-jumping your own farm and mobs wandering through it stop punching crops out of the ground. Other players' trampling stays vanilla.
- Safer pad arrivals: warping now checks the two blocks above the destination pad and refuses with a clear message if your feet or head would land inside lava, fire, sweet berry bush, a wither rose, or a low ceiling. Destinations in unloaded chunks teleport straight through instead of the old phantom-air read, which could wipe a perfectly good link.
- Honest pad placement: putting a pad where one already exists is refused with "There's already a pad here". If a place fails for any reason, the stuck end-portal-frame block is removed and your pad item is refunded, instead of the old behavior that sometimes said "Pad placed" and lied.
- Optional nightly builds: CI can now publish a rolling
nightlypre-release with commit changelog, SHA-256/512 hashes, and a dependency table. Off by default; flipreleaseDevBuilds=trueingradle.propertiesif you want it.
⚡ Performance
- Re-benchmarked honestly: one player farming flat-out (20 crops/sec, dev mode on) costs about 2% of one server thread on a default JVM launch: 1.98% measured over a 5-minute spark capture on Paper 26.3-151, Ryzen 5 5600, 2 GB heap, TPS pinned at 20.00 with 0.92ms median MSPT. The full capture is committed at
benchmark/default-jvm.sparkprofile. The old 0.16% headline was a tuned-JVM best case that most servers will never see; the new BENCHMARK.md explains the per-boot spread and quotes the number real servers get. Scaling is linear in flat-out farmers: roughly 20% of a thread at 10, ~50% at 25, ~100% at 50. - Growth scanning eliminated: the old periodic block scan (measured at 1.02% of the server thread on dense auto-farms) is gone entirely; growth is now pure events (
BlockPlaceEvent+BlockGrowEvent), and the dev tick task does nothing but the once-per-second inventory scan. - Pad saves debounced and atomic: GUI-click bursts write
pads.ymlat most once per tick through a temp file plus atomic move, and shutdown force-writes any pending save so nothing is lost. Previously every click hit the disk. - Queue memo widened: the chunk-loaded cache serving replant decisions went from 16 to 64 slots, so large multi-chunk farms stop evicting entries every replant.
- Cocoa replant check narrowed: the queue now re-validates the specific facing it's about to plant against its own jungle log, so a log broken between decide and replant can no longer produce a popping crop (also closes a cocoa-minting dupe).
🛠️ Fixes & Tweaks
- Update check hardening: response bodies are capped at 2 MiB, JSON is parsed structure-aware (text that merely looks like a version inside other fields can never win), and every candidate version string must match a safe character set before it can reach a click URL or chat, closing a Modrinth-side injection vector. Failed checks complete as failed instead of hanging as pending, shutdown can't fork a second HTTP chain, and an unparseable local version now logs "status unknown" instead of a misleading verdict.
- Dev-mode harvest counter is now permission-gated: only the console and players actually in dev mode can start, stop, or toggle the tracking window; a stranger typing
/spark profilercommands does nothing. Stopping always works, even afterharvest-counterwas switched off and reloaded, and re-runningstartmid-window no longer extends a timed window. The--timeout 60flag form works, absurd timeout values clamp instead of crashing, and command-blocker plugins cancelling/sparkcan't puppet the counter. - Dev-mode growth edge cases: enabling dev near the bedrock floor or build limit no longer throws (the sweep clamps to world height and only touches loaded chunks), and any inventory-clear pass that actually deleted something now invalidates the seed cache, so the next break can't read a stale seed slot.
- Pad persistence: a corrupted
pads.ymlnow logs a loud warning instead of silently loading zero pads and overwriting your data on the next change, and a leftoverpads.yml.tmpfrom an interrupted save is swept at startup. - Pad orphan self-heal: when a chunk loads, registered pads whose frame block was destroyed externally (like by
/setblockor a world edit) are removed in one batched pass, links pointing at them are cleared, and their slot in the 56-per-player cap is freed. Persistent ghost display entities are still wiped on every chunk sync. - Pad rename safety: a rename prompt that outlived its pad (you closed the menu, the pad got picked up, someone else placed a new one there) can no longer rename the wrong pad; ownership is re-checked at apply time.
- Pad menu spam: menu clicks are throttled to one action per player per second, so GUI spam can't churn the registry or respawn icon displays, and picking a pad up cancels any pending rename prompt.
- Pad world names: world names containing semicolons now round-trip through
pads.ymlcorrectly. /rpp toggle global: theconfig.ymlwrite is atomic (temp file plus move), and if it fails you get an explicit "couldn't be written" message plus a severe log instead of the old silent swallow that reset your choice on restart./rpp reload: when the file was broken and previous settings stayed live, the output now says "Nothing was applied" instead of claiming your changes went live.- Backward compatibility:
/rppand/replenishaliases still work, all 7.0.0 config and pads files load unchanged, and custom edits toen_us.ymlare kept (missing or broken keys silently fall back to the built-in English text).
📚 Docs
- BENCHMARK.md: rewritten from scratch: honest ~2% headline, a per-slice breakdown of where the cost goes, player-count scaling, and a capture-conditions section explaining why JVM launch flags swing the reading between 0.16% and 2%.
- benchmark/default-jvm.sparkprofile: the offline spark profile of the benchmark run, committed so anyone can verify the numbers.
- DEV_MODE.md: updated for the event-driven growth redesign,
no-trample, the gated harvest counter, and the packaged testing world (devmode/Server Testing.7z, farm at -75 5 -91) that reproduces the benchmark. - AGENTS.md: rewritten for the Gradle build, Modrinth checking, the removal of the crop-drop fallback, and a new Conventional Commits rule.
- README.md: Modrinth listed as the recommended install source, a "coming from Replenish 6.x?" warning, and the
checkUpdatescomment now describes both sources. - THIRD_PARTY_NOTICES.md: Gson (Apache 2.0) added for the Modrinth JSON parsing.
Full Changelog: https://github.com/Mitra-88/ReplenishPlusPlus/compare/7.0.0...7.0.1
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:9rWJrVZX:ebpwTIIS"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:9rWJrVZX:ebpwTIIS"
}
