Finish soccer mode in network
This commit is contained in:
parent
d5168691e1
commit
c5cdfcebfe
@ -328,13 +328,6 @@ void PlayerController::update(int ticks)
|
||||
{
|
||||
steer(ticks, m_steer_val);
|
||||
|
||||
if (World::getWorld()->getPhase() == World::GOAL_PHASE)
|
||||
{
|
||||
m_controls->setBrake(false);
|
||||
m_controls->setAccel(0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (World::getWorld()->isStartPhase())
|
||||
{
|
||||
if (m_controls->getAccel() || m_controls->getBrake()||
|
||||
|
@ -32,7 +32,10 @@
|
||||
#include "karts/controller/local_player_controller.hpp"
|
||||
#include "karts/controller/network_player_controller.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
@ -146,7 +149,8 @@ void SoccerWorld::reset()
|
||||
m_blue_kdm.clear();
|
||||
m_ball_heading = 0.0f;
|
||||
m_ball_invalid_timer = 0;
|
||||
|
||||
m_goal_transforms.clear();
|
||||
m_goal_transforms.resize(m_karts.size());
|
||||
if (m_goal_sound != NULL &&
|
||||
m_goal_sound->getStatus() == SFXBase::SFX_PLAYING)
|
||||
{
|
||||
@ -158,9 +162,11 @@ void SoccerWorld::reset()
|
||||
m_ball_track_sector->reset();
|
||||
}
|
||||
|
||||
m_reset_ball_ticks = -1;
|
||||
initKartList();
|
||||
m_ball->reset();
|
||||
m_bgd.reset();
|
||||
m_ball->setEnabled(false);
|
||||
|
||||
// Make the player kart in profiling mode up
|
||||
// ie make this kart less likely to affect gaming result
|
||||
@ -169,6 +175,27 @@ void SoccerWorld::reset()
|
||||
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::onGo()
|
||||
{
|
||||
m_ball->setEnabled(true);
|
||||
m_ball->reset();
|
||||
WorldWithRank::onGo();
|
||||
} // onGo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::terminateRace()
|
||||
{
|
||||
const unsigned int kart_amount = getNumKarts();
|
||||
for (unsigned int i = 0; i < kart_amount ; i++)
|
||||
{
|
||||
// Soccer mode use goal for race result, and each goal time is
|
||||
// handled by handlePlayerGoalFromServer already
|
||||
m_karts[i]->finishedRace(0.0f, true/*from_server*/);
|
||||
} // i<kart_amount
|
||||
WorldWithRank::terminateRace();
|
||||
} // terminateRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the internal identifier for this race.
|
||||
*/
|
||||
@ -196,23 +223,29 @@ void SoccerWorld::update(int ticks)
|
||||
|
||||
if (getPhase() == World::GOAL_PHASE)
|
||||
{
|
||||
if (m_goal_timer == 0)
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
// Stop all karts
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
m_karts[i]->setVelocity(btVector3(0, 0, 0));
|
||||
AbstractKart* kart = m_karts[i];
|
||||
if (kart->isEliminated())
|
||||
continue;
|
||||
kart->getBody()->setLinearVelocity(Vec3(0.0f));
|
||||
kart->getBody()->setAngularVelocity(Vec3(0.0f));
|
||||
kart->getBody()->proceedToTransform(m_goal_transforms[i]);
|
||||
kart->setTrans(m_goal_transforms[i]);
|
||||
}
|
||||
m_goal_timer += ticks;
|
||||
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isClient())
|
||||
return;
|
||||
|
||||
m_goal_timer += ticks;
|
||||
if (m_goal_timer > stk_config->time2Ticks(3.0f))
|
||||
{
|
||||
setPhase(WorldStatus::RACE_PHASE);
|
||||
m_goal_timer = 0;
|
||||
if (!isRaceOver())
|
||||
{
|
||||
// Reset all karts
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
moveKartAfterRescue(m_karts[i]);
|
||||
// Reset all karts and ball
|
||||
resetKartsToSelfGoals();
|
||||
if (UserConfigParams::m_arena_ai_stats)
|
||||
getKart(8)->flyUp();
|
||||
}
|
||||
@ -226,11 +259,14 @@ void SoccerWorld::update(int ticks)
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::onCheckGoalTriggered(bool first_goal)
|
||||
{
|
||||
if (isRaceOver() || isStartPhase())
|
||||
if (isRaceOver() || isStartPhase() ||
|
||||
(NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isClient()))
|
||||
return;
|
||||
|
||||
setPhase(WorldStatus::GOAL_PHASE);
|
||||
m_goal_sound->play();
|
||||
m_ball->setEnabled(false);
|
||||
if (m_ball_hitter != -1)
|
||||
{
|
||||
if (UserConfigParams::m_arena_ai_stats)
|
||||
@ -256,6 +292,7 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
|
||||
->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/);
|
||||
}
|
||||
|
||||
float score_time = 0.0f;
|
||||
if (first_goal)
|
||||
{
|
||||
// Notice: true first_goal means it's blue goal being shoot,
|
||||
@ -263,28 +300,146 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
|
||||
m_red_scorers.push_back(sd);
|
||||
if (race_manager->hasTimeTarget())
|
||||
{
|
||||
m_red_score_times.push_back(race_manager->getTimeTarget()
|
||||
- getTime());
|
||||
score_time = race_manager->getTimeTarget() - getTime();
|
||||
}
|
||||
else
|
||||
m_red_score_times.push_back(getTime());
|
||||
score_time = getTime();
|
||||
m_red_score_times.push_back(score_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_blue_scorers.push_back(sd);
|
||||
if (race_manager->hasTimeTarget())
|
||||
{
|
||||
m_blue_score_times.push_back(race_manager->getTimeTarget()
|
||||
- getTime());
|
||||
score_time = race_manager->getTimeTarget() - getTime();
|
||||
}
|
||||
else
|
||||
m_blue_score_times.push_back(getTime());
|
||||
score_time = getTime();
|
||||
m_blue_score_times.push_back(score_time);
|
||||
}
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isServer())
|
||||
{
|
||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
||||
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)
|
||||
.addTime(World::getWorld()->getTicksSinceStart() +
|
||||
stk_config->time2Ticks(3.0f));
|
||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
||||
}
|
||||
}
|
||||
m_ball->reset();
|
||||
for (unsigned i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
if (kart->isEliminated())
|
||||
continue;
|
||||
kart->getBody()->setLinearVelocity(Vec3(0.0f));
|
||||
kart->getBody()->setAngularVelocity(Vec3(0.0f));
|
||||
m_goal_transforms[i] = kart->getBody()->getWorldTransform();
|
||||
}
|
||||
|
||||
} // onCheckGoalTriggered
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
|
||||
{
|
||||
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 "
|
||||
"%d when reset player", ticks_back_to_own_goal, ticks_now);
|
||||
return;
|
||||
}
|
||||
RewindManager::get()->getRewindQueue().insertRewindInfo(new
|
||||
RewindInfoEventFunction(ticks_back_to_own_goal,
|
||||
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
|
||||
|
||||
} // handleResetBallFromServer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
|
||||
{
|
||||
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();
|
||||
if (sd.m_correct_goal)
|
||||
{
|
||||
m_karts[sd.m_id]->getKartModel()
|
||||
->setAnimation(KartModel::AF_WIN_START, true/* play_non_loop*/);
|
||||
}
|
||||
else if (!sd.m_correct_goal)
|
||||
{
|
||||
m_karts[sd.m_id]->getKartModel()
|
||||
->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 "
|
||||
"%d when goal", ticks_back_to_own_goal, ticks_now);
|
||||
return;
|
||||
}
|
||||
|
||||
setPhase(WorldStatus::GOAL_PHASE);
|
||||
m_goal_sound->play();
|
||||
m_ball->setEnabled(false);
|
||||
for (unsigned i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* 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()->getRewindQueue().insertRewindInfo(new
|
||||
RewindInfoEventFunction(ticks_back_to_own_goal,
|
||||
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
|
||||
|
||||
} // handlePlayerGoalFromServer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::resetKartsToSelfGoals()
|
||||
{
|
||||
m_ball->setEnabled(true);
|
||||
m_ball->reset();
|
||||
m_bgd.resetCheckGoal(Track::getCurrentTrack());
|
||||
setPhase(WorldStatus::RACE_PHASE);
|
||||
for (unsigned i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
if (kart->isEliminated())
|
||||
continue;
|
||||
|
||||
kart->getBody()->setLinearVelocity(Vec3(0.0f));
|
||||
kart->getBody()->setAngularVelocity(Vec3(0.0f));
|
||||
unsigned index = m_kart_position_map.at(kart->getWorldKartId());
|
||||
btTransform t = Track::getCurrentTrack()->getStartTransform(index);
|
||||
moveKartTo(kart, t);
|
||||
}
|
||||
} // resetKartsToSelfGoals
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the last kart that hit the ball, to be able to
|
||||
* identify the scorer later.
|
||||
@ -299,16 +454,15 @@ void SoccerWorld::setBallHitter(unsigned int kart_id)
|
||||
*/
|
||||
bool SoccerWorld::isRaceOver()
|
||||
{
|
||||
|
||||
if(race_manager->hasTimeTarget())
|
||||
if (race_manager->hasTimeTarget())
|
||||
{
|
||||
return m_count_down_reached_zero;
|
||||
}
|
||||
// One team scored the target goals ...
|
||||
else
|
||||
{
|
||||
return (getScore(SOCCER_TEAM_BLUE) >= m_goal_target ||
|
||||
getScore(SOCCER_TEAM_RED) >= m_goal_target);
|
||||
return (getScore(SOCCER_TEAM_BLUE) >= m_goal_target ||
|
||||
getScore(SOCCER_TEAM_RED) >= m_goal_target);
|
||||
}
|
||||
|
||||
} // isRaceOver
|
||||
@ -492,22 +646,46 @@ void SoccerWorld::updateBallPosition(int ticks)
|
||||
{
|
||||
m_ball_track_sector
|
||||
->update(getBallPosition(), true/*ignore_vertical*/);
|
||||
if (!m_ball_track_sector->isOnRoad() && getPhase() == RACE_PHASE)
|
||||
if (!m_ball_track_sector->isOnRoad() && getPhase() == RACE_PHASE &&
|
||||
m_reset_ball_ticks == -1)
|
||||
{
|
||||
m_ball_invalid_timer += ticks;
|
||||
// Reset the ball and karts if out of navmesh after 2 seconds
|
||||
if (m_ball_invalid_timer >= stk_config->time2Ticks(2.0f))
|
||||
{
|
||||
m_ball_invalid_timer = 0;
|
||||
m_ball->reset();
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
moveKartAfterRescue(m_karts[i]);
|
||||
if (UserConfigParams::m_arena_ai_stats)
|
||||
getKart(8)->flyUp();
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isServer())
|
||||
{
|
||||
// Reset the ball 2 seconds in the future to make sure it's
|
||||
// after all clients time
|
||||
m_reset_ball_ticks =
|
||||
World::getWorld()->getTicksSinceStart() +
|
||||
stk_config->time2Ticks(2.0f);
|
||||
|
||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
||||
p.setSynchronous(true);
|
||||
p.addUInt8(GameEventsProtocol::GE_RESET_BALL)
|
||||
.addTime(m_reset_ball_ticks);
|
||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
||||
}
|
||||
else if (!NetworkConfig::get()->isNetworking())
|
||||
{
|
||||
m_ball_invalid_timer = 0;
|
||||
resetKartsToSelfGoals();
|
||||
if (UserConfigParams::m_arena_ai_stats)
|
||||
getKart(8)->flyUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_ball_invalid_timer = 0;
|
||||
if (m_reset_ball_ticks == World::getWorld()->getTicksSinceStart())
|
||||
{
|
||||
assert(NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isServer());
|
||||
resetKartsToSelfGoals();
|
||||
m_reset_ball_ticks = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // updateBallPosition
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
class AbstractKart;
|
||||
class Controller;
|
||||
class NetworkString;
|
||||
class TrackObject;
|
||||
class TrackSector;
|
||||
|
||||
@ -248,7 +249,11 @@ private:
|
||||
return (reverse ? m_trans(Vec3(-x, 0, -y)) :
|
||||
m_trans(Vec3(x, 0, y)));
|
||||
} // getAimPosition
|
||||
|
||||
void resetCheckGoal(const Track* t)
|
||||
{
|
||||
m_red_check_goal->reset(*t);
|
||||
m_blue_check_goal->reset(*t);
|
||||
}
|
||||
}; // BallGoalData
|
||||
|
||||
std::vector<KartDistanceMap> m_red_kdm;
|
||||
@ -290,6 +295,7 @@ private:
|
||||
|
||||
float m_ball_heading;
|
||||
|
||||
std::vector<btTransform> m_goal_transforms;
|
||||
/** Set the team for the karts */
|
||||
void initKartList();
|
||||
/** Function to update the location the ball on the polygon map */
|
||||
@ -303,16 +309,21 @@ private:
|
||||
int m_frame_count;
|
||||
std::vector<int> m_goal_frame;
|
||||
|
||||
int m_reset_ball_ticks;
|
||||
void resetKartsToSelfGoals();
|
||||
|
||||
public:
|
||||
|
||||
SoccerWorld();
|
||||
virtual ~SoccerWorld();
|
||||
|
||||
virtual void init() OVERRIDE;
|
||||
virtual void onGo() OVERRIDE;
|
||||
|
||||
// clock events
|
||||
virtual bool isRaceOver() OVERRIDE;
|
||||
virtual void countdownReachedZero() OVERRIDE;
|
||||
virtual void terminateRace() OVERRIDE;
|
||||
|
||||
// overriding World methods
|
||||
virtual void reset() OVERRIDE;
|
||||
@ -394,6 +405,9 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
void setAITeam();
|
||||
// ------------------------------------------------------------------------
|
||||
void handlePlayerGoalFromServer(const NetworkString& ns);
|
||||
// ------------------------------------------------------------------------
|
||||
void handleResetBallFromServer(const NetworkString& ns);
|
||||
|
||||
}; // SoccerWorld
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** This class handles all 'major' game events. E.g.
|
||||
* finishing a race etc. The game events manager is notified from the
|
||||
* finishing a race or goal etc. The game events manager is notified from the
|
||||
* game code, and it calls the corresponding function in this class.
|
||||
* The server then notifies all clients. Clients receive the message
|
||||
* in the synchronous notifyEvent function here, decode the message
|
||||
@ -43,12 +44,27 @@ bool GameEventsProtocol::notifyEvent(Event* event)
|
||||
return true;
|
||||
}
|
||||
uint8_t type = data.getUInt8();
|
||||
SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
switch (type)
|
||||
{
|
||||
case GE_KART_FINISHED_RACE:
|
||||
kartFinishedRace(data); break;
|
||||
case GE_PLAYER_DISCONNECT:
|
||||
eliminatePlayer(data); break;
|
||||
case GE_RESET_BALL:
|
||||
{
|
||||
if (!sw)
|
||||
throw("No soccer world");
|
||||
sw->handleResetBallFromServer(data);
|
||||
break;
|
||||
}
|
||||
case GE_PLAYER_GOAL:
|
||||
{
|
||||
if (!sw)
|
||||
throw("No soccer world");
|
||||
sw->handlePlayerGoalFromServer(data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Log::warn("GameEventsProtocol", "Unkown message type.");
|
||||
break;
|
||||
|
@ -12,7 +12,9 @@ public:
|
||||
enum GameEventType : uint8_t
|
||||
{
|
||||
GE_KART_FINISHED_RACE = 1,
|
||||
GE_PLAYER_DISCONNECT = 2
|
||||
GE_PLAYER_DISCONNECT = 2,
|
||||
GE_RESET_BALL = 3,
|
||||
GE_PLAYER_GOAL = 4
|
||||
}; // GameEventType
|
||||
private:
|
||||
void eliminatePlayer(const NetworkString &ns);
|
||||
|
Loading…
Reference in New Issue
Block a user