Move PNG loading in SkinDL to fetch thread (fixes #3398)

Sorry for the trouble, seems to work.
This commit is contained in:
def 2020-12-12 12:37:43 +01:00
parent 5c7bc040e8
commit cd00c4c04b
4 changed files with 60 additions and 9 deletions

View file

@ -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));

View file

@ -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:

View file

@ -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<CGetFile>(Storage(), aUrl, Skin.m_aPath, IStorage::TYPE_SAVE, CTimeout{0, 0, 0}, false);
Skin.m_pTask = std::make_shared<CGetPngFile>(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;

View file

@ -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<CGetFile> m_pTask;
std::shared_ptr<CSkins::CGetPngFile> m_pTask;
char m_aPath[MAX_PATH_LENGTH];
char m_aName[24];
@ -35,7 +47,9 @@ private:
sorted_array<CDownloadSkin> 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);
};