SnLib v1.25.0
Placeholders that need no player.
Not every placeholder describes a player. A leaderboard row, a server-wide counter, an event countdown - that is global data that merely happens to be exposed through PlaceholderAPI's per-player surface. And the callers that ask for it routinely supply no player at all: a global hologram, a Discord bridge, a console task, /papi parse --null.
BuiltExpansion.onRequest rejected a null requester before it had even looked at which resolver was being asked for, so a token that needed no player was dropped along with the ones that did. The consumer could not opt out: sn.papi().expansion(...) is the only registration path, and taking the raw PlaceholderExpansion back would take back registration, persistence and unregistration with it.
ExpansionBuilder.global(String param, Supplier<String>)andglobalPrefixed(String prefix, Function<String, String>)- bind a resolver that takes NOOfflinePlayer, so it cannot dereference one and it answers a null requester like any other. Same keyspace and precedence asplaceholder/prefixed; the later declaration for one key wins outright.onRequestnow locates the resolver FIRST and rejects the null requester SECOND. Everything bound throughplaceholder/prefixedkeeps the short-circuit exactly as before, so a resolver written against the non-null contract its binder documents never starts seeing nulls.LeaderboardCache.exposePlaceholders(id)binds itstop_tokens global, so every board exposed through it renders in a global hologram without the consumer changing a line.pos_<id>asks about the requester by definition and stays player-bound.
sn.papi().expansion("shop")
.placeholder("balance", player -> money(player)) // needs a player
.global("open_shops", () -> String.valueOf(registry.openCount()))
.globalPrefixed("top_", position -> topSellerAt(position))
.register();Strictly additive: two new public methods, zero public signatures changed, and the only behaviour change on an existing path is exposePlaceholders, which answers strictly more than it did. SnApi.LEVEL 16 -> 17.