# API Reference
The Observer API allows third-party plugins to hook into Observer's event management systems. The API module provides interfaces, data classes, events, and exceptions for interacting with all major Observer subsystems.
---
## Maven Dependency
Observer-API is hosted on JitPack. Add the following to your `pom.xml`:
```xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.Lodestones</groupId>
<artifactId>Observer-API</artifactId>
<version>1.0.64</version>
<scope>provided</scope>
</dependency>
</dependencies>
```
### Gradle (Groovy)
```groovy
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
compileOnly 'com.github.Lodestones:Observer-API:1.0.64'
}
```
### Gradle (Kotlin DSL)
```kotlin
repositories {
maven("https://jitpack.io")
}
dependencies {
compileOnly("com.github.Lodestones:Observer-API:1.0.64")
}
```
---
## Accessing the API
The static entry point for the Observer API is `ObserverAPI.getApi()`. This returns an `IObserverAPI` instance once Observer has been loaded on the server.
```java
import gg.lode.observerapi.ObserverAPI;
import gg.lode.observerapi.IObserverAPI;
IObserverAPI api = ObserverAPI.getApi();
```
Ensure your plugin declares Observer as a dependency (or soft dependency) in `plugin.yml` so Observer loads first:
```yaml
depend:
- Observer
```
---
## IObserverAPI Interface
The core API interface provides access to all manager instances and game state control.
```java
public interface IObserverAPI {
ICapsuleManager getCapsuleManager();
ICustomRecipesManager getCustomRecipesManager();
IDecayManager getDecayManager();
IEliminationManager getEliminationManager();
ILateScatterManager getLateScatterManager();
ILifestealManager getLifestealManager();
IMechanicsManager getMechanicsManager();
IPedestalManager getPedestalManager();
IPlayerManager getPlayerManager();
IRespawnManager getRespawnManager();
ITranslationManager getTranslationManager();
IWorldEventManager getWorldEventManager();
IHelpOpManager getHelpOpManager();
IKitManager getKitManager();
void setGameState(Player player, GameState gameState);
void setGameState(GameState gameState);
GameState getGameState();
double getBaseHealth();
void setBaseHealth(double baseHealth);
World getLobbyWorld();
World getEventWorld();
}
```
### Game State
Observer manages three game states defined in the `GameState` enum:
| State | Description |
|---|---|
| `IN_LOBBY` | Players are in the lobby world awaiting the event start. |
| `PRE_GAME` | The event is being prepared (capsule assignment, countdown, etc.). |
| `IN_GAME` | The event is actively running. |
```java
// Get current state
GameState current = api.getGameState();
// Change state (fires PreGameStateChangeEvent)
api.setGameState(player, GameState.IN_GAME);
// Change state silently (no PreGameStateChangeEvent)
api.setGameState(GameState.IN_LOBBY);
```
---
## Custom Events
Observer fires custom Bukkit events at key lifecycle points. Cancellable events implement `Cancellable`.
### Game State Events
| Event | Cancellable | Description |
|---|---|---|
| `PreGameStateChangeEvent` | Yes | Fired before a game state transition. Allows setting a tick delay. |
| `GameStateChangeEvent` | No | Fired after a game state transition has completed. |
```java
@EventHandler
public void onPreStateChange(PreGameStateChangeEvent event) {
GameState oldState = event.getOldState();
GameState newState = event.getNewState();
Player source = event.getSource(); // nullable
// Add a 100-tick delay before the state change
event.setTickDelay(100);
// Or cancel it entirely
event.setCancelled(true);
}
@EventHandler
public void onStateChange(GameStateChangeEvent event) {
if (event.getNewState() == GameState.IN_GAME) {
// Game has started
}
}
```
### Elimination Events
| Event | Cancellable | Description |
|---|---|---|
| `PlayerEliminatedEvent` | Yes | Fired when a player is eliminated. Provides access to the killer, death message, drops, and the original `PlayerDeathEvent`. |
```java
@EventHandler
public void onElimination(PlayerEliminatedEvent event) {
Player eliminated = event.getPlayer();
LivingEntity killer = event.getKiller(); // nullable
// Modify the death message
event.setDeathMessage(Component.text("Custom death message"));
// Modify drops
event.setDrops(new ArrayList<>());
}
```
### Lifesteal Events
| Event | Cancellable | Description |
|---|---|---|
| `PlayerConsumeHeartEvent` | Yes | Fired when a player consumes a heart item. |
| `PlayerWithdrawHeartEvent` | Yes | Fired when a player withdraws a heart via `/withdraw`. |
### Capsule Events
| Event | Cancellable | Description |
|---|---|---|
| `PlayerAssignedToCapsuleEvent` | Yes | Fired when a player is assigned to a capsule. |
| `PlayerSwapCapsulesEvent` | Yes | Fired when two players swap capsule assignments. |
### Pedestal Events
| Event | Cancellable | Description |
|---|---|---|
| `PrePedestalCraftEvent` | Yes | Fired before a pedestal craft begins. |
| `PedestalCraftEvent` | No | Fired after a pedestal craft completes. |
| `PedestalLoadEvent` | No | Fired when a pedestal is loaded. |
### Recipe Events
| Event | Cancellable | Description |
|---|---|---|
| `PlayerCraftRecipeEvent` | Yes | Fired when a player crafts a custom recipe. |
### World Events
| Event | Cancellable | Description |
|---|---|---|
| `StartWorldEvent` | Yes | Fired when a world event is activated. |
| `EndWorldEvent` | Yes | Fired when a world event is deactivated. |
### Player Events
| Event | Cancellable | Description |
|---|---|---|
| `PlayerJoinFirstTimeEvent` | No | Fired the first time a player joins during an event. |
| `PlayerReviveEvent` | Yes | Fired when a player is revived. |
---
## Data Classes
### Capsule
```java
public record Capsule(UUID uniqueId, Location location, @Nullable String teamId) {}
```
Represents a spawn capsule with a unique ID, world location, and optional team assignment (requires Lead).
### RespawnData
```java
public record RespawnData(
String id, String timestamp, String name, String savedBy,
byte[] contents, double health, int foodLevel, float saturation,
float experience, int level, double absorption, int fireTicks,
List<String> potionEffects, Location location
) {}
```
A complete snapshot of a player's state used by the respawn and kit systems.
### PedestalData
```java
public record PedestalData(
String id, Location position, List<ItemStack> ingredients,
ItemStack result, int maxUses, float itemHeight,
PedestalType pedestalType, HashMap<UUID, Integer> uses
) {}
```
Represents a pedestal crafting station with its recipe, position, and usage tracking.
### WorldEvent
A data class representing a custom world event with an ID, icon material, translation ID, and a list of commands to execute on activation.
### Translation
```java
public record Translation(
@Nullable String tellraw, @Nullable Title title,
@Nullable SoundTranslation soundTranslation, List<String> commands
) {}
```
A translation entry that can be sent to individual players via `send(Player)` or broadcast to all players via `broadcast()`.
---
## Enums
| Enum | Values | Description |
|---|---|---|
| `GameState` | `IN_LOBBY`, `PRE_GAME`, `IN_GAME` | Current phase of the event lifecycle. |
| `CapsuleType` | `BATTLE_ROYALE`, `CIVILIZATION`, `WORLD_SPAWN` | Capsule spawning strategy. |
| `LifestealType` | `ANYTIME`, `DROP`, `CONSUME`, `OBTAIN` | When lifesteal hearts are distributed. |
| `PedestalType` | `SINGLE_USE`, `PER_PLAYER`, `REUSABLE` | How pedestal usage is limited. |
---
## Exceptions
The API defines specific exceptions for error handling:
| Exception | Description |
|---|---|
| `AlreadyInGameModeException` | Thrown when attempting to enter IN_GAME while already in that state. |
| `AlreadyInLobbyModeException` | Thrown when attempting to enter IN_LOBBY while already in that state. |
| `AlreadyInPreGameModeException` | Thrown when attempting to enter PRE_GAME while already in that state. |
| `InsufficientPlayersException` | Thrown when there are not enough players to start. |
| `InsufficientTeamsException` | Thrown when there are not enough teams to start. |
| `LeadNotInstalledException` | Thrown when a team operation requires Lead but it is not installed. |
| `NotInLobbyModeException` | Thrown when an operation requires IN_LOBBY state. |
| `NotInPreGameModeException` | Thrown when an operation requires PRE_GAME state. |
| `PlayerOverflowException` | Thrown when more players than capsules are available. |
| `TeamOverflowException` | Thrown when more teams than capsules are available. |
| `RecipeAddException` | Thrown when a custom recipe cannot be registered. |
---
## Player Data
Access player data through `IPlayerManager`:
```java
IPlayerManager playerManager = api.getPlayerManager();
// Online player data
IPlayerData data = playerManager.getPlayerData(player);
boolean inCombat = data.inCombat();
boolean isInLobby = data.isInLobbyMode();
boolean isDead = data.isDead();
String team = data.getBindedTeam();
// Offline player data
IOfflinePlayerData offlineData = playerManager.getPlayerData(uuid);
boolean wasEliminated = offlineData.isMarkedAsDead();
boolean wasSittingOut = offlineData.isSittingOut();
String region = offlineData.getRegion();
```
---
## Related Pages
- [[Observer/Developers/Overview]] - Developer overview
- [[Systems]] - Detailed system breakdowns