PlaceholderAPI
KaMenu includes a built-in PlaceholderAPI (PAPI) extension that exposes plugin data as placeholder variables for use in other plugins (such as scoreboards and chat plugins).
Prerequisites#
Requires the PlaceholderAPI plugin. KaMenu will automatically register the extension on startup — no extra steps needed.
Variable Types Overview#
| Variable Type | Prefix | Data Source | Persistent | Description |
|---|---|---|---|---|
| Player Data | %kamenu_data_<key>% |
Database | ✅ Yes | Per-player persistent data |
| Global Data | %kamenu_gdata_<key>% |
Database | ✅ Yes | Server-wide shared data |
| Player List | %kamenu_list_<key>% |
Database | ✅ Yes | Per-player persistent string list, returned as a JSON array |
| Global List | %kamenu_glist_<key>% |
Database | ✅ Yes | Server-wide shared string list, returned as a JSON array |
| Player List Size | %kamenu_list_size_<key>% |
Database | ✅ Yes | Number of items in a player's list |
| Global List Size | %kamenu_glist_size_<key>% |
Database | ✅ Yes | Number of items in a global list |
| Online Player List | %kamenu_online_players% |
Online players | ❌ No | Current online player names, returned as a JSON array |
| Player Metadata | %kamenu_meta_<key>% |
Memory | ❌ No | Temporary cached player data |
| Item Properties | %kamenu_checkitem_[source;property]% |
Player Inventory / Memory | ❌ No | Read common properties from held, slotted, or saved items |
| Inventory Items | %kamenu_hasitem_[item attributes]% |
Player Inventory | — | Count of matching items in player's inventory |
| Stock Items | %kamenu_hasstockitem_<itemName>% |
Player Inventory | — | Count of a saved stock item in player's inventory |
Quick Navigation:
- Player Data Variables
- Global Data Variables
- List Variables
- Online Player List Variable
- Player Metadata Variables
- Item Property Variables
- Inventory Item Variables
- Stock Item Variables
Provided Variables#
Player Data Variables#
Reads persistent per-player data (written via the set-data short form or the data: parameter action).
Format: %kamenu_data_<key>%
Examples:
| Variable | Description |
|---|---|
%kamenu_data_vip_level% |
Reads the player's vip_level data |
%kamenu_data_nickname% |
Reads the player's nickname data |
%kamenu_data_sign_count% |
Reads the player's sign_count data |
Usage in other plugins (e.g. CMI scoreboard):
# Scoreboard config example
scoreboard:
- '&6VIP Level: &f%kamenu_data_vip_level%'
- '&7Nickname: &f%kamenu_data_nickname%'
Global Data Variables#
Reads server-wide shared data (written via the set-gdata short form or the gdata: parameter action).
Format: %kamenu_gdata_<key>%
Examples:
| Variable | Description |
|---|---|
%kamenu_gdata_server_event% |
Reads the global server_event data |
%kamenu_gdata_event_winner% |
Reads the global event_winner data |
Usage in other plugins:
# Announcement config example
announcements:
- 'Current event status: %kamenu_gdata_server_event%'
- 'Last event winner: %kamenu_gdata_event_winner%'
List Variables#
Reads KaMenu built-in list data and returns a JSON string array. This is suitable for dynamic button repeat.source and inList / inGlist condition list parameters.
Format:
%kamenu_list_<key>%: read the current player's list%kamenu_glist_<key>%: read a global list
Examples:
| Variable | Description |
|---|---|
%kamenu_list_friends% |
Current player's friends list |
%kamenu_glist_servers% |
Global servers list |
%kamenu_list_size_friends% |
Item count of the current player's friends list |
%kamenu_glist_size_servers% |
Item count of the global servers list |
Bottom:
type: multi
buttons:
friends:
type: repeat
source: "%kamenu_list_friends%"
item:
text: "&a{item.value}"
Using in conditions:
condition: "%kamenu_list_size_friends% > 0"
condition: "%kamenu_glist_size_servers% >= 3"
Online Player List Variable#
Reads current online player names and returns a JSON string array.
Format: %kamenu_online_players%
Example return value:
["Steve","Alex","Notch"]
Using with dynamic buttons:
Bottom:
type: multi
buttons:
online_players:
type: repeat
source: "%kamenu_online_players%"
item:
text: "&a{item.value}"
Using in conditions:
condition: "inGlist.$(target);%kamenu_online_players%"
Player Metadata Variables#
Reads temporary in-memory metadata for a player (written via the set-meta short form or the meta: parameter action).
Format: %kamenu_meta_<key>%
Examples:
| Variable | Description |
|---|---|
%kamenu_meta_time% |
Reads the player's time metadata |
%kamenu_meta_last_menu% |
Reads the player's last_menu metadata |
%kamenu_meta_temp_data% |
Reads the player's temp_data metadata |
Usage in other plugins:
# Scoreboard config example (showing temporary data)
scoreboard:
- '&6Last Visit: &f%kamenu_meta_time%'
- '&7Temp Status: &f%kamenu_meta_temp_status%'
Notes:
- Metadata is stored in memory only and is not persisted to the database
- Player metadata is automatically cleared when the player disconnects
- All metadata is cleared when the plugin is reloaded or the server stops
- Returns
"null"if the data does not exist
Item Property Variables#
KaMenu can read common item properties. Prefer the built-in brace variable in menus because it does not require PlaceholderAPI; use PAPI when another plugin needs the value:
{checkitem:[hand;name]}
%kamenu_checkitem_[hand;name]%
Both forms use the same sources, properties, and return values.
Parameter structure:
{checkitem:[<item location>;<output property>;<optional format>]}
%kamenu_checkitem_[<item location>;<output property>;<optional format>]%
checkitem accepts up to three parameters separated by English semicolons (;):
| Order | Parameter | Required | Purpose |
|---|---|---|---|
| First | Item location/source | ✅ | Locates the item to read, such as hand, offhand, slot:0, or stock:Magic Sword |
| Second | Output property | ✅ | Selects the exact value to return, such as name, lore:1, ench:sharpness, or dura_pct |
| Third | Text format | ❌ | Uses fmt:plain, fmt:legacy, or fmt:mini; defaults to fmt:plain when omitted |
For example, {checkitem:[slot:0;lore:1;fmt:mini]} consists of:
slot:0: locate slot0in the player's inventory.lore:1: return lore line1from that item; lore line numbers start at1.fmt:mini: convert that line to MiniMessage format.
Semicolons (;) separate the three top-level parameters, while colons (:) assign values inside a parameter. Therefore slot:0, lore:1, and fmt:mini are each one complete parameter. Inventory slots start at 0, while lore line numbers start at 1.
Item sources:
| Source | Description |
|---|---|
hand |
Current player's main-hand item |
offhand |
Current player's off-hand item |
slot:<index> |
A Bukkit player inventory slot |
stock:<name> |
KaMenu saved-item storage; reads the memory cache without querying SQL |
itemsadder:<namespace:id> / ia:<namespace:id> |
ItemsAdder item template |
oraxen:<id> |
Oraxen item template |
craftengine:<namespace:id> / ce:<namespace:id> |
CraftEngine item template |
Properties:
| Property | Return value |
|---|---|
type |
Full material ID, such as minecraft:diamond_sword |
custom_id / external_id / item_id |
Canonical external ID including KaMenu's provider prefix; empty for vanilla items |
plugin_id / native_id |
The plugin's native item ID without KaMenu's provider prefix |
plugin / provider |
ItemsAdder, Oraxen, or CraftEngine; empty for vanilla items |
amt |
Stack amount |
name |
Effective item display name |
lore |
Lore as a JSON string array |
lore:<line> |
One lore line, starting at 1; lore:1 means the first line |
enchants |
A JSON array such as [ {"key":"minecraft:sharpness","level":5} ] |
ench:<enchantment ID> |
Enchantment level; returns 0 when absent |
model / item_model |
Item-model NamespacedKey |
cmd / custom_model_data / custom_model_id |
Custom model ID, returned as an integer by default; empty when absent |
dmg |
Consumed durability |
dura |
Remaining durability |
dura_pct |
Remaining durability from 0 to 100, without % |
Names and lore use plain text by default. The format option uses fmt:<format> as the third semicolon-separated argument:
| Format option | Returned content |
|---|---|
fmt:plain |
Plain text and the default; removes colors and events |
fmt:legacy |
Preserves & Legacy color formatting |
fmt:mini |
Converts to MiniMessage format |
fmt only affects name, lore, and lore:<line>. Material, model, enchantment, and numeric properties are unaffected.
Each line below is an independent example for its corresponding menu field. Do not place multiple duplicate text keys in the same YAML node:
# Return the effective display name of the main-hand item; plain text is used because fmt is omitted
text: '&fMain hand: {checkitem:[hand;name]}'
# Return remaining main-hand durability as a percentage; the placeholder does not include the percent sign
text: '&7Durability: {checkitem:[hand;dura_pct]}%'
# Check whether the main-hand item has Sharpness level 5 or higher
condition: '{checkitem:[hand;ench:sharpness]} >= 5'
# Return all enchantments from the saved “Legendary Sword” as JSON for use as a repeat source
source: '{checkitem:[stock:Legendary Sword;enchants]}'
# Return lore line 1 from the saved “Legendary Sword” and convert it to MiniMessage format
text: '{checkitem:[stock:Legendary Sword;lore:1;fmt:mini]}'
# Return both the main-hand ItemModel NamespacedKey and integer CustomModelData
text: 'Model: {checkitem:[hand;item_model]} / ID: {checkitem:[hand;custom_model_id]}'
# Read an ItemsAdder template name and identify the external item in the player's main hand
text: '{checkitem:[itemsadder:my_pack:magic_sword;name;fmt:mini]}'
condition: '{checkitem:[hand;custom_id]} == itemsadder:my_pack:magic_sword'
Vanilla enchantments may omit minecraft:, such as ench:sharpness. Custom enchantments require their full namespace, such as ench:myplugin:lifesteal.
When a saved-item name contains semicolons, wrap the item name in backticks to avoid conflicts with YAML single- or double-quoted strings:
text: '{checkitem:[stock:`Event;Sword`;name]}'
The outer YAML value may still use single or double quotes. Only backticks delimit the inner item name; checkitem does not treat single or double quotes as argument delimiters.
Missing strings return an empty string, missing numbers return 0, and missing lists return []. Player inventory sources and external-plugin item templates can only be read on the Paper main thread or the player's current Folia region thread. Asynchronous third-party PAPI requests do not block across threads and therefore receive empty values. The stock: source is not subject to this restriction.
Inventory Item Variables#
Counts matching vanilla or external-plugin items (by item ID, lore, or model) in the player's inventory.
Format: %kamenu_hasitem_[mats=material;lore=description;model=item-model;custom_model_id=integer-ID]%
mats accepts vanilla materials and the external prefixes itemsadder:/ia:, oraxen:, and craftengine:/ce:. External items match by their plugin item ID.
Parameter Description:
| Parameter | Required | Description | Example |
|---|---|---|---|
mats |
✅ Yes | Item material type | DIAMOND, GOLD_INGOT, IRON_INGOT |
lore |
❌ No | Item lore text (fuzzy match) | artifact, crafting material |
model / item_model |
❌ No | ItemModel (namespace:key format) | minecraft:custom_item |
cmd / custom_model_data / custom_model_id |
❌ No | Integer CustomModelData | 10001 |
Examples:
| Variable | Description |
|---|---|
%kamenu_hasitem_[mats=DIAMOND]% |
Returns the count of diamonds in the player's inventory |
%kamenu_hasitem_[mats=GOLD_INGOT]% |
Returns the count of gold ingots in the player's inventory |
%kamenu_hasitem_[mats=DIAMOND;lore=artifact]% |
Returns the count of diamonds with "artifact" in their lore |
%kamenu_hasitem_[mats=IRON_INGOT;lore=crafting material;model=custom:iron]% |
Returns the count of iron ingots matching material, lore, and model |
%kamenu_hasitem_[mats=PAPER;custom_model_id=10001]% |
Returns the number of paper items with custom model ID 10001 |
Usage in menus:
# Display item count
Body:
diamond_info:
type: 'message'
text: '&aDiamonds in inventory: &f%kamenu_hasitem_[mats=DIAMOND]%'
# Conditional check
Bottom:
type: 'multi'
buttons:
check_diamond:
text: '&aUse Diamonds'
actions:
- condition: '%kamenu_hasitem_[mats=DIAMOND]% >= 10'
allow:
- 'tell: &aYou have enough diamonds!'
deny:
- 'tell: &cNot enough diamonds, you only have %kamenu_hasitem_[mats=DIAMOND]%'
Stock Item Variables#
Counts how many of a saved stock item the player has in their inventory.
Format: %kamenu_hasstockitem_<itemName>%
Parameter Description:
| Parameter | Required | Description |
|---|---|---|
itemName |
✅ Yes | The name of the saved stock item |
Examples:
| Variable | Description |
|---|---|
%kamenu_hasstockitem_MysticFruit% |
Returns the count of "MysticFruit" in the player's inventory |
%kamenu_hasstockitem_TeleportScroll% |
Returns the count of "TeleportScroll" in the player's inventory |
%kamenu_hasstockitem_AdvancedExpBook% |
Returns the count of "AdvancedExpBook" in the player's inventory |
Usage in menus:
# Display stock item count
Body:
fruit_info:
type: 'message'
text: '&aMystic Fruits: &f%kamenu_hasstockitem_MysticFruit%'
# Conditional check
Bottom:
type: 'multi'
buttons:
use_fruit:
text: '&aUse Mystic Fruit'
actions:
- condition: '%kamenu_hasstockitem_MysticFruit% >= 5'
allow:
- 'tell: &aYou have enough Mystic Fruits!'
deny:
- 'tell: &cNot enough Mystic Fruits, you only have %kamenu_hasstockitem_MysticFruit%'
Notes:
- The item name must match the filename in the item stock
- Returns
0if the item does not exist - Item matching uses the
isSimilarmethod, which includes material and NBT - Returns the total count of all matching items regardless of stack size
Using PAPI Variables Inside KaMenu Menus#
KaMenu fully supports parsing variables from other PAPI extensions — use them in any text field or condition inside a menu:
Menu Title#
Title: '&aWelcome, &f%player_name%!'
Component Text#
Body:
stats:
type: 'message'
text: '&7Level: &f%player_level% &7| Health: &c%player_health%'
Conditions#
condition: "%player_level% >= 10 && %player_balance% >= 500"
Actions#
actions:
- 'tell: &aHello, %player_name%! You are in %player_world%.'
- 'console: give %player_name% diamond 1'
Handling Missing Data#
When the specified key does not exist:
PAPI Variables (
%kamenu_data_key%):- Returns the message defined in the language file (key:
papi.data_not_found) - Defaults to an empty string
- Can be customized in the language file
- Returns the message defined in the language file (key:
Built-in Variables (
{data:key}):- Returns the literal string
"null" - You can use
{data:key} == nullin conditions to check if data exists - Example:
{data:counter} != nullmeans the data exists
- Returns the literal string
PAPI Metadata Variables (
%kamenu_meta_key%):- Returns the literal string
"null" - Metadata is stored in memory only; it is automatically cleared when the player disconnects or the plugin is reloaded
- You can use
{meta:key} == nullin conditions to check if metadata exists
- Returns the literal string
Example:
# Check if data exists using built-in variable
actions:
- condition: "{data:counter} != null"
allow:
- 'tell: Data exists, value: {data:counter}'
deny:
- 'tell: Data does not exist'
# In scoreboard using PAPI variable (shows default prompt if not found)
scoreboard:
- '&6Visit Count: &f%kamenu_data_visit_count%'
# If visit_count does not exist, shows the default prompt or empty string
Usage Scenario Examples#
Display Player Data on Scoreboard#
scoreboard:
title: '&6Player Info'
lines:
- '&aPlayer: &f%player_name%'
- '&bLevel: &f%player_level%'
- '&cVIP: &f%kamenu_data_vip_level%'
- '&dNickname: &f%kamenu_data_nickname%'
- '&eVisits: &f%kamenu_data_visit_count%'
Display Global Data on Announcement Board#
announcements:
- '&6Current Event: &f%kamenu_gdata_server_event%'
- '&aWinner: &f%kamenu_gdata_event_winner%'
- '&bServer Status: &f%kamenu_gdata_server_status%'
Use in Chat Format#
chat_format:
format: '&7[%kamenu_data_vip_level%&7] &f%player_name%: &7%message%'
# If the player has no VIP level data, shows [] or a custom prompt
Store Temporary State with Metadata#
# Set temporary data in a menu
actions:
- 'set-meta: last_visit %player_time%'
- 'set-meta: temp_status shopping'
# Read temporary data in another menu
Title: 'Welcome back, %player_name%'
Body:
status:
type: 'message'
text: '&7Last Visit: %kamenu_meta_last_visit% | Status: %kamenu_meta_temp_status%'
Display Item Counts on Scoreboard#
scoreboard:
title: '&6Inventory Info'
lines:
- '&aPlayer: &f%player_name%'
- '&6Diamonds: &f%kamenu_hasitem_[mats=DIAMOND]%'
- '&eGold Ingots: &f%kamenu_hasitem_[mats=GOLD_INGOT]%'
- '&7Iron Ingots: &f%kamenu_hasitem_[mats=IRON_INGOT]%'
- '&dMystic Fruits: &f%kamenu_hasstockitem_MysticFruit%'
- '&bTeleport Scrolls: &f%kamenu_hasstockitem_TeleportScroll%'
Item Condition Check in Menu#
# Check if the player has enough diamonds
Bottom:
type: 'multi'
buttons:
buy_item:
text: '&aBuy Item'
actions:
- condition: '%kamenu_hasitem_[mats=DIAMOND]% >= 10'
allow:
- 'tell: &aPayment successful!'
- 'command: give %player_name% diamond_sword 1'
- 'console: clear %player_name% diamond 10'
deny:
- 'tell: &cNot enough diamonds! You need 10 diamonds.'
use_fruit:
text: '&bUse Mystic Fruit'
actions:
- condition: '%kamenu_hasstockitem_MysticFruit% >= 1'
allow:
- 'tell: &aUsed a Mystic Fruit!'
- 'command: effect %player_name% regeneration 600 2'
- 'data: take MysticFruit 1'
deny:
- 'tell: &cYou have no Mystic Fruits!'
Notes#
- PAPI Plugin Dependency: PlaceholderAPI must be installed to use these variables
- Data Persistence:
- Data written by
set-data/data:andset-gdata/gdata:is persisted to the database - Data written by
set-meta/meta:is stored in memory only and is not persisted
- Data written by
- Key Prefixes: Player data, global data, and metadata use different prefixes (
data_,gdata_,meta_) and have different storage locations and lifetimes - Type Limitation: All data is stored as strings; type conversion must be handled as needed
- Performance: Reading large amounts of data frequently may impact performance — use wisely
- Checking Data Existence:
- PAPI variables: returns a prompt or empty string if data does not exist
- Built-in variables: returns
"null"if data does not exist, suitable for condition checks - Metadata: returns
"null"if data does not exist; automatically cleared on disconnect or reload
- Metadata Lifecycle:
- Metadata is stored in memory only
- Player metadata is cleared on disconnect
- All metadata is cleared on plugin reload or server shutdown
- Suitable for storing temporary short-lived data
- Item Variable Features:
hasitemvariables support multi-condition matching (material, lore, ItemModel, integer CustomModelData)hasstockitemvariables use the saved stock item for exact matching- Returns
0if the item does not exist - Item count is calculated in real time as the sum of all matching items
- Supported in both conditions and text display
- Parameter Format:
- Item variables use square brackets
[]to wrap parameters (brackets are optional) - Parameters are separated by semicolons
; - Lore matching supports fuzzy matching (case-insensitive)
- Model format is
namespace:key
- Item variables use square brackets