> ## Documentation Index
> Fetch the complete documentation index at: https://docs.seraph.si/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference

> Every global object a Seraph plugin can reach.

These globals are in scope in every plugin. The authoritative version of this, with full types and
inline documentation, is written to `plugins/seraph.d.ts` every time plugins load, so your editor
will always describe the build you are actually running.

| Global      | Permission  | What it is                                   |
| ----------- | ----------- | -------------------------------------------- |
| `config`    | —           | This plugin's live settings                  |
| `console`   | —           | Logging to Seraph's log file                 |
| `events`    | —           | Event listeners and command registration     |
| `scheduler` | —           | Timeouts, intervals and cron                 |
| `input`     | —           | Keyboard state                               |
| `text`      | —           | Colour codes and number formatting           |
| `party`     | —           | The party you are in                         |
| `platform`  | —           | Which client Seraph is running inside        |
| `chat`      | `chat`      | Reading and writing chat                     |
| `player`    | `player`    | The local player and their inventory         |
| `movement`  | `player`    | Motion, rotation and movement state          |
| `world`     | `world`     | The world, entities and the scoreboard       |
| `http`      | `network`   | HTTP requests                                |
| `stats`     | `network`   | Hypixel lookups through Seraph's API layer   |
| `storage`   | `storage`   | Persistent key/value storage for this plugin |
| `render`    | `render`    | Drawing on screen                            |
| `nametags`  | `render`    | Decorating player nametags                   |
| `overlay`   | `render`    | Columns of your own on the stats overlay     |
| `waypoints` | `render`    | Waypoints Seraph draws on the HUD            |
| `hud`       | `notify`    | Titles, action bar and sounds                |
| `anticheat` | `anticheat` | Custom anti-cheat checks                     |
| `tray`      | `tray`      | System tray icon and OS notifications        |

## events

`events.on(name, callback)` returns an id, and `events.off(id)` removes it. A script's listeners
are cleared for it on reload; a module's are not.

| Event                 | Payload                                            |
| --------------------- | -------------------------------------------------- |
| `chat`                | `{ message, formatted, isSystem }`                 |
| `packet`              | The packet itself, narrowed with `events.isPacket` |
| `tick`                | —                                                  |
| `renderOverlay`       | —                                                  |
| `worldUnload`         | —                                                  |
| `playerMove`          | `{ x, y, z, yaw, pitch }`                          |
| `blockUpdate`         | `{ x, y, z, blockRegistryName }`                   |
| `playerJoin`          | `{ uuid, name }`                                   |
| `playerLeave`         | `{ uuid, name }`                                   |
| `playerDeath`         | The player's UUID                                  |
| `playerRespawn`       | The player's UUID                                  |
| `playerInteract`      | `{ entityId, action }`                             |
| `entityVelocity`      | `{ entityId, motionX, motionY, motionZ }`          |
| `soundPlay`           | `{ name, x, y, z, volume, pitch }`                 |
| `particleSpawn`       | `{ name, x, y, z, count }`                         |
| `windowOpen`          | `{ windowId, title, slots }`                       |
| `windowClose`         | —                                                  |
| `scoreboardObjective` | `{ name, value, type, mode }`                      |
| `title`               | `(type, message)`, as two arguments                |

An unrecognised event name is accepted but warned about in the log, since nothing would ever fire
it. [Events](/docs/features/plugin-api/events) describes every payload, when each one runs and what
can be cancelled.

### Cancelling

Returning `false` from a `chat` or `packet` listener stops that message or packet reaching the rest
of the client. Every other event ignores what a listener returns.

### Packets

`packet` fires for every packet the server sends, on the network thread, and hands you the object
Minecraft built rather than a copy of it, so read it through its Java accessors: `getX()`, not
`.x`. `events.isPacket(packet, name)` narrows one by its simple class name, which is also what
tells your editor the real signatures:

```js theme={null}
events.on("packet", (packet) => {
    if (events.isPacket(packet, "S02PacketChat")) {
        console.info(packet.getChatComponent().getUnformattedText());
    }
});
```

