Skip to main content

Player Data

zMenu includes a built-in player data system that allows you to store and retrieve values specific to each player. This is perfect for tracking progress, creating toggles, storing statistics, and more.

How It Works​

Player data is stored in a database (SQLite by default, MySQL/MariaDB optional) and persists across server restarts. Each player has their own set of key-value pairs.

Accessing Player Data​

Placeholder​

Use the %zmenu_player_value_<key>% placeholder:

item:
name: "&6Coins: %zmenu_player_value_coins%"
lore:
- "&7Kills: %zmenu_player_value_kills%"
- "&7Deaths: %zmenu_player_value_deaths%"

Commands​

# Set a value
/zm players set <player> <key> <value>

# Add to a value (numeric)
/zm players add <player> <key> <value>

# Get a value
/zm players get <player> <key>

# Remove a key
/zm players remove <player> <key>

# Remove a key from ALL players
/zm players removeall <key>

# List all keys for a player
/zm players keys <player>

Modifying Data with Actions​

The Data Action​

actions:
- type: data
action: SET # SET, ADD, SUBTRACT, MULTIPLY, DIVIDE, REMOVE
key: "coins"
value: "100"
math: true # Enable math expressions

Actions​

ActionDescriptionExample
SETSet to a specific valuevalue: "100"
ADDAdd to current valuevalue: "50"
SUBTRACTSubtract from currentvalue: "25"
MULTIPLYMultiply current valuevalue: "2"
DIVIDEDivide current valuevalue: "2"
REMOVERemove the key entirely-

Math Expressions​

Enable math with math: true:

actions:
- type: data
action: SET
key: "total"
value: "%zmenu_player_value_base%*1.5+100"
math: true

Examples​

Coins/Currency System​

# Display coins
items:
coin-display:
slot: 4
item:
material: GOLD_NUGGET
name: "&6&lYour Coins"
lore:
- "&7Balance: &e%zmenu_player_value_coins%"

# Add coins button
add-coins:
slot: 11
item:
material: GOLD_INGOT
name: "&a&l+100 Coins"
actions:
- type: data
action: ADD
key: "coins"
value: "100"
- type: message
messages:
- "&a+100 coins!"
- type: refresh

# Spend coins
spend-coins:
slot: 15
item:
material: DIAMOND
name: "&b&lBuy Diamond"
lore:
- "&7Cost: &e50 coins"
click-requirement:
purchase:
clicks:
- ALL
requirements:
- type: placeholder
placeholder: "%zmenu_player_value_coins%"
action: SUPERIOR_OR_EQUAL
value: 50
deny:
- type: message
messages:
- "&cYou need 50 coins!"
success:
- type: data
action: SUBTRACT
key: "coins"
value: "50"
- type: console-command
commands:
- "give %player% diamond 1"
- type: refresh

Toggle Setting​

items:
toggle-notifications:
type: SWITCH
slot: 13
placeholder: "%zmenu_player_value_notifications%"
buttons:
"true":
item:
material: LIME_DYE
name: "&a&lNotifications: ON"
lore:
- "&7Click to turn off"
actions:
- type: data
action: SET
key: "notifications"
value: "false"
- type: refresh

"false":
item:
material: GRAY_DYE
name: "&7&lNotifications: OFF"
lore:
- "&7Click to turn on"
actions:
- type: data
action: SET
key: "notifications"
value: "true"
- type: refresh

default:
item:
material: LIME_DYE
name: "&a&lNotifications: ON"
actions:
- type: data
action: SET
key: "notifications"
value: "false"
- type: refresh

Daily Reward System​

items:
# Daily reward system
daily-reward:
slot: 22
item:
material: CHEST
name: "&e&lDaily Reward"
lore:
- "&7Claim your daily reward!"
- ""
- "&7Last claim: &f%zmenu_player_value_last_daily%"
click-requirement:
claim:
clicks:
- ALL
requirements:
- type: placeholder
placeholder: "%zmenu_math_%zmenu_time_unix_timestamp%-%zmenu_player_value_last_daily%%"
action: SUPERIOR_OR_EQUAL
value: 86400 # 24 hours in seconds
deny:
- type: message
messages:
- "&cYou already claimed today's reward!"
success:
- type: data
action: SET
key: "last_daily"
value: "%zmenu_time_unix_timestamp%"
- type: console-command
commands:
- "give %player% diamond 5"
- type: data
action: ADD
key: "daily_streak"
value: "1"
- type: message
messages:
- "&aDaily reward claimed!"
- "&7Streak: &e%zmenu_player_value_daily_streak%"
- type: sound
sound: ENTITY_PLAYER_LEVELUP

Progress Tracking​

items:
quest-progress:
slot: 13
type: SWITCH
placeholder: "%zmenu_player_value_quest_1_stage%"
buttons:
"0":
item:
material: PAPER
name: "&7&lQuest: Not Started"
lore:
- "&7Click to begin"
actions:
- type: data
action: SET
key: "quest_1_stage"
value: "1"
- type: message
messages:
- "&aQuest started!"
- type: refresh

"1":
item:
material: WRITABLE_BOOK
name: "&e&lQuest: In Progress"
lore:
- "&7Stage 1: Collect 10 wood"

"2":
item:
material: WRITABLE_BOOK
name: "&e&lQuest: In Progress"
lore:
- "&7Stage 2: Craft a sword"

"complete":
item:
material: ENCHANTED_BOOK
name: "&a&lQuest: Complete!"
lore:
- "&7Click to claim reward"
glow: true
actions:
- type: console-command
commands:
- "give %player% emerald 10"
- type: data
action: SET
key: "quest_1_stage"
value: "claimed"
- type: refresh

"claimed":
item:
material: BOOK
name: "&8&lQuest: Claimed"
lore:
- "&7You've completed this quest"

default:
item:
material: PAPER
name: "&7&lQuest: Not Started"

Kill Counter​

items:
stats-display:
slot: 4
item:
material: PLAYER_HEAD
playerHead: "%player%"
name: "&a&l%player%'s Stats"
lore:
- "&8&m───────────────"
- ""
- "&7Kills: &a%zmenu_player_value_kills%"
- "&7Deaths: &c%zmenu_player_value_deaths%"
- "&7K/D Ratio: &e%zmenu_math_%zmenu_player_value_kills%/%zmenu_player_value_deaths%%"
- ""
- "&8&m───────────────"

Database Configuration​

Configure storage in config.yml:

# Storage type: SQLITE, MYSQL, MARIADB, or NONE
storage-type: SQLITE

# Database configuration (for MySQL/MariaDB)
database-configuration:
table-prefix: "zmenu_"
host: "localhost"
port: 3306
user: "username"
password: "password"
database: "zmenu"

Converting JSON to SQL​

If you previously used JSON storage:

/zm players convert

This migrates data from JSON files to the configured database.

Default Values​

If a key doesn't exist, the placeholder returns an empty string. Use default values:

# In requirements, check for existence
- type: placeholder
placeholder: "%zmenu_player_value_coins%"
action: SUPERIOR_OR_EQUAL
value: 0 # Works even if key doesn't exist

Or set defaults on first access:

items:
initialize:
slot: 0
view-requirement:
requirements:
- type: placeholder
placeholder: "%zmenu_player_value_initialized%"
action: DIFFERENT
value: "true"
item:
material: AIR
actions:
- type: data
action: SET
key: "coins"
value: "0"
- type: data
action: SET
key: "initialized"
value: "true"
- type: refresh

Best Practices​

  1. Use descriptive keys: daily_reward_claimed not drc
  2. Initialize defaults: Set initial values for new players
  3. Use math carefully: Ensure values are numeric for math operations
  4. Clean up old data: Use removeall for unused keys
  5. Backup your database: Especially before major changes
  6. Document your keys: Keep track of what data you're storing

Key Naming Conventions​

# Good examples
player_coins
quest_tutorial_complete
settings_notifications
stats_kills
daily_last_claim

# Bad examples
c # Too short
data1 # Not descriptive
x # Meaningless

Next Steps​

Copyright © 2026 GroupeZ|Build #loading...|-