Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Немного принципа:
- При подключении к серверу(при отправки connectionless), сервер присылает
- список файлов с хешами, которые нужны для сервера. Этот список записывается
- в глобальную переменную g_localfiles.
- Ставится хук функции UI_DisplayDownloadInfo, она вызывается только тогда,
- когда клиент начинает загрузку iwd файлов с сервера. В этом хуке ставится
- флаг g_donwload, что приводит к началу загрузки файлов в потоке downloadThread,
- и прерывается загрузка через стоковый протокол игры.
- После завершения загрузки, клиент переподключается к серверу и UI_DisplayDownloadInfo
- уже не вызывается, что и збс...
- Поток загрузки. Он делает основную работу:
- - Проверяет все файлы по md5-хешу, предварительно получив md5-хеши от сервера
- - Скачивает файлы и заменяет их
- */
- void downloadThread()
- {
- md5wrapper md5;
- for (;;)
- {
- if (!g_download)
- {
- Sleep(1000);
- continue;
- }
- #ifdef DEBUG
- printf("Host: %s\n", (char*)g_localfiles.host.c_str());
- printf("Start download:\n");
- #endif
- g_dl_from = (char*)g_localfiles.host.c_str();
- char *fs_game = GetCvar("fs_game")->string;
- for (int i = 0; i < g_localfiles.files.size(); i++)
- {
- if (!g_download)
- break;
- #ifdef DEBUG
- printf(" - %s", (char*)g_localfiles.files[i].c_str());
- #endif
- char file_path[MAX_PATH];
- sprintf(file_path, "%s/%s", fs_game, (char*)g_localfiles.files[i].c_str());
- g_dl_currentfile = (char*)g_localfiles.files[i].c_str();
- // check hash file
- if (file_exists(file_path))
- {
- std::string hash_path = md5.getHashFromFile(file_path);
- if (hash_path == "-1")
- {
- #ifdef DEBUG
- printf(" (failed to read)\n");
- #endif
- game.Printf(0, "^3[COD2X] ^1failed to read file %s\n", file_path);
- continue;
- }
- // get hash file from host
- char req[256], url[256];
- sprintf(req, "fs_game=%s&file=%s", fs_game, (char*)g_localfiles.files[i].c_str());
- sprintf(url, "%s/hash.php", (char*)g_localfiles.host.c_str());
- char *hash_url = sendGetRequest(url, req);
- if (strcmp(hash_url, "-1") == 0)
- {
- #ifdef DEBUG
- printf(" (%s)\n", getCurlError());
- #endif
- game.Printf(0, "^3[COD2X] ^1failed to get hash file %s\n", getCurlError());
- continue;
- }
- printf(" (%s)", hash_url);
- if (strcmp((char*)hash_path.c_str(), hash_url) != 0)
- {
- g_localfiles.state[i] = 1; // need download
- }
- #ifdef DEBUG
- else printf(" not needed...\n");
- #endif
- }
- else g_localfiles.state[i] = 1;
- if (g_localfiles.state[i] != 1)
- continue;
- // download if needed
- char file_url[MAX_PATH] = "\0";
- sprintf(file_url, "%s/%s/%s", (char*)g_localfiles.host.c_str(), fs_game, (char*)g_localfiles.files[i].c_str());
- g_dl_size = getFileSizeByUrl(file_url);
- if (g_dl_size < 0)
- {
- #ifdef DEBUG
- printf(" (%s)\n", getCurlError());
- #endif
- game.Printf(0, "^3[COD2X] ^1failed to get size file %s\n", getCurlError());
- continue;
- }
- // сохранить в .tmp файле
- char tmpfile[MAX_PATH];
- sprintf(tmpfile, "%s.tmp", file_path);
- g_dl_bytes = 0;
- g_dl_state = 1;
- // загрузка файла
- bool res = startDownload(file_url, tmpfile);
- if (!res)
- {
- if (g_dl_size < 0)
- {
- #ifdef DEBUG
- printf(" (%s)\n", getCurlError());
- #endif
- game.Printf(0, "^3[COD2X] ^1failed to download file %s\n", getCurlError());
- continue;
- }
- }
- #ifdef DEBUG
- printf("...OK\n");
- #endif
- // переименовать
- if (rename(tmpfile, file_path))
- copy(tmpfile, file_path);
- remove(tmpfile);
- }
- g_dl_state = 0;
- g_download = false;
- // переподключиться к серверу
- game.Cmd_ExecuteText(1, "disconnect; wait 1; reconnect");
- }
- }
- /*
- Хуки функций игры
- */
- bool MyDisplayDownload()
- {
- traceLastFunc("MyDisplayDownload()");
- if (g_dl_init || getClientState() > CA_LOADING)
- return false;
- if (g_download)
- return true;
- if (g_localfiles.files.empty() || g_localfiles.host == "")
- return false;
- // остановка загрузки файлов в игре
- game.CL_AddReliableCommand("stopdl");
- // флаг загрузки, в потоке загрузки он дает понять, что
- // нужно что-то скачать
- g_download = true;
- // если при переподключении к серверу, игрок все равно что-то скачивает
- // то этот флаг делает так, чтобы загрузка была через игру, а не CURL
- g_dl_init = 1;
- return true;
- }
- // 1.0 1.3
- // 0x00532830 : 0x00538AF0
- oUI_DisplayDownloadInfo pUI_DisplayDownloadInfo;
- void __declspec(naked) hUI_DisplayDownloadInfo(void)
- {
- __asm pushad;
- if (!MyDisplayDownload())
- {
- __asm popad;
- __asm jmp[pUI_DisplayDownloadInfo];
- }
- else
- {
- __asm popad;
- __asm ret;
- }
- }
RAW Paste Data