Every packet Seraph types is listed under `ServerPacketMap` in `seraph.d.ts`, from
`S00PacketKeepAlive` through to `S49PacketUpdateEntityNBT`. This is the busiest event there is, so
keep the body short and leave anything heavy to `tick`.

Also on `events`: `registerCommand(name, callback, tabComplete?)`, `registerCommand(name, submenus,
tabComplete?)` and `completePlayers(args)`. See
[Scripts and modules](/docs/features/plugin-api/modules).

## chat

`addChatMessage(msg)` prints locally, `sendChatMessage(msg)` sends to the server, and
`createBuilder()` returns a builder for anything richer:

```js theme={null}
const line = chat.createBuilder()
    .text("click me")
    .color("a")
    .bold()
    .hoverText("§7opens the docs")
    .clickUrl("https://docs.seraph.si");

chat.addChatMessage(line);
```

The builder also has `italic()`, `underline()`, `strikethrough()`, `clickCommand(command)` and
`clickSuggest(text)`.

## player and movement

`player` covers identity (`getName`, `getDisplayName`, `getUUID`), vitals (`getHealth`,
`getMaxHealth`, `getFoodLevel`, `getAir`, `getExperienceProgress`, `getExperienceLevel`), position
(`getPosX`, `getPosY`, `getPosZ`), state (`isSprinting`, `isSneaking`, `isOnGround` and
`isBlocking`, which is true while a sword is raised), actions (`swingItem`, `respawn`, `lookAt`,
`dropHeldItem`, `closeContainer`, `clickWindow`) and the inventory (`getInventoryItems`,
`getArmorItems`, `getItemInSlot`, `isSlotEmpty`, `getHeldItemSlot`, `setHeldItemSlot`,
`getCurrentItemName`).

`movement` reads `getYaw`, `getPitch`, `getMotionX/Y/Z`, `getSpeed` (blocks per tick), `isMoving`,
`isInWater` and the same sprint, sneak and ground flags, and writes `setRotation`, `setMotion`,
`setSprinting` and `setSneaking`.

## world

`getName`, `getTime`, `isRaining`, `isThundering`, `getDifficulty`, `getBlockAt(x, y, z)`,
`getPlayersInWorld()`, `getPlayerNames()`, `getEntities()`, `getClosestEntity(range)`,
`getEntityById(id)`, `attackEntity(id)`, `interactEntity(id)` and `getScoreboard()`, which returns
`{ getTitle(), getLines() }`.

`getPlayerNames()` is the tab list with NPCs and yourself removed, the same set Seraph's own
commands complete against.

## http and stats

`http.fetch` returns a promise, or takes a callback if you would rather not use one:

```js theme={null}
http.fetch("https://api.example.com/thing")
    .then((response) => console.info(response.responseCode + " " + JSON.stringify(response.body)))
    .catch((reason) => console.error(reason));
```

The full signature is `fetch(url, method?, body?, properties?, callback?)`, where `method` is
`GET`, `POST`, `PUT` or `DELETE` and `properties` is a map of request headers. A response is
`{ responseCode, responseMessage, body }`.

`stats.getUuid(nameOrId)` resolves a name or id to `{ name, uuid }`, or `null` if there is no such
account. `stats.getPlayer(nameOrId)` fetches a Hypixel profile through Seraph's own API layer, so
the lookup shares the mod's caching and proxy handling. Both take a callback instead of returning a
promise if you prefer, and both count against the same rate limit as `http.fetch`.

## storage

Key/value storage scoped to your plugin: `get(key)`, `set(key, value)`, `has(key)`, `remove(key)`,
`keys()`, `clear()` and `save()`.

Use `storage` for data your plugin manages itself and `config` for settings the user is meant to
change.

## render and nametags

`render` gives you `getScreenWidth`, `getScreenHeight`, `getTextWidth(text)`,
`drawText(text, x, y, color, shadow?)` and `drawRect(x, y, width, height, color)`. Call them from a
`renderOverlay` listener.

`nametags` decorates players by name or UUID: `set(nameOrId, prefix?, suffix?)`,
`setPrefix`, `setSuffix`, `clear(nameOrId)` and `clearAll()`. Only your own plugin's decorations are
cleared.

## overlay

