Better Veinminer
A Paper 1.21 veinminer plugin that mines entire ore veins instantly. Uses strict same-type BFS matching, so adjacent ores are never accidentally destroyed. Fully configurable via config.yml.
Better Veinminer
Better Veinminer
Link: 1.4.0 | Link: Paper 1.21+ | Link: Duong2012G Link: Apache-2.0 | Link: Link:
Mine an entire ore vein in one swing — with tier progression, persistent statistics, a custom event API, and deep configuration.
---
Features
Core
- Hot reload — accurate face-adjacent vein detection matching vanilla ore generation; no false positives from diagonal neighbours - Hot reload — only collects blocks of the exact same material - Hot reload — work automatically on every block in the vein - Hot reload — each player can enable/disable independently with `/bvm toggle` - Hot reload — matches vanilla's per-hit random probability model - Hot reload — restrict which worlds allow veinminer - Hot reload — `/bvm reload` applies config changes without a restart
Tier System
Players progress through 4 tiers as they mine more blocks:
| Tier | Blocks Required | Max Blocks (default) | |:----:|:--------------:|:-------------------:| | 1 | 0 | 32 | | 2 | 100,000 | 64 | | 3 | 500,000 | 128 | | 4 | 1,000,000 | 256 |
All thresholds and max-block limits are configurable. Check progress with `/bvm tier`.
Persistent Statistics
Stats survive server restarts. Saved per-player to `plugins/BetterVeinminer/stats/<uuid>.yml`: - Total blocks mined via veinminer - Total veinmines performed - Current tier - Auto-save every 5 minutes (thread-safe snapshot) + on player quit
Custom Event API
`BetterVeinmineEvent` lets other plugins hook into every veinmine:
```java @EventHandler public void onVeinmine(BetterVeinmineEvent event) { // Cancel completely (e.g. in protected regions) if (isProtected(event.getPlayer())) { event.setCancelled(true); return; }
// Double EXP on ancient debris if (event.getOreType() == Material.ANCIENT_DEBRIS) { event.setExpReward(event.getExpReward() * 2); }
plugin.getLogger().info(event.getPlayer().getName() + " veinmined " + event.getBlocks().size() + " blocks."); } ```
Protection Plugin Support
A `BlockBreakEvent` is fired for each extra block before it is broken. WorldGuard, GriefPrevention, Lands, and Residence can cancel individual blocks within protected regions. Per-block events are guarded by an anti-recursion lock so the plugin never triggers itself in a loop.
Permission-Based Limits
Give VIP/Premium players special treatment via `permission-levels` in config.
Ore Multipliers
Configure different EXP multipliers per ore type.
Per-Ore Cooldowns
Different cooldown per ore type.
Daily Limits
Cap veinmines per player per day. Resets at real midnight (persisted across restarts).
---
Installation
1. Download `BetterVeinminer-1.4.0.jar` 2. Drop into your server's `plugins/` folder 3. Restart or reload the server 4. Edit `plugins/BetterVeinminer/config.yml` 5. Use `/bvm reload` to apply changes without restarting
Requirements: Paper (or any Paper fork) 1.21+, Java 21+
---
Permissions
| Permission | Description | Default | |---|---|---| | `betterveinminer.use` | Use veinminer + `/bvm toggle/stats/tier` | `true` | | `betterveinminer.admin` | Reload config (`/bvm reload`) | `op` | | `betterveinminer.vip` | VIP tier (custom limits via config) | `false` | | `betterveinminer.premium` | Premium tier (best limits via config) | `false` |
---
Commands
| Command | Description | Permission | |---|---|---| | `/bvm toggle` | Enable/disable veinminer for yourself | `betterveinminer.use` | | `/bvm stats` | View your mining statistics | `betterveinminer.use` | | `/bvm tier` | Check your current tier & progression | `betterveinminer.use` | | `/bvm reload` | Reload configuration file | `betterveinminer.admin` |
---
How to Use
1. Hold a pickaxe from `tool-whitelist` 2. Sneak (Shift) if `require-sneak: true` 3. Break any ore block — the entire connected vein drops at once
Fortune and Silk Touch both work automatically on every block in the vein.
---
Configuration Reference
Basic Settings
```yaml enabled: true # Master on/off switch require-sneak: true # Player must sneak to activate require-pickaxe: true # Player must hold a whitelisted pickaxe max-blocks: 64 # Max blocks per veinmine (fallback when tier system is off) cooldown-ms: 200 # Cooldown between veinmines in milliseconds damage-tool: true # Whether the pickaxe takes extra durability damage damage-multiplier: 1.0 # Multiplier applied to the extra durability loss ```
Tier System
```yaml tier-system: enabled: true tier-2-threshold: 100000 tier-3-threshold: 500000 tier-4-threshold: 1000000 tier-1-max-blocks: 32 tier-2-max-blocks: 64 tier-3-max-blocks: 128 tier-4-max-blocks: 256 ```
Ore Multipliers
```yaml ore-multipliers: enabled: true multipliers: DIAMOND_ORE: 1.5 EMERALD_ORE: 2.0 COAL_ORE: 0.5 ```
Per-Ore Cooldowns
```yaml per-ore-cooldowns: enabled: false cooldowns: DIAMOND_ORE: 1000 COAL_ORE: 200 ```
Permission Levels
```yaml permission-levels: betterveinminer.vip: max-blocks: 128 cooldown-ms: 100 betterveinminer.premium: max-blocks: 256 cooldown-ms: 50 ```
Daily Limits
```yaml daily-limits: enabled: false limit-per-day: 10 ```
Custom Messages
All messages support `§` colour codes.
| Message key | Placeholders | |---|---| | `veinmine-success` | `{count}` | | `tier-up` | `{tier}`, `{blocks}` | | `stats` | `{blocks}`, `{tier}`, `{uses}` | | `daily-limit` | — | | `cooldown` | `{remaining}` |
EXP Rewards
```yaml exp-settings: enabled: false base-exp: 10 per-extra-block: 5 multiply-by-fortune: true ```
World Restrictions
```yaml whitelist-worlds: [] blacklist-worlds: [] ```
Effects
```yaml particle-effect: true sound-effect: true
effects: particle-type: BLOCK particle-color: "0xFFFFFF" particle-speed: 1.0 completion-sound: BLOCK_STONE_BREAK warning-sound: ENTITY_ITEM_PICKUP ```
---
Config Examples
Survival / Economy Server
```yaml tier-system: enabled: true tier-2-threshold: 50000 tier-3-threshold: 250000 tier-4-threshold: 500000
daily-limits: enabled: true limit-per-day: 5
ore-multipliers: enabled: true multipliers: DIAMOND_ORE: 1.5 EMERALD_ORE: 2.0 ```
Hardcore Mode
```yaml max-blocks: 16 cooldown-ms: 2000 tier-system: enabled: false damage-multiplier: 2.0 ```
---
Developer API
Add as a soft dependency: ```yaml softdepend: [BetterVeinminer] ```
Listen to `BetterVeinmineEvent`: ```java import dev.duong2012g.bvm.BetterVeinmineEvent;
@EventHandler public void onVeinmine(BetterVeinmineEvent event) { Player player = event.getPlayer(); Material ore = event.getOreType(); List<Block> blocks = event.getBlocks(); // unmodifiable int exp = event.getExpReward();
event.setExpReward(exp * 2); event.setCancelled(true); } ```
---
Bug Fixes in v1.4.0
| # | Bug | Status | |---|---|---| | 1 | Async save race condition — stats partially written while main thread modifies them | ✅ Fixed — snapshot taken on main thread before async I/O | | 2 | Cooldown cleanup used hardcoded 60 s regardless of configured cooldown | ✅ Fixed — cleanup now uses `config.getCooldownMs()` | | 3 | Daily reset based on server uptime ticks, not real calendar date | ✅ Fixed — `LocalDate.now()` with persistence in `data.yml` | | 4 | 26-direction BFS could link two separate nearby veins | ✅ Fixed — changed to 6-direction (face-adjacent) matching vanilla ore generation | | 5 | `breakNaturally()` bypassed protection plugins (WorldGuard, GriefPrevention…) | ✅ Fixed — `BlockBreakEvent` fired per block + anti-recursion guard | | 6 | Unbreaking durability formula was deterministic average, not vanilla per-hit random | ✅ Fixed — vanilla-style per-hit random check | | 7 | Tool swap exploit | ✅ Already fixed in v1.2.1 (slot + `isSimilar()` validation) | | 8 | `PlayerStats` exposed public mutable fields — external code could set negative values | ✅ Fixed — private fields with validated getters/setters and `copy()` method | | 9 | Config accepted invalid values (`max-blocks: -1`, `damage-multiplier: -100`) | ✅ Fixed — all numeric values clamped on load | | 10 | Concurrent async writes could corrupt the same YAML file | ✅ Fixed — single-threaded `ExecutorService` serialises all file I/O |
---
Troubleshooting
Veinminer not activating: - Check `enabled: true` in config - Verify the ore is in `ore-types` - Confirm you hold a pickaxe from `tool-whitelist` - Check you are sneaking if `require-sneak: true` - Verify the world is not blacklisted
Stats reset after restart: - Check `plugins/BetterVeinminer/stats/` is writable - Look for `"Failed to save stats"` warnings in server logs
Daily limit resets too early / not resetting: - Upgrade to v1.4.0 — the old tick-based timer drifted and was skipped on restarts - The new system persists the last reset date to `data.yml`
---
Changelog
See CHANGELOG.md
---
License
Apache-2.0 © Duong2012G