GroupeZ Docs
Configurations

Player Data

Store and retrieve player-specific 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

On this page

GroupeZ MCP

Documentation in your AI

MCP lets your AI search GroupeZ documentation and read current examples to help you configure your plugins.

Read-only · No documentation API key needed

1. Copy the server URL

Transport: HTTP (Streamable HTTP). Authentication: none. Your tool uses its own model and subscription limits.

  1. Open Plugins in ChatGPT on the web, then + → Add custom MCP server.
  2. Name it ‘GroupeZ Documentation’, paste the URL above and choose ‘No authentication’. Create and install the plugin.
  3. In a conversation, type @ and select the plugin before asking. If needed, enable search, get_page and list_pages in its settings.
Official setup guide

3. Ask a question

Use GroupeZ MCP to help me create a zMenu inventory. Search relevant pages, read the examples and cite your sources.
Other clients and troubleshooting

For clients using mcpServers, adapt this example to their format:

{
  "mcpServers": {
    "groupez-docs": {
      "url": ""
    }
  }
}

Available tools are search, get_page and list_pages. Refresh the connector’s tools after updates. If your AI cannot access them, check that the connector is enabled in the conversation and your account allows custom MCP servers. Opening the URL in a browser is not an MCP test.