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
- Model world layers (keys, names, owning map version, default spawn, unlock requirements).
- Provide waypoint unlock + warp logic inside a single layer.
- Define corridor triggers that teleport to another layer while keeping relative offsets and optional cutscenes.
- Render mirror mannequins inside the overlap volumes so players fading between layers remain visible.
- Offer editor tooling (commands + visual nodes) so builders can place/update triggers without JSON hand-editing.
- 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
- Unlocking – “When I reach a shrine, I activate its waypoint and can warp back instantly from any other unlocked point on that layer.”
- Corridors – “Walking up a staircase should seamlessly move me into the ‘upper’ layer, placing me at the same relative coordinates so the geometry aligns.”
- Visibility – “While I’m halfway through a corridor, I still see other mannequins both ahead and behind so nobody suddenly disappears.”
- 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
| Component | Responsibility |
|---|---|
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. |
LayerWaypointService | Tracks unlocked waypoints per player (Mongo player_waypoints), provides /waypoint unlock/list/tp. |
LayerEditorHook | Spawns 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
- Boot:
WorldLayerServiceloads allWorldLayerDefinitions → obtains/creates aÜWorldInstanceper uniquemapVersionIdand registers them withWorldOverlayManager. - Player Join:
WorldManagerasksWorldLayerServicefor the “main” layer; player spawns there unless their last known location references another layer. - Waypoint Unlock: When a player enters a waypoint radius, the service records the unlock in
player_waypoints(Mongo) and fires aneditor.layer.waypoint.unlockedaudit event. - Corridor Entry:
PlayerMoveEventchecks for intersection withentryBox. 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.
- 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
/layercommand (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)
LayerEditorHookattaches toÜEditorInstanceand 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
- Data + Commands (current) – Collections, DTOs, service scaffolding,
/layeradmin command to CRUD layers, waypoints, corridors. No mirror support yet. - Runtime transitions – Player move listeners + teleport math + per-player cooldown.
- Mirror MVP – Use armor-stand mannequins to mirror players for N seconds while they overlap.
- Cinematics & Cutscenes – Integrate with cutscene engine and add optional fades, audio cues, etc.
- 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
- Implement
WorldLayerDefinition,WorldCorridorDefinition, andLayerWaypointdata classes + Mongo collections. - Build
WorldLayerService(component skeleton, loader integration, event registration). - Extend
WorldAccessto surface layer/corridor data into editor instances so gizmos can attach. - Add
/layercommand scaffolding for CRUD/testing. - Mirror this plan into Obsidian once the MCP link is restored.