Advanced TreeCapitator
1.5.2Advanced TreeCapitator enables fast tree felling on Paper 1.21. Sneak with an axe to chop entire trees, with configurable durability loss, world restrictions, and a reload command.
1.5.2latestAdvanced TreeCapitator 1.5.2Jun 7, 2026 [1.5.2] — 2025-06-07
Fixed — Bug Fixes
| # | Bug | Details | |---|-----|---------| | 1 | `api-version: '1.20'` in plugin.yml while compiling against Paper 1.21.4 API | The plugin declaredapi-version: '1.20', which allowed Paper to load it on 1.20.x servers.Particle.BLOCKwas renamed fromParticle.BLOCK_CRACKin Paper 1.21+; running on a 1.20 server would produce aNoSuchFieldErrorat class-loading time, crashing the plugin on enable. Fixed by raisingapi-versionto'1.21', which prevents the plugin from loading on incompatible servers and eliminates the runtime risk. | | 2 | `Sound.BLOCK_WOOD_BREAK` played for Nether stems and Bamboo blocks | All felled trees used the overworld wood-break sound (Sound.BLOCK_WOOD_BREAK) regardless of log type. In vanilla Minecraft, Nether stems (CRIMSON_STEM,WARPED_STEM) useblock.nether_wood.breakand Bamboo blocks useblock.bamboo_wood.break. Playing the wrong sound for these types is audibly incorrect and breaks immersion. Fixed by adding afellSound(Material)helper that dispatches toSound.BLOCK_NETHER_WOOD_BREAKfor Nether-type stems,Sound.BLOCK_BAMBOO_WOOD_BREAKfor Bamboo, andSound.BLOCK_WOOD_BREAKfor all overworld logs. Detection uses a name-prefix check so future variants are covered automatically. | | 3 | `cfg` field in `TreeCapitatorTask` captured at construction time, not at execution time |TreeCapitatorTaskstored theConfiginstance as a field initializer (private final Config cfg = getInstance().getPluginConfig()), which ran whennew TreeCapitatorTask(...)was called insideonBlockBreak. Since the task executes one tick later viarunTask(), a/atc reloadissued in that one-tick window would leave the task using a stale pre-reloadConfigsnapshot — the new configuration was silently ignored for that fell. Fixed by removing the field and fetching the config fresh at the top ofdoFell()viaplugin.getPluginConfig(), always reflecting the most recent reload. |1.5.1Advanced TreeCapitator 1.5.1Jun 2, 2026 [1.5.1] — 2025-06-03
Fixed — Bug Fixes
| # | Bug | Details | |---|-----|---------| | 1 | BFS adds out-of-range blocks to the break-set before checking distance caps | InTreeFinder.findLogs(),logsToBreak.add(current)ran unconditionally at the start of the loop body — before thedist > MAX_DISTANCEandhdist > maxHorizontalDistancechecks. A block at the outer edge of the BFS scan (e.g.hdist == maxHorizontalDistance + 1) was enqueued as a neighbour of an in-range block, then added to the break-set when dequeued, even though the check immediately after prevented its own neighbours from being explored. Result: logs slightly beyondmax-horizontal-distancewere still felled, making the config option unreliable at the boundary. Fixed by moving both distance checks before thelogsToBreak.add()call. | | 2 | `cooldownMs` loaded with `(int)` cast before clamping — silent integer overflow |cooldownMs = clamp((int) cfg.getLong("cooldown-ms", 200L), 0, 60_000)cast the raw YAMLlongtointbefore clamping. Any value larger thanInteger.MAX_VALUE(2 147 483 647) in the config file overflowed to a negative number, whichclamp()then floored to0, silently disabling the per-player cooldown entirely. Fixed by clamping on thelongvalue first:(int) Math.min(Math.max(...), 60_000L). Field type also changed fromlongtointfor consistency;getCooldownMs()now returnsint. | | 3 | Hardcoded `MAX_DISTANCE = 30` truncated tall Jungle trees | The 3-D Manhattan BFS safety cap was hardcoded asprivate static final int MAX_DISTANCE = 30inTreeFinder. Jungle trees can reach 30+ blocks tall; a player chopping from a non-base position (reducing the vertical budget) or a tree with any horizontal spread would have its top logs excluded from the fell silently. Exposed asmax-distanceinconfig.ymlwith a default of 50. Configurable range: 10 – 200. | | 4 | `getBreakingTrees()` exposed the internal mutable anti-recursion set | The public gettergetBreakingTrees()returned the rawConcurrentHashMap.newKeySet()directly. External code (another plugin or a misbehaving task) could call.add(uuid)to permanently lock a player out of tree felling, or.clear()to disable the anti-recursion guard entirely mid-fell. Fixed by removing the public getter and replacing it with the package-private helpersmarkFelling(UUID)andunmarkFelling(UUID), used only byTreeCapitatorTask. | | 5 | `isOverworldLog()` did not cover stripped-log variants — `require-leaves` bypass | The method used a hard-coded switch that only listed nine non-stripped log variants (e.g.OAK_LOG). If a server operator added a stripped variant (e.g.STRIPPED_OAK_LOG) tolog-typesin config.yml,isOverworldLog()returnedfalse(default case), and therequire-leavescheck was silently skipped. A player-built wall of stripped logs could be felled with a single swing even withrequire-leaves: true. Fixed by replacing the switch with a Material name-suffix check: any material ending in_LOGor_WOODreturnstrue. Nether stems (CRIMSON_STEM,WARPED_STEM), hyphae, andBAMBOO_BLOCKend in_STEM,_HYPHAE, or_BLOCKand continue to returnfalsecorrectly. | | 6 | Leaf durability hits silently discarded by integer truncation |leafBreaks / safeRatioused integer division, dropping the remainder entirely. With the defaultleaf-durability-ratio: 10, breaking fewer than 10 leaves contributed exactly 0 durability hits — so a small tree with leaves produced no leaf-based durability cost at all. Fixed by resolving the remainder probabilistically:remainder / safeRatiogives the probability of one additional hit, resolved with aThreadLocalRandomroll, consistent with the existing fractional-hit logic incalcDamage(). | | 7 | `TreeCapitatorEvent` API lacked `@NotNull` annotations | All three public getters (getPlayer(),getLogs(),getLeaves()) and the constructor parameters had no nullability contract. Third-party plugins integrating the API had no IDE or static-analysis guidance about null safety. Added@NotNull(fromorg.jetbrains:annotations:24.1.0) to all public constructor parameters and return types.org.jetbrains:annotationsadded topom.xmlas aprovideddependency. |1.5.0Advanced TreeCapitator 1.5.0May 21, 2026 [1.5.0] — 2025-05-21
Fixed — Bug Fixes
| # | Bug | Details | |---|-----|---------| | 1 | `Enchantment.getByKey()` silently returned `null` on Paper 1.21+ |DurabilityHandler.getUnbreakingLevel()used the deprecatedEnchantment.getByKey(NamespacedKey.minecraft("unbreaking"))lookup. On Paper 1.21+ this returnsnullif the registry isn't fully initialised, causing the method to always return0— i.e. Unbreaking was completely ignored and axes lost durability as if they had no enchantment. Fixed by using the stable constantEnchantment.UNBREAKING. | | 2 | Player offline during 1-tick scheduling delay caused unsafe state |TreeCapitatorTaskran 1 tick afterBlockBreakEvent. If the player disconnected in that window,player.getInventory()andplayer.playSound()were called on an invalid player. Fixed by adding anisOnline()guard at the top ofdoFell(). | | 3 | `disabledPlayers` set accumulated stale UUIDs indefinitely | When a player used/atc toggleto disable felling and then quit the server, their UUID was never removed fromdisabledPlayers. On re-join, felling remained disabled without the player having toggled it again. Fixed by handlingPlayerQuitEventand clearing all per-player state (disabledPlayers,cooldowns,breakingTrees). | | 4 | Cooldown was consumed even when `TreeCapitatorEvent` was cancelled | The cooldown timestamp was written inonBlockBreak()before the task ran. If a third-party plugin cancelledTreeCapitatorEvent(e.g. an economy plugin denying the action), the player was still forced to wait out the full cooldown. Fixed by refunding (removing) the cooldown entry insidedoFell()immediately after a cancellation is detected. | | 5 | `TreeCapitatorEvent` Javadoc incorrectly stated "excludes origin" | The@param logsJavadoc said the set excluded the origin block. In realitytrimmedLogsalways includes the origin. Third-party plugins that relied on the documented behaviour miscounted tree size and produced incorrect reward calculations. Corrected the Javadoc; no runtime behaviour changed. | | 6 | Unbreaking durability calculation was deterministic (did not match vanilla) |calcDamage()multiplied hits by the expected-value probability1/(level+1), producing the same result every time. Vanilla Minecraft rolls each hit independently: each has a1/(level+1)chance to deal damage. With Unbreaking III chopping 20 logs, the plugin always applied exactly 5 durability; vanilla would apply anywhere from 0 to 20. Fixed by replacing the formula with a per-hitThreadLocalRandomroll matching the vanilla mechanic. | | 7 | Sound effect played at player location instead of the tree |player.playSound(player.getLocation(), ...)meant the wood-break sound originated from the player rather than the tree. Players nearby heard nothing; the audio source felt disconnected from the visual effect. Fixed by usingworld.playSound(startBlock.getLocation(), ...)so the sound radiates from the felled tree's base and all nearby players can hear it. |Added — New Features
| Feature | Details | |---------|---------| | `max-horizontal-distance` is now configurable | PreviouslyMAX_HORIZONTAL_DISTANCE = 8was a hardcoded constant inTreeFinder. It is now exposed asmax-horizontal-distanceinconfig.yml(default: 8). Modpack trees with unusually wide canopies can increase this; densely planted farms can decrease it to prevent cross-tree BFS merging. |Changed — Code Improvements
- Cooldown cleanup interval is now dynamic: entries are removed aftermax(5 s, 10 × cooldown-ms)instead of a flat 60 seconds. With the default 200 ms cooldown this reduces the time stale entries linger from 60 s to 2 s. -Config.getMaxHorizontalDistance()added;TreeFinder.findLogs()now accepts this as a parameter instead of reading a static field. -AdvancedTreeCapitator.getCooldowns()added to allowTreeCapitatorTaskto refund cooldowns without reflection. - All per-player state is now cleared inPlayerQuitEventin addition to each task'sfinallyblock.1.4.0Advanced TreeCapitator 1.4.0May 14, 2026 [1.4.0] — 2026-05-14
Fixed
- [CRITICAL] Forced Java 21 requirement — Thepom.xmlcompile target has been lowered from Java 21 to Java 17. Previously the plugin threwUnsupportedClassVersionErroron any server running Java 17 (Paper 1.20.x, Purpur, Pufferfish, most shared hosting providers). No source changes were needed because the code does not use any Java 21-specific APIs. - [CRITICAL] Protection plugin bypass — Extra log blocks (every block other than the origin) were broken withbreakNaturally()without first firing aBlockBreakEvent, meaning WorldGuard, GriefPrevention, Lands, and Residence had no opportunity to intervene. A dedicatedBlockBreakEventis now fired for each extra block before it is broken; if any protection plugin cancels that event, the block is silently skipped. - [CRITICAL] Missing anti-recursion guard — The protection-plugin fix above firesBlockBreakEventprogrammatically, which caused the plugin's own listener to trigger again for each block, creating an infinite loop. AbreakingTreesSet<UUID>now marks any player whose felling session is currently in progress; the listener returns immediately if the player's UUID is already present. The set is always cleared inside afinallyblock so a player can never get permanently stuck. - [MEDIUM] BFS linking two nearby trees — The 26-direction BFS could follow diagonal log connections to merge two adjacent trees into one oversized fell. A newMAX_HORIZONTAL_DISTANCE = 8constant (Manhattan X+Z distance from the origin block) causes BFS to skip any candidate block beyond that threshold. The value of 8 is wide enough to accommodate Big Oak and Dark Oak canopies without bridging two separate trunks. - [MEDIUM] No config value validation — Values such asmax-blocks: -1ordamage-multiplier: -100were loaded directly into fields, producing undefined behaviour (negative BFS limits, inverted durability).clamp()andclampDouble()helpers have been added toConfig.reload(); all numeric values are now constrained to a valid range (e.g.max-blocks→[1, 1000],damage-multiplier→[0.1, 10.0]).Clarified (not a bug)
- Double durability damage (analyst report #2) — The audit report claimed thatbreakNaturally(tool)automatically reduces the tool's durability in the player's inventory, causing damage to be applied twice alongsideDurabilityHandler. After reviewing the Paper API source:Block.breakNaturally(ItemStack)uses theItemStackonly to determine drop calculations (Fortune, Silk Touch) and does not modify the item in the player's inventory.DurabilityHandlerremains the sole source of durability loss. No double damage occurs.Changed
- Lowered the supportedapi-versionfrom Paper 1.21 to Paper 1.20.4+, broadening compatibility without requiring any 1.21-specific API. - Added Javadoc toTreeFinder,TreeCapitatorTask, andConfig.Not Fixed (planned v1.5.0)
- Folia incompatibility — The plugin schedules work withBukkitScheduler.runTask(), which is incompatible with Folia's region-based threading model. A proper fix requires migrating toRegionScheduler/GlobalRegionSchedulerand is planned for v1.5.0. ---1.3.0Advanced TreeCapitator 1.3.0Apr 26, 2026 [1.3.0] — 2026-04-25
Fixed
- `PALE_OAK_LOG` bypassed `require-leaves` check —isOverworldLog()was missingPALE_OAK_LOGfrom its switch statement, meaning Pale Oak trees were treated the same as Nether stems (no-leaf bypass). Withrequire-leaves: true, a Pale Oak log structure built by a player would be incorrectly felled. AddedPALE_OAK_LOGto the overworld log list so it is correctly guarded. - Fragile reference-equality trim check — The condition that decided whether leaves should be broken usedtrimmedLogs == logsToBreak(Java reference equality) instead of an explicit boolean. While this happened to work correctly, it was subtle and error-prone. Replaced with a dedicatedwasTrimmedboolean flag for clarity and safety.Added
- `TreeCapitatorEvent` (Plugin API) — A new cancellable Bukkit event fired just before any tree is felled. Other plugins can now listen toTreeCapitatorEventto: - Cancel the felling viaevent.setCancelled(true). - Inspect the full set of logs and leaves that will be broken. - Grant custom rewards (economy, XP, quests) based onevent.getLogs().size(). - `leaf-durability-ratio` config option (default:10) — Controls how many leaf blocks count as one durability hit whenbreak-leaves: true. Previously hardcoded to1/10, this is now fully configurable. Set to1to make every leaf cost a durability point; set higher to reduce tool wear from leaf breaking. - `MUSHROOM_STEM` support — Added a commented-out entry inconfig.ymlforMUSHROOM_STEM, enabling huge-mushroom felling. Uncomment to activate.Refactored (God Class split)
- `TreeFinder` (new class) — Extracted all BFS log-finding and leaf-scanning logic fromTreeCapitatorTaskinto a dedicated utility class.isOverworldLog()andisLeaf()helpers moved here. - `DurabilityHandler` (new class) — Extracted all durability calculation and application logic (getRemaining,calcMaxExtraBreaks,applyDamage) into a dedicated utility class. -TreeCapitatorTaskis now a lean orchestrator: BFS → leaves → trim → event → break → durability → effects. ---1.2.5Advanced TreeCapitator 1.2.5Apr 17, 2026 [1.2.5] — 2026-04-17
Fixed
* Nether stems, Warped stems, and Bamboo Block now work correctly withrequire-leaves: true.Improved
* Highly optimized BFS: usesArrayDeque, scans leaves only once, adds Manhattan distance, and usesHashSet. * Cleaner, more maintainable code. ---1.2.4Advanced TreeCapitator 1.2.4Apr 4, 2026 [1.2.4] — 2026-04-04
Fixed
- Large trees (Jungle Giant, Dark Oak) could not be felled — When a tree exceededmax-blocks(default: 100), the plugin aborted the entire felling operation and only the single broken log was harvested. This made giant Jungle trees (200-500 blocks) and large Dark Oaks impossible to chop efficiently. The plugin now performs a **partial chop** — it breaks logs up to the configuredmax-blockslimit instead of doing nothing. The remaining logs can be harvested with additional chops. - Off-by-one in max-blocks check — Changed from>to>=so the limit is correctly enforced at exactlymax-blocks. - Big Oak trees not fully harvested — The BFS search for logs was limited to 6 directions (face-adjacent only), causing the capitator to miss logs that are only diagonally adjacent. Big Oak trees have irregular structures where some logs only touch at corners. The search is now 26-direction (3×3×3 cube) to catch all connected logs. ---1.2.3Advanced TreeCapitator 1.2.3Mar 27, 2026 [1.2.3] — 2026-03-27
Added
- `require-leaves` option (default:true) — Before felling, the plugin now checks that the log cluster has at least one adjacent leaf block. If none are found, the capitator does nothing. This prevents accidental activation on player-built log structures such as house walls, cabin roofs, or log-block decorations. Set tofalseto restore the old behaviour.Fixed
- Durability did not limit felling — Tool durability was calculated and applied after all blocks were already broken. A nearly-broken axe (1 durability remaining) could silently fell a 100-log tree and would simply be destroyed at the end. The task now calculates the maximum number of extra logs the remaining durability permits before breaking any blocks, and trims the set accordingly. Unbreaking level is respected in this pre-check as well. ---1.2.2Advanced TreeCapitator 1.2.2Mar 16, 2026 [1.2.2] — 2026-03-16
Fixed
- Critical Item Swap Bug — Fixed a bug where switching items during a tree felling task (0.05s delay) could overwrite a new item in the player's hand with the old axe, potentially causing item loss. The task now tracks the specific inventory slot and verifies the tool's identity before applying durability changes. - Leaf Durability — Added durability loss for leaf felling. Every 10 leaves broken now counts as 1 tool hit to ensure balancing whenbreak-leavesis enabled.1.2.1Advanced TreeCapitator 1.2.1Mar 10, 2026 Changelog — Advanced TreeCapitator
All notable changes to this project are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ---[1.2.1] — 2025-03-10
Fixed
- Plugin was completely non-functional. The BFS task readblock.getType()one tick after the block-break event fired — at that point the block is alreadyAIR, so the search found nothing and no extra logs were cut. The blockMaterialis now captured inside the event handler (while the block still exists) and passed to the task. - Tool durability changes were silently discarded because the modifiedItemStackwas never written back to the player's hand. AddedsetItemInMainHand(tool)after updating the item meta. -Enchantment.UNBREAKINGresolved viaEnchantment.getByKey(NamespacedKey)with atry-catchfallback, fixing compatibility across all Paper 1.21.x patch builds. - Leaf blocks adjacent to a log in a cardinal direction were skipped during the 26-dir leaf scan because the log-BFSvisitedset had already claimed them. Leaf collection now deduplicates with its ownLinkedHashSet, independent of the log BFS. - Event priority reverted toNORMAL(was incorrectlyHIGH) so protection-plugin cancellations atNORMALpriority are still respected. ---1.2.0Advanced TreeCapitator 1.2.0Mar 10, 2026 Changelog — Advanced TreeCapitator
All notable changes to this project will be documented in this file. ---[1.2.0] — 2025-03-10
Added
- Per-player toggle (/atc toggle) — each player can enable or disable tree felling independently without affecting others - Tab completion for the/atccommand -README.mdwith full installation guide, permissions table, and usage notes -CHANGELOG.md(this file)Fixed
-@EventHandlerwas missingignoreCancelled = trueandpriority = EventPriority.HIGH— now correctly respects cancellation from other plugins - Leaf detection upgraded to 26-direction (3×3×3) scan whenbreak-leaves: true— diagonal leaves on Dark Oak and Jungle trees are now always caught - When a tree exceededmax-blocks,breakCountwas reset to1but damage was still calculated — now the task returns early with no extra block breaks or damage when the limit is hit - Tool durability now usesextraBreaks + 1(including the origin block) for an accurate damage totalChanged
- In-game messages translated to English for Modrinth release - Logger startup message now includes the plugin version -onDisable()clears bothcooldownsanddisabledPlayers- Config comments rewritten in English with explicit Fortune/Silk Touch notes -maven-compiler-pluginbumped to3.13.0- Version:1.1.0→1.2.0---[1.1.0]
Fixed (internal, per [FIX #x] comments)
-[FIX #1]enabledflag is now checked at the top of the event handler -[FIX #2]/atc reloadcommand handler registered correctly -[FIX #3]Permission checkadvancedtreecapitator.useapplied -[FIX #4]break-leavesnow actually breaks leaves -[FIX #5]Particle effect now renders correctly -[FIX #6]Periodic cooldown map cleanup to prevent memory leak -[FIX #8]Cooldown is configurable viacooldown-msinstead of being hardcoded -[FIX #9]Unbreaking enchantment respected; Pale Oak, Nether stems, and Bamboo added to default config ---[1.0.0]
- Initial release1.1.0Advanced TreeCapitator 1.1.0Mar 9, 2026 Changelog
All notable changes to Advanced TreeCapitator will be documented in this file. ---[1.1.0] - 2026-03-10
Fixed
- `enabled` flag was never checked — the plugin would still function even whenenabled: falsewas set inconfig.yml. A guard check is now placed at the top ofonBlockBreak(). - `/atc reload` command had no handler — the command was declared inplugin.ymlbut the plugin never implementedCommandExecutor, causing the server to return "Unknown command". The plugin now properly implementsonCommand()and handles/atc reload. - `advancedtreecapitator.use` permission was never enforced — any player could use the feature regardless of their permissions. A permission check is now performed before processing each block break. - Leaf breaking did nothing —break-leaves: truein config had no effect because the BFS loop collected leaf blocks into a dead branch with no code. Leaves are now properly collected and broken. - Particle effect was commented out — the particle block inTreeCapitatorTaskwas entirely commented out, soparticle-effect: truenever produced any visual feedback. Particles now spawn correctly using theParticle.BLOCKAPI. - `breakCount` did not include the initial block — durability loss was calculated one block short because the starting block (broken by the event itself) was excluded frombreakCount. The counter now starts at1to account for it.Added
- Configurable cooldown — a newcooldown-msoption inconfig.yml(default:200) replaces the previously hardcoded 100 ms cooldown, giving server admins full control. - Unbreaking enchantment support — axe durability loss now respects the Unbreaking enchantment level using Minecraft's standard probability formula (1 / (level + 1)chance per hit). - Automatic cooldown map cleanup — a repeating task runs every 10 minutes to purge stale entries from the cooldownsConcurrentHashMap, preventing a memory leak on long-running servers. - Additional log types in default config: -PALE_OAK_LOG(Minecraft 1.21.4+) -CRIMSON_STEMandWARPED_STEM(Nether wood) -BAMBOO_BLOCK(Minecraft 1.20+) ---[1.0.0] - Initial Release
- BFS-based tree felling on log break. - Configurable axe requirement, sneak requirement, world whitelist/blacklist. - Durability loss on axes with a configurable multiplier. - Sound and particle effect toggles. - Per-player cooldown to prevent spam.1.0.0Advanced TreeCapitator 1.0.0Mar 9, 2026 [1.0.0] - 2026-03-10
Added
- Initial release - Tree felling when sneaking with an axe (configurable viarequire-sneakin config.yml) - Configurable axe durability loss based on number of logs broken (damage-multiplier) - Max block limit to prevent lag (max-blocks) - World whitelist/blacklist support - Reload command/atc reloadto apply config changes without restart (requiresadvancedtreecapitator.adminpermission) - Permission nodes: -advancedtreecapitator.use– allows using the fast tree felling feature (default: true) -advancedtreecapitator.admin– allows reloading the configuration (default: op) - Support for all vanilla log types: oak, spruce, birch, jungle, acacia, dark oak, mangrove, cherry - Toggleable particle and sound effects (particle-effect,sound-effect)
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
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
WorldEdit
A Minecraft Map Editor... that runs in-game! With selections, schematics, copy and paste, brushes, and scripting. Use it in creative, or use it temporarily in survival.
11.6MSueta