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