COWMODSКаталог модов

DonutShards

DonutShard is a feature-rich custom currency plugin. Earn Shards by PvP kills and AFK farming, then spend them in a beautiful GUI shop with multiple categories.

Автор: Duong2012G4,7 тыс.2обновлён 20 июн. 2026 г.

Описание

🍩 DonutShard

A feature-rich custom currency plugin for PaperMC servers — earn Shards by killing, AFK farming, and spending them in a configurable shop.

Version API Java License


✨ Features

FeatureDescription
💰 Shard CurrencyCustom economy currency with leaderboard, balance commands
⚔️ Kill RewardsEarn Shards for PvP kills with cooldown and bonus multiplier
🌙 AFK SystemEarn Shards passively while AFK in designated warp zones
🛡️ Zone ProtectionWorldGuard-like protection for AFK zones (no WorldGuard required)
🏪 Shard ShopMulti-category GUI shop — buy items with Shards
🌐 Multi-language5 built-in languages: vi en zh es fr
📊 Leaderboard/shard top with PlaceholderAPI support
🔌 Developer APIHook into Shard events from other plugins
💾 Dual StorageYAML or SQLite, with WAL-mode async writes

📦 Requirements

RequirementVersion
PaperMC1.21.x
Java21+
PlaceholderAPI2.11+ (optional)

⚙️ Installation

  1. Download DonutShard-1.0.0.jar and drop it into your /plugins folder.
  2. Start the server — config files generate automatically.
  3. Edit plugins/DonutShard/config.yml to your liking.
  4. Run /shard reload in-game to apply changes without restarting.

🗂️ File Structure

plugins/DonutShard/
├── config.yml          # Main config (kill reward, storage, leaderboard)
├── afk.yml             # AFK zones, protection rules, earn rates
├── shop.yml            # Shop categories & GUI layout
├── shops/
│   ├── Spawners.yml    # Spawner items
│   ├── Ores.yml        # Ore blocks
│   └── Farm.yml        # Farming items
├── languages/
│   ├── en.yml
│   ├── vi.yml
│   ├── zh.yml
│   ├── es.yml
│   └── fr.yml
└── data/               # YAML storage files (if YAML mode)
    ├── balances.yml
    ├── afk_sessions.yml
    ├── afk_warps.yml
    └── daily_earnings.yml

🔧 Configuration

config.yml — Quick Reference

language: en           # Active language (en/vi/zh/es/fr)

kill-reward:
  enabled: true
  shards-per-kill: 10
  kill-cooldown: 30    # seconds before same kill gives reward again
  ignore-afk-victims: false
  bonus-multiplier:
    enabled: false
    threshold: 1000    # if victim has >= this many Shards
    multiplier: 1.5

storage:
  type: SQLITE         # YAML or SQLITE
  auto-save-interval: 5  # minutes

leaderboard:
  size: 10

afk.yml — AFK System

enabled: true
shards-per-minute: 1
daily-limit: 100       # 0 = unlimited
teleport-cooldown: 5   # seconds between /afk uses
auto-detect-afk: true  # auto-detect players already in AFK world

protection:
  default:
    no-damage: true
    no-hunger: true
    no-pvp: true
    no-mob-spawn: true
    no-item-drop: true
    restore-health-on-enter: true
    clear-effects-on-enter: true

Adding a Shop Category

  1. Create plugins/DonutShard/shops/MyCategory.yml:
gui-title: "<gold>⭐ My Category"
items:
  - id: DIAMOND
    name: "<aqua>💎 Diamond"
    price: 100
    slot: 10
    quantity: 1
    lore:
      - "<gray>Shiny and expensive"
  - id: SPAWNER
    name: "<red>🔥 Blaze Spawner"
    spawnertype: BLAZE
    price: 5000
    slot: 11
    quantity: 1
  1. Add the category to shop.yml under categories:
categories:
  MyCategory:
    icon: DIAMOND
    name: "<aqua>My Category"
    slot: 4
    lore:
      - "<gray>Buy diamonds and spawners"
  1. Run /shard reload. No restart needed!

