Optimize moddownload
This commit is contained in:
parent
9298e5688f
commit
af21b8a6d9
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
||||
Subproject commit 74638a253ea76baa0aed78491b92d157326295a6
|
||||
Subproject commit 14e74f6a21f2726d25e0e679c59d569f6bc8fe8e
|
@ -11,11 +11,11 @@ namespace Components
|
||||
{
|
||||
if (Download::CLDownload.Running) return;
|
||||
|
||||
Download::CLDownload.Mutex.lock();
|
||||
Download::CLDownload.Progress = "Downloading mod";
|
||||
Download::CLDownload.Mutex.unlock();
|
||||
Localization::SetTemp("MPUI_EST_TIME_LEFT", Utils::String::FormatTimeSpan(0));
|
||||
Localization::SetTemp("MPUI_PROGRESS_DL", "(0/0) %");
|
||||
Localization::SetTemp("MPUI_TRANS_RATE", "0.0 MB/s");
|
||||
|
||||
Command::Execute("openmenu popup_reconnectingtoparty", true);
|
||||
Command::Execute("openmenu mod_download_popmenu", true);
|
||||
|
||||
Download::CLDownload.Running = true;
|
||||
Download::CLDownload.Mod = mod;
|
||||
@ -35,6 +35,8 @@ namespace Components
|
||||
|
||||
if (!error.empty() || !listData.is_array()) return false;
|
||||
|
||||
download->TotalBytes = 0;
|
||||
|
||||
for (auto& file : listData.array_items())
|
||||
{
|
||||
if (!file.is_object()) return false;
|
||||
@ -53,6 +55,7 @@ namespace Components
|
||||
if (!fileEntry.Name.empty())
|
||||
{
|
||||
download->Files.push_back(fileEntry);
|
||||
download->TotalBytes += fileEntry.Size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,12 +78,32 @@ namespace Components
|
||||
|
||||
if (ev == MG_EV_RECV)
|
||||
{
|
||||
fDownload->receivedBytes += static_cast<size_t>(*reinterpret_cast<int*>(ev_data));
|
||||
size_t bytes = static_cast<size_t>(*reinterpret_cast<int*>(ev_data));
|
||||
fDownload->receivedBytes += bytes;
|
||||
fDownload->download->DownBytes += bytes;
|
||||
fDownload->download->TimeStampBytes += bytes;
|
||||
|
||||
double progress = (100.0 / fDownload->file.Size) * fDownload->receivedBytes;
|
||||
fDownload->download->Mutex.lock();
|
||||
fDownload->download->Progress = fmt::sprintf("Downloading file (%d/%d) %s %d%%", fDownload->index + 1, fDownload->download->Files.size(), fDownload->file.Name.data(), static_cast<unsigned int>(progress));
|
||||
fDownload->download->Mutex.unlock();
|
||||
double progress = (100.0 / fDownload->download->TotalBytes) * fDownload->download->DownBytes;
|
||||
Localization::SetTemp("MPUI_PROGRESS_DL", fmt::sprintf("(%d/%d) %d%%", fDownload->index + 1, fDownload->download->Files.size(), static_cast<unsigned int>(progress)));
|
||||
|
||||
int delta = Game::Sys_Milliseconds() - fDownload->download->LastTimeStamp;
|
||||
if (delta > 300)
|
||||
{
|
||||
bool doFormat = fDownload->download->LastTimeStamp != 0;
|
||||
fDownload->download->LastTimeStamp = Game::Sys_Milliseconds();
|
||||
|
||||
size_t dataLeft = fDownload->download->TotalBytes - fDownload->download->DownBytes;
|
||||
double timeLeftD = ((1.0 * dataLeft) / fDownload->download->TimeStampBytes) * delta;
|
||||
int timeLeft = static_cast<int>(timeLeftD);
|
||||
|
||||
if (doFormat)
|
||||
{
|
||||
Localization::SetTemp("MPUI_EST_TIME_LEFT", Utils::String::FormatTimeSpan(timeLeft));
|
||||
Localization::SetTemp("MPUI_TRANS_RATE", Utils::String::FormatBandwidth(fDownload->download->TimeStampBytes, delta));
|
||||
}
|
||||
|
||||
fDownload->download->TimeStampBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ev == MG_EV_HTTP_REPLY)
|
||||
@ -98,10 +121,6 @@ namespace Components
|
||||
|
||||
auto file = download->Files[index];
|
||||
|
||||
download->Mutex.lock();
|
||||
download->Progress = fmt::sprintf("Downloading file (%d/%d) %s 0%%", index + 1, download->Files.size(), file.Name.data());
|
||||
download->Mutex.unlock();
|
||||
|
||||
std::string path = download->Mod + "/" + file.Name;
|
||||
if (Utils::IO::FileExists(path))
|
||||
{
|
||||
@ -109,6 +128,7 @@ namespace Components
|
||||
|
||||
if (data.size() == file.Size && Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(data), "") == file.Hash)
|
||||
{
|
||||
download->TotalBytes += file.Size;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -122,6 +142,8 @@ namespace Components
|
||||
fDownload.downloading = true;
|
||||
fDownload.receivedBytes = 0;
|
||||
|
||||
Utils::String::Replace(url, " ", "%20");
|
||||
|
||||
download->Valid = true;
|
||||
mg_mgr_init(&download->Mgr, &fDownload);
|
||||
mg_connect_http(&download->Mgr, Download::DownloadHandler, url.data(), NULL, NULL);
|
||||
@ -154,6 +176,8 @@ namespace Components
|
||||
|
||||
if (list.empty())
|
||||
{
|
||||
if (download->TerminateThread) return;
|
||||
|
||||
download->Thread.detach();
|
||||
download->Clear();
|
||||
|
||||
@ -169,6 +193,8 @@ namespace Components
|
||||
|
||||
if (!Download::ParseModList(download, list))
|
||||
{
|
||||
if (download->TerminateThread) return;
|
||||
|
||||
download->Thread.detach();
|
||||
download->Clear();
|
||||
|
||||
@ -182,21 +208,27 @@ namespace Components
|
||||
|
||||
if (download->TerminateThread) return;
|
||||
|
||||
static std::string mod = download->Mod;
|
||||
|
||||
for (unsigned int i = 0; i < download->Files.size(); ++i)
|
||||
{
|
||||
if (download->TerminateThread) return;
|
||||
|
||||
if (!Download::DownloadFile(download, i))
|
||||
{
|
||||
Dvar::Var("partyend_reason").Set(fmt::sprintf("Failed to download file: %s!", download->Files[i].Name.data()));
|
||||
if (download->TerminateThread) return;
|
||||
|
||||
mod = fmt::sprintf("Failed to download file: %s!", download->Files[i].Name.data());
|
||||
download->Thread.detach();
|
||||
download->Clear();
|
||||
|
||||
QuickPatch::Once([] ()
|
||||
{
|
||||
Dvar::Var("partyend_reason").Set(mod);
|
||||
mod.clear();
|
||||
|
||||
Localization::ClearTemp();
|
||||
Command::Execute("closemenu popup_reconnectingtoparty");
|
||||
Command::Execute("closemenu mod_download_popmenu");
|
||||
Command::Execute("openmenu menu_xboxlive_partyended");
|
||||
});
|
||||
|
||||
@ -206,8 +238,6 @@ namespace Components
|
||||
|
||||
if (download->TerminateThread) return;
|
||||
|
||||
static std::string mod = download->Mod;
|
||||
|
||||
download->Thread.detach();
|
||||
download->Clear();
|
||||
|
||||
@ -221,7 +251,7 @@ namespace Components
|
||||
mod.clear();
|
||||
|
||||
Localization::ClearTemp();
|
||||
Command::Execute("closemenu popup_reconnectingtoparty", true);
|
||||
Command::Execute("closemenu mod_download_popmenu", true);
|
||||
|
||||
if (Dvar::Var("cl_modVidRestart").Get<bool>())
|
||||
{
|
||||
@ -346,6 +376,8 @@ namespace Components
|
||||
Utils::String::Replace(url, "\\", "/");
|
||||
url = url.substr(6);
|
||||
|
||||
Utils::String::Replace(url, "%20", " ");
|
||||
|
||||
if (url.find_first_of("/") != std::string::npos || (!Utils::String::EndsWith(url, ".iwd") && url != "mod.ff") || strstr(url.data(), "_svr_") != NULL)
|
||||
{
|
||||
Download::Forbid(nc);
|
||||
@ -542,14 +574,9 @@ namespace Components
|
||||
}
|
||||
else
|
||||
{
|
||||
QuickPatch::OnFrame([]
|
||||
UIScript::Add("mod_download_cancel", [] ()
|
||||
{
|
||||
if (Download::CLDownload.Running)
|
||||
{
|
||||
Download::CLDownload.Mutex.lock();
|
||||
Localization::SetTemp("MENU_RECONNECTING_TO_PARTY", Download::CLDownload.Progress);
|
||||
Download::CLDownload.Mutex.unlock();
|
||||
}
|
||||
Download::CLDownload.Clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace Components
|
||||
class ClientDownload
|
||||
{
|
||||
public:
|
||||
ClientDownload() : Valid(false), Running(false), TerminateThread(false) {}
|
||||
ClientDownload() : Valid(false), Running(false), TerminateThread(false), TotalBytes(0), DownBytes(0), LastTimeStamp(0), TimeStampBytes(0) {}
|
||||
~ClientDownload() { this->Clear(); }
|
||||
|
||||
bool Running;
|
||||
@ -25,10 +25,13 @@ namespace Components
|
||||
mg_mgr Mgr;
|
||||
Network::Address Target;
|
||||
std::string Mod;
|
||||
std::mutex Mutex;
|
||||
std::thread Thread;
|
||||
std::string Progress;
|
||||
|
||||
size_t TotalBytes;
|
||||
size_t DownBytes;
|
||||
|
||||
int LastTimeStamp;
|
||||
size_t TimeStampBytes;
|
||||
|
||||
class File
|
||||
{
|
||||
@ -58,10 +61,6 @@ namespace Components
|
||||
this->Valid = false;
|
||||
mg_mgr_free(&(this->Mgr));
|
||||
}
|
||||
|
||||
this->Mutex.lock();
|
||||
this->Progress.clear();
|
||||
this->Mutex.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
@ -71,10 +70,13 @@ namespace Components
|
||||
ClientDownload* download;
|
||||
ClientDownload::File file;
|
||||
|
||||
int timestamp;
|
||||
bool downloading;
|
||||
unsigned int index;
|
||||
std::string buffer;
|
||||
size_t receivedBytes;
|
||||
|
||||
|
||||
};
|
||||
|
||||
static mg_mgr Mgr;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::mutex Localization::LocalizeMutex;
|
||||
Dvar::Var Localization::UseLocalization;
|
||||
Utils::Memory::Allocator Localization::MemAllocator;
|
||||
std::map<std::string, Game::LocalizedEntry*> Localization::LocalizeMap;
|
||||
@ -9,6 +10,8 @@ namespace Components
|
||||
|
||||
void Localization::Set(std::string key, std::string value)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Localization::LocalizeMutex);
|
||||
|
||||
if (Localization::LocalizeMap.find(key) != Localization::LocalizeMap.end())
|
||||
{
|
||||
Game::LocalizedEntry* entry = Localization::LocalizeMap[key];
|
||||
@ -46,6 +49,7 @@ namespace Components
|
||||
if (!Localization::UseLocalization.Get<bool>()) return key;
|
||||
|
||||
Game::LocalizedEntry* entry = nullptr;
|
||||
std::lock_guard<std::mutex> _(Localization::LocalizeMutex);
|
||||
|
||||
if (Localization::TempLocalizeMap.find(key) != Localization::TempLocalizeMap.end())
|
||||
{
|
||||
@ -56,7 +60,12 @@ namespace Components
|
||||
entry = Localization::LocalizeMap[key];
|
||||
}
|
||||
|
||||
if (!entry || !entry->value) entry = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_LOCALIZE, key).localize;
|
||||
if (!entry || !entry->value)
|
||||
{
|
||||
Localization::LocalizeMutex.unlock();
|
||||
entry = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_LOCALIZE, key).localize;
|
||||
Localization::LocalizeMutex.lock();
|
||||
}
|
||||
|
||||
if (entry && entry->value)
|
||||
{
|
||||
@ -68,6 +77,8 @@ namespace Components
|
||||
|
||||
void Localization::SetTemp(std::string key, std::string value)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Localization::LocalizeMutex);
|
||||
|
||||
if (Localization::TempLocalizeMap.find(key) != Localization::TempLocalizeMap.end())
|
||||
{
|
||||
Game::LocalizedEntry* entry = Localization::TempLocalizeMap[key];
|
||||
@ -100,6 +111,8 @@ namespace Components
|
||||
|
||||
void Localization::ClearTemp()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(Localization::LocalizeMutex);
|
||||
|
||||
for (auto i = Localization::TempLocalizeMap.begin(); i != Localization::TempLocalizeMap.end(); ++i)
|
||||
{
|
||||
if (i->second)
|
||||
@ -131,6 +144,7 @@ namespace Components
|
||||
AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_LOCALIZE, [] (Game::XAssetType, std::string filename)
|
||||
{
|
||||
Game::XAssetHeader header = { 0 };
|
||||
std::lock_guard<std::mutex> _(Localization::LocalizeMutex);
|
||||
|
||||
if (Localization::TempLocalizeMap.find(filename) != Localization::TempLocalizeMap.end())
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ namespace Components
|
||||
static void ClearTemp();
|
||||
|
||||
private:
|
||||
static std::mutex LocalizeMutex;
|
||||
static Utils::Memory::Allocator MemAllocator;
|
||||
static std::map<std::string, Game::LocalizedEntry*> LocalizeMap;
|
||||
static std::map<std::string, Game::LocalizedEntry*> TempLocalizeMap;
|
||||
|
@ -674,6 +674,7 @@ namespace Components
|
||||
Menus::Add("ui_mp/stats_reset.menu");
|
||||
Menus::Add("ui_mp/stats_unlock.menu");
|
||||
Menus::Add("ui_mp/security_increase_popmenu.menu");
|
||||
Menus::Add("ui_mp/mod_download_popmenu.menu");
|
||||
}
|
||||
|
||||
Menus::~Menus()
|
||||
|
@ -119,6 +119,28 @@ namespace Utils
|
||||
return fmt::sprintf("%02d:%02d:%02d", hoursTotal, minutes, seconds);
|
||||
}
|
||||
|
||||
std::string FormatBandwidth(size_t bytes, int milliseconds)
|
||||
{
|
||||
static char* sizes[] =
|
||||
{
|
||||
"B",
|
||||
"KB",
|
||||
"MB",
|
||||
"GB",
|
||||
"TB"
|
||||
};
|
||||
|
||||
double bytesPerSecond = (1000.0 / milliseconds) * bytes;
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; bytesPerSecond > 1000 && i < ARRAY_SIZE(sizes); ++i) // 1024 or 1000?
|
||||
{
|
||||
bytesPerSecond /= 1000;
|
||||
}
|
||||
|
||||
return fmt::sprintf("%.2f %s/s", static_cast<float>(bytesPerSecond), sizes[i]);
|
||||
}
|
||||
|
||||
// Encodes a given string in Base64
|
||||
std::string EncodeBase64(const char* input, const unsigned long inputSize)
|
||||
{
|
||||
|
@ -35,6 +35,7 @@ namespace Utils
|
||||
std::string &Trim(std::string &s);
|
||||
|
||||
std::string FormatTimeSpan(int milliseconds);
|
||||
std::string FormatBandwidth(size_t bytes, int milliseconds);
|
||||
|
||||
std::string DumpHex(std::string data, std::string separator = " ");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user