Skip to content

Commit

Permalink
feat: implement new boards api
Browse files Browse the repository at this point in the history
  • Loading branch information
hero622 committed Nov 3, 2023
1 parent 9ab88e1 commit 2871c23
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 34 deletions.
33 changes: 28 additions & 5 deletions src/Features/AutoSubmitMod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ std::optional<std::string> AutoSubmitMod::GetMapId(std::string map_name) {
return it->second;
}

std::optional<int> AutoSubmitMod::GetCurrentPbScore(std::string &map_id) {
std::optional<int> getCurrentPbScore(std::string &map_id) {
if (!ensureCurlReady()) return {};

curl_mime *form = curl_mime_init(g_curl);
Expand Down Expand Up @@ -166,10 +166,33 @@ std::optional<int> AutoSubmitMod::GetCurrentPbScore(std::string &map_id) {
return atoi(str.c_str());
}

json11::Json::object AutoSubmitMod::GetMapJson(std::string &map_id) {
json11::Json::array AutoSubmitMod::GetTopScores(std::string &map_id) {
if (!ensureCurlReady()) return {};

auto response = request(g_api_base.substr(0, g_api_base.length() - 6) + "chamber/" + map_id + "/json");
curl_mime *form = curl_mime_init(g_curl);
curl_mimepart *field;

field = curl_mime_addpart(form);
curl_mime_name(field, "auth_hash");
curl_mime_data(field, g_api_key.c_str(), CURL_ZERO_TERMINATED);

field = curl_mime_addpart(form);
curl_mime_name(field, "mapId");
curl_mime_data(field, map_id.c_str(), CURL_ZERO_TERMINATED);

field = curl_mime_addpart(form);
curl_mime_name(field, "before");
curl_mime_data(field, "3", CURL_ZERO_TERMINATED);

field = curl_mime_addpart(form);
curl_mime_name(field, "after");
curl_mime_data(field, "2", CURL_ZERO_TERMINATED);

curl_easy_setopt(g_curl, CURLOPT_MIMEPOST, form);

auto response = request(g_api_base + "/top-scores");

curl_mime_free(form);

if (!response) return {};

Expand All @@ -180,7 +203,7 @@ json11::Json::object AutoSubmitMod::GetMapJson(std::string &map_id) {
return {};
}

return json.object_items();
return json.array_items();
}

static void submitTime(int score, std::string demopath, bool coop, std::string map_id, std::optional<std::string> rename_if_pb, std::optional<std::string> replay_append_if_pb) {
Expand All @@ -196,7 +219,7 @@ static void submitTime(int score, std::string demopath, bool coop, std::string m
return;
}

auto cur_pb = AutoSubmitMod::GetCurrentPbScore(map_id);
auto cur_pb = getCurrentPbScore(map_id);
if (cur_pb) {
if (*cur_pb > -1 && score >= *cur_pb) {
THREAD_PRINT("Not PB; not submitting.\n");
Expand Down
3 changes: 1 addition & 2 deletions src/Features/AutoSubmitMod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ namespace AutoSubmitMod {
void LoadApiKey(bool output_nonexist);
void FinishRun(float final_time, const char *demopath, std::optional<std::string> rename_if_pb, std::optional<std::string> replay_append_if_pb);
std::optional<std::string> GetMapId(std::string map_name);
std::optional<int> GetCurrentPbScore(std::string &map_id);
json11::Json::object GetMapJson(std::string &map_id);
json11::Json::array GetTopScores(std::string &map_id);
}; // namespace AutoSubmitMod
55 changes: 28 additions & 27 deletions src/Modules/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ REDECL(Client::GetLeaderboard);
REDECL(Client::PurgeAndDeleteElements);
REDECL(Client::IsQuerying);
REDECL(Client::SetPanelStats);
REDECL(Client::OnCommand);

CMDECL(Client::GetAbsOrigin, Vector, m_vecAbsOrigin);
CMDECL(Client::GetAbsAngles, QAngle, m_angAbsRotation);
Expand Down Expand Up @@ -520,36 +521,18 @@ Hook g_AddShadowToReceiverHook(&Client::AddShadowToReceiver_Hook);

static std::thread g_worker;
static bool g_is_querying;
static std::vector<std::pair<std::string, json11::Json>> g_times;
static std::pair<int, int> g_ranges;
static std::vector<json11::Json> g_times;

static void startSearching(const char *mapName) {
auto map_id = AutoSubmitMod::GetMapId(std::string(mapName));
auto json = AutoSubmitMod::GetMapJson(*map_id);

auto json = AutoSubmitMod::GetTopScores(*map_id);

g_times.clear();
for (auto score : json) {
g_times.push_back(score);
}

std::sort(g_times.begin(), g_times.end(), [](std::pair<std::string, json11::Json> a, std::pair<std::string, json11::Json> b) {
return atoi(a.second["scoreData"]["score"].string_value().c_str()) < atoi(b.second["scoreData"]["score"].string_value().c_str());
});

auto pb = AutoSubmitMod::GetCurrentPbScore(*map_id);
int pb_idx = 0;
for (int i = 0; i < g_times.size(); ++i) {
if (atoi(g_times[i].second["scoreData"]["score"].string_value().c_str()) == *pb) {
pb_idx = i;
break;
}
}

g_ranges.first = std::max(pb_idx - 3, 0);
g_ranges.second = std::min(pb_idx + 3, (int)g_times.size());
if (g_ranges.second - g_ranges.first < 6 && pb_idx - 3 < 0) g_ranges.second = std::min(g_ranges.first + 6, (int)g_times.size());
if (g_ranges.second - g_ranges.first < 6 && pb_idx + 3 > g_times.size()) g_ranges.first = std::max(g_ranges.second - 6, 0);

g_is_querying = false;
}

Expand All @@ -568,7 +551,7 @@ DETOUR(Client::StartSearching) {
}
Hook g_StartSearchingHook(&Client::StartSearching_Hook);

static std::vector<const char *> g_registeredLbs;
static std::vector<std::string> g_registeredLbs;

extern Hook g_GetLeaderboardHook;
DETOUR_T(void *, Client::GetLeaderboard, const char *a2) {
Expand Down Expand Up @@ -610,13 +593,13 @@ DETOUR(Client::SetPanelStats) {
void *m_pStatList = *(void **)((uintptr_t)thisptr + Offsets::m_pStatList);
int m_nStatHeight = *(int *)((uintptr_t)thisptr + Offsets::m_nStatHeight);

for (int i = g_ranges.first; i < g_ranges.second; ++i) {
for (int i = 0; i < g_times.size(); ++i) {
const auto &time = g_times[i];

PortalLeaderboardItem_t data;
data.m_xuid = atoll(time.first.c_str());
data.m_iScore = atoi(time.second["scoreData"]["score"].string_value().c_str());
strncpy(data.m_szName, time.second["userData"]["boardname"].string_value().c_str(), sizeof(data.m_szName));
data.m_xuid = atoll(time["userData"]["profileNumber"].string_value().c_str());
data.m_iScore = atoi(time["scoreData"]["score"].string_value().c_str());
strncpy(data.m_szName, time["userData"]["boardname"].string_value().c_str(), sizeof(data.m_szName));

client->AddAvatarPanelItem(m_pLeaderboard, m_pStatList, &data, data.m_iScore, 1, -1, i, m_nStatHeight, -1, 0);
}
Expand All @@ -625,6 +608,19 @@ DETOUR(Client::SetPanelStats) {
}
Hook g_SetPanelStatsHook(&Client::SetPanelStats_Hook);

extern Hook g_OnCommandHook;
DETOUR(Client::OnCommand, const char *a2) {
if (!strcmp(a2, "Leaderboard_Time")) {
return 0;
}

g_OnCommandHook.Disable();
auto ret = Client::OnCommand(thisptr, a2);
g_OnCommandHook.Enable();
return ret;
}
Hook g_OnCommandHook(&Client::OnCommand_Hook);

ON_EVENT(SAR_UNLOAD) {
if (g_worker.joinable()) g_worker.detach();
}
Expand Down Expand Up @@ -814,6 +810,8 @@ bool Client::Init() {

auto OnEvent = Memory::Scan(this->Name(), "55 8B EC 57 8B F9 8B 4D 08 E8");
Client::PurgeAndDeleteElements = Memory::Read<decltype(Client::PurgeAndDeleteElements)>(OnEvent + 37);

Client::OnCommand = (decltype(Client::OnCommand))Memory::Scan(this->Name(), "55 8B EC 56 57 8B 7D 08 57 68 ? ? ? ? 8B F1 E8 ? ? ? ? 83 C4 08 85 C0 0F 84");
#else
auto CPortalLeaderboardPanel_OnThink = Memory::Scan(this->Name(), "55 89 E5 57 56 53 81 EC ? ? ? ? 65 A1 ? ? ? ? 89 45 E4 31 C0 A1 ? ? ? ? 8B 5D 08 8B 70 30");
Client::GetLeaderboard = Memory::Read<decltype(Client::GetLeaderboard)>(CPortalLeaderboardPanel_OnThink + 973);
Expand All @@ -824,13 +822,16 @@ bool Client::Init() {

auto OnEvent = Memory::Scan(this->Name(), "55 89 E5 57 56 53 83 EC 1C 8B 45 0C 8B 7D 08 89 04 24 E8 ? ? ? ? C7 04 24");
Client::PurgeAndDeleteElements = Memory::Read<decltype(Client::PurgeAndDeleteElements)>(OnEvent + 120);

Client::OnCommand = (decltype(Client::OnCommand))Memory::Scan(this->Name(), "55 89 E5 57 56 53 83 EC 2C 8B 75 0C C7 04 24 ? ? ? ? 8B 5D 08 89 74 24 04 E8 ? ? ? ? 85 C0 75 3D");
#endif

g_PurgeAndDeleteElementsHook.SetFunc(Client::PurgeAndDeleteElements);
g_GetLeaderboardHook.SetFunc(Client::GetLeaderboard);
g_IsQueryingHook.SetFunc(Client::IsQuerying);
g_SetPanelStatsHook.SetFunc(Client::SetPanelStats);
g_StartSearchingHook.SetFunc(Client::StartSearching);
g_PurgeAndDeleteElementsHook.SetFunc(Client::PurgeAndDeleteElements);
g_OnCommandHook.SetFunc(Client::OnCommand);
}

cl_showpos = Variable("cl_showpos");
Expand Down
3 changes: 3 additions & 0 deletions src/Modules/Client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class Client : public Module {
void OpenChat();

public:
// BaseModUI::CPortalLeaderboardPanel::OnCommand
DECL_DETOUR(OnCommand, const char *a2);

// BaseModUI::CPortalLeaderboardPanel::SetPanelStats
DECL_DETOUR(SetPanelStats);

Expand Down

0 comments on commit 2871c23

Please sign in to comment.