Skip to content

Commit

Permalink
Various refactoring of 0.7 skin loading
Browse files Browse the repository at this point in the history
- Only log successful log messages when `debug` is enabled, consistent with logging for regular skins.
- Use `IsImageFormatRgba` to check for RGBA image format, so this also shows a warning popup.
- Remove redundant logic for non-RGBA image data.
- Use `CheckImageDivisibility` instead of enforcing exact size of xmas hat and bot decoration images to allow higher resolution images.
- Fix image data not being freed if it has the wrong format or ratio.
- Fix potential integer overflow when calculating skin part blood color (same as for regular skins).
- Extract `LoadXmasHat` and `LoadBotDecoration` functions for readability.
  • Loading branch information
Robyt3 committed Aug 10, 2024
1 parent afd1bd9 commit 38b60b1
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 36 deletions.
2 changes: 1 addition & 1 deletion src/game/client/components/skins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ const CSkin *CSkins::LoadSkin(const char *pName, CImageInfo &Info)

if(g_Config.m_Debug)
{
log_trace("skins", "Loaded skin %s", Skin.GetName());
log_trace("skins", "Loaded skin '%s'", Skin.GetName());
}

auto &&pSkin = std::make_unique<CSkin>(std::move(Skin));
Expand Down
82 changes: 47 additions & 35 deletions src/game/client/components/skins7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,17 @@ int CSkins7::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser
log_error("skins7", "Failed to load skin part '%s'", pName);
return 0;
}
if(Info.m_Format != CImageInfo::FORMAT_RGBA)
if(!pSelf->Graphics()->IsImageFormatRgba(aFilename, Info))
{
log_error("skins7", "Failed to load skin part '%s': must be RGBA format", pName);
Info.Free();
return 0;
}

Part.m_OrgTexture = pSelf->Graphics()->LoadTextureRaw(Info, 0, aFilename);
Part.m_BloodColor = ColorRGBA(1.0f, 1.0f, 1.0f);

int Step = Info.m_Format == CImageInfo::FORMAT_RGBA ? 4 : 3;
const int Step = 4;
unsigned char *pData = (unsigned char *)Info.m_pData;

// dig out blood color
Expand All @@ -78,7 +79,7 @@ int CSkins7::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser
int PartWidth = Info.m_Width / 2;
int PartHeight = Info.m_Height / 2;

int aColors[3] = {0};
int64_t aColors[3] = {0};
for(int y = PartY; y < PartY + PartHeight; y++)
for(int x = PartX; x < PartX + PartWidth; x++)
if(pData[y * Pitch + x * Step + 3] > 128)
Expand All @@ -105,7 +106,11 @@ int CSkins7::SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser
Part.m_Flags |= SKINFLAG_SPECIAL;
if(DirType != IStorage::TYPE_SAVE)
Part.m_Flags |= SKINFLAG_STANDARD;
log_debug("skins7", "load skin part %s", Part.m_aName);

if(pSelf->Config()->m_Debug)
{
log_trace("skins7", "Loaded skin part '%s'", Part.m_aName);
}
pSelf->m_avSkinParts[pSelf->m_ScanningPart].emplace_back(Part);

return 0;
Expand Down Expand Up @@ -206,9 +211,10 @@ int CSkins7::SkinScan(const char *pName, int IsDir, int DirType, void *pUser)
Skin.m_Flags = SpecialSkin ? SKINFLAG_SPECIAL : 0;
if(DirType != IStorage::TYPE_SAVE)
Skin.m_Flags |= SKINFLAG_STANDARD;

if(pSelf->Config()->m_Debug)
{
log_debug("skins7", "load skin %s", Skin.m_aName);
log_trace("skins7", "Loaded skin '%s'", Skin.m_aName);
}
pSelf->m_vSkins.insert(std::lower_bound(pSelf->m_vSkins.begin(), pSelf->m_vSkins.end(), Skin), Skin);

Expand Down Expand Up @@ -322,45 +328,51 @@ void CSkins7::OnInit()
if(m_vSkins.empty())
m_vSkins.emplace_back(m_DummySkin);

LoadXmasHat();
LoadBotDecoration();
GameClient()->m_Menus.RenderLoading(Localize("Loading DDNet Client"), Localize("Loading skin files"), 0);
}

void CSkins7::LoadXmasHat()
{
const char *pFilename = SKINS_DIR "/xmas_hat.png";
CImageInfo Info;
if(!Graphics()->LoadPng(Info, pFilename, IStorage::TYPE_ALL) ||
!Graphics()->IsImageFormatRgba(pFilename, Info) ||
!Graphics()->CheckImageDivisibility(pFilename, Info, 1, 4, false))
{
// add xmas hat
const char *pFileName = SKINS_DIR "/xmas_hat.png";
CImageInfo Info;
if(!Graphics()->LoadPng(Info, pFileName, IStorage::TYPE_ALL) || Info.m_Width != 128 || Info.m_Height != 512)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "failed to load xmas hat '%s'", pFileName);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins7", aBuf);
}
else
log_error("skins7", "Failed to xmas hat '%s'", pFilename);
Info.Free();
}
else
{
if(Config()->m_Debug)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "loaded xmas hat '%s'", pFileName);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins7", aBuf);
m_XmasHatTexture = Graphics()->LoadTextureRawMove(Info, 0, pFileName);
log_trace("skins7", "Loaded xmas hat '%s'", pFilename);
}
m_XmasHatTexture = Graphics()->LoadTextureRawMove(Info, 0, pFilename);
}
GameClient()->m_Menus.RenderLoading(Localize("Loading DDNet Client"), Localize("Loading skin files"), 0);
}

void CSkins7::LoadBotDecoration()
{
const char *pFilename = SKINS_DIR "/bot.png";
CImageInfo Info;
if(!Graphics()->LoadPng(Info, pFilename, IStorage::TYPE_ALL) ||
!Graphics()->IsImageFormatRgba(pFilename, Info) ||
!Graphics()->CheckImageDivisibility(pFilename, Info, 12, 5, false))
{
// add bot decoration
const char *pFileName = SKINS_DIR "/bot.png";
CImageInfo Info;
if(!Graphics()->LoadPng(Info, pFileName, IStorage::TYPE_ALL) || Info.m_Width != 384 || Info.m_Height != 160)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "failed to load bot '%s'", pFileName);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins7", aBuf);
}
else
log_error("skins7", "Failed to load bot '%s'", pFilename);
Info.Free();
}
else
{
if(Config()->m_Debug)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "loaded bot '%s'", pFileName);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "skins7", aBuf);
m_BotTexture = Graphics()->LoadTextureRawMove(Info, 0, pFileName);
log_trace("skins7", "Loaded bot '%s'", pFilename);
}
m_BotTexture = Graphics()->LoadTextureRawMove(Info, 0, pFilename);
}
GameClient()->m_Menus.RenderLoading(Localize("Loading DDNet Client"), Localize("Loading skin files"), 0);
}

void CSkins7::AddSkin(const char *pSkinName, int Dummy)
Expand Down
3 changes: 3 additions & 0 deletions src/game/client/components/skins7.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ class CSkins7 : public CComponent

static int SkinPartScan(const char *pName, int IsDir, int DirType, void *pUser);
static int SkinScan(const char *pName, int IsDir, int DirType, void *pUser);

void LoadXmasHat();
void LoadBotDecoration();
};

#endif

0 comments on commit 38b60b1

Please sign in to comment.