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 #ifndef NETWORK_H
21 #define NETWORK_H
22 
23 #include "NetworkMessage.h"
24 #include "Chat.h"
25 #include "ChatInput.h"
26 #include "GameList.h"
27 #include "TrackState.h"
28 #include "CircularBuffer.h"
29 #include "Map.h"
30 #include "RaceSetup.h"
31 #include <set>
32 #include <map>
33 #include <string>
34 
35 class Track;
36 
37 enum
38 {
39 	NETWORK_GAME_STATE_BLANK,
40 	NETWORK_GAME_STATE_RACE,
41 	NETWORK_GAME_STATE_TIMES,
42 	NETWORK_GAME_STATE_POINTS
43 };
44 
45 enum
46 {
47 	JOIN_NOT_STARTED,
48 	JOIN_MORE_CARS,
49 	JOIN_NO_MORE_CARS,
50 	JOIN_HAS_ENDED,
51 	JOIN_ERROR
52 };
53 
54 struct JoinStatus
55 {
56 	bool updated;
57 	IPaddress address;
58 	int state;
59 	int joinedPlayers;
60 	Uint8 reservedCars;
61 	Uint32 lastTimestamp;
62 };
63 
64 enum ConnectionType
65 {
66 	NET_LOBBY,
67 	NET_GAME_OWNER,
68 	NET_GAME_PLAYER
69 };
70 
71 struct NetworkGame
72 {
73 	std::string name;
74 	int maxPlayers;
75 	int maxPlayersPerClient;
76 	int laps;
77 	int track;
78 	int tracks;
79 	bool tournament;
80 	bool collisions;
81 };
82 
83 struct NetworkGameInfo
84 {
85 	std::string name;
86 	int players;
87 	int maxPlayers;
88 	int track;
89 	int tracks;
90 	bool tournament;
91 	bool collisions;
92 	Uint32 ping;
93 };
94 
95 
96 struct Connection
97 {
ConnectionConnection98 	Connection()
99 	:	lastRecive(0),
100 		lastSend(0),
101 		lastChatMessageRecived(0),
102 		lastChatMessageDelivered(0),
103 		lastTimestamp(0),
104 		isBot(false),
105 		gameInfo()
106 	{
107 	}
108 	Uint32 lastRecive;
109 	Uint32 lastSend;
110 	Uint32 lastChatMessageRecived;
111 	Uint32 lastChatMessageDelivered;
112 	Uint32 lastTimestamp;
113 	bool isBot;
114 	NetworkGameInfo *gameInfo;
115 };
116 
117 struct SentChatMessage
118 {
119 	std::string text;
120 	Uint32 timestamp;
121 	int car;
122 };
123 
124 struct JoinInProgress
125 {
126 	Uint32 timeout;
127 	int reservedPlayers;
128 	Uint8 reservedCars;
129 	std::vector<int> cars;
130 	Uint32 lastTimestamp;
131 	int maxPlayers;
132 	bool noMore;
133 };
134 
135 struct NetworkRaceCar
136 {
137 	struct GamePlayer* player;
138 	std::string name;
139 	int car;
140 	int id;
141 	int time;
142 	int points;
143 	int driver;
144 	bool human;
145 
146 };
147 
148 struct GamePlayer
149 {
150 	std::vector<NetworkRaceCar> cars;
151 	std::vector<int> removedCars;
152 	int gameStateId;
153 	Uint32 lastTimestamp;
154 	Uint32 lastRecive;
155 	Uint32 lastTick;
156 	Uint32 inputMask;
157 	Uint32 ticksTooFast;
158 	Uint32 lastSent;
159 
160 	Uint32 lastChatMessageRecived;
161 	Uint32 lastChatMessageDelivered;
162 	bool mute;
163 };
164 
165 inline bool operator<(const IPaddress& addr1, const IPaddress& addr2)
166 {
167 	return (addr1.host == addr2.host) ? (addr1.port < addr2.port) : (addr1.host < addr2.host);
168 }
169 
170 inline bool operator==(const IPaddress& addr1, const IPaddress& addr2)
171 {
172 	return addr1.host == addr2.host && addr1.port == addr2.port;
173 }
174 
175 inline bool operator!=(const IPaddress& addr1, const IPaddress& addr2)
176 {
177 	return !(addr1 == addr2);
178 }
179 
180 class Network
181 {
182 public:
183 	Network();
184 	virtual ~Network();
185 	virtual void step();
186 	void updateTrack(bool noInput);
187 	void setStatus(const std::string& str);
188 	const std::string& getError() const;
189 	virtual std::string name() const = 0;
190 	void setGameState(GameState* gameState, bool chatOn = true, bool gameListOn = false);
191 	void enableChatInput(bool chatInputOn);
192 	bool onEvent(const SDL_Event& event, bool isDriving = false);
193 	void setGame(const std::string& name, int maxPlayers, int maxPlayersPerClient, int laps, int tracks, int collisions);
194 	void createGame(Uint8 reservedCars, std::vector<int> cars);
195 	GameList& getGameList();
196 	void sendJoinStart();
197 	void sendJoinCar(int car);
198 	void sendJoinEnd();
199 	void join(const IPaddress& address);
200 	bool getJoinStatus(JoinStatus&);
201 	GameState* getNewGameState();
202 	void join();
203 	void onRaceFinished(const RaceSetup& rs);
204 	void onShowPoints(const RaceSetup& rs);
205 	bool isOwner() const;
206 	void startRace();
207 	void sleep(Uint32 duration);
208 	void sendChatMessage(const std::string& text, int car = -1);
209 	void quitGame();
210 	void erasePlayer(std::map<IPaddress, GamePlayer>::iterator it, const std::string& reason = "");
211 	std::vector<NetworkRaceCar>::iterator eraseCar(std::vector<NetworkRaceCar>::iterator it, const std::string& reason = "");
212 	void eraseCar(int carId);
213 	void writeChatMessage();
214 	void writeChatMessage(const GamePlayer& gp);
215 	void readChatMessage(GamePlayer& gp);
216 	bool readChatMessage();
217 	std::string uniqueName(const std::string& name) const;
218 	void lobby();
219 	int numberOfPlayersWaiting() const;
220 protected:
221 	void setNewGameState(GameState*);
222 	virtual void handleMessage(Uint8 msgType, IPaddress address);
223 	virtual void onConnectionTimeout(const IPaddress& addr);
224 	virtual void refreshAsNeeded() = 0;
225 	void send(IPaddress address);
226 	bool receive();
227 private:
228 	void sendJoinStatus(const IPaddress& address, int state, Uint8 joinedPlayers, Uint8 reservedCars);
229 	void sendLobbyMessage(Connection& connection, const IPaddress& address);
230 
231 protected:
232 	std::map<IPaddress, JoinInProgress> joinInProgress;
233 
234 	UDPsocket socket;
235 
236 	std::map<IPaddress, Connection> connections;
237 	std::map<IPaddress, Connection>::iterator connectionsIt;
238 
239 	NetworkMessage msg;
240 
241 	enum
242 	{
243 		LOBBY_CONNECTION = 0x1,
244 		LOBBY_CHAT       = 0x2
245 	};
246 	ConnectionType connectionType;
247 	std::string error;
248 
249 
250 private:
251 	RenderObject statusRenderObject;
252 	Chat chat;
253 	ChatInput chatInput;
254 	GameState* gameState;
255 
256 	std::deque<SentChatMessage> chatBuffer;
257 	Uint32 lastChatMessage;
258 	bool chatOn;
259 	NetworkGame game;
260 	GameList gameList;
261 
262 	std::map<IPaddress, GamePlayer> gameClients;
263 	Uint8 reservedCars;
264 	int reservedPlayers;
265 
266 	JoinStatus joinStatus;
267 	GameState* newGameState;
268 	int gameStateId;
269 	Uint32 gameStateCount;
270 
271 	IPaddress gameOwner;
272 	Uint32 lastGameTimestamp;
273 	Uint32 lastGameRecive;
274 	Uint32 lastGameSent;
275 	static const std::size_t TRACK_BUFFER_SIZE = 10;
276 	CircularBuffer<TrackState, TRACK_BUFFER_SIZE> trackStateBuffer;
277 	bool newTrackInfoReady;
278 	int newTrackInfoCounter;
279 	Uint32 newTrackStateTick;
280 	static const std::size_t INPUT_BUFFER_SIZE = 50;
281 	CircularBuffer<Uint32, INPUT_BUFFER_SIZE> inputBuffer;
282 	Uint32 raceTick;
283 	Uint32 inputMask;
284 	Uint32 lastSlowDown;
285 	Map map;
286 	Track* track;
287 	std::vector<NetworkRaceCar> localCars;
288 	std::vector<NetworkRaceCar*> raceCars;
289 	Uint32 lastChatMessageDeliveredToGameOwner;
290 	Uint32 lastChatMessageRecivedFromGameOwner;
291 	std::vector<int> removedCars;
292 	std::set<Uint32> blacklist;
293 };
294 
295 enum
296 {
297 	MSG_PING,
298 	MSG_PONG,
299 	MSG_LOBBY,
300 	MSG_GAME_INFO,
301 	MSG_JOIN_START,
302 	MSG_JOIN_CAR,
303 	MSG_JOIN_END,
304 	MSG_JOIN_STATUS,
305 	MSG_NEW_STATE_RACE,
306 	MSG_NEW_STATE_TIMES,
307 	MSG_NEW_STATE_POINTS,
308 	MSG_STATE_STATUS,
309 	MSG_GAME_CHAT_INFO,
310 	MSG_GAME_CHAT_ADD,
311 	MSG_RACE_STATE,
312 	MSG_RACE_INPUT,
313 	MSG_QUIT_GAME,
314 	MSG_END_GAME,
315 	MSG_JOIN_QUIT
316 };
317 
createAddress(Uint32 ip,Uint16 port)318 inline IPaddress createAddress(Uint32 ip, Uint16 port)
319 {
320 	IPaddress addr;
321 
322 	SDLNet_Write32(ip, &addr.host);
323 	SDLNet_Write16(port, &addr.port);
324 
325 	return addr;
326 }
327 
getIP(IPaddress addr)328 inline Uint32 getIP(IPaddress addr)
329 {
330 	return SDLNet_Read32(&addr.host);
331 }
332 
getPort(IPaddress addr)333 inline Uint16 getPort(IPaddress addr)
334 {
335 	return SDLNet_Read16(&addr.port);
336 }
337 
338 #endif
339