> 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/pinnaprison/developers/edlib-api.md).

# EdLib API

PinnaPrison is built on **EdLib** — a version-neutral NMS layer that handles the hard, packet-level work: fake (client-only) entities, custom 3D models, fake block changes, boss bars, action bars and an async task executor. Every animated pickaxe enchant in PinnaPrison (Meteor Shower, Zombie Horde, Dragon Breath…) is just EdLib entities driven by [goals](/p/pinnaprison/developers/edlib-api/goals.md) over a packet-based mine.

Because EdLib is **packet-based**, everything it spawns is *client-only*: entities, blocks and displays are sent to the players you choose and never touch the server world. That is exactly what makes them safe to use inside private mines (which live in a shared void world) and cheap enough to spawn dozens at a time.

{% hint style="info" %}
EdLib is a **separate plugin** that PinnaPrison depends on — it is already on the server. To call it from your own plugin, `depend: [EdLib]` (or `[PinnaPrison, EdLib]`) in your `plugin.yml` and compile against the EdLib `api` artifact.
{% endhint %}

## Getting the API

EdLib uses a singleton, available as soon as EdLib has enabled:

```java
import es.edwardbelt.edlib.iapi.EdLibAPI;

EdLibAPI edlib = EdLibAPI.getInstance();

EdEntity zombie = edlib.createEntity(EntityType.ZOMBIE, location);
zombie.addWatcher(player);
zombie.spawn();
```

## What the API gives you

| Method                                                                                               | What it does                                                                                                                                  |
| ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `EdModel getModel(String id)`                                                                        | Looks up a registered custom [model](/p/pinnaprison/developers/edlib-api/models.md) by id (`null` if missing).                                |
| `EdEntity createEntity(EntityType type, Location loc)`                                               | Creates a client-only entity of any type. Returns the matching subtype — `EdFallingBlock`, `EdPrimedTNT`, `EdNPC`, etc. — which you can cast. |
| `EdNPC createNPC(Location loc, String name, String texture, String signature)`                       | Creates a packet player [NPC](/p/pinnaprison/developers/edlib-api/entities.md#ednpc) with a skin.                                             |
| `EdEntity createInteractionEntity(Location loc, float height, float width)`                          | An invisible interaction hitbox for click detection.                                                                                          |
| `EdEntity createBlockDisplay(Location loc, Matrix4f matrix, Material material)`                      | A block display with a transform matrix (scale/rotate/offset).                                                                                |
| `EdEntity createItemDisplay(Location loc, Matrix4f matrix, String texture, int[] uuid, String name)` | An item display with a custom texture.                                                                                                        |
| `void sendActionbar(Player p, String message)`                                                       | Sends an action-bar message (color codes supported).                                                                                          |
| `void sendXPBar(Player p, float progress, int level)`                                                | Overrides the player's XP bar display (`progress` 0–1).                                                                                       |
| `void hidePlayer(Player viewer, Player target)` / `showPlayer(...)`                                  | Per-viewer player visibility.                                                                                                                 |
| `void sendBlocks(Player p, Map<Vector, Material> blocks)`                                            | Sends fake block changes to one player.                                                                                                       |
| `void sendBossBar(Player p, UUID id, String title, float progress, String color)`                    | Creates a boss bar. Update with `updateBossBarTitle` / `updateBossBarProgress`, remove with `removeBossBar`.                                  |

Color names for boss bars: `blue`, `red`, `green`, `yellow`, `purple`, `white`, `pink`.

### Creating entities

`createEntity` returns the right interface for the `EntityType`, so you can cast to the [specialised type](/p/pinnaprison/developers/edlib-api/entities.md):

```java
EdFallingBlock rock = (EdFallingBlock) edlib.createEntity(EntityType.FALLING_BLOCK, loc);
rock.setFallingBlock(Material.MAGMA_BLOCK);
rock.setGravity(false);

EdPrimedTNT tnt = (EdPrimedTNT) edlib.createEntity(EntityType.TNT, loc);
tnt.setFuseTicks(40);

EdNPC miner = edlib.createNPC(loc, "§bMiner", texture, signature);
```

Nothing is visible until you add **watchers** and call `spawn()`. See [Entities](/p/pinnaprison/developers/edlib-api/entities.md).

## The task executor

Goals and animations need a scheduler that is safe to call from EdLib's async pipelines. EdLib exposes one through `EdLibAPI.getExecutor()` (a `TaskExecutor`); every method returns an `EdTask` you can `cancel()`:

```java
TaskExecutor exec = EdLibAPI.getExecutor();

exec.async(() -> { ... }, "my-task");                 // run now, off-thread
exec.asyncLater(() -> entity.remove(), 100, "cleanup"); // 100 ticks later
EdTask loop = exec.repeatedAsync(() -> tick(), 0, 1, "anim"); // every tick
exec.sync(() -> spawnBossMob(), "main-thread");        // hop to the main thread
loop.cancel();
```

| `TaskExecutor` method                      |                                                    |
| ------------------------------------------ | -------------------------------------------------- |
| `async(task, type)`                        | Run off the main thread immediately.               |
| `asyncLater(task, delayTicks, type)`       | Run off-thread after a delay.                      |
| `repeatedAsync(task, delay, period, type)` | Repeating off-thread task (delay/period in ticks). |
| `sync(task, type)`                         | Run on the **main server thread**.                 |
| `syncLater(task, delayTicks, type)`        | Run on the main thread after a delay.              |

`EdTask` exposes `cancel()`, `isCancelled()` and `getTaskId()`.

## Threading model

This is the single most important thing to get right.

* **Packet work is thread-safe.** Spawning EdLib entities, moving them, running goals, `sendBlocks`, boss bars and action bars are all packet sends — fine from any thread. This is why PinnaPrison's enchants run entirely on the async break pipeline.
* **Bukkit world / entity / inventory access is not.** If you need to read the real world, fire Bukkit events, or open inventories, hop to the main thread with `getExecutor().sync(...)`.
* **A few entity constructors must be built on the main thread** (e.g. the Ender Dragon fires a Bukkit phase event). Create those with `getExecutor().sync(...)`, then animate them off-thread.

{% hint style="warning" %}
Always `remove()` your entities when done (or schedule an `asyncLater` cleanup). Client-only entities are not garbage-collected by the server — if you never remove them, they linger on the client until relog.
{% endhint %}

## Pages

* [Entities](/p/pinnaprison/developers/edlib-api/entities.md) — `EdEntity` and its subtypes (NPC, falling block, TNT…), equipment, animations, transforms.
* [Goals](/p/pinnaprison/developers/edlib-api/goals.md) — the movement/behaviour system that drives animations.
* [Models](/p/pinnaprison/developers/edlib-api/models.md) — custom multi-part 3D models with animations.
* [Spawning entities into mines](/p/pinnaprison/developers/edlib-api/mine-entities.md) — **the practical guide**: do what the built-in enchants do — spawn packet entities into a player's mine, drive them with goals, and break + reward blocks on impact.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://edseries-plugins.gitbook.io/p/pinnaprison/developers/edlib-api.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.
