Crate format
Each crate is defined in its own .yml file inside the plugins/CrateForge/crates/ folder. This page covers every field in detail.
Full example: crates/legendary.yml
# crates/legendary.yml
# ─────────────────────────────────────────────────
# Unique identifier for this crate — used in commands like /cf set legendary
id: legendary
# Display name shown in GUIs and holograms — supports MiniMessage color format
display-name: "<gradient:gold:yellow>Legendary Crate</gradient>"
# The key ID required to open this crate (must match a file in keys/)
key-id: legendary_key
# Animation to play when this crate is opened
# Options: CSGO | ROULETTE | WHEEL | QUAD | SLOT | COSMIC
# WAR | FIREWORKS | CASCADE | AUCTION | MYSTERY
animation: CSGO
# ─────────────────────────────────────────────────
# PRIZES — list of possible rewards
# ─────────────────────────────────────────────────
prizes:
# Prize entry — Legendary sword
- id: diamond_sword # Unique prize ID (used in history logs)
display-name: "<aqua>Godly Sword" # Shown in preview GUI
material: DIAMOND_SWORD # Bukkit material name
weight: 5 # Relative weight — lower = rarer
rarity: LEGENDARY # COMMON | UNCOMMON | RARE | EPIC | LEGENDARY
rewards:
- type: ITEM # Give the item itself
- type: COMMAND # Also run a command
command: "broadcast {player} won a Godly Sword!"
run-as-console: true # true = run as console, false = run as player
# Prize entry — Money reward
- id: money_1000
display-name: "<green>$1,000"
material: SUNFLOWER # Display item in preview GUI
weight: 20
rarity: RARE
rewards:
- type: MONEY
amount: 1000.0 # Requires Vault
# Prize entry — XP reward
- id: xp_levels_10
display-name: "<yellow>10 XP Levels"
material: EXPERIENCE_BOTTLE
weight: 40
rarity: UNCOMMON
rewards:
- type: XP
levels: 10 # XP levels to give
# Prize entry — Token reward
- id: premium_tokens_50
display-name: "<light_purple>50 Premium Tokens"
material: AMETHYST_SHARD
weight: 15
rarity: RARE
rewards:
- type: TOKEN
token-type: premium # Must match a token type defined in config.yml
amount: 50
# Prize entry — Command only (no item)
- id: rank_vip
display-name: "<gold>VIP Rank"
material: NETHER_STAR # Display item in preview GUI
weight: 1
rarity: LEGENDARY
rewards:
- type: COMMAND
command: "lp user {player} parent set vip"
run-as-console: true
# ─────────────────────────────────────────────────
# PITY SYSTEM
# ─────────────────────────────────────────────────
pity:
enabled: true
threshold: 50 # After this many opens, guarantee a min-rarity prize
guaranteed-min-rarity: RARE # Minimum rarity of the guaranteed prize
Field reference
Top-Level Fields
| Field | Type | Required | Description |
|---|---|---|---|
id |
String | Yes | Unique crate identifier, used in commands |
display-name |
String | Yes | MiniMessage formatted name |
key-id |
String | Yes | Must match a key file in keys/ |
animation |
String | Yes | Animation type (see Animations) |
prizes |
List | Yes | List of prize entries |
pity |
Object | No | Pity system configuration |
Prize Entry Fields
| Field | Type | Required | Description |
|---|---|---|---|
id |
String | Yes | Unique prize ID within this crate |
display-name |
String | Yes | MiniMessage name shown in preview |
material |
String | Yes | Bukkit material — shown in GUI and given for ITEM type |
weight |
Integer | Yes | Relative weight (higher = more common) |
rarity |
String | Yes | COMMON, UNCOMMON, RARE, EPIC, or LEGENDARY |
rewards |
List | Yes | List of reward actions |
limit |
Object | No | global: N (times it can be won in total) and per-player: N (by each player). A prize at its limit leaves the draw; with none left the key is not spent. See /cf limits |
Reward Types
| Type | Required Fields | Description |
|---|---|---|
ITEM |
(none extra) | Give the prize's material as an item |
MONEY |
amount: <double> |
Give money via Vault (Vault required) |
XP |
levels: <int> |
Give XP levels |
TOKEN |
token-type: <str>, amount: <int> |
Give tokens of a specific type |
CURRENCY |
currency: <name>, amount: <number> |
Give any other currency: playerpoints, xp-points, tokenmanager, coinsengine:<id>, crate-tokens:<type> |
COMMAND |
command: <str>, run-as-console: <bool> |
Run a command; {player} replaced with player name |
ENCHANT_BOOK |
enchant: <id>, level: <int> |
An EnchantsForge (or addon) book, made by EnchantsForge itself |
ENCHANT_ORB |
tier: <id> |
An EFV2Addon orb (common, rare…) |
SKILL_XP |
skill: <id>, amount: <int> |
SkillsRPG experience in that skill |
QUEST |
quest: <id> |
Starts that QuestForge quest |
The last four need their plugin installed; a crate that uses one without it says so once when it loads.
Opening many at once
Shift + right-click a crate with at least mass-open.min-keys keys opens up to mass-open.max (64)
in one go: no animation, one chat line with everything won, the best prize revealed. Pity, prize limits
and the open events apply to each crate exactly as when opened one by one. Permission
crateforge.massopen (everyone by default).
Pity Fields
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
Boolean | false |
Enable or disable the pity system |
threshold |
Integer | — | Number of opens before guaranteed prize |
guaranteed-min-rarity |
String | — | Minimum rarity of the pity prize |
Weight system explained
Prizes are selected by weighted random. Higher weight = more likely to be selected.
prizes:
- id: common_prize
weight: 100 # Very common
- id: rare_prize
weight: 10 # 10x less likely than common_prize
- id: legendary_prize
weight: 1 # 100x less likely than common_prize
Total weight = 111. Chance of each:
- Common: 100/111 = ~90.1%
- Rare: 10/111 = ~9.0%
- Legendary: 1/111 = ~0.9%
MiniMessage format
Display names support full MiniMessage formatting:
display-name: "<gradient:gold:yellow>Legendary Crate</gradient>"
display-name: "<red><bold>Epic Prize</bold></red>"
display-name: "<rainbow>Rainbow Prize</rainbow>"
display-name: "<aqua>Normal Prize</aqua>"
Placeholder substitution (v1.0.0 fix)
CrateForge interpolates {name} style placeholders inside messages.yml and per-prize command: strings. A v1.0.0 release fix corrected a regression where these brace placeholders were being passed through unreplaced (the renderer used a non-matching key syntax internally). Every templated message and command now substitutes correctly:
# messages.yml — brace placeholders now resolve correctly
key-given: "Gave {amount}x {key} to {player}."
key-received: "You received {amount}x {key}!"
# crate prize commands — {player} still resolves as before
rewards:
- type: COMMAND
command: "lp user {player} parent set vip"
run-as-console: true
If you customized messages.yml and noticed literal {player} / {crate} / {prize} text appearing in chat on an earlier build, this fix makes them render properly without any config change on your part.