Minecraft-Bridge – Architektur & Komponenten

Die Bridge verbindet jeden Minecraft-Server (Paper-Backend) und -Proxy (Velocity) mit dem Nexus Core über eine dauerhafte WebSocket-Verbindung. Sie ist das Bindeglied zwischen Spiel und Panel: Spieler-Events fließen zum Core, Aktionen (Kick, Ban, Rang, Konsole) fließen zurück. Das vollständige Nachrichtenprotokoll steht in der Bridge-Protokoll-Referenz; diese Seite erklärt Aufbau und Komponenten.

Module

Maven-ModulInhalt
bridge-minecraft/bridge-commonPlattformneutrale Client-Lib: NexusBridgeClient, BanCache, Outbox, BridgeMessage, BridgeConfig, BridgeListener
bridge-minecraft/bridge-paperPaper-Plugin (role=BACKEND): Events, Strafbefehle, Vault-Rangsync, Telemetrie, Konsole
bridge-minecraft/bridge-velocityVelocity-Plugin (role=PROXY): netzwerkweites Pre-Login-Ban-Gate

Entwurfsprinzipien

  • Offline-fest: Ein Core-Ausfall darf den Spielserver nie blockieren. Join-/Mute-Checks laufen aus einem lokalen Cache in < 1 ms; ausgehende Events werden gepuffert.
  • Asynchron: Sämtliche Netzwerk-I/O läuft auf einem eigenen Virtual-Thread-Executor, nie auf dem Game-Main-Thread. Callbacks an das Plugin werden bei Bedarf auf den Main-Thread zurückgeplant.
  • Selbstheilend: Verbindungsabbrüche lösen automatischen Reconnect mit exponentiellem Backoff aus; nach dem Wiederverbinden wird die Outbox geleert und der Ban-Cache neu synchronisiert.

NexusBridgeClient (bridge-common)

Der WebSocket-Client mit vollständigem Lebenszyklus. Kernzustände als atomare Felder: running (gestartet), ready (verbunden + Handshake ok), backoffSeconds (1 → 2 → … → max 30 s).

  • Verbindung: start() verbindet und plant den Heartbeat (alle 10 s); connect() baut den WebSocket (Connect-Timeout 10 s) und sendet sofort den handshake.
  • Senden: send(type, data) schickt sofort, wenn ready; sonst landet die Nachricht in der Outbox.
  • Empfangen: eingehende Frames werden (auch fragmentiert) zusammengesetzt, als BridgeMessage geparst und je type an den BridgeListener dispatcht — inkl. command.*-Aktionen mit automatischem command.ack.
  • Panel-Texte: message(key, fallback, placeholders) liefert vom Core synchronisierte, spielersichtbare Texte (z. B. Kick-/Ban-Screen) mit {platzhalter}-Ersetzung; offline gilt der Fallback.

BanCache

Zweistufige ConcurrentHashMap: gameId → (Straftyp → CachedBan). Ein CachedBan trägt type, reason, expiresAt, banCode, caseNumber, ip.

  • activeBan(gameId) (BAN vor TEMPBAN), activeMute(gameId), activeBanByIp(ip) (Ban-Evasion-Schutz) — alles lokale O(1)/O(aktiveBans)-Lookups ohne Netz.
  • Befüllt durch ban.sync (Voll-Snapshot nach Handshake) und ban.created/ban.revoked; abgelaufene Einträge werden beim Zugriff lazy entfernt.

Outbox

FIFO-Queue (ConcurrentLinkedDeque, Kapazität 10 000) für Events während einer Offline-Phase. Bei Überlauf fallen die ältesten Nachrichten weg; nach handshake.ok wird per drain() in Einfügereihenfolge geflusht. Keine Persistenz (Dedup passiert Core-seitig über die Message-id).

BridgeListener

Callback-Vertrag, den jede Plattform implementiert (alle Methoden default): onConnected/onDisconnected, onServerKeyIssued, onKick, onPunishment, onMessage, onBroadcast, onTeleport, onSetRank, onExecute, onConsoleSubscribe/Unsubscribe, onLinkCode, onPower. Aufrufe erfolgen im Client-Executor — plattformseitig ggf. auf den Main-Thread planen.

Paper-Plugin (Backend)

NexusBridgePlugin lädt config.yml, initialisiert BanModule + VaultBridge, erzeugt den Client und registriert Events, den nexus:hwid-Plugin-Channel sowie periodische Tasks (Metrik-Snapshot 5 s, Telemetrie 60 s, Vault-Report 60 s).

  • Capabilities: KICK, BROADCAST, CHAT_READ, EXECUTE.
  • PlayerEvents: AsyncPlayerPreLogin (Ban-Gate aus dem Cache, per UUID und IP, mit Ban-Screen) · PlayerJoinplayer.join (inkl. Rang & Skin) · PlayerQuitplayer.quit · AsyncPlayerChatplayer.chat + lokale Mute-Durchsetzung.
  • BanModule: /ban /tempban /mute /tempmute /kick /warn /unban /unmute /punishpunishment.request/revoke; Dauer-Parser (7d, 12h, 30m, 90s).
  • VaultBridge: liest Vault-Gruppen + Farben (Hex/Legacy) und meldet sie als vault.groups; setzt Ränge (onSetRank) async (LuckPerms-sicher).
  • Telemetry + HwidChannel: Geräte-Fingerprint (player.device) und Inventar-Snapshots (player.inventory, Sektionen MAIN/ARMOR/OFFHAND/ENDERCHEST).
  • Konsole: console.subscribe hängt einen Log4j2-Appender an und streamt console.line (Rekursionsschutz); command.execute läuft mit 10 s Timeout auf dem Main-Thread.

Velocity-Plugin (Proxy)

NexusVelocityPlugin (role=PROXY) ist bewusst schlank: es erzwingt Bans beim Pre-Login netzwerkweit aus dem BanCache (< 1 ms), meldet player.join/player.quit und nach jedem Reconnect ein players.sync-Roster. Capabilities: KICK, BROADCAST, SUBSERVER_AWARE. Keine Vault-, Konsolen- oder TPS-Metriken (das liefern die Backends), Heartbeat nur mit playersOnline/maxPlayers.

Authentifizierung

Beim ersten Handshake legitimiert sich die Bridge mit einem Einmal-Token (im ACP unter Server → Server verbinden erzeugt). Der Core gibt einen persistenten Server-Key (nxk_<base64>) zurück, der lokal gespeichert und fortan statt des Tokens verwendet wird. Details + Hash-Verfahren: Bridge-Protokoll §6. Praktische Einrichtung: Minecraft-Server verbinden.

Resilienz auf einen Blick

SituationVerhalten
Core offline, Spieler-LoginBan-Check aus lokalem Cache, normaler Join wenn kein Ban
Core offline, Event entstehtOutbox-Pufferung (max 10 000), Flush nach Reconnect
VerbindungsabbruchReconnect mit Backoff 1→30 s, danach Ban-Cache-Resync
Lizenz-/Netzproblemnie ein Hard-Shutdown des Spielservers