SnLib v1.26.0
The owner picks how a number reads.
A plugin decided at its call site whether a balance rendered 1500000, 1,500,000 or 1.5M. The server owner could not change it without the plugin being rebuilt, and across a fleet that meant three formatters with three different suffix ladders, plus plugins that formatted nothing at all and left raw digits sitting in chat.
SnText.applyLocals now understands a trailing format hint on a local token. The choice moves to the language file the owner already edits.
| Hint | 1500000 becomes |
|---|---|
{balance:short} |
1.5M |
{balance:grouped} |
1,500,000 |
{balance:raw} |
1500000 |
# Before
balance-msg: "&aYou have &f{balance} &acoins" # You have 1500000 coins
# After
balance-msg: "&aYou have &f{balance:short} &acoins" # You have 1.5M coinsIt works in messages, item names, item lore and menu titles, and it needs no change to the consumer plugin: update SnLib.jar, restart, and every plugin already installed honours it.
Inert unless it is asked for. Five rules keep it from touching text that never opted in:
- the full token resolves FIRST, so a key that itself contains a colon is never reinterpreted as a hint;
- only
raw,shortandgroupedcount. A Discord timestamp like<t:1700000000:R>, or a PAPI token that takes an argument, passes through verbatim; - an unknown key keeps the whole token, hint included, exactly as an unhinted unknown token already did;
- a non-numeric value comes back UNCHANGED rather than blanked, so
{player:short}still renders the name; - a non-finite result is left alone, since
parseFormattedaccepts1e400andBigDecimal.valueOfwould throw on it.
short and grouped round HALF_UP to two decimals; raw never rounds, because exactness is the only reason to reach for it.
One caveat worth knowing: the value is re-parsed from its rendered form, which is precisely what lets an unmodified plugin honour the hint. So a caller that already abbreviated hands over 1.23M, and :raw answers 1230000 rather than the exact figure. Only a caller that passes unformatted digits can be re-rendered losslessly.
No public API added, so SnApi.LEVEL stays 17 and no consumer needs recompiling to benefit. 500 tests, 12 of them new.