ゲームの開梱を自動化した方法

プログラミングに加えて、私の趣味はSTALKERゲームの変更の開発であり、私たちはチームで働いています。 開発者であることに加えて、チーム用のソフトウェアも開発しています。 カットの下で、ゲームアーカイブの展開を自動化した方法、発生した問題、および解決方法をご覧ください。



ゲームリソースはアーカイブにまとめられています。 以下の現在のビルドにあるアーカイブの数を見積もることができます。







開発者はこれらのアーカイブをすべて解凍し、テスター向けに単一のアーカイブとして配布される累積的な更新をリリースします。



さらに、下位4つのアーカイブからの異なる変更セットもあります。 時々それらすべてを解凍することが必要になります。 パッケージ化と展開にはさまざまなツールがありますが、少なくとも2セット-コンソールバージョンとGUIバージョンを知っています。 それぞれに欠点があります:



コンソール:

1.アーカイブを解凍すると、約1.6 GBがドロップします。



GUI:

1.開始フォルダー、アーカイブ、宛先ディレクトリーの選択-手作業で行います。

2.一度に1つのアーカイブのみを解凍できます。



アーカイブと2GB近い容量があるため、GUIを使用する必要があります。 同じことを100回やるのにうんざりしていたとき、私はそれを自動化することにしました。



アンパッカーには次のインターフェースがあります。















これらはすべてダイアログボックスです。 ファイル名が表示されるフィールドでプロンプトが出されました。 手動で入力したり選択したりできる場合は、同じことをプログラムで繰り返すことができます。



C ++ WinAPIとSPY ++を使用して、最初のウィンドウで作業します。 unpackerとSPY ++を実行し、そこでプロセスを見つけます。







そして、はい、画面で必要なフィールドを検索しやすくするために、たとえば、アーカイブを選択したなど、情報を入力することをお勧めします。 さて、ここにフィールドがあります。 コードを書き始めることができます...



アイデアを初めて考えたときでも、便利な構成ファイルを作成するというアイデアがありました。 その構造はすぐに発明され、変更されませんでした:



Unpacker.exe-アンパッカーGUIに任せる

C:\ STALKER \-ゲーム前でも

D:\ StalkerSH®C \ 1 \-展開したいフォルダに移動します

YES-アーカイブのリストを再帰的に取得(NO)または以下のリストから取得

gamedata.db1-アーカイブ名のリスト

/gamedata.db2-コメント行



構成の読み取り方法については説明しません。 同様のフィールドを持つ構造があるとしか言えません。 別のウィンドウのボタンをクリックするには、そのハンドルを取得する必要があります。 次に、必要なコントロールのハンドルを取得する必要があります。 さらに、それらを接続された順序で正確に取得します(接続方法は、SPY ++の要素のドロップダウンリストに表示されます。見てみましょう。







次のコードを含むhandlsを受け取ります。



HWND hwnd = FindWindow(NULL, "Select file to unpack..."); HWND hbnd = FindWindowEx(hwnd, NULL, "Button", "&"); HWND hnd = FindWindowEx(hwnd, NULL, "ComboBoxEx32", ""); hnd = FindWindowEx(hnd, NULL, "ComboBox", NULL); hnd = FindWindowEx(hnd, 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', '') " << hnd; #endif
      
      





関数FindWindow(Ex)-オブジェクトの名前でハンドルを返します。 2番目のパラメーターはオブジェクトクラスの値を取ることができ、最初のパラメーターは検索するオブジェクトを渡すことができます(たとえば、ウィンドウハンドルを渡してボタンを検索します)。



データを受信した後、コントロールにメッセージを送信する必要があります。 このようにします:



 if ((hwnd != NULL && hbnd != NULL ) && hnd != NULL) { //  SendMessage(hnd, 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 }
      
      





ComboBoxに記入するのが難しいため、ここで詳しく説明します。 最初は、コードが少し異なっていて、私は次のことしか得られませんでした



 HWND hnd = FindWindowEx(hwnd, NULL, "ComboBoxEx32", "");
      
      





そして、それを使用してそれを埋めようとしました:



 SendMessage(hnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR(path_to_db.c_str())));
      
      





しかし、何もうまくいきませんでした。 なぜ-私はこれまで知りません。 もう1つの問題は、このウィンドウの動作原理に混乱していたことです。 上のスクリーンショットは、アーカイブを選択すると、その名前のみがComboBoxに追加されることを示しています。 パスはどこにも表示されません。 奇跡を期待して、私はそこでアーカイブへの完全なパスを渡しました、そして、それは働きました。 奇跡はありますか? [Ok]ボタンのクリックは明らかであると思いますが、考慮しません。



次に、2番目のフォルダー選択ウィンドウを操作します。 コードをすぐに提供してコメントします。



 //  2  Sleep(time); hwnd = FindWindow(NULL, " "); hbnd = FindWindowEx(hwnd, NULL, "Button", ""); hnd = FindWindowEx(hwnd, NULL, "Edit", NULL); if ((hwnd != NULL && hbnd != NULL) && hnd != NULL) { //  SendMessage(hnd, 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 }
      
      





このウィンドウにも問題がありました。 ボタンを除いて、目に見えるコントロールはありません。 SPY ++を開き、内部の内容を確認します。







別のフォルダーを選択し始め、ディレクトリの名前をエディットコントロールに入力しました。名前だけを入力しました(それらを行に入れるマウスクリックハンドラーはありますか?)。 そして、どうやってそこに自分の道を移すことができるか想像できなかったので、私は完全に必死でした。 最初の考えは、これをすべてデバッガーの下で実行し、最終パスが存在するメモリアドレスを見つけ、dllをプロセスに挿入し、メモリ内の値を変更することでした(そして、DEPはこれを可能にしますか?)。



デバッガの操作方法がわからず、一度も実行したことがないため、このアイデアは失敗しました。より簡単なものから学習を開始する必要があります。 再び奇跡を期待して、私は編集へのフルパスを渡しました-そしてそれはうまくいきました! 喜びはチャペルではありませんでした。 それから、 ここで見つけることができるルーチンコード補完がありました 。 開梱に便利で汎用性の高いツールを入手しました。 私は問題に対する私の解決策が唯一のものではないと思います、そして、コメントで役に立つ何かが言われるならば、私はうれしいです。 ご清聴ありがとうございました。



All Articles