DonutShards
1.2.0DonutShard 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.
1.2.0latestDonutShards 1.2.0Jun 20, 2026 1.1.0DonutShards 1.1.0Jun 9, 2026 [1.1.0] — Bug Fix & Refactor Release
Bug Fixes
####Critical - [BUG-1] DonutShardProvider.take() race condition — Replaced two-step
getBalance() → take()withshardManager.safeTake()(atomic CAS viaConcurrentHashMap.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 callsfireSpentHooks()internally. Removed the redundantplugin.getApiProvider().fireSpent()call inShopHook.charge(). ExternalShardEventHookimplementations no longer receive 2 events for 1 purchase. ####Medium - [BUG-3] DonutShardProvider.hooks not thread-safe — Changed
ArrayList<ShardEventHook>toCopyOnWriteArrayList. PreventsConcurrentModificationExceptionwhen hooks are fired from the async SQLite writer thread while another thread callsregisterHook()/unregisterHook(). - [BUG-4] autoDetectAfkPlayers() checks world only, not zone bounds — Addedplugin.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 — AddedrankCache(Map<UUID, Integer>) with 60s TTL inShardManager, 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 — AddedStorage.savePlayer(UUID)default method. YamlStorage overrides it to write onlybalances.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 oftickAllSessions()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 intobeginSessionInPlace()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 inpom.xmlto repackageorg.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 toplugin.ymlwithdefault: opand included it as a child ofdonutshard.admin. LuckPerms / PermissionsEx now show it in autocomplete. - [BUG-12] 17 dead message getters in ConfigManager — Removed allgetMsgXxx()fields and getters following the completed migration ofDonutShardCommandtoLanguageManager.ConfigManagernow only holds numeric/boolean/format config values. Theprefixfield 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 inlanguages/<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()andgetRank()now share the same 60s TTL and are invalidated together viainvalidateLeaderboardCache(). - AfkSettingCommand migrated — All inline response messages now uselm().getPrefix()consistently. Thereloadsubcommand now reloads AFK config, shop config, and language files in addition to the main config. - plugin.yml — All permissions now fully declared includingdonutshard.zone.bypassanddonutshard.language.donutshard.admingrants all child permissions including zone bypass.1.0.0DonutShards 1.0.0May 23, 2026
Similar projects
Plugin →Let Me Despawn
Improves performance by tweaking mob despawn rules. Say bye to pesky unintentional persistent mobs.
25MSueta
JourneyMap
Real-time map used for mapping in-game or your browser as you explore.
14.7MSueta
Emotecraft
Create your own emotes in Minecraft.
7.5MSueta
Simple Tpa
A simple tpa plugin which sends requests
5.4MSueta
Common Network
Forge and Fabric Unified Networking Solution
3.9MSueta
Set Home
A lightweight plugin for players to set their homes.
3.8MSueta