Columns of your own, alongside the ones the overlay draws itself:

```js theme={null}
declareModule({ name: "party-marker", permissions: ["render"] });

overlay.addColumn("Party");

events.on("tick", () => {
    for (const member of party.getMembers()) {
        overlay.setColumn("Party", member.uuid, "§b*");
    }
});
```

`addColumn(label)` adds one and is `false` if this plugin already added it. `setColumn(label,
nameOrId, text?)` fills one player's cell, taking a name or a UUID, and is `false` when that player
is not in the tab list or the column was never added; `null` or an empty string blanks the cell.
`getColumn(label, nameOrId)` reads back what **this** plugin last set there.

`clearColumn(label)` blanks every cell but keeps the column, `removeColumn(label)` takes the column
away with everything in it, `clearColumns()` removes every column this plugin added, and
`columns()` lists this plugin's headings alphabetically.

## waypoints

Waypoints Seraph draws itself, listed nearest first with the distance and compass direction to
each. Unlike Lunar's and Badlion's own waypoints these render the same on every client, so a plugin
does not have to care which one it is running under:

```js theme={null}
declareModule({ name: "diamonds", permissions: ["render"] });

waypoints.set("Diamonds", 214, 12, -388, 0xFF55FFFF);

events.on("tick", () => {
    if (waypoints.distanceTo("Diamonds") < 8) waypoints.remove("Diamonds");
});
```

`set(name, x, y, z, colour?)` adds or moves one, taking an ARGB colour that defaults to white.
`remove(name)`, `clear()` and `list()` cover the rest, `distanceTo(name)` is in blocks and `-1` for
a waypoint that is not set, and `directionTo(name)` is `"N"`, `"NE"`, `"E"` and so on, or `null`.

`setPosition(x, y)` moves the on-screen list, which is shared by every plugin, so the last call
wins. A plugin's waypoints go when it unloads.

## platform

Seraph injects into Lunar, Badlion and Forge alike, so anything client specific should ask here
rather than assume:

```js theme={null}
if (platform.isBadlion()) chat.addChatMessage("§7badlion detected");
```

`getClient()` returns `"Lunar"`, `"Badlion"`, `"Forge"`, or `"Unknown"` before Seraph has finished
starting. `isLunar()`, `isBadlion()`, `isForge()` and `isClient(name)` are the shorthands, and
`isClient` compares without regard to case.

## hud

`title(title, subtitle?, stay?, fadeIn?, fadeOut?)`, `actionBar(text)` and
`sound(name, volume?, pitch?)`. Times are in ticks; twenty ticks is a second.

## party

`isInParty()`, `getLeader()`, `getMembers()`, `getSize()`, `getRole(nameOrId)` and
`isLeader(nameOrId)`. `refresh()` asks Hypixel for fresh party information, which arrives
asynchronously, so the getters reflect it a moment later.

## anticheat

```js theme={null}
anticheat.registerCheck("fast-turn", (data) => {
    return Math.abs(data.rotationYaw) > 180;
}, "Fast Turn");

anticheat.onFlag((uuid, checkId, name) => {
    console.info(uuid + " flagged " + name);
});
```

`registerCheck(name, tickFn, userFriendlyName?, blacklistCode?)` runs `tickFn` once per tick for
every observed player; return `true` to flag them and the built-in flag message and report pipeline
takes over. `unregisterCheck(name)` removes it, and `onFlag` fires for every check, built-in or
plugin-registered.

## tray

`isSupported` says whether the platform has a system tray. `show(tooltip?)`, `hide()`,
`setTooltip(tooltip)` and `notify(title, message, type?)`, where `type` is `info`, `warning`,
`error` or `none`.

## text and input

`text.colour(text)` (and `text.color`) turns `&` codes into the section signs Minecraft renders,
`text.strip(text)` removes them, and `text.formatNumber(value)` groups a number the way the overlay
does.

`input.isKeyDown(keyName)` reports whether a key is held, for example `"F"`, `"LSHIFT"` or
`"SPACE"`.

## console

`log`, `info`, `warn` and `error`, all written to Seraph's log file. Use these rather than chat for
anything diagnostic, they need no permission and do not spam the player.
