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.

348

Quick challenge

How far can you run before the mobs catch you?

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

ADS