Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add overrides for name and color from rating lookup #3316

Merged
merged 3 commits into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions doc/AutoratingServer.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,24 @@ The server must return a response code 200 and some data json format. Otherwise
* `elo` (string): the text to display under the player's name.
* `autohoster` (boolean): if the player is a dedicated hoster. It will have an hoster icon instead of a medal and no stars.
* `details` (string): notes to display in the player's tooltip.
* `name` (string): provides an alternative name of the player in lobby (optional) (ignored if empty).
* `nameTextColorOverride` (array of three integers): overrides alt name color in lobby (rgb 0-255) ([255,255,255] will result in default coloring) (optional).
* `eloTextColorOverride` (array of three integers): overrides elo text color in lobby (rgb 0-255) (optional).

### Response sample

```
{
"dummy": false,
"star": [3,2,1],
"medal": 2,
"level": 4,
"elo": "ELO: 1283",
"autohoster": false,
"details": "Played 264 games, win rate: 53%"
"dummy": false,
"star": [3,2,1],
"medal": 2,
"level": 4,
"elo": "ELO: 1283",
"autohoster": false,
"details": "Played 264 games, win rate: 53%",
"name": "Flex seal",
"nameTextColorOverride": [51,255,51],
"eloTextColorOverride": [255,255,255]
}
```

Expand Down
125 changes: 108 additions & 17 deletions src/multiint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ struct DisplayPlayerCache {
std::string fullMainText; // the “full” main text (used for storing the full player name when displaying a player)
WzText wzMainText; // the main text

std::string fullAltNameText;
WzText wzAltNameText;

WzText wzSubText; // the sub text (used for players)
WzText wzEloText; // the elo text (used for players)
};
Expand Down Expand Up @@ -4313,33 +4316,62 @@ class WzPlayerRow : public WIDGET
playerInfoTooltip += _("Player ID: ");
playerInfoTooltip += hash.empty()? _("(none)") : hash;
}
if (stats.autorating.valid && !stats.autorating.details.empty()
&& stats.autoratingFrom == RATING_SOURCE_LOCAL) // do not display host-provided details (for now)
std::string autoratingTooltipText;
if (stats.autorating.valid)
{
if (!playerInfoTooltip.empty())
if (!stats.autorating.altName.empty())
{
playerInfoTooltip += "\n\n";
if (!autoratingTooltipText.empty())
{
autoratingTooltipText += "\n";
}
std::string altnameStr = stats.autorating.altName;
if (altnameStr.size() > 128)
{
altnameStr = altnameStr.substr(0, 128);
}
size_t maxLinePos = nthOccurrenceOfChar(altnameStr, '\n', 1);
if (maxLinePos != std::string::npos)
{
altnameStr = altnameStr.substr(0, maxLinePos);
}
autoratingTooltipText += std::string(_("Alt Name:")) + " " + altnameStr;
}
std::string detailsstr = stats.autorating.details;
if (detailsstr.size() > 512)
if (!stats.autorating.details.empty()
&& stats.autoratingFrom == RATING_SOURCE_LOCAL) // do not display host-provided details (for now)
{
detailsstr = detailsstr.substr(0, 512);
if (!autoratingTooltipText.empty())
{
autoratingTooltipText += "\n";
}
std::string detailsstr = stats.autorating.details;
if (detailsstr.size() > 512)
{
detailsstr = detailsstr.substr(0, 512);
}
size_t maxLinePos = nthOccurrenceOfChar(detailsstr, '\n', 10);
if (maxLinePos != std::string::npos)
{
detailsstr = detailsstr.substr(0, maxLinePos);
}
autoratingTooltipText += std::string(_("Player rating:")) + "\n" + detailsstr;
}
size_t maxLinePos = nthOccurrenceOfChar(detailsstr, '\n', 10);
if (maxLinePos != std::string::npos)
}
if (!autoratingTooltipText.empty())
{
if (!playerInfoTooltip.empty())
{
detailsstr = detailsstr.substr(0, maxLinePos);
playerInfoTooltip += "\n\n";
}
playerInfoTooltip += std::string(_("Player rating:")) + "\n";
if (stats.autoratingFrom == RATING_SOURCE_HOST)
{
playerInfoTooltip += std::string("(") + _("Host provided") + ")";
playerInfoTooltip += std::string("[") + _("Host provided") + "]\n";
}
else
{
playerInfoTooltip += std::string("(") + astringf(_("From: %s"), getAutoratingUrl().c_str()) + ")";
playerInfoTooltip += std::string("[") + astringf(_("From: %s"), getAutoratingUrl().c_str()) + "]\n";
}
playerInfoTooltip += "\n" + detailsstr;
playerInfoTooltip += autoratingTooltipText;
}
}
playerInfo->setTip(playerInfoTooltip);
Expand Down Expand Up @@ -7657,6 +7689,28 @@ static bool isKnownPlayer(std::map<std::string, EcKey::Key> const &knownPlayers,
return i != knownPlayers.end() && key.toBytes(EcKey::Public) == i->second;
}

