From 39dd6b9822980158457b4d4c5b2846ac25ca9e37 Mon Sep 17 00:00:00 2001 From: Nickito12 Date: Mon, 27 Nov 2017 19:42:33 -0300 Subject: [PATCH] Add new server API things and make some HTTP requests use the multi interface --- .../downloads.lua | 26 +- .../ScreenSelectMusic decorations/profile.lua | 278 ++++++++--- .../ScreenSelectMusic decorations/tabs.lua | 5 +- Themes/Til Death/BGAnimations/_PlayerInfo.lua | 21 +- src/DownloadManager.cpp | 467 ++++++++++++++---- src/DownloadManager.h | 51 +- 6 files changed, 666 insertions(+), 182 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/downloads.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/downloads.lua index 9b3987cbb6..ddd869b209 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/downloads.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/downloads.lua @@ -43,7 +43,7 @@ end local numbershers = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"} local englishes = {"a", "b", "c", "d", "e","f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",";"} local function DlInput(event) - if event.type ~= "InputEventType_Release" and update then + if event.type ~= "InputEventType_Release" and update and inputting ~= 0 then local changed = false if event.button == "Start" then curInput = "" @@ -53,8 +53,9 @@ local function DlInput(event) if currentpage > numpages or currentpage < 1 then currentpage = 1 end + MESSAGEMAN:Broadcast("UpdatePacks") MESSAGEMAN:Broadcast("DlInputEnded") - SCREENMAN:set_input_redirected(PLAYER_1, false) + MESSAGEMAN:Broadcast("NumericInputEnded") return true elseif event.button == "Back" then curInput = "" @@ -66,8 +67,9 @@ local function DlInput(event) filters[inputting] = curInput inputting = 0 packlist = DLMAN:GetFilteredAndSearchedPackList(tostring(filters[1]), tonumber(filters[2]), tonumber(filters[3]), tonumber(filters[4]*1024*1024), tonumber(filters[5]*1024*1024)) + MESSAGEMAN:Broadcast("UpdatePacks") MESSAGEMAN:Broadcast("DlInputEnded") - SCREENMAN:set_input_redirected(PLAYER_1, false) + MESSAGEMAN:Broadcast("NumericInputEnded") return true elseif event.DeviceInput.button == "DeviceButton_backspace" then curInput = curInput:sub(1, -2) @@ -118,11 +120,13 @@ local t = Def.ActorFrame{ self:bouncebegin(0.2):xy(0,0):diffusealpha(1) end, MouseRightClickMessageCommand=function(self) - inputting = 0 - curInput = 0 - MESSAGEMAN:Broadcast("DlInputEnded") - MESSAGEMAN:Broadcast("UpdatePacks") - SCREENMAN:set_input_redirected(PLAYER_1, false) + if update == true then + inputting = 0 + curInput = 0 + MESSAGEMAN:Broadcast("DlInputEnded") + MESSAGEMAN:Broadcast("NumericInputEnded") + MESSAGEMAN:Broadcast("UpdatePacks") + end end, SetCommand=function(self) self:finishtweening() @@ -312,6 +316,7 @@ local function numFilter(i,x,y) inputting = i curInput = "" MESSAGEMAN:Broadcast("DlInputActive") + MESSAGEMAN:Broadcast("NumericInputActive") self:diffusealpha(0.1) SCREENMAN:set_input_redirected(PLAYER_1, true) end @@ -376,6 +381,7 @@ filters[#filters+1] = Def.ActorFrame{ inputting = 2 curInput = "" MESSAGEMAN:Broadcast("DlInputActive") + MESSAGEMAN:Broadcast("NumericInputActive") self:diffusealpha(0.1) SCREENMAN:set_input_redirected(PLAYER_1, true) end @@ -425,6 +431,7 @@ filters[#filters+1] = Def.ActorFrame{ inputting=3 curInput = "" MESSAGEMAN:Broadcast("DlInputActive") + MESSAGEMAN:Broadcast("NumericInputActive") self:diffusealpha(0.1) SCREENMAN:set_input_redirected(PLAYER_1, true) end @@ -482,6 +489,7 @@ filters[#filters+1] = Def.ActorFrame{ inputting = 4 curInput = "" MESSAGEMAN:Broadcast("DlInputActive") + MESSAGEMAN:Broadcast("NumericInputActive") self:diffusealpha(0.1) SCREENMAN:set_input_redirected(PLAYER_1, true) end @@ -531,6 +539,7 @@ filters[#filters+1] = Def.ActorFrame{ inputting=5 curInput = "" MESSAGEMAN:Broadcast("DlInputActive") + MESSAGEMAN:Broadcast("NumericInputActive") self:diffusealpha(0.1) SCREENMAN:set_input_redirected(PLAYER_1, true) end @@ -580,6 +589,7 @@ filters[#filters+1] = Def.ActorFrame{ inputting=1 curInput = "" MESSAGEMAN:Broadcast("DlInputActive") + MESSAGEMAN:Broadcast("NumericInputActive") self:diffusealpha(0.1) SCREENMAN:set_input_redirected(PLAYER_1, true) end diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/profile.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/profile.lua index 432fe5823e..b8b8a389ad 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/profile.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/profile.lua @@ -1,4 +1,10 @@ local update = false +local showOnline = false +local function BroadcastIfActive(msg) + if update then + MESSAGEMAN:Broadcast(msg) + end +end local t = Def.ActorFrame{ BeginCommand=function(self) self:queuecommand("Set"):visible(false) @@ -20,6 +26,19 @@ local t = Def.ActorFrame{ update = false end end, + LogOutMessageCommand=function(self) + showOnline = false + BroadcastIfActive("UpdateRanking") + end, + LoginMessageCommand=function(self) + BroadcastIfActive("UpdateRanking") + end, + LoginFailedMessageCommand=function(self) + BroadcastIfActive("UpdateRanking") + end, + OnlineUpdateMessageCommand=function(self) + BroadcastIfActive("UpdateRanking") + end, TabChangedMessageCommand=function(self) self:queuecommand("Set") end, @@ -56,14 +75,7 @@ end t[#t+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')):settext("Profile Info (WIP)") - end -} + local function byValidity(valid) @@ -73,11 +85,6 @@ local function byValidity(valid) return byJudgment("TapNoteScore_Miss") end -local function BroadcastIfActive(msg) - if update then - MESSAGEMAN:Broadcast(msg) - end -end local function ButtonActive(self) return isOver(self) and update @@ -99,6 +106,7 @@ local function rankingLabel(i) local thssteps local thssong local xoffset + local onlineScore local t = Def.ActorFrame{ InitCommand=function(self) @@ -108,15 +116,26 @@ local function rankingLabel(i) end, UpdateRankingMessageCommand=function(self) if rankingSkillset > 1 and update then - ths = SCOREMAN:GetTopSSRHighScore(i+(scoresperpage*(rankingPage-1)), ms.SkillSets[rankingSkillset]) - if ths then - self:visible(true) - ck = ths:GetChartKey() - thssong = SONGMAN:GetSongByChartKey(ck) - thssteps = SONGMAN:GetStepsByChartKey(ck) + if not showOnline then + ths = SCOREMAN:GetTopSSRHighScore(i+(scoresperpage*(rankingPage-1)), ms.SkillSets[rankingSkillset]) + if ths then + self:visible(true) + ck = ths:GetChartKey() + thssong = SONGMAN:GetSongByChartKey(ck) + thssteps = SONGMAN:GetStepsByChartKey(ck) + MESSAGEMAN:Broadcast("DisplayProfileRankingLabels") + end + else + onlineScore = DLMAN:GetTopSkillsetScore(i, ms.SkillSets[rankingSkillset]) MESSAGEMAN:Broadcast("DisplayProfileRankingLabels") + if not onlineScore then + self:visible(false) + else + self:visible(true) + end end else + onlinesScore = nil self:visible(false) end end, @@ -126,10 +145,16 @@ local function rankingLabel(i) self:maxwidth(100) end, DisplayProfileRankingLabelsMessageCommand=function(self) - if ths then + if not showOnline then + if ths then + self:halign(0.5) + self:settext(((rankingPage-1)*25)+i..".") + self:diffuse(byValidity(ths:GetEtternaValid())) + end + else self:halign(0.5) - self:settext(((rankingPage-1)*25)+i..".") - self:diffuse(byValidity(ths:GetEtternaValid())) + self:settext(i..".") + self:diffuse(getMainColor('positive')) end end }, @@ -139,9 +164,14 @@ local function rankingLabel(i) self:x(15):maxwidth(160) end, DisplayProfileRankingLabelsMessageCommand=function(self) - if ths then - self:settextf("%5.2f", ths:GetSkillsetSSR(ms.SkillSets[rankingSkillset])) - self:diffuse(byValidity(ths:GetEtternaValid())) + if not showOnline then + if ths then + self:settextf("%5.2f", ths:GetSkillsetSSR(ms.SkillSets[rankingSkillset])) + self:diffuse(byValidity(ths:GetEtternaValid())) + end + elseif onlineScore then + self:settextf("%5.2f", onlineScore.ssr) + self:diffuse(getMainColor('positive')) end end }, @@ -151,9 +181,14 @@ local function rankingLabel(i) self:x(55):maxwidth(580) end, DisplayProfileRankingLabelsMessageCommand=function(self) - if thssong then - self:settext(thssong:GetDisplayMainTitle()) - self:diffuse(byValidity(ths:GetEtternaValid())) + if not showOnline then + if thssong then + self:settext(thssong:GetDisplayMainTitle()) + self:diffuse(byValidity(ths:GetEtternaValid())) + end + elseif onlineScore then + self:settext(onlineScore.songName) + self:diffuse(getMainColor('positive')) end end }, @@ -163,11 +198,18 @@ local function rankingLabel(i) self:x(220) end, DisplayProfileRankingLabelsMessageCommand=function(self) - if ths then + if not showOnline then + if ths then + self:halign(0.5) + local ratestring = string.format("%.2f", ths:GetMusicRate()):gsub("%.?0+$", "").."x" + self:settext(ratestring) + self:diffuse(byValidity(ths:GetEtternaValid())) + end + elseif onlineScore then + local ratestring = string.format("%.2f", onlineScore.rate):gsub("%.?0+$", "").."x" self:halign(0.5) - local ratestring = string.format("%.2f", ths:GetMusicRate()):gsub("%.?0+$", "").."x" self:settext(ratestring) - self:diffuse(byValidity(ths:GetEtternaValid())) + self:diffuse(getMainColor('positive')) end end }, @@ -177,13 +219,18 @@ local function rankingLabel(i) self:x(240):maxwidth(160) end, DisplayProfileRankingLabelsMessageCommand=function(self) - if ths then - self:settextf("%5.2f%%", ths:GetWifeScore()*100) - if not ths:GetEtternaValid() then - self:diffuse(byJudgment("TapNoteScore_Miss")) - else - self:diffuse(getGradeColor(ths:GetWifeGrade())) + if not showOnline then + if ths then + self:settextf("%5.2f%%", ths:GetWifeScore()*100) + if not ths:GetEtternaValid() then + self:diffuse(byJudgment("TapNoteScore_Miss")) + else + self:diffuse(getGradeColor(ths:GetWifeGrade())) + end end + elseif onlineScore then + self:settextf("%5.2f%%", onlineScore.wife*100) + self:diffuse(getGradeColor("Grade_Tier03")) end end }, @@ -193,6 +240,7 @@ local function rankingLabel(i) self:x(300) end, DisplayProfileRankingLabelsMessageCommand=function(self) + self:visible(not showOnline) if thssteps then local diff = thssteps:GetDifficulty() self:halign(0.5) @@ -211,7 +259,7 @@ local function rankingLabel(i) self:zoomto(300,scoreYspacing) end, MouseRightClickMessageCommand=function(self) - if ths and ButtonActive(self) then + if not showOnline and ths and ButtonActive(self) then ths:ToggleEtternaValidation() BroadcastIfActive("UpdateRanking") if ths:GetEtternaValid() then @@ -222,8 +270,17 @@ local function rankingLabel(i) end end, MouseLeftClickMessageCommand=function(self) - if ths and ButtonActive(self) then - whee:SelectSong(thssong) + if rankingSkillset>1 and ths and ButtonActive(self) then + if not showOnline then + if ths then + whee:SelectSong(thssong) + end + elseif onlineScore and onlineScore.chartkey then + local song = SONGMAN:GetSongByChartKey(onlineScore.chartkey) + if song then + whee:SelectSong(song) + end + end end end } @@ -275,13 +332,115 @@ local function rankingButton(i) return t end +t[#t+1]= Def.ActorFrame { + InitCommand=function(self) + if DLMAN:IsLoggedIn() then + self:visible(true) + else + self:visible(false) + end + end, + SetCommand=function(self) + if DLMAN:IsLoggedIn() then + self:visible(true) + else + self:visible(false) + end + end, + UpdateRankingMessageCommand=function(self) + self:queuecommand("Set") + end, + Def.ActorFrame { + InitCommand=function(self) + self:xy(rankingX + frameWidth/4-rankingTitleSpacing, rankingY+offsetY*0.9) + end, + Def.Quad{ + InitCommand=function(self) + self:zoomto(rankingTitleSpacing,offsetY):diffusealpha(0.35) + if DLMAN:IsLoggedIn() then + self:diffuse(getMainColor('frames')) + if showOnline then + self:diffusealpha(1) + else + self:diffusealpha(0.35) + end + else + self:diffuse(getMainColor('disabled')):diffusealpha(0.1) + end + end, + SetCommand=function(self) + if DLMAN:IsLoggedIn() then + self:diffuse(getMainColor('frames')) + if showOnline then + self:diffusealpha(1) + else + self:diffusealpha(0.35) + end + else + self:diffuse(getMainColor('disabled')):diffusealpha(0.1) + end + end, + MouseLeftClickMessageCommand=function(self) + if ButtonActive(self) and DLMAN:IsLoggedIn() then + showOnline = true + BroadcastIfActive("UpdateRanking") + end + end, + UpdateRankingMessageCommand=function(self) + self:queuecommand("Set") + end + }, + LoadFont("Common Large") .. { + InitCommand=function(self) + self:diffuse(getMainColor('positive')):maxwidth(rankingTitleSpacing):maxheight(25):zoom(0.85) + end, + BeginCommand=function(self) + self:settext("Online") + end, + } + }, + Def.ActorFrame{ + InitCommand=function(self) + self:xy(rankingX + frameWidth*3/4-rankingTitleSpacing, rankingY+offsetY*0.9) + end, + Def.Quad{ + InitCommand=function(self) + self:zoomto(rankingTitleSpacing,offsetY):diffusealpha(0.35):diffuse(getMainColor('frames')) + end, + SetCommand=function(self) + if not showOnline then + self:diffusealpha(1) + else + self:diffusealpha(0.35) + end + end, + MouseLeftClickMessageCommand=function(self) + if ButtonActive(self) then + showOnline = false + BroadcastIfActive("UpdateRanking") + end + end, + UpdateRankingMessageCommand=function(self) + self:queuecommand("Set") + end + }, + LoadFont("Common Large") .. { + InitCommand=function(self) + self:diffuse(getMainColor('positive')):maxwidth(rankingTitleSpacing):maxheight(25):zoom(0.85) + end, + BeginCommand=function(self) + self:settext("Local") + end + } + } +} -- prev/next page r[#r+1] = Def.ActorFrame{ InitCommand=function(self) self:xy( 10, frameHeight - offsetY):visible(false) end, UpdateRankingMessageCommand=function(self) - if rankingSkillset > 1 then + if rankingSkillset > 1 and not showOnline then self:visible(true) if not self and self.GetChildren then for child in self:GetChildren() do @@ -377,10 +536,18 @@ local function littlebits(i) self:xy(240,22*i):halign(1):zoom(0.5) end, SetCommand=function(self) - local rating = profile:GetPlayerSkillsetRating(ms.SkillSets[i]) + local rating = 0 + if not showOnline then + rating = profile:GetPlayerSkillsetRating(ms.SkillSets[i]) + else + rating = DLMAN:GetSkillsetRating(ms.SkillSets[i]) + end self:settextf("%5.2f",rating) self:diffuse(ByMSD(rating)) - end + end, + UpdateRankingMessageCommand=function(self) + self:queuecommand("Set") + end, } } return t @@ -480,12 +647,11 @@ local profilebuttons = Def.ActorFrame{ end }, LoadFont("Common Large") .. { - LoggedInMessageCommand=function(self) - if DLMAN:IsLoggedIn() then - self:settext("Logout") - else - self:settext("Login") - end + LogOutMessageCommand=function(self) + self:settext("Login") + end, + LoginMessageCommand=function(self) + self:settext("Logout") end, InitCommand=function(self) if DLMAN:IsLoggedIn() then @@ -500,6 +666,12 @@ local profilebuttons = Def.ActorFrame{ InitCommand=function(self) self:x(300):zoomto(110,20):diffusealpha(buttondiffuse) end, + LoginFailedMessageCommand=function(self) + ms.ok("Login failed!") + end, + LoginMessageCommand=function(self) + ms.ok("Succesfully logged in") + end, MouseLeftClickMessageCommand=function(self) if ButtonActive(self) and rankingSkillset == 1 then if not DLMAN:IsLoggedIn() then @@ -508,18 +680,12 @@ local profilebuttons = Def.ActorFrame{ end password = function(answer) pass=answer - if DLMAN:Login(user, pass) then - ms.ok("Succesfully logged in") - else - ms.ok("Login failed!") - end - MESSAGEMAN:Broadcast("LoggedIn") + DLMAN:Login(user, pass) end easyInputStringWithFunction("Password:", 50, true, password) easyInputStringWithFunction("Username:",50, false, username) else DLMAN:Logout() - MESSAGEMAN:Broadcast("LoggedIn") end end end diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua index 6531cc4373..1e731ab14f 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua @@ -1,6 +1,5 @@ local active = true local numericinputactive = false -local packinputactive = false local whee local tabNames = {"General","MSD","Score","Search","Profile","Filters", "Goals", "Playlists", "Packs"} -- this probably should be in tabmanager. @@ -9,7 +8,7 @@ local tabNames = {"General","MSD","Score","Search","Profile","Filters", "Goals", ]] local function input(event) if event.type ~= "InputEventType_Release" and active then - if numericinputactive == false and packinputactive == false then + if numericinputactive == false then for i=1,#tabNames do if not (INPUTFILTER:IsBeingPressed("left ctrl") or INPUTFILTER:IsBeingPressed("right ctrl") or IsNetSMOnline()) and event.char and tonumber(event.char) and tonumber(event.char)==i then setTabIndex(i-1) @@ -37,8 +36,6 @@ local t = Def.ActorFrame{ EndingSearchMessageCommand=function(self) active = true end, NumericInputActiveMessageCommand=function(self) numericinputactive = true end, NumericInputEndedMessageCommand=function(self) numericinputactive = false end, - DlInputActiveMessageCommand=function(self) packinputactive = true end, - DlInputEndedMessageCommand=function(self) packinputactive = false end, } -- Just for debug diff --git a/Themes/Til Death/BGAnimations/_PlayerInfo.lua b/Themes/Til Death/BGAnimations/_PlayerInfo.lua index b3c6781de8..73f864710a 100644 --- a/Themes/Til Death/BGAnimations/_PlayerInfo.lua +++ b/Themes/Til Death/BGAnimations/_PlayerInfo.lua @@ -75,7 +75,7 @@ t[#t+1] = Def.ActorFrame{ }, LoadFont("Common Normal") .. { InitCommand=function(self) - self:xy(AvatarX+53,AvatarY+7):halign(0):zoom(0.6):diffuse(getMainColor('positive')) + self:xy(AvatarX+53,AvatarY+7):maxwidth(200):halign(0):zoom(0.6):diffuse(getMainColor('positive')) end, BeginCommand=function(self) self:queuecommand("Set") @@ -90,6 +90,25 @@ t[#t+1] = Def.ActorFrame{ self:queuecommand("Set") end, }, + LoadFont("Common Normal") .. { + InitCommand=function(self) + self:xy(SCREEN_CENTER_X+100,AvatarY+40):halign(0):zoom(0.35):diffuse(getMainColor('positive')) + if DLMAN:IsLoggedIn() then + self:settextf("Logged in as %s (#%i)",DLMAN:GetUsername(),DLMAN:GetUserRank()) + else + self:settext("Not logged in") + end + end, + BeginCommand=function(self) + self:queuecommand("Set") + end, + LogOutMessageCommand=function(self) + self:settext("Not logged in") + end, + LogInMessageCommand=function(self) + self:settextf("Logged in as %s (#%i)",DLMAN:GetUsername(),DLMAN:GetUserRank()) + end, + }, LoadFont("Common Normal") .. { InitCommand=function(self) self:xy(AvatarX+53,AvatarY+20):halign(0):zoom(0.35):diffuse(getMainColor('positive')) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index cf632fa5a1..e38c58af72 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -84,11 +84,14 @@ int ReadThisSeekCallback(void *arg, curl_off_t offset, int origin) return static_cast(arg)->file.Seek(offset, origin); } -void DownloadManager::InstallSmzip(const string &sZipFile) +bool DownloadManager::InstallSmzip(const string &sZipFile) { if (!FILEMAN->Mount("zip", sZipFile, TEMP_ZIP_MOUNT_POINT)) FAIL_M(static_cast("Failed to mount " + sZipFile).c_str()); - + vector v_packs; + GetDirListing(TEMP_ZIP_MOUNT_POINT + "*", v_packs, true, true); + if (v_packs.size() > 1) + return false; vector vsFiles; { vector vsRawFiles; @@ -107,7 +110,6 @@ void DownloadManager::InstallSmzip(const string &sZipFile) } sort(vsPrettyFiles.begin(), vsPrettyFiles.end()); } - string sResult = "Success installing " + sZipFile; FOREACH_CONST(string, vsFiles, sSrcFile) { @@ -129,6 +131,7 @@ void DownloadManager::InstallSmzip(const string &sZipFile) SCREENMAN->SystemMessage(sResult); + return true; } @@ -198,11 +201,15 @@ inline void SetCURLResultsString(CURL *curlHandle, string& str) curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, &str); curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, write_memory_buffer); } -inline void DownloadManager::SetCURLPostToURL(CURL *curlHandle, string url) +inline void DownloadManager::SetCURLURL(CURL *curlHandle, string url) { checkProtocol(url); EncodeSpaces(url); curl_easy_setopt(curlHandle, CURLOPT_URL, url.c_str()); +} +inline void DownloadManager::SetCURLPostToURL(CURL *curlHandle, string url) +{ + SetCURLURL(curlHandle, url); curl_easy_setopt(curlHandle, CURLOPT_POST, 1L); } void CURLFormPostField(CURL* curlHandle, curl_httppost *&form, curl_httppost *&lastPtr, const char* field, const char* value) @@ -245,9 +252,12 @@ DownloadManager::DownloadManager() { DownloadManager::~DownloadManager() { - if (mHandle != nullptr) - curl_multi_cleanup(mHandle); - mHandle = nullptr; + if (mPackHandle != nullptr) + curl_multi_cleanup(mPackHandle); + mPackHandle = nullptr; + if (mHTTPHandle != nullptr) + curl_multi_cleanup(mHTTPHandle); + mHTTPHandle = nullptr; for (auto &dl : downloads) { if (dl.second->handle != nullptr) { curl_easy_cleanup(dl.second->handle); @@ -256,20 +266,22 @@ DownloadManager::~DownloadManager() delete dl.second; } curl_global_cleanup(); + if (LoggedIn()) + EndSessionIfExists(); } Download* DownloadManager::DownloadAndInstallPack(const string &url) { Download* dl = new Download(url); - if (mHandle == nullptr) - mHandle = curl_multi_init(); - curl_multi_add_handle(mHandle, dl->handle); + if (mPackHandle == nullptr) + mPackHandle = curl_multi_init(); + curl_multi_add_handle(mPackHandle, dl->handle); downloads[url] = dl; UpdateDLSpeed(); - ret = curl_multi_perform(mHandle, &running); + ret = curl_multi_perform(mPackHandle, &downloadingPacks); SCREENMAN->SystemMessage(dl->StartMessage()); return dl; @@ -336,6 +348,76 @@ Download* DownloadManager::DownloadAndInstallPack(DownloadablePack* pack) } bool DownloadManager::UpdateAndIsFinished(float fDeltaSeconds) +{ + bool packs = UpdatePacksAndIsFinished(fDeltaSeconds); + bool http = UpdateHTTPAndIsFinished(fDeltaSeconds); + return packs && http; +} +bool DownloadManager::UpdateHTTPAndIsFinished(float fDeltaSeconds) +{ + if (!HTTPRunning && HTTPRequests.size() == 0) + return true; + timeval timeout; + int rc, maxfd = -1; + CURLMcode mc; + fd_set fdread, fdwrite, fdexcep; + long curl_timeo = -1; + FD_ZERO(&fdread); + FD_ZERO(&fdwrite); + FD_ZERO(&fdexcep); + timeout.tv_sec = 0; + timeout.tv_usec = 1; + curl_multi_timeout(mHTTPHandle, &curl_timeo); + + mc = curl_multi_fdset(mHTTPHandle, &fdread, &fdwrite, &fdexcep, &maxfd); + if (mc != CURLM_OK) { + error = "curl_multi_fdset() failed, code " + mc; + return false; + } + if (maxfd == -1) { + rc = 0; + } + else { + rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); + } + switch (rc) { + case -1: + error = "select error" + mc; + break; + case 0: /* timeout */ + default: /* action */ + curl_multi_perform(mHTTPHandle, &HTTPRunning); + break; + } + + //Check for finished downloads + CURLMsg *msg; + int msgs_left; + while (msg = curl_multi_info_read(mHTTPHandle, &msgs_left)) { + /* Find out which handle this message is about */ + for (int i = 0; i < HTTPRequests.size();++i) { + if (msg->easy_handle == HTTPRequests[i]->handle) { + if (msg->msg == CURLMSG_DONE) { + HTTPRequests[i]->Done(*(HTTPRequests[i])); + } + else { + HTTPRequests[i]->Failed(*(HTTPRequests[i])); + } + if (HTTPRequests[i]->handle != nullptr) + curl_easy_cleanup(HTTPRequests[i]->handle); + HTTPRequests[i]->handle = nullptr; + if (HTTPRequests[i]->form != nullptr) + curl_formfree(HTTPRequests[i]->form); + HTTPRequests[i]->form = nullptr; + delete HTTPRequests[i]; + HTTPRequests.erase(HTTPRequests.begin()+i); + break; + } + } + } + return false; +} +bool DownloadManager::UpdatePacksAndIsFinished(float fDeltaSeconds) { if (reloadPending && !gameplay) { auto screen = SCREENMAN->GetScreen(0); @@ -345,7 +427,7 @@ bool DownloadManager::UpdateAndIsFinished(float fDeltaSeconds) SONGMAN->DifferentialReload(); reloadPending = false; } - if (!running) + if (!downloadingPacks) return true; timeval timeout; int rc, maxfd = -1; @@ -357,9 +439,9 @@ bool DownloadManager::UpdateAndIsFinished(float fDeltaSeconds) FD_ZERO(&fdexcep); timeout.tv_sec = 0; timeout.tv_usec = 1; - curl_multi_timeout(mHandle, &curl_timeo); + curl_multi_timeout(mPackHandle, &curl_timeo); - mc = curl_multi_fdset(mHandle, &fdread, &fdwrite, &fdexcep, &maxfd); + mc = curl_multi_fdset(mPackHandle, &fdread, &fdwrite, &fdexcep, &maxfd); if (mc != CURLM_OK) { error = "curl_multi_fdset() failed, code " + mc; return false; @@ -376,7 +458,7 @@ bool DownloadManager::UpdateAndIsFinished(float fDeltaSeconds) break; case 0: /* timeout */ default: /* action */ - curl_multi_perform(mHandle, &running); + curl_multi_perform(mPackHandle, &downloadingPacks); for (auto &dl : downloads) dl.second->Update(fDeltaSeconds); break; @@ -386,7 +468,7 @@ bool DownloadManager::UpdateAndIsFinished(float fDeltaSeconds) CURLMsg *msg; int msgs_left; bool addedPacks = false; - while (msg = curl_multi_info_read(mHandle, &msgs_left)) { + while (msg = curl_multi_info_read(mPackHandle, &msgs_left)) { /* Find out which handle this message is about */ for (auto i = downloads.begin(); i != downloads.end(); i++) { if (msg->easy_handle == i->second->handle) { @@ -434,13 +516,6 @@ bool DownloadManager::LoggedIn() { return !session.empty(); } -bool DownloadManager::LoginAndUploadProfile(string file, string profileName, string user, string pass) -{ - if (user != sessionUser || pass != sessionPass) - if (!StartSession(user, pass)) - return false; - return UploadProfile(file, profileName); -} bool DownloadManager::UploadProfile(string file, string profileName) { @@ -463,6 +538,7 @@ bool DownloadManager::UploadProfile(string file, string profileName) curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); CURLcode ret = curl_easy_perform(curlHandle); curl_easy_cleanup(curlHandle); + curl_formfree(form); if (result != "\"Success\"") { LOG->Trace(result.c_str()); return false; @@ -474,15 +550,8 @@ bool DownloadManager::ShouldUploadScores() { return LoggedIn() && automaticSync; } -bool DownloadManager::UploadScore(HighScore* hs) +inline void SetCURLPOSTScore(CURL* curlHandle, curl_httppost* form, curl_httppost* lastPtr, HighScore* hs) { - if (!LoggedIn()) - return false; - CURL *curlHandle = initCURLHandle(); - string url = serverURL.Get() + "/upload_score"; - curl_httppost *form = nullptr; - curl_httppost *lastPtr = nullptr; - curl_slist *headerlist = nullptr; SetCURLFormPostField(curlHandle, form, lastPtr, "scorekey", hs->GetScoreKey()); FOREACH_ENUM(Skillset, ss) SetCURLFormPostField(curlHandle, form, lastPtr, SkillsetToString(ss), hs->GetSkillsetSSR(ss)); @@ -506,6 +575,16 @@ bool DownloadManager::UploadScore(HighScore* hs) SetCURLFormPostField(curlHandle, form, lastPtr, "cc", static_cast(!hs->GetChordCohesion())); SetCURLFormPostField(curlHandle, form, lastPtr, "calc_version", hs->GetSSRCalcVersion()); SetCURLFormPostField(curlHandle, form, lastPtr, "topscore", hs->GetTopScore()); +} +void DownloadManager::UploadScore(HighScore* hs) +{ + if (!LoggedIn()) + return; + CURL *curlHandle = initCURLHandle(); + string url = serverURL.Get() + "/upload_score"; + curl_httppost *form = nullptr; + curl_httppost *lastPtr = nullptr; + SetCURLPOSTScore(curlHandle, form, lastPtr, hs); string replayString = "["; vector timestamps = hs->timeStamps; vector offsets = hs->GetOffsetVector(); @@ -517,35 +596,55 @@ bool DownloadManager::UploadScore(HighScore* hs) SetCURLFormPostField(curlHandle, form, lastPtr, "replay_data", replayString); SetCURLPostToURL(curlHandle, url); AddSessionCookieToCURL(curlHandle); - string result; - SetCURLResultsString(curlHandle, result); curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); - CURLcode ret = curl_easy_perform(curlHandle); - curl_easy_cleanup(curlHandle); - if (result != "\"Success\"") { - LOG->Trace(result.c_str()); - return false; + HTTPRequest* req = new HTTPRequest(curlHandle); + SetCURLResultsString(curlHandle, req->result); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); + return; +} +void DownloadManager::UploadScoreWithReplayData(HighScore* hs) +{ + if (!LoggedIn()) + return; + CURL *curlHandle = initCURLHandle(); + string url = serverURL.Get() + "/upload_score"; + curl_httppost *form = nullptr; + curl_httppost *lastPtr = nullptr; + curl_slist *headerlist = nullptr; + SetCURLPOSTScore(curlHandle, form, lastPtr, hs); + string replayString = "["; + vector timestamps = hs->timeStamps; + vector offsets = hs->GetOffsetVector(); + for (int i = 0; i < offsets.size(); i++) { + replayString += "[" + to_string(timestamps[i]) + "," + to_string(1000.f * offsets[i]) + "],"; } - - mostrecentresult = result; - - return ret == 0; + replayString = replayString.substr(0, replayString.size() - 1); //remove "," + replayString += "]"; + SetCURLFormPostField(curlHandle, form, lastPtr, "replay_data", replayString); + SetCURLPostToURL(curlHandle, url); + AddSessionCookieToCURL(curlHandle); + curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); + HTTPRequest* req = new HTTPRequest(curlHandle); + SetCURLResultsString(curlHandle, req->result); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); + return; } void DownloadManager::EndSessionIfExists() { if (!LoggedIn()) return; - string url = serverURL.Get() +"/destroy"; + string url = serverURL.Get() + "/destroy"; CURL *curlHandle = initCURLHandle(); - SetCURLPostToURL(curlHandle, url); - AddSessionCookieToCURL(curlHandle); - CURLcode ret = curl_easy_perform(curlHandle); - curl_easy_cleanup(curlHandle); session = sessionUser = sessionPass = sessionCookie = ""; + scores.clear(); + sessionRatings.clear(); + MESSAGEMAN->Broadcast("LogOut"); } std::vector split(const std::string& s, char delimiter) @@ -559,7 +658,107 @@ std::vector split(const std::string& s, char delimiter) } return tokens; } - +// User rank +void DownloadManager::RefreshUserRank() +{ + if (!LoggedIn()) + return; + string url = serverURL.Get() + "/user_rank"; + CURL *curlHandle = initCURLHandle(); + url += "?username=" + sessionUser; + SetCURLURL(curlHandle, url); + function done = [](HTTPRequest& req) { + Json::Value json; + RString error; + if (!JsonUtil::LoadFromString(json, req.result, error)) { + DLMAN->sessionRank = 0; + return; + } + DLMAN->sessionRank = atoi(json.get("rank", "error").asString().c_str()); + MESSAGEMAN->Broadcast("OnlineUpdate"); + }; + HTTPRequest* req = new HTTPRequest(curlHandle, done); + SetCURLResultsString(curlHandle, req->result); + AddSessionCookieToCURL(curlHandle); + curl_easy_setopt(curlHandle, CURLOPT_HTTPGET, 1L); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); + return; +} +OnlineScore DownloadManager::GetTopSkillsetScore(unsigned int rank, Skillset ss, bool &result) +{ + unsigned int index = rank - 1; + if (index < scores[ss].size()) { + result = true; + return scores[ss][index]; + } + result=false; + return OnlineScore(); +} +void DownloadManager::RefreshTop25(Skillset ss) +{ + if (!LoggedIn()) + return; + string url = serverURL.Get() + "/user_top25_scores"; + CURL *curlHandle = initCURLHandle(); + url += "?username=" + sessionUser; + if(ss!= Skill_Overall) + url += "&ss="+SkillsetToString(ss); + SetCURLURL(curlHandle, url); + function done = [ss](HTTPRequest& req) { + Json::Value json; + RString error; + if (!JsonUtil::LoadFromString(json, req.result, error) || (json.isObject() && json.isMember("error"))) + return; + vector & vec = DLMAN->scores[ss]; + for (auto it = json.begin(); it != json.end(); ++it) { + OnlineScore tmp; + tmp.songName = (*it).get("songname", "").asString(); + tmp.wifeScore = atof((*it).get("wifescore", "0.0").asCString()); + tmp.ssr = atof((*it).get("calcscore", "0.0").asCString()); + tmp.chartkey = (*it).get("chartkey", "").asString(); + tmp.scorekey = (*it).get("scorekey", "").asString(); + tmp.rate = atof((*it).get("user_chart_rate_rate", "0.0").asCString()); + vec.push_back(tmp); + } + MESSAGEMAN->Broadcast("OnlineUpdate"); + }; + HTTPRequest* req= new HTTPRequest(curlHandle, done); + SetCURLResultsString(curlHandle, req->result); + AddSessionCookieToCURL(curlHandle); + curl_easy_setopt(curlHandle, CURLOPT_HTTPGET, 1L); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); + return; +} +// Skillset ratings (we dont care about mod lvl, username, about, etc) +void DownloadManager::RefreshUserData() +{ + if (!LoggedIn()) + return; + string url = serverURL.Get() + "/user_data"; + CURL *curlHandle = initCURLHandle(); + url += "?username=" + sessionUser; + SetCURLURL(curlHandle, url); + function done = [](HTTPRequest& req) { + Json::Value json; + RString error; + if (!JsonUtil::LoadFromString(json, req.result, error)) { + FOREACH_ENUM(Skillset, ss) + (DLMAN->sessionRatings)[ss] = 0.0f; + return; + } + FOREACH_ENUM(Skillset, ss) + (DLMAN->sessionRatings)[ss] = atof(json.get(SkillsetToString(ss), "0.0").asCString()); + }; + HTTPRequest* req = new HTTPRequest(curlHandle, done); + SetCURLResultsString(curlHandle, req->result); + AddSessionCookieToCURL(curlHandle); + curl_easy_setopt(curlHandle, CURLOPT_HTTPGET, 1L); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); + return; +} DateTime DownloadManager::GetLastUploadDate(string profileName) { string url = serverURL.Get() + "/last_upload"; @@ -570,7 +769,6 @@ DateTime DownloadManager::GetLastUploadDate(string profileName) curl_httppost *form = nullptr; curl_httppost *lastPtr = nullptr; curl_slist *headerlist = nullptr; - ComputerIdentity(); SetCURLFormPostField(curlHandle, form, lastPtr, "origin", ComputerIdentity() + ":_:" + profileName); SetCURLPostToURL(curlHandle, url); AddSessionCookieToCURL(curlHandle); @@ -579,69 +777,72 @@ DateTime DownloadManager::GetLastUploadDate(string profileName) curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); CURLcode ret = curl_easy_perform(curlHandle); curl_easy_cleanup(curlHandle); + curl_formfree(form); t.FromString(result.c_str()); return t; } -bool DownloadManager::StartSession(string user, string pass) +void DownloadManager::StartSession(string user, string pass) { string url = serverURL.Get() + "/login"; - if (user == sessionUser && pass == sessionPass) { - return true; + if (loggingIn || (user == sessionUser && pass == sessionPass)) { + return; } + DLMAN->loggingIn = true; EndSessionIfExists(); CURL *curlHandle = initCURLHandle(); + SetCURLPostToURL(curlHandle, url); curl_easy_setopt(curlHandle, CURLOPT_COOKIEFILE, ""); /* start cookie engine */ - curl_httppost *form = nullptr; curl_httppost *lastPtr = nullptr; - - SetCURLFormPostField(curlHandle, form, lastPtr, "username", user); - SetCURLFormPostField(curlHandle, form, lastPtr, "password", pass); - - SetCURLPostToURL(curlHandle, url); - + CURLFormPostField(curlHandle, form, lastPtr, "username", user.c_str()); + CURLFormPostField(curlHandle, form, lastPtr, "password", pass.c_str()); curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); - string result; - SetCURLResultsString(curlHandle, result); - - CURLcode ret = curl_easy_perform(curlHandle); - - vector v_cookies; - if (result == "\"Success\"") { - struct curl_slist *cookies; - struct curl_slist *cookieIterator; - - printf("Cookies, curl knows:\n"); - curl_easy_getinfo(curlHandle, CURLINFO_COOKIELIST, &cookies); - - cookieIterator = cookies; - while (cookieIterator) { - v_cookies.push_back(cookieIterator->data); - cookieIterator = cookieIterator->next; - } - curl_slist_free_all(cookies); - curl_easy_cleanup(curlHandle); - for (auto& cook : v_cookies) { - vector parts = split(cook, '\t'); - for (auto x = parts.begin(); x != parts.end(); x++) { - if (*x == "ci_session") { - session = *(x + 1); - sessionCookie = cook; - break; + function done = [user, pass](HTTPRequest& req) { + vector v_cookies; + if (req.result == "\"Success\"") { + struct curl_slist *cookies; + struct curl_slist *cookieIterator; + curl_easy_getinfo(req.handle, CURLINFO_COOKIELIST, &cookies); + cookieIterator = cookies; + while (cookieIterator) { + v_cookies.push_back(cookieIterator->data); + cookieIterator = cookieIterator->next; + } + curl_slist_free_all(cookies); + for (auto& cook : v_cookies) { + vector parts = split(cook, '\t'); + for (auto x = parts.begin(); x != parts.end(); x++) { + if (*x == "ci_session") { + DLMAN->session = *(x + 1); + DLMAN->sessionCookie = cook; + break; + } } + if (!DLMAN->session.empty()) + break; } - if (!session.empty()) - break; + DLMAN->sessionUser = user; + DLMAN->sessionPass = pass; + DLMAN->RefreshUserRank(); + DLMAN->RefreshUserData(); + FOREACH_ENUM(Skillset, ss) + DLMAN->RefreshTop25(ss); + MESSAGEMAN->Broadcast("Login"); } - sessionUser = user; - sessionPass = pass; - } - else { - session = sessionUser = sessionPass = sessionCookie = ""; - } - return !session.empty(); + else { + DLMAN->session = DLMAN->sessionUser = DLMAN->sessionPass = DLMAN->sessionCookie = ""; + MESSAGEMAN->Broadcast("LoginFailed"); + } + DLMAN->loggingIn = false; + }; + HTTPRequest* req = new HTTPRequest(curlHandle, done, form); + SetCURLResultsString(curlHandle, req->result); + if (mHTTPHandle == nullptr) + mHTTPHandle = curl_multi_init(); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); } @@ -656,6 +857,19 @@ bool DownloadManager::CachePackList(string url) return result; } +int DownloadManager::GetRank() +{ + if (!LoggedIn()) + return 0; + return sessionRank; +} + +float DownloadManager::GetSkillsetRating(Skillset ss) +{ + if (!LoggedIn()) + return 0.0f; + return sessionRatings[ss]; +} vector* DownloadManager::GetPackList(string url, bool &result) { if (url == "") { @@ -745,11 +959,14 @@ Download::~Download() void Download::Install() { - DLMAN->InstallSmzip(m_TempFileName); - Message msg("PackDownloaded"); - msg.SetParam("pack", LuaReference::CreateFromPush(*p_Pack)); - MESSAGEMAN->Broadcast(msg); - return; + Message* msg; + if(!DLMAN->InstallSmzip(m_TempFileName)) + msg = new Message("DownloadFailed"); + else + msg = new Message("PackDownloaded"); + msg->SetParam("pack", LuaReference::CreateFromPush(*p_Pack)); + MESSAGEMAN->Broadcast(*msg); + delete msg; } void Download::Failed() @@ -802,6 +1019,21 @@ class LunaDownloadManager : public Luna } return 1; } + static int GetUsername(T* p, lua_State* L) + { + lua_pushstring(L, DLMAN->sessionUser.c_str()); + return 1; + } + static int GetUserRank(T* p, lua_State* L) + { + lua_pushnumber(L, DLMAN->GetRank()); + return 1; + } + static int GetSkillsetRating(T* p, lua_State* L) + { + lua_pushnumber(L, DLMAN->GetSkillsetRating(Enum::Check(L, 1))); + return 1; + } static int GetDownloads(T* p, lua_State* L) { map& dls = DLMAN->downloads; @@ -823,7 +1055,7 @@ class LunaDownloadManager : public Luna { string user = SArg(1); string pass = SArg(2); - lua_pushboolean(L, DLMAN->StartSession(user, pass)); + DLMAN->StartSession(user, pass); return 1; } static int Logout(T* p, lua_State* L) @@ -831,6 +1063,29 @@ class LunaDownloadManager : public Luna DLMAN->EndSessionIfExists(); return 1; } + static int GetTopSkillsetScore(T* p, lua_State* L) + { + int rank = IArg(1); + auto ss = Enum::Check(L, 2); + bool result; + OnlineScore onlineScore = DLMAN->GetTopSkillsetScore(rank, ss, result); + if (!result) { + lua_pushnil(L); + return 1; + } + lua_createtable(L, 0, 5); + lua_pushstring(L, onlineScore.songName.c_str()); + lua_setfield(L, -2, "songName"); + lua_pushnumber(L, onlineScore.rate); + lua_setfield(L, -2, "rate"); + lua_pushnumber(L, onlineScore.ssr); + lua_setfield(L, -2, "ssr"); + lua_pushnumber(L, onlineScore.wifeScore); + lua_setfield(L, -2, "wife"); + lua_pushstring(L, onlineScore.chartkey.c_str()); + lua_setfield(L, -2, "ck"); + return 1; + } static int GetFilteredAndSearchedPackList(T* p, lua_State* L) { if (lua_gettop(L) < 5) { @@ -858,11 +1113,6 @@ class LunaDownloadManager : public Luna } return 1; } - static int GetMostRecentUploadResult(T* p, lua_State* L) - { - lua_pushstring(L, p->mostrecentresult); - return 1; - } LunaDownloadManager() { ADD_METHOD(GetPackList); @@ -871,7 +1121,10 @@ class LunaDownloadManager : public Luna ADD_METHOD(GetFilteredAndSearchedPackList); ADD_METHOD(IsLoggedIn); ADD_METHOD(Login); - ADD_METHOD(GetMostRecentUploadResult); + ADD_METHOD(GetUsername); + ADD_METHOD(GetUserRank); + ADD_METHOD(GetSkillsetRating); + ADD_METHOD(GetTopSkillsetScore); ADD_METHOD(Logout); } }; diff --git a/src/DownloadManager.h b/src/DownloadManager.h index bb36ab5d64..8ea7f9c64a 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -76,16 +76,41 @@ class DownloadablePack { void PushSelf(lua_State *L); }; +class HTTPRequest { +public: + HTTPRequest(CURL * h, function done = [](HTTPRequest& req) {return; }, + curl_httppost* postform = nullptr, function fail = [](HTTPRequest& req) {return; }): + handle(h), form(postform), Done(done), Failed(fail) {}; + CURL * handle{ nullptr }; + curl_httppost* form{ nullptr }; + string result; + function Done; + function Failed; +}; +class OnlineScore { +public: + float wifeScore{ 0.0f }; + string songName; + float rate{ 0.0f }; + float ssr{ 0.0f }; + string chartkey; + string scorekey; + string steps; +}; class DownloadManager { public: DownloadManager(); ~DownloadManager(); map downloads; + vector HTTPRequests; map finishedDownloads; - CURLM* mHandle{nullptr}; + CURLM* mPackHandle{nullptr}; + CURLM* mHTTPHandle{ nullptr }; CURLMcode ret; - int running{0}; + int downloadingPacks{0}; + int HTTPRunning{ 0 }; + bool loggingIn{ false }; bool gameplay{false}; string error{""}; int lastid{0}; @@ -96,15 +121,19 @@ class DownloadManager string session{ "" }; string sessionUser{ "" }; string sessionPass{ "" }; + double sessionRating{ 0.0 }; + int sessionRank{ 0 }; bool LoggedIn(); void EndSessionIfExists(); - bool StartSession(string user, string pass); + void StartSession(string user, string pass); vector* GetPackList(string url, bool &result); Download* DownloadAndInstallPack(const string &url); Download* DownloadAndInstallPack(DownloadablePack* pack); bool UpdateAndIsFinished(float fDeltaSeconds); - void InstallSmzip(const string &sZipFile); + bool UpdatePacksAndIsFinished(float fDeltaSeconds); + bool UpdateHTTPAndIsFinished(float fDeltaSeconds); + bool InstallSmzip(const string &sZipFile); void UpdateDLSpeed(); void UpdateDLSpeed(bool gameplay); @@ -114,16 +143,26 @@ class DownloadManager bool Error() { return error == ""; } bool EncodeSpaces(string& str); - bool LoginAndUploadProfile(string file, string profileName, string user, string pass); bool UploadProfile(string file, string profileName); - bool UploadScore(HighScore* hs); + void UploadScoreWithReplayData(HighScore* hs); + void UploadScore(HighScore* hs); DateTime GetLastUploadDate(string profileName); bool ShouldUploadScores(); inline void AddSessionCookieToCURL(CURL *curlHandle); inline void SetCURLPostToURL(CURL *curlHandle, string url); + inline void SetCURLURL(CURL *curlHandle, string url); + + void RefreshUserData(); + void RefreshUserRank(); + void RefreshTop25(Skillset ss); + map sessionRatings; + map> scores; + OnlineScore GetTopSkillsetScore(unsigned int rank, Skillset ss, bool &result); + float GetSkillsetRating(Skillset ss); + int GetRank(); // most recent single score upload result -mina RString mostrecentresult = "";