📦

SmartInventoryBridge

Cross-Server Inventory Sync für Hytale. Spieler-Inventare, Equipment, Stats und Effekte nahtlos über dein gesamtes Server-Netzwerk synchronisieren.

📦 v1.0.0 ☕ Java 25+ 🗄️ MySQL / PostgreSQL / Redis 🔒 Dupe-Protection

✨ Features

🔄

Auto-Sync bei Join

Spieler wird eingefroren, Inventar geladen, alles angewendet — vollautomatisch.

💾

Auto-Save bei Disconnect

Inventar wird gespeichert, Server-Inventar geleert — keine Duplikationen.

🎒

Komplette Daten

Inventar, Rüstung, XP, Health, Hunger, GameMode, Potion-Effekte.

🗄️

Multi-Storage

MySQL, PostgreSQL oder Redis — du hast die Wahl.

🛡️

Dupe-Protection

Active-Flag verhindert gleichzeitige Logins auf mehreren Servern.

Async & Fast

GZIP-Kompression, Connection-Pooling, async DB-Operationen.

🧊

Freeze-System

Spieler kann während Sync nichts machen — keine Items droppen oder aufheben.

🔁

Auto-Save Interval

Periodisches Speichern aller Online-Spieler als Backup.

🚀 Installation

  1. Plugin JAR in den plugins/ Ordner des Hytale-Servers kopieren
  2. Server starten — config.yml wird automatisch erstellt
  3. Server stoppen und plugins/SmartInventoryBridge/config.yml anpassen
  4. Datenbank einrichten (MySQL/PostgreSQL) oder Redis konfigurieren
  5. Server neu starten

Datenbank Setup

Die Tabelle wird automatisch erstellt. Für manuelle Einrichtung:

CREATE DATABASE hytale_inventory;

CREATE USER 'hytale_inv'@'%' IDENTIFIED BY 'sicheres_passwort';

GRANT ALL PRIVILEGES ON hytale_inventory.* TO 'hytale_inv'@'%';
💡 Tipp Für ein Server-Netzwerk: Alle Server müssen auf die gleiche Datenbank zeigen, damit die Synchronisierung funktioniert.

⚙️ Konfiguration

Datenbank

database:
  # "mysql", "postgresql", oder "redis"
  type: "mysql"

  host: "127.0.0.1"
  port: 3306
  database: "hytale_inventory"
  username: "hytale_inv"
  password: "sicheres_passwort"

  # Nützlich für Shared-Databases
  tablePrefix: "inv_"

  # Connection Pool
  maxPoolSize: 10
  minIdleConnections: 2

Redis (Alternative)

redis:
  host: "localhost"
  port: 6379
  password: ""
  database: 0
  keyPrefix: "invbridge:"
  maxPoolSize: 10
  timeoutMs: 3000

Sync Settings

sync:
  prefix: "[InventoryBridge]"

  # Max. Wartezeit wenn Spieler noch auf anderem Server aktiv (ms)
  maxWaitTime: 10000

  # Auto-Save alle X Sekunden (0 = deaktiviert)
  autoSaveIntervalSeconds: 60

  # Nachrichten (anpassbar)
  syncMessage: "Inventar wird synchronisiert, bitte warten..."
  completeMessage: "Inventar erfolgreich synchronisiert!"
  waitMessage: "Bitte warte, bis dein Inventar synchronisiert ist!"

🏗️ Architektur

SmartInventoryBridgePlugin (Main) ├── DatabaseConfig ← Verbindungsparameter ├── DataSource ← DB-Operationen (save/load/active) │ └── MySQLConnection ← Connection-Pool ├── PlayerEventHandler ← Join/Disconnect/Interact-Events ├── InventorySerializer ← GZIP Compress/Decompress └── PlayerUtil ← Freeze, Message, Kick

Projekt-Struktur

src/main/java/de/smartcodelabs/inventorybridge/
├── SmartInventoryBridgePlugin.java    // Main Plugin
├── config/
│   └── DatabaseConfig.java            // Config-Klasse
├── database/
│   ├── DatabaseConnection.java        // Interface
│   ├── MySQLDatabaseConnection.java   // MySQL-Impl
│   └── DataSource.java                // DB-Operations
├── event/
│   └── PlayerEventHandler.java        // Event-Logik
├── serializer/
│   └── InventorySerializer.java       // Serialisierung
└── util/
    └── PlayerUtil.java                // Helper-Funktionen

