Wie wir das Spiel automatisiert entpacken

Neben dem Programmieren ist mein Hobby die Entwicklung von Modifikationen für das STALKER-Spiel. Wir arbeiten in einem Team, in dem wie üblich jeder für etwas Eigenes verantwortlich ist. Ich bin nicht nur Entwickler, sondern entwickle auch Software für das Team. Lesen Sie im Folgenden, wie wir das Entpacken von Spielearchiven automatisiert haben, auf welche Probleme wir gestoßen sind und wie sie gelöst wurden.

Spielressourcen sind in Archiven gepackt. Sie können die Anzahl der Archive im aktuellen Build unten auswerten:



Die Entwickler haben alle diese Archive entpackt, und für Tester veröffentlichen wir kumulative Updates, die als einzelnes Archiv verteilt werden.

Darüber hinaus gibt es auch verschiedene Arten von Änderungen aus den 4 unteren Archiven. Manchmal muss man sie alle auspacken. Wir haben verschiedene Tools zum Ein- und Auspacken, ich kenne mindestens 2 Sets - Konsolen- und GUI-Versionen. Jeder von ihnen hat seine eigenen Nachteile:

Konsole:
1. Beim Entpacken von Archiven werden mehr als ~ 1,6 GB gelöscht.

GUI:
1. Auswahl des Startordners, Archivs, Zielverzeichnisses - von Hand.
2. Es kann jeweils nur 1 Archiv entpackt werden.

Da wir Archive und fast 2 GB haben, müssen Sie die GUI verwenden. Als ich es müde war, einhundert Mal dasselbe zu tun, habe ich beschlossen, es zu automatisieren.

Der Entpacker hat diese Schnittstelle:







Dies sind alles Dialogfelder. Ich wurde von dem Feld aufgefordert, in dem der Dateiname angezeigt wird. Wenn es dort von Hand eingegeben oder ausgewählt werden kann, kann dasselbe programmatisch wiederholt werden.

Wir werden mit C ++ WinAPI und SPY ++ aufrüsten und vorerst am ersten Fenster arbeiten. Führen Sie den Entpacker und SPY ++ aus und finden Sie dort den Prozess:



Und ja, um die Suche nach den erforderlichen Feldern auf dem Bildschirm zu vereinfachen , empfehle ich Ihnen, diese mit Informationen zu füllen, z. B. habe ich das Archiv ausgewählt. Nun, wir sehen die Felder hier. Sie können mit dem Schreiben von Code beginnen ...

Schon als ich über die Idee nachdachte, hatte ich die Idee, eine praktische Konfigurationsdatei zu erstellen. Seine Struktur wurde sofort erfunden und nie geändert:

Unpacker.exe - lass es bei der Unpacker-GUI
C: \ STALKER \ sein - lass es bei dem Spiel sein
D: \ Stalker SHоC \ 1 \ - lass es bei dem Ordner liegen, in den du
YES entpacken möchtest - hole die Liste der Archive rekursiv (NO) oder aus der Liste unter
gamedata.db1 - Liste mit den Namen der Archive
/gamedata.db2 - kommentierte Zeile

Ich werde nicht im Detail aufhören wie die config gelesen wird. Ich kann nur sagen, dass wir eine Struktur mit ähnlichen Feldern haben. Um in einem anderen Fenster auf Schaltflächen zu klicken, müssen wir dessen Handle erhalten. Als nächstes müssen wir die Griffe der Steuerelemente bekommen, die wir brauchen. Außerdem, um sie in der genauen Reihenfolge zu erhalten, in der sie verbunden sind (die Art und Weise, wie sie verbunden sind, ist in den Dropdown-Listen der Elemente in SPY ++ sichtbar. Mal sehen:



Wir erhalten die Handles mit dem folgenden Code:

HWND hwnd = FindWindow(NULL, "Select file to unpack...");
HWND hbnd = FindWindowEx(hwnd, NULL, "Button", "&Открыть");
HWND hсnd = FindWindowEx(hwnd, NULL, "ComboBoxEx32", "");
hсnd = FindWindowEx(hсnd, NULL, "ComboBox", NULL);
hсnd = FindWindowEx(hсnd, NULL, "Edit", NULL);
#ifdef _DEBUG 
BOOST_LOG_TRIVIAL(info) << "FindWindow(NULL, 'Select file to unpack...') " << hwnd;
BOOST_LOG_TRIVIAL(info) << "FindWindow(NULL, 'Button', '&Открыть') " << hbnd;
BOOST_LOG_TRIVIAL(info) << "FindWindow(NULL, 'Edit', '') " << hсnd;
#endif

Funktion FindWindow (Ex) - Gibt das Handle mit dem Namen des Objekts zurück. Der zweite Parameter kann den Wert der Objektklasse annehmen, und der erste Parameter kann das Objekt übergeben, in dem gesucht werden soll (wir übergeben beispielsweise das Fensterhandle, um nach der Schaltfläche zu suchen).

Nachdem wir die Daten erhalten haben, müssen wir eine Nachricht an die Steuerung senden. Wir werden es so machen:

if ((hwnd != NULL && hbnd != NULL ) && hсnd != NULL)
 {
  //устанавливаем текст
  SendMessage(hсnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR(path_to_db.c_str())));
  //кликаем
  SendMessage(hbnd, WM_LBUTTONDOWN, 0, 0);
  SendMessage(hbnd, WM_LBUTTONUP, 0, 0);
  #ifdef _DEBUG
  BOOST_LOG_TRIVIAL(info) << "Sended";
  #endif
}