💬 Commands

CommandDescriptionPermission
/shard balance [player]View Shard balancedonutshard.balance
/shard give <player> <amount>Give Shardsdonutshard.give
/shard take <player> <amount>Take Shardsdonutshard.take
/shard set <player> <amount>Set Shardsdonutshard.set
/shard top [page]View leaderboarddonutshard.top
/shard reloadReload configdonutshard.reload
/shard set-afk-warp <name>Set AFK warp to a worlddonutshard.admin
/shard remove-afk-warp <name>Remove AFK warpdonutshard.admin
/shard list-afk-warpList all AFK warpsdonutshard.admin
/shard language <code>Change languagedonutshard.language
/afk [warpname]Enter an AFK zonedonutshard.afk
/afk-settingManage AFK zone settingsdonutshard.afk.admin
/shardshopOpen the Shard Shopdonutshard.shop

Aliases: /shard → /donutshard, /ds


🛡️ Permissions

PermissionDescriptionDefault
donutshard.balanceCheck own balancetrue
donutshard.balance.othersCheck other's balanceop
donutshard.giveGive Shards to othersop
donutshard.takeTake Shards from othersop
donutshard.setSet Shard balanceop
donutshard.topView leaderboardtrue
donutshard.reloadReload pluginop
donutshard.adminAll admin commandsop
donutshard.afkUse /afk commandtrue
donutshard.afk.adminManage AFK settingsop
donutshard.shopOpen Shard shoptrue
donutshard.kill.bypassThis player's deaths give no Shardsfalse
donutshard.zone.bypassBypass zone protectionop
donutshard.languageChange languagetrue

📊 PlaceholderAPI

Register these placeholders in any compatible plugin:

PlaceholderReturns
%donutshard_balance%Player's Shard balance
%donutshard_rank%Player's leaderboard rank
%donutshard_top_1% to %donutshard_top_10%Top player name at rank N
%donutshard_top_balance_1%Top player balance at rank N

🔌 Developer API

Add DonutShard as a dependency in your plugin:

// Check availability
if (DonutShardAPI.isAvailable()) {

    // Get balance
    long balance = DonutShardAPI.getBalance(player);

    // Give Shards with a reason
    DonutShardAPI.give(player, 100, "Quest reward");

    // Take Shards (returns false if insufficient)
    boolean success = DonutShardAPI.take(player, 50);

    // Listen to Shard events
    DonutShardAPI.registerHook(new ShardEventHook() {
        @Override
        public void onShardEarned(UUID uuid, long amount, String reason) {
            // ...
        }
        @Override
        public void onShardSpent(UUID uuid, long amount, String reason, long newBalance) {
            // ...
        }
    });
}

🔨 Building from Source

git clone https://github.com/duong2012g/DonutShard.git
cd DonutShard
mvn clean package
# Output: target/DonutShard-1.0.0.jar

Requirements: Java 21, Maven 3.8+


📝 License

MIT — free to use, modify, and redistribute with attribution.


Made with ❤️ by duong2012g

Последние версии

Все версии →
release

DonutShards 1.2.0

1.2.0
20 июн. 2026 г.4 тыс.Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11bukkit, paper, purpur, spigot
Скачать
release

DonutShards 1.1.0

