* Save and use usernames in replay files Fixes #2754. * Store usernames of each racer in recorded replay files * Display those usernames in a column of the replay selection UI and in race result dialogs * RaceResultGUI::getKartDisplayName functionality moved into Controller::getName * Move Controller::getName definition to avoid unnecessary #include * Backwards compatibility: use kart name if username is not in replay * Fix code style issues
This commit is contained in:
parent
623bb460c6
commit
a73af6eb0d
@ -34,3 +34,8 @@ Controller::Controller(AbstractKart *kart)
|
||||
m_kart = kart;
|
||||
setControllerName("Controller");
|
||||
} // Controller
|
||||
|
||||
core::stringw Controller::getName() const
|
||||
{
|
||||
return translations->fribidize(m_kart->getName());
|
||||
}
|
||||
|
@ -100,17 +100,16 @@ public:
|
||||
/** Only local players can get achievements. */
|
||||
virtual bool canGetAchievements () const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** This should only be called for End- and LocalPlayer-Controller. */
|
||||
virtual core::stringw getName() const
|
||||
{
|
||||
assert(false);
|
||||
return core::stringw("");
|
||||
} // getName
|
||||
/** Display name of the controller.
|
||||
* Defaults to kart name; overriden by controller classes
|
||||
* (such as player controllers) to display username. */
|
||||
virtual core::stringw getName() const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the kart controlled by this controller. */
|
||||
AbstractKart *getKart() const { return m_kart; }
|
||||
}; // Controller
|
||||
|
||||
extern Translations* translations;
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
@ -21,9 +21,10 @@
|
||||
#include "karts/controller/kart_control.hpp"
|
||||
#include "modes/world.hpp"
|
||||
|
||||
GhostController::GhostController(AbstractKart *kart)
|
||||
GhostController::GhostController(AbstractKart *kart, core::stringw display_name)
|
||||
: Controller(kart)
|
||||
{
|
||||
m_display_name = display_name;
|
||||
} // GhostController
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -37,11 +37,14 @@ private:
|
||||
/** The current world time. */
|
||||
float m_current_time;
|
||||
|
||||
/** Player name of the ghost kart. */
|
||||
core::stringw m_display_name;
|
||||
|
||||
/** The list of the times at which the events of kart were reached. */
|
||||
std::vector<float> m_all_times;
|
||||
|
||||
public:
|
||||
GhostController(AbstractKart *kart);
|
||||
GhostController(AbstractKart *kart, core::stringw display_name);
|
||||
virtual ~GhostController() {};
|
||||
virtual void reset() OVERRIDE;
|
||||
virtual void update (float dt) OVERRIDE;
|
||||
@ -73,6 +76,11 @@ public:
|
||||
unsigned int getCurrentReplayIndex() const
|
||||
{ return m_current_index; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the display name; if not set, use default display name (kart name) */
|
||||
core::stringw getName() const OVERRIDE
|
||||
{
|
||||
return m_display_name.empty() ? Controller::getName() : m_display_name;
|
||||
}
|
||||
}; // GhostController
|
||||
|
||||
#endif
|
||||
|
@ -135,13 +135,31 @@ bool ReplayPlay::addReplayFile(const std::string& fn, bool custom_replay)
|
||||
is_end.trim();
|
||||
if (is_end == "kart_list_end") break;
|
||||
char s1[1024];
|
||||
char display_name_encoded[1024];
|
||||
|
||||
if (sscanf(s,"kart: %s", s1) != 1)
|
||||
int scanned = sscanf(s,"kart: %s %[^\n]", s1, display_name_encoded);
|
||||
if (scanned < 1)
|
||||
{
|
||||
Log::warn("Replay", "Could not read ghost karts info!");
|
||||
break;
|
||||
}
|
||||
|
||||
rd.m_kart_list.push_back(std::string(s1));
|
||||
if (scanned == 2)
|
||||
{
|
||||
// If username of kart is present, use it
|
||||
rd.m_name_list.push_back(StringUtils::xmlDecode(std::string(display_name_encoded)));
|
||||
if (rd.m_name_list.size() == 1)
|
||||
{
|
||||
// First user is the game master and the "owner" of this replay file
|
||||
rd.m_user_name = rd.m_name_list[0];
|
||||
}
|
||||
} else
|
||||
{ // scanned == 1
|
||||
// If username is not present, kart display name will default to kart name
|
||||
// (see GhostController::getName)
|
||||
rd.m_name_list.push_back("");
|
||||
}
|
||||
}
|
||||
|
||||
int reverse = 0;
|
||||
@ -249,11 +267,12 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line)
|
||||
{
|
||||
char s[1024];
|
||||
const unsigned int kart_num = m_ghost_karts.size();
|
||||
m_ghost_karts.push_back(new GhostKart(m_replay_file_list
|
||||
[m_current_replay_file].m_kart_list.at(kart_num),
|
||||
kart_num, kart_num + 1));
|
||||
ReplayData &rd = m_replay_file_list[m_current_replay_file];
|
||||
m_ghost_karts.push_back(new GhostKart(rd.m_kart_list.at(kart_num),
|
||||
kart_num, kart_num + 1));
|
||||
m_ghost_karts[kart_num].init(RaceManager::KT_GHOST);
|
||||
Controller* controller = new GhostController(getGhostKart(kart_num));
|
||||
Controller* controller = new GhostController(getGhostKart(kart_num),
|
||||
rd.m_name_list[kart_num]);
|
||||
getGhostKart(kart_num)->setController(controller);
|
||||
|
||||
unsigned int size;
|
||||
|
@ -45,20 +45,23 @@ public:
|
||||
SO_KART_NUM,
|
||||
SO_DIFF,
|
||||
SO_LAPS,
|
||||
SO_TIME
|
||||
SO_TIME,
|
||||
SO_USER
|
||||
};
|
||||
|
||||
class ReplayData
|
||||
{
|
||||
public:
|
||||
std::string m_filename;
|
||||
std::string m_track_name;
|
||||
std::vector<std::string> m_kart_list;
|
||||
bool m_reverse;
|
||||
bool m_custom_replay_file;
|
||||
unsigned int m_difficulty;
|
||||
unsigned int m_laps;
|
||||
float m_min_time;
|
||||
std::string m_filename;
|
||||
std::string m_track_name;
|
||||
core::stringw m_user_name;
|
||||
std::vector<std::string> m_kart_list;
|
||||
std::vector<core::stringw> m_name_list;
|
||||
bool m_reverse;
|
||||
bool m_custom_replay_file;
|
||||
unsigned int m_difficulty;
|
||||
unsigned int m_laps;
|
||||
float m_min_time;
|
||||
|
||||
bool operator < (const ReplayData& r) const
|
||||
{
|
||||
@ -82,6 +85,9 @@ public:
|
||||
case SO_TIME:
|
||||
return m_min_time < r.m_min_time;
|
||||
break;
|
||||
case SO_USER:
|
||||
return m_user_name < r.m_user_name;
|
||||
break;
|
||||
} // switch
|
||||
return true;
|
||||
} // operator <
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <karts/controller/player_controller.hpp>
|
||||
|
||||
ReplayRecorder *ReplayRecorder::m_replay_recorder = NULL;
|
||||
|
||||
@ -222,9 +223,12 @@ void ReplayRecorder::save()
|
||||
fprintf(fd, "version: %d\n", getReplayVersion());
|
||||
for (unsigned int real_karts = 0; real_karts < num_karts; real_karts++)
|
||||
{
|
||||
if (world->getKart(real_karts)->isGhostKart()) continue;
|
||||
fprintf(fd, "kart: %s\n",
|
||||
world->getKart(real_karts)->getIdent().c_str());
|
||||
const AbstractKart *kart = world->getKart(real_karts);
|
||||
if (kart->isGhostKart()) continue;
|
||||
|
||||
// XML encode the username to handle Unicode
|
||||
fprintf(fd, "kart: %s %s\n", kart->getIdent().c_str(),
|
||||
StringUtils::xmlEncode(kart->getController()->getName()).c_str());
|
||||
}
|
||||
|
||||
fprintf(fd, "kart_list_end\n");
|
||||
|
@ -80,6 +80,7 @@ void GhostReplaySelection::beforeAddingWidget()
|
||||
m_replay_list_widget->addColumn( _("Difficulty"), 1);
|
||||
m_replay_list_widget->addColumn( _("Laps"), 1);
|
||||
m_replay_list_widget->addColumn( _("Finish Time"), 1);
|
||||
m_replay_list_widget->addColumn( _("User"), 1);
|
||||
} // beforeAddingWidget
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -122,6 +123,8 @@ void GhostReplaySelection::loadList()
|
||||
(StringUtils::toWString(rd.m_laps), -1, 1, true));
|
||||
row.push_back(GUIEngine::ListWidget::ListCell
|
||||
(StringUtils::toWString(rd.m_min_time) + L"s", -1, 1, true));
|
||||
row.push_back(GUIEngine::ListWidget::ListCell
|
||||
(rd.m_user_name, -1, 1, true));
|
||||
m_replay_list_widget->addItem(StringUtils::toString(i), row);
|
||||
}
|
||||
} // loadList
|
||||
@ -213,6 +216,9 @@ void GhostReplaySelection::onColumnClicked(int column_id)
|
||||
case 5:
|
||||
ReplayPlay::setSortOrder(ReplayPlay::SO_TIME);
|
||||
break;
|
||||
case 6:
|
||||
ReplayPlay::setSortOrder(ReplayPlay::SO_USER);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
|
@ -486,7 +486,7 @@ void RaceResultGUI::backToLobby()
|
||||
// Save a pointer to the current row_info entry
|
||||
RowInfo *ri = &(m_all_row_infos[position - first_position]);
|
||||
ri->m_is_player_kart = kart->getController()->isLocalPlayerController();
|
||||
ri->m_kart_name = getKartDisplayName(kart);
|
||||
ri->m_kart_name = kart->getController()->getName();
|
||||
|
||||
video::ITexture *icon =
|
||||
kart->getKartProperties()->getIconMaterial()->getTexture();
|
||||
@ -855,7 +855,7 @@ void RaceResultGUI::backToLobby()
|
||||
ri->m_kart_icon =
|
||||
kart->getKartProperties()->getIconMaterial()->getTexture();
|
||||
ri->m_is_player_kart = kart->getController()->isLocalPlayerController();
|
||||
ri->m_kart_name = getKartDisplayName(kart);
|
||||
ri->m_kart_name = kart->getController()->getName();
|
||||
|
||||
// In FTL karts do have a time, which is shown even when the kart
|
||||
// is eliminated
|
||||
@ -907,29 +907,6 @@ void RaceResultGUI::backToLobby()
|
||||
#endif
|
||||
} // determineGPLayout
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns a string to display next to a kart. For a player that's the name
|
||||
* of the player, for an AI kart it's the name of the driver.
|
||||
*/
|
||||
core::stringw RaceResultGUI::getKartDisplayName(const AbstractKart *kart) const
|
||||
{
|
||||
const EndController *ec =
|
||||
dynamic_cast<const EndController*>(kart->getController());
|
||||
// If the race was given up, there is no end controller for the
|
||||
// players, so this case needs to be handled separately
|
||||
if(ec && ec->isLocalPlayerController())
|
||||
return ec->getName();
|
||||
else
|
||||
{
|
||||
// No end controller, check explicitely for a player controller
|
||||
const PlayerController *pc =
|
||||
dynamic_cast<const PlayerController*>(kart->getController());
|
||||
// Check if the kart is a player controller to get the real name
|
||||
if(pc) return pc->getName();
|
||||
}
|
||||
return translations->fribidize(kart->getName());
|
||||
} // getKartDisplayName
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Displays the race results for a single kart.
|
||||
* \param n Index of the kart to be displayed.
|
||||
|
@ -194,7 +194,6 @@ private:
|
||||
void displayPostRaceInfo();
|
||||
void displaySoccerResults();
|
||||
void displayScreenShots();
|
||||
irr::core::stringw getKartDisplayName(const AbstractKart *kart) const;
|
||||
|
||||
int getFontHeight () const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user