Skip to content

Commit

Permalink
Add global stuff to record queries
Browse files Browse the repository at this point in the history
  • Loading branch information
zer0k-z committed Feb 3, 2025
1 parent a4bb32f commit db5aca9
Show file tree
Hide file tree
Showing 18 changed files with 613 additions and 100 deletions.
6 changes: 3 additions & 3 deletions src/kz/global/api/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ namespace KZ::API
Classic = 2,
};

static bool DecodeModeString(const std::string &modeString, Mode &mode)
static bool DecodeModeString(std::string_view modeString, Mode &mode)
{
if (modeString == "vanilla")
if (KZ_STREQI(modeString.data(), "vanilla") || KZ_STREQI(modeString.data(), "vnl"))
{
mode = Mode::Vanilla;
return true;
}
else if (modeString == "classic")
else if (KZ_STREQI(modeString.data(), "classic") || KZ_STREQI(modeString.data(), "ckz"))
{
mode = Mode::Classic;
return true;
Expand Down
108 changes: 103 additions & 5 deletions src/kz/global/api/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ namespace KZ::API::events
}
};

struct WantPlayerRecords
struct WantPlayerRecordsForCache
{
u16 mapId;
u64 playerId;
Expand All @@ -190,7 +190,7 @@ namespace KZ::API::events
}
};

struct PlayerRecords
struct PlayerRecordsForCache
{
std::vector<Record> records {};

Expand All @@ -200,19 +200,19 @@ namespace KZ::API::events
}
};

struct WantWorldRecords
struct WantWorldRecordsForCache
{
u16 mapId;

WantWorldRecords(u16 mapId) : mapId(mapId) {}
WantWorldRecordsForCache(u16 mapId) : mapId(mapId) {}

bool ToJson(Json &json) const
{
return json.Set("map_id", this->mapId);
}
};

struct WorldRecords
struct WorldRecordsForCache
{
std::vector<Record> records {};

Expand All @@ -221,4 +221,102 @@ namespace KZ::API::events
return json.Get("records", this->records);
}
};

struct WantCourseTop
{
std::string mapName;
std::string courseNameOrNumber;
Mode mode;
u32 limit;
u32 offset;

bool ToJson(Json &json) const
{
bool success = true;
success &= json.Set("map", mapName);
success &= json.Set("course", courseNameOrNumber);
success &= json.Set("mode", (u8)mode);
success &= json.Set("limit", limit);
success &= json.Set("offset", offset);
return success;
}
};

struct CourseTop
{
std::vector<Record> overall;
std::vector<Record> pro;

bool FromJson(const Json &json)
{
return json.Get("overall", this->overall) && json.Get("pro", this->pro);
}
};

struct WantPersonalBest
{
u64 steamid64;
std::string playerName;
std::string mapName;
std::string courseNameOrNumber;
Mode mode;
std::vector<std::string> styles;

bool ToJson(Json &json) const
{
bool success = true;
if (steamid64)
{
success &= json.Set("player", steamid64);
}
else
{
success &= json.Set("player", playerName);
}
success &= json.Set("map", mapName);
success &= json.Set("course", courseNameOrNumber);
success &= json.Set("mode", (u8)mode);
success &= json.Set("styles", styles);
return success;
}
};

struct PersonalBest
{
std::optional<PlayerInfo> player;
std::optional<Record> overall;
std::optional<Record> pro;

bool FromJson(const Json &json)
{
return json.Get("player", this->player) && json.Get("overall", this->overall) && json.Get("pro", this->pro);
}
};

struct WantWorldRecords
{
std::string mapName;
std::string courseNameOrNumber;
Mode mode;

bool ToJson(Json &json) const
{
bool success = true;
success &= json.Set("map", mapName);
success &= json.Set("course", courseNameOrNumber);
success &= json.Set("mode", (u8)mode);
return success;
}
};

struct WorldRecords
{
std::optional<Record> overall;
std::optional<Record> pro;

bool FromJson(const Json &json)
{
return json.Get("overall", this->overall) && json.Get("pro", this->pro);
}
};
} // namespace KZ::API::events
6 changes: 5 additions & 1 deletion src/kz/global/api/players.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ namespace KZ::API
return false;
}

if (!json.Get("is_banned", this->isCheater))
{
return false;
}
return true;
}

