| [2488852] | 1 | #include <cstdlib> | 
|---|
| [371ce29] | 2 | #include <cstdio> | 
|---|
| [e3535b3] | 3 | #include <unistd.h> | 
|---|
| [2488852] | 4 | #include <string> | 
|---|
| [e3535b3] | 5 | #include <iostream> | 
|---|
| [3b1efcc] | 6 | #include <sstream> | 
|---|
| [edfd1d0] | 7 | #include <cstring> | 
|---|
| [60017fc] | 8 | #include <cmath> | 
|---|
| [371ce29] | 9 |  | 
|---|
| [01d0d00] | 10 | #include <vector> | 
|---|
|  | 11 | #include <map> | 
|---|
|  | 12 |  | 
|---|
| [d211210] | 13 | #include <sys/time.h> | 
|---|
|  | 14 |  | 
|---|
| [73f75c1] | 15 | #include <sys/socket.h> | 
|---|
| [371ce29] | 16 | #include <netdb.h> | 
|---|
| [73f75c1] | 17 | #include <netinet/in.h> | 
|---|
|  | 18 | #include <arpa/inet.h> | 
|---|
|  | 19 |  | 
|---|
| [b128109] | 20 | #include <crypt.h> | 
|---|
|  | 21 |  | 
|---|
| [edfd1d0] | 22 | /* | 
|---|
| [e3535b3] | 23 | #include <openssl/bio.h> | 
|---|
|  | 24 | #include <openssl/ssl.h> | 
|---|
|  | 25 | #include <openssl/err.h> | 
|---|
| [edfd1d0] | 26 | */ | 
|---|
| [e3535b3] | 27 |  | 
|---|
| [b53c6b3] | 28 | #include "../common/Compiler.h" | 
|---|
| [3b1efcc] | 29 | #include "../common/Common.h" | 
|---|
| [edfd1d0] | 30 | #include "../common/Message.h" | 
|---|
| [60017fc] | 31 | #include "../common/WorldMap.h" | 
|---|
| [edfd1d0] | 32 | #include "../common/Player.h" | 
|---|
| [b53c6b3] | 33 |  | 
|---|
| [36082e8] | 34 | #include "DataAccess.h" | 
|---|
| [d2b411a] | 35 |  | 
|---|
| [e3535b3] | 36 | using namespace std; | 
|---|
|  | 37 |  | 
|---|
| [d211210] | 38 | // from used to be const. Removed that so I could take a reference | 
|---|
|  | 39 | // and use it to send messages | 
|---|
|  | 40 | bool processMessage(const NETWORK_MSG &clientMsg, struct sockaddr_in &from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedId, NETWORK_MSG &serverMsg, int sock); | 
|---|
| [01d0d00] | 41 |  | 
|---|
| [1106210] | 42 | void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers); | 
|---|
| [8e540f4] | 43 |  | 
|---|
| [73f75c1] | 44 | // this should probably go somewhere in the common folder | 
|---|
| [e3535b3] | 45 | void error(const char *msg) | 
|---|
|  | 46 | { | 
|---|
|  | 47 | perror(msg); | 
|---|
|  | 48 | exit(0); | 
|---|
|  | 49 | } | 
|---|
|  | 50 |  | 
|---|
| [01d0d00] | 51 | Player *findPlayerByName(map<unsigned int, Player> &m, string name) | 
|---|
| [2488852] | 52 | { | 
|---|
| [01d0d00] | 53 | map<unsigned int, Player>::iterator it; | 
|---|
| [2488852] | 54 |  | 
|---|
| [01d0d00] | 55 | for (it = m.begin(); it != m.end(); it++) | 
|---|
| [2488852] | 56 | { | 
|---|
| [01d0d00] | 57 | if ( it->second.name.compare(name) == 0 ) | 
|---|
|  | 58 | return &(it->second); | 
|---|
| [2488852] | 59 | } | 
|---|
|  | 60 |  | 
|---|
|  | 61 | return NULL; | 
|---|
|  | 62 | } | 
|---|
|  | 63 |  | 
|---|
| [01d0d00] | 64 | Player *findPlayerByAddr(map<unsigned int, Player> &m, const sockaddr_in &addr) | 
|---|
| [73f75c1] | 65 | { | 
|---|
| [01d0d00] | 66 | map<unsigned int, Player>::iterator it; | 
|---|
| [73f75c1] | 67 |  | 
|---|
| [01d0d00] | 68 | for (it = m.begin(); it != m.end(); it++) | 
|---|
| [73f75c1] | 69 | { | 
|---|
| [01d0d00] | 70 | if ( it->second.addr.sin_addr.s_addr == addr.sin_addr.s_addr && | 
|---|
|  | 71 | it->second.addr.sin_port == addr.sin_port ) | 
|---|
|  | 72 | return &(it->second); | 
|---|
| [73f75c1] | 73 | } | 
|---|
|  | 74 |  | 
|---|
|  | 75 | return NULL; | 
|---|
|  | 76 | } | 
|---|
|  | 77 |  | 
|---|
| [e3535b3] | 78 | int main(int argc, char *argv[]) | 
|---|
|  | 79 | { | 
|---|
|  | 80 | int sock, length, n; | 
|---|
|  | 81 | struct sockaddr_in server; | 
|---|
| [3b1efcc] | 82 | struct sockaddr_in from; // info of client sending the message | 
|---|
| [e084950] | 83 | NETWORK_MSG clientMsg, serverMsg; | 
|---|
| [01d0d00] | 84 | map<unsigned int, Player> mapPlayers; | 
|---|
| [1106210] | 85 | unsigned int unusedId = 1; | 
|---|
| [e084950] | 86 |  | 
|---|
| [edfd1d0] | 87 | //SSL_load_error_strings(); | 
|---|
|  | 88 | //ERR_load_BIO_strings(); | 
|---|
|  | 89 | //OpenSSL_add_all_algorithms(); | 
|---|
| [e3535b3] | 90 |  | 
|---|
|  | 91 | if (argc < 2) { | 
|---|
| [73f75c1] | 92 | cerr << "ERROR, no port provided" << endl; | 
|---|
|  | 93 | exit(1); | 
|---|
| [e3535b3] | 94 | } | 
|---|
| [60017fc] | 95 |  | 
|---|
| [7b43385] | 96 | WorldMap* gameMap = WorldMap::loadMapFromFile("../data/map.txt"); | 
|---|
| [6e66ffd] | 97 |  | 
|---|
|  | 98 | // add some items to the map. They will be sent out | 
|---|
|  | 99 | // to players when they login | 
|---|
| [5f868c0] | 100 | for (int y=0; y<gameMap->height; y++) { | 
|---|
|  | 101 | for (int x=0; x<gameMap->width; x++) { | 
|---|
|  | 102 | switch (gameMap->getStructure(x, y)) { | 
|---|
|  | 103 | case WorldMap::STRUCTURE_BLUE_FLAG: | 
|---|
|  | 104 | gameMap->addObject(WorldMap::OBJECT_BLUE_FLAG, x*25+12, y*25+12); | 
|---|
|  | 105 | break; | 
|---|
|  | 106 | case WorldMap::STRUCTURE_RED_FLAG: | 
|---|
|  | 107 | gameMap->addObject(WorldMap::OBJECT_RED_FLAG, x*25+12, y*25+12); | 
|---|
|  | 108 | break; | 
|---|
|  | 109 | } | 
|---|
|  | 110 | } | 
|---|
|  | 111 | } | 
|---|
| [6e66ffd] | 112 |  | 
|---|
| [371ce29] | 113 | sock = socket(AF_INET, SOCK_DGRAM, 0); | 
|---|
| [e3535b3] | 114 | if (sock < 0) error("Opening socket"); | 
|---|
|  | 115 | length = sizeof(server); | 
|---|
|  | 116 | bzero(&server,length); | 
|---|
|  | 117 | server.sin_family=AF_INET; | 
|---|
|  | 118 | server.sin_port=htons(atoi(argv[1])); | 
|---|
| [2488852] | 119 | server.sin_addr.s_addr=INADDR_ANY; | 
|---|
|  | 120 | if ( bind(sock, (struct sockaddr *)&server, length) < 0 ) | 
|---|
| [e084950] | 121 | error("binding"); | 
|---|
| [73f75c1] | 122 |  | 
|---|
| [371ce29] | 123 | set_nonblock(sock); | 
|---|
|  | 124 |  | 
|---|
| [da692b9] | 125 | bool broadcastResponse; | 
|---|
| [d211210] | 126 | timespec ts; | 
|---|
| [430c80e] | 127 | int timeLastUpdated = 0, curTime = 0, timeLastBroadcast = 0; | 
|---|
| [cb1f288] | 128 | while (true) { | 
|---|
| [371ce29] | 129 |  | 
|---|
|  | 130 | usleep(5000); | 
|---|
|  | 131 |  | 
|---|
| [d211210] | 132 | clock_gettime(CLOCK_REALTIME, &ts); | 
|---|
| [430c80e] | 133 | // make the number smaller so millis can fit in an int | 
|---|
| [d69eb32] | 134 | ts.tv_sec -= 1368000000; | 
|---|
| [430c80e] | 135 | curTime = ts.tv_sec*1000 + ts.tv_nsec/1000000; | 
|---|
| [d211210] | 136 |  | 
|---|
| [430c80e] | 137 | if (timeLastUpdated == 0 || (curTime-timeLastUpdated) >= 50) { | 
|---|
| [d211210] | 138 | timeLastUpdated = curTime; | 
|---|
|  | 139 |  | 
|---|
|  | 140 | // maybe put this in a separate method | 
|---|
| [23559e7] | 141 | map<unsigned int, Player>::iterator it; | 
|---|
|  | 142 | FLOAT_POSITION oldPos; | 
|---|
|  | 143 | bool broadcastMove = false; | 
|---|
| [d211210] | 144 | for (it = mapPlayers.begin(); it != mapPlayers.end(); it++) { | 
|---|
| [23559e7] | 145 | oldPos = it->second.pos; | 
|---|
|  | 146 | if (it->second.move(gameMap)) { | 
|---|
|  | 147 |  | 
|---|
|  | 148 | // check if the move needs to be canceled | 
|---|
|  | 149 | switch(gameMap->getElement(it->second.pos.x/25, it->second.pos.y/25)) { | 
|---|
|  | 150 | case WorldMap::TERRAIN_NONE: | 
|---|
|  | 151 | case WorldMap::TERRAIN_OCEAN: | 
|---|
|  | 152 | case WorldMap::TERRAIN_ROCK: | 
|---|
| [e4c60ba] | 153 | { | 
|---|
| [23559e7] | 154 | it->second.pos = oldPos; | 
|---|
|  | 155 | it->second.target.x = it->second.pos.x; | 
|---|
|  | 156 | it->second.target.y = it->second.pos.y; | 
|---|
|  | 157 | broadcastMove = true; | 
|---|
|  | 158 | break; | 
|---|
| [e4c60ba] | 159 | } | 
|---|
| [23559e7] | 160 | default: | 
|---|
|  | 161 | // if there are no obstacles, do nothing | 
|---|
|  | 162 | break; | 
|---|
|  | 163 | } | 
|---|
|  | 164 |  | 
|---|
| [e4c60ba] | 165 | WorldMap::ObjectType flagType; | 
|---|
|  | 166 | POSITION pos; | 
|---|
| [7553db9] | 167 | bool flagTurnedIn = false; | 
|---|
|  | 168 |  | 
|---|
| [e4c60ba] | 169 | switch(gameMap->getStructure(it->second.pos.x/25, it->second.pos.y/25)) { | 
|---|
|  | 170 | case WorldMap::STRUCTURE_BLUE_FLAG: | 
|---|
|  | 171 | { | 
|---|
| [7553db9] | 172 | if (it->second.team == 0 && it->second.hasRedFlag) | 
|---|
|  | 173 | { | 
|---|
| [e4c60ba] | 174 | it->second.hasRedFlag = false; | 
|---|
|  | 175 | flagType = WorldMap::OBJECT_RED_FLAG; | 
|---|
|  | 176 | pos = gameMap->getStructureLocation(WorldMap::STRUCTURE_RED_FLAG); | 
|---|
| [7553db9] | 177 | flagTurnedIn = true; | 
|---|
| [e4c60ba] | 178 | } | 
|---|
| [7553db9] | 179 |  | 
|---|
|  | 180 | break; | 
|---|
| [e4c60ba] | 181 | } | 
|---|
|  | 182 | case WorldMap::STRUCTURE_RED_FLAG: | 
|---|
|  | 183 | { | 
|---|
| [7553db9] | 184 | if (it->second.team == 1 && it->second.hasBlueFlag) | 
|---|
|  | 185 | { | 
|---|
| [e4c60ba] | 186 | it->second.hasBlueFlag = false; | 
|---|
|  | 187 | flagType = WorldMap::OBJECT_BLUE_FLAG; | 
|---|
|  | 188 | pos = gameMap->getStructureLocation(WorldMap::STRUCTURE_BLUE_FLAG); | 
|---|
| [7553db9] | 189 | flagTurnedIn = true; | 
|---|
| [e4c60ba] | 190 | } | 
|---|
|  | 191 |  | 
|---|
| [7553db9] | 192 | break; | 
|---|
|  | 193 | } | 
|---|
|  | 194 | } | 
|---|
| [e4c60ba] | 195 |  | 
|---|
| [7553db9] | 196 | if (flagTurnedIn) { | 
|---|
|  | 197 | // send an OBJECT message to add the flag back to its spawn point | 
|---|
|  | 198 | pos.x = pos.x*25+12; | 
|---|
|  | 199 | pos.y = pos.y*25+12; | 
|---|
|  | 200 | gameMap->addObject(flagType, pos.x, pos.y); | 
|---|
| [e4c60ba] | 201 |  | 
|---|
| [7553db9] | 202 | serverMsg.type = MSG_TYPE_OBJECT; | 
|---|
|  | 203 | gameMap->getObjects()->back().serialize(serverMsg.buffer); | 
|---|
| [e4c60ba] | 204 |  | 
|---|
| [7553db9] | 205 | map<unsigned int, Player>::iterator it2; | 
|---|
|  | 206 | for (it2 = mapPlayers.begin(); it2 != mapPlayers.end(); it2++) | 
|---|
|  | 207 | { | 
|---|
|  | 208 | if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 ) | 
|---|
|  | 209 | error("sendMessage"); | 
|---|
| [e4c60ba] | 210 | } | 
|---|
| [7553db9] | 211 |  | 
|---|
|  | 212 | // this means a PLAYER message will be sent | 
|---|
|  | 213 | broadcastMove = true; | 
|---|
| [e4c60ba] | 214 | } | 
|---|
|  | 215 |  | 
|---|
| [e487381] | 216 | vector<WorldMap::Object>* vctObjects = gameMap->getObjects(); | 
|---|
| [b07eeac] | 217 | vector<WorldMap::Object>::iterator itObjects; | 
|---|
|  | 218 |  | 
|---|
| [e487381] | 219 | for (itObjects = vctObjects->begin(); itObjects != vctObjects->end();) { | 
|---|
| [b07eeac] | 220 | POSITION pos = itObjects->pos; | 
|---|
| [7553db9] | 221 | bool gotFlag = false; | 
|---|
|  | 222 |  | 
|---|
| [b07eeac] | 223 | if (posDistance(it->second.pos, pos.toFloat()) < 10) { | 
|---|
|  | 224 | switch (itObjects->type) { | 
|---|
|  | 225 | case WorldMap::OBJECT_BLUE_FLAG: | 
|---|
| [7553db9] | 226 | if (it->second.team == 1) { | 
|---|
|  | 227 | gotFlag = true; | 
|---|
|  | 228 | it->second.hasBlueFlag = true; | 
|---|
|  | 229 | broadcastMove = true; | 
|---|
|  | 230 | } | 
|---|
| [b07eeac] | 231 | break; | 
|---|
|  | 232 | case WorldMap::OBJECT_RED_FLAG: | 
|---|
| [7553db9] | 233 | if (it->second.team == 0) { | 
|---|
|  | 234 | gotFlag = true; | 
|---|
|  | 235 | it->second.hasRedFlag = true; | 
|---|
|  | 236 | broadcastMove = true; | 
|---|
|  | 237 | } | 
|---|
| [b07eeac] | 238 | break; | 
|---|
|  | 239 | } | 
|---|
|  | 240 |  | 
|---|
| [7553db9] | 241 | if (gotFlag) { | 
|---|
|  | 242 | serverMsg.type = MSG_TYPE_REMOVE_OBJECT; | 
|---|
|  | 243 | memcpy(serverMsg.buffer, &itObjects->id, 4); | 
|---|
|  | 244 |  | 
|---|
|  | 245 | map<unsigned int, Player>::iterator it2; | 
|---|
|  | 246 | for (it2 = mapPlayers.begin(); it2 != mapPlayers.end(); it2++) | 
|---|
|  | 247 | { | 
|---|
|  | 248 | if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 ) | 
|---|
|  | 249 | error("sendMessage"); | 
|---|
|  | 250 | } | 
|---|
|  | 251 |  | 
|---|
|  | 252 | // remove the object from the server-side map | 
|---|
|  | 253 | cout << "size before: " << gameMap->getObjects()->size() << endl; | 
|---|
|  | 254 | itObjects = vctObjects->erase(itObjects); | 
|---|
|  | 255 | cout << "size after: " << gameMap->getObjects()->size() << endl; | 
|---|
| [b07eeac] | 256 | } | 
|---|
|  | 257 | } | 
|---|
| [7553db9] | 258 |  | 
|---|
|  | 259 | itObjects++; | 
|---|
| [23559e7] | 260 | } | 
|---|
|  | 261 |  | 
|---|
|  | 262 | if (broadcastMove) { | 
|---|
|  | 263 | serverMsg.type = MSG_TYPE_PLAYER; | 
|---|
|  | 264 | it->second.serialize(serverMsg.buffer); | 
|---|
|  | 265 |  | 
|---|
|  | 266 | cout << "about to broadcast move" << endl; | 
|---|
| [b07eeac] | 267 | map<unsigned int, Player>::iterator it2; | 
|---|
| [23559e7] | 268 | for (it2 = mapPlayers.begin(); it2 != mapPlayers.end(); it2++) | 
|---|
|  | 269 | { | 
|---|
|  | 270 | if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 ) | 
|---|
|  | 271 | error("sendMessage"); | 
|---|
|  | 272 | } | 
|---|
| [d211210] | 273 | } | 
|---|
|  | 274 | } | 
|---|
|  | 275 | } | 
|---|
|  | 276 | } | 
|---|
|  | 277 |  | 
|---|
| [e084950] | 278 | n = receiveMessage(&clientMsg, sock, &from); | 
|---|
| [8e540f4] | 279 |  | 
|---|
| [371ce29] | 280 | if (n >= 0) { | 
|---|
| [d211210] | 281 | broadcastResponse = processMessage(clientMsg, from, mapPlayers, gameMap, unusedId, serverMsg, sock); | 
|---|
| [371ce29] | 282 |  | 
|---|
| [b128109] | 283 | // probably replace this with a function that prints based on the | 
|---|
|  | 284 | // message type | 
|---|
| [371ce29] | 285 | cout << "msg: " << serverMsg.buffer << endl; | 
|---|
| [da692b9] | 286 | if (broadcastResponse) | 
|---|
| [3b1efcc] | 287 | { | 
|---|
| [da692b9] | 288 | cout << "Should be broadcasting the message" << endl; | 
|---|
|  | 289 |  | 
|---|
| [01d0d00] | 290 | map<unsigned int, Player>::iterator it; | 
|---|
|  | 291 | for (it = mapPlayers.begin(); it != mapPlayers.end(); it++) | 
|---|
| [3b1efcc] | 292 | { | 
|---|
| [d211210] | 293 | cout << "Sent message back to " << it->second.name << endl; | 
|---|
| [01d0d00] | 294 | if ( sendMessage(&serverMsg, sock, &(it->second.addr)) < 0 ) | 
|---|
| [3b1efcc] | 295 | error("sendMessage"); | 
|---|
|  | 296 | } | 
|---|
|  | 297 | } | 
|---|
|  | 298 | else | 
|---|
|  | 299 | { | 
|---|
| [da692b9] | 300 | cout << "Should be sending back the message" << endl; | 
|---|
|  | 301 |  | 
|---|
| [3b1efcc] | 302 | if ( sendMessage(&serverMsg, sock, &from) < 0 ) | 
|---|
|  | 303 | error("sendMessage"); | 
|---|
|  | 304 | } | 
|---|
| [7b43385] | 305 | } | 
|---|
| [8e540f4] | 306 | } | 
|---|
| [371ce29] | 307 |  | 
|---|
| [8e540f4] | 308 | return 0; | 
|---|
|  | 309 | } | 
|---|
|  | 310 |  | 
|---|
| [d211210] | 311 | bool processMessage(const NETWORK_MSG& clientMsg, struct sockaddr_in& from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedId, NETWORK_MSG& serverMsg, int sock) | 
|---|
| [8e540f4] | 312 | { | 
|---|
| [41ad8ed] | 313 | DataAccess da; | 
|---|
|  | 314 |  | 
|---|
| [b8cb03f] | 315 | cout << "Received message" << endl; | 
|---|
| [8e540f4] | 316 | cout << "MSG: type: " << clientMsg.type << endl; | 
|---|
|  | 317 | cout << "MSG contents: " << clientMsg.buffer << endl; | 
|---|
|  | 318 |  | 
|---|
| [da692b9] | 319 | // maybe we should make a message class and have this be a member | 
|---|
| [3b1efcc] | 320 | bool broadcastResponse = false; | 
|---|
|  | 321 |  | 
|---|
| [8e540f4] | 322 | // Check that if an invalid message is sent, the client will correctly | 
|---|
|  | 323 | // receive and display the response. Maybe make a special error msg type | 
|---|
|  | 324 | switch(clientMsg.type) | 
|---|
|  | 325 | { | 
|---|
|  | 326 | case MSG_TYPE_REGISTER: | 
|---|
| [d2b411a] | 327 | { | 
|---|
| [8e540f4] | 328 | string username(clientMsg.buffer); | 
|---|
|  | 329 | string password(strchr(clientMsg.buffer, '\0')+1); | 
|---|
| [d2b411a] | 330 |  | 
|---|
| [8e540f4] | 331 | cout << "username: " << username << endl; | 
|---|
|  | 332 | cout << "password: " << password << endl; | 
|---|
| [d2b411a] | 333 |  | 
|---|
| [3b1efcc] | 334 | int error = da.insertPlayer(username, password); | 
|---|
| [41ad8ed] | 335 |  | 
|---|
| [3b1efcc] | 336 | if (!error) | 
|---|
|  | 337 | strcpy(serverMsg.buffer, "Registration successful."); | 
|---|
|  | 338 | else | 
|---|
|  | 339 | strcpy(serverMsg.buffer, "Registration failed. Please try again."); | 
|---|
| [8e540f4] | 340 |  | 
|---|
|  | 341 | serverMsg.type = MSG_TYPE_REGISTER; | 
|---|
| [d2b411a] | 342 |  | 
|---|
| [8e540f4] | 343 | break; | 
|---|
|  | 344 | } | 
|---|
|  | 345 | case MSG_TYPE_LOGIN: | 
|---|
|  | 346 | { | 
|---|
| [60017fc] | 347 | cout << "Got login message" << endl; | 
|---|
|  | 348 |  | 
|---|
| [d211210] | 349 | serverMsg.type = MSG_TYPE_LOGIN; | 
|---|
|  | 350 |  | 
|---|
| [8e540f4] | 351 | string username(clientMsg.buffer); | 
|---|
| [41ad8ed] | 352 | string password(strchr(clientMsg.buffer, '\0')+1); | 
|---|
| [8e540f4] | 353 |  | 
|---|
| [41ad8ed] | 354 | Player* p = da.getPlayer(username); | 
|---|
| [d2b411a] | 355 |  | 
|---|
| [b128109] | 356 | if (p == NULL || !da.verifyPassword(password, p->password)) | 
|---|
| [41ad8ed] | 357 | { | 
|---|
|  | 358 | strcpy(serverMsg.buffer, "Incorrect username or password"); | 
|---|
|  | 359 | } | 
|---|
| [01d0d00] | 360 | else if(findPlayerByName(mapPlayers, username) != NULL) | 
|---|
| [41ad8ed] | 361 | { | 
|---|
|  | 362 | strcpy(serverMsg.buffer, "Player has already logged in."); | 
|---|
|  | 363 | } | 
|---|
|  | 364 | else | 
|---|
| [8e540f4] | 365 | { | 
|---|
| [d211210] | 366 | serverMsg.type = MSG_TYPE_PLAYER; | 
|---|
|  | 367 |  | 
|---|
| [1106210] | 368 | updateUnusedId(unusedId, mapPlayers); | 
|---|
| [01d0d00] | 369 | p->id = unusedId; | 
|---|
| [d211210] | 370 | cout << "new player id: " << p->id << endl; | 
|---|
| [df79cfd] | 371 | p->setAddr(from); | 
|---|
|  | 372 |  | 
|---|
|  | 373 | // choose a random team (either 0 or 1) | 
|---|
|  | 374 | p->team = rand() % 2; | 
|---|
| [d211210] | 375 |  | 
|---|
|  | 376 | // tell the new player about all the existing players | 
|---|
|  | 377 | cout << "Sending other players to new player" << endl; | 
|---|
|  | 378 |  | 
|---|
|  | 379 | map<unsigned int, Player>::iterator it; | 
|---|
|  | 380 | for (it = mapPlayers.begin(); it != mapPlayers.end(); it++) | 
|---|
|  | 381 | { | 
|---|
|  | 382 | it->second.serialize(serverMsg.buffer); | 
|---|
|  | 383 |  | 
|---|
|  | 384 | cout << "sending info about " << it->second.name  << endl; | 
|---|
| [5f868c0] | 385 | cout << "sending id " << it->second.id  << endl; | 
|---|
|  | 386 | if ( sendMessage(&serverMsg, sock, &from) < 0 ) | 
|---|
|  | 387 | error("sendMessage"); | 
|---|
|  | 388 | } | 
|---|
|  | 389 |  | 
|---|
|  | 390 | // tell the new player about all map objects | 
|---|
|  | 391 | // (currently just the flags) | 
|---|
|  | 392 | serverMsg.type = MSG_TYPE_OBJECT; | 
|---|
| [e487381] | 393 | vector<WorldMap::Object>* vctObjects = gameMap->getObjects(); | 
|---|
| [5f868c0] | 394 | vector<WorldMap::Object>::iterator itObjects; | 
|---|
|  | 395 | cout << "sending items" << endl; | 
|---|
| [e487381] | 396 | for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) { | 
|---|
| [5f868c0] | 397 | itObjects->serialize(serverMsg.buffer); | 
|---|
|  | 398 | cout << "sending item id " << itObjects->id  << endl; | 
|---|
| [d211210] | 399 | if ( sendMessage(&serverMsg, sock, &from) < 0 ) | 
|---|
|  | 400 | error("sendMessage"); | 
|---|
|  | 401 | } | 
|---|
| [59061f6] | 402 |  | 
|---|
| [594d2e9] | 403 | p->serialize(serverMsg.buffer); | 
|---|
| [d211210] | 404 | cout << "Should be broadcasting the message" << endl; | 
|---|
|  | 405 |  | 
|---|
|  | 406 | for (it = mapPlayers.begin(); it != mapPlayers.end(); it++) | 
|---|
|  | 407 | { | 
|---|
|  | 408 | cout << "Sent message back to " << it->second.name << endl; | 
|---|
|  | 409 | if ( sendMessage(&serverMsg, sock, &(it->second.addr)) < 0 ) | 
|---|
|  | 410 | error("sendMessage"); | 
|---|
|  | 411 | } | 
|---|
|  | 412 |  | 
|---|
|  | 413 | serverMsg.type = MSG_TYPE_LOGIN; | 
|---|
|  | 414 | mapPlayers[unusedId] = *p; | 
|---|
| [07028b9] | 415 | } | 
|---|
|  | 416 |  | 
|---|
| [41ad8ed] | 417 | delete(p); | 
|---|
| [07028b9] | 418 |  | 
|---|
| [8e540f4] | 419 | break; | 
|---|
|  | 420 | } | 
|---|
|  | 421 | case MSG_TYPE_LOGOUT: | 
|---|
|  | 422 | { | 
|---|
|  | 423 | string name(clientMsg.buffer); | 
|---|
|  | 424 | cout << "Player logging out: " << name << endl; | 
|---|
|  | 425 |  | 
|---|
| [01d0d00] | 426 | Player *p = findPlayerByName(mapPlayers, name); | 
|---|
| [633f42a] | 427 |  | 
|---|
| [8e540f4] | 428 | if (p == NULL) | 
|---|
|  | 429 | { | 
|---|
|  | 430 | strcpy(serverMsg.buffer, "That player is not logged in. This is either a bug, or you're trying to hack the server."); | 
|---|
| [8a3ef42] | 431 | cout << "Player not logged in" << endl; | 
|---|
| [07028b9] | 432 | } | 
|---|
| [01d0d00] | 433 | else if ( p->addr.sin_addr.s_addr != from.sin_addr.s_addr || | 
|---|
|  | 434 | p->addr.sin_port != from.sin_port ) | 
|---|
| [07028b9] | 435 | { | 
|---|
| [8e540f4] | 436 | strcpy(serverMsg.buffer, "That player is logged in using a differemt connection. This is either a bug, or you're trying to hack the server."); | 
|---|
| [8a3ef42] | 437 | cout << "Player logged in using a different connection" << endl; | 
|---|
| [2488852] | 438 | } | 
|---|
| [8e540f4] | 439 | else | 
|---|
| [2488852] | 440 | { | 
|---|
| [01d0d00] | 441 | if (p->id < unusedId) | 
|---|
|  | 442 | unusedId = p->id; | 
|---|
|  | 443 | mapPlayers.erase(p->id); | 
|---|
| [41ad8ed] | 444 | strcpy(serverMsg.buffer, "You have successfully logged out."); | 
|---|
| [8e540f4] | 445 | } | 
|---|
| [07028b9] | 446 |  | 
|---|
| [d211210] | 447 | serverMsg.type = MSG_TYPE_LOGOUT; | 
|---|
| [8a3ef42] | 448 |  | 
|---|
| [8e540f4] | 449 | break; | 
|---|
|  | 450 | } | 
|---|
|  | 451 | case MSG_TYPE_CHAT: | 
|---|
|  | 452 | { | 
|---|
| [da692b9] | 453 | cout << "Got a chat message" << endl; | 
|---|
|  | 454 |  | 
|---|
| [01d0d00] | 455 | Player *p = findPlayerByAddr(mapPlayers, from); | 
|---|
| [07028b9] | 456 |  | 
|---|
| [8e540f4] | 457 | if (p == NULL) | 
|---|
|  | 458 | { | 
|---|
|  | 459 | strcpy(serverMsg.buffer, "No player is logged in using this connection. This is either a bug, or you're trying to hack the server."); | 
|---|
| [2488852] | 460 | } | 
|---|
| [8e540f4] | 461 | else | 
|---|
|  | 462 | { | 
|---|
| [3b1efcc] | 463 | broadcastResponse = true; | 
|---|
|  | 464 |  | 
|---|
| [b128109] | 465 | ostringstream oss; | 
|---|
|  | 466 | oss << p->name << ": " << clientMsg.buffer; | 
|---|
| [3b1efcc] | 467 |  | 
|---|
| [b128109] | 468 | strcpy(serverMsg.buffer, oss.str().c_str()); | 
|---|
| [8e540f4] | 469 | } | 
|---|
|  | 470 |  | 
|---|
|  | 471 | serverMsg.type = MSG_TYPE_CHAT; | 
|---|
|  | 472 |  | 
|---|
|  | 473 | break; | 
|---|
| [e084950] | 474 | } | 
|---|
| [b128109] | 475 | case MSG_TYPE_PLAYER_MOVE: | 
|---|
|  | 476 | { | 
|---|
|  | 477 | cout << "PLAYER_MOVE" << endl; | 
|---|
|  | 478 |  | 
|---|
|  | 479 | int id, x, y; | 
|---|
|  | 480 |  | 
|---|
|  | 481 | memcpy(&id, clientMsg.buffer, 4); | 
|---|
|  | 482 | memcpy(&x, clientMsg.buffer+4, 4); | 
|---|
|  | 483 | memcpy(&y, clientMsg.buffer+8, 4); | 
|---|
| [7b43385] | 484 |  | 
|---|
| [b128109] | 485 | cout << "x: " << x << endl; | 
|---|
|  | 486 | cout << "y: " << y << endl; | 
|---|
|  | 487 | cout << "id: " << id << endl; | 
|---|
| [7b43385] | 488 |  | 
|---|
| [b128109] | 489 | if ( mapPlayers[id].addr.sin_addr.s_addr == from.sin_addr.s_addr && | 
|---|
|  | 490 | mapPlayers[id].addr.sin_port == from.sin_port ) | 
|---|
|  | 491 | { | 
|---|
| [60017fc] | 492 | // we need to make sure the player can move here | 
|---|
|  | 493 | if (0 <= x && x < 300 && 0 <= y && y < 300 && | 
|---|
|  | 494 | gameMap->getElement(x/25, y/25) == WorldMap::TERRAIN_GRASS) | 
|---|
|  | 495 | { | 
|---|
| [7b43385] | 496 | cout << "valid terrain" << endl; | 
|---|
|  | 497 |  | 
|---|
| [60017fc] | 498 | mapPlayers[id].target.x = x; | 
|---|
|  | 499 | mapPlayers[id].target.y = y; | 
|---|
|  | 500 |  | 
|---|
|  | 501 | serverMsg.type = MSG_TYPE_PLAYER_MOVE; | 
|---|
|  | 502 |  | 
|---|
|  | 503 | memcpy(serverMsg.buffer, &id, 4); | 
|---|
| [d211210] | 504 | memcpy(serverMsg.buffer+4, &mapPlayers[id].target.x, 4); | 
|---|
|  | 505 | memcpy(serverMsg.buffer+8, &mapPlayers[id].target.y, 4); | 
|---|
| [60017fc] | 506 |  | 
|---|
|  | 507 | broadcastResponse = true; | 
|---|
|  | 508 | } | 
|---|
|  | 509 | else | 
|---|
|  | 510 | cout << "Bad terrain detected" << endl; | 
|---|
| [b128109] | 511 | } | 
|---|
|  | 512 | else  // nned to send back a message indicating failure | 
|---|
|  | 513 | cout << "Player id (" << id << ") doesn't match sender" << endl; | 
|---|
|  | 514 |  | 
|---|
|  | 515 | break; | 
|---|
|  | 516 | } | 
|---|
| [e487381] | 517 | case MSG_TYPE_DROP_FLAG: | 
|---|
|  | 518 | { | 
|---|
|  | 519 | // may want to check the id matches the sender, just like for PLAYER_NOVE | 
|---|
|  | 520 | cout << "DROP_FLAG" << endl; | 
|---|
|  | 521 |  | 
|---|
|  | 522 | int id; | 
|---|
|  | 523 |  | 
|---|
|  | 524 | memcpy(&id, clientMsg.buffer, 4); | 
|---|
|  | 525 | cout << "id: " << id << endl; | 
|---|
|  | 526 |  | 
|---|
|  | 527 | WorldMap::ObjectType flagType = WorldMap::OBJECT_NONE; | 
|---|
|  | 528 | if (mapPlayers[id].hasBlueFlag) | 
|---|
|  | 529 | flagType = WorldMap::OBJECT_BLUE_FLAG; | 
|---|
|  | 530 | else if (mapPlayers[id].hasRedFlag) | 
|---|
|  | 531 | flagType = WorldMap::OBJECT_RED_FLAG; | 
|---|
|  | 532 |  | 
|---|
|  | 533 | gameMap->addObject(flagType, mapPlayers[id].pos.x, mapPlayers[id].pos.y); | 
|---|
|  | 534 |  | 
|---|
|  | 535 | // need to send the OBJECT message too | 
|---|
|  | 536 | serverMsg.type = MSG_TYPE_OBJECT; | 
|---|
|  | 537 | gameMap->getObjects()->back().serialize(serverMsg.buffer); | 
|---|
|  | 538 |  | 
|---|
|  | 539 | map<unsigned int, Player>::iterator it; | 
|---|
|  | 540 | for (it = mapPlayers.begin(); it != mapPlayers.end(); it++) | 
|---|
|  | 541 | { | 
|---|
|  | 542 | if ( sendMessage(&serverMsg, sock, &(it->second.addr)) < 0 ) | 
|---|
|  | 543 | error("sendMessage"); | 
|---|
|  | 544 | } | 
|---|
|  | 545 |  | 
|---|
|  | 546 | mapPlayers[id].hasBlueFlag = false; | 
|---|
|  | 547 | mapPlayers[id].hasRedFlag = false; | 
|---|
|  | 548 |  | 
|---|
|  | 549 | serverMsg.type = MSG_TYPE_PLAYER; | 
|---|
|  | 550 | mapPlayers[id].serialize(serverMsg.buffer); | 
|---|
|  | 551 |  | 
|---|
|  | 552 | map<unsigned int, Player>::iterator it2; | 
|---|
|  | 553 | broadcastResponse = true; | 
|---|
|  | 554 |  | 
|---|
|  | 555 | break; | 
|---|
|  | 556 | } | 
|---|
| [8e540f4] | 557 | default: | 
|---|
|  | 558 | { | 
|---|
|  | 559 | strcpy(serverMsg.buffer, "Server error occured. Report this please."); | 
|---|
| [e084950] | 560 |  | 
|---|
| [8e540f4] | 561 | serverMsg.type = MSG_TYPE_CHAT; | 
|---|
| [e084950] | 562 |  | 
|---|
| [8e540f4] | 563 | break; | 
|---|
|  | 564 | } | 
|---|
| [e3535b3] | 565 | } | 
|---|
| [da692b9] | 566 |  | 
|---|
|  | 567 | return broadcastResponse; | 
|---|
| [e3535b3] | 568 | } | 
|---|
| [da692b9] | 569 |  | 
|---|
| [1106210] | 570 | void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers) | 
|---|
| [01d0d00] | 571 | { | 
|---|
| [1106210] | 572 | while (mapPlayers.find(id) != mapPlayers.end()) | 
|---|
|  | 573 | id++; | 
|---|
| [01d0d00] | 574 | } | 
|---|