# PlaceholderAPI

KaMenu includes a built-in PlaceholderAPI (PAPI) expansion that exposes plugin data as placeholder variables usable in other plugins (such as scoreboards and chat plugins).

***

## Prerequisites

Requires installation of [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) plugin. KaMenu will automatically register the expansion on startup, with no extra steps required.

***

## 📊 Variable Type Overview

| Variable Type       | Prefix                               | Data Source      | Persistence | Description                                                                     |
| ------------------- | ------------------------------------ | ---------------- | ----------- | ------------------------------------------------------------------------------- |
| **Player Data**     | `%kamenu_data_<key>%`                | Database         | ✅ Yes       | Persisted personal data for players                                             |
| **Global Data**     | `%kamenu_gdata_<key>%`               | Database         | ✅ Yes       | Server-wide shared data                                                         |
| **Player Metadata** | `%kamenu_meta_<key>%`                | Memory           | ❌ No        | Temporarily cached player data                                                  |
| **Inventory Items** | `%kamenu_hasitem_[item attributes]%` | Player inventory | -           | Queries the number of items in the player's inventory that match the conditions |
| **Storage Items**   | `%kamenu_hasstockitem_<item name>%`  | Player inventory | -           | Queries the number of the specified storage item in the player's inventory      |

**Quick Navigation:**

