Skip to content

Commit

Permalink
Groundwork for a favorite-tracks system
Browse files Browse the repository at this point in the history
- Save a per-player list of favorite tracks in the players config file
- Read said lists and setup a matching track group
- New logic for the isInGroup function to ensure favorite tracks are correctly detected and displayed in the track selection screen
- Switch the active list of favorite tracks when switching the active player profile
- Clarify some unclear comments
  • Loading branch information
Alayan-stk-2 committed Aug 7, 2024
1 parent e6d0df3 commit bf62de8
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 8 deletions.
7 changes: 7 additions & 0 deletions src/config/player_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,10 @@ void PlayerManager::initRemainingData()

// Sort player by frequency
m_all_players.insertionSort(/*start*/0, /*desc*/true);

// Load favorite tracks for the current player
if (m_current_player)
m_current_player->setFavoriteTracks();
} // initRemainingData

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -480,7 +484,10 @@ void PlayerManager::setCurrentPlayer(PlayerProfile *player)

m_current_player = player;
if(m_current_player)
{
m_current_player->computeActive();
m_current_player->setFavoriteTracks();
}

if (player_has_changed)
story_mode_timer->playerHasChanged();
Expand Down
44 changes: 41 additions & 3 deletions src/config/player_profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "online/online_player_profile.hpp"
#include "tracks/track_manager.hpp"
#include "utils/string_utils.hpp"

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -78,6 +79,7 @@ PlayerProfile::PlayerProfile(const XMLNode* node)
m_remember_password = false;
m_story_mode_status = NULL;
m_achievements_status = NULL;
m_favorite_tracks.clear();
m_default_kart_color = 0.0f;
m_icon_filename = "";

Expand Down Expand Up @@ -111,9 +113,8 @@ PlayerProfile::~PlayerProfile()


//------------------------------------------------------------------------------
/** This function loads the achievement and story mode data. These can only
* be loaded after the UnlockManager is created, which needs the karts
* and tracks to be loaded first.
/** This function loads the achievement, story mode and favorites data.
* These can only be loaded after the karts and tracks.
*/
void PlayerProfile::loadRemainingData(const XMLNode *node)
{
Expand All @@ -123,6 +124,24 @@ void PlayerProfile::loadRemainingData(const XMLNode *node)
const XMLNode *xml_achievements = node->getNode("achievements");
m_achievements_status = AchievementsManager::get()
->createAchievementsStatus(xml_achievements, m_unique_id == 1);

// We first load the list of all favorite tracks
// Some favorites may correspond to uninstalled addons, so we do not sanitize the strings
// TODO : handle Arena and Soccer fields
const XMLNode *xml_favorites = node->getNode("favorites");
std::vector<XMLNode*> xml_favorite_tracks;
xml_favorites->getNodes("track", xml_favorite_tracks);
for (unsigned int i = 0; i < xml_favorite_tracks.size(); i++)
{
std::string temp_string;
xml_favorite_tracks[i]->get("ident", &temp_string);
m_favorite_tracks.push_back(temp_string);
}
// Deduplicate the list just in case.
std::sort(m_favorite_tracks.begin(), m_favorite_tracks.end());
auto it = std::unique(m_favorite_tracks.begin(), m_favorite_tracks.end());
m_favorite_tracks.erase(it, m_favorite_tracks.end());

// Fix up any potentially missing icons.
addIcon();
} // initRemainingData
Expand All @@ -139,6 +158,16 @@ void PlayerProfile::initRemainingData()
addIcon();
} // initRemainingData

void PlayerProfile::setFavoriteTracks()
{
// Update the group data from the Track Manager
track_manager->clearFavoriteTracks();
for (unsigned int i = 0; i < m_favorite_tracks.size(); i++)
{
track_manager->addFavoriteTrack(m_favorite_tracks[i]);
}
} // setFavoriteTracks

//------------------------------------------------------------------------------
/** Creates an icon for a player if non exist so far. It takes the unique
* player id modulo the number of karts to pick an icon from the karts. It
Expand Down Expand Up @@ -201,6 +230,8 @@ const std::string PlayerProfile::getIconFilename() const
*/
void PlayerProfile::save(UTFWriter &out)
{
//m_favorite_tracks.push_back("cornfield_crossing");

out << " <player name=\"" << StringUtils::xmlEncode(m_local_name)
<< "\" guest=\"" << m_is_guest_account
<< "\" use-frequency=\"" << m_use_frequency << "\"\n";
Expand Down Expand Up @@ -228,6 +259,13 @@ void PlayerProfile::save(UTFWriter &out)

if(m_achievements_status)
m_achievements_status->save(out);

out << " <favorites>\n";
for (unsigned int i=0; i < m_favorite_tracks.size(); i++)
{
out << " <track ident=\"" << m_favorite_tracks[i] << "\"/>\n";
}
out << " </favorites>\n";
}
out << " </player>\n";
} // save
Expand Down
5 changes: 5 additions & 0 deletions src/config/player_profile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,12 @@ class PlayerProfile : public NoCopy
/** The complete challenge state. */
StoryModeStatus *m_story_mode_status;

/** The complete achievement data. */
AchievementsStatus *m_achievements_status;

/** The list of identifiers of favorite tracks .*/
std::vector<std::string> m_favorite_tracks;

public:

PlayerProfile(const core::stringw &name, bool is_guest = false);
Expand All @@ -121,6 +125,7 @@ class PlayerProfile : public NoCopy
void save(UTFWriter &out);
void loadRemainingData(const XMLNode *node);
void initRemainingData();
void setFavoriteTracks();
void incrementUseFrequency();
int getUseFrequency() const { return m_use_frequency; }
bool operator<(const PlayerProfile &other);
Expand Down
6 changes: 4 additions & 2 deletions src/states_screens/tracks_and_gp_screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ void TracksAndGPScreen::beforeAddingWidget()
//I18N: track group name
FOR_GETTEXT_ONLY( _("All") )
//I18N: track group name
FOR_GETTEXT_ONLY( _("Favorites") )
//I18N: track group name
FOR_GETTEXT_ONLY( _("Standard") )
//I18N: track group name
FOR_GETTEXT_ONLY( _("Add-Ons") )
Expand Down Expand Up @@ -250,8 +252,8 @@ void TracksAndGPScreen::init()
} // init

// -----------------------------------------------------------------------------
/** Rebuild the list of tracks and GPs. This need to be recomputed e.g. to
* take unlocked tracks into account.
/** Rebuild the list of tracks and GPs. This need to be recomputed to
* take unlocked tracks into account, when changing the current track group, etc.
*/
void TracksAndGPScreen::buildTrackList()
{
Expand Down
8 changes: 8 additions & 0 deletions src/tracks/track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ core::stringw Track::getSortName() const
*/
bool Track::isInGroup(const std::string &group_name)
{
if (group_name == "Favorites")
{
int index = track_manager->getTrackIndexByIdent(m_ident);
std::vector<int> favorite_list = track_manager->getTracksInGroup("Favorites");
return std::find(favorite_list.begin(), favorite_list.end(), index)
!= favorite_list.end();
}

return std::find(m_groups.begin(), m_groups.end(), group_name)
!= m_groups.end();
} // isInGroup
Expand Down
24 changes: 24 additions & 0 deletions src/tracks/track_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ void TrackManager::loadTrackList()
delete track;
m_tracks.clear();

// Add the special favorites group
m_track_group_names.push_back("Favorites");

for(unsigned int i=0; i<m_track_search_path.size(); i++)
{
const std::string &dir = m_track_search_path[i];
Expand Down Expand Up @@ -312,6 +315,7 @@ void TrackManager::updateGroups(const Track* track)
{
if (track->isInternal()) return;

//TODO : ignore self-declarations from tracks as being in the "favorites" group
const std::vector<std::string>& new_groups = track->getGroups();

Group2Indices &group_2_indices =
Expand All @@ -335,6 +339,26 @@ void TrackManager::updateGroups(const Track* track)
}
} // updateGroups

// ----------------------------------------------------------------------------
/** \brief Adds a track to the favorite track group
*/
void TrackManager::addFavoriteTrack(const std::string& ident)
{
// TODO : check if the ident corresponds to a race-track
int index = getTrackIndexByIdent(ident);
if (index >= 0) // index is negative if a track matching the index is missing
m_track_groups["Favorites"].push_back(index);
} // addFavoriteTrack

// ----------------------------------------------------------------------------
/** \brief Clears the list of active favorite tracks, used e.g. when switching
* between player profiles.
*/
void TrackManager::clearFavoriteTracks()
{
m_track_groups["Favorites"].clear();
} // clearFavoriteTracks

// ----------------------------------------------------------------------------
int TrackManager::getTrackIndexByIdent(const std::string& ident) const
{
Expand Down
14 changes: 11 additions & 3 deletions src/tracks/track_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ class TrackManager
Tracks m_tracks;

typedef std::map<std::string, std::vector<int> > Group2Indices;
/** List of all racing track groups. */
/** List of all track indexes for each racing track group. */
Group2Indices m_track_groups;

/** List of all arena groups. */
/** List of all arena indexes for each arena group. */
Group2Indices m_arena_groups;

/** List of all soccer arena groups. */
/** List of all soccer arena indexes for each soccer arena group. */
Group2Indices m_soccer_arena_groups;

/** List of the names of all groups containing tracks */
Expand All @@ -74,6 +74,14 @@ class TrackManager
~TrackManager();
static void removeTrackSearchDirs();
static void addTrackSearchDir(const std::string &dir);

/** Adds a track to the special group of favorite tracks.
* We need a special treatment, because the list of tracks in this group
* depends on the player-profile, not on the track data. */
void addFavoriteTrack(const std::string& ident);

void clearFavoriteTracks();

/** Returns a list of all track identifiers. */
std::vector<std::string> getAllTrackIdentifiers();

Expand Down

0 comments on commit bf62de8

Please sign in to comment.