> For the complete documentation index, see [llms.txt](https://edseries-plugins.gitbook.io/p/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://edseries-plugins.gitbook.io/p/pinnablockselector/getting-started/storage.md).

# Storage & MySQL

The plugin stores who unlocked the Block Selector (bought / given, and whether they had the rank permission at their last join), their name and their chosen blocks. Pick where in `config.yml`:

```yaml
storage:
  type: yaml          # yaml (default) or mysql
  mysql:
    host: 'localhost'
    port: 3306
    database: 'minecraft'
    username: 'root'
    password: ''
    table-prefix: 'pbs_'
    use-ssl: false
    properties: 'useUnicode=true&characterEncoding=utf8&serverTimezone=UTC'
```

| Type    | Where                                                            | Use it for                                                            |
| ------- | ---------------------------------------------------------------- | --------------------------------------------------------------------- |
| `yaml`  | `plugins/PinnaBlockSelector/data/players.yml`                    | one server (the default, nothing to set up)                           |
| `mysql` | the table `<table-prefix>players` in a MySQL or MariaDB database | several servers sharing the same data, or keeping it in your database |

Changing `storage.type` needs a **restart** (`/blockselector reload` keeps the storage the server started with and warns in the console). Copy the data over first with [migrate](#moving-data).

Every change is saved a moment after it is made, off the main thread, and on shutdown. The data is small (only players who have the Block Selector are stored), so the plugin keeps it all in memory; the mine refill always uses that copy.

## Setting up MySQL

1. Create a database (or use an existing one) and a user that may create tables in it.
2. Fill in `storage.mysql` and set `type: mysql`.
3. Restart. The table is created on start; the console shows `... players stored (mysql).`

No extra jar is needed: Paper and Spigot ship the MySQL driver (the MariaDB driver is used when that is the one present). `properties` are added to the JDBC URL; `use-ssl: true` turns on an encrypted connection.

If MySQL can't be reached at startup (wrong host or password, database down), the console shows a clear error with the host, port and database, and the plugin uses the local `data/players.yml` until the next restart, so the server still runs. Fix `storage.mysql`, restart, and if players changed something meanwhile, copy it over with `/blockselector migrate yaml mysql`. A connection that drops while the server runs is reopened by itself; a save that fails is tried again 30 seconds later.

## Several servers

With `mysql`, servers that use the same database and `table-prefix` share every unlock and choice:

* a player's data is read from the database when they join (before their mine is built), so a choice applied on another server is used;
* admin commands on an offline player (`give`, `take`, `info`, `set`, `clear`) read their data from the database first, so a store purchase on one server never overwrites a choice made on another;
* a season reset (`/pinna restoreall`) reads every player from the database first.

Don't let the same player be online on two servers that share the database at the same time (normal with a proxy, where a player is on one server at a time). Use a different `table-prefix` for servers that should keep separate data in the same database.

## Moving data

```
/blockselector migrate <from> <to>
```

`from` / `to` are `yaml` or `mysql`, e.g. `/blockselector migrate yaml mysql` before switching a server to MySQL. It runs in the background (console or `pinnablockselector.admin`): changes not written yet are saved first, then every record is copied and the number is reported. Players already in the target are overwritten; copying to `yaml` replaces `data/players.yml` with the copied records. The connection settings of the current `config.yml` are used, so you can copy to MySQL before switching `storage.type`. When the target is the storage in use, the server reads its data again from it.

Switching a server to MySQL:

1. Fill in `storage.mysql` (keep `type: yaml`), `/blockselector reload`.
2. `/blockselector migrate yaml mysql`.
3. Set `type: mysql` and restart.

## The table

`<table-prefix>players` (InnoDB, utf8mb4), one row per player:

| Column        |                                                                                               |
| ------------- | --------------------------------------------------------------------------------------------- |
| `uuid`        | the player's UUID (key)                                                                       |
| `name`        | their last known name                                                                         |
| `owned`       | 1 = bought or given                                                                           |
| `rank_unlock` | 1 = had `unlock-permission` at their last join                                                |
| `blocks`      | the chosen block keys in order, comma separated (`STONE,OAK_PLANKS`); empty = the tier blocks |
| `updated_at`  | when the row was last written (milliseconds since 1970)                                       |