🔄 Workflow

Player Join

1

PlayerJoinEvent wird getriggert

2

Spieler einfrieren — keine Interaktionen möglich

3

Nachricht: "Inventar wird synchronisiert..."

4

Async: Prüfen ob Spieler auf anderem Server aktiv ist (max. 10s warten)

5

Async: Inventar aus Datenbank laden + GZIP dekomprimieren

6

Sync (Main Thread): Inventar auf Spieler anwenden

7

Spieler als Active = TRUE in DB markieren

8

Spieler entsperren — Erfolgsmeldung anzeigen ✅

Player Disconnect

1

PlayerDisconnectEvent wird getriggert

2

Aktuelles Inventar serialisieren + GZIP komprimieren

3

In Datenbank speichern

4

Inventar auf dem Server leeren (Anti-Dupe)

5

Spieler als Active = FALSE markieren

🧵 Threading-Modell

ThreadOperationen
Main ThreadEvent-Handler, Inventory-Manipulation, Player-Freeze, Message-Sending
Async ThreadDatenbank-Operationen (Load/Save), Serialisierung, Active-Flag Warten
⚠️ Wichtig Inventory-Manipulation muss immer auf dem Main Thread passieren. DB-Operationen immer async, um den Server nicht zu blockieren.

🗄️ Datenbank-Schema

SQL (MySQL / PostgreSQL)

SpalteTypBeschreibung
UUIDBINARY(16)Spieler-UUID (Primary Key)
ActiveBOOLEANIst der Spieler gerade online?
DataBLOBGZIP-komprimiertes Inventar
LastUpdateTIMESTAMPLetztes Update

DataSource API

// Inventar speichern
dataSource.saveInventory(uuid, compressedData);

// Inventar laden
byte[] data = dataSource.loadInventory(uuid);

// Active-Flag setzen
dataSource.setActive(uuid, true);

// Prüfen ob auf anderem Server aktiv
boolean active = dataSource.isActive(uuid);

// Active-Flag löschen
dataSource.clearActive(uuid);

Redis Keys

KeyTypBeschreibung
invbridge:{uuid}:dataBINARYGZIP-komprimiertes Inventar
invbridge:{uuid}:activeBOOLEANActive-Flag

🧩 Komponenten

🔌

SmartInventoryBridgePlugin

Main Entry Point — Lifecycle, Config, Event-Registration.

🗄️

DataSource

Datenbank-Layer — Save, Load, Active-Flag Management.

📡

PlayerEventHandler

Join/Disconnect Events, Freeze, Interact-Blocking.

📦

InventorySerializer

GZIP Kompression/Dekompression von Inventar-Daten.

🛠️

PlayerUtil

Helper — UUID, Name, Freeze, Message, Kick.

⚙️

DatabaseConfig

Verbindungsparameter für MySQL/PostgreSQL/Redis.

Synchronisierte Daten

DatenBeschreibung
🎒 Haupt-InventarAlle Slots mit Items, Stacks und Meta
🛡️ Rüstung/EquipmentHelm, Brustplatte, Hose, Schuhe
XP & LevelErfahrungspunkte und Level
❤️ GesundheitHealth Points
🍖 Hunger & SättigungFood Level und Saturation
🎮 GameModeSurvival, Creative, Adventure, etc.
Potion-EffekteAktive Effekte mit Dauer und Stärke

📦 Serialisierung

Inventar-Daten werden als binäres BSON serialisiert und mit GZIP komprimiert (~70% Größenreduktion).

Spieler-Inventar ↓ Serialisierung (Items → BSON/Binary) ↓ GZIP-Kompression (~70% kleiner) ↓ Datenbank (BLOB / Redis Binary) ↓ GZIP-Dekompression ↓ Deserialisierung (Binary → Items) ↓ Spieler-Inventar wiederherstellen

🔒 Sicherheit

🛡️

Active-Flag

Verhindert gleichzeitige Logins auf mehreren Servern.

🧊

Freeze-System

Spieler kann während Sync nichts tun — keine Item-Duplikationen.

