Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
69 changes: 63 additions & 6 deletions src/Features/AutoSubmit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ ON_EVENT(SESSION_START) {
}

ON_INIT {
NetMessage::RegisterHandler(COOP_NAME_MESSAGE_TYPE, +[](const void *data, size_t size) {
AutoSubmit::g_partner_name = std::string((char *)data, size);
});
NetMessage::RegisterHandler(COOP_NAME_MESSAGE_TYPE, +[](const void *data, size_t size) { AutoSubmit::g_partner_name = std::string((char *)data, size); });
}

ON_EVENT(SESSION_START) {
Expand All @@ -65,6 +63,8 @@ static std::thread g_worker_search;
static std::map<std::string, std::string> g_map_ids;
static bool g_is_querying;
static std::vector<PortalLeaderboardItem_t> g_times;
static std::vector<PortalLeaderboardItem_t> g_portals;
static bool g_lp;

static bool ensureCurlReady(CURL **curl) {
if (!*curl) {
Expand Down Expand Up @@ -257,6 +257,7 @@ static std::shared_ptr<uint8_t> getAvatar(std::string url) {
}

static void startSearching(std::string mapName) {
/* get scores */
auto map_id = AutoSubmit::GetMapId(mapName);
if (!map_id.has_value()) {
g_is_querying = false;
Expand Down Expand Up @@ -294,6 +295,36 @@ static void startSearching(std::string mapName) {
++i;
}

/* get lp scores */
auto lp_map_id = std::to_string(distance(Game::mapNames.begin(), find(Game::mapNames.begin(), Game::mapNames.end(), mapName)) + 1);

auto lp_json = AutoSubmit::GetLeastPortals(lp_map_id);

g_portals.clear();
for (const auto &score : lp_json) {
g_lp = true;

bool is_coop = stoi(lp_map_id) > 60;

PortalLeaderboardItem_t data;

if (!is_coop) {
strncpy(data.name, score["user"]["user_name"].string_value().c_str(), sizeof(data.name));
strncpy(data.autorender, "null", sizeof(data.autorender));
data.avatarTex = getAvatar(score["user"]["avatar_link"].string_value());
data.rank = score["placement"].int_value();
data.score = score["score_count"].int_value();
} else {
strncpy(data.name, (score["host"]["user_name"].string_value() + " & " + score["partner"]["user_name"].string_value()).c_str(), sizeof(data.name));
strncpy(data.autorender, "null", sizeof(data.autorender));
data.avatarTex = getAvatar(score["host"]["avatar_link"].string_value());
data.rank = score["placement"].int_value();
data.score = score["score_count"].int_value();
}

g_portals.push_back(data);
}

g_is_querying = false;
}

Expand Down Expand Up @@ -321,6 +352,24 @@ json11::Json::object AutoSubmit::GetTopScores(std::string &map_id) {
return json.object_items();
}

json11::Json::array AutoSubmit::GetLeastPortals(std::string &map_id) {
if (!ensureCurlReady(&g_curl_search)) return {};

auto response = request(g_curl_search, "lp.pektezol.dev/api/v1/maps/" + map_id + "/leaderboards?page=1&pageSize=40");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


if (!response) return {};

std::string err;
auto json = json11::Json::parse(*response, err);

if (err != "") {
return {};
}

return json["data"]["records"].array_items();
}


bool AutoSubmit::IsQuerying() {
return g_is_querying;
}
Expand All @@ -329,6 +378,14 @@ const std::vector<PortalLeaderboardItem_t> &AutoSubmit::GetTimes() {
return g_times;
}

const std::vector<PortalLeaderboardItem_t> &AutoSubmit::GetPortals() {
return g_portals;
}

bool AutoSubmit::IsLpAvailable() {
return g_lp;
}

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) {
auto score_str = std::to_string(score);

Expand Down Expand Up @@ -406,7 +463,7 @@ static void submitTime(int score, std::string demopath, bool coop, std::string m

curl_easy_setopt(g_curl, CURLOPT_MIMEPOST, form);

auto resp = request(g_curl, g_api_base + "/auto-submit");
auto resp = request(g_curl, g_api_base + "/auto-submit");

curl_mime_free(form);

Expand Down Expand Up @@ -500,7 +557,7 @@ void AutoSubmit::LoadApiKey(bool output_nonexist) {
return;
}

g_api_base = "https://" + base + "/api-v2";
g_api_base = "https://" + base + "/api-v2";
g_api_key = key;
g_key_valid = false;
console->Print("Set API key! Testing...\n");
Expand Down Expand Up @@ -571,7 +628,7 @@ void retrieveMtriggers(int rank, std::string map_name) {
auto ticks = split["ticks"].int_value();
auto segmentTime = ticks * engine->GetIPT();
time += ticks * engine->GetIPT();
auto timeS = SpeedrunTimer::Format(time);
auto timeS = SpeedrunTimer::Format(time);
auto segmentTimeS = SpeedrunTimer::Format(segmentTime);
THREAD_PRINT("[%s] - %s (%s) (%i)\n", split["name"].string_value().c_str(), timeS.c_str(), segmentTimeS.c_str(), ticks);
}
Expand Down
3 changes: 3 additions & 0 deletions src/Features/AutoSubmit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ namespace AutoSubmit {
std::optional<std::string> GetMapId(std::string map_name);
void Search(std::string map);
json11::Json::object GetTopScores(std::string &map_id);
json11::Json::array GetLeastPortals(std::string &map_id);
bool IsQuerying();
const std::vector<PortalLeaderboardItem_t> &GetTimes();
const std::vector<PortalLeaderboardItem_t> &GetPortals();
bool IsLpAvailable();
};
24 changes: 19 additions & 5 deletions src/Modules/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,8 @@ DETOUR_T(bool, Client::ActivateSelectedItem) {

// we stored the autorender ID in this earlier
char *m_nSteamID = *(char **)((uintptr_t)thisptr + Offsets::m_pGamerName - 16);
if (!strcmp(m_nSteamID, "null"))
return false;

steam->ActivateGameOverlayToWebPage(steam->SteamFriends(), Utils::ssprintf("https://autorender.portal2.sr/videos/%s", m_nSteamID).c_str(), 0);

Expand Down Expand Up @@ -905,12 +907,12 @@ DETOUR(Client::SetPanelStats) {
int m_CurrentLeaderboardType = *(int *)((uintptr_t)thisptr + Offsets::m_nStatHeight + 212);

/* here for the future if we want to integrate lp boards */
bool showLp = false; // sar.game->Is(SourceGame_Portal2);
bool showLp = sar.game->Is(SourceGame_Portal2) && AutoSubmit::IsLpAvailable();

/* set time/portals button visible (only in p2 though) */
if (showLp)
if (showLp) {
Memory::VMT<void(__rescall *)(void *, bool)>(m_pLeaderboardListButton, Offsets::Panel_SetVisible)(m_pLeaderboardListButton, true); // Panel::SetVisible
else
} else
m_CurrentLeaderboardType = 1;

/* set boards visible */
Expand Down Expand Up @@ -950,6 +952,14 @@ DETOUR(Client::SetPanelStats) {

client->AddAvatarPanelItem(m_pLeaderboard, m_pStatList, &time, time.score, 1, -1, i, m_nStatHeight, -1, 0);
}
} else /* portals */ {
const auto &times = AutoSubmit::GetPortals();

for (size_t i = 0; i < times.size(); ++i) {
const auto &time = times[i];

client->AddAvatarPanelItem(m_pLeaderboard, m_pStatList, &time, time.score, 0, -1, i, m_nStatHeight, -1, 0);
}
}

return 0;
Expand All @@ -970,9 +980,13 @@ DETOUR(Client::SetPlayerData, PortalLeaderboardItem_t *pData, int nType) {
char **m_nSteamID = (char **)((uintptr_t)thisptr + Offsets::m_pGamerName - 16);
*m_nSteamID = pData->autorender;

auto score = std::to_string(pData->score);

/* cut off last digit lol */
auto score = SpeedrunTimer::Format(pData->score / 100.0f);
score = score.substr(0, score.length() - 1);
if (nType == 1) {
score = SpeedrunTimer::Format(pData->score / 100.0f);
score = score.substr(0, score.length() - 1);
}

/* set player name */
Memory::VMT<void(__rescall *)(void *, const char *)>(m_pGamerName, Offsets::Label_SetText)(m_pGamerName, pData->name); // Label::SetText
Expand Down