Improve goal when live join is happening

This commit is contained in:
Benau 2019-03-07 15:40:25 +08:00
parent 09a62747f6
commit ffca0c0d36
9 changed files with 67 additions and 105 deletions

View File

@ -120,7 +120,7 @@ void SoccerAI::update(int ticks)
m_front_transform.setOrigin(m_kart->getFrontXYZ()); m_front_transform.setOrigin(m_kart->getFrontXYZ());
m_front_transform.setBasis(m_kart->getTrans().getBasis()); m_front_transform.setBasis(m_kart->getTrans().getBasis());
if (m_world->getPhase() == World::GOAL_PHASE) if (m_world->isGoalPhase())
{ {
resetAfterStop(); resetAfterStop();
m_controls->setBrake(false); m_controls->setBrake(false);

View File

@ -23,18 +23,13 @@
#include "config/user_config.hpp" #include "config/user_config.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "graphics/render_info.hpp"
#include "karts/kart_model.hpp" #include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp" #include "karts/kart_properties.hpp"
#include "karts/kart_rewinder.hpp"
#include "karts/rescue_animation.hpp"
#include "karts/controller/local_player_controller.hpp" #include "karts/controller/local_player_controller.hpp"
#include "karts/controller/network_player_controller.hpp" #include "karts/controller/network_player_controller.hpp"
#include "network/network_config.hpp" #include "network/network_config.hpp"
#include "network/network_string.hpp" #include "network/network_string.hpp"
#include "network/protocols/game_events_protocol.hpp" #include "network/protocols/game_events_protocol.hpp"
#include "network/rewind_info.hpp"
#include "network/rewind_manager.hpp"
#include "network/stk_host.hpp" #include "network/stk_host.hpp"
#include "physics/physics.hpp" #include "physics/physics.hpp"
#include "states_screens/race_gui_base.hpp" #include "states_screens/race_gui_base.hpp"
@ -91,7 +86,6 @@ void SoccerWorld::init()
m_kart_position_map.clear(); m_kart_position_map.clear();
WorldWithRank::init(); WorldWithRank::init();
m_display_rank = false; m_display_rank = false;
m_goal_timer = 0;
m_ball_hitter = -1; m_ball_hitter = -1;
m_ball = NULL; m_ball = NULL;
m_ball_body = NULL; m_ball_body = NULL;
@ -165,6 +159,7 @@ void SoccerWorld::reset(bool restart)
m_reset_ball_ticks = -1; m_reset_ball_ticks = -1;
m_ball->reset(); m_ball->reset();
m_bgd.reset(); m_bgd.reset();
m_ticks_back_to_own_goal = -1;
m_ball->setEnabled(false); m_ball->setEnabled(false);
// Make the player kart in profiling mode up // Make the player kart in profiling mode up
@ -220,7 +215,7 @@ void SoccerWorld::update(int ticks)
WorldWithRank::update(ticks); WorldWithRank::update(ticks);
WorldWithRank::updateTrack(ticks); WorldWithRank::updateTrack(ticks);
if (getPhase() == World::GOAL_PHASE) if (isGoalPhase())
{ {
for (unsigned int i = 0; i < m_karts.size(); i++) for (unsigned int i = 0; i < m_karts.size(); i++)
{ {
@ -232,22 +227,13 @@ void SoccerWorld::update(int ticks)
kart->getBody()->proceedToTransform(m_goal_transforms[i]); kart->getBody()->proceedToTransform(m_goal_transforms[i]);
kart->setTrans(m_goal_transforms[i]); kart->setTrans(m_goal_transforms[i]);
} }
if (m_ticks_back_to_own_goal - getTicksSinceStart() == 1 &&
if (NetworkConfig::get()->isNetworking() && !isRaceOver())
NetworkConfig::get()->isClient())
return;
m_goal_timer += ticks;
if (m_goal_timer > stk_config->time2Ticks(3.0f))
{ {
m_goal_timer = 0; // Reset all karts and ball
if (!isRaceOver()) resetKartsToSelfGoals();
{ if (UserConfigParams::m_arena_ai_stats)
// Reset all karts and ball getKart(8)->flyUp();
resetKartsToSelfGoals();
if (UserConfigParams::m_arena_ai_stats)
getKart(8)->flyUp();
}
} }
} }
if (UserConfigParams::m_arena_ai_stats) if (UserConfigParams::m_arena_ai_stats)
@ -263,8 +249,10 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
NetworkConfig::get()->isClient())) NetworkConfig::get()->isClient()))
return; return;
setPhase(WorldStatus::GOAL_PHASE); m_ticks_back_to_own_goal = getTicksSinceStart() +
stk_config->time2Ticks(3.0f);
m_goal_sound->play(); m_goal_sound->play();
m_ball->reset();
m_ball->setEnabled(false); m_ball->setEnabled(false);
if (m_ball_hitter != -1) if (m_ball_hitter != -1)
{ {
@ -323,8 +311,7 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
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(sd.m_time) .addUInt8(first_goal).addFloat(sd.m_time)
.addTime(World::getWorld()->getTicksSinceStart() + .addTime(m_ticks_back_to_own_goal)
stk_config->time2Ticks(3.0f))
.encodeString(sd.m_kart) .encodeString(sd.m_kart)
.encodeString(sd.m_player); .encodeString(sd.m_player);
STKHost::get()->sendPacketToAllPeers(&p, true); STKHost::get()->sendPacketToAllPeers(&p, true);
@ -333,21 +320,15 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
for (unsigned i = 0; i < m_karts.size(); i++) for (unsigned i = 0; i < m_karts.size(); i++)
{ {
auto& kart = m_karts[i]; auto& kart = m_karts[i];
if (kart->isEliminated())
continue;
kart->getBody()->setLinearVelocity(Vec3(0.0f)); kart->getBody()->setLinearVelocity(Vec3(0.0f));
kart->getBody()->setAngularVelocity(Vec3(0.0f)); kart->getBody()->setAngularVelocity(Vec3(0.0f));
m_goal_transforms[i] = kart->getBody()->getWorldTransform(); m_goal_transforms[i] = kart->getBody()->getWorldTransform();
} }
} // onCheckGoalTriggered } // onCheckGoalTriggered
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
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)
@ -356,10 +337,7 @@ void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
"%d when reset player", ticks_back_to_own_goal, ticks_now); "%d when reset player", ticks_back_to_own_goal, ticks_now);
return; return;
} }
RewindManager::get()->addRewindInfoEventFunction(new m_reset_ball_ticks = ticks_back_to_own_goal;
RewindInfoEventFunction(ticks_back_to_own_goal,
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
} // handleResetBallFromServer } // handleResetBallFromServer
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -372,17 +350,8 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
sd.m_time = ns.getFloat(); sd.m_time = ns.getFloat();
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();
try ns.decodeString(&sd.m_kart);
{ ns.decodeStringW(&sd.m_player);
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) if (first_goal)
{ {
@ -393,7 +362,27 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
m_blue_scorers.push_back(sd); m_blue_scorers.push_back(sd);
} }
// Ignore in live join if (ticks_now >= ticks_back_to_own_goal && !isStartPhase())
{
Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks "
"%d when goal", ticks_back_to_own_goal, ticks_now);
return;
}
m_ticks_back_to_own_goal = ticks_back_to_own_goal;
for (unsigned i = 0; i < m_karts.size(); i++)
{
auto& kart = m_karts[i];
btTransform transform_now = kart->getBody()->getWorldTransform();
kart->getBody()->setLinearVelocity(Vec3(0.0f));
kart->getBody()->setAngularVelocity(Vec3(0.0f));
kart->getBody()->proceedToTransform(transform_now);
kart->setTrans(transform_now);
m_goal_transforms[i] = transform_now;
}
m_ball->reset();
m_ball->setEnabled(false);
// Ignore the rest in live join
if (isStartPhase()) if (isStartPhase())
return; return;
@ -407,32 +396,7 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
m_karts[sd.m_id]->getKartModel() m_karts[sd.m_id]->getKartModel()
->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/); ->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/);
} }
if (ticks_now >= ticks_back_to_own_goal)
{
Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks "
"%d when goal", ticks_back_to_own_goal, ticks_now);
return;
}
setPhase(WorldStatus::GOAL_PHASE);
m_goal_sound->play(); m_goal_sound->play();
m_ball->setEnabled(false);
for (unsigned i = 0; i < m_karts.size(); i++)
{
auto& kart = m_karts[i];
if (kart->isEliminated())
continue;
btTransform transform_now = kart->getBody()->getWorldTransform();
kart->getBody()->setLinearVelocity(Vec3(0.0f));
kart->getBody()->setAngularVelocity(Vec3(0.0f));
kart->getBody()->proceedToTransform(transform_now);
kart->setTrans(transform_now);
m_goal_transforms[i] = transform_now;
}
RewindManager::get()->addRewindInfoEventFunction(new
RewindInfoEventFunction(ticks_back_to_own_goal,
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
} // handlePlayerGoalFromServer } // handlePlayerGoalFromServer
@ -442,7 +406,6 @@ void SoccerWorld::resetKartsToSelfGoals()
m_ball->setEnabled(true); m_ball->setEnabled(true);
m_ball->reset(); m_ball->reset();
m_bgd.resetCheckGoal(Track::getCurrentTrack()); m_bgd.resetCheckGoal(Track::getCurrentTrack());
setPhase(WorldStatus::RACE_PHASE);
for (unsigned i = 0; i < m_karts.size(); i++) for (unsigned i = 0; i < m_karts.size(); i++)
{ {
auto& kart = m_karts[i]; auto& kart = m_karts[i];
@ -532,20 +495,24 @@ void SoccerWorld::updateBallPosition(int ticks)
{ {
m_ball_track_sector m_ball_track_sector
->update(getBallPosition(), true/*ignore_vertical*/); ->update(getBallPosition(), true/*ignore_vertical*/);
if (!m_ball_track_sector->isOnRoad() && getPhase() == RACE_PHASE &&
m_reset_ball_ticks == -1) bool is_client = NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isClient();
bool is_server = NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isServer();
if (!is_client && getTicksSinceStart() > m_reset_ball_ticks &&
!m_ball_track_sector->isOnRoad())
{ {
m_ball_invalid_timer += ticks; m_ball_invalid_timer += ticks;
// Reset the ball and karts if out of navmesh after 2 seconds // Reset the ball and karts if out of navmesh after 2 seconds
if (m_ball_invalid_timer >= stk_config->time2Ticks(2.0f)) if (m_ball_invalid_timer >= stk_config->time2Ticks(2.0f))
{ {
if (NetworkConfig::get()->isNetworking() && if (is_server)
NetworkConfig::get()->isServer())
{ {
// Reset the ball 2 seconds in the future to make sure it's // Reset the ball 2 seconds in the future to make sure it's
// after all clients time // after all clients time
m_reset_ball_ticks = m_reset_ball_ticks = getTicksSinceStart() +
World::getWorld()->getTicksSinceStart() +
stk_config->time2Ticks(2.0f); stk_config->time2Ticks(2.0f);
NetworkString p(PROTOCOL_GAME_EVENTS); NetworkString p(PROTOCOL_GAME_EVENTS);
@ -567,10 +534,7 @@ void SoccerWorld::updateBallPosition(int ticks)
m_ball_invalid_timer = 0; m_ball_invalid_timer = 0;
if (m_reset_ball_ticks == World::getWorld()->getTicksSinceStart()) if (m_reset_ball_ticks == World::getWorld()->getTicksSinceStart())
{ {
assert(NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isServer());
resetKartsToSelfGoals(); resetKartsToSelfGoals();
m_reset_ball_ticks = -1;
} }
} }
@ -792,6 +756,7 @@ void SoccerWorld::saveCompleteState(BareNetworkString* bns)
.encodeString(m_blue_scorers[i].m_kart) .encodeString(m_blue_scorers[i].m_kart)
.encodeString(m_blue_scorers[i].m_player); .encodeString(m_blue_scorers[i].m_player);
} }
bns->addTime(m_reset_ball_ticks).addTime(m_ticks_back_to_own_goal);
} // saveCompleteState } // saveCompleteState
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -823,4 +788,6 @@ void SoccerWorld::restoreCompleteState(const BareNetworkString& b)
b.decodeStringW(&sd.m_player); b.decodeStringW(&sd.m_player);
m_blue_scorers.push_back(sd); m_blue_scorers.push_back(sd);
} }
m_reset_ball_ticks = b.getTime();
m_ticks_back_to_own_goal = b.getTime();
} // restoreCompleteState } // restoreCompleteState

View File

@ -269,9 +269,6 @@ private:
SFXBase *m_goal_sound; SFXBase *m_goal_sound;
/** Timer for displaying goal text*/
int m_goal_timer;
/** Counts ticks when the ball is off track, so a reset can be /** Counts ticks when the ball is off track, so a reset can be
* triggered if the ball is off for more than 2 seconds. */ * triggered if the ball is off for more than 2 seconds. */
int m_ball_invalid_timer; int m_ball_invalid_timer;
@ -299,6 +296,8 @@ private:
std::vector<int> m_goal_frame; std::vector<int> m_goal_frame;
int m_reset_ball_ticks; int m_reset_ball_ticks;
int m_ticks_back_to_own_goal;
void resetKartsToSelfGoals(); void resetKartsToSelfGoals();
public: public:
@ -418,6 +417,12 @@ public:
virtual void saveCompleteState(BareNetworkString* bns) OVERRIDE; virtual void saveCompleteState(BareNetworkString* bns) OVERRIDE;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE; virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE;
// ------------------------------------------------------------------------
virtual bool isGoalPhase() const OVERRIDE
{
int diff = m_ticks_back_to_own_goal - getTicksSinceStart();
return diff > 0 && diff < stk_config->time2Ticks(3.0f);
}
}; // SoccerWorld }; // SoccerWorld

View File

@ -383,6 +383,8 @@ public:
return std::make_pair(std::numeric_limits<uint32_t>::max(), return std::make_pair(std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max()); std::numeric_limits<uint32_t>::max());
} }
// ------------------------------------------------------------------------
virtual bool isGoalPhase() const { return false; }
}; // World }; // World
#endif #endif

