diff --git a/src/Profile.cpp b/src/Profile.cpp index 1aed0f260f..b77ad30e07 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -1012,11 +1012,32 @@ ProfileLoadResult Profile::LoadEttXmlFromNode(const XNode *xml) { return ProfileLoadResult_FailedTampered; } + const XNode* gen = xml->GetChild("GeneralData"); + if(gen) + LoadEttGeneralDataFromNode(gen); - LOAD_NODE(GeneralData); + const XNode* favs = xml->GetChild("Favorites"); + if(favs) + LoadFavoritesFromNode(favs); + LOG->Warn("wat"); + + const XNode* goals = xml->GetChild("ScoreGoals"); + if(goals) + LoadScoreGoalsFromNode(goals); + + LOG->Warn("wat"); + + const XNode* play = xml->GetChild("Playlists"); + if (play) + LoadPlaylistsFromNode(play); + + LOG->Warn("wat"); + const XNode* scores = xml->GetChild("PlayerScores"); - LoadEttScoresFromNode(scores); + if (scores) + LoadEttScoresFromNode(scores); + CalculateStatsFromScores(); return ProfileLoadResult_Success; } @@ -1079,9 +1100,16 @@ XNode *Profile::SaveEttXmlCreateNode() const { XNode *xml = new XNode("Stats"); xml->AppendChild(SaveEttGeneralDataCreateNode()); - xml->AppendChild(SaveFavoritesCreateNode()); - xml->AppendChild(SavePlaylistsCreateNode()); - xml->AppendChild(SaveScoreGoalsCreateNode()); + + if(!FavoritedCharts.empty()) + xml->AppendChild(SaveFavoritesCreateNode()); + + if (!SONGMAN->allplaylists.empty()) + xml->AppendChild(SavePlaylistsCreateNode()); + + if(!goalmap.empty()) + xml->AppendChild(SaveScoreGoalsCreateNode()); + xml->AppendChild(SaveEttScoresCreateNode()); return xml; } @@ -1366,17 +1394,56 @@ XNode* Profile::SaveScoreGoalsCreateNode() const { const GoalsForChart& cg = i->second; goals->AppendChild(cg.CreateNode()); } - return goals; } XNode* Profile::SavePlaylistsCreateNode() const { - XNode* playlists = new XNode("PlayLists"); - FOREACH_CONST(string, FavoritedCharts, it) - playlists->AppendChild(*it); + XNode* playlists = new XNode("Playlists"); + auto& pls = SONGMAN->allplaylists; + FOREACH(Playlist, pls, pl) + playlists->AppendChild(pl->CreateNode()); return playlists; } +void Profile::LoadFavoritesFromNode(const XNode *pNode) { + FOREACH_CONST_Child(pNode, ck) { + RString tmp = ck->GetName(); + bool duplicated = false; + FOREACH(string, FavoritedCharts, chartkey) + if (*chartkey == tmp) + duplicated = true; + if (!duplicated) + FavoritedCharts.emplace_back(tmp); + } + SONGMAN->SetFavoritedStatus(FavoritedCharts); +} + +void GoalsForChart::LoadFromNode(const XNode *pNode) { + FOREACH_CONST_Child(pNode, sg) { + ScoreGoal doot; + doot.LoadFromNode(sg); + Add(doot); + } +} + +void Profile::LoadScoreGoalsFromNode(const XNode *pNode) { + RString ck; + FOREACH_CONST_Child(pNode, chgoals) { + chgoals->GetAttrValue("Key", ck); + goalmap[ck].LoadFromNode(chgoals); + } +} + +void Profile::LoadPlaylistsFromNode(const XNode *pNode) { + auto& pls = SONGMAN->allplaylists; + FOREACH_CONST_Child(pNode, pl) { + Playlist tmp; + tmp.LoadFromNode(pl); + pls.emplace_back(tmp); + } +} + + XNode* Profile::SaveEttGeneralDataCreateNode() const { XNode* pGeneralDataNode = new XNode("GeneralData"); @@ -1627,6 +1694,72 @@ void Profile::LoadGeneralDataFromNode( const XNode* pNode ) } + +void Profile::LoadEttGeneralDataFromNode(const XNode* pNode) +{ + ASSERT(pNode->GetName() == "GeneralData"); + + RString s; + const XNode* pTemp; + + pNode->GetChildValue("DisplayName", m_sDisplayName); + pNode->GetChildValue("CharacterID", m_sCharacterID); + pNode->GetChildValue("LastUsedHighScoreName", m_sLastUsedHighScoreName); + pNode->GetChildValue("Guid", m_sGuid); + pNode->GetChildValue("SortOrder", s); m_SortOrder = StringToSortOrder(s); + pNode->GetChildValue("LastDifficulty", s); m_LastDifficulty = StringToDifficulty(s); + pNode->GetChildValue("LastStepsType", s); m_LastStepsType = GAMEMAN->StringToStepsType(s); + pTemp = pNode->GetChild("Song"); if (pTemp) m_lastSong.LoadFromNode(pTemp); + pNode->GetChildValue("CurrentCombo", m_iCurrentCombo); + pNode->GetChildValue("TotalSessions", m_iTotalSessions); + pNode->GetChildValue("TotalSessionSeconds", m_iTotalSessionSeconds); + pNode->GetChildValue("TotalGameplaySeconds", m_iTotalGameplaySeconds); + pNode->GetChildValue("LastPlayedDate", s); m_LastPlayedDate.FromString(s); + pNode->GetChildValue("TotalDancePoints", m_iTotalDancePoints); + pNode->GetChildValue("NumToasties", m_iNumToasties); + pNode->GetChildValue("TotalTapsAndHolds", m_iTotalTapsAndHolds); + pNode->GetChildValue("TotalJumps", m_iTotalJumps); + pNode->GetChildValue("TotalHolds", m_iTotalHolds); + pNode->GetChildValue("TotalRolls", m_iTotalRolls); + pNode->GetChildValue("TotalMines", m_iTotalMines); + pNode->GetChildValue("TotalHands", m_iTotalHands); + pNode->GetChildValue("TotalLifts", m_iTotalLifts); + pNode->GetChildValue("PlayerRating", m_fPlayerRating); + + { + const XNode* pDefaultModifiers = pNode->GetChild("DefaultModifiers"); + if (pDefaultModifiers) + { + FOREACH_CONST_Child(pDefaultModifiers, game_type) + { + game_type->GetTextValue(m_sDefaultModifiers[game_type->GetName()]); + } + } + } + + { + const XNode* pPlayerSkillsets = pNode->GetChild("PlayerSkillsets"); + if (pPlayerSkillsets) { + FOREACH_ENUM(Skillset, ss) + pPlayerSkillsets->GetChildValue(SkillsetToString(ss), m_fPlayerSkillsets[ss]); + } + } + + const XNode *pUserTable = pNode->GetChild("UserTable"); + + Lua *L = LUA->Get(); + + // If we have custom data, load it. Otherwise, make a blank table. + if (pUserTable) + LuaHelpers::CreateTableFromXNode(L, pUserTable); + else + lua_newtable(L); + + m_UserTable.SetFromStack(L); + LUA->Release(L); + +} + void Profile::AddStepTotals( int iTotalTapsAndHolds, int iTotalJumps, int iTotalHolds, int iTotalRolls, int iTotalMines, int iTotalHands, int iTotalLifts) { m_iTotalTapsAndHolds += iTotalTapsAndHolds; diff --git a/src/Profile.h b/src/Profile.h index 75a87fbfb3..646b05f8bd 100644 --- a/src/Profile.h +++ b/src/Profile.h @@ -105,10 +105,13 @@ class ScoreGoal struct GoalsForChart { public: - XNode* CreateNode() const; + void Add(ScoreGoal& sg) { goals.emplace_back(sg); } vector& Get() { return goals; } vector goals; + + XNode* CreateNode() const; + void LoadFromNode(const XNode *pNode); }; /** @@ -259,8 +262,9 @@ class Profile XNode* SaveFavoritesCreateNode() const; XNode* SaveScoreGoalsCreateNode() const; XNode* SavePlaylistsCreateNode() const; - void LoadFavoritesFromNode(); - + void LoadFavoritesFromNode(const XNode *pNode); + void LoadScoreGoalsFromNode(const XNode *pNode); + void LoadPlaylistsFromNode(const XNode *pNode); // more future goalman stuff -mina void CreateGoal(string& ck); @@ -370,6 +374,7 @@ class Profile // Etterna profile ProfileLoadResult LoadEttFromDir(RString dir); ProfileLoadResult LoadEttXmlFromNode(const XNode* pNode); + void LoadEttGeneralDataFromNode(const XNode* pNode); void LoadEttScoresFromNode(const XNode* pNode); bool SaveEttXmlToDir(RString sDir) const; diff --git a/src/ScoreManager.cpp b/src/ScoreManager.cpp index dd5f5f2fb5..768b2e3737 100644 --- a/src/ScoreManager.cpp +++ b/src/ScoreManager.cpp @@ -121,12 +121,15 @@ vector ScoresForChart::GetPlayedRateDisplayStrings() { } string ScoresForChart::RateKeyToDisplayString(float rate) { + rate = 0.9f; + string rs = ssprintf("%.2f", rate); int j = 1; if (rs.find_last_not_of('0') == rs.find('.')) j = 2; rs.erase(rs.find_last_not_of('0') + j, rs.npos); rs.append("x"); + LOG->Warn(rs.c_str()); return rs; } @@ -248,11 +251,11 @@ XNode * ScoresForChart::CreateNode(const string& ck) const { XNode* o = new XNode("ChartScores"); Song* song = SONGMAN->GetSongByChartkey(ck); if (song) { - o->AppendAttr("Song", song->GetDisplayMainTitle()); o->AppendAttr("Pack", song->m_sGroupName); + o->AppendAttr("Song", song->GetDisplayMainTitle()); } else { - o->AppendAttr("Song", LastSeenSong); o->AppendAttr("Pack", LastSeenPack); + o->AppendAttr("Song", LastSeenSong); } FOREACHM_CONST(int, ScoresAtRate, ScoresByRate, i) diff --git a/src/ScoreManager.h b/src/ScoreManager.h index 57167d2b25..0350c3940e 100644 --- a/src/ScoreManager.h +++ b/src/ScoreManager.h @@ -116,7 +116,7 @@ class ScoreManager HighScore * GetTopSSRHighScore(unsigned int rank, int ss); bool KeyHasScores(const string& ck) { return pscores.count(ck) == 1; } - + bool HasAnyScores() { return !AllScores.empty(); } diff --git a/src/SongManager.cpp b/src/SongManager.cpp index f62429cea6..edf459e454 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -140,6 +140,46 @@ void SongManager::InitSongsFromDisk( LoadingWindow *ld ) LOG->Trace( "Found %d songs in %f seconds.", (int)m_pSongs.size(), tm.GetDeltaTime() ); } + + +XNode* Playlist::CreateNode() const { + XNode* pl = new XNode("Playlist"); + pl->AppendAttr("Name", name); + + FOREACH_CONST(Chart, chartlist, ch) { + XNode* chart = new XNode(ch->key); + Song* song = SONGMAN->GetSongByChartkey(ch->key); + if (song) { + chart->AppendAttr("Pack", song->m_sGroupName); + chart->AppendAttr("Song", song->GetDisplayMainTitle()); + + } + else { + chart->AppendAttr("Pack", ch->lastpack); + chart->AppendAttr("Song", ch->lastsong); + } + pl->AppendChild(chart); + } + + return pl; +} +void Playlist::LoadFromNode(const XNode* node) { + node->GetAttrValue("Name", name); + FOREACH_CONST_Child(node, chart) { + Chart ch; + ch.key = chart->GetName(); + chart->GetAttrValue("Pack", ch.lastpack); + chart->GetAttrValue("Song", ch.lastsong); + + Song* song = SONGMAN->GetSongByChartkey(ch.key); + if (song) { + ch.lastpack = song->m_sGroupName; + ch.lastsong = song->GetDisplayMainTitle(); + } + chartlist.emplace_back(ch); + } +} + // Only store 1 steps/song pointer per key -Mina void SongManager::AddKeyedPointers(Song* new_song) { const vector steps = new_song->GetAllSteps(); diff --git a/src/SongManager.h b/src/SongManager.h index df3119facd..87b8919c32 100644 --- a/src/SongManager.h +++ b/src/SongManager.h @@ -19,12 +19,39 @@ struct lua_State; #include "RageUtil.h" #include "Profile.h" +#include +using std::string; + RString SONG_GROUP_COLOR_NAME( size_t i ); bool CompareNotesPointersForExtra(const Steps *n1, const Steps *n2); /** @brief The max number of edit steps a profile can have. */ const int MAX_EDIT_STEPS_PER_PROFILE = 200; + +struct Chart { + string key; + RString lastsong; + RString lastpack; +}; + +struct Playlist { + RString name; + vector chartlist; + void Add(Chart ch) { chartlist.emplace_back(ch); } + void SwapPosition(); + + + XNode* CreateNode() const; + void LoadFromNode(const XNode* node); + + void PushSelf(lua_State *L); +}; + + + + + /** @brief The holder for the Songs and its Steps. */ class SongManager { @@ -140,6 +167,9 @@ class SongManager // Lua void PushSelf( lua_State *L ); + + vector allplaylists; + protected: void LoadStepManiaSongDir( RString sDir, LoadingWindow *ld ); void LoadDWISongDir( const RString &sDir ); @@ -154,8 +184,8 @@ class SongManager // Indexed by chartkeys void AddKeyedPointers(Song* new_song); - map SongsByKey; - map StepsByKey; + unordered_map SongsByKey; + unordered_map StepsByKey; set m_GroupsToNeverCache; /** @brief Hold pointers to all the songs that have been deleted from disk but must at least be kept temporarily alive for smooth audio transitions. */