Hier werde ich näher darauf eingehen, da es beim Ausfüllen der ComboBox Schwierigkeiten gab. Anfangs war der Code etwas anders und ich bekam nur:

HWND hсnd = FindWindowEx(hwnd, NULL, "ComboBoxEx32", "");

Und versuchte es zu füllen mit:

SendMessage(hсnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR(path_to_db.c_str())));

Aber nichts hat geklappt. Warum - ich weiß es noch nicht. Ein weiteres Problem war, dass mich das Funktionsprinzip dieses Fensters verwirrte. Der Screenshot oben zeigt, dass bei Auswahl des Archivs nur der Name in die ComboBox aufgenommen wird. Der Pfad erscheint nirgendwo. In der Hoffnung auf ein Wunder habe ich den vollständigen Weg zum dortigen Archiv zurückgelegt und es hat funktioniert. Gibt es Wunder? Ich denke, der Klick auf die Schaltfläche OK ist offensichtlich, und wir werden es nicht berücksichtigen.

Jetzt ist es Zeit, mit dem zweiten Ordnerauswahlfenster zu arbeiten. Ich werde den Code sofort geben und dann kommentieren.

//работа со 2м окном
Sleep(time);
hwnd = FindWindow(NULL, "Обзор папок");
hbnd = FindWindowEx(hwnd, NULL, "Button", "ОК");
hсnd = FindWindowEx(hwnd, NULL, "Edit", NULL);
if ((hwnd != NULL && hbnd != NULL) && hсnd != NULL)
{
//устанавливаем текст
SendMessage(hсnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR(config.path_to_output.c_str())));
//кликаем
SendMessage(hbnd, WM_LBUTTONDOWN, 0, 0);
SendMessage(hbnd, WM_LBUTTONUP, 0, 0);
#ifdef _DEBUG
BOOST_LOG_TRIVIAL(info) << "Sended";
#endif
}

Es gab auch Probleme mit diesem Fenster. Es gibt keine sichtbaren Steuerelemente außer Schaltflächen. Wir öffnen SPY ++ und sehen uns an, was sich in uns befindet:



Ich begann, verschiedene Ordner auszuwählen, und der Name des Verzeichnisses wurde in das Bearbeitungssteuerelement eingegeben, wieder nur der Name (ist das der Ort, an dem der Mausklick-Handler sie in eine Zeile setzt?). Und ich war total verzweifelt, weil ich mir nicht vorstellen konnte, wie ich meinen Weg dorthin verlegen könnte. Der erste Gedanke war, all dies unter dem Debugger auszuführen und die Speicheradresse zu finden, unter der der endgültige Pfad liegt, Ihre DLL in den Prozess einzuspeisen und den Wert im Speicher zu ändern (und wird DEP dies zulassen?).

Diese Idee ist fehlgeschlagen, da ich nicht weiß, wie ich mit dem Debugger arbeiten soll und es noch nie getan habe. Sie müssen mit einem einfacheren lernen. Ich hoffte wieder auf ein Wunder und überwand den vollständigen Pfad zu Edit - und es funktionierte! Freude war keine Kapelle. Dann gab es die routinemäßige Code-Vervollständigung, die Sie hier finden . Wir haben ein praktisches und vielseitiges Werkzeug zum Auspacken. Ich denke, dass meine Lösung des Problems nicht die einzige ist, und ich bin froh, wenn in den Kommentaren etwas Nützliches gesagt wird. Vielen Dank für Ihre Aufmerksamkeit.

Jetzt auch beliebt: