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_red_scorers.clear();
m_red_score_times.clear();
m_blue_scorers.clear();
m_blue_score_times.clear();
m_ball_hitter = -1;
m_red_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);
}
ScorerData sd;
ScorerData sd = {};
sd.m_id = m_ball_hitter;
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)
{
@ -293,30 +293,27 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/);
}
float score_time = 0.0f;
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,
// so red team can score
m_red_scorers.push_back(sd);
}
else
{
if (race_manager->hasTimeTarget())
{
score_time = race_manager->getTimeTarget() - getTime();
sd.m_time = race_manager->getTimeTarget() - getTime();
}
else
score_time = getTime();
m_red_score_times.push_back(score_time);
}
else
{
sd.m_time = getTime();
m_blue_scorers.push_back(sd);
if (race_manager->hasTimeTarget())
{
score_time = race_manager->getTimeTarget() - getTime();
}
else
score_time = getTime();
m_blue_score_times.push_back(score_time);
}
if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isServer())
@ -325,9 +322,11 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
p.setSynchronous(true);
p.addUInt8(GameEventsProtocol::GE_PLAYER_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() +
stk_config->time2Ticks(3.0f));
stk_config->time2Ticks(3.0f))
.encodeString(sd.m_kart)
.encodeString(sd.m_player);
STKHost::get()->sendPacketToAllPeers(&p, true);
}
}
@ -346,6 +345,9 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
//-----------------------------------------------------------------------------
void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
{
// Ignore in live join
if (isStartPhase())
return;
int ticks_now = World::getWorld()->getTicksSinceStart();
int ticks_back_to_own_goal = ns.getTime();
if (ticks_now >= ticks_back_to_own_goal)
@ -363,11 +365,38 @@ void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
//-----------------------------------------------------------------------------
void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
{
ScorerData sd;
ScorerData sd = {};
sd.m_id = ns.getUInt8();
sd.m_correct_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)
{
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*/);
}
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)
{
Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks "
@ -751,3 +767,60 @@ void SoccerWorld::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
{
public:
class ScorerData
struct ScorerData
{
public:
/** World ID of kart which scores. */
unsigned int m_id;
/** Whether this goal is socred correctly (identify for own 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
private:
@ -274,9 +279,7 @@ private:
/** Goals data of each team scored */
std::vector<ScorerData> m_red_scorers;
std::vector<float> m_red_score_times;
std::vector<ScorerData> m_blue_scorers;
std::vector<float> m_blue_score_times;
/** Data generated from navmesh */
TrackSector* m_ball_track_sector;
@ -347,12 +350,6 @@ public:
const std::vector<ScorerData>& getScorers(KartTeam team) const
{ 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;
// ------------------------------------------------------------------------
const Vec3& getBallPosition() const
@ -417,6 +414,10 @@ public:
}
return progress;
}
// ------------------------------------------------------------------------
virtual void saveCompleteState(BareNetworkString* bns) OVERRIDE;
// ------------------------------------------------------------------------
virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE;
}; // SoccerWorld

View File

@ -1286,16 +1286,12 @@ void RaceResultGUI::displayCTFResults()
current_y += rect.Height / 2 + rect.Height / 4;
font = GUIEngine::getSmallFont();
std::vector<SoccerWorld::ScorerData> scorers = sw->getScorers(KART_TEAM_RED);
// Maximum 10 scorers displayed in result screen
while (scorers.size() > 10)
{
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;
@ -1303,8 +1299,7 @@ void RaceResultGUI::displayCTFResults()
{
const bool own_goal = !(scorers.at(i).m_correct_goal);
const int kart_id = scorers.at(i).m_id;
result_text = sw->getKart(kart_id)->getController()->getName();
result_text = scorers.at(i).m_player;
if (own_goal)
{
@ -1314,7 +1309,7 @@ void RaceResultGUI::displayCTFResults()
}
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());
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);
font->draw(result_text, pos, (own_goal ?
video::SColor(255, 255, 0, 0) : color), true, false);
scorer_icon = sw->getKart(scorers.at(i).m_id)
->getKartProperties()->getIconMaterial()->getTexture();
irr::video::ITexture* scorer_icon = NULL;
const KartProperties* kp = kart_properties_manager->getKart(scorers.at(i).m_kart);
if (kp)
scorer_icon = kp->getIconMaterial()->getTexture();
if (scorer_icon)
{
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);
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,
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:
current_y = prev_y;
current_x += UserConfigParams::m_width / 2 - red_icon->getSize().Width / 2;
scorers = sw->getScorers(KART_TEAM_BLUE);
while (scorers.size() > 10)
{
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++)
{
const bool own_goal = !(scorers.at(i).m_correct_goal);
const int kart_id = scorers.at(i).m_id;
result_text = sw->getKart(kart_id)->getController()->getName();
result_text = scorers.at(i).m_player;
if (own_goal)
{
@ -1363,7 +1359,7 @@ void RaceResultGUI::displayCTFResults()
}
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());
if (height - prev_y < ((short)scorers.size() + 1)*(short)rect.Height)
@ -1376,15 +1372,19 @@ void RaceResultGUI::displayCTFResults()
pos = core::rect<s32>(current_x, current_y, current_x, current_y);
font->draw(result_text, pos, (own_goal ?
video::SColor(255, 255, 0, 0) : color), true, false);
scorer_icon = sw->getKart(scorers.at(i).m_id)->
getKartProperties()->getIconMaterial()->getTexture();
irr::video::ITexture* scorer_icon = NULL;
const KartProperties* kp = kart_properties_manager->getKart(scorers.at(i).m_kart);
if (kp)
scorer_icon = kp->getIconMaterial()->getTexture();
if (scorer_icon)
{
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);
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,
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
}