# Player Data and Global Data

KaMenu has a built-in key-value storage system, allowing persistent read/write data in menus without any extra plugins.

***

## Data Types

### Player Data (Player Data)

Key-value pairs scoped to each player's UUID; each player's data is independent.

**Write (in actions):**

```yaml
actions:
  - 'set-data: <key> <value>'
```

**Read (in any text position):**

| Method            | Format              | Description                                         |
| ----------------- | ------------------- | --------------------------------------------------- |
| Built-in Variable | `{data:key}`        | Use directly in menu text                           |
| PAPI Variable     | `%kamenu_data_key%` | Use via PlaceholderAPI (can be used across plugins) |

**Example:**

```yaml
# Write
actions:
  - 'set-data: vip_level 3'
  - 'set-data: nickname $(input_nickname)'

# Read - in menu text
text: '&7Your VIP level: &6{data:vip_level}'
text: '&7Your nickname: &f{data:nickname}'

# Read - in conditions
condition: '{data:vip_level} >= 2'
```

***

### Global Data (Global Data)

Key-value pairs shared by all players, commonly used to store server-level state information.

**Write (in actions):**

```yaml
actions:
  - 'set-gdata: <key> <value>'
```

**Read (in any text position):**

| Method            | Format               | Description                                         |
| ----------------- | -------------------- | --------------------------------------------------- |
| Built-in Variable | `{gdata:key}`        | Use directly in menu text                           |
| PAPI Variable     | `%kamenu_gdata_key%` | Use via PlaceholderAPI (can be used across plugins) |

**Example:**

```yaml
# Write
actions:
  - 'set-gdata: server_event active'
  - 'set-gdata: event_winner %player_name%'

# Read - in menu text
text: '&7Server event status: &a{gdata:server_event}'
text: '&7Event winner: &e{gdata:event_winner}'

# Read - in conditions
condition: '{gdata:server_event} == active'
```

***

## Complete Usage Example

### Below is an example of using the data storage system to make a "daily check-in" menu:

Principle: Use`last_sign`The data stores the date when the player clicked check-in, and this value is compared with the current date. If they are the same, it means the player has already checked in today; if different, it means they have not checked in today.

```yaml
Title: '&6Daily Check-in'

Settings:
  need_placeholder:
    - 'server'

Body:
  reward_item:
    type: 'item'
    material: 'CHEST'
    name: '&6Today's Check-in Reward'
  reward_text:
    type: 'message'
    text: |
      &6Daily check-in rewards:
      &e100 coins
      &e1 diamond
  info:
    type: 'message'
    text:
      - condition: "{data:last_sign} == %server_time_YYYYMMdd%"
        allow: '&cYou have already checked in today. Come back tomorrow!'
        deny: '&aYou haven't checked in today yet. Click the button below to claim your reward.'

Bottom:
  type: 'notice'
  confirm:
    text:
      - condition: "{data:last_sign} == %server_time_YYYYMMdd%"
        allow: '&8[ Checked In ]'
        deny: '&a[ Check In Now ]'
    actions:
      - condition: "{data:last_sign} == %server_time_YYYYMMdd%"
        allow:
          - 'actionbar: &cYou have already checked in today! Please come back tomorrow.'
          - 'sound: block.note_block.bass'
        deny:
          - 'set-data: last_sign %server_time_YYYYMMdd%'
          - 'console: eco give %player_name% 100'
          - 'console: give %player_name% diamond 1'
          - 'tell: &aCheck-in successful! You received 100 coins and 1 diamond.'
          - 'title: title=&6Check-in Successful;subtitle=&fReward has been sent'
          - 'sound: entity.player.levelup'
```

### Below is an example of using the data storage system to make a "daily limit purchase of 100 diamonds" menu:

Principle:

* Use`last_day`The data stores the date when the player last entered the menu, and this value is compared with the current date. If different, it means the date has changed and the purchase count needs to be reset.
* Use`diamond_amount`The data stores the number of diamonds the player can still purchase.

```yaml
Title: '&6Diamond Shop'

Settings:
  need_placeholder:
    - 'server'
    - 'math'

Events:
  Open:
    - condition: '{data:last_day} != %server_time_YYYYMMdd%'
      allow:
        - 'set-data: last_day %server_time_YYYYMMdd%'
        - 'set-data: diamond_amount 100'
        - 'tell: &aWelcome to the Diamond Shop, today's diamond stock has been replenished.'
        - 'wait: 1'

Body:
  item:
    type: 'item'
    material: 'DIAMOND'
    name: '&6Diamond'
  text-info:
    type: 'message'
    text: |
      &6Please choose how many diamonds to buy:
      &e50 coins each
      &eYou can buy at most 100 per day
  remaining_amount:
    type: 'message'
    text: '&9Remaining purchase amount: {data:diamond_amount}'

Inputs:
  amount:
    type:
      - condition: '{data:diamond_amount} > 0'
        allow: 'slider'
        deny: 'none'
    text: '&bPurchase amount:'
    min: 0
    max: '{data:diamond_amount}'
    default: 1
    format: '%s %s '

Bottom:
  type: 'confirmation'
  confirm:
    text: '&a[ Buy Now ]'
    actions:
      - condition: '{data:diamond_amount} > 0'
        allow:
          - condition: '!isPosInt.$(amount)'
            allow:
              - 'tell: &cPlease enter a valid number.'
              - 'return'
          - condition: 'hasMoney.%math_2_50*$(amount)%'
            allow:
              - 'money: type=take;num=%math_2_50*$(amount)%' # Deduct coins
              - 'item: type=give;mats=DIAMOND;amount=$(amount)' # Give diamonds
              - 'data: type=take;key=diamond_amount;var=$(amount)' # Deduct the remaining amount in the database
              - 'tell: &aPurchase successful, spent %math_2_50*$(amount)% coins to buy diamond x$(amount)'
            deny:
              - 'tell: &cNot enough coins! Need coins x%math_2_50*$(amount)%'
        deny:
          - 'actionbar: &cToday's diamonds are sold out! Please come back tomorrow.'
  deny:
    text: '&c[ Cancel ]'
    actions:
      - 'tell: &7Purchase canceled.'
      - 'sound: block.note_block.bass'
```

***

## Database Configuration

The backend database for data storage can be configured in `config.yml` and supports both SQLite and MySQL.

For detailed configuration, please refer to [⛳ Configuration file: config.yml](/plugins/kamenu-en/config/config.md).

***

## Table Structure (Reference)

KaMenu creates the following two tables in the database:

**player\_data table (player data):**

| Field         | Type        | Description                |
| ------------- | ----------- | -------------------------- |
| `id`          | INTEGER     | Auto-increment primary key |
| `player_uuid` | VARCHAR(36) | Player UUID                |
| `data_key`    | VARCHAR(64) | Data key name              |
| `data_value`  | TEXT        | Data value                 |
| `update_time` | BIGINT      | Last update timestamp      |

**global\_data table (global data):**

| Field         | Type        | Description                |
| ------------- | ----------- | -------------------------- |
| `id`          | INTEGER     | Auto-increment primary key |
| `data_key`    | VARCHAR(64) | Data key name (unique)     |
| `data_value`  | TEXT        | Data value                 |
| `update_time` | BIGINT      | Last update timestamp      |


---

# 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/data/storage.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.