static void displayAltNameBox(int x, int y, WIDGET *psWidget, DisplayPlayerCache& cache, const PLAYERSTATS::Autorating& ar, bool isHighlight)
{
int altNameBoxWidth = cache.wzAltNameText.width() + 4;
int altNameBoxHeight = cache.wzAltNameText.lineSize() + 2;
int altNameBoxX0 = (x + psWidget->width()) - altNameBoxWidth;
PIELIGHT altNameBoxColor = WZCOL_MENU_BORDER;
altNameBoxColor.byte.a = static_cast<uint8_t>(static_cast<float>(altNameBoxColor.byte.a) * (isHighlight ? 0.3f : 0.75f));
pie_UniTransBoxFill(altNameBoxX0, y, altNameBoxX0 + altNameBoxWidth, y + altNameBoxHeight, altNameBoxColor);

int altNameTextY0 = y + (altNameBoxHeight - cache.wzAltNameText.lineSize()) / 2 - cache.wzAltNameText.aboveBase();
PIELIGHT altNameTextColor = WZCOL_TEXT_MEDIUM;
if (ar.altNameTextColorOverride[0] != 255 || ar.altNameTextColorOverride[1] != 255 || ar.altNameTextColorOverride[2] != 255)
{
altNameTextColor = pal_Colour(ar.altNameTextColorOverride[0], ar.altNameTextColorOverride[1], ar.altNameTextColorOverride[2]);
}
if (isHighlight)
{
altNameTextColor.byte.a = static_cast<uint8_t>(static_cast<float>(altNameTextColor.byte.a) * 0.3f);
}
cache.wzAltNameText.render(altNameBoxX0 + 2, altNameTextY0, altNameTextColor);
}

// ////////////////////////////////////////////////////////////////////////////
void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
{
Expand All @@ -7667,6 +7721,7 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
int const x = xOffset + psWidget->x();
int const y = yOffset + psWidget->y();
unsigned const j = psWidget->UserData;
bool isHighlight = (psWidget->getState() & WBUT_HIGHLIGHT) != 0;

const int nameX = 32;

Expand All @@ -7684,6 +7739,9 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
}
else if (ingame.localOptionsReceived && NetPlay.players[j].allocated) // only draw if real player!
{
const PLAYERSTATS& stat = getMultiStats(j);
auto ar = stat.autorating;

std::string name = NetPlay.players[j].name;

std::map<std::string, EcKey::Key> serverPlayers; // TODO Fill this with players known to the server (needs implementing on the server, too). Currently useless.
Expand Down Expand Up @@ -7743,8 +7801,6 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
subText += buf;
}

const PLAYERSTATS& stat = getMultiStats(j);
auto ar = stat.autorating;
if (!ar.valid)
{
ar.dummy = stat.played < 5;
Expand All @@ -7765,6 +7821,30 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
ar.elo.clear();
}

if (cache.fullAltNameText != ar.altName)
{
std::string altName = ar.altName;
int maxAltNameWidth = static_cast<int>(static_cast<float>(psWidget->width() - nameX) * 0.65f);
iV_fonts fontID = font_small;
cache.wzAltNameText.setText(WzString::fromUtf8(altName), fontID);
cache.fullAltNameText = altName;
if (cache.wzAltNameText.width() > maxAltNameWidth)
{
while (!altName.empty() && ((int)iV_GetTextWidth(altName.c_str(), cache.wzAltNameText.getFontID()) + iV_GetEllipsisWidth(cache.wzAltNameText.getFontID())) > maxAltNameWidth)
{
altName.resize(altName.size() - 1); // Clip alt name.
}
altName += "\u2026";
cache.wzAltNameText.setText(WzString::fromUtf8(altName), fontID);
}
}

