ddnet/src/game/client/skin.h
Robert Müller 6fc3470a8d Check for valid favorite skin name, add CSkin::IsValidName
Favorite skin names were previously not escaped as intended when saving, as the variable `aNameEscaped` was unused so the original skin name was saved instead of the escaped one. Escaping is not really necessary, as skins should not contain `\` and `"` anyway and it was only possible to add such favorites through the console or config files. Instead of escaping the favorite skin names when saving, now favorite skin names are validated when they are added so no escaping is necessary. Skins names are considered valid when they have a length of 1-23 bytes and don't contain the characters `/`, `\` and `"`.
2023-12-22 22:13:33 +01:00

165 lines
3.2 KiB
C++

#ifndef GAME_CLIENT_SKIN_H
#define GAME_CLIENT_SKIN_H
#include <base/color.h>
#include <base/system.h>
#include <base/vmath.h>
#include <engine/graphics.h>
#include <limits>
// do this better and nicer
struct CSkin
{
private:
char m_aName[24];
public:
struct SSkinTextures
{
IGraphics::CTextureHandle m_Body;
IGraphics::CTextureHandle m_BodyOutline;
IGraphics::CTextureHandle m_Feet;
IGraphics::CTextureHandle m_FeetOutline;
IGraphics::CTextureHandle m_Hands;
IGraphics::CTextureHandle m_HandsOutline;
IGraphics::CTextureHandle m_aEyes[6];
void Reset()
{
m_Body = IGraphics::CTextureHandle();
m_BodyOutline = IGraphics::CTextureHandle();
m_Feet = IGraphics::CTextureHandle();
m_FeetOutline = IGraphics::CTextureHandle();
m_Hands = IGraphics::CTextureHandle();
m_HandsOutline = IGraphics::CTextureHandle();
for(auto &Eye : m_aEyes)
Eye = IGraphics::CTextureHandle();
}
};
SSkinTextures m_OriginalSkin;
SSkinTextures m_ColorableSkin;
ColorRGBA m_BloodColor;
template<bool IsSizeType>
struct SSkinMetricVariableInt
{
int m_Value;
operator int() const { return m_Value; }
SSkinMetricVariableInt &operator=(int NewVal)
{
if(IsSizeType)
m_Value = maximum(m_Value, NewVal);
else
m_Value = minimum(m_Value, NewVal);
return *this;
}
SSkinMetricVariableInt()
{
Reset();
}
void Reset()
{
if(IsSizeType)
m_Value = std::numeric_limits<int>::lowest();
else
m_Value = std::numeric_limits<int>::max();
}
};
struct SSkinMetricVariable
{
SSkinMetricVariableInt<true> m_Width;
SSkinMetricVariableInt<true> m_Height;
SSkinMetricVariableInt<false> m_OffsetX;
SSkinMetricVariableInt<false> m_OffsetY;
// these can be used to normalize the metrics
SSkinMetricVariableInt<true> m_MaxWidth;
SSkinMetricVariableInt<true> m_MaxHeight;
float WidthNormalized() const
{
return (float)m_Width / (float)m_MaxWidth;
}
float HeightNormalized() const
{
return (float)m_Height / (float)m_MaxHeight;
}
float OffsetXNormalized() const
{
return (float)m_OffsetX / (float)m_MaxWidth;
}
float OffsetYNormalized() const
{
return (float)m_OffsetY / (float)m_MaxHeight;
}
void Reset()
{
m_Width.Reset();
m_Height.Reset();
m_OffsetX.Reset();
m_OffsetY.Reset();
m_MaxWidth.Reset();
m_MaxHeight.Reset();
}
};
struct SSkinMetrics
{
SSkinMetricVariable m_Body;
SSkinMetricVariable m_Feet;
void Reset()
{
m_Body.Reset();
m_Feet.Reset();
}
SSkinMetrics()
{
Reset();
}
};
SSkinMetrics m_Metrics;
bool operator<(const CSkin &Other) const { return str_comp(m_aName, Other.m_aName) < 0; }
bool operator==(const CSkin &Other) const { return !str_comp(m_aName, Other.m_aName); }
CSkin(const char *pName)
{
str_copy(m_aName, pName);
}
CSkin(CSkin &&) = default;
CSkin &operator=(CSkin &&) = default;
const char *GetName() const { return m_aName; }
static bool IsValidName(const char *pName)
{
if(pName[0] == '\0' || str_length(pName) >= (int)sizeof(CSkin("").m_aName))
{
return false;
}
for(int i = 0; pName[i] != '\0'; ++i)
{
if(pName[i] == '"' || pName[i] == '/' || pName[i] == '\\')
{
return false;
}
}
return true;
}
};
#endif