View File

@ -424,10 +424,6 @@ void WorldStatus::updateTime(int ticks)
case IN_GAME_MENU_PHASE: case IN_GAME_MENU_PHASE:
// Nothing to do here. // Nothing to do here.
break; break;
case GOAL_PHASE:
// Nothing to do here as well.
break;
default: break; default: break;
} }

View File

@ -86,9 +86,6 @@ public:
// Undefined, used in asserts to catch incorrect states. // Undefined, used in asserts to catch incorrect states.
UNDEFINED_PHASE, UNDEFINED_PHASE,
//Goal scored phase
GOAL_PHASE
}; };
protected: protected:
@ -165,13 +162,11 @@ public:
// Note: GO_PHASE is both: start phase and race phase // Note: GO_PHASE is both: start phase and race phase
bool isStartPhase() const { return m_phase<GO_PHASE; } bool isStartPhase() const { return m_phase<GO_PHASE; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool isRacePhase() const { return (m_phase>=GO_PHASE && bool isRacePhase() const { return m_phase>=GO_PHASE &&
m_phase<FINISH_PHASE) || m_phase<FINISH_PHASE; }
m_phase == GOAL_PHASE; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool isActiveRacePhase() const { return (m_phase>=GO_PHASE && bool isActiveRacePhase() const { return m_phase>=GO_PHASE &&
m_phase<DELAY_FINISH_PHASE) || m_phase<DELAY_FINISH_PHASE; }
m_phase == GOAL_PHASE; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** While the race menu is being displayed, m_phase is limbo, and /** While the race menu is being displayed, m_phase is limbo, and
* m_previous_phase is finish. So we have to test this case, too. */ * m_previous_phase is finish. So we have to test this case, too. */

View File

@ -710,8 +710,7 @@ bool ServerLobby::worldIsActive() const
{ {
return World::getWorld() && RaceEventManager::getInstance()->isRunning() && return World::getWorld() && RaceEventManager::getInstance()->isRunning() &&
!RaceEventManager::getInstance()->isRaceOver() && !RaceEventManager::getInstance()->isRaceOver() &&
(World::getWorld()->getPhase() == WorldStatus::RACE_PHASE || World::getWorld()->getPhase() == WorldStatus::RACE_PHASE;
World::getWorld()->getPhase() == WorldStatus::GOAL_PHASE);
} // worldIsActive } // worldIsActive
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1033,8 +1032,7 @@ void ServerLobby::update(int ticks)
else else
resetGameStartedProgress(); resetGameStartedProgress();
if (w && (w->getPhase() == World::RACE_PHASE || if (w && w->getPhase() == World::RACE_PHASE)
w->getPhase() == World::GOAL_PHASE))
{ {
storePlayingTrack(track_manager->getTrackIndexByIdent( storePlayingTrack(track_manager->getTrackIndexByIdent(
race_manager->getTrackName())); race_manager->getTrackName()));

View File

@ -44,7 +44,6 @@ bool RaceEventManager::isRaceOver()
if(!World::getWorld()) if(!World::getWorld())
return false; return false;
return (World::getWorld()->getPhase() > WorldStatus::RACE_PHASE && return (World::getWorld()->getPhase() > WorldStatus::RACE_PHASE &&
World::getWorld()->getPhase() != WorldStatus::GOAL_PHASE &&
World::getWorld()->getPhase() != WorldStatus::IN_GAME_MENU_PHASE); World::getWorld()->getPhase() != WorldStatus::IN_GAME_MENU_PHASE);
} // isRaceOver } // isRaceOver

View File

@ -263,7 +263,7 @@ void RaceGUI::renderGlobal(float dt)
{ {
drawGlobalReadySetGo(); drawGlobalReadySetGo();
} }
if(world->getPhase() == World::GOAL_PHASE) else if (world->isGoalPhase())
drawGlobalGoal(); drawGlobalGoal();
if (!m_enabled) return; if (!m_enabled) return;