if (!ar.altName.empty() && isHighlight)
{
// display first, behind everything
displayAltNameBox(x, y, psWidget, cache, ar, isHighlight);
}

int H = 5;
cache.wzMainText.render(x + nameX, y + 22 - H*!subText.isEmpty() - H*(ar.valid && !ar.elo.empty()), colour);
if (!subText.isEmpty())
Expand Down Expand Up @@ -7810,8 +7890,19 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)

if (!ar.elo.empty())
{
PIELIGHT eloColour = WZCOL_TEXT_BRIGHT;
if (ar.eloTextColorOverride[0] != 255 || ar.eloTextColorOverride[1] != 255 || ar.eloTextColorOverride[2] != 255)
{
eloColour = pal_Colour(ar.eloTextColorOverride[0], ar.eloTextColorOverride[1], ar.eloTextColorOverride[2]);
}
cache.wzEloText.setText(WzString::fromUtf8(ar.elo), font_small);
cache.wzEloText.render(x + nameX, y + 28 + H*!subText.isEmpty(), WZCOL_TEXT_BRIGHT);
cache.wzEloText.render(x + nameX, y + 28 + H*!subText.isEmpty(), eloColour);
}

if (!ar.altName.empty() && !isHighlight)
{
// display last, over top of everything
displayAltNameBox(x, y, psWidget, cache, ar, isHighlight);
}
}
else // AI
Expand Down
21 changes: 20 additions & 1 deletion src/multistat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ static void NETauto(PLAYERSTATS::Autorating &ar)
NETauto(ar.elo);
NETauto(ar.autohoster);
NETauto(ar.details);
NETauto(ar.altName);
NETauto(ar.altNameTextColorOverride);
NETauto(ar.eloTextColorOverride);
}
}

Expand All @@ -86,6 +89,22 @@ PLAYERSTATS::Autorating::Autorating(nlohmann::json const &json)
elo = json["elo"].get<std::string>();
autohoster = json["autohoster"].get<bool>();
details = json["details"].get<std::string>();
if (json.contains("name"))
{
altName = json["name"].get<std::string>();
}
if (json.contains("nameTextColorOverride"))
{
altNameTextColorOverride[0] = json["nameTextColorOverride"][0].get<uint8_t>();
altNameTextColorOverride[1] = json["nameTextColorOverride"][1].get<uint8_t>();
altNameTextColorOverride[2] = json["nameTextColorOverride"][2].get<uint8_t>();
}
if (json.contains("eloTextColorOverride"))
{
eloTextColorOverride[0] = json["eloTextColorOverride"][0].get<uint8_t>();
eloTextColorOverride[1] = json["eloTextColorOverride"][1].get<uint8_t>();
eloTextColorOverride[2] = json["eloTextColorOverride"][2].get<uint8_t>();
}
valid = true;
} catch (const std::exception &e) {
debug(LOG_WARNING, "Error parsing rating JSON: %s", e.what());
Expand Down Expand Up @@ -165,7 +184,7 @@ void lookupRatingAsync(uint32_t playerIndex)
debug(LOG_WARNING, "Failure fetching \"%s\".", urlCopy.c_str());
});
};
req.maxDownloadSizeLimit = 4096;
req.maxDownloadSizeLimit = 4096*4;
urlRequestData(req);
}

Expand Down
3 changes: 3 additions & 0 deletions src/multistat.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,11 @@ struct PLAYERSTATS
uint8_t star[3] = {0, 0, 0};
uint8_t medal = 0;
uint8_t level = 0;
uint8_t altNameTextColorOverride[3] = {255, 255, 255}; // rgb
uint8_t eloTextColorOverride[3] = {255, 255, 255}; // rgb
std::string elo;
std::string details;
std::string altName;
};
Autorating autorating;
RATING_SOURCE autoratingFrom = RATING_SOURCE_HOST;
Expand Down
Loading