private:
std::string id {};
std::string name {};
bool isCheater;
};
} // namespace KZ::API
10 changes: 10 additions & 0 deletions src/kz/global/api/records.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ namespace KZ::API
f64 time;
u32 nubRank = 0;
f64 nubPoints = -1;
u32 nubMaxRank = 0;
u32 proRank = 0;
f64 proPoints = -1;
u32 proMaxRank = 0;

bool FromJson(const Json &json)
{
Expand Down Expand Up @@ -72,6 +74,10 @@ namespace KZ::API
{
return false;
}
if (!json.Get("nub_max_rank", this->nubMaxRank))
{
return false;
}
}

if (json.Get("pro_rank", this->proRank))
Expand All @@ -80,6 +86,10 @@ namespace KZ::API
{
return false;
}
if (!json.Get("pro_max_rank", this->proMaxRank))
{
return false;
}
}

return true;
Expand Down
52 changes: 41 additions & 11 deletions src/kz/global/kz_global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "common.h"
#include "kz/kz.h"
#include "kz/language/kz_language.h"
#include "kz/mode/kz_mode.h"
#include "kz/timer/kz_timer.h"
#include "kz/option/kz_option.h"
Expand Down Expand Up @@ -139,9 +140,9 @@ void KZGlobalService::OnActivateServer()
KZ::course::UpdateCourseGlobalID(course.name.c_str(), course.id);
}

KZ::API::events::WantWorldRecords data(mapInfo.map->id);
KZ::API::events::WantWorldRecordsForCache data(mapInfo.map->id);

