Skip to content

PhoenixCrates Lite ​

collector-phoenixcrates · version 0.6.0 · registers as crate · CI 2026-09-25

PhoenixCrates metrics — and above all: does the randomness keep its promises?

That's the one thing you can't see in-game. A player who opens a hundred crates can sense that the reward advertised at 2% never comes up, but can't prove it; neither can an admin. Two metrics settle it:

<pre># OBSERVED probability over 30 days, against the CONFIGURED one sum by (crate,reward) (increase(mc_crate_rewards_total{alternative="false"[30d])) / ignoring(reward) group_left sum by (crate) (increase(mc_crate_rewards_total{alternative="false"}[30d])) / mc_crate_reward_expected_ratio # 1.0 = matches, 0.5 = half as frequent as promised }</pre>

There is no way to measure the raw draw, which had to be learned the hard way on the server. This module originally declared a reward_draws counter fed by CrateRewardSelectionEvent — which never fires as its name suggests. The event fires BEFORE the draw, with the list of candidates and a null reward, to let a third-party plugin impose its own choice; only afterward, if nobody responded, does selectByWeight actually draw. So there's no draw outcome to listen for.

The fallback is rewards_total filtered on alternative="false": what gets handed out WITHOUT having been substituted. An acknowledged imprecision remains — win limits and permissions remove candidates before the draw, invisibly. Hence crate_reward_candidates, which says how many rewards were actually in play.

Two regimes live in one class. The counters are fed by events and cost nothing at scrape time: they're already current. The gauges — configuration and per-player state — require walking lists, hence #isBackground() being true. Both mechanics live here together because they describe the same object; splitting them would force sharing crate identifiers between two classes.

All handlers run at MONITOR and in O(1). PhoenixCrates' events fire on the main thread, in the call stack of the open itself — verified at the bytecode level. A handler that took a millisecond would take it out of the tick.

Install ​

Put vania-metrics-collector-phoenixcrates-0.6.0.jar in the plugins folder, next to the core and to PhoenixCrates Lite, then restart. The collector depends on both: without PhoenixCrates Lite it stays disabled, and the core keeps running.

  • Target plugin: PhoenixCrates Lite 6.2.1 — latest for Minecraft 1.21.11: 6.2.1
  • Built against: core v0.6.0
  • Download: vania-metrics-collector-phoenixcrates-0.6.0.jar, with its SHA-512, from the v0.6.0 release
  • Collects: in the background, every few s — reading the plugin's state never blocks a scrape
  • Tested on: Java 21
  • Latest CI: success · 2026-09-25 21:34 UTC · commit 717801e · run

Platforms ​

PlatformTarget pluginCollectorLatest CI
PaperyesPassedpaper ✓
PurpuryesPassedpurpur ✓
FoliayesPassedfolia ✓
SpigotyesPassedspigot ✓
CraftBukkitunknownUnknown—
Spongenon/a—
Velocitynon/a—
BungeeCordnon/a—
Waterfallnon/a—
Geysernon/a—

See the compatibility matrix for every collector at once.

Metrics ​

mc_crate_deliveries_total ​

counter source

Item DELIVERIES, not items delivered: eight keys given at once count as one. "source" is key_grant, crate_grant or reward_grant. Only PHYSICAL keys go through here — granting a virtual key fires no event and only shows up as a jump in mc_crate_player_keys.

mc_crate_keys ​

gauge virtual

Keys declared.

mc_crate_open_attempts_total ​

counter crate

Opens REQUESTED, whether they completed or not. Checks the invariant attempts = opens + failures; a gap means the plugin opened a crate without going through the normal path.

mc_crate_open_cooldown_seconds ​

gauge crate

Delay imposed between two opens of the same crate.

mc_crate_open_cost ​

gauge crate currency

Price of an open. "currency" is the configured cost engine, which leaves the door open to multiple currencies, as with the economy module.

mc_crate_open_failures_total ​

counter crate reason

Opens refused. "reason" is INFERRED from the player's state at the time of the request, since the plugin only returns a translated message: cooldown, no_key, money, cancelled, other.

mc_crate_opens_total ​

counter crate

Opens completed, across all players.

mc_crate_placements_total ​

counter crate world

Physical crates placed in the world.

mc_crate_player_cooldown_seconds ​

gauge player uuid crate

Time REMAINING before a player can reopen a crate. Zero if they can open right away.

mc_crate_player_keys ​

gauge player uuid key

VIRTUAL keys in stock for a connected player. Physical keys are in their inventory and are not counted here.

mc_crate_player_opens ​

gauge player uuid crate

A player's opens EVER, by crate type. Persisted by the plugin: the only metric in this module that doesn't reset to zero on restart.

mc_crate_player_opens_total ​

counter player uuid crate

Opens completed, per player and per crate. Counts SINCE THE EXPORTER STARTED; for the all-time total, see mc_crate_player_opens, which the plugin persists.

mc_crate_player_reward_wins ​

gauge player uuid reward

How many times a player has won a given reward, ever. WITHOUT a "crate" label: the plugin indexes these wins by reward identifier ALONE, so two crates that both name a reward "diamond" share the counter. That's not a design choice, it's what the data allows.

mc_crate_previews_total ​

counter crate

Previews opened without opening the crate: interest that doesn't convert.

mc_crate_reward_candidates ​

gauge crate

Rewards actually in play at the last draw. Lower than crate_rewards_configured when win limits or permissions removed rewards: this is what explains why a player can no longer win a reward they already got.

mc_crate_reward_expected_ratio ​

gauge crate reward

EXPECTED probability of a reward, between 0 and 1, normalized BY US (weight / sum of weights). Describes the draw's configuration, not the effective odds: guaranteed rewards, win limits and permissions are applied on top of it.

mc_crate_reward_required_keys ​

gauge crate reward

Keys required to be eligible for a reward. This is the ONLY notion of rarity the plugin has: there is no getRarity() in its API.

mc_crate_reward_weight ​

gauge crate reward

Raw weight of a reward in the draw. This is NOT a percentage.

mc_crate_reward_win_limit ​

gauge crate reward

Maximum number of times a reward can be won. NEGATIVE means unlimited: -1 is what the plugin returns, observed on its sample crates, not 0 as one might assume.

mc_crate_rewards_configured ​

gauge crate

Rewards declared on a crate. The Lite edition caps this at 5: this gauge says when that cap is hit.

mc_crate_rewards_total ​

counter crate reward alternative

Rewards actually HANDED OUT. "alternative" distinguishes the consolation reward from the drawn one.

mc_crate_selective_confirms_total ​

counter crate reward

Choices confirmed in selective mode, where the player picks their reward.

mc_crate_types ​

gauge enabled

Crate types declared.

Configuration ​

In metrics.properties, or as environment variables. See Configuration.

KeyDefaultEnvironment variable
collector.cratetrueVANIA_METRICS_COLLECTOR_CRATE
collector.crate.interval30VANIA_METRICS_COLLECTOR_CRATE_INTERVAL
collector.crate.player_reward_winstrueVANIA_METRICS_COLLECTOR_CRATE_PLAYER_REWARD_WINS

Minecraft 1.21.11 · core 0.6.0 · rebuilt after every CI run