# Developer Overview
Painting-API is a platform-neutral interface for reading the active pack registry, reacting to player pack status, and triggering resends. The same API works against the Paper and Velocity implementations — only the Bukkit / Velocity event-bus glue differs.
---
## Maven / Gradle
The Painting-API artifact is hosted on JitPack. Add it as a `compileOnly` / `provided` dependency so Painting is not shaded into your plugin.
**Repository:**
*Gradle (Kotlin DSL):*
```kotlin
repositories {
maven("https://jitpack.io")
}
```
*Maven:*
```xml
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
```
**Dependency:**
*Gradle (Kotlin DSL):*
```kotlin
compileOnly("com.github.Lodestones:Painting-API:1.0.0")
```
*Maven:*
```xml
<dependency>
<groupId>com.github.Lodestones</groupId>
<artifactId>Painting-API</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
```
Add `Painting` as a dependency in your `paper-plugin.yml` (Paper) or to your Velocity plugin metadata.
```yaml
dependencies:
server:
Painting:
required: true
load: BEFORE
```
---
## Accessing the API
The API is accessed through the static `PaintingAPI` class. The instance is registered by the platform plugin during enable.
```java
import gg.lode.paintingapi.PaintingAPI;
import gg.lode.paintingapi.IPaintingAPI;
if (!PaintingAPI.isAvailable()) return;
IPaintingAPI api = PaintingAPI.get();
```
Calling `PaintingAPI.get()` before the plugin has initialized throws `IllegalStateException`. Use `PaintingAPI.isAvailable()` to gate the call when load order is not guaranteed.
---
## Common Operations
### List all configured packs
```java
for (PackDefinition def : PaintingAPI.get().getPackDefinitions()) {
plugin.getLogger().info("Pack " + def.name() + " has " + def.variants().size() + " variants.");
}
```
### Look up a pack by name
```java
PackDefinition base = PaintingAPI.get().getPackDefinition("base");
if (base == null) return;
PackVariant variant = base.pickFor(player.getProtocolVersion().getProtocol());
```
### Check if a server requires a pack
```java
boolean required = PaintingAPI.get().isRequiredForServer("survival-1");
```
### Force a resend
```java
// Resend to a single player (Paper or Velocity).
PaintingAPI.get().resendPacksToPlayer(player.getUniqueId());
// Resend to everyone online.
PaintingAPI.get().resendPacksToOnlinePlayers();
```
### Reload the registry
```java
PaintingAPI.get().reload();
```
---
## Events
Painting fires three event types through each platform's native event bus. All three implement the platform-neutral interfaces in `gg.lode.paintingapi.api.event` so consumers can write platform-agnostic listener interfaces if desired.
### PackStatusEvent
Fired whenever the player's resource pack state changes (`ACCEPTED`, `DECLINED`, `DOWNLOADED`, `LOADED`, `FAILED`, `DISCARDED`, `INVALID_URL`).
*Paper:*
```java
@EventHandler
public void onPackStatus(PaperPackStatusEvent event) {
if (event.getStatus() == PackStatus.LOADED) {
// Pack applied successfully
}
}
```
*Velocity:*
```java
@Subscribe
public void onPackStatus(VelocityPackStatusEvent event) {
if (event.getStatus() == PackStatus.FAILED && event.isRequiredForServer()) {
// Failed and going to be kicked unless retry succeeds
}
}
```
### PackPreSendEvent (Paper only — cancellable)
Fired before each pack offer is sent to a player. Cancelling skips that specific pack.
```java
@EventHandler
public void onPreSend(PaperPackPreSendEvent event) {
if (event.getPackName().equals("staff-overlay") && !isStaff(event.getPlayerId())) {
event.setCancelled(true);
}
}
```
### PackRegistryReloadEvent (Paper only)
Fired after `/painting reload` once the pack and server registries have been re-read.
```java
@EventHandler
public void onReload(PaperPackRegistryReloadEvent event) {
plugin.getLogger().info("Painting reloaded: " + event.getDefinitionCount() + " packs, "
+ event.getServerEntryCount() + " server entries.");
}
```
---
## Pack Status Values
| Status | Meaning |
|---|---|
| `ACCEPTED` | Player clicked Yes on the prompt. Download starts. |
| `DOWNLOADED` | Pack download finished. |
| `LOADED` | Pack applied to the client. |
| `DECLINED` | Player clicked No. |
| `FAILED` | Download failed. |
| `DISCARDED` | Pack was unloaded (replaced or removed). |
| `INVALID_URL` | Client rejected the URL as malformed. |
| `UNKNOWN` | Future status not mapped by this version. |
---
## Related Pages
- [[Painting/Developers/API Reference]] — full interface documentation
- [[Painting/Server Owners/Configuration]] — config values the API exposes
- [[Painting/API/PaintingAPI]] — static accessor source