auto callback = [](const KZ::API::events::WorldRecords &records)
auto callback = [](const KZ::API::events::WorldRecordsForCache &records)
{
for (const KZ::API::Record &record : records.records)
{
Expand Down Expand Up @@ -186,11 +187,11 @@ void KZGlobalService::OnPlayerAuthorized()

if (KZGlobalService::currentMap.has_value())
{
KZ::API::events::WantPlayerRecords data;
KZ::API::events::WantPlayerRecordsForCache data;
data.mapId = KZGlobalService::currentMap->id;
data.playerId = this->player->GetSteamId64();

auto callback = [player = this->player](const KZ::API::events::PlayerRecords &pbs)
auto callback = [player = this->player](const KZ::API::events::PlayerRecordsForCache &pbs)
{
for (const KZ::API::Record &record : pbs.records)
{
Expand Down Expand Up @@ -239,17 +240,15 @@ void KZGlobalService::OnClientDisconnect()
KZGlobalService::SendMessage("player-leave", data);
}

bool KZGlobalService::SubmitRecord(u32 localId, const char *courseName, const char *modeName, f64 time, u32 teleports, const char *metadata)
bool KZGlobalService::SubmitRecord(u32 localId, const char *courseName, KZ::API::Mode mode, f64 time, u32 teleports, const char *metadata)
{
if (!KZGlobalService::currentMap.has_value())
if (!this->player->IsAuthenticated() && !this->player->hasPrime)
{
META_CONPRINTF("[KZ::Global] Cannot submit record on non-global map.\n");
return false;
}

if (!(KZ_STREQI(modeName, "vnl") || KZ_STREQI(modeName, "ckz")))
if (!KZGlobalService::currentMap.has_value())
{
META_CONPRINTF("[KZ::Global] Cannot submit record on non-global mode.\n");
META_CONPRINTF("[KZ::Global] Cannot submit record on non-global map.\n");
return false;
}

Expand All @@ -272,7 +271,7 @@ bool KZGlobalService::SubmitRecord(u32 localId, const char *courseName, const ch

KZ::API::events::NewRecord data;
data.playerId = this->player->GetSteamId64();
data.filterId = KZ_STREQI(modeName, "vnl") ? course->filters.vanilla.id : course->filters.classic.id;
data.filterId = (mode == KZ::API::Mode::Vanilla) ? course->filters.vanilla.id : course->filters.classic.id;
data.styles = {}; // TODO
data.teleports = teleports;
data.time = time;
Expand Down Expand Up @@ -302,6 +301,37 @@ bool KZGlobalService::SubmitRecord(u32 localId, const char *courseName, const ch
return true;
}

bool KZGlobalService::QueryPB(u64 steamid64, CUtlString targetPlayerName, CUtlString mapName, CUtlString courseNameOrNumber, KZ::API::Mode mode,
CUtlVector<CUtlString> &styleNames, Callback<KZ::API::events::PersonalBest> cb)
{
KZ::API::events::WantPersonalBest pbRequest = {steamid64, targetPlayerName.Get(), mapName.Get(), courseNameOrNumber, mode};
FOR_EACH_VEC(styleNames, i)
{
pbRequest.styles.emplace_back(styleNames[i].Get());
}

KZGlobalService::SendMessage("query-pb", pbRequest, cb);
return true;
}

bool KZGlobalService::QueryCourseTop(CUtlString mapName, CUtlString courseNameOrNumber, KZ::API::Mode mode, u32 limit, u32 offset,
Callback<KZ::API::events::CourseTop> cb)
{
KZ::API::events::WantCourseTop ctopRequest = {mapName.Get(), courseNameOrNumber.Get(), mode, limit, offset};

KZGlobalService::SendMessage("query-course-top", ctopRequest, cb);
return true;
}

bool KZGlobalService::QueryWorldRecords(CUtlString mapName, CUtlString courseNameOrNumber, KZ::API::Mode mode,
Callback<KZ::API::events::WorldRecords> cb)
{
KZ::API::events::WantWorldRecords ctopRequest = {mapName.Get(), courseNameOrNumber.Get(), mode};

KZGlobalService::SendMessage("query-wr", ctopRequest, cb);
return true;
}

void KZGlobalService::OnWebSocketMessage(const ix::WebSocketMessagePtr &message)
{
switch (message->type)
Expand Down
33 changes: 29 additions & 4 deletions src/kz/global/kz_global.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
#include "utils/json.h"

#include "kz/kz.h"
#include "kz/global/api/api.h"
#include "kz/global/api/events.h"
#include "kz/global/api/maps.h"

class KZGlobalService : public KZBaseService
{
using KZBaseService::KZBaseService;

public:
template<typename... Args>
using Callback = std::function<void(Args...)>;

static void Init();
static void Cleanup();
static void RegisterCommands();
Expand Down Expand Up @@ -47,12 +52,32 @@ class KZGlobalService : public KZBaseService
*
* Returns whether the record was submitted. This could be false if the filter is not ranked.
*/
bool SubmitRecord(u32 localId, const char *courseName, const char *modeName, f64 time, u32 teleports, const char *metadata);
bool SubmitRecord(u32 localId, const char *courseName, KZ::API::Mode mode, f64 time, u32 teleports, const char *metadata);

private:
template<typename... Args>
using Callback = std::function<void(Args...)>;
/**
* Query the personal best of a player on a certain map, course, mode, style.
*
* Always return true.
*/
static bool QueryPB(u64 steamid64, CUtlString targetPlayerName, CUtlString mapName, CUtlString courseNameOrNumber, KZ::API::Mode mode,
CUtlVector<CUtlString> &styleNames, Callback<KZ::API::events::PersonalBest> cb);

/**
* Query the course top on a certain map, mode with a certain limit and offset.
*
* Always return true.
*/
static bool QueryCourseTop(CUtlString mapName, CUtlString courseNameOrNumber, KZ::API::Mode mode, u32 limit, u32 offset,
Callback<KZ::API::events::CourseTop> cb);

/**
* Query the world record of a course on a certain mode.
*
* Always return true.
*/
static bool QueryWorldRecords(CUtlString mapName, CUtlString courseNameOrNumber, KZ::API::Mode mode, Callback<KZ::API::events::WorldRecords> cb);

private:
/**
* URL to make HTTP requests to.
*
Expand Down
6 changes: 5 additions & 1 deletion src/kz/timer/announce_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ struct AnnounceData
}
if (KZGlobalService::IsConnected() && player->IsAuthenticated())
{
player->globalService->SubmitRecord(id, courseName.Get(), modeName, time, teleportsUsed, metadata);
KZ::API::Mode mode;
if (KZ::API::DecodeModeString(modeName.Get(), mode))
{
player->globalService->SubmitRecord(id, courseName.Get(), mode, time, teleportsUsed, metadata);
}
}
}

Expand Down
Loading

0 comments on commit db5aca9

Please sign in to comment.