Skip to content

Commit

Permalink
Revert "Revert "Fix #1258: Add mixed hex and RGB(A) parsing to XMLCol…
Browse files Browse the repository at this point in the history
…orToInt (#1261)""

This reverts commit 3f39bb5.

Signed-off-by: Patrik Juvonen <patrik@scope.studio>
  • Loading branch information
patrikjuvonen committed Apr 28, 2020
1 parent 80bf1c1 commit febb856
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 26 deletions.
26 changes: 9 additions & 17 deletions Server/mods/deathmatch/logic/CVehicle.cpp
Expand Up @@ -304,28 +304,20 @@ bool CVehicle::ReadSpecialData(const int iLine)
char szTemp[256];
if (GetCustomDataString("color", szTemp, 256, true))
{
uchar ucValues[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char* sz1 = strtok(szTemp, ", ");
if (sz1)
ucValues[0] = atoi(sz1);
std::vector<SColorRGBA> vecColors;
unsigned char ucCount;

int i;
for (i = 1; i < 12; i++)
if (ColorStringToRGB(szTemp, SColorRGBA(0, 0, 0, 0), vecColors, ucCount))
{
char* szn = strtok(NULL, ", ");
if (!szn)
break;
ucValues[i] = atoi(szn);
}

if (i == 3 || i == 6 || i == 9 || i == 12)
{
m_Color.SetRGBColors(SColorRGBA(ucValues[0], ucValues[1], ucValues[2], 0), SColorRGBA(ucValues[3], ucValues[4], ucValues[5], 0),
SColorRGBA(ucValues[6], ucValues[7], ucValues[8], 0), SColorRGBA(ucValues[9], ucValues[10], ucValues[11], 0));
if (ucCount % 3 == 0)
m_Color.SetRGBColors(vecColors[0], vecColors[1], vecColors[2], vecColors[3]);
else
m_Color.SetPaletteColors(vecColors[0].R, vecColors[0].G, vecColors[0].B, vecColors[1].R);
}
else
{
m_Color.SetPaletteColors(ucValues[0], ucValues[1], ucValues[2], ucValues[3]);
CLogger::ErrorPrintf("Bad 'color' value specified in <vehicle> (line %u)\n", iLine);
return false;
}
}

Expand Down
120 changes: 111 additions & 9 deletions Server/mods/deathmatch/logic/Utils.cpp
Expand Up @@ -535,18 +535,120 @@ bool XMLColorToInt(const char* szColor, unsigned long& ulColor)

bool XMLColorToInt(const char* szColor, unsigned char& ucRed, unsigned char& ucGreen, unsigned char& ucBlue, unsigned char& ucAlpha)
{
// Convert it to an integer first
unsigned long ulColor;
if (!XMLColorToInt(szColor, ulColor))
{
// If we're empty, let's just stop right away
if (!szColor || strlen(szColor) == 0)
return false;

std::vector<SColorRGBA> vecColors;
unsigned char ucCount;

if (ColorStringToRGBA(szColor, SColorRGBA(ucRed, ucGreen, ucBlue, ucAlpha), vecColors, ucCount))
{
ucRed = vecColors[0].R;
ucGreen = vecColors[0].G;
ucBlue = vecColors[0].B;
ucAlpha = vecColors[0].A;

return true;
}

return false;
}

bool ColorStringToRGBA(const char* szColor, SColorRGBA defaultColor, std::vector<SColorRGBA>& vecColors, unsigned char& ucCount, bool bIgnoreAlpha)
{
std::stringstream ss(szColor);
SColorRGBA color = defaultColor;
bool bPreviousWasHex = false;
unsigned int uiRGBAIndex = 0;
unsigned long ulColor;
unsigned char ucValue;
unsigned char ucLength = bIgnoreAlpha ? 3 : 4;

while (ss.good())
{
// Ambiguous value before a comma
SString strValue;
getline(ss, strValue, ',');

// Remove spaces
ReplaceOccurrencesInString(strValue, " ", "");

// Is the value looking like a hexadecimal?
if (strValue[0] == '#')
{
// Try converting it to an integer
if (XMLColorToInt(strValue.c_str(), ulColor))
{
// If a previous RGBA wasn't finished, let's finish it now
if (!bPreviousWasHex && uiRGBAIndex != 0)
{
vecColors.push_back(color);
ucCount += ucLength - uiRGBAIndex;
color = defaultColor;
}

color.R = static_cast<unsigned char>(ulColor);
color.G = static_cast<unsigned char>(ulColor >> 8);
color.B = static_cast<unsigned char>(ulColor >> 16);

if (!bIgnoreAlpha)
color.A = static_cast<unsigned char>(ulColor >> 24);

bPreviousWasHex = true;
ucCount += ucLength;
}
else
return false;
}
// It looks like we have an empty value, let's skip the value but treat it as RGB
else if (strValue.empty())
{
if (bPreviousWasHex || uiRGBAIndex % ucLength == 0)
{
bPreviousWasHex = false;
uiRGBAIndex = 0;
}

uiRGBAIndex++;
ucCount++;

if (uiRGBAIndex % ucLength != 0 && ss.good())
continue;
}
// It looks like a plain number so let's treat it as a RGBA value
else if (strValue.find_first_not_of("0123456789") == std::string::npos)
{
ucValue = atoi(strValue.c_str());

if (bPreviousWasHex || uiRGBAIndex % ucLength == 0)
{
color.R = ucValue;
bPreviousWasHex = false;
uiRGBAIndex = 0;
}
else if (uiRGBAIndex % ucLength == 1)
color.G = ucValue;
else if (uiRGBAIndex % ucLength == 2)
color.B = ucValue;
else if (uiRGBAIndex % ucLength == 3)
color.A = ucValue;

uiRGBAIndex++;
ucCount++;

if (uiRGBAIndex % ucLength != 0 && ss.good())
continue;
}
else
return false;

// We have a color, so let's push it
vecColors.push_back(color);
color = defaultColor;
uiRGBAIndex = 0;
}

// Convert it to red, green, blue and alpha
ucRed = static_cast<unsigned char>(ulColor);
ucGreen = static_cast<unsigned char>(ulColor >> 8);
ucBlue = static_cast<unsigned char>(ulColor >> 16);
ucAlpha = static_cast<unsigned char>(ulColor >> 24);
return true;
}

Expand Down
5 changes: 5 additions & 0 deletions Server/mods/deathmatch/logic/Utils.h
Expand Up @@ -57,6 +57,11 @@ bool IsValidOrganizationPath(const char* szPath);
unsigned int HexToInt(const char* szHex);
bool XMLColorToInt(const char* szColor, unsigned long& ulColor);
bool XMLColorToInt(const char* szColor, unsigned char& ucRed, unsigned char& ucGreen, unsigned char& ucBlue, unsigned char& ucAlpha);
bool ColorStringToRGBA(const char* szColor, SColorRGBA defaultColor, std::vector<SColorRGBA>& vecColors, unsigned char& ucCount, bool bIgnoreAlpha = false);
inline bool ColorStringToRGB(const char* szColor, SColorRGBA defaultColor, std::vector<SColorRGBA>& vecColors, unsigned char& ucCount)
{
return ColorStringToRGBA(szColor, defaultColor, vecColors, ucCount, true);
}

inline float WrapAround(float fValue, float fHigh)
{
Expand Down

0 comments on commit febb856

Please sign in to comment.