diff --git a/src/cs2kz.cpp b/src/cs2kz.cpp index 718bcb12..3f5e88b5 100644 --- a/src/cs2kz.cpp +++ b/src/cs2kz.cpp @@ -39,6 +39,7 @@ PLUGIN_EXPOSE(KZPlugin, g_KZPlugin); bool KZPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) { + setlocale(LC_ALL, "en_US.utf8"); PLUGIN_SAVEVARS(); if (!utils::Initialize(ismm, error, maxlen)) diff --git a/src/kz/timer/queries/base_request.h b/src/kz/timer/queries/base_request.h index 38253dee..60b70828 100644 --- a/src/kz/timer/queries/base_request.h +++ b/src/kz/timer/queries/base_request.h @@ -116,7 +116,7 @@ struct BaseRequest CUtlString courseName; bool requestingFirstCourse = false; - u64 limit = 20; + u64 limit = 10; u64 offset = 0; u64 targetSteamID64 {}; diff --git a/src/kz/timer/queries/course_top.cpp b/src/kz/timer/queries/course_top.cpp index 4036c2cc..21dc2402 100644 --- a/src/kz/timer/queries/course_top.cpp +++ b/src/kz/timer/queries/course_top.cpp @@ -65,6 +65,11 @@ struct CourseTopRequest : public BaseRequest u64 steamid64; u64 points {}; // 0 for local database + CUtlString GetName() + { + return name; + } + CUtlString GetRunID() { CUtlString fmt; @@ -268,79 +273,108 @@ struct CourseTopRequest : public BaseRequest void ReplyGlobal() { KZPlayer *player = g_pKZPlayerManager->ToPlayer(userID); + CUtlString rank; + + // Overall table CUtlString headers[Q_ARRAYSIZE(columnKeysGlobal)]; for (u32 i = 0; i < Q_ARRAYSIZE(columnKeysGlobal); i++) { headers[i] = player->languageService->PrepareMessage(columnKeysGlobal[i]).c_str(); } + utils::Table table( + player->languageService->PrepareMessage(COURSE_TOP_TABLE_KEY_GLOBAL, mapName.Get(), courseName.Get(), modeName.Get()).c_str(), headers); + FOR_EACH_VEC(wrData.overallData, i) + { + rank.Format("%llu", this->offset + i + 1); + RunStats stats = wrData.overallData[i]; + table.SetRow(i, rank, stats.GetName(), stats.GetTime(), stats.GetTeleportCount(), stats.GetSteamID64(), stats.GetPoints(), + stats.GetRunID()); + } + player->PrintConsole(false, false, table.GetSeparator("=")); + player->PrintConsole(false, false, table.GetTitle()); + player->PrintConsole(false, false, table.GetHeader()); + + for (u32 i = 0; i < table.GetNumEntries(); i++) + { + player->PrintConsole(false, false, table.GetLine(i)); + } + player->PrintConsole(false, false, table.GetSeparator("=")); + + // Pro table CUtlString headersPro[Q_ARRAYSIZE(columnKeysGlobalPro)]; for (u32 i = 0; i < Q_ARRAYSIZE(columnKeysGlobalPro); i++) { headersPro[i] = player->languageService->PrepareMessage(columnKeysGlobalPro[i]).c_str(); } - utils::DualTable dualTable( - player->languageService->PrepareMessage(COURSE_TOP_TABLE_KEY_GLOBAL, mapName.Get(), courseName.Get(), modeName.Get()).c_str(), headers, + utils::Table tablePro( player->languageService->PrepareMessage(COURSE_TOP_PRO_TABLE_KEY_GLOBAL, mapName.Get(), courseName.Get(), modeName.Get()).c_str(), headersPro); - CUtlString rank; - FOR_EACH_VEC(wrData.overallData, i) - { - rank.Format("%llu", this->offset + i + 1); - RunStats stats = wrData.overallData[i]; - dualTable.left.SetRow(i, rank, stats.name, stats.GetTime(), stats.GetTeleportCount(), stats.GetSteamID64(), stats.GetPoints(), - stats.GetRunID()); - } FOR_EACH_VEC(wrData.proData, i) { rank.Format("%llu", this->offset + i + 1); RunStats stats = wrData.proData[i]; - dualTable.right.SetRow(i, rank, stats.name, stats.GetTime(), stats.GetSteamID64(), stats.GetPoints(), stats.GetRunID()); + tablePro.SetRow(i, rank, stats.GetName(), stats.GetTime(), stats.GetSteamID64(), stats.GetPoints(), stats.GetRunID()); } - player->PrintConsole(false, false, dualTable.GetTitle()); - player->PrintConsole(false, false, dualTable.GetHeader()); - player->PrintConsole(false, false, dualTable.GetSeparator()); - for (u32 i = 0; i < dualTable.GetNumEntries(); i++) + player->PrintConsole(false, false, tablePro.GetSeparator("=")); + player->PrintConsole(false, false, tablePro.GetTitle()); + player->PrintConsole(false, false, tablePro.GetHeader()); + for (u32 i = 0; i < tablePro.GetNumEntries(); i++) { - player->PrintConsole(false, false, dualTable.GetLine(i)); + player->PrintConsole(false, false, tablePro.GetLine(i)); } + player->PrintConsole(false, false, tablePro.GetSeparator("=")); } void ReplyLocal() { KZPlayer *player = g_pKZPlayerManager->ToPlayer(userID); + CUtlString rank; + + // Overall table CUtlString headers[Q_ARRAYSIZE(columnKeysLocal)]; for (u32 i = 0; i < Q_ARRAYSIZE(columnKeysLocal); i++) { headers[i] = player->languageService->PrepareMessage(columnKeysLocal[i]).c_str(); } + utils::Table table( + player->languageService->PrepareMessage(COURSE_TOP_TABLE_KEY, mapName.Get(), courseName.Get(), modeName.Get()).c_str(), headers); + FOR_EACH_VEC(srData.overallData, i) + { + rank.Format("%llu", this->offset + i + 1); + RunStats stats = srData.overallData[i]; + table.SetRow(i, rank, stats.GetName(), stats.GetTime(), stats.GetTeleportCount(), stats.GetSteamID64(), stats.GetRunID()); + } + player->PrintConsole(false, false, table.GetSeparator("=")); + player->PrintConsole(false, false, table.GetTitle()); + player->PrintConsole(false, false, table.GetHeader()); + + for (u32 i = 0; i < table.GetNumEntries(); i++) + { + player->PrintConsole(false, false, table.GetLine(i)); + } + player->PrintConsole(false, false, table.GetSeparator("=")); + // Pro table CUtlString headersPro[Q_ARRAYSIZE(columnKeysLocalPro)]; for (u32 i = 0; i < Q_ARRAYSIZE(columnKeysLocalPro); i++) { headersPro[i] = player->languageService->PrepareMessage(columnKeysLocalPro[i]).c_str(); } - utils::DualTable dualTable( - player->languageService->PrepareMessage(COURSE_TOP_TABLE_KEY, mapName.Get(), courseName.Get(), modeName.Get()).c_str(), headers, + utils::Table tablePro( player->languageService->PrepareMessage(COURSE_TOP_PRO_TABLE_KEY, mapName.Get(), courseName.Get(), modeName.Get()).c_str(), headersPro); - CUtlString rank; - FOR_EACH_VEC(srData.overallData, i) - { - rank.Format("%llu", this->offset + i + 1); - RunStats stats = srData.overallData[i]; - dualTable.left.SetRow(i, rank, stats.name, stats.GetTime(), stats.GetTeleportCount(), stats.GetSteamID64(), stats.GetRunID()); - } FOR_EACH_VEC(srData.proData, i) { rank.Format("%llu", this->offset + i + 1); RunStats stats = srData.proData[i]; - dualTable.right.SetRow(i, rank, stats.name, stats.GetTime(), stats.GetSteamID64(), stats.GetRunID()); + tablePro.SetRow(i, rank, stats.GetName(), stats.GetTime(), stats.GetSteamID64(), stats.GetRunID()); } - player->PrintConsole(false, false, dualTable.GetTitle()); - player->PrintConsole(false, false, dualTable.GetHeader()); - player->PrintConsole(false, false, dualTable.GetSeparator()); - for (u32 i = 0; i < dualTable.GetNumEntries(); i++) + player->PrintConsole(false, false, tablePro.GetSeparator("=")); + player->PrintConsole(false, false, tablePro.GetTitle()); + player->PrintConsole(false, false, tablePro.GetHeader()); + for (u32 i = 0; i < tablePro.GetNumEntries(); i++) { - player->PrintConsole(false, false, dualTable.GetLine(i)); + player->PrintConsole(false, false, tablePro.GetLine(i)); } + player->PrintConsole(false, false, tablePro.GetSeparator("=")); } }; diff --git a/src/utils/tables.h b/src/utils/tables.h index 287054a7..d5489ce4 100644 --- a/src/utils/tables.h +++ b/src/utils/tables.h @@ -19,6 +19,7 @@ namespace utils for (u32 i = 0; i < columnCount; i++) { this->headers[i] = headers[i]; + this->headers[i].Append("ᅟ"); // Add a space to reset the "font" to monospace columnLengths[i] = this->headers[i].Length(); } } @@ -28,6 +29,7 @@ namespace utils for (u32 i = 0; i < columnCount; i++) { this->headers[i] = headers[i]; + this->headers[i].Append("ᅟ"); // Add a space to reset the "font" to monospace columnLengths[i] = this->headers[i].Length(); } } @@ -55,7 +57,8 @@ namespace utils entries.SetCountNonDestructively(row + 1); } entries[row].data[column] = value; - columnLengths[column] = MAX(columnLengths[column], V_strlen(value)); + entries[row].data[column].Append("ᅟ"); // Add a space to reset the "font" to monospace + columnLengths[column] = MAX(columnLengths[column], V_strlen(entries[row].data[i].Get())); return true; } @@ -75,6 +78,7 @@ namespace utils entries[row] = {args...}; for (u32 i = 0; i < columnCount; i++) { + entries[row].data[i].Append("ᅟ"); // Add a space to reset the "font" to monospace columnLengths[i] = MAX(columnLengths[i], (u32)V_strlen(entries[row].data[i].Get())); } } @@ -101,7 +105,8 @@ namespace utils for (u32 i = 0; i < columnCount; i++) { CUtlString value; - value.Format("%-*s%s", columnLengths[i], headers[i].Get(), i == columnCount - 1 ? "" : " "); + value.Format("%-*s%s", columnLengths[i] + GetPaddingForWideString(headers[i].Get()), headers[i].Get(), + i == columnCount - 1 ? "" : " "); for (i32 i = 0; i < value.Length() - 1; i++) { if (value[i] == '%' && value[i + 1] == '%') @@ -125,7 +130,8 @@ namespace utils for (u32 i = 0; i < columnCount; i++) { CUtlString value; - value.Format("%-*s%s", columnLengths[i], entries[row].data[i].Get(), i == columnCount - 1 ? "" : " "); + value.Format("%-*s%s", columnLengths[i] + GetPaddingForWideString(entries[row].data[i].Get()), entries[row].data[i].Get(), + i == columnCount - 1 ? "" : " "); for (i32 i = 0; i < value.Length() - 1; i++) { if (value[i] == '%' && value[i + 1] == '%') @@ -139,12 +145,12 @@ namespace utils return result; } - CUtlString GetSeparator() + CUtlString GetSeparator(const char *characters = "_") { CUtlString result; for (u32 i = 0; i < GetTableWidth(); i++) { - result += "_"; + result += characters; } return result; } @@ -176,14 +182,14 @@ namespace utils CUtlString GetTitle() { CUtlString result; - result.Format("%-*s | %-*s", left.GetTableWidth(), left.GetTitle().Get(), right.GetTableWidth(), right.GetTitle().Get()); + result.Format("%-*s\t|\t%-*s", left.GetTableWidth(), left.GetTitle().Get(), right.GetTableWidth(), right.GetTitle().Get()); return result; } CUtlString GetHeader() { CUtlString result; - result.Format("%-*s | %-*s", left.GetTableWidth(), left.GetHeader().Get(), right.GetTableWidth(), right.GetHeader().Get()); + result.Format("%-*s\t|\t%-*s", left.GetTableWidth(), left.GetHeader().Get(), right.GetTableWidth(), right.GetHeader().Get()); return result; } @@ -194,14 +200,15 @@ namespace utils return ""; } CUtlString result; - result.Format("%-*s | %-*s", left.GetTableWidth(), left.GetLine(row).Get(), right.GetTableWidth(), right.GetLine(row).Get()); + result.Format("%-*s\t|\t%-*s", left.GetTableWidth(), left.GetLine(row).Get(), right.GetTableWidth(), right.GetLine(row).Get()); return result; } - CUtlString GetSeparator() + CUtlString GetSeparator(const char *characters = "_") { CUtlString result; - result.Format("%-*s | %-*s", left.GetTableWidth(), left.GetSeparator().Get(), right.GetTableWidth(), right.GetSeparator().Get()); + result.Format("%-*s \t|\t %-*s", left.GetTableWidth(), left.GetSeparator(characters).Get(), right.GetTableWidth(), + right.GetSeparator(characters).Get()); return result; } diff --git a/src/utils/utils.h b/src/utils/utils.h index b574a0cf..264b587e 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -90,4 +90,8 @@ namespace utils bool ParseSteamID2(std::string_view steamID, u64 &out); + inline u32 GetPaddingForWideString(const char *string) + { + return MAX(0, strlen(string) - mbstowcs(NULL, string, 0)); + } } // namespace utils