🔍 Conditions¶
KaMenu provides a powerful universal condition system that can be used in any text field and action list in menus, dynamically displaying different content or executing different actions based on player state.
Supported Locations¶
Conditions can be used in the following locations:
| Location | Description |
|---|---|
Title |
Menu title |
Body.*.text |
Body component text |
Body.*.name / Body.*.lore |
Item component name and Lore |
Body.*.type |
Component type (for conditional hiding of components) |
Inputs.*.text |
Input component label text |
Bottom.*.text |
All button text |
Bottom.*.actions |
Button action list (conditional branching) |
Events.* |
Menu event action lists (See event system) |
Text Field Conditions¶
Syntax¶
field_name:
- condition: "condition_expression"
allow: 'value when condition is met'
deny: 'value when condition is not met'
Any text inside a condition expression can use built-in placeholders such as {data:...}, {gdata:...}, {meta:...}, $(input), and {js:...}:
condition: '{js:player.getLevel() >= 10} == true'
allow: '&aLevel requirement met'
deny: '&cLevel too low'
Variable Resolution Order¶
Conditions resolve variables in the expression first, then pass the resolved expression to the condition engine and built-in condition methods.
For example:
condition: "isNull.{data:nickname}"
condition: "isNull.%player_name%"
condition: "isNull.$(nickname)"
At runtime, {data:nickname}, %player_name%, or $(nickname) is resolved first, then the resolved value is passed to isNull. Conditions inside action lists also include the current button, input component, and action-package argument context, so values such as $(input) and {arg:0} are replaced before evaluation.
Runtime variable values are treated as complete string values, not reinterpreted as condition expression syntax. Even if player input contains ||, &&, newlines, quotes, or YAML-like text, it is handled as ordinary string content.
Examples¶
Menu Title:
Title:
- condition: "%player_is_op% == true"
allow: '&8» &4&lAdmin Panel &8«'
deny: '&8» &6&lPlayer Panel &8«'
Input Component Label:
Inputs:
amount:
type: 'slider'
text:
- condition: "%player_level% >= 10"
allow: '&6VIP Purchase Quantity (max 64)'
deny: '&7Purchase Quantity (max 16)'
min: 1
max:
- condition: "%player_level% >= 10"
allow: '64'
deny: '16'
Button Text:
Bottom:
type: 'confirmation'
confirm:
text:
- condition: "%player_level% >= 10"
allow: '&6[ VIP Confirm ]'
deny: '&a[ Confirm ]'
Action List Conditions¶
Nesting conditions in actions lists enables branching execution:
Syntax¶
actions:
- condition: "condition_expression"
allow:
- 'action 1 when condition is met'
- 'action 2 when condition is met'
deny:
- 'action 1 when condition is not met'
- 'action 2 when condition is not met'
The deny field is optional; if not provided, nothing executes when the condition is not met.
Mixed Usage¶
You can mix regular actions and conditional actions in the same actions list:
actions:
- 'sound: ui.button.click' # Always executes
- condition: "%player_balance% >= 100"
allow:
- 'console: eco take %player_name% 100'
- 'tell: &aDeduction successful!'
deny:
- 'tell: &cInsufficient balance!'
- 'close' # Always executes
Condition Expression Syntax¶
Comparison Operators¶
| Operator | Description | Example |
|---|---|---|
== |
Equals | %player_name% == Steve |
!= |
Not equals | %world_name% != world_nether |
> |
Greater than | %player_level% > 10 |
>= |
Greater than or equal | %player_health% >= 10 |
< |
Less than | %player_food_level% < 18 |
<= |
Less than or equal | %player_exp% <= 100 |
Note:
- String comparisons (
==and!=) are case-insensitive by default - Strings that cannot be converted to numbers are treated as
0in numeric comparisons {js:...}can be used in conditions to dynamically compute a returned value
Logical Operators¶
| Operator | Description | Priority |
|---|---|---|
&& |
Logical AND | High |
\|\| |
Logical OR | Low |
() |
Parentheses (change priority) | Highest |
Short-circuit evaluation is supported:
||: If the first condition istrue, subsequent conditions are not evaluated&&: If the first condition isfalse, subsequent conditions are not evaluated
Expression Examples¶
# Single condition
- condition: "%player_level% >= 10"
# AND condition
- condition: "%player_level% >= 10 && %player_level% < 20"
# OR condition
- condition: "%player_is_op% == true || %player_level% >= 20"
# Using parentheses
- condition: "(%player_level% >= 5 && %player_level% <= 10) || %player_is_op% == true"
Built-in Condition Methods¶
KaMenu provides some built-in condition methods, called using the . symbol.
Syntax¶
Supported Methods¶
| Method | Description | Forward Example | Reverse Example |
|---|---|---|---|
isNull |
Check whether a value is empty. Empty strings, whitespace-only strings, and null are treated as empty |
isNull.$(nickname) |
!isNull.{data:nickname} |
isPass |
Check whether a value is an absolute empty string. Only length 0 passes; whitespace strings do not pass |
isPass.$(nickname) |
!isPass.$(nickname) |
isTrue |
Check whether a value is true. Accepts true, yes, and 1; true / yes are case-insensitive |
isTrue.$(agree) |
!isTrue.{data:enabled} |
getLength |
Output string length, usually used with comparison operators | getLength.%player_name% >= 3 |
getLength.$(nickname) == 0 |
isNum |
Check if value is a number (integer or decimal) | isNum.$(amount) |
!isNum.$(amount) |
isPosNum |
Check if value is a positive number (>0) | isPosNum.{data:price} |
!isPosNum.{data:price} |
isInt |
Check if value is an integer | isInt.$(count) |
!isInt.$(count) |
isPosInt |
Check if value is a positive integer (>0) | isPosInt.$(amount) |
!isPosInt.$(amount) |
hasPerm |
Check if player has permission | hasPerm.kamenu.admin |
!hasPerm.kamenu.admin |
hasMoney |
Check if player has enough coins | hasMoney.100 |
!hasMoney.100 |
hasItem |
Check if player inventory has specified material/quantity | hasItem.[mats=DIAMOND;amount=10] |
!hasItem.[mats=DIAMOND;amount=10] |
hasStockItem |
Check if player inventory has stored item | hasStockItem.MysticFruit;16 |
!hasStockItem.MysticFruit;16 |
inList / inGlist |
Check whether a value is in a player/global list | inGlist.%player_name%;{glist:vip_players} |
!inList.%player_name%;Steve,Alex |
For detailed usage of item checks, see hasItem and hasStockItem Condition Methods.
Usage Examples¶
Check if input value is an integer:
actions:
- condition: "isInt.$(amount)"
allow:
- 'tell: &aInput value is an integer: $(amount)'
deny:
- 'tell: &cPlease enter a valid integer!'
Check whether input or data is empty:
actions:
- condition: "isNull.$(nickname)"
allow:
- 'toast: type=error;msg=Enter name;icon=barrier'
- 'return'
- condition: "!isNull.{data:nickname}"
allow:
- 'tell: &aSaved nickname: {data:nickname}'
isNull can be used with PAPI, KaMenu internal variables, and input component values:
Check whether a value is an absolute empty string:
actions:
- condition: "isPass.$(nickname)"
allow:
- 'toast: type=error;msg=Enter name;icon=barrier'
- 'return'
isPass only passes when the value length is 0. One or more spaces do not pass; use isNull if whitespace should count as empty.
Check whether a value is true:
actions:
- condition: "isTrue.$(agree)"
allow:
- 'toast: type=task;msg=Accepted;icon=emerald'
deny:
- 'toast: type=error;msg=Check first;icon=barrier'
- 'return'
isTrue accepts true, yes, and numeric 1; true and yes are case-insensitive. Other values, empty values, and whitespace-only strings are treated as false.
Check string length:
actions:
- condition: "getLength.%player_name% >= 3"
allow:
- 'tell: &aYour name length is at least 3'
- condition: "getLength.$(nickname) > 12"
allow:
- 'toast: type=error;msg=Name long;icon=barrier'
- 'return'
getLength.xxx resolves variables first, then outputs the length of the resolved string. It is a value function and is usually used with ==, !=, >, >=, <, or <=.
Check if value is a positive integer:
actions:
- condition: "isPosInt.$(amount)"
allow:
- 'tell: &aValid positive integer: $(amount)'
deny:
- 'tell: &cPlease enter an integer greater than 0!'
Check if player has enough coins:
actions:
- condition: "hasMoney.100"
allow:
- 'console: eco take %player_name% 100'
- 'tell: &aPurchase successful!'
deny:
- 'tell: &cInsufficient balance, 100 coins required'
Check whether a value is in a list:
actions:
- condition: "inGlist.%player_name%;{glist:vip_players}"
allow:
- 'toast: type=task;msg=Listed;icon=emerald'
deny:
- 'toast: type=error;msg=Not listed;icon=barrier'
inList and inGlist use the same membership logic and are named for player-list and global-list scenarios. Parameter format is value;list, and the list supports:
- JSON array strings returned by
{list:key}/{glist:key} - JSON string arrays, such as
["Steve","Alex"] - Simple string lists, such as
Steve,Alex,Notch
Membership matching is exact and case-insensitive by default.
Permission check (forward):
Bottom:
confirm:
text: 'Admin Operation'
actions:
- condition: "hasPerm.kamenu.admin"
allow:
- 'open: admin_panel'
deny:
- 'tell: &cYou don''t have permission to perform this action!'
Permission check (reverse - execute when no permission):
Bottom:
confirm:
text: 'Admin Operation'
actions:
- condition: "!hasPerm.kamenu.admin"
allow:
- 'tell: &cYou don''t have permission!'
Check if player has 10 diamonds:
actions:
- condition: "hasItem.[mats=DIAMOND;amount=10]"
allow:
- 'tell: &aYou have enough diamonds!'
deny:
- 'tell: &cYou need 10 diamonds!'
Check if player has 16 Mystic Fruits:
actions:
- condition: "hasStockItem.MysticFruit;16"
allow:
- 'tell: &aYou have enough Mystic Fruits!'
deny:
- 'tell: &cYou need 16 Mystic Fruits!'
Variable Support¶
The following variable formats are supported in condition expressions:
| Variable Format | Description | Example |
|---|---|---|
%papi_var% |
PlaceholderAPI variable | %player_level% |
{data:key} |
Player personal data (persistent) | {data:vip_level} |
{gdata:key} |
Global shared data (persistent) | {gdata:server_status} |
{meta:key} |
Player metadata (memory cache) | {meta:last_visit} |
$(key) |
Dialog input variable (only supported in Actions and Inputs, not in Body) | $(amount) |
Body Area Special Notes:
- Text in the Body area is rendered before dialog and button inputs, so does not support
$(key)input variables - Body area supports
{data:key},{gdata:key}, and{meta:key}internal variables - Inputs and Actions areas support all variable formats
Metadata Notes:
- Metadata is only stored in memory, not persisted to database
- Automatically cleaned when player disconnects
- All metadata is cleared on plugin reload or server shutdown
- Suitable for scenarios requiring short-term temporary data storage
Complete Examples¶
Example 1: VIP Level Check¶
Bottom:
type: 'notice'
confirm:
text: '&aClaim Daily Reward'
actions:
- condition: "%player_level% >= 10"
allow:
- 'console: give %player_name% diamond 5'
- 'tell: &a&lVIP Reward: &f5 diamonds'
- 'title: title=&6Claim successful;subtitle=&fVIP exclusive reward;in=5;keep=40;out=10'
deny:
- 'console: give %player_name% dirt 1'
- 'tell: &7Normal reward: 1 dirt'
- 'tell: &eReach level 10 to claim VIP rewards!'
Example 2: Admin Operation¶
Bottom:
type: 'multi'
columns: 2
buttons:
admin_panel:
text:
- condition: "%player_is_op% == true"
allow: '&4[ Admin Panel ]'
deny: '&8[ Locked ]'
actions:
- condition: "%player_is_op% == true"
allow:
- 'open: admin/tools'
deny:
- 'tell: &cYou don''t have permission to access the admin panel!'
Example 3: Balance Check¶
actions:
- condition: "hasMoney.1000"
allow:
- 'console: eco take %player_name% 1000'
- 'tell: &aPurchase successful! Spent 1000 coins'
- 'sound: entity.player.levelup'
deny:
- 'tell: &cInsufficient balance! 1000 coins required'
- 'tell: &7Current balance: &f%player_balance%'
- 'sound: block.note_block.bass'
Example 4: Complex Multi-Condition¶
actions:
- condition: "(%player_level% >= 5 && %player_level% <= 10) || %player_is_op% == true"
allow:
- 'tell: &aCondition passed: You are a level 5-10 player, or you are an admin'
deny:
- 'tell: &cCondition not met'
Example 5: Metadata State Check¶
actions:
- condition: "{meta:temp_status} != null"
allow:
- 'tell: &aTemporary status exists: {meta:temp_status}'
deny:
- 'tell: &7No temporary status set'
- 'set-meta: last_action clicked'
Example 6: Metadata Combined with Conditions¶
actions:
# Set temporary status
- 'set-meta: temp_user true'
- condition: "{meta:temp_user} == true"
allow:
- 'tell: &aMarked as temporary user'
- 'open: temp_menu'
deny:
- 'tell: &cNot marked as temporary user'
Example 7: Using Built-in Methods to Validate Input¶
Inputs:
amount:
type: 'input'
text: 'Please enter quantity (positive integer)'
actions:
- condition: "isPosInt.$(amount)"
allow:
- 'tell: &aValid input: $(amount)'
- 'set-meta: purchase_amount $(amount)'
deny:
- 'tell: &cPlease enter an integer greater than 0!'
- 'close'
Example 8: Reverse Permission Check (prompt when no permission)¶
Bottom:
confirm:
text: 'Purchase VIP'
actions:
# Prompt when no permission (reverse check)
- condition: "!hasPerm.vip.purchase"
allow:
- 'tell: &cYou need to purchase the vip.purchase permission to perform this action!'
deny: []
# Execute purchase logic when has permission
- condition: "hasPerm.vip.purchase"
allow:
- 'console: eco give %player_name% 1000'
- 'tell: &a1000 coins credited as VIP reward!'
Notes¶
- PAPI Dependency: Using
%papi_var%format requires PlaceholderAPI plugin to be installed - Numeric Conversion: Strings that cannot be converted to numbers are treated as
0in numeric comparisons (>,<, etc.) - Case Insensitive:
==and!=operators are case-insensitive in string comparisons - deny is Optional: The
denyfield in action conditions is optional; for text field conditions,denyis recommended to avoid blank display - Nested Parentheses: Supports multiple levels of nested parentheses to build complex logical expressions
- Data Persistence:
{data:key}and{gdata:key}are stored in database, persisted{meta:key}is only stored in memory, automatically cleared after player disconnect or plugin reload- Use
{meta:key} != nullto check if metadata exists
- Built-in Method Format:
- Use
method.valueformat, e.g.,isInt.$(amount) - Supports reverse checks using
!prefix, e.g.,!hasPerm.kamenu.admin - Reverse checks are useful for scenarios requiring operations when conditions are not met
- Use
Related Documents¶
- 🍉 hasItem and hasStockItem Condition Methods - Learn detailed usage of item checks
- ⚙️ Events - Learn detailed usage of the event system
- 🤖 Actions - Learn all available action types
- 💾 Data Storage - Learn about data storage and variable usage
Demo Menu¶
The plugin includes a demo menu for conditions, which can be opened with the following command: