diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index cc716c425a..0bc157105b 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -6,6 +6,25 @@ local rateIndex = 1 local scoreIndex = 1 local score local pn = GAMESTATE:GetEnabledPlayers()[1] +local nestedTab = 1 +local nestedTabs = {"Local", "Online"} + +local frameX = 10 +local frameY = 45 +local frameWidth = capWideScale(320,400) +local frameHeight = 350 +local fontScale = 0.4 +local offsetX = 10 +local offsetY = 30 +local netScoresPerPage = 5 +local netScoresCurrentPage = 1 +local netScores = {} +local nestedTabButtonWidth = 50 +local nestedTabButtonHeight = offsetY*2/3 +local netPageButtonWidth = 40 +local netPageButtonHeight = 20 + +local judges = {'TapNoteScore_W1','TapNoteScore_W2','TapNoteScore_W3','TapNoteScore_W4','TapNoteScore_W5','TapNoteScore_Miss','HoldNoteScore_Held','HoldNoteScore_LetGo'} local defaultRateText = "" if themeConfig:get_data().global.RateSort then @@ -14,7 +33,7 @@ else defaultRateText = "All" end -local t = Def.ActorFrame{ +local ret = Def.ActorFrame{ BeginCommand=function(self) self:queuecommand("Set"):visible(false) end, @@ -31,16 +50,18 @@ local t = Def.ActorFrame{ self:visible(true) update = true self:playcommand("InitScore") + MESSAGEMAN:Broadcast("ScoreUpdate") else self:queuecommand("Off") update = false + MESSAGEMAN:Broadcast("ScoreUpdate") end end, TabChangedMessageCommand=function(self) self:queuecommand("Set") end, CodeMessageCommand=function(self,params) - if update then + if update and nestedTab == 1 then if params.Name == "NextRate" then rateIndex = ((rateIndex)%(#rates))+1 scoreIndex = 1 @@ -105,30 +126,21 @@ local t = Def.ActorFrame{ end } -local frameX = 10 -local frameY = 45 -local frameWidth = capWideScale(320,400) -local frameHeight = 350 -local fontScale = 0.4 -local offsetX = 10 -local offsetY = 20 - -local judges = {'TapNoteScore_W1','TapNoteScore_W2','TapNoteScore_W3','TapNoteScore_W4','TapNoteScore_W5','TapNoteScore_Miss','HoldNoteScore_Held','HoldNoteScore_LetGo'} - -t[#t+1] = Def.Quad{InitCommand=function(self) +ret[#ret+1] = Def.Quad{InitCommand=function(self) self:xy(frameX,frameY):zoomto(frameWidth,frameHeight):halign(0):valign(0):diffuse(color("#333333CC")) end} -t[#t+1] = Def.Quad{InitCommand=function(self) - self:xy(frameX,frameY):zoomto(frameWidth,offsetY):halign(0):valign(0):diffuse(getMainColor('frames')):diffusealpha(0.5) -end} -t[#t+1] = LoadFont("Common Normal")..{ - InitCommand=function(self) - self:xy(frameX+5,frameY+offsetY-9):zoom(0.6):halign(0):diffuse(getMainColor('positive')) + +local t = Def.ActorFrame { + SetCommand=function(self) + self:visible(nestedTab == 1) + end, + NestedTabChangedMessageCommand=function(self) + self:queuecommand("Set") + end, + ScoreUpdateMessageCommand=function(self) + self:queuecommand("Set") end, - BeginCommand=function(self) - self:settext("Score Info") - end } t[#t+1] = LoadFont("Common Large")..{ @@ -489,13 +501,358 @@ t[#t+1] = Def.Quad{ self:xy(frameX+offsetX,frameY+offsetY+288):zoomto(120,30):halign(0):diffusealpha(0) end, MouseLeftClickMessageCommand=function(self) - if update then + if update and nestedTab == 1 then if getTabIndex() == 2 and getScoreForPlot() and getScoreForPlot():HasReplayData() and isOver(self) then SCREENMAN:AddNewScreenToTop("ScreenScoreTabOffsetPlot") end end end } - -return t \ No newline at end of file + +local function ButtonActive(self) + return isOver(self) and update +end + +ret[#ret+1] = t +local netscoreframeWidth = capWideScale(get43size(300),300) +local netscorespacing = 34 +local netscoreframex = capWideScale(get43size(70),70) +local netscoreframey = offsetY+netscorespacing/2+capWideScale(get43size(70),70) +local netTab = Def.ActorFrame { + SetCommand = function(self) + netScores = {} + local steps = GAMESTATE:GetCurrentSteps(PLAYER_1) + if steps and GAMESTATE:GetCurrentSong() then + local ck = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() + for i=1,DLMAN:GetTopChartScoreCount(ck) do + netScores[i] = DLMAN:GetTopChartScore(ck, i) + end + end + if not (netScoresCurrentPage < math.ceil(#netScores/netScoresPerPage)) then + netScoresCurrentPage = 1 + end + MESSAGEMAN:Broadcast("NetScoreUpdate") + end, + ChartLeaderboardUpdateCommand = function(self) + self:queuecommand("Set") + end, + ChartLeaderboardUpdateMessageCommand = function(self) + self:queuecommand("Set") + end, + PlayerJoinedMessageCommand=function(self) + self:queuecommand("Set") + end, + CurrentSongChangedMessageCommand=function(self) + self:queuecommand("Set") + end, + CurrentStepsP1ChangedMessageCommand=function(self) + self:queuecommand("Set") + end, + CurrentStepsP2ChangedMessageCommand=function(self) + self:queuecommand("Set") + end, + VisibilityCommand=function(self) + self:visible(nestedTab == 2) + end, + NestedTabChangedMessageCommand=function(self) + self:queuecommand("Visibility") + end, + ScoreUpdateMessageCommand=function(self) + self:queuecommand("Visibility") + end, + Def.ActorFrame { + InitCommand=function(self) + self:xy(offsetX+frameWidth/2-netPageButtonWidth*1.5, frameY+frameHeight-netPageButtonHeight*1.5) + end, + --prev + Def.ActorFrame{ + Def.Quad{ + InitCommand=function(self) + self:zoomto(netPageButtonWidth, netPageButtonHeight):diffusealpha(0.35):diffuse(getMainColor('frames')) + end, + MouseLeftClickMessageCommand=function(self) + if ButtonActive(self) and update and nestedTab == 2 then + if netScoresCurrentPage > 1 then + netScoresCurrentPage = netScoresCurrentPage - 1 + else + netScoresCurrentPage = math.ceil(#netScores/netScoresPerPage) + end + MESSAGEMAN:Broadcast("NetScoreUpdate") + end + end + }, + LoadFont("Common Large") .. { + InitCommand=function(self) + self:diffuse(getMainColor('positive')):maxwidth(netPageButtonWidth):maxheight(25):zoom(0.85) + end, + BeginCommand=function(self) + self:settext("Prev") + end + } + }, + --next + Def.ActorFrame{ + InitCommand=function(self) + self:x(netPageButtonWidth*3) + end, + Def.Quad{ + InitCommand=function(self) + self:zoomto(netPageButtonWidth, netPageButtonHeight):diffusealpha(0.35):diffuse(getMainColor('frames')) + end, + MouseLeftClickMessageCommand=function(self) + if ButtonActive(self) and update and nestedTab == 2 then + if netScoresCurrentPage < math.ceil(#netScores/netScoresPerPage) then + netScoresCurrentPage = netScoresCurrentPage + 1 + else + netScoresCurrentPage = 1 + end + MESSAGEMAN:Broadcast("NetScoreUpdate") + end + end + }, + LoadFont("Common Large") .. { + InitCommand=function(self) + self:diffuse(getMainColor('positive')):maxwidth(netPageButtonWidth):maxheight(25):zoom(0.85) + end, + BeginCommand=function(self) + self:settext("Next") + end + } + } + } +} +local function netscoreitem(drawindex) + local t = Def.ActorFrame { + Name="scoreItem"..tostring(i), + SetCommand=function(self) + self:visible(nestedTab == 2 and netScores ~= nil and netScores[drawindex + (netScoresCurrentPage-1)*netScoresPerPage] ~= nil) + end, + NetScoreUpdateMessageCommand=function(self) + self:queuecommand("Set") + end, + NestedTabChangedMessageCommand=function(self) + self:queuecommand("Set") + end, + --The main quad + Def.Quad{ + InitCommand=function(self) + self:xy(netscoreframex,netscoreframey+(drawindex*netscorespacing)):zoomto(netscoreframeWidth,30):halign(0):valign(0):diffuse(color("#444444")):diffusealpha(1) + end, + }, + --rank + LoadFont("Common normal")..{ + InitCommand=function(self) + self:xy(netscoreframex-8,netscoreframey+netscorespacing/2+(drawindex*netscorespacing)-2):zoom(0.35) + end, + SetCommand=function(self) + local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage + if netScores[index] then + self:settext(index) + else + self:settext("") + end + end, + NetScoreUpdateMessageCommand=function(self) + self:queuecommand("Set") + end, + BeginCommand=function(self) + self:queuecommand("Set") + end, + }, + --mods + LoadFont("Common normal")..{ + Name="option", + InitCommand=function(self) + self:xy(netscoreframex+10,netscoreframey+10+(drawindex*netscorespacing)+4):zoom(0.35):halign(0):maxwidth((netscoreframeWidth-15)/0.35) + end, + SetCommand=function(self) + local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage + if netScores[index] then + self:settext(netScores[index].modifiers) + else + self:settext("") + end + end, + NetScoreUpdateMessageCommand=function(self) + self:queuecommand("Set") + end, + BeginCommand=function(self) + self:queuecommand("Set") + end, + }, + + --grade text + LoadFont("Common normal")..{ + InitCommand=function(self) + self:xy(netscoreframex+130+capWideScale(get43size(0),50),netscoreframey+2+(drawindex*netscorespacing)):zoom(0.35):halign(0.5):maxwidth((netscoreframeWidth-15)/0.35) + end, + SetCommand=function(self) + local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage + if netScores[index] then + --self:settext(calcGradeFromWife(netScores[index].wife)) + else + self:settext("") + end + end, + NetScoreUpdateMessageCommand=function(self) + self:queuecommand("Set") + end, + BeginCommand=function(self) + self:queuecommand("Set") + end, + }, + --judgment + LoadFont("Common normal")..{ + Name="judge"; + InitCommand=function(self) + self:xy(netscoreframex+10,netscoreframey+(drawindex*netscorespacing)+4):zoom(0.35):halign(0):maxwidth((netscoreframeWidth-15)/0.35) + end, + SetCommand=function(self) + local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage + if netScores[index] then + self:settextf("%05.5f%% (Wife) %d / %d / %d / %d / %d / %d x%d", + netScores[index].wife*10000/100, + netScores[index].marvelous, + netScores[index].perfect, + netScores[index].great, + netScores[index].good, + netScores[index].bad, + netScores[index].miss, + netScores[index].maxcombo) + else + self:settext("") + end + end, + NetScoreUpdateMessageCommand=function(self) + self:queuecommand("Set") + end, + BeginCommand=function(self) + self:queuecommand("Set") + end, + }, + + --date and user + LoadFont("Common normal")..{ + Name="date"; + InitCommand=function(self) + self:xy(netscoreframex+10,netscoreframey+20+(drawindex*netscorespacing)+4):zoom(0.35):halign(0) + end, + SetCommand=function(self) + local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage + if netScores[index] then + self:settext(netScores[index].datetime.." "..netScores[index].username) + else + self:settext("") + end + end, + NetScoreUpdateMessageCommand=function(self) + self:queuecommand("Set") + end, + BeginCommand=function(self) + self:queuecommand("Set") + end, + }, + + } + return t +end +--format example +netTab[#netTab+1] = Def.ActorFrame { + Name="scoreItem"..tostring(i), + SetCommand=function(self) + self:visible(true):y(-10) + end, + --The main quad + Def.Quad{ + InitCommand=function(self) + self:xy(netscoreframex,netscoreframey):zoomto(netscoreframeWidth,30):halign(0):valign(0):diffuse(color("#444444")):diffusealpha(1) + end, + }, + --rank + LoadFont("Common normal")..{ + InitCommand=function(self) + self:xy(netscoreframex-8,netscoreframey+12):zoom(0.35) + end, + SetCommand=function(self) + self:settext("Nth") + end, + }, + --mods + LoadFont("Common normal")..{ + Name="option", + InitCommand=function(self) + self:xy(netscoreframex+10,netscoreframey+14):zoom(0.35):halign(0):maxwidth((netscoreframeWidth-15)/0.35) + end, + SetCommand=function(self) + self:settext("Options") + end, + }, + --judgment + LoadFont("Common normal")..{ + Name="judge"; + InitCommand=function(self) + self:xy(netscoreframex+10,netscoreframey+4):zoom(0.35):halign(0):maxwidth((netscoreframeWidth-15)/0.35) + end, + SetCommand=function(self) + self:settextf("0.0 (Wife) marvelous / perfect / great / good / bad / miss maxcombo") + end, + }, + + --date and user + LoadFont("Common normal")..{ + Name="date"; + InitCommand=function(self) + self:xy(netscoreframex+10,netscoreframey+24):zoom(0.35):halign(0) + end, + SetCommand=function(self) + self:settext("Date User") + end, + }, + + } +for i=1,netScoresPerPage do + netTab[#netTab+1] = netscoreitem(i) +end +ret[#ret+1] = netTab +function nestedTabButton(i) + return + Def.ActorFrame{ + InitCommand=function(self) + self:xy(frameX+offsetX+i*(frameWidth*6/8)/#nestedTabs-nestedTabButtonWidth/2, frameY+offsetY/2) + end, + Def.Quad{ + InitCommand=function(self) + self:zoomto(nestedTabButtonWidth,nestedTabButtonHeight):diffusealpha(0.35):diffuse(getMainColor('frames')) + end, + SetCommand=function(self) + if nestedTab == i then + self:diffusealpha(1) + else + self:diffusealpha(0.35) + end + end, + MouseLeftClickMessageCommand=function(self) + if ButtonActive(self) then + nestedTab = i + MESSAGEMAN:Broadcast("NestedTabChanged") + end + end, + NestedTabChangedMessageCommand=function(self) + self:queuecommand("Set") + end + }, + LoadFont("Common Large") .. { + InitCommand=function(self) + self:diffuse(getMainColor('positive')):maxwidth(nestedTabButtonWidth):maxheight(25):zoom(0.85) + end, + BeginCommand=function(self) + self:settext(nestedTabs[i]) + end + } + } +end +for i=1,#nestedTabs do + ret[#ret+1] = nestedTabButton(i) +end +return ret \ No newline at end of file diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 9a3c33c36a..3c5efc3d14 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -8,6 +8,7 @@ #include "RageLog.h" #include "RageFile.h" #include "DownloadManager.h" +#include "GameState.h" #include "ScoreManager.h" #include "RageFileManager.h" #include "ProfileManager.h" @@ -260,6 +261,7 @@ DownloadManager::DownloadManager() { LUA->Release(L); } CachePackList(packListURL); + RefreshLastVersion(); } DownloadManager::~DownloadManager() @@ -669,7 +671,7 @@ void DownloadManager::EndSession() CURLcode ret = curl_easy_perform(curlHandle); curl_easy_cleanup(curlHandle); session = sessionUser = sessionPass = sessionCookie = ""; - scores.clear(); + topScores.clear(); sessionRatings.clear(); } @@ -713,17 +715,106 @@ void DownloadManager::RefreshUserRank() HTTPRequests.push_back(req); return; } -OnlineScore DownloadManager::GetTopSkillsetScore(unsigned int rank, Skillset ss, bool &result) +OnlineTopScore DownloadManager::GetTopSkillsetScore(unsigned int rank, Skillset ss, bool &result) { unsigned int index = rank - 1; - if (index < scores[ss].size()) { + if (index < topScores[ss].size()) { result = true; - return scores[ss][index]; + return topScores[ss][index]; } result=false; - return OnlineScore(); + return OnlineTopScore(); } +void DownloadManager::SendRequest(string requestName, vector> params, function done , bool requireLogin, bool post, bool async) +{ + if (requireLogin && !LoggedIn()) + return; + string url = serverURL.Get()+ "/" + requestName; + if (!post && !params.empty()) { + url += "?"; + for (auto& param : params) + url += param.first + "=" + param.second + "&"; + url = url.substr(0, url.length() - 1); + } + CURL *curlHandle = initCURLHandle(); + SetCURLURL(curlHandle, url); + HTTPRequest* req; + if (post) { + curl_httppost *form = nullptr; + curl_httppost *lastPtr = nullptr; + for (auto& param : params) + CURLFormPostField(curlHandle, form, lastPtr, param.first.c_str(), param.second.c_str()); + curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); + req = new HTTPRequest(curlHandle, done, form); + } + else { + req = new HTTPRequest(curlHandle, done); + curl_easy_setopt(curlHandle, CURLOPT_HTTPGET, 1L); + } + if (requireLogin) + AddSessionCookieToCURL(curlHandle); + SetCURLResultsString(curlHandle, req->result); + if (async) { + if (mHTTPHandle == nullptr) + mHTTPHandle = curl_multi_init(); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); + } + else { + CURLcode res = curl_easy_perform(req->handle); + curl_easy_cleanup(req->handle); + done(*req); + } + return; +} +void DownloadManager::RequestChartLeaderBoard(string chartkey) +{ + function done = [chartkey](HTTPRequest& req) { + Json::Value json; + RString error; + if (!JsonUtil::LoadFromString(json, req.result, error) || (json.isObject() && json.isMember("error"))) + return; + vector & vec = DLMAN->chartLeaderboards[chartkey]; + vec.clear(); + for (auto it = json.begin(); it != json.end(); ++it) { + OnlineScore tmp; + tmp.wife = atof((*it).get("wifescore", "0.0").asCString()); + tmp.modifiers = (*it).get("modifiers", "").asString(); + tmp.username = (*it).get("username", "").asString(); + tmp.maxcombo = atoi((*it).get("maxcombo", "0").asCString()); + tmp.marvelous = atoi((*it).get("marv", "0").asCString()); + tmp.perfect = atoi((*it).get("perfect", "0").asCString()); + tmp.good = atoi((*it).get("good", "0").asCString()); + tmp.bad = atoi((*it).get("bad", "0").asCString()); + tmp.miss = atoi((*it).get("miss", "0").asCString()); + tmp.minehits = atoi((*it).get("minehits", "0").asCString()); + tmp.held = atoi((*it).get("held", "0").asCString()); + tmp.letgo = atoi((*it).get("letgo", "0").asCString()); + tmp.datetime.FromString((*it).get("datetime", "0").asCString()); + tmp.rate = atof((*it).get("user_chart_rate_rate", "0.0").asCString()); + tmp.nocc = (*it).get("nocc", "0").asBool(); + tmp.valid = (*it).get("valid", "0").asBool(); + FOREACH_ENUM(Skillset, ss) + tmp.SSRs[ss] = atof((*it).get(SkillsetToString(ss).c_str(), "0.0").asCString()); + //todo:replaydata from "replay" field + vec.push_back(tmp); + } + MESSAGEMAN->Broadcast("ChartLeaderboardUpdate"); + }; + SendRequest("chart_leaderboard", {make_pair("chartkey", chartkey)}, done, true); +} +void DownloadManager::RefreshLastVersion() +{ + function done = [this](HTTPRequest& req) { + Json::Value json; + RString error; + if (!JsonUtil::LoadFromString(json, req.result, error) || (json.isObject() && json.isMember("error"))) + return; + this->lastVersion = json.get("version", GAMESTATE->GetEtternaVersion()).asCString(); + }; + SendRequest("client_version", vector>(), done, false, false, false); +} void DownloadManager::RefreshTop25(Skillset ss) { if (!LoggedIn()) @@ -741,9 +832,9 @@ void DownloadManager::RefreshTop25(Skillset ss) LOG->Flush(); if (!JsonUtil::LoadFromString(json, req.result, error) || (json.isObject() && json.isMember("error"))) return; - vector & vec = DLMAN->scores[ss]; + vector & vec = DLMAN->topScores[ss]; for (auto it = json.begin(); it != json.end(); ++it) { - OnlineScore tmp; + OnlineTopScore tmp; tmp.songName = (*it).get("songname", "").asString(); tmp.wifeScore = atof((*it).get("wifescore", "0.0").asCString()); tmp.ssr = atof((*it).get(SkillsetToString(ss), "0.0").asCString()); @@ -835,7 +926,9 @@ void DownloadManager::StartSession(string user, string pass) function done = [user, pass](HTTPRequest& req) { vector v_cookies; - if (req.result == "\"Success\"") { + Json::Value json; + RString error; + if (JsonUtil::LoadFromString(json, req.result, error) && json.get("success", "").asString() == "Valid" && ! json.isMember("error")) { struct curl_slist *cookies; struct curl_slist *cookieIterator; curl_easy_getinfo(req.handle, CURLINFO_COOKIELIST, &cookies); @@ -1117,7 +1210,7 @@ class LunaDownloadManager : public Luna int rank = IArg(1); auto ss = Enum::Check(L, 2); bool result; - OnlineScore onlineScore = DLMAN->GetTopSkillsetScore(rank, ss, result); + auto onlineScore = DLMAN->GetTopSkillsetScore(rank, ss, result); if (!result) { lua_pushnil(L); return 1; @@ -1137,6 +1230,67 @@ class LunaDownloadManager : public Luna lua_setfield(L, -2, "difficulty"); return 1; } + static int GetTopChartScoreCount(T* p, lua_State* L) + { + lua_pushnumber(L, DLMAN->chartLeaderboards[SArg(1)].size()); + return 1; + } + static int GetTopChartScore(T* p, lua_State* L) + { + string chartkey = SArg(1); + unsigned int rank = IArg(2); + bool result; + unsigned int index = rank - 1; + if (!DLMAN->chartLeaderboards.count(chartkey) || index >= DLMAN->chartLeaderboards[chartkey].size()) { + lua_pushnil(L); + return 1; + } + auto& score = DLMAN->chartLeaderboards[chartkey][index]; + if (!result) { + lua_pushnil(L); + return 1; + } + lua_createtable(L, 0, 17 + NUM_Skillset); + FOREACH_ENUM(Skillset, ss) { + lua_pushnumber(L, score.SSRs[ss]); + lua_setfield(L, -2, SkillsetToString(ss).c_str()); + } + lua_pushboolean(L, score.valid); + lua_setfield(L, -2, "valid"); + lua_pushnumber(L, score.rate); + lua_setfield(L, -2, "rate"); + lua_pushnumber(L, score.wife); + lua_setfield(L, -2, "wife"); + lua_pushnumber(L, score.miss); + lua_setfield(L, -2, "miss"); + lua_pushnumber(L, score.marvelous); + lua_setfield(L, -2, "marvelous"); + lua_pushnumber(L, score.perfect); + lua_setfield(L, -2, "perfect"); + lua_pushnumber(L, score.bad); + lua_setfield(L, -2, "bad"); + lua_pushnumber(L, score.good); + lua_setfield(L, -2, "good"); + lua_pushnumber(L, score.great); + lua_setfield(L, -2, "great"); + lua_pushnumber(L, score.maxcombo); + lua_setfield(L, -2, "maxcombo"); + lua_pushnumber(L, score.held); + lua_setfield(L, -2, "held"); + lua_pushnumber(L, score.letgo); + lua_setfield(L, -2, "letgo"); + lua_pushnumber(L, score.minehits); + lua_setfield(L, -2, "minehits"); + lua_pushboolean(L, score.nocc); + lua_setfield(L, -2, "nocc"); + lua_pushstring(L, score.modifiers.c_str()); + lua_setfield(L, -2, "modifiers"); + lua_pushstring(L, score.username.c_str()); + lua_setfield(L, -2, "username"); + lua_pushstring(L, score.datetime.GetString().c_str()); + lua_setfield(L, -2, "datetime"); + return 1; + } static int GetFilteredAndSearchedPackList(T* p, lua_State* L) { if (lua_gettop(L) < 5) { @@ -1176,6 +1330,8 @@ class LunaDownloadManager : public Luna ADD_METHOD(GetSkillsetRank); ADD_METHOD(GetSkillsetRating); ADD_METHOD(GetTopSkillsetScore); + ADD_METHOD(GetTopChartScore); + ADD_METHOD(GetTopChartScoreCount); ADD_METHOD(Logout); } }; diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 4ad14cba43..f83e191990 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -88,7 +88,7 @@ class HTTPRequest { function Done; function Failed; }; -class OnlineScore { +class OnlineTopScore { public: float wifeScore{ 0.0f }; string songName; @@ -100,6 +100,29 @@ class OnlineScore { Difficulty difficulty; string steps; }; +class OnlineScore { +public: + map SSRs; + float rate{ 0.0f }; + float wife{ 0.0f }; + int maxcombo{ 0 }; + int miss{ 0 }; + int bad{ 0 }; + int good{ 0 }; + int great{ 0 }; + int perfect{ 0 }; + int marvelous{ 0 }; + int minehits{ 0 }; + int held{ 0 }; + int letgo{ 0 }; + bool valid{ false }; + bool nocc{ false }; + string username; + float playerRating{ 0.0f }; + string modifiers; + DateTime datetime; + vector> replayData; +}; class DownloadManager { public: @@ -108,15 +131,15 @@ class DownloadManager map downloads; vector HTTPRequests; map finishedDownloads; - CURLM* mPackHandle{nullptr}; + CURLM* mPackHandle{ nullptr }; CURLM* mHTTPHandle{ nullptr }; CURLMcode ret; - int downloadingPacks{0}; - int HTTPRunning{ 0 }; + int downloadingPacks{ 0 }; + int HTTPRunning{ 0 }; bool loggingIn{ false }; - bool gameplay{false}; - string error{""}; - int lastid{0}; + bool gameplay{ false }; + string error{ "" }; + int lastid{ 0 }; string sessionCookie{ "" }; vector downloadablePacks; bool reloadPending{ false }; @@ -124,6 +147,8 @@ class DownloadManager string session{ "" }; string sessionUser{ "" }; string sessionPass{ "" }; + string lastVersion{""}; + map> chartLeaderboards; double sessionRating{ 0.0 }; map sessionRanks; bool LoggedIn(); @@ -160,12 +185,15 @@ class DownloadManager inline void SetCURLPostToURL(CURL *curlHandle, string url); inline void SetCURLURL(CURL *curlHandle, string url); + void SendRequest(string requestName, vector> params, function done, bool requireLogin = true, bool post = false, bool async = true); + void RefreshLastVersion(); + void RequestChartLeaderBoard(string chartkey); void RefreshUserData(); void RefreshUserRank(); void RefreshTop25(Skillset ss); map sessionRatings; - map> scores; - OnlineScore GetTopSkillsetScore(unsigned int rank, Skillset ss, bool &result); + map> topScores; + OnlineTopScore GetTopSkillsetScore(unsigned int rank, Skillset ss, bool &result); float GetSkillsetRating(Skillset ss); int GetSkillsetRank(Skillset ss); diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 579ced4918..565f93e2c1 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -33,6 +33,7 @@ #include "RageFileManager.h" #include "ScreenTextEntry.h" #include "ProfileManager.h" +#include "DownloadManager.h" static const char *SelectionStateNames[] = { "SelectingSong", @@ -1451,6 +1452,7 @@ void ScreenSelectMusic::AfterStepsOrTrailChange(const vector &vpns } m_textHighScore[pn].SetText(ssprintf("%*i", NUM_SCORE_DIGITS, iScore)); + DLMAN->RequestChartLeaderBoard(pSteps->GetChartKey()); } else {