# Systems Observer is composed of interconnected systems, each managed by a dedicated manager class. This page provides a detailed breakdown of each system's API interface, available methods, events, and how they interact programmatically. --- ## Event Lifecycle The core flow of an Observer-managed event follows a three-phase lifecycle controlled by the `GameState` enum. ### Phase 1: IN_LOBBY Players connect and are held in the lobby world. During this phase: - The **LobbyManager** manages the lobby world and player positioning. - The **PlayerManager** tracks player connections and initializes `IPlayerData`. - The **KitManager** allows staff to prepare kits. - The **CapsuleManager** can pre-configure capsule locations and types. - The **RestrictionManager** can set up item and enchantment restrictions. ### Phase 2: PRE_GAME Triggered by a state change from `IN_LOBBY` to `PRE_GAME`. This fires `PreGameStateChangeEvent` (cancellable, supports tick delay) followed by `GameStateChangeEvent`. During this phase: - The **CapsuleManager** assigns players to capsules based on the configured `CapsuleType`. - If Lead is installed, teams are assigned to capsules via `teamId`. - The **PlayerStateManager** prepares player states. - The **LateScatterManager** configuration determines how late joiners will be handled. ### Phase 3: IN_GAME Triggered by a state change from `PRE_GAME` to `IN_GAME`. The event is now actively running. During this phase: - The **CapsuleManager** releases players from capsules via `release()`. - The **EliminationManager** tracks deaths and fires `PlayerEliminatedEvent`. - The **LifestealManager** handles heart drops, consumption, and withdrawal. - The **DecayManager** tracks and decays placed blocks. - The **MechanicsManager** enforces all gameplay toggles. - The **WorldEventManager** can activate and deactivate world events. - The **PedestalManager** monitors pedestal interactions and crafting. - The **CustomRecipesManager** manages active custom recipes. - The **RespawnManager** captures and restores player states on death. - The **HelpOpManager** accepts player help requests. - The **TranslationManager** resolves and dispatches messages. --- ## Capsule System **API Interface:** `ICapsuleManager` **Config File:** `capsules.yml` The capsule system determines how players are distributed into the event world. Each capsule is a `Capsule` record containing a UUID, location, and optional team ID. ### Capsule Types | Type | Behavior | |---|---| | `BATTLE_ROYALE` | Scatters players randomly across the map within a min/max distance range. | | `CIVILIZATION` | Groups players into clusters within a configurable radius. | | `WORLD_SPAWN` | Spawns players near the world spawn within a configurable radius. | ### Key Operations - `setCapsules(List<Capsule>)` - Set capsule locations directly. - `sendPlayersToCapsules(Player executor)` - Assign all players to capsules. Fires `PlayerAssignedToCapsuleEvent` for each assignment. - `release()` - Release all players from their capsules (start the game). - `swapCapsules(Player, Player)` - Swap two players' capsule assignments. Fires `PlayerSwapCapsulesEvent`. - `sendPlayerToCapsule(Player, Capsule)` - Send a specific player to a specific capsule. ### Team Integration When Lead is installed, capsules can be bound to teams via the `teamId` field. The `CapsuleManager` assigns team members to their team's capsule during the `sendPlayersToCapsules()` operation. If Lead is not installed and a team operation is attempted, `LeadNotInstalledException` is thrown. --- ## Elimination System **API Interface:** `IEliminationManager` **Config File:** `managers/elimination.yml` The elimination system intercepts player deaths and applies configurable consequences. ### Flow 1. A player dies, triggering a `PlayerDeathEvent`. 2. Observer creates a `PlayerEliminatedEvent` (cancellable) with the player, killer, death message, and drops. 3. If not cancelled, the player's gamemode is set to `gamemode_on_death` (default: `SPECTATOR`). 4. If `lightning_on_kill` is enabled, lightning strikes at the death location. 5. The death message translation is broadcast using the configured `death_message` key. 6. If `auto_ban.enabled` is true and the player lacks the bypass permission, they are banned and shown the `kick_message` translation. 7. The remaining player count is updated (offset by `minimum_remaining_players`). ### Auto-Respawn When `auto_respawn` is enabled, eliminated players are automatically respawned instead of staying on the death screen. This works in conjunction with the **RespawnManager**. --- ## Lifesteal System **API Interface:** `ILifestealManager` **Config File:** `managers/lifesteal.yml` The lifesteal system adds health-based item mechanics to the game. ### Lifesteal Types | Type | Behavior | |---|---| | `DROP` | Hearts drop as items when a player is killed. | | `CONSUME` | Hearts are consumed directly on kill, granting health to the killer. | | `OBTAIN` | Hearts are added to the killer's inventory on kill. | | `ANYTIME` | Hearts can be obtained at any time. | ### Heart Items Hearts are custom items (default: Nether Star) registered through Bookshelf's item system. They have configurable display names, lore (MiniMessage format), material, item model, and stackability. ### Withdrawal When `can_withdraw` is true, players use `/withdraw [amount]` to convert their health into heart items. Each withdrawal removes 2 health points (1 heart) and produces one heart item. Withdrawal is blocked if the player's health would drop below `min_health`. The `PlayerWithdrawHeartEvent` is fired and can be cancelled. ### Consumption When a player right-clicks a heart item, the `PlayerConsumeHeartEvent` is fired. If not cancelled, the player gains 2 health points per heart. Consumption is blocked at `max_health`. If `should_remove_heart` is true, the heart item is consumed. ### Health Bounds - `max_health` (default: 40) — Maximum achievable health. - `min_health` (default: 14) — Minimum health before withdrawal is blocked. --- ## Decay System **API Interface:** `IDecayManager` The decay system tracks player-placed blocks and reverts them to air after a configurable time. ### Key Operations - `markBlockForDecay(Block block)` - Mark a block for decay with the default timer. - `markBlockForDecay(Block block, int decayTime)` - Mark a block for decay with a custom timer in ticks. - `unmarkBlockForDecay(Block block)` - Cancel a pending decay. - `isMarkedForDecay(Location location)` - Check if a block is pending decay. ### Global Block Decay When `should_global_block_decay` is enabled in `mechanics.yml`, all player-placed blocks are automatically marked for decay. --- ## Pedestal System **API Interface:** `IPedestalManager` **Config File:** `pedestals.yml` Pedestals are world-placed crafting stations that require specific ingredients and produce a result item. ### Pedestal Types | Type | Behavior | |---|---| | `SINGLE_USE` | The pedestal can only be used once, globally. | | `PER_PLAYER` | Each player can use the pedestal up to `maxUses` times. | | `REUSABLE` | The pedestal has unlimited uses. | ### PedestalData Record Each pedestal is a `PedestalData` record containing: - `id` - Unique string identifier. - `position` - World location. - `ingredients` - List of required `ItemStack` ingredients. - `result` - The `ItemStack` produced on craft. - `maxUses` - Maximum number of uses (for PER_PLAYER type). - `itemHeight` - Height offset for the holographic item display. - `pedestalType` - The usage limitation type. - `uses` - Per-player usage tracking map. ### Events - `PrePedestalCraftEvent` (cancellable) - Fired before ingredients are consumed. - `PedestalCraftEvent` - Fired after the craft completes. - `PedestalLoadEvent` - Fired when a pedestal is loaded from configuration. --- ## Mechanics System **API Interface:** `IMechanicsManager` **Config File:** `mechanics.yml` The mechanics system provides toggles for a wide range of gameplay behaviors. Each toggle has a getter and setter method on the `IMechanicsManager` interface. ### Combat Logging The `ICombatLoggingManager` (nested interface within `IMechanicsManager`) tracks combat state: - `canCombatLog()` - Whether combat logging detection is enabled. - `getCombatTimer()` - Duration of combat tag in seconds. - `getDisplayType()` - Where the combat notification appears (`ACTION_BAR`, `TITLE`, `CHAT`). - `getDisplayMessage()` - The message template with `{time}` placeholder. Combat state is tracked per-player through `IPlayerData.inCombat()` and `IPlayerData.setCombat(boolean)`. --- ## World Event System **API Interface:** `IWorldEventManager` **Config File:** `managers/world_events.yml` World events are named occurrences that execute commands and broadcast translation messages when activated. ### WorldEvent Data Each `WorldEvent` contains: - `id` - Unique string identifier. - `itemIcon` - Material used as the icon in the GUI. - `translationId` - Translation key broadcast on activation/deactivation. - `commands` - List of commands executed on activation. ### Key Operations - `addWorldEvent(WorldEvent)` - Register a new world event. - `activateWorldEvent(String eventId)` - Start a world event. Fires `StartWorldEvent`. - `deactivateWorldEvent(String eventId)` - End a world event. Fires `EndWorldEvent`. - `isWorldEventActive(String eventId)` - Check if a specific event is active. - `hasActiveWorldEvent()` - Check if any event is active. - `getActiveWorldEvents()` - Get all currently active event IDs. --- ## Kit System **API Interface:** `IKitManager` The kit system saves and restores complete player states as named kits. ### RespawnData Record Kits use the `RespawnData` record which captures: - Inventory contents (serialized as bytes) - Health, food level, saturation - Experience and level - Absorption amount - Fire ticks - Active potion effects - Location (optional) - Metadata: ID, timestamp, name, saved-by player ### Key Operations - `savePlayerState(Player, String kitId, boolean saveLocation)` - Capture a player's current state as a kit. - `loadPlayerState(Player, RespawnData)` - Apply a kit to a player. - `deleteKit(String kitId)` - Remove a kit. - `renameKit(String kitId, String newName)` - Rename a kit. - `getKitById(String kitId)` - Retrieve a specific kit. - `getKitIds()` - List all kit IDs. - `getKits()` - Retrieve all kit data. ### Export and Import Kits can be exported to shareable codes or mclo.gs URLs and imported back, enabling kit sharing across servers. --- ## Custom Recipes System **API Interface:** `ICustomRecipesManager` **Config File:** `custom_recipes.yml` Register custom shaped and shapeless crafting recipes that persist across server restarts. ### Key Operations - `newEmptyShaped(String id, ItemStack result)` - Create a new empty shaped recipe. - `newEmptyShapeless(String id, ItemStack result)` - Create a new empty shapeless recipe. - `add(ShapedRecipe)` / `add(ShapelessRecipe)` - Register a recipe. Throws `RecipeAddException` on failure. - `remove(String id)` - Unregister a recipe. - `get(String id)` - Retrieve a recipe by ID. - `reload()` / `save()` - Reload from or persist to configuration. --- ## Respawn System **API Interface:** `IRespawnManager` **Config File:** `managers/respawn.yml` The respawn system captures player state snapshots and restores them on respawn. - `createRespawnData(Player)` - Capture the player's current state. - `respawnPlayer(Player, RespawnData)` - Restore a player from a saved state. - `isEnabled()` / `setEnabled(boolean)` - Toggle the system. --- ## Late Scatter System **API Interface:** `ILateScatterManager` **Config File:** `managers/late_scatter.yml` Handles players who join after the game has started by scattering them into the event world. - `isEnabled()` / `setEnabled(boolean)` - Toggle late scatter. - `getGamemode()` / `setGamemode(GameMode)` - The gamemode assigned to late joiners. - `getItems()` / `setItems(ItemStack[])` - Starting inventory for late joiners. - `getTranslation()` / `setTranslation(String)` - Translation key for the late join broadcast. Per-player tracking via `IOfflinePlayerData.hasBeenLateScattered()` prevents duplicate scattering. --- ## Player Data System **API Interface:** `IPlayerManager`, `IPlayerData`, `IOfflinePlayerData` **Config File:** `players.yml` Tracks per-player state throughout the event. ### IPlayerData (Online) | Method | Description | |---|---| | `inCombat()` | Whether the player is in combat. | | `isInLobbyMode()` | Whether the player is in lobby mode. | | `isDead()` | Whether the player is dead/eliminated. | | `isStaffing()` | Whether the player is in staff mode. | | `getBindedTeam()` | The team ID the player is bound to (requires Lead). | ### IOfflinePlayerData | Method | Description | |---|---| | `hasBeenLateScattered()` | Whether the player has been late scattered. | | `isMarkedAsDead()` | Whether the player has been eliminated. | | `isSittingOut()` | Whether the player is sitting out. | | `getRegion()` | The WorldGuard region the player is assigned to. | --- ## Translation System **API Interface:** `ITranslationManager` **Config File:** `translations.yml` The translation system resolves message keys into `Translation` objects that can include tellraw messages, titles, sounds, and commands. ```java ITranslationManager translations = api.getTranslationManager(); // Simple translation Translation msg = translations.translate("ELIMINATION_MESSAGE"); msg.send(player); // Send to one player msg.broadcast(); // Broadcast to all players // Translation with variables Translation msg = translations.translate("PEDESTAL_CRAFT", VariableContext.of("player", player.getName(), "item_name", "Diamond Sword")); msg.broadcast(); ``` ### Translation Structure Each translation key can define: - `tellraw` - MiniMessage chat message. Prefix with `<center>` for centered text. - `title.title` / `title.subtitle` - Title and subtitle display. - `sound.sound` / `sound.volume` / `sound.pitch` - Sound effect. - `broadcastable` - Whether the translation supports broadcasting. - `commands` - Commands to execute alongside the translation. --- ## HelpOp System **API Interface:** `IHelpOpManager` **Config File:** `managers/helpop.yml` A simple staff assistance system with cooldown management. - `isEnabled()` / `setEnabled(boolean)` - Toggle the system. - `getCooldown()` / `setCooldown(long)` - Get or set the cooldown in milliseconds. - `clearHelpOps()` - Clear all pending help requests. Staff members with the `lodestone.observer.staff` permission receive notifications when players submit help requests. --- ## System Interaction Diagram The following describes the primary interactions between systems during a typical event: 1. **IN_LOBBY** - `PlayerManager` tracks joins. `KitManager` and `RestrictionManager` prepare the event. 2. **PRE_GAME** - `CapsuleManager` assigns players. `PlayerStateManager` saves lobby states. 3. **IN_GAME** - `CapsuleManager.release()` starts the game. `EliminationManager` watches for deaths. `LifestealManager` drops hearts. `DecayManager` tracks blocks. `MechanicsManager` enforces rules. `WorldEventManager` triggers events. `PedestalManager` monitors crafting. `TranslationManager` delivers messages. 4. **End of Event** - State transitions back to `IN_LOBBY`. Managers reset their state. --- ## Related Pages - [[Observer/Developers/Overview]] — Developer overview - [[Observer/Developers/API Reference]] — API classes and interfaces