JuByteNexus Bridge-Protokoll – Vollständige technische Referenz (v1)
1. Überblick
Das JuByteNexus Bridge-Protokoll verbindet Minecraft-Proxy- und Backend-Server mit dem zentralen Nexus-Core über WebSocket (JSON). Die Implementierung besteht aus:
- Proxy-Seite:
NexusVelocityPlugin (Velocity, role: PROXY)
- Backend-Seite:
NexusBridgePlugin (Paper, role: BACKEND)
- Core-Seite:
BridgeWsHandler + BridgeManager (Spring WebSocket-Handler)
- Gemeinsame Lib:
NexusBridgeClient (Reconnect, Heartbeat, Ban-Cache, Outbox)
2. Velocity-Plugin – Proxy-Spezifisches Verhalten
2.1 Lifecycle & Initialisierung
| Phase | Aktion | Code |
|---|
| Plugin-Load | Config laden (nexus-bridge.properties); NexusBridgeClient instanziieren mit ProxyBridgeListener | onInit(ProxyInitializeEvent) |
| Config-Defaulting | Falls nicht vorhanden: core-url, server-name, token, server-key initialisieren | loadConfig() |
| Start | client.start() nur wenn Token ODER Server-Key vorhanden | start() in Listener |
| Shutdown | client.stop() (sauberes WebSocket-Close) | onShutdown(ProxyShutdownEvent) |
2.2 Was Velocity UNTERSCHIEDLICH macht (vs. Paper)
| Aspekt | Paper | Velocity |
|---|
| Role | BACKEND | PROXY |
| Ban-Enforcement | Join + Live (Kick bei aktivem Ban) | Nur Join (Pre-Login), reicht bei Proxy |
| Capabilities | KICK, BROADCAST, CHAT_READ, EXECUTE | KICK, BROADCAST, SUBSERVER_AWARE |
| Player-Tracking | Pro-Backend; TPS/Entity-Metriken | Nur Proxy-weite Online-Count |
| Vault/Ranks | Vollständiger Vault-Support + Farben | Keine Vault-Integration (Ranks kommen vom Backend) |
| Console | Kann Console-Output streamen | Nicht unterstützt |
| Heartbeat-Fields | tps, cpuLoad, memUsedMb, memMaxMb, entities, chunks, maxPlayers, uptimeSeconds | Nur playersOnline, maxPlayers |
2.3 Weitergeleitete Events (Bridge → Core)
| Event | Velocity-Handler | Payload | Timing |
|---|
| handshake | onInit() | {token, serverName, bridgeType: "VELOCITY", role: "PROXY", version, gameVersion, capabilities} | Nach Core-Connect |
| player.join | onPostLogin() | {game: "minecraft", gameId: UUID, name, ip?} | Sofort nach erfolg. Login |
| players.sync | onConnected() | {players: [{gameId, name, ip?}, ...]} | Nach jedem Reconnect |
| player.quit | onDisconnect() | {game: "minecraft", gameId: UUID} | Bei Disconnect |
2.4 Kommandos (Core → Velocity)
| Kommando | Handler | Effekt | Ack |
|---|
| command.kick | onKick() | player.disconnect(Component.text("Gekickt: " + reason)) | command.ack |
| command.broadcast | onBroadcast() | proxy.sendMessage(Component.text("[Nexus] " + message)) | Sync (Fire-and-Forget) |
| command.message | onMessage() | player.sendMessage(Component.text(message)) | Sync |
| punishment.request | (Ban-Cache nur) | Ban-Cache lokal aktualisiert; Live-Kicks über onPunishment() | Über ban.created |
| command.execute | Nicht unterstützt | – | – |
| server.power | Nicht unterstützt | – | – |
2.5 Ban-Cache-Enforcement
Velocity:
1. Handshake → Core sendet "ban.sync" mit allen aktiven BAN/TEMPBAN
2. ProxyBridgeListener registriert BanCache.activeBan() im Client
3. Bei Login: ban check PRÜFT lokal (< 1 ms), keine Netzwerk-Latenz
4. Live: bei "ban.created" → client kickt sofort Spieler (if online)
Besonderheit Proxy: Ban-Evasion-Schutz über IP ist möglich, kann aber nur vom Paper-Backend konfiguriert werden. Velocity hält die IP-Ban-Liste aus dem Core-Sync, kann aber nicht selbst IP-Bans erzwingen (kümmert sich um Auth nicht).
3. Core WebSocket Handler – Server-Seite
3.1 Endpoint & Connection-Lifecycle
| Aspekt | Details |
|---|
| Endpoint | ws://<host>:8080/bridge/ws (oder über Nginx reverse proxy) |
| Transport | Spring WebSocket (TextWebSocketHandler) |
| Session-Tracking | Map<sessionId, ConnState> mit serverId + Dedup-Set (seenIds) |
| Authentifizierung | Nur Handshake; danach sessionId-basiert |
| Max Connections | Theoretisch unbegrenzt (1 Pro Server) |
3.2 Handshake (Bridge → Core)
Request (erste Nachricht, type: handshake):
{
"type": "handshake",
"id": "<uuid>",
"data": {
"token": "<einmal-token ODER server-key>",
"serverName": "lobby-1",
"bridgeType": "PAPER" | "VELOCITY" | "BUNGEE",
"role": "BACKEND" | "PROXY",
"version": "0.1.0",
"gameVersion": "1.21.4",
"capabilities": ["KICK", "BROADCAST", "CHAT_READ", "EXECUTE", "SUBSERVER_AWARE"]
}
}
Success-Response (type: handshake.ok):
{
"type": "handshake.ok",
"id": "<gen>",
"data": {
"serverId": "<uuid>",
"serverKey": "nxk_<base64-48-bytes>" | null,
"coreVersion": "0.1.0"
}
}
Error-Response (type: handshake.error):
{
"type": "handshake.error",
"id": "<gen>",
"data": {
"code": "NX-3001",
"message": "Bridge token invalid"
}
}
Handshake-Logik (BridgeWsHandler.handshake):
- Hash des
token berechnen: SHA-256(credential)
- Nachschlag in
GameServer.serverKeyHash → Existiert?
- Ja: Server bekannt, re-connect, kein neuer Key.
- Nein:
ServerToken mit diesem Hash suchen, used=false?
- Bei neuer Server aus Token:
- Neuer Server erzeugen/update
GameServer (name, type, role, version, capabilities)
- Zufälliger 48-Byte-Key generieren →
nxk_<base64> → Hash speichern
- Token als
used=true markieren
ConnState(serverId, BoundedMap<2000 seenIds>) erstellen und registrieren
- Antwort mit
handshake.ok senden
- Ban-Cache-Sync:
BridgeManager.sendBanSync(session) (alle aktiven BAN/TEMPBAN/MUTE + Metadaten)
- Message-Sync:
BridgeManager.sendMessagesSync(session) (Panel-editierte Texte)
- Template-Sync:
TemplateSyncBridge.sendTo(session) (Ban- & Report-Templates)
- Event publish:
server.online
4. Kompletter Nachrichtenkatalog (Beide Richtungen)
4.1 Bridge → Core (Inbound in BridgeWsHandler)
Player Events
| Typ | Wann | Felder | Beschreibung |
|---|
| player.join | Nach erfolgreichem Login | game: "minecraft", gameId: "<uuid>", name: "<string>", ip: "<ip>"?, rank: "<group>"?, skin: "<url>"? | Spieler betritt Server; Optional Vault-Rank + Skin-URL (online-mode). |
| players.sync | Nach jedem Reconnect (Handshake+) | players: [{game, gameId, name, ip?, rank?}, ...] | Roster aller derzeit online Spieler; verhindert verwaiste Offline-Einträge bei Reconnect. |
| player.quit | Bei Disconnect | game: "minecraft", gameId: "<uuid>" | Spieler verlässt Server. |
| player.chat | Chat-Event (nur wenn Bridge Capability CHAT_READ) | gameId: "<uuid>", message: "<string>" | Nur wenn Modul abonniert hat. |
| player.report | /report-Kommando (Ingame) | reporterGameId: "<uuid>", reporterName: "<string>", targetName: "<string>", reason: "<string>", `category: "GENERAL" | ...` |
| player.device | Alle 60s (Telemetry) | gameId: "<uuid>", name: "<string>", hardwareId: "<sha256>", os: "<string>"?, mcVersion: "<string>"?, client: "<string>"? | Client-Fingerprint vom Plugin-Channel nexus:hwid oder Launcher. |
| player.inventory | Alle 60s (Telemetry) | gameId: "<uuid>", name: "<string>", `kind: "MAIN" | "ARMOR" |
Server Events
| Typ | Wann | Felder | Beschreibung |
|---|
| vault.groups | Nach Vault-Init, dann bei Gruppen-Update | groups: {<name>: <hexColor>?} oder groups: [<name>, ...] | Alle Vault-Gruppen mit auto-erkannter Farbe. Wird union'ed in VaultGroupRegistry für ACP-Dropdown. |
| heartbeat | Alle 10s | playersOnline: <int>, maxPlayers: <int>?, tps: <float>?, cpuLoad: <float>?, memUsedMb: <int>?, memMaxMb: <int>?, entities: <int>?, chunks: <int>?, uptimeSeconds: <long>? | Alle Felder optional (rückwärtskompatibel). Backend füllt Metriken; Proxy nur playersOnline. |
| console.line | Stream läuft (nur wenn console.subscribe aktiv) | line: "<string>" | Eine Zeile Console-Output; landet in ConsoleBuffer (Ring: 400 lines/Server). |
Link & Punishment
| Typ | Wann | Felder | Beschreibung |
|---|
| link.request | /nexus link (Ingame) | gameId: "<uuid>", name: "<string>" | Spieler verknüpft Konto; Core antwortet mit link.code. |
| punishment.request | /ban, /mute, … (Ingame-Kommando oder Admin-Modul) | targetGameId: "<uuid>"?, targetName: "<string>"?, `type: "BAN" | "TEMPBAN" |
| punishment.revoke | Admin hebt Strafe auf | targetGameId: "<uuid>"?, targetName: "<string>"?, `type: "BAN" | ..., actorName: "<string>"` |
| chatlog.request | /chatlog <player> (Ingame, nur wenn Chat-Buffer vorhanden) | targetGameId: "<uuid>"?, targetName: "<string>"?, actorName: "<string>" | Event chatlog.requested publish'ed für BanSystem-Snapshot. |
Scheduler & Acknowledge
| Typ | Wann | Felder | Beschreibung |
|---|
| command.ack | Nach Kommando-Ausführung (Bridge → Core) | `ok: true | false, error: "<string>"?` |
4.2 Core → Bridge (Outbound aus BridgeManager & BridgeWsHandler)
Ban-Cache-Synchronisation
| Typ | Wann | Felder | Beschreibung |
|---|
| ban.sync | Nach Handshake.ok, einmalig | `bans: [{gameId, type, reason, expiresAt: "<ISO-8601>" | null, banCode: <int>?, caseNumber: "<string>"?, ip: "<ip>"?}, ...]` |
| ban.created | Bei neuer Strafe | gameId: "<uuid>", `type: "BAN" | ..., reason: "<string>", expiresAt: "<ISO>"?, banCode: <int>?, caseNumber: "<string>"?, ip: "<ip>"?` |
| ban.revoked | Bei Strafe-Aufhebung | gameId: "<uuid>", `type: "BAN" | ...` |
Player Commands
| Typ | Wann | Felder | Beschreibung | Ack? |
|---|
| command.kick | Admin/Modul befiehlt Kick | gameId: "<uuid>", reason: "<string>" | Bridge kickt Spieler mit Grund. | Ja |
| command.message | PM vom Core an Spieler | gameId: "<uuid>", message: "<string>" | Bridge sendet Message an Spieler. | Ja |
| command.broadcast | Broadcast an alle Spieler | message: "<string>" | Bridge broadcastet. | Ja |
| command.teleport | Admin teleportiert Spieler (z.B. bei Report-Claim) | whoGameId: "<uuid>", toGameId: "<uuid>" | Bridge teleportiert who zu to. | Ja |
| command.setrank | ACP setzt Vault-Rang | gameId: "<uuid>", rank: "<group>", `exclusive: true | false` | Bridge setzt Gruppe in Vault (add oder replace). |
| command.execute | Shop-Lieferung oder Script (nur mit Capability EXECUTE) | command: "<string>" | Konsolen-Kommando auf Main-Thread; Bridge ack't Erfolg/Fehler. | Ja |
Server Lifecycle
| Typ | Wann | Felder | Beschreibung | Ack? |
|---|
| server.power | ACP befiehlt Stop/Restart | `action: "stop" | "restart"` | stop: Bukkit.shutdown(). restart: Restart-Routine. |
Console Streaming
| Typ | Wann | Felder | Beschreibung | Ack? |
|---|
| console.subscribe | ACP öffnet Console-Tab | – | Bridge startet Console-Streaming. | Nein |
| console.unsubscribe | ACP schließt Console-Tab | – | Bridge stoppt Streaming. | Nein |
Link & Messages
| Typ | Wann | Felder | Beschreibung | Ack? |
|---|
| link.code | Antwort auf link.request | gameId: "<uuid>", code: "ABC-123", expiresInSeconds: 300 | Bridge zeigt Code im Chat. | Nein |
| messages.sync | Nach Handshake, bei Hot-Reload | messages: {<key>: "<legacy-§-code-text>", ...} | Panel-editierte spielersichtbare Texte; Bridge nutzt für Replacements (z.B. Kick-Grund). | Nein |
Templates
| Typ | Wann | Felder | Beschreibung | Ack? |
|---|
| templates.sync | Bei Template-Update | banTemplates: ["template1", ...], reportTemplates: [...] | Namen für Tab-Completion & Validierung. | Nein |
5. Verbindung & Resilienz
5.1 Heartbeat-Protokoll
Client-Seite (Bridge):
- executor.scheduleAtFixedRate(heartbeat, 10, 10, TimeUnit.SECONDS)
- Nur gesendet wenn ready=true (nach handshake.ok)
- Payload: playersOnline + alle optional Metriken (paper) oder leer (velocity)
Core-Seite (BridgeWsHandler):
case "heartbeat":
- ServerMetrics.applyHeartbeat(server, data) → setzt alle Felder (optional-safe)
- server.setLastSeenAt(Instant.now())
- servers.save()
- alertService.check() → Prüft auf Offline-Anomalien
Heartbeat-Timeout: Nicht implementiert; Core nutzt lastSeenAt für Admin-UI (keine auto-Disconnect bei fehlenden Heartbeats).
5.2 Reconnect & Exponential Backoff
Fehlerfall:
- socket = null, ready = false
- backoffSeconds *= 2, max 30s
- LOG.warn("Core unreachable, retrying in {delay}s")
- Outbox.add(message) für alle outgoing Events (max 10.000 queued)
Nach reconnect (handshake.ok):
- backoffSeconds = 1 (reset)
- Outbox.drain() → alle ausstehend Events flushen (FIFO)
- Ban-Cache neu synced
Duplikat-Deduplizierung: Jede Nachricht hat eindeutige id. Core-Seite speichert seenIds pro Connection in BoundedMap<2000> (LRU). Bei Replay (z.B. retried message) wird duplikat ignoriert.
5.3 Offline-Verhalten (Cache)
| Situation | Verhalten |
|---|
| Core down, Spieler versucht Login | Proxy/Backend liest aus lokalem Ban-Cache → kein Netzwerk-Hit. |
| Core down, /ban wird eingegeben | Event in Outbox queued. Bei reconnect gesendet. |
| Core down, /kick wird eingegeben | Kein Kommando vom Core erhalten → Spieler bleibt online. |
| Vault-Gruppen veraltet | Letzte Sync-Gruppe gelten; bei reconnect neue Sync. |
| Message-Bundle alt | Fallback-Texte in Bridge hardcoded (z.B. Kick-Grund Default). |
6. Authentifizierung & Sicherheit
6.1 Token vs. Server-Key
| Aspekt | Token | Server-Key |
|---|
| Format | Beliebig, ACP-generiert | nxk_ + 48 Bytes Base64 |
| Gültigkeit | Einmal; wird nach Handshake ungültig | Persistent, in Bridge-Config gespeichert |
| Verwendung | Erstes Handshake einer neuen Bridge | Alle folgenden Handshakes |
| Storage | ACP (Server-Token-Tabelle) | Bridge Config (plain-text) |
| Rotation | Manuell über ACP (Token-Revoke) | Automatisch bei Token-Handshake |
6.2 Hash & Verifikation
handshake(data):
credential = data.token
credentialHash = SHA-256(credential)
if (findByServerKeyHash(credentialHash)) → known server
else if (findByTokenHashAndUsedFalse(credentialHash)) → new server
token.used = true
newServerKey = "nxk_" + Base64(random 48 bytes)
sendResponse(handshake.ok, serverKey)
else → credentials invalid
sendResponse(handshake.error, NX-3001)
close()
Kanal-Sicherheit: WebSocket über wss:// (TLS) empfohlen; credentials im data Feld unverschlüsselt (kein HTTP-Body-Encryption notwendig bei TLS).
7. Nachrichtenformat & Frame-Struktur
7.1 Allgemeine Nachricht
{
"type": "<string>",
"id": "<uuid oder custom-id>",
"data": {
...
}
}
- type: Nachrichten-Typ (z.B.
player.join, command.kick, handshake)
- id: Eindeutige Frame-ID für Dedup. Bei Commands: echoed in
command.ack. Optional für fire-and-forget Events.
- data: Payload als Objekt/Array/String, varies by type.
7.2 Message-ID Semantik
| Quelle | ID-Muster | Behavior |
|---|
| Bridge → Core | UUID.randomUUID().toString() | Core speichert in seenIds; duplikat ignoriert |
| Core → Bridge | UUID.randomUUID().toString() (fire-and-forget) | Kein Ack erwartet |
| Core → Bridge (Scheduler) | "schedrun:<runId>" | Bridge ack't mit dieser ID → Core matched Result |
8. Fehlerbehandlung & Edge Cases
8.1 Fehler-Szenarien
| Fehler | Handling |
|---|
| Ungültiger Token | handshake.error NX-3001, Close |
| Malformed JSON | LOG.warn, Frame ignoriert (forward-compatible) |
| Unbekannter Message-Type | Forward-compatible: ignoriert, kein Error |
| Server nicht gefunden (ConnState=null) | Close mit SERVER_ERROR |
| Session Closed | afterConnectionClosed() → BridgeManager.unregister(), Players offline markiert |
| Send Failed (IOException) | LOG.warn, Outbox-Flush bei nächstem Connect |
8.2 Duplikat-Handling
Scenario: Bridge sendet player.join, dann Verbindung bricht und Reconnect spielt Outbox ab.
Client (Bridge):
1. Send "player.join" id=abc123
2. Disconnect
3. Reconnect + handshake.ok
4. Outbox.drain() → resend "player.join" id=abc123
Server (Core):
1. Receive "player.join" id=abc123 → seenIds.add(abc123) ✓
2. Disconnect
3. Reconnect, new session, new seenIds = empty
4. Receive "player.join" id=abc123 → seenIds.add(abc123) ✓
(Pro Session, also nicht global duplikat-safe über Sessions hinweg)
Implication: Idempotenz auf Core-Seite nur pro Session. Wenn Backend über 2 Sessions versucht, selbe Event zweimal zu senden (nach brutaler Neubindung), wird es twice processed. Aktuell akzeptiert (spieler 2x join, dann quit).
9. Capability-System
Bridges berichten ihre Fähigkeiten im Handshake; Core prüft vor Kommando-Dispatch.
| Capability | Meaning | Commands |
|---|
| KICK | Can disconnect players | command.kick, ban.created |
| BROADCAST | Can send to all players | command.broadcast |
| CHAT_READ | Can read & forward chat events | player.chat inbound |
| EXECUTE | Can run console commands | command.execute |
| SUBSERVER_AWARE | Proxy: weiß von Backend-Servern, kann routing | Used by Velocity for info only |
Velocity-Defaults: ["KICK", "BROADCAST", "SUBSERVER_AWARE"]
Paper-Defaults: ["KICK", "BROADCAST", "CHAT_READ", "EXECUTE"]
10. Performance & Skalierung
10.1 Latenz-Profile
| Operation | Latenz | Bottleneck |
|---|
| Ban-Check (Join) | < 1 ms | Map Lookup (Local) |
| Player.join → Core Process | 50–200 ms | Netzwerk + Message-Queue |
| Message-Delivery (Kick) | 50–200 ms | Netzwerk |
| Heartbeat-Cycle | 10 s | Scheduler Interval |
10.2 Memory-Footprint
| Component | Size | Notes |
|---|
| Ban-Cache (1000 active bans) | ~500 KB | ConcurrentHashMap |
| Message-Bundle (200 keys) | ~50 KB | Strings in HashMap |
| Console-Buffer (400 lines, 512 bytes avg) | ~200 KB | Ring-Buffer pro Server |
| Outbox (10.000 messages) | ~5 MB | Worst case (connected bridge = leerer Outbox) |
| Connections-Map | ~1 KB per Bridge | UUID → Session |
11. Konfiguration (Bridge-Seite)
11.1 Velocity: plugins/jubyte-nexus-bridge/nexus-bridge.properties
core-url=ws://localhost:8080/bridge/ws
server-name=proxy-1
token=<generated-from-acp>
server-key=nxk_<generated-on-first-handshake>
11.2 Paper: plugins/JuByteNexusBridge/config.yml
core-url: ws://localhost:8080/bridge/ws
server-name: server-1
token: ""
server-key: ""
Flow nach Token-Handshake:
- ACP generiert Token, Admin gibt Token in Bridge ein
- Bridge:
token=<token>
- Erstes Handshake → Core antwortet mit
serverKey
BridgeListener.onServerKeyIssued(key) speichert persistent
- Nächstes Handshake:
token=<leer>, nutzt server-key stattdessen
12. Integrationen & Dependencies
12.1 Core-Seitig
| Komponente | Funktion | Quelle |
|---|
| BridgeManager | Session-Tracking, Command-Dispatch, Ban-Broadcast | Spring Component |
| VaultGroupRegistry | Gruppen-Union aus allen Bridges für ACP-UI | In-Memory (pro Restart rebuild) |
| ConsoleBuffer | Ring-Buffer console.line Frames (400 lines/Server) | In-Memory (pro Restart reset) |
| BanCacheProvider (SPI) | Abstraktion über Punishment-Module (Ban-System) | Plugin-Pattern |
| EventBus | Publish server.online, player.chat, chatlog.requested, etc. | Spring Application Events |
| PlayerService | Player join/quit/sync/rank/skin ORM | Domain Service |
| LinkService | Generiert Link-Codes (UCP Account-Linking) | Domain Service |
| PunishmentCreator (SPI) | Instanziiert Punishment aus Request | Plugin-Pattern |
12.2 Bridge-Seitig (Paper)
| Komponente | Funktion |
|---|
| PlayerEvents | Bukkit-Events → Bridge (join, quit, chat, move, …) |
| BanModule | /ban, /mute, /report Commands + Chat-Filter |
| VaultBridge | Vault-Gruppe Erkennung + Farben |
| HwidChannel | Plugin-Channel nexus:hwid für Hardware-Fingerprints |
| Telemetry | Alle 60s: Device + Inventory Snapshot |
| PluginBridgeListener | Implementiert BridgeListener, dispatch lokale Commands |
13. Testing & Debugging
13.1 Logging
Bridge-Seite:
nexus.bridge Logger (System.Logger)
- WARN: "Core unreachable (…), retrying in 30s"
- ERROR: "Core rejected handshake: NX-3001 — check the bridge token!"
- INFO: "Ban cache synced: 42 entries"
Core-Seite:
org.springframework.web.socket → TRACE
- Inbound frame (type=handshake, id=abc)
- Outbound frame (type=ban.created, id=xyz)
13.2 Mock-Tests
NexusBridgeClient-Test:
BridgeConfig config = new BridgeConfig("ws://…", "test", "PAPER", "BACKEND", "0.1.0", "1.21",
List.of("KICK", "BROADCAST"), "token", "");
NexusBridgeClient client = new NexusBridgeClient(() -> config, listener, () -> 5);
// Manuell BridgeMessage.of("handshake.ok", ...) auf listener → ready.get() = true
14. Zusammenfassung: Differenzen Velocity vs. Paper
| Eigenschaft | Velocity (Proxy) | Paper (Backend) |
|---|
| Rolle | Netzwerk-Edge, Ban-Prä-Check | Game-Server, Spieler-Management |
| Ban-Enforcement | Pre-Login nur (kann nicht fein-granular) | Join + Live (mit Mute-Chat-Filter) |
| Capabilities | KICK, BROADCAST, SUBSERVER_AWARE | KICK, BROADCAST, CHAT_READ, EXECUTE |
| Metriken | Nur playersOnline, maxPlayers | Voll: TPS, CPU, Entities, Chunks, RAM |
| Vault-Support | Keine Gruppen-Erkennung | Vollständig mit Farb-Sync |
| Console | Nicht möglich | Streaming (400-line Buffer) |
| Heartbeat | Minimal | Umfangreich |
| Telemetry | – | Device + Inventory (je 60s) |
| Config-Ort | plugins/jubyte-nexus-bridge/nexus-bridge.properties | plugins/JuByteNexusBridge/config.yml |
15. Referenz: Alle Message-Type Strings (Canonical List)
Inbound (Bridge → Core)
handshake
player.join
player.quit
player.chat
player.report
player.device
player.inventory
players.sync
vault.groups
heartbeat
link.request
punishment.request
punishment.revoke
chatlog.request
command.ack
console.line
Outbound (Core → Bridge)
handshake.ok
handshake.error
ban.sync
ban.created
ban.revoked
command.kick
command.teleport
command.setrank
command.message
command.broadcast
command.execute
server.power
console.subscribe
console.unsubscribe
link.code
messages.sync
templates.sync