1.1.0
9 июн. 2026 г.410Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11bukkit, paper, purpur, spigot
Скачать
Что нового
## [1.1.0] — Bug Fix & Refactor Release ### Bug Fixes #### 🔴 Critical - **[BUG-1] DonutShardProvider.take() race condition** — Replaced two-step `getBalance() → take()` with `shardManager.safeTake()` (atomic CAS via `ConcurrentHashMap.compute()`). Players can no longer go negative or bypass balance checks when AFK ticker and shop purchase happen simultaneously. - **[BUG-2] ShopHook.charge() double-fires spent hook** — `DonutShardAPI.take()` already calls `fireSpentHooks()` internally. Removed the redundant `plugin.getApiProvider().fireSpent()` call in `ShopHook.charge()`. External `ShardEventHook` implementations no longer receive 2 events for 1 purchase. #### 🟡 Medium - **[BUG-3] DonutShardProvider.hooks not thread-safe** — Changed `ArrayList<ShardEventHook>` to `CopyOnWriteArrayList`. Prevents `ConcurrentModificationException` when hooks are fired from the async SQLite writer thread while another thread calls `registerHook()` / `unregisterHook()`. - **[BUG-4] autoDetectAfkPlayers() checks world only, not zone bounds** — Added `plugin.getAfkConfigManager().isInAnyZone(player.getLocation())` check before creating an auto-AFK session. Previously any player in the correct world (not just inside the zone) would start earning rewards. - **[BUG-5] getRank() O(n log n) on every PAPI render** — Added `rankCache` (`Map<UUID, Integer>`) with 60s TTL in `ShardManager`, mirroring the existing leaderboard cache. `invalidateLeaderboardCache()` now resets both caches. PlaceholderAPI `%donutshard_rank%` no longer sorts all players on every tab-list refresh. - **[BUG-6] ShardShopGUI calls saveAll() after every purchase** — Added `Storage.savePlayer(UUID)` default method. YamlStorage overrides it to write only `balances.yml` (vs. all 4 YAML files). SQLiteStorage keeps the default no-op (already async). Reduces synchronous main-thread I/O on busy shops. #### 🟢 Low - **[BUG-7] AFK ticker does not invalidate leaderboard cache** — Added `shardManager.invalidateLeaderboardCache()` at the end of `tickAllSessions()` whenever shards were distributed. Leaderboard now reflects AFK rewards within the same 60s cache window. - **[BUG-8] autoDetect calls startSession() → unnecessary teleport** — Split auto-detect path into `beginSessionInPlace()` which does NOT teleport. `startSession()` (called by `/afk`) continues to teleport. Players standing inside a zone are no longer sent to spawn on auto-detection. - **[BUG-9] Duplicate `afk_session_restored` key in en.yml** — Removed the stale copy at line 88 (the parser was silently using the version at line 105). - **[BUG-10] sqlite-jdbc not relocated in maven-shade-plugin** — Added `<relocation>` block in `pom.xml` to repackage `org.sqlite` → `dev.duong2012g.libs.sqlite`. Prevents ClassLoader conflicts with other plugins that also shade sqlite-jdbc (e.g. LuckPerms, AdvancedBan). - **[BUG-11] `donutshard.zone.bypass` not declared in plugin.yml** — Added the permission to `plugin.yml` with `default: op` and included it as a child of `donutshard.admin`. LuckPerms / PermissionsEx now show it in autocomplete. - **[BUG-12] 17 dead message getters in ConfigManager** — Removed all `getMsgXxx()` fields and getters following the completed migration of `DonutShardCommand` to `LanguageManager`. `ConfigManager` now only holds numeric/boolean/format config values. The `prefix` field was also removed (LanguageManager is now the single source-of-truth for all messages). ### Refactors - **ConfigManager cleaned** — Down from ~230 lines to ~120 lines. Zero message strings remain; all messages live in `languages/<code>.yml`. - **AfkManager restructured** — Code reorganised into three clearly labelled sections: ① Session lifecycle, ② Reward ticker, ③ Auto-detect. No external API change. - **ShardManager — dual cache** — `getTopBalances()` and `getRank()` now share the same 60s TTL and are invalidated together via `invalidateLeaderboardCache()`. - **AfkSettingCommand migrated** — All inline response messages now use `lm().getPrefix()` consistently. The `reload` subcommand now reloads AFK config, shop config, and language files in addition to the main config. - **plugin.yml** — All permissions now fully declared including `donutshard.zone.bypass` and `donutshard.language`. `donutshard.admin` grants all child permissions including zone bypass.
release

DonutShards 1.0.0

1.0.0
23 мая 2026 г.317Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11bukkit, paper, purpur, spigot
Скачать