Information

BattleStudio Plugin
OptimalMilestones
Long-run progression tracks: numbered milestones per category, each with its own threshold and rewards to claim.
- Paper / Folia
- MC 1.20+
- Java 21+
- PlaceholderAPI
OptimalMilestones gives players one or more categories - Blocks, Playtime, Prestige, whatever
you define - and each category is a numbered track of milestones. A milestone has a cumulative
Required threshold and a set of rewards. Reach the threshold and the milestone becomes claimable;
claim it once and the rewards run.
Every category is one file. Add a file, get a new track, complete with its own icon in the menu’s category row.
Categories and progress
Section titled “Categories and progress”A category tracks progress in one of two ways, set by Progress.Type:
| Type | Progress comes from | Admin-adjustable |
|---|---|---|
API |
An internal counter fed by a single named event source. Every matching event adds +1. | Yes |
PLACEHOLDER |
A numeric PlaceholderAPI placeholder, read live every time it’s needed. | No |
API categories store their counter in the plugin’s own database, so
/milestonesadmin progress can adjust them. PLACEHOLDER categories own nothing - they just read
whatever the placeholder says, so the plugin refuses to modify them.
API sources
Section titled “API sources”One source per category, no filters - no chance roll, no world or block whitelist. Every matching event is +1.
| Source | Fires on |
|---|---|
BLOCK_BREAK |
Bukkit BlockBreakEvent |
BLOCK_PLACE |
Bukkit BlockPlaceEvent |
MOB_KILL |
A non-player entity dies with a player killer |
PINNAPRISON |
PinnaPrison’s BlockMineEvent |
EDDUNGEONS |
EdDungeons’ EdDungeonsSwingSwordEvent |
RIVALHARVESTERHOE |
RivalHarvesterHoes’ RivalBlockBreakEvent |
Names are parsed case-insensitively and - counts as _, so block-break works. An unknown name
fails the load loudly. The last three are hooked purely by reflection and register only when their
plugin is installed.
Claiming
Section titled “Claiming”Required is a cumulative total, not a per-step amount. Milestone 3 at Required: 5000 means
5,000 total, not 5,000 more than milestone 2.
Milestones are never claimed automatically. When progress crosses a threshold the milestone turns
claimable and a MILESTONE-UNLOCKED message fires (a timer scans every Notify-Interval seconds).
The player then clicks it in /milestones. The claim is written to the database immediately, so a
crash can’t re-grant it, and the milestone’s Commands run from console.
Claims never expire and progress is never reset by the plugin.
Features
Section titled “Features”- Any number of categories, one file each, each with its own icon and menu slot
- Two progress types: an internal event counter or a live PlaceholderAPI value
- Per-category milestone icons, so each track formats its own units and colors
- Cumulative thresholds, Roman-numeral labels, configurable progress bar
- Paginated milestone grid, opening on the player’s first unclaimed milestone
- Unlock notifications with an optional screen title
- Temporary feedback icons on blocked clicks
- Full PlaceholderAPI output, per category
- SQLite storage with write-behind flushing
- Folia-ready (region schedulers throughout)
Commands
Section titled “Commands”Player - /milestones (aliases /ms, /milestone):
/milestones- open the menu on the default category ·optimalmilestones.use/milestones <category>- open a specific category ·optimalmilestones.use
Admin - /milestonesadmin (aliases /msadmin, /milestoneadmin) · all optimalmilestones.admin:
/milestonesadmin progress <give|take|set> <player> <category> <amount>- adjust a tracked counter.APIcategories only - aPLACEHOLDERcategory answersCATEGORY-NOT-TRACKED. Works offline./milestonesadmin reset <player> [category]- wipe progress and claims, for one category or all of them. Works offline./milestonesadmin reload- reload every config file.
Permissions
Section titled “Permissions”optimalmilestones.use-/milestonesand the menu (default: everyone)optimalmilestones.admin- every/milestonesadmincommand (default: op)
Milestones and categories have no permission nodes of their own.
Placeholders
Section titled “Placeholders”Requires PlaceholderAPI. Identifier optimalmilestones. Every placeholder is per category - swap
<category> for the category’s id (its file name without .yml).
%optimalmilestones_<category>_progress%- raw progress%optimalmilestones_<category>_progress_formatted%- same, comma-grouped (1,234)%optimalmilestones_<category>_completed%- milestones claimed%optimalmilestones_<category>_total%- milestones in the category%optimalmilestones_<category>_reached%- milestones whose threshold is met (claimed or not)%optimalmilestones_<category>_percent%- claimed ÷ total as a rounded percentage
For example, %optimalmilestones_blocks_progress%. An unknown category returns empty.
PLACEHOLDER categories return 0 for _progress when the player is offline, since the value can
only be read live.
Formatting
Section titled “Formatting”Every text field supports legacy & codes, &#RRGGBB hex, MiniMessage (<gradient:a,b,c>,
<rainbow>, <bold>, <#RRGGBB>, <solid:HEX>, …) and PlaceholderAPI %...% in messages and
action arguments. <gradient> accepts comma-separated hex stops.
Reference
Section titled “Reference”- Install: Installation
- Add a track: Creating Categories
- Config files: config.yml · milestones · menus · messages.yml
