Skip to content

Feature Plan: Layered World & Corridor System

Summary

  • Owner: Yuna (review: Freddi)
  • Status: Design → scaffolding
  • Backlog Link: docs/agendas/uebliche.md → 📥 Inbox (“Ebenen System / Übergangskorridore”)
  • Target Release: 2025.11.x (blocked by runtime scaffolding + content authoring tools)

The main world must behave like a stack of “layers”: fast-travel waypoints unlock within a layer, while cinematic corridors (trigger areas) move players between independent Minestom instances at seamless, relative positions. Transition zones also need “mirror” actors so players inside both layers can see one another during the swap.

Goals

  1. Model world layers (keys, names, owning map version, default spawn, unlock requirements).
  2. Provide waypoint unlock + warp logic inside a single layer.
  3. Define corridor triggers that teleport to another layer while keeping relative offsets and optional cutscenes.
  4. Render mirror mannequins inside the overlap volumes so players fading between layers remain visible.
  5. Offer editor tooling (commands + visual nodes) so builders can place/update triggers without JSON hand-editing.
  6. Persist definitions (Mongo) and stream them into runtime instances automatically.

Non-goals

  • Building the cinematic scripting system itself (just hook into existing cutscene runner once available).
  • Pathfinding or auto-generated corridors.
  • Cross-project fast travel (limited to ÜEblichE main world scope for now).

User Stories

  1. Unlocking – “When I reach a shrine, I activate its waypoint and can warp back instantly from any other unlocked point on that layer.”
  2. Corridors – “Walking up a staircase should seamlessly move me into the ‘upper’ layer, placing me at the same relative coordinates so the geometry aligns.”
  3. Visibility – “While I’m halfway through a corridor, I still see other mannequins both ahead and behind so nobody suddenly disappears.”
  4. Editing – “Inside the editor instance I can drop two boxes (‘entry’ and ‘exit’) to define a corridor and point it at another layer without restarting the server.”

Architecture Overview

ComponentResponsibility
WorldLayerDefinition (Mongo)Persistent record describing one layer (key, mapVersionId, default spawn, unlockables, visibility rules).
WorldCorridorDefinition (Mongo)Entry volume, optional exit volume, source/target layer keys, transition style, mirror settings.
WorldLayerService (server component)Loads definitions, instantiates per-layer instances via ÜInstanceManger, listens to player move events, runs transitions, manages mannequins.
LayerWaypointServiceTracks unlocked waypoints per player (Mongo player_waypoints), provides /waypoint unlock/list/tp.
LayerEditorHookSpawns gizmos (similar to LocationEditor/AreaEditor) to visualize entry/exit boxes and metadata nodes inside editor worlds.

Data Model

mermaid
classDiagram
    class WorldLayerDefinition {
        ObjectId id
        String key
        ObjectId mapVersionId
        String displayName
        Pos spawn
        List~LayerWaypoint~ waypoints
        LayerVisibilityMode visibilityMode
        List~String~ tags
    }
    class LayerWaypoint {
        String key
        String name
        Pos position
        boolean unlockedByDefault
        List~String~ requirements
    }
    class WorldCorridorDefinition {
        ObjectId id
        String key
        String fromLayer
        String toLayer
        Box3 entryBox
        Box3 exitBox
        boolean bidirectional
        TransitionStyle style
        boolean mirrorPlayers
        long cooldownMillis
    }

Coordinate System: Entry/exit boxes live in their respective layer coordinate spaces. During teleportation we store the player’s offset from the entry-box origin (delta = playerPos - entryBox.origin) and apply it to the target exit origin for seamless placement. Pitch/yaw stay untouched unless the corridor defines overrides.

Runtime Flow

  1. Boot: WorldLayerService loads all WorldLayerDefinitions → obtains/creates a ÜWorldInstance per unique mapVersionId and registers them with WorldOverlayManager.
  2. Player Join: WorldManager asks WorldLayerService for the “main” layer; player spawns there unless their last known location references another layer.
  3. Waypoint Unlock: When a player enters a waypoint radius, the service records the unlock in player_waypoints (Mongo) and fires an editor.layer.waypoint.unlocked audit event.
  4. Corridor Entry: PlayerMoveEvent checks for intersection with entryBox. If the corridor has a cinematic style, the service sends a cutscene packet/event, otherwise teleports immediately:
    • Validate cooldown + requirements.
    • Compute delta.
    • Teleport to target layer instance at exitBox.origin + delta.
    • If mirrorPlayers=true, spawn mirrored mannequins inside the corridor volumes for players on the opposite side until they leave the overlap.
  5. Mirror Management: Mirror mannequins reuse the mannequin/NPC system already powering the editor mannequins; they despawn once both the source and target players leave the transition buffer.

Editor Tooling

  • /layer command (scaffold) with subcommands:
    • layer create <key> <mapVersionId>
    • layer waypoint add <layerKey> <waypointKey> (records current position)
    • layer corridor add <key> <from> <to> (stores two selection boxes)
  • LayerEditorHook attaches to ÜEditorInstance and spawns:
    • Entry/Exit corner nodes (AreaEditor-style) for corridor boxes.
    • Floating label entity for metadata (target layer, style, cooldown).
    • Waypoint nodes with unlock radius spheres.

Phased Implementation

  1. Data + Commands (current) – Collections, DTOs, service scaffolding, /layer admin command to CRUD layers, waypoints, corridors. No mirror support yet.
  2. Runtime transitions – Player move listeners + teleport math + per-player cooldown.
  3. Mirror MVP – Use armor-stand mannequins to mirror players for N seconds while they overlap.
  4. Cinematics & Cutscenes – Integrate with cutscene engine and add optional fades, audio cues, etc.
  5. Web tooling – Dashboard view to monitor layers/corridors, edit metadata, and link to content docs.

Open Questions

  • Should waypoints unlock account-wide or per-character? (Assumed per Minecraft UUID for now.)
  • How do we store corridor-specific cutscenes (resource id vs inline script)?
  • Do we need support for more than two layers inside one corridor (e.g., chain of rooms) or will nested corridors suffice?

Next Steps

  1. Implement WorldLayerDefinition, WorldCorridorDefinition, and LayerWaypoint data classes + Mongo collections.
  2. Build WorldLayerService (component skeleton, loader integration, event registration).
  3. Extend WorldAccess to surface layer/corridor data into editor instances so gizmos can attach.
  4. Add /layer command scaffolding for CRUD/testing.
  5. Mirror this plan into Obsidian once the MCP link is restored.