Add save and restore complete state for soccer world

This commit is contained in:
Benau 2019-01-04 14:01:31 +08:00
parent 17ecbe69af
commit 62ce61d980
3 changed files with 150 additions and 76 deletions

View File

@ -143,9 +143,7 @@ void SoccerWorld::reset(bool restart)
m_count_down_reached_zero = false; m_count_down_reached_zero = false;
m_red_scorers.clear(); m_red_scorers.clear();
m_red_score_times.clear();
m_blue_scorers.clear(); m_blue_scorers.clear();
m_blue_score_times.clear();
m_ball_hitter = -1; m_ball_hitter = -1;
m_red_kdm.clear(); m_red_kdm.clear();
m_blue_kdm.clear(); m_blue_kdm.clear();
@ -277,9 +275,11 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
m_goal_frame.push_back(m_frame_count - elapsed_frame); m_goal_frame.push_back(m_frame_count - elapsed_frame);
} }
ScorerData sd; ScorerData sd = {};
sd.m_id = m_ball_hitter; sd.m_id = m_ball_hitter;
sd.m_correct_goal = isCorrectGoal(m_ball_hitter, first_goal); sd.m_correct_goal = isCorrectGoal(m_ball_hitter, first_goal);
sd.m_kart = getKart(m_ball_hitter)->getIdent();
sd.m_player = getKart(m_ball_hitter)->getController()->getName();
if (sd.m_correct_goal) if (sd.m_correct_goal)
{ {
@ -293,30 +293,27 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/); ->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/);
} }
float score_time = 0.0f;
if (first_goal) if (first_goal)
{ {
if (race_manager->hasTimeTarget())
{
sd.m_time = race_manager->getTimeTarget() - getTime();
}
else
sd.m_time = getTime();
// Notice: true first_goal means it's blue goal being shoot, // Notice: true first_goal means it's blue goal being shoot,
// so red team can score // so red team can score
m_red_scorers.push_back(sd); m_red_scorers.push_back(sd);
if (race_manager->hasTimeTarget())
{
score_time = race_manager->getTimeTarget() - getTime();
}
else
score_time = getTime();
m_red_score_times.push_back(score_time);
} }
else else
{ {
m_blue_scorers.push_back(sd);
if (race_manager->hasTimeTarget()) if (race_manager->hasTimeTarget())
{ {
score_time = race_manager->getTimeTarget() - getTime(); sd.m_time = race_manager->getTimeTarget() - getTime();
} }
else else
score_time = getTime(); sd.m_time = getTime();
m_blue_score_times.push_back(score_time); m_blue_scorers.push_back(sd);
} }
if (NetworkConfig::get()->isNetworking() && if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isServer()) NetworkConfig::get()->isServer())
@ -325,9 +322,11 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
p.setSynchronous(true); p.setSynchronous(true);
p.addUInt8(GameEventsProtocol::GE_PLAYER_GOAL) p.addUInt8(GameEventsProtocol::GE_PLAYER_GOAL)
.addUInt8((uint8_t)sd.m_id).addUInt8(sd.m_correct_goal) .addUInt8((uint8_t)sd.m_id).addUInt8(sd.m_correct_goal)
.addUInt8(first_goal).addFloat(score_time) .addUInt8(first_goal).addFloat(sd.m_time)
.addTime(World::getWorld()->getTicksSinceStart() + .addTime(World::getWorld()->getTicksSinceStart() +
stk_config->time2Ticks(3.0f)); stk_config->time2Ticks(3.0f))
.encodeString(sd.m_kart)
.encodeString(sd.m_player);
STKHost::get()->sendPacketToAllPeers(&p, true); STKHost::get()->sendPacketToAllPeers(&p, true);
} }
} }
@ -346,6 +345,9 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SoccerWorld::handleResetBallFromServer(const NetworkString& ns) void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
{ {
// Ignore in live join
if (isStartPhase())
return;
int ticks_now = World::getWorld()->getTicksSinceStart(); int ticks_now = World::getWorld()->getTicksSinceStart();
int ticks_back_to_own_goal = ns.getTime(); int ticks_back_to_own_goal = ns.getTime();
if (ticks_now >= ticks_back_to_own_goal) if (ticks_now >= ticks_back_to_own_goal)
@ -363,11 +365,38 @@ void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns) void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
{ {
ScorerData sd; ScorerData sd = {};
sd.m_id = ns.getUInt8(); sd.m_id = ns.getUInt8();
sd.m_correct_goal = ns.getUInt8() == 1; sd.m_correct_goal = ns.getUInt8() == 1;
bool first_goal = ns.getUInt8() == 1; bool first_goal = ns.getUInt8() == 1;
float score_time = ns.getFloat(); sd.m_time = ns.getFloat();
int ticks_now = World::getWorld()->getTicksSinceStart();
int ticks_back_to_own_goal = ns.getTime();
try
{
ns.decodeString(&sd.m_kart);
ns.decodeStringW(&sd.m_player);
}
catch (std::exception &e)
{
sd.m_kart = getKart(sd.m_id)->getIdent();
sd.m_player = getKart(sd.m_id)->getController()->getName();
(void)e;
}
if (first_goal)
{
m_red_scorers.push_back(sd);
}
else
{
m_blue_scorers.push_back(sd);
}
// Ignore in live join
if (isStartPhase())
return;
if (sd.m_correct_goal) if (sd.m_correct_goal)
{ {
m_karts[sd.m_id]->getKartModel() m_karts[sd.m_id]->getKartModel()
@ -379,19 +408,6 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/); ->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/);
} }
if (first_goal)
{
m_red_scorers.push_back(sd);
m_red_score_times.push_back(score_time);
}
else
{
m_blue_scorers.push_back(sd);
m_blue_score_times.push_back(score_time);
}
int ticks_now = World::getWorld()->getTicksSinceStart();
int ticks_back_to_own_goal = ns.getTime();
if (ticks_now >= ticks_back_to_own_goal) if (ticks_now >= ticks_back_to_own_goal)
{ {
Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks " Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks "
@ -751,3 +767,60 @@ void SoccerWorld::enterRaceOverState()
} }
} // enterRaceOverState } // enterRaceOverState
// ----------------------------------------------------------------------------
void SoccerWorld::saveCompleteState(BareNetworkString* bns)
{
const unsigned red_scorers = m_red_scorers.size();
bns->addUInt32(red_scorers);
for (unsigned i = 0; i < red_scorers; i++)
{
bns->addUInt8((uint8_t)m_red_scorers[i].m_id)
.addUInt8(m_red_scorers[i].m_correct_goal)
.addFloat(m_red_scorers[i].m_time)
.encodeString(m_red_scorers[i].m_kart)
.encodeString(m_red_scorers[i].m_player);
}
const unsigned blue_scorers = m_blue_scorers.size();
bns->addUInt32(blue_scorers);
for (unsigned i = 0; i < blue_scorers; i++)
{
bns->addUInt8((uint8_t)m_blue_scorers[i].m_id)
.addUInt8(m_blue_scorers[i].m_correct_goal)
.addFloat(m_blue_scorers[i].m_time)
.encodeString(m_blue_scorers[i].m_kart)
.encodeString(m_blue_scorers[i].m_player);
}
} // saveCompleteState
// ----------------------------------------------------------------------------
void SoccerWorld::restoreCompleteState(const BareNetworkString& b)
{
m_red_scorers.clear();
m_blue_scorers.clear();
const unsigned red_size = b.getUInt32();
for (unsigned i = 0; i < red_size; i++)
{
ScorerData sd;
sd.m_id = b.getUInt8();
sd.m_correct_goal = b.getUInt8() == 1;
sd.m_time = b.getFloat();
b.decodeString(&sd.m_kart);
b.decodeStringW(&sd.m_player);
m_red_scorers.push_back(sd);
}
const unsigned blue_size = b.getUInt32();
for (unsigned i = 0; i < blue_size; i++)
{
ScorerData sd;
sd.m_id = b.getUInt8();
sd.m_correct_goal = b.getUInt8() == 1;
sd.m_time = b.getFloat();
b.decodeString(&sd.m_kart);
b.decodeStringW(&sd.m_player);
m_blue_scorers.push_back(sd);
}
} // restoreCompleteState

