diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 497af44504..5a52ce2714 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -359,8 +359,6 @@ void GameState::JoinPlayer( PlayerNumber pn ) void GameState::UnjoinPlayer( PlayerNumber pn ) { - PROFILEMAN->UnloadProfile( pn ); - m_bSideIsJoined[pn] = false; m_iPlayerStageTokens[pn] = 0; @@ -369,8 +367,10 @@ void GameState::UnjoinPlayer( PlayerNumber pn ) if( m_MasterPlayerNumber == pn ) m_MasterPlayerNumber = GetFirstHumanPlayer(); - + /* Unjoin STATSMAN first, so steps used by this player are released + * and can be released by PROFILEMAN. */ STATSMAN->UnjoinPlayer( pn ); + PROFILEMAN->UnloadProfile( pn ); Message msg( MessageIDToString(Message_PlayerUnjoined) ); msg.SetParam( "Player", pn ); diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 84d0879e84..c58fe12f66 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -1263,7 +1263,9 @@ bool Song::Matches(RString sGroup, RString sSong) const return false; } -void Song::FreeAllLoadedFromProfile( ProfileSlot slot ) +/* If apInUse is set, it contains a list of steps which are in use elsewhere, and + * should not be deleted. */ +void Song::FreeAllLoadedFromProfile( ProfileSlot slot, const set *setInUse ) { /* DeleteSteps will remove and recreate autogen notes, which may reorder * m_vpSteps, so be careful not to skip over entries. */ @@ -1273,8 +1275,11 @@ void Song::FreeAllLoadedFromProfile( ProfileSlot slot ) Steps* pSteps = m_vpSteps[s]; if( !pSteps->WasLoadedFromProfile() ) continue; - if( slot == ProfileSlot_Invalid || pSteps->GetLoadedFromProfileSlot() == slot ) - apToRemove.push_back( pSteps ); + if( slot != ProfileSlot_Invalid && pSteps->GetLoadedFromProfileSlot() != slot ) + continue; + if( setInUse != NULL && setInUse->find(pSteps) != setInUse->end() ) + continue; + apToRemove.push_back( pSteps ); } for( unsigned i = 0; i < apToRemove.size(); ++i ) diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index 37df305d88..499d8559b9 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -1585,8 +1585,11 @@ void SongManager::FreeAllLoadedFromProfile( ProfileSlot slot ) RefreshCourseGroupInfo(); /* Free profile steps. */ + set setInUse; + if( STATSMAN ) + STATSMAN->GetStepsInUse( setInUse ); FOREACH( Song*, m_pSongs, s ) - (*s)->FreeAllLoadedFromProfile( slot ); + (*s)->FreeAllLoadedFromProfile( slot, &setInUse ); // After freeing some Steps pointers, the cache will be invalid. StepsID::ClearCache(); diff --git a/stepmania/src/StatsManager.cpp b/stepmania/src/StatsManager.cpp index 472dd12dab..57a5b6c5b2 100644 --- a/stepmania/src/StatsManager.cpp +++ b/stepmania/src/StatsManager.cpp @@ -229,7 +229,24 @@ void StatsManager::UnjoinPlayer( PlayerNumber pn ) m_vPlayedStageStats.erase( m_vPlayedStageStats.begin()+i ); --i; } +} +void StatsManager::GetStepsInUse( set &apInUseOut ) const +{ + for( int i = 0; i < (int) m_vPlayedStageStats.size(); ++i ) + { + FOREACH_PlayerNumber( pn ) + { + const PlayerStageStats &pss = m_vPlayedStageStats[i].m_player[pn]; + apInUseOut.insert( pss.m_vpPossibleSteps.begin(), pss.m_vpPossibleSteps.end() ); + } + + FOREACH_MultiPlayer( mp ) + { + const PlayerStageStats &pss = m_vPlayedStageStats[i].m_multiPlayer[mp]; + apInUseOut.insert( pss.m_vpPossibleSteps.begin(), pss.m_vpPossibleSteps.end() ); + } + } } // lua start diff --git a/stepmania/src/StatsManager.h b/stepmania/src/StatsManager.h index dba13f5a55..23a946c0ec 100644 --- a/stepmania/src/StatsManager.h +++ b/stepmania/src/StatsManager.h @@ -27,6 +27,7 @@ public: static void CommitStatsToProfiles( const StageStats *pSS ); void UnjoinPlayer( PlayerNumber pn ); + void GetStepsInUse( set &apInUseOut ) const; // Lua void PushSelf( lua_State *L ); diff --git a/stepmania/src/song.h b/stepmania/src/song.h index 433baf4c00..b37b3c9c3b 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -8,6 +8,7 @@ #include "EnumHelper.h" #include "RageUtil_AutoPtr.h" #include "RageTypes.h" +#include class Steps; class Style; @@ -212,7 +213,7 @@ public: void AddSteps( Steps* pSteps ); // we are responsible for deleting the memory pointed to by pSteps! void DeleteSteps( const Steps* pSteps, bool bReAutoGen = true ); - void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_Invalid ); + void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_Invalid, const set *setInUse = NULL ); bool WasLoadedFromProfile() const { return m_LoadedFromProfile != ProfileSlot_Invalid; } void GetStepsLoadedFromProfile( ProfileSlot slot, vector &vpStepsOut ) const; int GetNumStepsLoadedFromProfile( ProfileSlot slot ) const;