# Configuration
Painting-Paper uses `config.yml`. Painting-Velocity uses `plugins/painting/resourcepack.yml`. Both share the same shape with a few platform-specific keys called out below. Apply changes by running `/painting reload`.
---
## General Settings
| Field | Type | Default | Description |
|---|---|---|---|
| `enabled` | Boolean | `true` | Master switch. When `false`, Painting does nothing. |
| `mode` *(Paper only)* | String | `AUTO` | `AUTO`, `STANDALONE`, or `PROXIED`. `AUTO` flips to `PROXIED` after the first plugin-message receipt from Velocity. |
| `server_name` *(Paper only)* | String | `default` | Used to match the `servers:` regex when running standalone. |
| `append-hash-to-url` | Boolean | `false` | Append `?hash=<sha1>` to the pack URL. Useful for cache-busting CDN responses. |
| `prompt-timeout` | Integer | `15` *(Velocity)* / `15` *(Paper)* | Seconds to wait for the player to accept the prompt before kicking. Only applies to required packs. `0` disables the timeout. |
| `kickdelay` | Integer | `0` | Seconds to wait before kicking after `DECLINED` or `FAILED_DOWNLOAD`. `0` kicks immediately. |
| `failed-retries` | Integer | `2` | How many times to retry a `FAILED_DOWNLOAD` before kicking. Each retry re-issues the offer with `?_painting_retry=N` so a stale CDN edge doesn't kick a player while others on the same server are unaffected. `0` disables retry. |
| `hash-refresh-throttle` *(Velocity only)* | Integer | `60` | Seconds between hash freshness checks. Player joins and a periodic timer share the same throttled refresh. `0` disables auto-refresh. |
---
## Messages
| Field | Type | Description |
|---|---|---|
| `messages.prompt` | String | Prompt text shown above the resource pack offer. MiniMessage. |
| `messages.declined` | String | Kick message when a required pack is declined. MiniMessage. |
| `messages.failed` | String | Kick message when a required pack fails to download (after retries). MiniMessage. |
```yaml
messages:
prompt: "<green>Welcome! Please install the resourcepack."
declined: "<red>You need to accept the resourcepack in order to play."
failed: "<red>Failed to download the resourcepack. Please try reconnecting."
```
---
## Pack Definitions
Each pack name maps to a list of variants. The first variant whose `protocols` or `versions` matches the player is sent.
| Field | Type | Description |
|---|---|---|
| `resourcepacks.<name>[].url` | String | Public URL of the `.zip` resource pack. |
| `resourcepacks.<name>[].hash` | String | SHA-1 hash of the pack. Populated by `/painting generatehashes` or auto-refresh. |
| `resourcepacks.<name>[].protocols` | Integer List | Raw protocol numbers this variant matches. Optional. |
| `resourcepacks.<name>[].versions` | String List | Version expressions this variant matches. Optional if `protocols` is set. |
A variant must define at least one of `protocols` or `versions`, otherwise it is skipped.
```yaml
resourcepacks:
base:
- url: "https://cdn.example.com/packs/base-1.21.zip"
hash: ""
versions: ["1.21+"]
legacy:
- url: "https://cdn.example.com/packs/legacy-old.zip"
hash: ""
protocols: [763, 764]
- url: "https://cdn.example.com/packs/legacy-new.zip"
hash: ""
versions: [">=1.21,<26.1"]
```
### Version Expressions
| Form | Meaning |
|---|---|
| `1.21` | Exact match. |
| `1.21+` | Greater than or equal to 1.21. |
| `>=1.21.4` | Greater than or equal. |
| `>1.21.4` | Strictly greater than. |
| `<=1.21.7` | Less than or equal. |
| `<26.1` | Strictly less than. |
| `>=1.21.4,<26.1` | AND — comma chains conditions. |
| `["1.21+", "26.1+"]` | OR — list entries are evaluated as alternatives. |
The version table is loaded from the bundled `version_protocols.yml` and can be extended in config:
```yaml
version_protocols:
"26.1.3": 776
```
---
## Server Entries
Server entries match against the current server name (Paper: `server_name` config; Velocity: registered server name). Packs from every matching entry are sent in declaration order. `required: true` kicks players who decline or fail.
| Field | Type | Description |
|---|---|---|
| `servers.<name>.regex` | String | Regex matched against the server name. |
| `servers.<name>.required` | Boolean | When `true`, declining or failing kicks the player. |
| `servers.<name>.packs` | String List | Pack names to send, in order. Top of the list is the bottom layer; later entries override earlier ones. |
```yaml
servers:
global:
regex: ".*"
required: false
packs:
- base
survival:
regex: "^survival-\\d+
quot;
required: true
packs:
- base
- survival-overlay
```
Server entries that reference an unknown pack name log a warning at reload.
---
## Redis (CI/CD Push)
Painting can subscribe to a Redis Pub/Sub channel and react to JSON envelopes. Useful for re-deploying a pack from CI without restarting the server.
| Field | Type | Default | Description |
|---|---|---|---|
| `redis.enabled` | Boolean | `false` | Subscribe to the channel. |
| `redis.host` | String | `127.0.0.1` | Redis host. |
| `redis.port` | Integer | `6379` | Redis port. |
| `redis.password` | String | `""` | Optional AUTH password. |
| `redis.channel` | String | `painting:redis` | Pub/Sub channel name. |
In hybrid setups, Velocity owns Redis. Disable `redis.enabled` on Paper backends to avoid double handling.
### Envelope Format
| Action | Payload | Effect |
|---|---|---|
| `reload` | `{"action":"reload"}` | Reload pack and server registries from disk. |
| `update_pack` | `{"action":"update_pack","force_resend_online":true}` | Reload, then optionally resend to all online players. |
| `resend` | `{"action":"resend","force_resend_online":true}` | Resend pack offers without reloading config. |
---
## Example Configuration (Paper)
```yaml
enabled: true
mode: AUTO
append-hash-to-url: false
prompt-timeout: 15
kickdelay: 0
failed-retries: 2
server_name: "default"
redis:
enabled: false
host: "127.0.0.1"
port: 6379
password: ""
channel: "painting:redis"
messages:
prompt: "<green>Welcome! Please install the resourcepack."
declined: "<red>You need to accept the resourcepack in order to play."
failed: "<red>Failed to download the resourcepack. Please try reconnecting."
resourcepacks:
base:
- url: "https://cdn.example.com/base.zip"
hash: ""
versions: ["1.21+"]
servers:
global:
regex: ".*"
required: false
packs:
- base
```
---
## Example Configuration (Velocity)
```yaml
enabled: true
append-hash-to-url: false
prompt-timeout: 15
kickdelay: 0
failed-retries: 2
hash-refresh-throttle: 60
redis:
enabled: false
host: "127.0.0.1"
port: 6379
password: ""
channel: "painting:redis"
messages:
prompt: "<green>Welcome! Please install the resourcepack."
declined: "<red>You need to accept the resourcepack in order to play."
failed: "<red>Failed to download the resourcepack. Please try reconnecting."
resourcepacks:
base:
- url: "https://cdn.example.com/base.zip"
hash: ""
versions: ["1.21+"]
servers:
global:
regex: ".*"
required: false
packs:
- base
```
---
## Related Pages
- [[Painting/Server Owners/Overview]] — plugin features and modes
- [[Painting/Server Owners/Commands]] — command reference
- [[Painting/Developers/Overview]] — developer API documentation