Add sorting by Block level
(cherry picked from commit e1c8326a6a71f4a15c3f123391dc3f3331ee4a7b)
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
Common fallback banner
|
||||||
@@ -170,6 +170,7 @@ static const char *SortOrderNames[] = {
|
|||||||
"TopP2Grades",
|
"TopP2Grades",
|
||||||
"Artist",
|
"Artist",
|
||||||
"Genre",
|
"Genre",
|
||||||
|
"Meter",
|
||||||
"BeginnerMeter",
|
"BeginnerMeter",
|
||||||
"EasyMeter",
|
"EasyMeter",
|
||||||
"MediumMeter",
|
"MediumMeter",
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ enum SortOrder
|
|||||||
SORT_TOP_GRADES_P2, /**< Sort by the highest grades earned on a Song for P2. */
|
SORT_TOP_GRADES_P2, /**< Sort by the highest grades earned on a Song for P2. */
|
||||||
SORT_ARTIST, /**< Sort by the name of the artist of the Song. */
|
SORT_ARTIST, /**< Sort by the name of the artist of the Song. */
|
||||||
SORT_GENRE, /**< Sort by the Song's genre. */
|
SORT_GENRE, /**< Sort by the Song's genre. */
|
||||||
|
SORT_METER, /**< Sort by the difficulty of all meters */
|
||||||
SORT_BEGINNER_METER, /**< Sort by the difficulty of the single beginner meter. */
|
SORT_BEGINNER_METER, /**< Sort by the difficulty of the single beginner meter. */
|
||||||
SORT_EASY_METER, /**< Sort by the difficulty of the single easy meter. */
|
SORT_EASY_METER, /**< Sort by the difficulty of the single easy meter. */
|
||||||
SORT_MEDIUM_METER, /**< Sort by the difficulty of the single medium meter. */
|
SORT_MEDIUM_METER, /**< Sort by the difficulty of the single medium meter. */
|
||||||
|
|||||||
+70
-46
@@ -537,6 +537,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SORT_METER:
|
||||||
case SORT_PREFERRED:
|
case SORT_PREFERRED:
|
||||||
case SORT_ROULETTE:
|
case SORT_ROULETTE:
|
||||||
case SORT_GROUP:
|
case SORT_GROUP:
|
||||||
@@ -569,6 +570,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
|
|||||||
// sort the songs
|
// sort the songs
|
||||||
switch( so )
|
switch( so )
|
||||||
{
|
{
|
||||||
|
case SORT_METER:
|
||||||
case SORT_PREFERRED:
|
case SORT_PREFERRED:
|
||||||
// obey order specified by the preferred sort list
|
// obey order specified by the preferred sort list
|
||||||
break;
|
break;
|
||||||
@@ -674,6 +676,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
|
|||||||
/* We're using sections, so use the section name as the top-level sort. */
|
/* We're using sections, so use the section name as the top-level sort. */
|
||||||
switch( so )
|
switch( so )
|
||||||
{
|
{
|
||||||
|
case SORT_METER:
|
||||||
case SORT_PREFERRED:
|
case SORT_PREFERRED:
|
||||||
case SORT_TOP_GRADES:
|
case SORT_TOP_GRADES:
|
||||||
case SORT_TOP_GRADES_P1:
|
case SORT_TOP_GRADES_P1:
|
||||||
@@ -689,58 +692,79 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
|
|||||||
// make WheelItemDatas with sections
|
// make WheelItemDatas with sections
|
||||||
RString sLastSection = "";
|
RString sLastSection = "";
|
||||||
int iSectionColorIndex = 0;
|
int iSectionColorIndex = 0;
|
||||||
|
switch (so) {
|
||||||
// If the sort order is Preferred handle it differently because we already know the sections
|
case SORT_PREFERRED:
|
||||||
if( so == SORT_PREFERRED )
|
// If the sort order is Preferred handle it differently because we already know the sections
|
||||||
{
|
|
||||||
if( bUseSections )
|
|
||||||
{
|
|
||||||
// Get mappping of section names to songs
|
|
||||||
std::map<RString, std::vector<Song*>> preferredSortSongsMap = SONGMAN->GetPreferredSortSongsMap();
|
|
||||||
for (auto const& [sectionName, songs] : SONGMAN->GetPreferredSortSongsMap())
|
|
||||||
{
|
|
||||||
// todo: preferred sort section color handling? -aj
|
|
||||||
RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex);
|
|
||||||
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
|
|
||||||
// Add the section item
|
|
||||||
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sectionName, nullptr, colorSection, songs.size()) );
|
|
||||||
// Add all the songs in this section
|
|
||||||
for (auto const& song : songs)
|
|
||||||
{
|
|
||||||
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, sectionName, nullptr, SONGMAN->GetSongColor(song), 0) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
for( unsigned i=0; i< arraySongs.size(); i++ )
|
|
||||||
{
|
|
||||||
Song* pSong = arraySongs[i];
|
|
||||||
if( bUseSections )
|
if( bUseSections )
|
||||||
{
|
{
|
||||||
RString sThisSection = SongUtil::GetSectionNameFromSongAndSort( pSong, so );
|
// Get mappping of section names to songs
|
||||||
|
std::map<RString, std::vector<Song*>> preferredSortSongsMap = SONGMAN->GetPreferredSortSongsMap();
|
||||||
if( sThisSection != sLastSection )
|
for (auto const& [sectionName, songs] : SONGMAN->GetPreferredSortSongsMap())
|
||||||
{
|
{
|
||||||
int iSectionCount = 0;
|
// todo: preferred sort section color handling? -aj
|
||||||
// Count songs in this section
|
RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex);
|
||||||
unsigned j;
|
|
||||||
for( j=i; j < arraySongs.size(); j++ )
|
|
||||||
{
|
|
||||||
if( SongUtil::GetSectionNameFromSongAndSort( arraySongs[j], so ) != sThisSection )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iSectionCount = j-i;
|
|
||||||
|
|
||||||
// new section, make a section item
|
|
||||||
RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex);
|
|
||||||
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
|
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
|
||||||
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, colorSection, iSectionCount) );
|
// Add the section item
|
||||||
sLastSection = sThisSection;
|
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sectionName, nullptr, colorSection, songs.size()) );
|
||||||
|
// Add all the songs in this section
|
||||||
|
for (auto const& song : songs)
|
||||||
|
{
|
||||||
|
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, sectionName, nullptr, SONGMAN->GetSongColor(song), 0) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, pSong, sLastSection, nullptr, SONGMAN->GetSongColor(pSong), 0) );
|
break;
|
||||||
}
|
case SORT_METER:
|
||||||
|
// If the sort order is Preferred handle it differently because we already know the sections
|
||||||
|
if( bUseSections )
|
||||||
|
{
|
||||||
|
int iSectionCount = 0;
|
||||||
|
// // Get all section names
|
||||||
|
std::map<int, std::vector<Song*>> meterSortSongsMap = SONGMAN->GetMeterToSongsMap();
|
||||||
|
for (auto const& [sectionName, songs] : SONGMAN->GetMeterToSongsMap()) {
|
||||||
|
RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex);
|
||||||
|
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
|
||||||
|
// Add the section item
|
||||||
|
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, ssprintf("%d",sectionName), nullptr, colorSection, songs.size()) );
|
||||||
|
// Add all the songs in this section
|
||||||
|
for (auto const& song : songs)
|
||||||
|
{
|
||||||
|
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, ssprintf("%d",sectionName), nullptr, SONGMAN->GetSongColor(song), 0) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
for( unsigned i=0; i< arraySongs.size(); i++ )
|
||||||
|
{
|
||||||
|
Song* pSong = arraySongs[i];
|
||||||
|
if( bUseSections )
|
||||||
|
{
|
||||||
|
RString sThisSection = SongUtil::GetSectionNameFromSongAndSort( pSong, so );
|
||||||
|
|
||||||
|
if( sThisSection != sLastSection )
|
||||||
|
{
|
||||||
|
int iSectionCount = 0;
|
||||||
|
// Count songs in this section
|
||||||
|
unsigned j;
|
||||||
|
for( j=i; j < arraySongs.size(); j++ )
|
||||||
|
{
|
||||||
|
if( SongUtil::GetSectionNameFromSongAndSort( arraySongs[j], so ) != sThisSection )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iSectionCount = j-i;
|
||||||
|
|
||||||
|
// new section, make a section item
|
||||||
|
// todo: preferred sort section color handling? -aj
|
||||||
|
RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex);
|
||||||
|
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
|
||||||
|
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, colorSection, iSectionCount) );
|
||||||
|
sLastSection = sThisSection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, pSong, sLastSection, nullptr, SONGMAN->GetSongColor(pSong), 0) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( so != SORT_ROULETTE )
|
if( so != SORT_ROULETTE )
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ void SongManager::Reload( bool bAllowFastLoad, LoadingWindow *ld )
|
|||||||
PREFSMAN->m_bFastLoad.Set( oldVal );
|
PREFSMAN->m_bFastLoad.Set( oldVal );
|
||||||
|
|
||||||
UpdatePreferredSort();
|
UpdatePreferredSort();
|
||||||
|
UpdateMeterSort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongManager::LoadAdditions( LoadingWindow *ld )
|
void SongManager::LoadAdditions( LoadingWindow *ld )
|
||||||
@@ -227,6 +228,7 @@ void SongManager::LoadAdditions( LoadingWindow *ld )
|
|||||||
UNLOCKMAN->Reload();
|
UNLOCKMAN->Reload();
|
||||||
|
|
||||||
UpdatePreferredSort();
|
UpdatePreferredSort();
|
||||||
|
UpdateMeterSort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongManager::InitSongsFromDisk( LoadingWindow *ld, bool onlyAdditions )
|
void SongManager::InitSongsFromDisk( LoadingWindow *ld, bool onlyAdditions )
|
||||||
@@ -889,6 +891,16 @@ void SongManager::GetPreferredSortCourses( CourseType ct, std::vector<Course*> &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Song*> SongManager::GetSongsByMeter(const int iMeter) const {
|
||||||
|
std::vector<Song*> AddTo;
|
||||||
|
auto iter = m_mapSongsByDifficulty.find(iMeter);
|
||||||
|
if (iter != m_mapSongsByDifficulty.end()) {
|
||||||
|
// Found the level, add the songs to AddTo
|
||||||
|
AddTo.insert(AddTo.end(), iter->second.begin(), iter->second.end());
|
||||||
|
}
|
||||||
|
return AddTo;
|
||||||
|
}
|
||||||
|
|
||||||
int SongManager::GetNumSongs() const
|
int SongManager::GetNumSongs() const
|
||||||
{
|
{
|
||||||
return m_pSongs.size();
|
return m_pSongs.size();
|
||||||
@@ -1225,6 +1237,7 @@ void SongManager::Invalidate( const Song *pStaleSong )
|
|||||||
|
|
||||||
UpdatePopular();
|
UpdatePopular();
|
||||||
UpdateShuffled();
|
UpdateShuffled();
|
||||||
|
UpdateMeterSort();
|
||||||
RefreshCourseGroupInfo();
|
RefreshCourseGroupInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1617,6 +1630,33 @@ void SongManager::UpdatePopular()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SongManager::UpdateMeterSort() {
|
||||||
|
std::vector<Song*> apDifficultSongs = m_pSongs;
|
||||||
|
// For each song, for each step
|
||||||
|
for( unsigned i = 0; i < apDifficultSongs.size(); ++i )
|
||||||
|
{
|
||||||
|
const std::vector<Steps*> &vSteps = apDifficultSongs[i]->GetAllSteps();
|
||||||
|
for( unsigned j = 0; j < vSteps.size(); ++j )
|
||||||
|
{
|
||||||
|
Steps *pSteps = vSteps[j];
|
||||||
|
// Check if the meter is already in m_mapSongsByDifficulty
|
||||||
|
|
||||||
|
if (std::find(m_mapSongsByDifficulty[pSteps->GetMeter()].begin(), m_mapSongsByDifficulty[pSteps->GetMeter()].end(), apDifficultSongs[i]) != m_mapSongsByDifficulty[pSteps->GetMeter()].end())
|
||||||
|
continue;
|
||||||
|
else {
|
||||||
|
m_mapSongsByDifficulty[pSteps->GetMeter()].push_back(apDifficultSongs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each meter in m_mapSongsByDifficulty, sort the songs by title
|
||||||
|
for( unsigned i = 0; i < m_mapSongsByDifficulty.size(); ++i )
|
||||||
|
{
|
||||||
|
SongUtil::SortSongPointerArrayByTitle( m_mapSongsByDifficulty[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SongManager::UpdateShuffled()
|
void SongManager::UpdateShuffled()
|
||||||
{
|
{
|
||||||
// update shuffled
|
// update shuffled
|
||||||
|
|||||||
+7
-1
@@ -142,13 +142,14 @@ public:
|
|||||||
* @return the songs within the game that have at least one valid Step. */
|
* @return the songs within the game that have at least one valid Step. */
|
||||||
const std::vector<Song *> &GetAllSongsOfCurrentGame() const;
|
const std::vector<Song *> &GetAllSongsOfCurrentGame() const;
|
||||||
|
|
||||||
|
std::map<int, std::vector<Song*>> GetMeterToSongsMap() const { return m_mapSongsByDifficulty; }
|
||||||
void GetPreferredSortSongs( std::vector<Song*> &AddTo ) const;
|
void GetPreferredSortSongs( std::vector<Song*> &AddTo ) const;
|
||||||
std::map<RString, std::vector<Song*>> GetPreferredSortSongsMap() const { return m_mapPreferredSectionToSongs;};
|
std::map<RString, std::vector<Song*>> GetPreferredSortSongsMap() const { return m_mapPreferredSectionToSongs;};
|
||||||
RString SongToPreferredSortSectionName( const Song *pSong ) const;
|
RString SongToPreferredSortSectionName( const Song *pSong ) const;
|
||||||
std::vector<RString> GetPreferredSortSectionNames() const;
|
std::vector<RString> GetPreferredSortSectionNames() const;
|
||||||
std::vector<Song*> GetPreferredSortSongsBySectionName( const RString &sSectionName ) const;
|
std::vector<Song*> GetPreferredSortSongsBySectionName( const RString &sSectionName ) const;
|
||||||
void GetPreferredSortSongsBySectionName( const RString &sSectionName, std::vector<Song*> &AddTo ) const;
|
void GetPreferredSortSongsBySectionName( const RString &sSectionName, std::vector<Song*> &AddTo ) const;
|
||||||
|
std::vector<Song*> GetSongsByMeter( int iMeter ) const;
|
||||||
const std::vector<Course*> &GetPopularCourses( CourseType ct ) const { return m_pPopularCourses[ct]; }
|
const std::vector<Course*> &GetPopularCourses( CourseType ct ) const { return m_pPopularCourses[ct]; }
|
||||||
Song *FindSong( RString sPath ) const;
|
Song *FindSong( RString sPath ) const;
|
||||||
Song *FindSong( RString sGroup, RString sSong ) const;
|
Song *FindSong( RString sGroup, RString sSong ) const;
|
||||||
@@ -188,6 +189,7 @@ public:
|
|||||||
|
|
||||||
void UpdatePopular();
|
void UpdatePopular();
|
||||||
void UpdateShuffled(); // re-shuffle songs and courses
|
void UpdateShuffled(); // re-shuffle songs and courses
|
||||||
|
void UpdateMeterSort();
|
||||||
void SetPreferredSongs(RString sPreferredSongs, bool bIsAbsolute = false);
|
void SetPreferredSongs(RString sPreferredSongs, bool bIsAbsolute = false);
|
||||||
void SetPreferredCourses(RString sPreferredCourses, bool bIsAbsolute = false);
|
void SetPreferredCourses(RString sPreferredCourses, bool bIsAbsolute = false);
|
||||||
void UpdatePreferredSort(RString sPreferredSongs = "PreferredSongs.txt", RString sPreferredCourses = "PreferredCourses.txt");
|
void UpdatePreferredSort(RString sPreferredSongs = "PreferredSongs.txt", RString sPreferredCourses = "PreferredCourses.txt");
|
||||||
@@ -225,6 +227,10 @@ protected:
|
|||||||
/** @brief The most popular songs ranked by number of plays. */
|
/** @brief The most popular songs ranked by number of plays. */
|
||||||
std::vector<Song*> m_pPopularSongs;
|
std::vector<Song*> m_pPopularSongs;
|
||||||
std::vector<Song*> m_pShuffledSongs; // used by GetRandomSong
|
std::vector<Song*> m_pShuffledSongs; // used by GetRandomSong
|
||||||
|
|
||||||
|
/** @brief Meter numbers and the songs with Steps that are within.*/
|
||||||
|
std::map<int, std::vector<Song*>> m_mapSongsByDifficulty;
|
||||||
|
|
||||||
struct PreferredSortSection
|
struct PreferredSortSection
|
||||||
{
|
{
|
||||||
RString sName;
|
RString sName;
|
||||||
|
|||||||
@@ -543,6 +543,7 @@ void SongUtil::SortSongPointerArrayByDisplayArtist( std::vector<Song*> &vpSongsI
|
|||||||
stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending );
|
stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CompareSongPointersByGenre(const Song *pSong1, const Song *pSong2)
|
static int CompareSongPointersByGenre(const Song *pSong1, const Song *pSong2)
|
||||||
{
|
{
|
||||||
return pSong1->m_sGenre < pSong2->m_sGenre;
|
return pSong1->m_sGenre < pSong2->m_sGenre;
|
||||||
@@ -720,6 +721,8 @@ RString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so
|
|||||||
return ssprintf("%02d", pSteps->GetMeter() );
|
return ssprintf("%02d", pSteps->GetMeter() );
|
||||||
return SORT_NOT_AVAILABLE.GetValue();
|
return SORT_NOT_AVAILABLE.GetValue();
|
||||||
}
|
}
|
||||||
|
case SORT_METER:
|
||||||
|
return RString();
|
||||||
case SORT_MODE_MENU:
|
case SORT_MODE_MENU:
|
||||||
return RString();
|
return RString();
|
||||||
case SORT_ALL_COURSES:
|
case SORT_ALL_COURSES:
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ namespace SongUtil
|
|||||||
void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, ProfileSlot slot, bool bDescending );
|
void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, ProfileSlot slot, bool bDescending );
|
||||||
void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, const Profile* pProfile, bool bDescending );
|
void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, const Profile* pProfile, bool bDescending );
|
||||||
void SortSongPointerArrayByStepsTypeAndMeter( std::vector<Song*> &vpSongsInOut, StepsType st, Difficulty dc );
|
void SortSongPointerArrayByStepsTypeAndMeter( std::vector<Song*> &vpSongsInOut, StepsType st, Difficulty dc );
|
||||||
|
void SortSongPointerArrayByStepsTypeAndLevel( std::vector<Song*> &vpSongsInOut, StepsType st, int iMeter );
|
||||||
RString GetSectionNameFromSongAndSort( const Song *pSong, SortOrder so );
|
RString GetSectionNameFromSongAndSort( const Song *pSong, SortOrder so );
|
||||||
void SortSongPointerArrayBySectionName( std::vector<Song*> &vpSongsInOut, SortOrder so );
|
void SortSongPointerArrayBySectionName( std::vector<Song*> &vpSongsInOut, SortOrder so );
|
||||||
void SortByMostRecentlyPlayedForMachine( std::vector<Song*> &vpSongsInOut );
|
void SortByMostRecentlyPlayedForMachine( std::vector<Song*> &vpSongsInOut );
|
||||||
|
|||||||
@@ -1006,6 +1006,7 @@ int sm_main(int argc, char* argv[])
|
|||||||
UNLOCKMAN = new UnlockManager;
|
UNLOCKMAN = new UnlockManager;
|
||||||
SONGMAN->UpdatePopular();
|
SONGMAN->UpdatePopular();
|
||||||
SONGMAN->UpdatePreferredSort();
|
SONGMAN->UpdatePreferredSort();
|
||||||
|
SONGMAN->UpdateMeterSort();
|
||||||
NETWORK = new NetworkManager;
|
NETWORK = new NetworkManager;
|
||||||
STATSMAN = new StatsManager;
|
STATSMAN = new StatsManager;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user