# threading and safety

PracticeBot sits on top of Bukkit, Paper, and Citizens runtime state. Treat API methods as main-thread only unless explicitly documented otherwise.

## Main-thread only operations

Call these on the server main thread:

* resolving active bots
* listing active bots
* reading live state snapshots
* spawning bots
* despawning bots
* applying templates
* setting targets
* clearing targets
* mutating metadata
* updating CPvP runtime settings

## Metadata read exception

These metadata read methods are detached from Bukkit/Citizens state and may be read off-thread:

* `getMetadata(key)`
* `getMetadataSnapshot()`
* `hasMetadata(key)`

Metadata writes are still main-thread only.

## Safe async pattern

```java
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
    // Do external work here: database, HTTP, analytics, file IO.
    String result = loadSomethingFromDatabase();

    Bukkit.getScheduler().runTask(this, () -> {
        // Back on the main thread before using PracticeBot API.
        PracticeBotApi api = PracticeBotApiProvider.get();
        for (PracticeBotHandle bot : api.getActiveBots()) {
            bot.setMetadata(new NamespacedKey(this, "result"),
                    PracticeBotMetadataType.STRING,
                    result);
        }
    });
});
```

## Unsupported patterns

Do not:

* call spawn/despawn/template methods asynchronously
* store mutable Bukkit `Location` or `Entity` references from snapshots
* import internal classes outside `com.sheldera.practicebot.api.*`
* modify Citizens NPCs directly when they are PracticeBot runtime bots
* use reflection to access internals
* depend on obfuscated or private classes

## Failure behavior

Async misuse may throw `IllegalStateException` or cause unstable runtime behavior. Keep API usage on the main thread unless a method is explicitly documented as safe for off-thread use.


---

# 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://edelweiss-network.gitbook.io/practicebot/threading-and-safety.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.