View File

@ -41,13 +41,18 @@ class TrackSector;
class SoccerWorld : public WorldWithRank class SoccerWorld : public WorldWithRank
{ {
public: public:
class ScorerData struct ScorerData
{ {
public:
/** World ID of kart which scores. */ /** World ID of kart which scores. */
unsigned int m_id; unsigned int m_id;
/** Whether this goal is socred correctly (identify for own goal). */ /** Whether this goal is socred correctly (identify for own goal). */
bool m_correct_goal; bool m_correct_goal;
/** Time goal. */
float m_time;
/** Kart ident which scores. */
std::string m_kart;
/** Player name which scores. */
core::stringw m_player;
}; // ScorerData }; // ScorerData
private: private:
@ -274,9 +279,7 @@ private:
/** Goals data of each team scored */ /** Goals data of each team scored */
std::vector<ScorerData> m_red_scorers; std::vector<ScorerData> m_red_scorers;
std::vector<float> m_red_score_times;
std::vector<ScorerData> m_blue_scorers; std::vector<ScorerData> m_blue_scorers;
std::vector<float> m_blue_score_times;
/** Data generated from navmesh */ /** Data generated from navmesh */
TrackSector* m_ball_track_sector; TrackSector* m_ball_track_sector;
@ -347,12 +350,6 @@ public:
const std::vector<ScorerData>& getScorers(KartTeam team) const const std::vector<ScorerData>& getScorers(KartTeam team) const
{ return (team == KART_TEAM_BLUE ? m_blue_scorers : m_red_scorers); } { return (team == KART_TEAM_BLUE ? m_blue_scorers : m_red_scorers); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
const std::vector<float>& getScoreTimes(KartTeam team) const
{
return (team == KART_TEAM_BLUE ?
m_blue_score_times : m_red_score_times);
}
// ------------------------------------------------------------------------
int getBallNode() const; int getBallNode() const;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
const Vec3& getBallPosition() const const Vec3& getBallPosition() const
@ -417,6 +414,10 @@ public:
} }
return progress; return progress;
} }
// ------------------------------------------------------------------------
virtual void saveCompleteState(BareNetworkString* bns) OVERRIDE;
// ------------------------------------------------------------------------
virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE;
}; // SoccerWorld }; // SoccerWorld