* 📦 [Player Data Variables](#玩家数据变量)
* 🌐 [Global Data Variables](#全局数据变量)
* 💾 [Player Metadata Variables](#玩家元数据变量)
* 🎒 [Inventory Item Variables](#背包物品变量)
* 📦 [Storage Item Variables](#存储库物品变量)

***

## Provided Variables

### Player Data Variables

Read a specific player's personal persistent data (written by the `set-data` action).

**Format:** `%kamenu_data_<key>%`

**Example:**

| 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 |

**Use in other plugins (for example, a CMI scoreboard):**

```yaml
# Scoreboard configuration example
scoreboard:
  - '&6VIP Level: &f%kamenu_data_vip_level%'
  - '&7Nickname: &f%kamenu_data_nickname%'
```

***

### Global Data Variables

Read server-wide shared global data (written by the `set-gdata` action).

**Format:** `%kamenu_gdata_<key>%`

**Example:**

| Variable                      | Description                          |
| ----------------------------- | ------------------------------------ |
| `%kamenu_gdata_server_event%` | Reads the global `server_event` data |
| `%kamenu_gdata_event_winner%` | Reads the global `event_winner` data |

**Use in other plugins:**

```yaml
# Announcement board configuration example
announcements:
  - 'Current event status: %kamenu_gdata_server_event%'
  - 'Last event winner: %kamenu_gdata_event_winner%'
```

***

### Player Metadata Variables

Read a specific player's temporary in-memory cached data (written by the `set-meta` action).

**Format:** `%kamenu_meta_<key>%`

**Example:**

| 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 |

**Use in other plugins:**

```yaml
# Scoreboard configuration example (show temporary data)
scoreboard:
  - '&6Last visit: &f%kamenu_meta_time%'
  - '&7Temporary status: &f%kamenu_meta_temp_status%'
```

**Note:**

* Metadata is stored only in memory and is not persisted to the database
* Player metadata is automatically cleared when the player logs out
* All metadata is cleared when the plugin reloads or the server shuts down
* When data does not exist, returns `"null"`

***

### Inventory Item Variables

Queries the number of normal items in the player's inventory that match the conditions (material, lore, model, etc.).

**Format:** `%kamenu_hasitem_[mats=material;lore=description;model=model]%`

**Parameter description:**

| Parameter | Required | Description                                | Example                               |
| --------- | -------- | ------------------------------------------ | ------------------------------------- |
| `mats`    | ✅ Yes    | Item material type                         | `DIAMOND`, `GOLD_INGOT`, `IRON_INGOT` |
| `lore`    | ❌ No     | Item description (supports fuzzy matching) | `artifact`, `forging material`        |
| `model`   | ❌ No     | Item model (namespace:key format)          | `minecraft:custom_item`               |

**Example:**

| Variable                                                                     | Description                                                                |
| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `%kamenu_hasitem_[mats=DIAMOND]%`                                            | Returns the number of diamonds in the inventory                            |
| `%kamenu_hasitem_[mats=GOLD_INGOT]%`                                         | Returns the number of gold ingots in the inventory                         |
| `%kamenu_hasitem_[mats=DIAMOND;lore=artifact]%`                              | Returns the number of diamonds in the inventory with the "artifact" lore   |
| `%kamenu_hasitem_[mats=IRON_INGOT;lore=forging material;model=custom:iron]%` | Returns the number of iron ingots that match the material, lore, and model |

**Use in menus:**

```yaml
# Show item count
Body:
  diamond_info:
    type: 'message'
    text: '&aDiamond count in inventory: &f%kamenu_hasitem_[mats=DIAMOND]%'

# Condition 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]% now'
```

***

### Storage Item Variables

Queries the number of the specified storage item in the player's inventory.

**Format:** `%kamenu_hasstockitem_<item name>%`

**Parameter description:**

| Parameter   | Required | Description                       |
| ----------- | -------- | --------------------------------- |
| `Item name` | ✅ Yes    | Name of the item saved in storage |

{% hint style="info" %}
**How to store items?**

Storage items must be saved to the database via a command before they can be used.

1. Hold the item you want to save
2. Execute `/km item save <item name>` command
3. For details, see:[📝 Command list - /km item](/plugins/kamenu-en/perm/commands.md#km-item)
   {% endhint %}

**Example:**

| Variable                      | Description                                                       |
| ----------------------------- | ----------------------------------------------------------------- |
| `%kamenu_hasstockitem_神秘果%`   | Returns the number of "Mystic Fruit" in the inventory             |
| `%kamenu_hasstockitem_传送卷轴%`  | Returns the number of "Teleport Scroll" in the inventory          |
| `%kamenu_hasstockitem_高级经验书%` | Returns the number of "Advanced Experience Book" in the inventory |

**Use in menus:**

```yaml
# Show storage item count
Body:
  fruit_info:
    type: 'message'
    text: '&aMystic Fruit count: &f%kamenu_hasstockitem_神秘果%'

# Condition check
Bottom:
  type: 'multi'
  buttons:
    use_fruit:
      text: '&aUse Mystic Fruit'
      actions:
        - condition: '%kamenu_hasstockitem_神秘果% >= 5'
          allow:
            - 'tell: &aYou have enough Mystic Fruit!'
          deny:
            - 'tell: &cNot enough Mystic Fruit, you only have %kamenu_hasstockitem_神秘果% now'
```

**Notes:**

* The item name must match the filename in storage
* If the item does not exist, returns `0`
* Item matching uses the `isSimilar` method, including material, NBT, etc.
* Stack size is ignored; returns the total of all matching items

***

## Using PAPI variables inside KaMenu menus

KaMenu also fully supports**parsing variables from other PAPI expansions**, and they can be used in any text field and condition check in menus:

### Menu title

```yaml
Title: '&aWelcome, &f%player_name%!'
```

### Component text

```yaml
Body:
  stats:
    type: 'message'
    text: '&7Level: &f%player_level% &7| Health: &c%player_health%'
```

### Condition check

```yaml
condition: "%player_level% >= 10 && %player_balance% >= 500"
```

### In actions

```yaml
actions:
  - 'tell: &aHello, %player_name%! You are now in %player_world%.'
  - 'console: give %player_name% diamond 1'
```

***

## Handling missing data

When the data for a specified key does not exist:

1. **PAPI variable (%kamenu\_data\_key%)**：
   * Returns the prompt defined in the language file (key:`papi.data_not_found`）
   * Returns an empty string by default
   * This prompt can be customized in the language file
2. **Built-in variable ({data:key})**：
   * Returns a literal string `"null"`
   * Can be used in condition checks `{data:key} == null` to determine whether data exists
   * For example:`{data:counter} != null` means the data exists
3. **PAPI metadata variable (%kamenu\_meta\_key%)**：
   * Returns a literal string `"null"`
   * Metadata is stored only in memory and is automatically cleared when the player logs out or the plugin reloads
   * Can be used in condition checks `{meta:key} == null` to determine whether data exists

**Example:**

```yaml
# Use built-in variables in condition checks to determine whether data exists
actions:
  - condition: "{data:counter} != null"
    allow:
      - 'tell: Data exists, value is: {data:counter}'
    deny:
      - 'tell: Data does not exist'

# Use PAPI variables in the scoreboard (show custom prompt when data does not exist)
scoreboard:
  - '&6Visits: &f%kamenu_data_visit_count%'
  # If visit_count does not exist, show the default prompt or an empty string
```

***

## Example use cases for variables

### Show player data in the scoreboard

```yaml
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%'
```

### Show global data on the announcement board

```yaml
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

```yaml
chat_format:
  format: '&7[%kamenu_data_vip_level%&7] &f%player_name%: &7%message%'
  # If the player has no VIP level data, show [empty] or a custom prompt
```

### Use metadata to store temporary state

```yaml
# Set temporary data in a menu
actions:
  - 'set-meta: last_visit %player_time%'
  - 'set-meta: temp_status shopping'

# Read temporary data in other menus
Title: 'Welcome back, %player_name%'
Body:
  status:
    type: 'message'
    text: '&7Last visit: %kamenu_meta_last_visit% | Status: %kamenu_meta_temp_status%'
```

### Show item count in the scoreboard

```yaml
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 Fruit: &f%kamenu_hasstockitem_神秘果%'
    - '&bTeleport Scroll: &f%kamenu_hasstockitem_传送卷轴%'
```

### Use item condition checks in menus

```yaml
# Check whether there are enough diamonds in the inventory
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, 10 diamonds are required!'

    use_fruit:
      text: '&bUse Mystic Fruit'
      actions:
        - condition: '%kamenu_hasstockitem_神秘果% >= 1'
          allow:
            - 'tell: &aMystic Fruit used!'
            - 'command: effect %player_name% regeneration 600 2'
            - 'data: take 神秘果 1'
          deny:
            - 'tell: &cYou do not have any Mystic Fruit!'
```

***

## Notes

1. **PAPI plugin dependency**：You need to install PlaceholderAPI to use these variables
2. **Data persistence**：
   * Use `set-data` and `set-gdata` data written by actions will be saved persistently
   * Use `set-meta` data written by actions is stored only in memory and is not persisted
3. **Key distinction**：Player data keys, global data keys, and metadata keys use different prefixes (`data_`、`gdata_` and `meta_`), and their storage locations and lifecycles are also different
4. **Type limitation**：All data is stored as strings, so type conversion is needed when using it
5. **Performance considerations**：Frequent reading of large amounts of data may affect performance; use reasonably
6. **Data existence check**：
   * PAPI variables: return a prompt or an empty string when data does not exist
   * Built-in variables: return `"null"`when data does not exist, making them convenient for condition checks
   * Metadata: return `"null"`when data does not exist, and it is automatically cleared when the player logs out or the plugin reloads
7. **Metadata lifecycle**：
   * Metadata is stored only in memory
   * Player metadata is automatically cleared when the player logs out
   * All metadata is cleared when the plugin reloads or the server shuts down
   * Suitable for scenarios that need to store temporary data for a short time
8. **Item variable features**：
   * `hasitem` variable supports multi-condition matching (material, lore, model)
   * `hasstockitem` variable uses storage items for exact matching
   * Returns when the item does not exist `0`
   * The item count is calculated in real time, including the total of all matching items
   * Supports use in condition checks and text display
9. **Parameter format**：
   * Item variables use square brackets `[]` to wrap parameters, but the brackets are optional
   * Semicolons are used between parameters `;` separate them
   * Lore matching supports fuzzy matching (case-insensitive)
   * The model format is `namespace:key`


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://katacr.gitbook.io/plugins/kamenu-en/placeholderapi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