🔐

Prepared Statements

SQL-Injection-Schutz durch parametrisierte Queries.

🧵

Thread-Safety

ConcurrentHashMap für Lock-freie Threadsicherheit.

Graceful Shutdown

Alle Inventare werden beim Server-Stop gespeichert.

🚪

Error-Kick

Bei DB-Fehler wird Spieler gekickt — keine Halb-Syncs.

Anti-Duplikation

Wie verhindert das Plugin Item-Duplikation?
  1. Freeze bei Join: Spieler kann keine Items droppen/aufheben während geladen wird
  2. Active-Flag: Nur ein Server kann gleichzeitig das Inventar eines Spielers halten
  3. Clear bei Disconnect: Server-Inventar wird nach Speichern geleert
  4. Wait-Mechanismus: Neuer Server wartet bis alter Server fertig gespeichert hat (max. 10s)

⚡ Performance

FeatureVorteil
GZIP-Kompression~70% weniger DB-Speicher
Async DB-OpsKein Main-Thread-Blocking
Connection-PoolingSchnelle Wiederverwendung von DB-Verbindungen
ConcurrentHashMapLock-frei, Thread-safe
Auto-Save IntervalPeriodisches Backup gegen Datenverlust

📋 Config-Referenz

Database

OptionDefaultBeschreibung
type"mysql"Storage-Typ: mysql, postgresql, redis
host"127.0.0.1"DB-Host
port3306DB-Port (PostgreSQL: 5432)
database"hytale_inventory"Datenbank-Name
username"root"DB-User
password""DB-Passwort
tablePrefix"inv_"Tabellen-Prefix
maxPoolSize10Max. Connection-Pool-Größe
minIdleConnections2Mindest-Idle-Connections

Redis

OptionDefaultBeschreibung
host"localhost"Redis-Host
port6379Redis-Port
password""Redis-Passwort
database0Redis-DB-Index
keyPrefix"invbridge:"Key-Prefix
timeoutMs3000Timeout in ms

Sync

OptionDefaultBeschreibung
prefix"[InventoryBridge]"Chat-Prefix
maxWaitTime10000Max. Wartezeit auf Active-Flag (ms)
autoSaveIntervalSeconds60Auto-Save Intervall (0 = aus)
syncMessage"Inventar wird synchronisiert..."Sync-Nachricht
completeMessage"Inventar erfolgreich synchronisiert!"Erfolgs-Nachricht
waitMessage"Bitte warte..."Interact-Block-Nachricht

🐛 Debug & Logging

debug:
  # Master switch
  enabled: false

  logDatabaseOperations: false  # SQL/Redis Queries
  logSaveLoad: false            # Dirty-Flag, Compression, BSON
  logActiveFlag: false          # Active-Flag Lifecycle
  logFreezeState: false         # Freeze/Unfreeze Events
  logEventFlow: false           # Join/Disconnect/Ready Events

Log-Levels

LevelInhalt
INFOPlayer Join/Disconnect, DB-Verbindung
FINEDetaillierte Ops (Freeze, Save, Load)
WARNINGTimeouts, fehlgeschlagene Joins
SEVEREDB-Fehler, Serialisierungs-Fehler

🧪 Test-Szenarien

1. Erster Join

✅ Erwartung Spieler joint → kein Inventar in DB → leeres Inventar wird gespeichert → Spieler kann spielen.

2. Re-Join (gleicher Server)

✅ Erwartung Spieler sammelt Items → Disconnect → Inventar gespeichert → Re-Join → selbe Items zurück.

3. Server-Wechsel

✅ Erwartung Disconnect von Server A → Inventar gespeichert → Join auf Server B → selbes Inventar geladen.

4. Schneller Wechsel (Edge Case)

⚠️ Edge Case Disconnect von Server A → Server A speichert noch (Active=TRUE) → Join auf Server B → Plugin wartet bis Active=FALSE (max 10s) → dann Inventar laden.

5. Server-Crash

⛔ Crash Recovery Auto-Save Interval rettet Daten. Active-Flag wird beim nächsten Join nach Timeout automatisch zurückgesetzt.

📦 SmartInventoryBridge — Cross-Server Inventory Sync für Hytale

© 2026 SmartCodeLabs · v1.0.0