View File

@ -1286,16 +1286,12 @@ void RaceResultGUI::displayCTFResults()
current_y += rect.Height / 2 + rect.Height / 4; current_y += rect.Height / 2 + rect.Height / 4;
font = GUIEngine::getSmallFont(); font = GUIEngine::getSmallFont();
std::vector<SoccerWorld::ScorerData> scorers = sw->getScorers(KART_TEAM_RED); std::vector<SoccerWorld::ScorerData> scorers = sw->getScorers(KART_TEAM_RED);
// Maximum 10 scorers displayed in result screen
while (scorers.size() > 10) while (scorers.size() > 10)
{ {
scorers.erase(scorers.begin()); scorers.erase(scorers.begin());
} }
std::vector<float> score_times = sw->getScoreTimes(KART_TEAM_RED);
while (score_times.size() > 10)
{
score_times.erase(score_times.begin());
}
irr::video::ITexture* scorer_icon;
int prev_y = current_y; int prev_y = current_y;
@ -1303,8 +1299,7 @@ void RaceResultGUI::displayCTFResults()
{ {
const bool own_goal = !(scorers.at(i).m_correct_goal); const bool own_goal = !(scorers.at(i).m_correct_goal);
const int kart_id = scorers.at(i).m_id; result_text = scorers.at(i).m_player;
result_text = sw->getKart(kart_id)->getController()->getName();
if (own_goal) if (own_goal)
{ {
@ -1314,7 +1309,7 @@ void RaceResultGUI::displayCTFResults()
} }
result_text.append(" "); result_text.append(" ");
result_text.append(StringUtils::timeToString(score_times.at(i)).c_str()); result_text.append(StringUtils::timeToString(scorers.at(i).m_time).c_str());
rect = font->getDimension(result_text.c_str()); rect = font->getDimension(result_text.c_str());
if (height - prev_y < ((short)scorers.size() + 1)*(short)rect.Height) if (height - prev_y < ((short)scorers.size() + 1)*(short)rect.Height)
@ -1327,34 +1322,35 @@ void RaceResultGUI::displayCTFResults()
pos = core::rect<s32>(current_x, current_y, current_x, current_y); pos = core::rect<s32>(current_x, current_y, current_x, current_y);
font->draw(result_text, pos, (own_goal ? font->draw(result_text, pos, (own_goal ?
video::SColor(255, 255, 0, 0) : color), true, false); video::SColor(255, 255, 0, 0) : color), true, false);
scorer_icon = sw->getKart(scorers.at(i).m_id) irr::video::ITexture* scorer_icon = NULL;
->getKartProperties()->getIconMaterial()->getTexture(); const KartProperties* kp = kart_properties_manager->getKart(scorers.at(i).m_kart);
source_rect = core::recti(core::vector2di(0, 0), scorer_icon->getSize()); if (kp)
irr::u32 offset_x = (irr::u32)(font->getDimension(result_text.c_str()).Width / 1.5f); scorer_icon = kp->getIconMaterial()->getTexture();
dest_rect = core::recti(current_x - offset_x - 30, current_y, current_x - offset_x, current_y + 30); if (scorer_icon)
draw2DImage(scorer_icon, dest_rect, source_rect, {
NULL, NULL, true); source_rect = core::recti(core::vector2di(0, 0), scorer_icon->getSize());
irr::u32 offset_x = (irr::u32)(font->getDimension(result_text.c_str()).Width / 1.5f);
core::recti r = core::recti(current_x - offset_x - 30, current_y, current_x - offset_x, current_y + 30);
draw2DImage(scorer_icon, r, source_rect,
NULL, NULL, true);
}
} }
//The blue scorers: //The blue scorers:
current_y = prev_y; current_y = prev_y;
current_x += UserConfigParams::m_width / 2 - red_icon->getSize().Width / 2; current_x += UserConfigParams::m_width / 2 - red_icon->getSize().Width / 2;
scorers = sw->getScorers(KART_TEAM_BLUE); scorers = sw->getScorers(KART_TEAM_BLUE);
while (scorers.size() > 10) while (scorers.size() > 10)
{ {
scorers.erase(scorers.begin()); scorers.erase(scorers.begin());
} }
score_times = sw->getScoreTimes(KART_TEAM_BLUE);
while (score_times.size() > 10)
{
score_times.erase(score_times.begin());
}
for (unsigned int i = 0; i < scorers.size(); i++) for (unsigned int i = 0; i < scorers.size(); i++)
{ {
const bool own_goal = !(scorers.at(i).m_correct_goal); const bool own_goal = !(scorers.at(i).m_correct_goal);
const int kart_id = scorers.at(i).m_id; result_text = scorers.at(i).m_player;
result_text = sw->getKart(kart_id)->getController()->getName();
if (own_goal) if (own_goal)
{ {
@ -1363,7 +1359,7 @@ void RaceResultGUI::displayCTFResults()
} }
result_text.append(" "); result_text.append(" ");
result_text.append(StringUtils::timeToString(score_times.at(i)).c_str()); result_text.append(StringUtils::timeToString(scorers.at(i).m_time).c_str());
rect = font->getDimension(result_text.c_str()); rect = font->getDimension(result_text.c_str());
if (height - prev_y < ((short)scorers.size() + 1)*(short)rect.Height) if (height - prev_y < ((short)scorers.size() + 1)*(short)rect.Height)
@ -1376,14 +1372,18 @@ void RaceResultGUI::displayCTFResults()
pos = core::rect<s32>(current_x, current_y, current_x, current_y); pos = core::rect<s32>(current_x, current_y, current_x, current_y);
font->draw(result_text, pos, (own_goal ? font->draw(result_text, pos, (own_goal ?
video::SColor(255, 255, 0, 0) : color), true, false); video::SColor(255, 255, 0, 0) : color), true, false);
scorer_icon = sw->getKart(scorers.at(i).m_id)-> irr::video::ITexture* scorer_icon = NULL;
getKartProperties()->getIconMaterial()->getTexture(); const KartProperties* kp = kart_properties_manager->getKart(scorers.at(i).m_kart);
source_rect = core::recti(core::vector2di(0, 0), scorer_icon->getSize()); if (kp)
irr::u32 offset_x = (irr::u32)(font->getDimension(result_text.c_str()).Width / 1.5f); scorer_icon = kp->getIconMaterial()->getTexture();
if (scorer_icon)
dest_rect = core::recti(current_x - offset_x - 30, current_y, current_x - offset_x, current_y + 30); {
draw2DImage(scorer_icon, dest_rect, source_rect, source_rect = core::recti(core::vector2di(0, 0), scorer_icon->getSize());
NULL, NULL, true); irr::u32 offset_x = (irr::u32)(font->getDimension(result_text.c_str()).Width / 1.5f);
core::recti r = core::recti(current_x - offset_x - 30, current_y, current_x - offset_x, current_y + 30);
draw2DImage(scorer_icon, r, source_rect,
NULL, NULL, true);
}
} }
#endif #endif
} }