
PlayerStats-ActionBar
A comprehensive yet lightweight Minecraft player statistics plugin that efficiently tracks player achievements, displays real-time stats via action bar, features an intuitive GUI system, and includes leaderboards. Built with asynchronous data
Tags
Creators
Details
2.0.0
Compatibility
Changes
Every message and menu a player sees is now translatable, and each player reads it in their own language. Two people standing next to each other can open the same menu and see it in Indonesian and English at once.
This release also moves the plugin to Paper 26.2. Everything 1.1 added is still here; nothing was dropped.
⚠️ Read before updating
- The jar is now
PlayerStats-2.0.0.jar. Delete the old jar first — with two present, Paper finds two plugins named PlayerStats and refuses to start. - This build is for Paper 26.2. Stay on 1.1 for 1.21.x servers.
- Your config and player data are safe. An existing
config.ymlkeeps working, and any text in it now acts as an override shown to everyone exactly as you typed it. - Two placeholders were renamed, and the old names still work:
%playerstats_blocks%→%playerstats_blocks_mined%,%playerstats_playtime_formatted%→%playerstats_playtime%. - API break, developers only:
MilestoneManager.MilestoneRewardis nownew MilestoneReward(Sound). Milestone wording moved into the language files.
Translations
- Text lives in
lang/<code>.yml.en_usandid_idship with the plugin. - Adding a language is a file copy. Copy
lang/en_us.ymltolang/de_de.yml, translate the values, run/pstats reload. There is no list of supported languages in the code — the plugin looks for the file matching the code the client reports. language.default: auto(the default) serves each player their own client language. Set it to a fixed code to force one language for everybody.- Partial translations are fine. Missing keys fall back one key at a time, so you never have to finish a file before using it.
- A shipped language you have edited falls back to the jar's copy of that same language first, so your edits survive an update and new strings still appear translated.
- Time format follows the language too (
2h 30m/2j 30m), including in%playerstats_playtime%and every menu. - Covered: the action bar, all 25 milestone names, achievement wording, menu titles, session menus, the confirmation prompt, and every command reply.
Crystal PvP tracking
- New statistics: crystals placed, crystal kills, totems forced out of others, totems popped, respawn anchors used, and an all-time best kill streak.
- Fixes plain kill counting on crystal servers. An end crystal explosion names no owner, so
getKiller()is null and the kill was previously not counted at all. Kills are now carried by a combat tag (statistics.combat-tag-seconds, default 12s). - Credit goes to whoever set the crystal off, falling back to whoever placed it. In crystal PvP those are usually different players.
- Respawn anchor kills are attributed by place and time, since anchor damage has no attacker entity at all.
Each tracking flag now owns its whole surface
Turning off a statistics.track-* flag no longer just stops counting. It also removes that statistic's menu items, leaderboard buttons, achievement categories and /pstats top types, so you never see a menu full of zeros.
track-pvp→ kills, kdr, streaktrack-pve→ mobstrack-blocks→ blockstrack-crystal-pvp→ crystals, crystal_kills, totems, totems_popped, anchors
Carried over from 1.1, now wired to their config
Session stats, the confirmation system and action bar caching all work as before. Several of their settings were never actually read by the code. They are now.
session.streak-milestonesandsession.streak-messagesare used. The streak shout used to fire on every fifth kill regardless of what you configured, and the wording in config was ignored entirely.session.multikill-windowis used. The window was hardcoded at 5 seconds.confirmation.play-soundand the three sound settings are used. None were read.action-bar.cache-durationis used, and the cache is dropped the moment a statistic changes, so the bar never shows a stale number.%playerstats_rank_*%no longer sleeps the main thread. It used to block for 10ms per lookup. Ranks now come from an index built with the leaderboard refresh, and reach 1000 places deep instead of 100.- Permissions: the plugin now declares only nodes it actually checks, and checks them. 1.1 declared 27 and enforced 2.
/pstats resetworks from console again and accepts offline players.playerstats.bypass.confirmationskips the prompt.
Fixes
- Paper 26.2 support.
- Join and quit handlers ran twice per event.
- Blocks broken but cancelled by a protection plugin counted towards mining stats.
- Menus were identified by title, which broke when a title was renamed or colour-coded. They now use an inventory holder, and dragging items into a menu is blocked.
- The leaderboard cache was not thread safe, and player data was read by the async save task while the main thread wrote it.
- Saving re-serialised the whole data file once per online player. It is one write now.
- Milestones are checked with
>=, so stats loaded from disk still award what was earned. - The deaths leaderboard was never pre-cached, so
%playerstats_top_name_deaths_1%always returned-. - A confirmation that was answered could still be expired by the timeout of an earlier request.
- Several config keys were read but never used. They all work now.
Requires PlaceholderAPI. Vault is optional, for the balance placeholder and milestone money rewards.
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:kWTJ88AH:tchytrPu"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:kWTJ88AH:tchytrPu"
}
