Skip to content

Commit c5cdfce

Browse files
committed
Finish soccer mode in network
1 parent d516869 commit c5cdfce

File tree

5 files changed

+243
-40
lines changed

5 files changed

+243
-40
lines changed

src/karts/controller/player_controller.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,6 @@ void PlayerController::update(int ticks)
328328
{
329329
steer(ticks, m_steer_val);
330330

331-
if (World::getWorld()->getPhase() == World::GOAL_PHASE)
332-
{
333-
m_controls->setBrake(false);
334-
m_controls->setAccel(0.0f);
335-
return;
336-
}
337-
338331
if (World::getWorld()->isStartPhase())
339332
{
340333
if (m_controls->getAccel() || m_controls->getBrake()||

src/modes/soccer_world.cpp

Lines changed: 207 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
#include "karts/controller/local_player_controller.hpp"
3333
#include "karts/controller/network_player_controller.hpp"
3434
#include "network/network_config.hpp"
35+
#include "network/network_string.hpp"
36+
#include "network/protocols/game_events_protocol.hpp"
3537
#include "network/rewind_manager.hpp"
38+
#include "network/stk_host.hpp"
3639
#include "physics/physics.hpp"
3740
#include "states_screens/race_gui_base.hpp"
3841
#include "tracks/track.hpp"
@@ -146,7 +149,8 @@ void SoccerWorld::reset()
146149
m_blue_kdm.clear();
147150
m_ball_heading = 0.0f;
148151
m_ball_invalid_timer = 0;
149-
152+
m_goal_transforms.clear();
153+
m_goal_transforms.resize(m_karts.size());
150154
if (m_goal_sound != NULL &&
151155
m_goal_sound->getStatus() == SFXBase::SFX_PLAYING)
152156
{
@@ -158,9 +162,11 @@ void SoccerWorld::reset()
158162
m_ball_track_sector->reset();
159163
}
160164

165+
m_reset_ball_ticks = -1;
161166
initKartList();
162167
m_ball->reset();
163168
m_bgd.reset();
169+
m_ball->setEnabled(false);
164170

165171
// Make the player kart in profiling mode up
166172
// ie make this kart less likely to affect gaming result
@@ -169,6 +175,27 @@ void SoccerWorld::reset()
169175

170176
} // reset
171177

178+
//-----------------------------------------------------------------------------
179+
void SoccerWorld::onGo()
180+
{
181+
m_ball->setEnabled(true);
182+
m_ball->reset();
183+
WorldWithRank::onGo();
184+
} // onGo
185+
186+
//-----------------------------------------------------------------------------
187+
void SoccerWorld::terminateRace()
188+
{
189+
const unsigned int kart_amount = getNumKarts();
190+
for (unsigned int i = 0; i < kart_amount ; i++)
191+
{
192+
// Soccer mode use goal for race result, and each goal time is
193+
// handled by handlePlayerGoalFromServer already
194+
m_karts[i]->finishedRace(0.0f, true/*from_server*/);
195+
} // i<kart_amount
196+
WorldWithRank::terminateRace();
197+
} // terminateRace
198+
172199
//-----------------------------------------------------------------------------
173200
/** Returns the internal identifier for this race.
174201
*/
@@ -196,23 +223,29 @@ void SoccerWorld::update(int ticks)
196223

197224
if (getPhase() == World::GOAL_PHASE)
198225
{
199-
if (m_goal_timer == 0)
226+
for (unsigned int i = 0; i < m_karts.size(); i++)
200227
{
201-
// Stop all karts
202-
for (unsigned int i = 0; i < m_karts.size(); i++)
203-
m_karts[i]->setVelocity(btVector3(0, 0, 0));
228+
AbstractKart* kart = m_karts[i];
229+
if (kart->isEliminated())
230+
continue;
231+
kart->getBody()->setLinearVelocity(Vec3(0.0f));
232+
kart->getBody()->setAngularVelocity(Vec3(0.0f));
233+
kart->getBody()->proceedToTransform(m_goal_transforms[i]);
234+
kart->setTrans(m_goal_transforms[i]);
204235
}
205-
m_goal_timer += ticks;
206236

237+
if (NetworkConfig::get()->isNetworking() &&
238+
NetworkConfig::get()->isClient())
239+
return;
240+
241+
m_goal_timer += ticks;
207242
if (m_goal_timer > stk_config->time2Ticks(3.0f))
208243
{
209-
setPhase(WorldStatus::RACE_PHASE);
210244
m_goal_timer = 0;
211245
if (!isRaceOver())
212246
{
213-
// Reset all karts
214-
for (unsigned int i = 0; i < m_karts.size(); i++)
215-
moveKartAfterRescue(m_karts[i]);
247+
// Reset all karts and ball
248+
resetKartsToSelfGoals();
216249
if (UserConfigParams::m_arena_ai_stats)
217250
getKart(8)->flyUp();
218251
}
@@ -226,11 +259,14 @@ void SoccerWorld::update(int ticks)
226259
//-----------------------------------------------------------------------------
227260
void SoccerWorld::onCheckGoalTriggered(bool first_goal)
228261
{
229-
if (isRaceOver() || isStartPhase())
262+
if (isRaceOver() || isStartPhase() ||
263+
(NetworkConfig::get()->isNetworking() &&
264+
NetworkConfig::get()->isClient()))
230265
return;
231266

232267
setPhase(WorldStatus::GOAL_PHASE);
233268
m_goal_sound->play();
269+
m_ball->setEnabled(false);
234270
if (m_ball_hitter != -1)
235271
{
236272
if (UserConfigParams::m_arena_ai_stats)
@@ -256,35 +292,154 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
256292
->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/);
257293
}
258294

295+
float score_time = 0.0f;
259296
if (first_goal)
260297
{
261298
// Notice: true first_goal means it's blue goal being shoot,
262299
// so red team can score
263300
m_red_scorers.push_back(sd);
264301
if (race_manager->hasTimeTarget())
265302
{
266-
m_red_score_times.push_back(race_manager->getTimeTarget()
267-
- getTime());
303+
score_time = race_manager->getTimeTarget() - getTime();
268304
}
269305
else
270-
m_red_score_times.push_back(getTime());
306+
score_time = getTime();
307+
m_red_score_times.push_back(score_time);
271308
}
272309
else
273310
{
274311
m_blue_scorers.push_back(sd);
275312
if (race_manager->hasTimeTarget())
276313
{
277-
m_blue_score_times.push_back(race_manager->getTimeTarget()
278-
- getTime());
314+
score_time = race_manager->getTimeTarget() - getTime();
279315
}
280316
else
281-
m_blue_score_times.push_back(getTime());
317+
score_time = getTime();
318+
m_blue_score_times.push_back(score_time);
319+
}
320+
if (NetworkConfig::get()->isNetworking() &&
321+
NetworkConfig::get()->isServer())
322+
{
323+
NetworkString p(PROTOCOL_GAME_EVENTS);
324+
p.setSynchronous(true);
325+
p.addUInt8(GameEventsProtocol::GE_PLAYER_GOAL)
326+
.addUInt8((uint8_t)sd.m_id).addUInt8(sd.m_correct_goal)
327+
.addUInt8(first_goal).addFloat(score_time)
328+
.addTime(World::getWorld()->getTicksSinceStart() +
329+
stk_config->time2Ticks(3.0f));
330+
STKHost::get()->sendPacketToAllPeers(&p, true);
282331
}
283332
}
284-
m_ball->reset();
333+
for (unsigned i = 0; i < m_karts.size(); i++)
334+
{
335+
AbstractKart* kart = m_karts[i];
336+
if (kart->isEliminated())
337+
continue;
338+
kart->getBody()->setLinearVelocity(Vec3(0.0f));
339+
kart->getBody()->setAngularVelocity(Vec3(0.0f));
340+
m_goal_transforms[i] = kart->getBody()->getWorldTransform();
341+
}
285342

286343
} // onCheckGoalTriggered
287344

345+
//-----------------------------------------------------------------------------
346+
void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
347+
{
348+
int ticks_now = World::getWorld()->getTicksSinceStart();
349+
int ticks_back_to_own_goal = ns.getTime();
350+
if (ticks_now >= ticks_back_to_own_goal)
351+
{
352+
Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks "
353+
"%d when reset player", ticks_back_to_own_goal, ticks_now);
354+
return;
355+
}
356+
RewindManager::get()->getRewindQueue().insertRewindInfo(new
357+
RewindInfoEventFunction(ticks_back_to_own_goal,
358+
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
359+
360+
} // handleResetBallFromServer
361+
362+
//-----------------------------------------------------------------------------
363+
void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
364+
{
365+
ScorerData sd;
366+
sd.m_id = ns.getUInt8();
367+
sd.m_correct_goal = ns.getUInt8() == 1;
368+
bool first_goal = ns.getUInt8() == 1;
369+
float score_time = ns.getFloat();
370+
if (sd.m_correct_goal)
371+
{
372+
m_karts[sd.m_id]->getKartModel()
373+
->setAnimation(KartModel::AF_WIN_START, true/* play_non_loop*/);
374+
}
375+
else if (!sd.m_correct_goal)
376+
{
377+
m_karts[sd.m_id]->getKartModel()
378+
->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/);
379+
}
380+
381+
if (first_goal)
382+
{
383+
m_red_scorers.push_back(sd);
384+
m_red_score_times.push_back(score_time);
385+
}
386+
else
387+
{
388+
m_blue_scorers.push_back(sd);
389+
m_blue_score_times.push_back(score_time);
390+
}
391+
int ticks_now = World::getWorld()->getTicksSinceStart();
392+
int ticks_back_to_own_goal = ns.getTime();
393+
394+
if (ticks_now >= ticks_back_to_own_goal)
395+
{
396+
Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks "
397+
"%d when goal", ticks_back_to_own_goal, ticks_now);
398+
return;
399+
}
400+
401+
setPhase(WorldStatus::GOAL_PHASE);
402+
m_goal_sound->play();
403+
m_ball->setEnabled(false);
404+
for (unsigned i = 0; i < m_karts.size(); i++)
405+
{
406+
AbstractKart* kart = m_karts[i];
407+
if (kart->isEliminated())
408+
continue;
409+
btTransform transform_now = kart->getBody()->getWorldTransform();
410+
kart->getBody()->setLinearVelocity(Vec3(0.0f));
411+
kart->getBody()->setAngularVelocity(Vec3(0.0f));
412+
kart->getBody()->proceedToTransform(transform_now);
413+
kart->setTrans(transform_now);
414+
m_goal_transforms[i] = transform_now;
415+
}
416+
RewindManager::get()->getRewindQueue().insertRewindInfo(new
417+
RewindInfoEventFunction(ticks_back_to_own_goal,
418+
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
419+
420+
} // handlePlayerGoalFromServer
421+
422+
//-----------------------------------------------------------------------------
423+
void SoccerWorld::resetKartsToSelfGoals()
424+
{
425+
m_ball->setEnabled(true);
426+
m_ball->reset();
427+
m_bgd.resetCheckGoal(Track::getCurrentTrack());
428+
setPhase(WorldStatus::RACE_PHASE);
429+
for (unsigned i = 0; i < m_karts.size(); i++)
430+
{
431+
AbstractKart* kart = m_karts[i];
432+
if (kart->isEliminated())
433+
continue;
434+
435+
kart->getBody()->setLinearVelocity(Vec3(0.0f));
436+
kart->getBody()->setAngularVelocity(Vec3(0.0f));
437+
unsigned index = m_kart_position_map.at(kart->getWorldKartId());
438+
btTransform t = Track::getCurrentTrack()->getStartTransform(index);
439+
moveKartTo(kart, t);
440+
}
441+
} // resetKartsToSelfGoals
442+
288443
//-----------------------------------------------------------------------------
289444
/** Sets the last kart that hit the ball, to be able to
290445
* identify the scorer later.
@@ -299,16 +454,15 @@ void SoccerWorld::setBallHitter(unsigned int kart_id)
299454
*/
300455
bool SoccerWorld::isRaceOver()
301456
{
302-
303-
if(race_manager->hasTimeTarget())
457+
if (race_manager->hasTimeTarget())
304458
{
305459
return m_count_down_reached_zero;
306460
}
307461
// One team scored the target goals ...
308462
else
309463
{
310-
return (getScore(SOCCER_TEAM_BLUE) >= m_goal_target ||
311-
getScore(SOCCER_TEAM_RED) >= m_goal_target);
464+
return (getScore(SOCCER_TEAM_BLUE) >= m_goal_target ||
465+
getScore(SOCCER_TEAM_RED) >= m_goal_target);
312466
}
313467

314468
} // isRaceOver
@@ -492,22 +646,46 @@ void SoccerWorld::updateBallPosition(int ticks)
492646
{
493647
m_ball_track_sector
494648
->update(getBallPosition(), true/*ignore_vertical*/);
495-
if (!m_ball_track_sector->isOnRoad() && getPhase() == RACE_PHASE)
649+
if (!m_ball_track_sector->isOnRoad() && getPhase() == RACE_PHASE &&
650+
m_reset_ball_ticks == -1)
496651
{
497652
m_ball_invalid_timer += ticks;
498653
// Reset the ball and karts if out of navmesh after 2 seconds
499654
if (m_ball_invalid_timer >= stk_config->time2Ticks(2.0f))
500655
{
501-
m_ball_invalid_timer = 0;
502-
m_ball->reset();
503-
for (unsigned int i = 0; i < m_karts.size(); i++)
504-
moveKartAfterRescue(m_karts[i]);
505-
if (UserConfigParams::m_arena_ai_stats)
506-
getKart(8)->flyUp();
656+
if (NetworkConfig::get()->isNetworking() &&
657+
NetworkConfig::get()->isServer())
658+
{
659+
// Reset the ball 2 seconds in the future to make sure it's
660+
// after all clients time
661+
m_reset_ball_ticks =
662+
World::getWorld()->getTicksSinceStart() +
663+
stk_config->time2Ticks(2.0f);
664+
665+
NetworkString p(PROTOCOL_GAME_EVENTS);
666+
p.setSynchronous(true);
667+
p.addUInt8(GameEventsProtocol::GE_RESET_BALL)
668+
.addTime(m_reset_ball_ticks);
669+
STKHost::get()->sendPacketToAllPeers(&p, true);
670+
}
671+
else if (!NetworkConfig::get()->isNetworking())
672+
{
673+
m_ball_invalid_timer = 0;
674+
resetKartsToSelfGoals();
675+
if (UserConfigParams::m_arena_ai_stats)
676+
getKart(8)->flyUp();
677+
}
507678
}
508679
}
509680
else
510681
m_ball_invalid_timer = 0;
682+
if (m_reset_ball_ticks == World::getWorld()->getTicksSinceStart())
683+
{
684+
assert(NetworkConfig::get()->isNetworking() &&
685+
NetworkConfig::get()->isServer());
686+
resetKartsToSelfGoals();
687+
m_reset_ball_ticks = -1;
688+
}
511689
}
512690

513691
} // updateBallPosition

0 commit comments

Comments
 (0)