Die Metin2-Inventarerweiterung ist eines der am häufigsten gewünschten Server-Features: Sobald die Standardtasche voll ist, werden Farmen, Drops und die Lagerverwaltung mühsam. Der Schlüssel ist zu verstehen, dass das Inventar nicht an einer einzigen Stelle definiert wird — die Slotanzahl lebt sowohl in der Server-Source als auch auf der Client-Seite, und diese beiden Werte müssen exakt übereinstimmen. In dieser Anleitung zeige ich Schritt für Schritt und sicher, wie du Taschenslots und zusätzliche Seiten hinzufügst.
Wie das Inventar funktioniert: Slots, Seiten und die gemeinsame Konstante
In Metin2 ist das Inventar ein Array von Slots. Im klassischen Layout besteht jede Seite aus 45 Slots (9 Spalten × 5 Zeilen), und die Gesamtzahl der Slots muss ein Vielfaches der Seitengröße sein. Der Standardwert ist in den meisten Sources 90, also zwei Seiten. Willst du vier Seiten, setzt du das Total auf 180.
- Gesamtslots = Anzahl der Seiten × Seitengröße (45).
- Slotpositionen (
pos) beginnen bei 0; die Equipment-Slots liegen in einem separaten Block oberhalb dieses Bereichs. - Teilen Server und Client nicht dieselbe Konstante, verschieben sich die Itempositionen, was Itemverlust und Abstürze verursacht.
Serverseite: length.h und INVENTORY_MAX_NUM
Das Herz der Erweiterung ist die Konstante in der Datei common/length.h. Dort findest du die Gesamtzahl der Slots und die Seitengröße:
// common/length.h
enum EInventoryConstants
{
INVENTORY_MAX_NUM = 90, // 2 Seiten × 45 -> setze 180 für 4 Seiten
INVENTORY_PAGE_SIZE = 45,
};
Ändere INVENTORY_MAX_NUM und stelle sicher, dass der Wert ein sauberes Vielfaches von 45 bleibt. Kompiliere danach das game-Binary neu:
cd Server/game/src
make clean && make -j$(nproc)
Diese Konstante wird an vielen Stellen verwendet, die Items validieren: IsValidItemPosition in char_item.cpp und die Funktionen zum Verschieben/Ablegen von Items, dazu die Paketprüfungen in input_main.cpp. Da sie alle auf INVENTORY_MAX_NUM aufbauen, reicht es, die eine Quelle zu ändern — du musst keine zusätzlichen if-Anweisungen aufspüren.
Datenbank: die item-Tabelle und Positionsprüfungen
Items werden nicht beim Spieler gespeichert, sondern in einer separaten item-Tabelle; jede Zeile verweist mit den Spalten window (Inventar/Equipment) und pos auf ihren Platz. Für eine Erweiterung musst du das Schema nicht ändern, da pos bereits ein Integer-Feld ist, das die neuen, größeren Werte aufnehmen kann. Prüfe trotzdem zwei Dinge:
- Erst sichern: dumpe die Tabellen
playerunditem. Eine Positionsabweichung kann Itemverlust verursachen. - Mit einem Testaccount testen: lege Items auf die neuen Seiten und relogge den Charakter; prüfe, ob die neuen
pos-Werte (z. B. 90–179) korrekt in dieitem-Tabelle geschrieben werden.
Es ist außerdem ratsam, den DB-Cache neu zu kompilieren, da db und game dieselben Protokoll-Header teilen.
Client-Source: die Konstante synchron halten
Die kritischste Regel: Der Client muss dieselbe Gesamtzahl der Slots kennen. In der Client-Source werden Inventar-Arrays und Paketstrukturen durch ihre eigene Konstante im UserInterface-Projekt dimensioniert. Bist du auf dem Server von 90 auf 180 gegangen, aktualisiere denselben Wert auf dem Client und kompiliere UserInterface neu:
// Client UserInterface (z. B. Packet.h / Locale_inc.h)
#define INVENTORY_MAX_NUM 180
#define INVENTORY_PAGE_SIZE 45
Hast du die Client-Source nicht, reicht es nicht, die UI nur mit Python zu vergrößern: das Binary ist weiterhin mit der alten Slotanzahl kompiliert, sodass Items auf den zusätzlichen Seiten unsichtbar bleiben oder die Verbindung getrennt wird. Deshalb ist die Client-Source für eine Inventarerweiterung unverzichtbar.
Client-Python: zusätzliche Seiten mit uiInventory.py
Sobald das Binary in der richtigen Größe kompiliert ist, ist die UI an der Reihe. In root/uiInventory.py wird das Inventarfenster mit seinen Seitenbuttons und dem Slot-Raster gezeichnet. Das ist zu tun:
- Erhöhe die Seitenanzahl: aktualisiere die Schleife und die
GetInventoryPageCount-Logik, damit das Fenster die zusätzlichen Seitenbuttons/Tabs anzeigt. - Berechne die Slotpositionen anhand der Konstante
player.INVENTORY_PAGE_SIZE; bereinige fest codierte Zahlen wie 90. - Ist das Fenster zu klein, passe Breite/Höhe in der
.pyan oder bearbeite die zugehörigen.sub-Bilder.
Die Python-Seite zeichnet nur; das echte Slotlimit setzt das Binary. Die Seitenanzahl, die du in Python anzeigst, muss daher zum kompilierten INVENTORY_MAX_NUM passen — zeigst du mehr, laufen die Klicks ins Leere.
Testen und häufige Fehler
Teste nach der Änderung immer von Anfang bis Ende:
- Server/Client-Abweichung: der häufigste Fehler. Sind beide Seiten mit einem unterschiedlichen
INVENTORY_MAX_NUMkompiliert, verschieben sich die Itempositionen. Aktualisiere und kompiliere beide gleichzeitig. - Ein Wert, der kein Vielfaches von 45 ist: die Seite bleibt halb gezeichnet und die letzten Zeilen sind nicht anklickbar. Halte das Total immer durch 45 teilbar.
- Exploit-Prüfung: separate Fenster wie Pet oder Dragon Soul nutzen ebenfalls Positionen; prüfe beim Vergrößern der Inventarkonstante, dass ihre pos-Bereiche nicht kollidieren.
- Ein stabiles Backup: bewahre vor dem Live-Gang einen DB-Dump und die alten Binaries auf, damit dein Rollback-Weg offen bleibt.
Häufige Fragen
Kann ich das Inventar ohne Client-Source erweitern?
Nein. Mit Python vergrößerst du nur das Visuelle, aber das Binary ist mit der alten Slotanzahl kompiliert; die zusätzlichen Slots funktionieren nicht und die Abweichung zum Server verursacht Abstürze. Du brauchst sowohl die Server- als auch die Client-Source.
Verlieren bestehende Spieler ihre Items?
Wenn du die Gesamtzahl der Slots erhöhst, bleiben die bestehenden Positionen (0–89) erhalten und es werden nur neue leere Slots hinzugefügt; kein Itemverlust. Eine falsche Konstante oder eine Verkleinerung kann jedoch Verlust verursachen, also dumpe zuerst die DB.
Warum muss es ein Vielfaches von 45 sein?
Eine Inventarseite hat 9×5 = 45 Slots. Ist das Total kein Vielfaches davon, wird die letzte Seite unvollständig gezeichnet und die Slot-Indizes zwischen UI und Binary stimmen nicht überein.
Willst du eine saubere, exploit-freie Inventarerweiterung in deinem Server-Projekt? Ich kann bei der Systementwicklung an Metin2-Source und -Client helfen — lass uns über dein Projekt sprechen: nimm Kontakt mit mir auf.