1 /*
2  * Copyright 2014, 2016 Peter Olsson
3  *
4  * This file is part of Brum Brum Rally.
5  *
6  * Brum Brum Rally is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Brum Brum Rally is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "Network.h"
21 #include "GameState.h"
22 #include "Settings.h"
23 #include "Track.h"
24 #include "StateManager.h"
25 #include "RaceState.h"
26 #include "NetworkBlankState.h"
27 #include "Track.h"
28 #include "Driver.h"
29 #include "ResultState.h"
30 #include "AIDriver.h"
31 #include "ErrorState.h"
32 #include "NetworkMenu.h"
33 #include "str.h"
34 #include <limits>
35 #include <algorithm>
36 #include <cassert>
37 #include <sstream>
38 
39 extern const int GAME_WIDTH;
40 
41 const Uint32 CONNECTION_TIMEOUT = 30000;
42 const Uint32 GAMEINFO_SEND_INTERVAL = 1000;
43 const Uint32 GAMEINFO_TIMEOUT = 3000;
44 const Uint32 CHAT_SEND_INTERVAL = 250;
45 const Uint32 PING_SEND_START = 20000;
46 const Uint32 PING_SEND_INTERVAL = 3000;
47 const Uint32 JOIN_TIMEOUT = 20000;
48 const Uint32 GAME_STATE_SEND_INTERVAL = 100;
49 const Uint32 GAME_TIMEOUT = 10000;
50 const Uint32 GAME_NO_CHAT_INTERVAL = 2000;
51 const Uint32 GAME_CHAT_INTERVAL = 100;
52 
53 const Uint32 CHAT_MESSAGE_TIMEOUT = 8000;
54 
55 const int NETWORK_STEP = 5;
56 
Network()57 Network::Network()
58 :	socket(0),
59 	connectionsIt(connections.end()),
60 	connectionType(NET_LOBBY),
61 	gameState(),
62 	lastChatMessage(0),
63 	chatOn(true),
64 	game(),
65 	reservedCars(0),
66 	joinStatus(),
67 	newGameState(0),
68 	gameStateId(0),
69 	gameStateCount(0),
70 	lastGameTimestamp(0),
71 	lastGameSent(0),
72 	newTrackInfoReady(false),
73 	newTrackInfoCounter(0),
74 	newTrackStateTick(0),
75 	inputBuffer(),
76 	raceTick(0),
77 	lastSlowDown(0),
78 	track(),
79 	lastChatMessageDeliveredToGameOwner(0),
80 	lastChatMessageRecivedFromGameOwner(0)
81 {
82 	if (SDLNet_Init() < 0)
83 	{
84 		error = SDL_GetError();
85 	}
86 }
87 
~Network()88 Network::~Network()
89 {
90 	quitGame();
91 
92 	SDLNet_UDP_Close(socket);
93 	SDLNet_Quit();
94 }
95 
step()96 void Network::step()
97 {
98 	while (receive())
99 	{
100 		handleMessage(msg.read8(), msg.getPacket().address);
101 	}
102 
103 	Uint32 now = SDL_GetTicks();
104 
105 	while (!chatBuffer.empty() && chatBuffer.back().timestamp + CHAT_MESSAGE_TIMEOUT <= now)
106 	{
107 		chatBuffer.pop_back();
108 	}
109 
110 	if (!connections.empty())
111 	{
112 		if (connectionsIt == connections.end())
113 		{
114 			connectionsIt = connections.begin();
115 		}
116 
117 		const IPaddress& address = connectionsIt->first;
118 		Connection& connection = connectionsIt->second;
119 
120 		if (connection.lastRecive + CONNECTION_TIMEOUT <= now)
121 		{
122 			// Timeout.
123 			onConnectionTimeout(address);
124 			gameList.update(address, 0);
125 			delete connection.gameInfo;
126 			connections.erase(connectionsIt++);
127 		}
128 		else
129 		{
130 			if (connection.gameInfo && connection.lastRecive + GAMEINFO_TIMEOUT <= now)
131 			{
132 				gameList.update(address, 0);
133 				delete connection.gameInfo;
134 				connection.gameInfo = 0;
135 			}
136 
137 			if (connectionType == NET_LOBBY)
138 			{
139 				if (connection.gameInfo == 0 &&
140 				    !chatBuffer.empty() &&
141 				    connection.lastChatMessageDelivered < lastChatMessage)
142 				{
143 					if (connection.lastSend + CHAT_SEND_INTERVAL <= now)
144 					{
145 						// Send unreceived message.
146 						sendLobbyMessage(connection, address);
147 					}
148 				}
149 				if (connection.lastSend + GAMEINFO_SEND_INTERVAL <= now)
150 				{
151 					// Request game info from game owners.
152 					// This also helps avoid timeout.
153 					// We send this message for all connections because
154 					// we don't know if they have become a game owner
155 					// without us notice.
156 					sendLobbyMessage(connection, address);
157 				}
158 			}
159 			else if (connectionType == NET_GAME_OWNER)
160 			{
161 				if (connection.lastRecive + PING_SEND_START <= now)
162 				{
163 					if (connection.lastSend + PING_SEND_INTERVAL <= now)
164 					{
165 						msg.reset();
166 						msg.write8(MSG_PING);
167 						msg.write32(now);
168 						send(address);
169 						connection.lastSend = SDL_GetTicks();
170 					}
171 				}
172 			}
173 			++connectionsIt;
174 		}
175 	}
176 
177 	chat.update();
178 
179 	if (connectionType == NET_GAME_OWNER)
180 	{
181 		// Timeouts
182 		std::map<IPaddress, GamePlayer>::iterator it;
183 		for (it = gameClients.begin(); it != gameClients.end();)
184 		{
185 			GamePlayer& gp = it->second;
186 			std::map<IPaddress, GamePlayer>::iterator tmp = it++;
187 			if (gp.lastRecive + GAME_TIMEOUT <= now)
188 			{
189 				erasePlayer(tmp, "timeout");
190 			}
191 		}
192 
193 		std::map<IPaddress, JoinInProgress>::iterator jit;
194 		for (jit = joinInProgress.begin(); jit != joinInProgress.end();)
195 		{
196 			JoinInProgress& jip = jit->second;
197 			std::map<IPaddress, JoinInProgress>::iterator tmp = jit++;
198 			if (jip.timeout <= now)
199 			{
200 				reservedCars &= ~jip.reservedCars;
201 				reservedPlayers -= jip.reservedPlayers;
202 				joinInProgress.erase(tmp);
203 			}
204 		}
205 
206 		// Send new state info.
207 		if (lastGameSent + GAME_STATE_SEND_INTERVAL <= now)
208 		{
209 			std::map<IPaddress, GamePlayer>::iterator it;
210 			for (it = gameClients.begin(); it != gameClients.end(); ++it)
211 			{
212 				GamePlayer& gp = it->second;
213 				const IPaddress& address = it->first;
214 
215 				if (gp.gameStateId != gameStateId)
216 				{
217 					msg.reset();
218 					if (gameStateId == NETWORK_GAME_STATE_RACE)
219 					{
220 						msg.write8(MSG_NEW_STATE_RACE);
221 						msg.write32(now);
222 						msg.write32(gameStateCount);
223 						msg.write8(game.laps);
224 						msg.write8(game.collisions);
225 						map.write(msg);
226 						msg.write8(raceCars.size());
227 						for (std::size_t i = 0; i < raceCars.size(); ++i)
228 						{
229 							NetworkRaceCar& nrc = *raceCars[i];
230 							msg.write8(nrc.car);
231 							msg.write8(nrc.player == &gp ? nrc.driver : std::numeric_limits<Uint8>::max());
232 						}
233 					}
234 					else if (gameStateId == NETWORK_GAME_STATE_TIMES ||
235 					         gameStateId == NETWORK_GAME_STATE_POINTS)
236 					{
237 						msg.write8(gameStateId == NETWORK_GAME_STATE_TIMES ? MSG_NEW_STATE_TIMES : MSG_NEW_STATE_POINTS);
238 						msg.write32(now);
239 						msg.write32(gameStateCount);
240 						msg.write8(game.tracks);
241 						msg.write8(game.track);
242 						msg.write8(raceCars.size());
243 
244 						std::vector<NetworkRaceCar*>::iterator it;
245 						for (it = raceCars.begin(); it != raceCars.end(); ++it)
246 						{
247 							NetworkRaceCar& car = **it;
248 
249 							msg.write8(car.car);
250 							msg.writeString(car.name);
251 							msg.write32(gameStateId == NETWORK_GAME_STATE_TIMES ? car.time : car.points);
252 						}
253 					}
254 					else
255 					{
256 						// This should never happen!
257 						assert("invalid game state id");
258 						continue;
259 					}
260 					send(address);
261 				}
262 			}
263 			lastGameSent = SDL_GetTicks();
264 		}
265 
266 		// Send race state.
267 		if (gameStateId == NETWORK_GAME_STATE_RACE && newTrackInfoReady)
268 		{
269 			std::map<IPaddress, GamePlayer>::iterator it;
270 			for (it = gameClients.begin(); it != gameClients.end(); ++it)
271 			{
272 				GamePlayer& gp = it->second;
273 				const IPaddress& address = it->first;
274 
275 				if (gp.gameStateId == gameStateId)
276 				{
277 					msg.reset();
278 					msg.write8(MSG_RACE_STATE);
279 					msg.write32(now);
280 
281 					msg.write8(track->getCarCount());
282 					msg.write8(removedCars.size());
283 					for (std::size_t i = removedCars.size() - 1; i < removedCars.size(); --i)
284 					{
285 						msg.write8(removedCars[i]);
286 					}
287 
288 					msg.write32(raceTick);
289 					Uint32 stateTick = std::max<Uint32>(gp.lastTick - gp.lastTick % NETWORK_STEP, newTrackStateTick - (TRACK_BUFFER_SIZE - 1) * NETWORK_STEP);
290 					msg.write32(stateTick);
291 					msg.write32(gp.ticksTooFast);
292 					msg.write32(gp.lastTimestamp);
293 
294 					const TrackState& trackState = trackStateBuffer[(newTrackStateTick - stateTick) / NETWORK_STEP];
295 					trackState.write(msg, raceCars.size());
296 
297 					for (Uint32 tick = stateTick; tick <= raceTick; ++tick)
298 					{
299 						msg.write32(inputBuffer[raceTick - tick]);
300 					}
301 
302 					writeChatMessage(gp);
303 
304 					send(address);
305 				}
306 			}
307 			newTrackInfoReady = false;
308 			newTrackInfoCounter = 0;
309 		}
310 		else if (gameStateId == NETWORK_GAME_STATE_TIMES ||
311 		         gameStateId == NETWORK_GAME_STATE_POINTS)
312 		{
313 			for (it = gameClients.begin(); it != gameClients.end(); ++it)
314 			{
315 				GamePlayer& gp = it->second;
316 				IPaddress address = it->first;
317 				bool haveMessagesToSend = !chatBuffer.empty() && gp.lastChatMessageDelivered < lastChatMessage;
318 
319 				if (gp.lastSent + (haveMessagesToSend ? GAME_CHAT_INTERVAL : GAME_NO_CHAT_INTERVAL) <= now)
320 				{
321 					msg.reset();
322 					msg.write8(MSG_GAME_CHAT_INFO);
323 					msg.write32(now);
324 					writeChatMessage(gp);
325 					send(address);
326 					gp.lastSent = SDL_GetTicks();
327 				}
328 			}
329 		}
330 	}
331 	else if (connectionType == NET_GAME_PLAYER)
332 	{
333 		// Timeout
334 		if (lastGameRecive + GAME_TIMEOUT <= now)
335 		{
336 			setNewGameState(new ErrorState("End of game", "The network game has timed out", new NetworkMenu(this)));
337 		}
338 		else if (newTrackInfoReady)
339 		{
340 			msg.write8(MSG_RACE_INPUT);
341 			msg.write32(now);
342 
343 			writeChatMessage();
344 
345 			msg.write32(raceTick);
346 			for (std::size_t i = 0; i < INPUT_BUFFER_SIZE; ++i)
347 			{
348 				msg.write32(inputBuffer[i]);
349 			}
350 
351 			send(gameOwner);
352 
353 			newTrackInfoReady = false;
354 			newTrackInfoCounter = 0;
355 		}
356 		else if (gameStateId == NETWORK_GAME_STATE_TIMES ||
357 		         gameStateId == NETWORK_GAME_STATE_POINTS)
358 		{
359 			bool haveMessagesToSend = !chatBuffer.empty() && lastChatMessageDeliveredToGameOwner < lastChatMessage;
360 
361 			if (lastGameSent + (haveMessagesToSend ? GAME_CHAT_INTERVAL : GAME_NO_CHAT_INTERVAL) <= now)
362 			{
363 				msg.write8(MSG_GAME_CHAT_ADD);
364 				msg.write32(now);
365 				writeChatMessage();
366 				send(gameOwner);
367 				lastGameSent = SDL_GetTicks();
368 			}
369 		}
370 	}
371 }
372 
updateTrack(bool noInput)373 void Network::updateTrack(bool noInput)
374 {
375 	if (gameStateId != NETWORK_GAME_STATE_RACE)
376 	{
377 		return;
378 	}
379 
380 	assert(track);
381 
382 	Uint32& prevInput = inputBuffer[0];
383 	Uint32& input = inputBuffer.next();
384 
385 	// Copy previous input.
386 	input = prevInput;
387 
388 	// Collect local input.
389 	for (std::size_t i = 0; i < localCars.size(); ++i)
390 	{
391 		assert(i < localCars.size());
392 		const NetworkRaceCar& car = localCars[i];
393 
394 		if (car.id >= 0 && car.human)
395 		{
396 			int carInput = noInput ? 0 : StateManager::getInstance().getDriver(car.driver)->drive(car.id, *track);
397 			input = (input & ~(0xF << (4 * car.id))) | (carInput << (4 * car.id));
398 		}
399 	}
400 
401 	track->update(TRACK_TIME_STEP * 0.001, &input);
402 	++raceTick;
403 
404 	if (raceTick % NETWORK_STEP == 0)
405 	{
406 		if (connectionType == NET_GAME_OWNER)
407 		{
408 			TrackState& trackState = trackStateBuffer.next();
409 			track->save(trackState);
410 			newTrackStateTick = raceTick;
411 		}
412 	}
413 	++newTrackInfoCounter;
414 	if (input != prevInput || newTrackInfoCounter >= NETWORK_STEP)
415 	{
416 		newTrackInfoReady = true;
417 	}
418 }
419 
setStatus(const std::string & str)420 void Network::setStatus(const std::string& str)
421 {
422 	Surface s(str, BIG_FONT, 123456, TEXT_BORDER_COLOR);
423 	statusRenderObject.setSurface(s);
424 	statusRenderObject.moveTo(GAME_WIDTH - s.width() - 2, 3);
425 }
426 
getError() const427 const std::string& Network::getError() const
428 {
429 	return error;
430 }
431 
handleMessage(Uint8 msgType,IPaddress address)432 void Network::handleMessage(Uint8 msgType, IPaddress address)
433 {
434 	Uint32 timestamp = msg.read32();
435 	Uint32 now = SDL_GetTicks();
436 
437 	switch (msgType)
438 	{
439 		case MSG_PING:
440 		case MSG_PONG:
441 		case MSG_LOBBY:
442 		case MSG_GAME_INFO:
443 		{
444 			std::map<IPaddress, Connection>::iterator it = connections.find(address);
445 			if (it == connections.end())
446 			{
447 				return;
448 			}
449 			Connection& connection = it->second;
450 
451 			if (timestamp <= connection.lastTimestamp)
452 			{
453 				return;
454 			}
455 			connection.lastTimestamp = timestamp;
456 
457 			connection.lastRecive = now;
458 
459 			switch (msgType)
460 			{
461 				case MSG_PING:
462 				{
463 					msg.reset();
464 					msg.write8(MSG_PONG);
465 					msg.write32(now);
466 					send(address);
467 					connection.lastSend = SDL_GetTicks();
468 					break;
469 				}
470 				case MSG_LOBBY:
471 				{
472 					if (connectionType == NET_LOBBY)
473 					{
474 						if (connection.gameInfo)
475 						{
476 							delete connection.gameInfo;
477 							connection.gameInfo = 0;
478 							gameList.update(address, 0);
479 						}
480 						Uint32 lastChatMessageDelivered = msg.read32();
481 						if (lastChatMessageDelivered > connection.lastChatMessageDelivered)
482 						{
483 							connection.lastChatMessageDelivered = lastChatMessageDelivered;
484 						}
485 						Uint32 chatMessage = msg.read32();
486 						if (chatMessage != 0 && chatMessage > connection.lastChatMessageRecived)
487 						{
488 							connection.lastChatMessageRecived = chatMessage;
489 							chat.addMessage(msg.readString(), CHAT_COLOR2);
490 						}
491 
492 						if (chatMessage != 0)
493 						{
494 							// It's necessary to send this message here
495 							// to make sure the sender knows that we
496 							// have received the chat message.
497 							sendLobbyMessage(connection, address);
498 						}
499 					}
500 					else if (connectionType == NET_GAME_OWNER)
501 					{
502 						if (blacklist.count(address.host))
503 						{
504 							return;
505 						}
506 						msg.reset();
507 						msg.write8(MSG_GAME_INFO);
508 						msg.write32(SDL_GetTicks());
509 						msg.write32(timestamp);
510 						msg.writeString(game.name);
511 						msg.write8(reservedPlayers);
512 						msg.write8(game.maxPlayers);
513 						msg.write8(game.tournament);
514 						msg.write8(game.collisions);
515 						send(address);
516 						connection.lastSend = SDL_GetTicks();
517 					}
518 					break;
519 				}
520 				case MSG_GAME_INFO:
521 				{
522 					if (!connection.gameInfo)
523 					{
524 						connection.gameInfo = new NetworkGameInfo();
525 					}
526 					connection.gameInfo->ping = now - msg.read32();
527 					connection.gameInfo->name = msg.readString();
528 					connection.gameInfo->players = msg.read8();
529 					connection.gameInfo->maxPlayers = msg.read8();
530 					connection.gameInfo->tournament = msg.read8();
531 					connection.gameInfo->collisions = msg.read8();
532 
533 					gameList.update(address, connection.gameInfo);
534 				}
535 			}
536 			break;
537 		}
538 		case MSG_JOIN_START:
539 		{
540 			if (blacklist.count(address.host))
541 			{
542 				return;
543 			}
544 			int maxPlayers = msg.read8();
545 			if (maxPlayers < 1 || maxPlayers > 8)
546 			{
547 				return;
548 			}
549 			std::map<IPaddress, JoinInProgress>::iterator it = joinInProgress.find(address);
550 			if (it != joinInProgress.end())
551 			{
552 				// Throw away the old join progress.
553 				JoinInProgress& jip = it->second;
554 				if (timestamp <= jip.lastTimestamp)
555 				{
556 					return;
557 				}
558 				reservedCars &= ~jip.reservedCars;
559 				reservedPlayers -= jip.reservedPlayers;
560 				joinInProgress.erase(it);
561 			}
562 
563 			if (reservedPlayers < game.maxPlayers)
564 			{
565 				JoinInProgress& jip = joinInProgress[address];
566 				jip.timeout = now + JOIN_TIMEOUT;
567 				jip.reservedPlayers = 1;
568 				++reservedPlayers;
569 				jip.reservedCars = 0;
570 				jip.lastTimestamp = timestamp;
571 				jip.maxPlayers = maxPlayers;
572 				jip.noMore = false;
573 
574 				sendJoinStatus(address, JOIN_MORE_CARS, 0, reservedCars);
575 			}
576 			else
577 			{
578 				sendJoinStatus(address, JOIN_ERROR, 0, reservedCars);
579 			}
580 			break;
581 		}
582 		case MSG_JOIN_CAR:
583 		{
584 			std::map<IPaddress, JoinInProgress>::iterator it = joinInProgress.find(address);
585 			if (it == joinInProgress.end())
586 			{
587 				return;
588 			}
589 			JoinInProgress& jip = it->second;
590 			if (timestamp <= jip.lastTimestamp)
591 			{
592 				return;
593 			}
594 			jip.lastTimestamp = timestamp;
595 			Uint8 car = msg.read8();
596 			if (car >= 8)
597 			{
598 				return;
599 			}
600 			jip.timeout = now + JOIN_TIMEOUT;
601 			Uint8 carBit = 1 << car;
602 
603 			if (jip.noMore)
604 			{
605 				sendJoinStatus(address, JOIN_NO_MORE_CARS, jip.cars.size(), reservedCars);
606 			}
607 			else if ((reservedCars & carBit) != 0)
608 			{
609 				// this car has already been taken
610 				sendJoinStatus(address, JOIN_MORE_CARS, jip.cars.size(), reservedCars);
611 			}
612 			else
613 			{
614 				jip.cars.push_back(car);
615 				jip.reservedCars |= carBit;
616 				reservedCars |= carBit;
617 
618 				if (jip.reservedPlayers < game.maxPlayersPerClient &&
619 				    reservedPlayers < game.maxPlayers &&
620 				    jip.reservedPlayers < jip.maxPlayers)
621 				{
622 					++reservedPlayers;
623 					++jip.reservedPlayers;
624 
625 					sendJoinStatus(address, JOIN_MORE_CARS, jip.cars.size(), reservedCars);
626 				}
627 				else
628 				{
629 					jip.noMore = true;
630 					sendJoinStatus(address, JOIN_NO_MORE_CARS, jip.cars.size(), reservedCars);
631 				}
632 			}
633 			break;
634 		}
635 		case MSG_JOIN_END:
636 		{
637 			std::map<IPaddress, JoinInProgress>::iterator it = joinInProgress.find(address);
638 			if (it == joinInProgress.end())
639 			{
640 				// Check if player has already joined.
641 				std::map<IPaddress, GamePlayer>::iterator it = gameClients.find(address);
642 				if (it != gameClients.end())
643 				{
644 					GamePlayer& gp = it->second;
645 					sendJoinStatus(address, JOIN_HAS_ENDED, gp.cars.size(), reservedCars);
646 				}
647 				return;
648 			}
649 			JoinInProgress& jip = it->second;
650 			if (timestamp <= jip.lastTimestamp)
651 			{
652 				return;
653 			}
654 
655 			GamePlayer& p = gameClients[address];
656 			for (std::size_t i = 0; i < jip.cars.size(); ++i)
657 			{
658 				NetworkRaceCar nrc;
659 				nrc.player = &p;
660 				nrc.car = jip.cars[i];
661 				nrc.name = uniqueName(msg.readString());
662 				nrc.id = -1;
663 				nrc.time = 0;
664 				nrc.points = 0;
665 				nrc.driver = i;
666 				nrc.human = true;
667 				p.cars.push_back(nrc);
668 				sendChatMessage(nrc.name + " has joined!", nrc.car);
669 			}
670 
671 			// The client has joined successfully!
672 			sendJoinStatus(address, JOIN_HAS_ENDED, jip.cars.size(), reservedCars);
673 
674 			p.gameStateId = NETWORK_GAME_STATE_BLANK;
675 			p.lastTick = 0;
676 			p.lastChatMessageDelivered = lastChatMessage;
677 			p.lastRecive = now;
678 
679 			joinInProgress.erase(address);
680 			break;
681 		}
682 		case MSG_JOIN_QUIT:
683 		{
684 			std::map<IPaddress, JoinInProgress>::iterator it = joinInProgress.find(address);
685 			if (it == joinInProgress.end())
686 			{
687 				return;
688 			}
689 			JoinInProgress& jip = it->second;
690 			if (timestamp <= jip.lastTimestamp)
691 			{
692 				return;
693 			}
694 			reservedCars &= ~jip.reservedCars;
695 			reservedPlayers -= jip.reservedPlayers;
696 			joinInProgress.erase(it);
697 			break;
698 		}
699 		case MSG_JOIN_STATUS:
700 		{
701 			if (connectionType == NET_LOBBY)
702 			{
703 				if (joinStatus.address == address)
704 				{
705 					if (timestamp <= joinStatus.lastTimestamp)
706 					{
707 						return;
708 					}
709 					joinStatus.updated = true;
710 					joinStatus.lastTimestamp = timestamp;
711 					joinStatus.state = msg.read8();
712 					joinStatus.joinedPlayers = msg.read8();
713 					joinStatus.reservedCars = msg.read8();
714 					if (joinStatus.state > JOIN_ERROR ||
715 					    joinStatus.joinedPlayers > 7)
716 					{
717 						joinStatus.state = JOIN_ERROR;
718 					}
719 					if (joinStatus.state == JOIN_HAS_ENDED)
720 					{
721 						int n = msg.read8();
722 						chatInput.clear();
723 						if (n > 8 || n < 0)
724 						{
725 							chatInput.addPlayer("error");
726 						}
727 						else
728 						{
729 							for (int i = 0; i < n; ++i)
730 							{
731 								std::string name = msg.readString();
732 								int car = msg.read8();
733 								chatInput.addPlayer(name, car);
734 							}
735 						}
736 					}
737 				}
738 			}
739 			break;
740 		}
741 		case MSG_NEW_STATE_RACE:
742 		case MSG_NEW_STATE_TIMES:
743 		case MSG_NEW_STATE_POINTS:
744 		case MSG_RACE_STATE:
745 		case MSG_END_GAME:
746 		case MSG_GAME_CHAT_INFO:
747 		{
748 			if (connectionType != NET_GAME_PLAYER)
749 			{
750 				return;
751 			}
752 			if (address != gameOwner)
753 			{
754 				return;
755 			}
756 			if (timestamp <= lastGameTimestamp)
757 			{
758 				return;
759 			}
760 			lastGameTimestamp = timestamp;
761 			lastGameRecive = now;
762 			if (msgType == MSG_NEW_STATE_RACE  ||
763 				msgType == MSG_NEW_STATE_TIMES ||
764 				msgType == MSG_NEW_STATE_POINTS)
765 			{
766 				Uint32 newGameStateCount = msg.read32();
767 				if (newGameStateCount <= gameStateCount)
768 				{
769 					if (newGameStateCount == gameStateCount)
770 					{
771 						// Resend game state info in case the game
772 						// owner has not received that information.
773 						msg.reset();
774 						msg.write8(MSG_STATE_STATUS);
775 						msg.write32(SDL_GetTicks());
776 						msg.write8(gameStateId);
777 						msg.write32(gameStateCount);
778 						send(address);
779 						lastGameSent = SDL_GetTicks();
780 					}
781 					return;
782 				}
783 
784 				switch (msgType)
785 				{
786 					case MSG_NEW_STATE_RACE:
787 					{
788 						Uint8 laps = msg.read8();
789 						if (laps > 9)
790 						{
791 							return;
792 						}
793 						bool collisions = msg.read8() != 0;
794 
795 						map.read(msg);
796 						if (!map.isValid())
797 						{
798 							return;
799 						}
800 
801 						std::size_t carCount = msg.read8();
802 						if (carCount < 1 || carCount > 8)
803 						{
804 							return;
805 						}
806 						std::vector<int> cars(carCount);
807 						std::vector<Driver*> drivers(carCount);
808 						localCars.clear();
809 						inputMask = 0;
810 						for (std::size_t i = 0; i < carCount; ++i)
811 						{
812 							Uint8 car = msg.read8();
813 							if (car >= 8)
814 							{
815 								return;
816 							}
817 							cars[i] = car;
818 
819 							Uint8 driver = msg.read8();
820 							if (driver < 8)
821 							{
822 								drivers[i] = StateManager::getInstance().getDriver(driver);
823 
824 								NetworkRaceCar nrc;
825 								nrc.player = 0;
826 								nrc.car = car;
827 								nrc.id = i;
828 								nrc.driver = driver;
829 								nrc.time = 0;
830 								nrc.points = 0;
831 								nrc.human = true;
832 								localCars.push_back(nrc);
833 								inputMask |= 0xF << (i * 4);
834 							}
835 						}
836 
837 						// Start race!
838 						std::vector<std::string> names(drivers.size());
839 						RaceState* raceState = new RaceState(map, RaceSetup(drivers, cars, names, laps, 1, false, collisions), this);
840 						setNewGameState(raceState);
841 						track = raceState->getTrack();
842 						for (std::size_t i = 0; i < TRACK_BUFFER_SIZE; ++i)
843 						{
844 							trackStateBuffer[i].setCars(carCount);
845 							track->save(trackStateBuffer[i]);
846 						}
847 						for (std::size_t i = 0; i < INPUT_BUFFER_SIZE; ++i)
848 						{
849 							inputBuffer[i] = 0;
850 						}
851 
852 						gameStateId = NETWORK_GAME_STATE_RACE;
853 
854 						raceTick = 0;
855 						newTrackInfoReady = false;
856 						newTrackInfoCounter = 0;
857 						newTrackStateTick = 0;
858 
859 						break;
860 					}
861 					case MSG_NEW_STATE_TIMES:
862 					case MSG_NEW_STATE_POINTS:
863 					{
864 						Uint8 tracks = msg.read8();
865 						Uint8 currentTrack = msg.read8();
866 
867 						Uint8 n = msg.read8();
868 						if (n > 8)
869 						{
870 							return;
871 						}
872 						std::vector<Driver*> drivers(n);
873 						std::vector<int> cars(n);
874 						std::vector<std::string> names(n);
875 						std::vector<int> values(n);
876 						for (int i = 0; i < n; ++i)
877 						{
878 							cars[i] = msg.read8() % 8;
879 							names[i] = msg.readString();
880 							values[i] = msg.read32();
881 						}
882 						RaceSetup raceSetup(drivers,cars ,names, 0, tracks, tracks > 1, 0);
883 						raceSetup.setTrack(currentTrack);
884 
885 						void (RaceSetup::*setValue)(int, int);
886 						if (msgType == MSG_NEW_STATE_TIMES)
887 						{
888 							gameStateId = NETWORK_GAME_STATE_TIMES;
889 							setValue = &RaceSetup::setPlayerTime;
890 						}
891 						else
892 						{
893 							gameStateId = NETWORK_GAME_STATE_POINTS;
894 							setValue = &RaceSetup::setPlayerPoints;
895 						}
896 						for (int i = 0; i < n; ++i)
897 						{
898 							(raceSetup.*setValue)(i, values[i]);
899 						}
900 
901 						setNewGameState(new ResultState(raceSetup, this, gameStateId == NETWORK_GAME_STATE_POINTS));
902 						break;
903 					}
904 				}
905 
906 				gameStateCount = newGameStateCount;
907 
908 				msg.reset();
909 				msg.write8(MSG_STATE_STATUS);
910 				msg.write32(SDL_GetTicks());
911 				msg.write8(gameStateId);
912 				msg.write32(gameStateCount);
913 				send(address);
914 				lastGameSent = SDL_GetTicks();
915 			}
916 			else if (msgType == MSG_RACE_STATE)
917 			{
918 				if (gameStateId != NETWORK_GAME_STATE_RACE)
919 				{
920 					return;
921 				}
922 
923 				Uint8 carCount = msg.read8();
924 				Uint8 removedCarCount = msg.read8();
925 				Uint8 removedCar;
926 				for (int i = 0; i < removedCarCount; ++i)
927 				{
928 					removedCar = msg.read8();
929 					if (carCount < track->getCarCount())
930 					{
931 						eraseCar(removedCar);
932 					}
933 				}
934 
935 				Uint32 tick = msg.read32();
936 				Uint32 stateTick = msg.read32();
937 				if (stateTick > tick)
938 				{
939 					return;
940 				}
941 
942 				// Last message received by game owner.
943 				Uint32 ticksTooFast = msg.read32();
944 				Uint32 myGameOwnerTimestamp = msg.read32();
945 
946 				if (ticksTooFast > 0 && myGameOwnerTimestamp > lastSlowDown)
947 				{
948 					// We are running too fast!
949 					raceTick -= ticksTooFast;
950 					lastSlowDown = now;
951 				}
952 
953 				// It's important that we don't use else-if here because
954 				// the above if statement can make raceTick greater than
955 				// tick if ticksTooFast is faulty. It is also possible
956 				// that we are running too slow even though the game
957 				// owner noticed we ran too fast only recently.
958 
959 				if (tick > raceTick)
960 				{
961 					// We are running too slow!
962 					raceTick = tick;
963 				}
964 
965 				if (raceTick - stateTick > INPUT_BUFFER_SIZE)
966 				{
967 					// We can't handle this in a good way so it's better
968 					// to do nothing and hope the sync improves.
969 					return;
970 				}
971 
972 				// We use one of the track states in the
973 				// buffer to avoid unnecessary reallocations.
974 				TrackState& trackState = trackStateBuffer[0];
975 				trackState.read(msg, track->getCarCount());
976 
977 				track->restore(trackState);
978 
979 				// This input might not look useful but it will be used in the
980 				// second loop below if stateTick == tick && tick < raceTick.
981 				Uint32 input = msg.read32();
982 
983 				for (Uint32 t = stateTick + 1; t <= tick; ++t)
984 				{
985 					Uint32 i = raceTick - t;
986 					input = msg.read32();
987 					inputBuffer[i] = (inputBuffer[i] & inputMask) | (input & ~inputMask);
988 				}
989 
990 				for (Uint32 t = tick + 1; t <= raceTick; ++t)
991 				{
992 					Uint32 i = raceTick - t;
993 					inputBuffer[i] = (inputBuffer[i] & inputMask) | (input & ~inputMask);
994 				}
995 
996 				for (Uint32 t = stateTick + 1; t <= raceTick; ++t)
997 				{
998 					Uint32 i = raceTick - t;
999 					track->update(TRACK_TIME_STEP * 0.001, &inputBuffer[i]);
1000 				}
1001 
1002 				readChatMessage();
1003 			}
1004 			else if (msgType == MSG_END_GAME)
1005 			{
1006 				setNewGameState(new ErrorState("End of game", "The network game has ended", new NetworkMenu(this)));
1007 			}
1008 			else if (msgType == MSG_GAME_CHAT_INFO)
1009 			{
1010 				if (readChatMessage())
1011 				{
1012 					// Force message to be sent as soon as possible to
1013 					// inform the game owner that we have received the
1014 					// message.
1015 					lastGameSent = 0;
1016 				}
1017 			}
1018 			break;
1019 		}
1020 		case MSG_STATE_STATUS:
1021 		case MSG_RACE_INPUT:
1022 		case MSG_QUIT_GAME:
1023 		case MSG_GAME_CHAT_ADD:
1024 		{
1025 			if (connectionType != NET_GAME_OWNER)
1026 			{
1027 				return;
1028 			}
1029 			std::map<IPaddress, GamePlayer>::iterator it = gameClients.find(address);
1030 			if (it == gameClients.end())
1031 			{
1032 				break;
1033 			}
1034 			GamePlayer& gp = it->second;
1035 			if (timestamp <= gp.lastTimestamp)
1036 			{
1037 				return;
1038 			}
1039 			gp.lastTimestamp = timestamp;
1040 			gp.lastRecive = now;
1041 			if (msgType == MSG_STATE_STATUS)
1042 			{
1043 				int newPlayerGameStateId = msg.read8();
1044 				Uint32 playerStateCount = msg.read32();
1045 				if (gp.gameStateId != newPlayerGameStateId && playerStateCount == gameStateCount)
1046 				{
1047 					gp.gameStateId = newPlayerGameStateId;
1048 				}
1049 			}
1050 			else if (msgType == MSG_RACE_INPUT)
1051 			{
1052 				if (gameStateId != NETWORK_GAME_STATE_RACE)
1053 				{
1054 					return;
1055 				}
1056 
1057 				readChatMessage(gp);
1058 
1059 				Uint32 tick = msg.read32();
1060 				gp.ticksTooFast = tick > raceTick ? tick - raceTick : 0;
1061 
1062 				if (gp.ticksTooFast > 0)
1063 				{
1064 					// No point handling out of sync input.
1065 					// Better wait until we are in sync.
1066 					return;
1067 				}
1068 
1069 				if (tick < gp.lastTick)
1070 				{
1071 					// This could happen when the player adjusts for out
1072 					// of sync so we just modify the last tick value so
1073 					// that it will work in the calculations that follow
1074 					gp.lastTick = tick;
1075 				}
1076 
1077 				Uint32 stepBackNeeded = raceTick - gp.lastTick;
1078 				Uint32 stepBackPossible = (TRACK_BUFFER_SIZE - 1) * NETWORK_STEP + raceTick % NETWORK_STEP;
1079 
1080 				Uint32 stepBack = std::min(stepBackNeeded, stepBackPossible);
1081 				Uint32 restoreTick = raceTick - stepBack;
1082 				Uint32 restoreStateIndex = raceTick / NETWORK_STEP - restoreTick / NETWORK_STEP;
1083 
1084 				track->restore(trackStateBuffer[restoreStateIndex]);
1085 
1086 				// Read player input.
1087 				for (Uint32 i = raceTick - tick; i < stepBack; ++i)
1088 				{
1089 					Uint32 preInputValue = inputBuffer[i];
1090 					inputBuffer[i] = (inputBuffer[i] & ~gp.inputMask) | (msg.read32() & gp.inputMask);
1091 					if (inputBuffer[i] != preInputValue)
1092 					{
1093 						newTrackInfoReady = true;
1094 					}
1095 				}
1096 				for (Uint32 i = 0; i < raceTick - tick; ++i)
1097 				{
1098 					inputBuffer[i] = (inputBuffer[i] & ~gp.inputMask) | (inputBuffer[raceTick - tick] & gp.inputMask);
1099 				}
1100 				stepBack += (restoreTick % NETWORK_STEP);
1101 				raceTick -= stepBack;
1102 
1103 				for (int i = stepBack - 1; i >= 0; --i)
1104 				{
1105 					track->update(TRACK_TIME_STEP * 0.001, &inputBuffer[i]);
1106 					++raceTick;
1107 					if (raceTick % NETWORK_STEP == 0)
1108 					{
1109 						--restoreStateIndex;
1110 						TrackState& trackState = trackStateBuffer[restoreStateIndex];
1111 						track->save(trackState);
1112 					}
1113 				}
1114 
1115 				gp.lastTick = tick;
1116 			}
1117 			else if (msgType == MSG_QUIT_GAME)
1118 			{
1119 				erasePlayer(it);
1120 			}
1121 			else if (msgType == MSG_GAME_CHAT_ADD)
1122 			{
1123 				readChatMessage(gp);
1124 			}
1125 			break;
1126 		}
1127 	}
1128 }
1129 
sendLobbyMessage(Connection & connection,const IPaddress & address)1130 void Network::sendLobbyMessage(Connection& connection, const IPaddress& address)
1131 {
1132 	msg.reset();
1133 	msg.write8(MSG_LOBBY);
1134 	msg.write32(SDL_GetTicks());
1135 	msg.write32(connection.lastChatMessageRecived);
1136 	if (!chatBuffer.empty() && connection.lastChatMessageDelivered < lastChatMessage)
1137 	{
1138 		Uint32 messageToSend = std::max(connection.lastChatMessageDelivered, static_cast<Uint32>(lastChatMessage - chatBuffer.size())) + 1;
1139 		msg.write32(messageToSend);
1140 		msg.writeString(chatBuffer[lastChatMessage - messageToSend].text);
1141 	}
1142 	else
1143 	{
1144 		msg.write32(0);
1145 	}
1146 	send(address);
1147 	connection.lastSend = SDL_GetTicks();
1148 }
1149 
onConnectionTimeout(const IPaddress & addr)1150 void Network::onConnectionTimeout(const IPaddress& addr)
1151 {
1152 }
1153 
send(IPaddress address)1154 void Network::send(IPaddress address)
1155 {
1156 	UDPpacket& packet = msg.getPacket();
1157 	packet.address = address;
1158 	SDLNet_UDP_Send(socket, -1, &packet);
1159 }
1160 
receive()1161 bool Network::receive()
1162 {
1163 	msg.reset();
1164 	UDPpacket& packet = msg.getPacket();
1165 	return SDLNet_UDP_Recv(socket, &packet) == 1;
1166 }
1167 
setGameState(GameState * newGameState,bool chatOn,bool gameListOn)1168 void Network::setGameState(GameState* newGameState, bool chatOn, bool gameListOn)
1169 {
1170 	this->chatOn = chatOn;
1171 	gameState = newGameState;
1172 	if (gameState)
1173 	{
1174 		gameState->addRenderObject(statusRenderObject);
1175 	}
1176 
1177 	chat.setGameState(chatOn ? gameState : 0);
1178 	chatInput.setGameState(chatOn && chat.isEnabled() ? gameState : 0);
1179 	gameList.setGameState(gameListOn ? gameState : 0);
1180 }
1181 
enableChatInput(bool chatInputOn)1182 void Network::enableChatInput(bool chatInputOn)
1183 {
1184 	chatInput.setGameState(chatInputOn && chat.isEnabled() ? gameState : 0);
1185 }
1186 
onEvent(const SDL_Event & event,bool isDriving)1187 bool Network::onEvent(const SDL_Event& event, bool isDriving)
1188 {
1189 	if (event.type == SDL_KEYDOWN)
1190 	{
1191 		SDLKey key = event.key.keysym.sym;
1192 
1193 		if (key == SDLK_F5 && connectionType == NET_LOBBY)
1194 		{
1195 			refreshAsNeeded();
1196 		}
1197 		else if (!chatOn)
1198 		{
1199 			return false;
1200 		}
1201 		else if (key == SDLK_TAB)
1202 		{
1203 			chat.toggle();
1204 			chatInput.setGameState(chat.isEnabled() ? gameState : 0);
1205 			return true;
1206 		}
1207 		else if (chat.isEnabled())
1208 		{
1209 			// Don't start inputting a new chat message if the key is used for driving.
1210 			if (isDriving && !chatInput.isVisible())
1211 			{
1212 				assert(gameStateId == NETWORK_GAME_STATE_RACE);
1213 
1214 				for (std::size_t i = 0; i < localCars.size(); ++i)
1215 				{
1216 					const NetworkRaceCar& car = localCars[i];
1217 
1218 					if (car.id >= 0 && car.human && StateManager::getInstance().getDriver(car.driver)->isUsingKey(key))
1219 					{
1220 						// Wait a small time period after the car has finished to avoid accidental chat input.
1221 						const double CHAT_KEY_DELAY = 1.0; // seconds
1222 						if (!track->isCarFinished(car.id) || track->getCarFinishTime(car.id) + CHAT_KEY_DELAY > track->getRaceTime())
1223 						{
1224 							// The key is used for driving!
1225 							return false;
1226 						}
1227 					}
1228 				}
1229 			}
1230 
1231 			if (chatInput.onEvent(event))
1232 			{
1233 				if (chatInput.isReady())
1234 				{
1235 					std::string text = chatInput.fetch();
1236 					std::istringstream iss(text);
1237 					iss.ignore(1000, ':'); // ignore username
1238 					iss.ignore(); // ignore space
1239 					if (iss.get() == '/')
1240 					{
1241 						if (connectionType == NET_LOBBY)
1242 						{
1243 							chat.addMessage("No commands allowed here!");
1244 						}
1245 						else if (connectionType == NET_GAME_PLAYER)
1246 						{
1247 							chat.addMessage("Commands can only be used by the \"game owner\"!");
1248 						}
1249 						else
1250 						{
1251 							std::string command;
1252 							if (iss >> command)
1253 							{
1254 								if (command == "help")
1255 								{
1256 									chat.addMessage("Commands: /ban /kick /kickall /mute /list /color");
1257 								}
1258 								else if (command == "list")
1259 								{
1260 									std::vector<std::string> names;
1261 
1262 									std::vector<NetworkRaceCar>::iterator itCar;
1263 									for (itCar = localCars.begin(); itCar != localCars.end(); ++itCar)
1264 									{
1265 										names.push_back(itCar->name);
1266 									}
1267 
1268 									std::map<IPaddress, GamePlayer>::iterator itPlayer;
1269 									for (itPlayer = gameClients.begin(); itPlayer != gameClients.end(); ++itPlayer)
1270 									{
1271 										GamePlayer& gp = itPlayer->second;
1272 										for (itCar = gp.cars.begin(); itCar != gp.cars.end(); ++itCar)
1273 										{
1274 											names.push_back(itCar->name);
1275 										}
1276 									}
1277 
1278 									std::sort(names.begin(), names.end());
1279 
1280 									std::string message;
1281 									for (std::size_t i = 0; i < names.size(); ++i)
1282 									{
1283 										message += (message.empty() ? "" : ", ") + names[i];
1284 									}
1285 									chat.addMessage(message);
1286 								}
1287 								else if (command == "color"   ||
1288 										 command == "colour"  ||
1289 								         command == "ban"     ||
1290 								         command == "kick"    ||
1291 								         command == "kickall" ||
1292 								         command == "mute")
1293 								{
1294 									std::map<IPaddress, GamePlayer>::iterator itPlayer = gameClients.end();
1295 									std::vector<NetworkRaceCar>::iterator itCar;
1296 									bool carFound = false;
1297 									std::string username;
1298 									iss >> username;
1299 									std::string token;
1300 									while (iss >> token)
1301 									{
1302 										username += " " + token;
1303 									}
1304 									for (itCar = localCars.begin(); itCar != localCars.end(); ++itCar)
1305 									{
1306 										if (itCar->name == username)
1307 										{
1308 											carFound = true;
1309 											break;
1310 										}
1311 									}
1312 									if (!carFound)
1313 									{
1314 										for (itPlayer = gameClients.begin(); itPlayer != gameClients.end(); ++itPlayer)
1315 										{
1316 											GamePlayer& gp = itPlayer->second;
1317 											for (itCar = gp.cars.begin(); itCar != gp.cars.end(); ++itCar)
1318 											{
1319 												if (itCar->name == username)
1320 												{
1321 													carFound = true;
1322 													break;
1323 												}
1324 											}
1325 											if (carFound)
1326 											{
1327 												break;
1328 											}
1329 										}
1330 									}
1331 									if (!carFound)
1332 									{
1333 										if (username.empty())
1334 										{
1335 											chat.addMessage("Missing username!");
1336 										}
1337 										else
1338 										{
1339 											chat.addMessage("No user named " + username +"!");
1340 										}
1341 									}
1342 									else if (command == "color" ||
1343 									         command == "colour")
1344 									{
1345 										chat.addMessage(username + " drives a " + carColorName(itCar->car) + " car", carColor(itCar->car));
1346 									}
1347 									else if (command == "ban")
1348 									{
1349 										if (itPlayer != gameClients.end())
1350 										{
1351 											GamePlayer& gp = itPlayer->second;
1352 											itCar = gp.cars.begin();
1353 											for (itCar = gp.cars.begin(); itCar != gp.cars.end();)
1354 											{
1355 												itCar = eraseCar(itCar, "banned");
1356 											}
1357 											blacklist.insert(itPlayer->first.host);
1358 										}
1359 										else
1360 										{
1361 											chat.addMessage("You can't ban yourself!");
1362 										}
1363 									}
1364 									else if (command == "kick")
1365 									{
1366 										if (itPlayer != gameClients.end())
1367 										{
1368 											eraseCar(itCar, "kicked");
1369 										}
1370 										else
1371 										{
1372 											std::size_t localHumanPlayers = 0;
1373 											for (std::size_t i = 0; i < localCars.size(); ++i)
1374 											{
1375 												if (localCars[i].human)
1376 												{
1377 													++localHumanPlayers;
1378 												}
1379 											}
1380 
1381 											if (!itCar->human || localHumanPlayers > 1)
1382 											{
1383 												eraseCar(itCar, "kicked");
1384 											}
1385 											else
1386 											{
1387 												chat.addMessage("You need at least one player!");
1388 											}
1389 										}
1390 									}
1391 									else if (command == "kickall")
1392 									{
1393 										if (itPlayer != gameClients.end())
1394 										{
1395 											GamePlayer& gp = itPlayer->second;
1396 											itCar = gp.cars.begin();
1397 											for (itCar = gp.cars.begin(); itCar != gp.cars.end();)
1398 											{
1399 												itCar = eraseCar(itCar, "kicked");
1400 											}
1401 										}
1402 										else
1403 										{
1404 											chat.addMessage("You need at least one player!");
1405 										}
1406 									}
1407 									else if (command == "mute")
1408 									{
1409 										if (itPlayer != gameClients.end())
1410 										{
1411 											GamePlayer& gp = itPlayer->second;
1412 											gp.mute = !gp.mute;
1413 											sendChatMessage(username + " has been " + (gp.mute ? "" : "un") + "muted!", itCar->car);
1414 										}
1415 										else
1416 										{
1417 											chat.addMessage("You can't mute yourself!");
1418 										}
1419 									}
1420 								}
1421 								else
1422 								{
1423 									chat.addMessage("Invalid command! Try /help");
1424 								}
1425 
1426 							}
1427 						}
1428 					}
1429 					else
1430 					{
1431 						sendChatMessage(text, chatInput.fetchCar());
1432 					}
1433 				}
1434 				return true;
1435 			}
1436 		}
1437 	}
1438 	return false;
1439 }
1440 
setGame(const std::string & name,int maxPlayers,int maxPlayersPerClient,int laps,int tracks,int collisions)1441 void Network::setGame(const std::string& name, int maxPlayers, int maxPlayersPerClient, int laps, int tracks, int collisions)
1442 {
1443 	game.name = name;
1444 	game.maxPlayers = maxPlayers;
1445 	game.maxPlayersPerClient = maxPlayersPerClient;
1446 	game.laps = laps;
1447 	game.tracks = tracks;
1448 	game.tournament = tracks > 1;
1449 	game.collisions = collisions;
1450 }
createGame(Uint8 reservedCars,std::vector<int> cars)1451 void Network::createGame(Uint8 reservedCars, std::vector<int> cars)
1452 {
1453 	chat.clear();
1454 	chatInput.clear();
1455 	chatBuffer.clear();
1456 	removedCars.clear();
1457 	gameClients.clear();
1458 	joinInProgress.clear();
1459 	gameClients.clear();
1460 	localCars.clear();
1461 
1462 	connectionType = NET_GAME_OWNER;
1463 	gameStateId = NETWORK_GAME_STATE_RACE; // Start race right away.
1464 
1465 	std::vector<int> freeCars(8);
1466 	for (int i = 0; i < 8; ++i)
1467 	{
1468 		freeCars[i] = i;
1469 	}
1470 
1471 	for (std::size_t i = 0; i < cars.size(); ++i)
1472 	{
1473 		NetworkRaceCar nrc;
1474 		nrc.player = 0;
1475 		nrc.name = Settings::players.humanNames[i];
1476 		nrc.car = cars[i];
1477 		nrc.id = -1;
1478 		nrc.driver = i;
1479 		nrc.time = 0;
1480 		nrc.points = 0;
1481 		nrc.human = true;
1482 		localCars.push_back(nrc);
1483 		freeCars.erase(std::remove(freeCars.begin(), freeCars.end(), nrc.car), freeCars.end());
1484 		chatInput.addPlayer(nrc.name, nrc.car);
1485 	}
1486 
1487 	std::random_shuffle(freeCars.begin(), freeCars.end());
1488 
1489 	// Add computer players
1490 	for (int i = 0; i < Settings::network.computerPlayers && i < int(freeCars.size()); ++i)
1491 	{
1492 		NetworkRaceCar nrc;
1493 		nrc.player = 0;
1494 		nrc.name = Settings::players.computerNames[i];
1495 		nrc.car = freeCars[i];
1496 		nrc.id = -1;
1497 		nrc.driver = i;
1498 		nrc.time = 0;
1499 		nrc.points = 0;
1500 		nrc.human = false;
1501 		localCars.push_back(nrc);
1502 		cars.push_back(nrc.car);
1503 		reservedCars |= 1 << nrc.car;
1504 	}
1505 
1506 	reservedPlayers = cars.size();
1507 	this->reservedCars = reservedCars;
1508 
1509 	gameStateCount = 0;
1510 	startRace();
1511 }
1512 
getGameList()1513 GameList& Network::getGameList()
1514 {
1515 	return gameList;
1516 }
1517 
sendJoinStart()1518 void Network::sendJoinStart()
1519 {
1520 	msg.reset();
1521 	msg.write8(MSG_JOIN_START);
1522 	msg.write32(SDL_GetTicks());
1523 	msg.write8(Settings::network.players);
1524 	send(joinStatus.address);
1525 }
1526 
sendJoinCar(int car)1527 void Network::sendJoinCar(int car)
1528 {
1529 	msg.reset();
1530 	msg.write8(MSG_JOIN_CAR);
1531 	msg.write32(SDL_GetTicks());
1532 	msg.write8(car);
1533 	send(joinStatus.address);
1534 }
1535 
sendJoinEnd()1536 void Network::sendJoinEnd()
1537 {
1538 	msg.reset();
1539 	msg.write8(MSG_JOIN_END);
1540 	msg.write32(SDL_GetTicks());
1541 	for (int i = 0; i < 8; ++i)
1542 	{
1543 			msg.writeString(Settings::players.humanNames[i]);
1544 	}
1545 	send(joinStatus.address);
1546 }
1547 
join(const IPaddress & address)1548 void Network::join(const IPaddress& address)
1549 {
1550 	joinStatus.updated = false;
1551 	joinStatus.address = address;
1552 	joinStatus.state = JOIN_NOT_STARTED;
1553 	joinStatus.joinedPlayers = 0;
1554 	joinStatus.reservedCars = 0;
1555 	joinStatus.lastTimestamp = 0;
1556 }
1557 
sendJoinStatus(const IPaddress & address,int state,Uint8 joinedPlayers,Uint8 reservedCars)1558 void Network::sendJoinStatus(const IPaddress& address, int state, Uint8 joinedPlayers, Uint8 reservedCars)
1559 {
1560 	msg.reset();
1561 	msg.write8(MSG_JOIN_STATUS);
1562 	msg.write32(SDL_GetTicks());
1563 	msg.write8(state);
1564 	msg.write8(joinedPlayers);
1565 	msg.write8(reservedCars);
1566 	if (state == JOIN_HAS_ENDED)
1567 	{
1568 		GamePlayer& gp = gameClients[address];
1569 		msg.write8(gp.cars.size());
1570 		for (std::size_t i = 0; i < gp.cars.size(); ++i)
1571 		{
1572 			msg.writeString(gp.cars[i].name);
1573 			msg.write8(gp.cars[i].car);
1574 		}
1575 	}
1576 	send(address);
1577 }
1578 
getJoinStatus(JoinStatus & status)1579 bool Network::getJoinStatus(JoinStatus& status)
1580 {
1581 	status = joinStatus;
1582 	joinStatus.updated = false;
1583 	return status.updated;
1584 }
1585 
getNewGameState()1586 GameState* Network::getNewGameState()
1587 {
1588 	GameState* gs = newGameState;
1589 	newGameState = 0;
1590 	return gs;
1591 }
setNewGameState(GameState * gs)1592 void Network::setNewGameState(GameState* gs)
1593 {
1594 	delete newGameState;
1595 	newGameState = gs;
1596 }
1597 
join()1598 void Network::join()
1599 {
1600 	connectionType = NET_GAME_PLAYER;
1601 	gameOwner = joinStatus.address;
1602 	gameStateId = NETWORK_GAME_STATE_BLANK;
1603 	gameStateCount = 0;
1604 	lastGameRecive = SDL_GetTicks();
1605 
1606 	// Instead calling connections.clear() here we simply let them
1607 	// time out to make sure all the necessary cleanup is made.
1608 
1609 	chat.clear();
1610 	// chatInput is cleared elsewhere.
1611 	chatBuffer.clear();
1612 
1613 	setNewGameState(new NetworkBlankState(this));
1614 }
1615 
raceCarSorter(const NetworkRaceCar * c1,const NetworkRaceCar * c2)1616 bool raceCarSorter(const NetworkRaceCar* c1, const NetworkRaceCar* c2)
1617 {
1618 	int t1 = c1->time > 0 ? c1->time : std::numeric_limits<int>::max();
1619 	int t2 = c2->time > 0 ? c2->time : std::numeric_limits<int>::max();
1620 	return t1 > t2;
1621 }
1622 
startRace()1623 void Network::startRace()
1624 {
1625 	// Add all cars.
1626 	raceCars.clear();
1627 	for (std::size_t i = 0; i < localCars.size(); ++i)
1628 	{
1629 		raceCars.push_back(&localCars[i]);
1630 	}
1631 	std::map<IPaddress, GamePlayer>::iterator it;
1632 	for (it = gameClients.begin(); it != gameClients.end(); ++it)
1633 	{
1634 		GamePlayer& gp = it->second;
1635 		std::vector<NetworkRaceCar>& nrc = gp.cars;
1636 		for (std::size_t i = 0; i < nrc.size(); ++i)
1637 		{
1638 			raceCars.push_back(&nrc[i]);
1639 		}
1640 		gp.inputMask = 0;
1641 		gp.lastTick = 0;
1642 	}
1643 
1644 	// Sort by time of previous race.
1645 	std::sort(raceCars.begin(), raceCars.end(), raceCarSorter);
1646 
1647 	// Update and collect information.
1648 	std::vector<Driver*> drivers(raceCars.size());
1649 	std::vector<int> cars(raceCars.size());
1650 	std::vector<std::string> names(raceCars.size());
1651 	for (std::size_t i = 0; i < raceCars.size(); ++i)
1652 	{
1653 		NetworkRaceCar& car = *raceCars[i];
1654 		car.id = i;
1655 		cars[i] = car.car;
1656 		names[i] = car.name;
1657 		if (car.player)
1658 		{
1659 			car.player->inputMask |= 0xF << (i * 4);
1660 		}
1661 		else
1662 		{
1663 			assert(car.driver < 8);
1664 			if (car.human)
1665 			{
1666 				drivers[i] = StateManager::getInstance().getDriver(car.driver);
1667 			}
1668 			else
1669 			{
1670 				int difficulty = Settings::players.computerDifficulties[car.driver];
1671 				if (difficulty < 0)
1672 				{
1673 					difficulty = Settings::network.computerDifficulty;
1674 				}
1675 				drivers[i] = &AIDriver::getInstance(difficulty);
1676 			}
1677 		}
1678 	}
1679 
1680 	map = Map::generate();
1681 
1682 	// Start new race!
1683 	++gameStateCount;
1684 	gameStateId = NETWORK_GAME_STATE_RACE;
1685 
1686 	RaceSetup raceSetup(drivers, cars, names, Settings::network.laps, Settings::network.tracks, Settings::network.tournament, Settings::network.collisions);
1687 	raceSetup.setTrack(game.track);
1688 
1689 	for (std::size_t i = 0; i < raceCars.size(); ++i)
1690 	{
1691 		raceSetup.setPlayerPoints(raceCars[i]->id, raceCars[i]->points);
1692 	}
1693 
1694 	RaceState* raceState = new RaceState(map, raceSetup, this);
1695 	setNewGameState(raceState);
1696 	track = raceState->getTrack();
1697 	for (std::size_t i = 0; i < TRACK_BUFFER_SIZE; ++i)
1698 	{
1699 		trackStateBuffer[i].setCars(raceCars.size());
1700 		track->save(trackStateBuffer[i]);
1701 	}
1702 	for (std::size_t i = 0; i < INPUT_BUFFER_SIZE; ++i)
1703 	{
1704 		inputBuffer[i] = 0;
1705 	}
1706 
1707 	raceTick = 0;
1708 	newTrackInfoReady = true; // Send state as soon as possible!
1709 	newTrackInfoCounter = 0;
1710 	newTrackStateTick = 0;
1711 }
1712 
onRaceFinished(const RaceSetup & rs)1713 void Network::onRaceFinished(const RaceSetup& rs)
1714 {
1715 	if (connectionType == NET_GAME_OWNER)
1716 	{
1717 		setNewGameState(new ResultState(rs, this));
1718 		++gameStateCount;
1719 		gameStateId = NETWORK_GAME_STATE_TIMES;
1720 
1721 		std::vector<NetworkRaceCar*>::iterator it;
1722 		for (it = raceCars.begin(); it != raceCars.end(); ++it)
1723 		{
1724 			NetworkRaceCar& car = **it;
1725 			car.time = rs.getPlayerTime(car.id);
1726 			car.points = rs.getPlayerPoints(car.id);
1727 		}
1728 		game.track = rs.getCurrentTrack();
1729 
1730 		// We call refresh here because finishing a race is not something that
1731 		// can happen repeatedly without a user at the keyboard. Fetching the
1732 		// list while not racing seems to be a good idea to minimize the cpu
1733 		// usage while racing.
1734 		refreshAsNeeded();
1735 	}
1736 }
1737 
onShowPoints(const RaceSetup & rs)1738 void Network::onShowPoints(const RaceSetup& rs)
1739 {
1740 	if (connectionType == NET_GAME_OWNER)
1741 	{
1742 		setNewGameState(new ResultState(rs, this, true));
1743 		++gameStateCount;
1744 		gameStateId = NETWORK_GAME_STATE_POINTS;
1745 	}
1746 }
1747 
isOwner() const1748 bool Network::isOwner() const
1749 {
1750 	return connectionType == NET_GAME_OWNER;
1751 }
1752 
sleep(Uint32 duration)1753 void Network::sleep(Uint32 duration)
1754 {
1755 	// The purpose of this "sleep" function is to handle messages more
1756 	// rapidly in order to get more accurate ping value.
1757 	if (connectionType != NET_GAME_PLAYER && !connections.empty())
1758 	{
1759 		Uint32 stop = SDL_GetTicks() + duration;
1760 		while (SDL_GetTicks() < stop)
1761 		{
1762 			if (receive())
1763 			{
1764 				handleMessage(msg.read8(), msg.getPacket().address);
1765 			}
1766 			else
1767 			{
1768 				SDL_Delay(1);
1769 			}
1770 		}
1771 	}
1772 	else
1773 	{
1774 		SDL_Delay(duration);
1775 	}
1776 }
1777 
sendChatMessage(const std::string & text,int car)1778 void Network::sendChatMessage(const std::string& text, int car)
1779 {
1780 	SentChatMessage cm;
1781 	cm.text = text;
1782 	cm.timestamp = SDL_GetTicks();
1783 	cm.car = car;
1784 	chatBuffer.push_front(cm);
1785 	++lastChatMessage;
1786 	if (connectionType != NET_GAME_PLAYER)
1787 	{
1788 		chat.addMessage(text, carColor(car));
1789 	}
1790 }
1791 
quitGame()1792 void Network::quitGame()
1793 {
1794 	// For simplicity we just send the message repeatedly and hope the
1795 	// other end receives it. I have no idea if routers might have some
1796 	// kind of filter for identical messages that are sent rapidly so
1797 	// for that reason we update the message each time so that at least
1798 	// the time data is different.
1799 
1800 	const int QUIT_SEND_COUNT = 8;
1801 	const int QUIT_SEND_DELAY = 28;
1802 
1803 	if (connectionType == NET_GAME_PLAYER)
1804 	{
1805 		for (int i = 0; i < QUIT_SEND_COUNT; ++i)
1806 		{
1807 			if (i > 0)
1808 			{
1809 				SDL_Delay(QUIT_SEND_DELAY);
1810 			}
1811 			msg.reset();
1812 			msg.write8(MSG_QUIT_GAME);
1813 			msg.write32(SDL_GetTicks());
1814 			send(gameOwner);
1815 		}
1816 	}
1817 	else if (connectionType == NET_GAME_OWNER)
1818 	{
1819 		for (int i = 0; i < QUIT_SEND_COUNT; ++i)
1820 		{
1821 			if (i > 0)
1822 			{
1823 				SDL_Delay(QUIT_SEND_DELAY);
1824 			}
1825 			msg.reset();
1826 			msg.write8(MSG_END_GAME);
1827 			msg.write32(SDL_GetTicks());
1828 			std::map<IPaddress, GamePlayer>::iterator it;
1829 			for (it = gameClients.begin(); it != gameClients.end(); ++it)
1830 			{
1831 				send(it->first);
1832 			}
1833 		}
1834 	}
1835 	else if (connectionType == NET_LOBBY && (joinStatus.state == JOIN_MORE_CARS || joinStatus.state == JOIN_NO_MORE_CARS))
1836 	{
1837 		for (int i = 0; i < QUIT_SEND_COUNT; ++i)
1838 		{
1839 			if (i > 0)
1840 			{
1841 				SDL_Delay(QUIT_SEND_DELAY);
1842 			}
1843 			msg.reset();
1844 			msg.write8(MSG_JOIN_QUIT);
1845 			msg.write32(SDL_GetTicks());
1846 			send(joinStatus.address);
1847 		}
1848 	}
1849 }
1850 
erasePlayer(std::map<IPaddress,GamePlayer>::iterator it,const std::string & reason)1851 void Network::erasePlayer(std::map<IPaddress, GamePlayer>::iterator it, const std::string& reason)
1852 {
1853 	GamePlayer& gp = it->second;
1854 	std::vector<NetworkRaceCar>::iterator carIt;
1855 	for (carIt = gp.cars.begin(); carIt != gp.cars.end();)
1856 	{
1857 		carIt = eraseCar(carIt, reason);
1858 	}
1859 	gameClients.erase(it);
1860 }
1861 
eraseCar(std::vector<NetworkRaceCar>::iterator carIt,const std::string & reason)1862 std::vector<NetworkRaceCar>::iterator Network::eraseCar(std::vector<NetworkRaceCar>::iterator carIt, const std::string& reason)
1863 {
1864 	assert(connectionType == NET_GAME_OWNER);
1865 	if (carIt->id >= 0)
1866 	{
1867 		if (gameStateId == NETWORK_GAME_STATE_RACE)
1868 		{
1869 			for (std::size_t i = 0; i < TRACK_BUFFER_SIZE; ++i)
1870 			{
1871 				trackStateBuffer[i].removeCar(carIt->id, track->getCarCount());
1872 			}
1873 			for (std::size_t i = 0; i < INPUT_BUFFER_SIZE; ++i)
1874 			{
1875 				Uint32 highMask = ~0U << ((carIt->id + 1) * 4);
1876 				Uint32 lowMask = ~(~0U << (carIt->id * 4));
1877 
1878 				Uint32 highInput = (inputBuffer[i] & highMask) >> 4;
1879 				Uint32 lowInput = inputBuffer[i] & lowMask;
1880 
1881 				inputBuffer[i] = highInput | lowInput;
1882 			}
1883 			track->removeCar(carIt->id);
1884 			removedCars.push_back(carIt->id);
1885 		}
1886 
1887 		raceCars.erase(raceCars.begin() + carIt->id);
1888 		for (std::size_t i = carIt->id; i < raceCars.size(); ++i)
1889 		{
1890 			Uint32* mask;
1891 			if (raceCars[i]->player)
1892 			{
1893 				mask = &raceCars[i]->player->inputMask;
1894 			}
1895 			else
1896 			{
1897 				mask = &inputMask;
1898 			}
1899 			*mask &= ~(0xF << (raceCars[i]->id * 4));  // remove old mask
1900 			--raceCars[i]->id;
1901 			*mask |= 0xF << (raceCars[i]->id * 4); // add new mask
1902 		}
1903 	}
1904 
1905 	std::string quitMessage = carIt->name + " has quit!";
1906 	if (!reason.empty())
1907 	{
1908 		quitMessage += " (" + reason + ")";
1909 	}
1910 	sendChatMessage(quitMessage, carIt->car);
1911 	reservedCars &= ~(1 << carIt->car);
1912 	--reservedPlayers;
1913 
1914 	std::vector<NetworkRaceCar>::iterator nextIt;
1915 	if (carIt->player)
1916 	{
1917 		carIt->player->removedCars.push_back(carIt->car);
1918 		nextIt = carIt->player->cars.erase(carIt);
1919 	}
1920 	else
1921 	{
1922 		chatInput.removePlayer(carIt->car);
1923 		nextIt = localCars.erase(carIt);
1924 	}
1925 
1926 	// The pointers need to be reinitialized because some
1927 	// of the old pointers might not be valid any more.
1928 	for (std::size_t i = 0; i < localCars.size(); ++i)
1929 	{
1930 		if (localCars[i].id >= 0)
1931 		{
1932 			raceCars[localCars[i].id] = &localCars[i];
1933 		}
1934 	}
1935 	std::map<IPaddress, GamePlayer>::iterator it;
1936 	for (it = gameClients.begin(); it != gameClients.end(); ++it)
1937 	{
1938 		GamePlayer& gp = it->second;
1939 		std::vector<NetworkRaceCar>& nrc = gp.cars;
1940 		for (std::size_t i = 0; i < nrc.size(); ++i)
1941 		{
1942 			if (nrc[i].id >= 0)
1943 			{
1944 				raceCars[nrc[i].id] = &nrc[i];
1945 			}
1946 		}
1947 	}
1948 
1949 	return nextIt;
1950 }
1951 
eraseCar(int carId)1952 void Network::eraseCar(int carId)
1953 {
1954 	assert(connectionType == NET_GAME_PLAYER);
1955 
1956 	if (gameStateId == NETWORK_GAME_STATE_RACE && carId < track->getCarCount())
1957 	{
1958 		track->removeCar(carId);
1959 		for (std::size_t i = 0; i < INPUT_BUFFER_SIZE; ++i)
1960 		{
1961 			Uint32 highMask = ~0U << ((carId + 1) * 4);
1962 			Uint32 lowMask = ~(~0U << (carId * 4));
1963 
1964 			Uint32 highInput = (inputBuffer[i] & highMask) >> 4;
1965 			Uint32 lowInput = inputBuffer[i] & lowMask;
1966 
1967 			inputBuffer[i] = highInput | lowInput;
1968 		}
1969 
1970 		inputMask = 0;
1971 		std::vector<NetworkRaceCar>::iterator carIt;
1972 		for (carIt = localCars.begin(); carIt != localCars.end();)
1973 		{
1974 			if (carIt->id == carId)
1975 			{
1976 				carIt = localCars.erase(carIt);
1977 			}
1978 			else
1979 			{
1980 				if (carIt->id > carId)
1981 				{
1982 					--carIt->id;
1983 				}
1984 				inputMask |= 0xF << (carIt->id * 4);
1985 				++carIt;
1986 			}
1987 		}
1988 	}
1989 }
1990 
writeChatMessage()1991 void Network::writeChatMessage()
1992 {
1993 	msg.write32(lastChatMessageRecivedFromGameOwner);
1994 	if (!chatBuffer.empty() && lastChatMessageDeliveredToGameOwner < lastChatMessage)
1995 	{
1996 		Uint32 messageToSend = std::max(lastChatMessageDeliveredToGameOwner, static_cast<Uint32>(lastChatMessage - chatBuffer.size())) + 1;
1997 		msg.write32(messageToSend);
1998 		SentChatMessage& message = chatBuffer[lastChatMessage - messageToSend];
1999 		msg.writeString(message.text);
2000 		msg.write8(message.car);
2001 	}
2002 	else
2003 	{
2004 		msg.write32(0);
2005 	}
2006 }
writeChatMessage(const GamePlayer & gp)2007 void Network::writeChatMessage(const GamePlayer& gp)
2008 {
2009 	msg.write32(gp.lastChatMessageRecived);
2010 	if (!chatBuffer.empty() && gp.lastChatMessageDelivered < lastChatMessage)
2011 	{
2012 		Uint32 messageToSend = std::max(gp.lastChatMessageDelivered, static_cast<Uint32>(lastChatMessage - chatBuffer.size())) + 1;
2013 		msg.write32(messageToSend);
2014 		SentChatMessage& message = chatBuffer[lastChatMessage - messageToSend];
2015 		msg.writeString(message.text);
2016 		msg.write8(message.car);
2017 	}
2018 	else
2019 	{
2020 		msg.write32(0);
2021 
2022 		// send removed cars so that they can be removed from chat list.
2023 		msg.write8(gp.removedCars.size());
2024 		for (std::size_t i = 0; i < gp.removedCars.size(); ++i)
2025 		{
2026 			msg.write8(gp.removedCars[i]);
2027 		}
2028 	}
2029 }
readChatMessage(GamePlayer & gp)2030 void Network::readChatMessage(GamePlayer& gp)
2031 {
2032 	Uint32 lastChatMessageDelivered = msg.read32();
2033 	if (lastChatMessageDelivered > gp.lastChatMessageDelivered)
2034 	{
2035 		gp.lastChatMessageDelivered = lastChatMessageDelivered;
2036 	}
2037 	Uint32 chatMessage = msg.read32();
2038 	if (chatMessage != 0 && chatMessage > gp.lastChatMessageRecived)
2039 	{
2040 		gp.lastChatMessageRecived = chatMessage;
2041 		std::string message = msg.readString();
2042 		int car = msg.read8();
2043 
2044 		if (!gp.mute)
2045 		{
2046 			// Make sure the car is valid.
2047 			for (std::size_t i = 0; i < gp.cars.size(); ++i)
2048 			{
2049 				if (gp.cars[i].car == car)
2050 				{
2051 					sendChatMessage(message, car);
2052 					break;
2053 				}
2054 			}
2055 		}
2056 	}
2057 }
readChatMessage()2058 bool Network::readChatMessage()
2059 {
2060 	Uint32 lastChatMessageDelivered = msg.read32();
2061 	if (lastChatMessageDelivered > lastChatMessageDeliveredToGameOwner)
2062 	{
2063 		lastChatMessageDeliveredToGameOwner = lastChatMessageDelivered;
2064 	}
2065 	Uint32 chatMessage = msg.read32();
2066 	if (chatMessage != 0)
2067 	{
2068 		if (chatMessage > lastChatMessageRecivedFromGameOwner)
2069 		{
2070 			lastChatMessageRecivedFromGameOwner = chatMessage;
2071 			std::string message = msg.readString();
2072 			int car = msg.read8();
2073 			chat.addMessage(message, carColor(car));
2074 		}
2075 		// Return true even if the chat message has already been received
2076 		// so that we can act properly in order to inform the game owner
2077 		// that we have received this message.
2078 		return true;
2079 	}
2080 	else
2081 	{
2082 		// Remove cars from char input list.
2083 		int n = msg.read8();
2084 		for (int i = 0; i < n; ++i)
2085 		{
2086 			chatInput.removePlayer(msg.read8());
2087 			if (chatInput.empty())
2088 			{
2089 				setNewGameState(new ErrorState("End of game", "You have been kicked out!", new NetworkMenu(this)));
2090 			}
2091 		}
2092 	}
2093 	return false;
2094 }
2095 
uniqueName(const std::string & name) const2096 std::string Network::uniqueName(const std::string& name) const
2097 {
2098 	std::vector<std::string> names;
2099 
2100 	std::vector<NetworkRaceCar>::const_iterator itCar;
2101 	for (itCar = localCars.begin(); itCar != localCars.end(); ++itCar)
2102 	{
2103 		names.push_back(itCar->name);
2104 	}
2105 
2106 	std::map<IPaddress, GamePlayer>::const_iterator itPlayer;
2107 	for (itPlayer = gameClients.begin(); itPlayer != gameClients.end(); ++itPlayer)
2108 	{
2109 		const GamePlayer& gp = itPlayer->second;
2110 		for (itCar = gp.cars.begin(); itCar != gp.cars.end(); ++itCar)
2111 		{
2112 			names.push_back(itCar->name);
2113 		}
2114 	}
2115 
2116 	std::string uName = name.empty() ? "noname" : name;
2117 	int n = 1;
2118 	while (std::find(names.begin(), names.end(), uName) != names.end())
2119 	{
2120 		uName = name + "-" + int2string(++n);
2121 	}
2122 	return uName;
2123 }
2124 
lobby()2125 void Network::lobby()
2126 {
2127 	if (connectionType != NET_LOBBY)
2128 	{
2129 		chat.clear();
2130 		chatInput.clear();
2131 		chatBuffer.clear();
2132 		chatInput.addDefaultPlayers();
2133 	}
2134 	if (connectionType == NET_GAME_PLAYER)
2135 	{
2136 		// Let GAME_PLAYER refresh it's list if needed.
2137 		refreshAsNeeded();
2138 	}
2139 
2140 	connectionType = NET_LOBBY;
2141 	reservedCars = 0;
2142 	joinStatus = JoinStatus();
2143 	gameStateId = 0;
2144 	gameStateCount = 0;
2145 	lastGameTimestamp = 0;
2146 	lastGameSent = 0;
2147 	track = 0;
2148 	lastChatMessageDeliveredToGameOwner = 0;
2149 	lastChatMessageRecivedFromGameOwner = 0;
2150 }
2151 
numberOfPlayersWaiting() const2152 int Network::numberOfPlayersWaiting() const
2153 {
2154 	int playerCount = 0;
2155 	std::map<IPaddress, Connection>::const_iterator it;
2156 
2157 	for (it = connections.begin(); it != connections.end(); ++it)
2158 	{
2159 		const Connection& connection = it->second;
2160 		if (!connection.isBot && connection.gameInfo == 0)
2161 		{
2162 			++playerCount;
2163 		}
2164 	}
2165 
2166 	return playerCount;
2167 }
2168