From cd00c4c04b846a822b3ea229f1d126d963b5e785 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 12 Dec 2020 12:37:43 +0100 Subject: [PATCH] Move PNG loading in SkinDL to fetch thread (fixes #3398) Sorry for the trouble, seems to work. --- src/engine/client/http.cpp | 4 +-- src/engine/client/http.h | 5 ++-- src/game/client/components/skins.cpp | 44 +++++++++++++++++++++++++--- src/game/client/components/skins.h | 16 +++++++++- 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/engine/client/http.cpp b/src/engine/client/http.cpp index 9333636d2..388a9430c 100644 --- a/src/engine/client/http.cpp +++ b/src/engine/client/http.cpp @@ -250,8 +250,8 @@ size_t CGet::OnData(char *pData, size_t DataSize) CGetFile::CGetFile(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType, CTimeout Timeout, bool LogProgress) : CRequest(pUrl, Timeout, LogProgress), m_pStorage(pStorage), - m_StorageType(StorageType), - m_File(0) + m_File(0), + m_StorageType(StorageType) { str_copy(m_aDest, pDest, sizeof(m_aDest)); diff --git a/src/engine/client/http.h b/src/engine/client/http.h index 79ab1f7bb..a29514499 100644 --- a/src/engine/client/http.h +++ b/src/engine/client/http.h @@ -101,12 +101,13 @@ class CGetFile : public CRequest IStorage *m_pStorage; - char m_aDest[MAX_PATH_LENGTH]; char m_aDestFull[MAX_PATH_LENGTH]; - int m_StorageType; IOHANDLE m_File; protected: + char m_aDest[MAX_PATH_LENGTH]; + int m_StorageType; + virtual int OnCompletion(int State); public: diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index 15bc9e07d..d5272adc2 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -30,6 +30,22 @@ static bool IsVanillaSkin(const char *pName) return false; } +int CSkins::CGetPngFile::OnCompletion(int State) +{ + State = CGetFile::OnCompletion(State); + + if(State != HTTP_ERROR && State != HTTP_ABORTED && !m_pSkins->LoadSkinPNG(m_Info, m_aDest, m_aDest, m_StorageType)) + { + State = HTTP_ERROR; + } + return State; +} + +CSkins::CGetPngFile::CGetPngFile(CSkins *pSkins, IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType, CTimeout Timeout, bool LogProgress) : + CGetFile(pStorage, pUrl, pDest, StorageType, Timeout, LogProgress), m_pSkins(pSkins) +{ +} + int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) { CSkins *pSelf = (CSkins *)pUser; @@ -92,12 +108,32 @@ static void CheckMetrics(CSkin::SSkinMetricVariable &Metrics, uint8_t *pImg, int int CSkins::LoadSkin(const char *pName, const char *pPath, int DirType) { - char aBuf[512]; CImageInfo Info; - if(!Graphics()->LoadPNG(&Info, pPath, DirType) || !Graphics()->CheckImageDivisibility(pPath, Info, g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridy, true)) + if(!LoadSkinPNG(Info, pName, pPath, DirType)) + return 0; + return LoadSkin(pName, Info); +} + +bool CSkins::LoadSkinPNG(CImageInfo &Info, const char *pName, const char *pPath, int DirType) +{ + char aBuf[512]; + if(!Graphics()->LoadPNG(&Info, pPath, DirType)) { str_format(aBuf, sizeof(aBuf), "failed to load skin from %s", pName); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf); + return false; + } + return true; +} + +int CSkins::LoadSkin(const char *pName, CImageInfo &Info) +{ + char aBuf[512]; + + if(!Graphics()->CheckImageDivisibility(pName, Info, g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridy, true)) + { + str_format(aBuf, sizeof(aBuf), "skin failed image divisibility: %s", pName); + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf); return 0; } @@ -366,7 +402,7 @@ int CSkins::FindImpl(const char *pName) char aPath[MAX_PATH_LENGTH]; str_format(aPath, sizeof(aPath), "downloadedskins/%s.png", d.front().m_aName); Storage()->RenameFile(d.front().m_aPath, aPath, IStorage::TYPE_SAVE); - LoadSkin(d.front().m_aName, aPath, IStorage::TYPE_SAVE); + LoadSkin(d.front().m_aName, d.front().m_pTask->m_Info); d.front().m_pTask = nullptr; } if(d.front().m_pTask && (d.front().m_pTask->State() == HTTP_ERROR || d.front().m_pTask->State() == HTTP_ABORTED)) @@ -382,7 +418,7 @@ int CSkins::FindImpl(const char *pName) char aUrl[256]; str_format(aUrl, sizeof(aUrl), "%s%s.png", g_Config.m_ClSkinDownloadUrl, pName); str_format(Skin.m_aPath, sizeof(Skin.m_aPath), "downloadedskins/%s.%d.tmp", pName, pid()); - Skin.m_pTask = std::make_shared(Storage(), aUrl, Skin.m_aPath, IStorage::TYPE_SAVE, CTimeout{0, 0, 0}, false); + Skin.m_pTask = std::make_shared(this, Storage(), aUrl, Skin.m_aPath, IStorage::TYPE_SAVE, CTimeout{0, 0, 0}, false); m_pClient->Engine()->AddJob(Skin.m_pTask); m_aDownloadSkins.add(Skin); return -1; diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index 4b6c35aff..8ec94f750 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -12,9 +12,21 @@ class CSkins : public CComponent { public: + class CGetPngFile : public CGetFile + { + CSkins *m_pSkins; + + protected: + virtual int OnCompletion(int State); + + public: + CGetPngFile(CSkins *pSkins, IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType = -2, CTimeout Timeout = CTimeout{4000, 500, 5}, bool LogProgress = true); + CImageInfo m_Info; + }; + struct CDownloadSkin { - std::shared_ptr m_pTask; + std::shared_ptr m_pTask; char m_aPath[MAX_PATH_LENGTH]; char m_aName[24]; @@ -35,7 +47,9 @@ private: sorted_array m_aDownloadSkins; char m_EventSkinPrefix[24]; + bool LoadSkinPNG(CImageInfo &Info, const char *pName, const char *pPath, int DirType); int LoadSkin(const char *pName, const char *pPath, int DirType); + int LoadSkin(const char *pName, CImageInfo &Info); int FindImpl(const char *pName); static int SkinScan(const char *pName, int IsDir, int DirType, void *pUser); };