home *** CD-ROM | disk | FTP | other *** search
Wrap
#include "Client.h" #include "Network.h" //#include "PacketHandler.h" #include "log.h" #include "Server.h" #include "Game.h" #include "Gui.h" Client::Client(){ //ipAddress = NULL; socket = NULL; clientId = -1; // not connected // ping = 0; lastPingMillis = SDL_GetTicks(); momentOfConnectMillis = SDL_GetTicks(); // secondsOnServer = 0; lastClientstateMillis = SDL_GetTicks(); nextSpawnMillis = 0; lastSpawnMillis = 0; // isReady = false; strcpy(ci.name, Game::info.var.player_name); // will be changed upon connect ci.ping = 0; ci.secondsOnServer = 0; ci.team = GAME_TEAM_SPECTATORS; ci.score = 0; ci.kills = 0; ci.deaths = 0; ci.vehicle = Game::info.var.player_vehicle; // THINKABOUTME: oder alles auf 0? ci.weapon1 = Game::info.var.player_weapon1; ci.weapon2 = Game::info.var.player_weapon2; ci.weapon3 = Game::info.var.player_weapon3; ci.weapon4 = Game::info.var.player_weapon4; cs.armor = 0; cs.energy = 0; vectorInit3d(0.0f, 0.0f, 0.0f, cs.pos); vectorInit3d(0.0f, 0.0f, 0.0f, cs.dir); vectorInit3d(0.0f, 0.0f, 0.0f, cs.up); vectorInit3d(0.0f, 0.0f, 0.0f, cs.vel); vehicle = NULL; } Client::~Client(){ if( vehicle != NULL ){ Game::unspawnVehicle(vehicle); } } void Client::setName(char* newName){ strncpy(ci.name, newName, CLIENT_MAX_NAME_LENGTH-1); ci.name[CLIENT_MAX_NAME_LENGTH-1] = '\0'; } bool Client::openPort(){ socket = SDLNet_UDP_Open(Network::info.var.client_port); if(socket == NULL){ error("(in Client::openPort()): SDLNet_UDP_Open() failed: %s.\n\n", SDLNet_GetError()); return false; } if(SDLNet_ResolveHost(&ipAddress, Network::info.var.client_ip, Network::info.var.client_port) == -1){ error("(in Client::openPort()): SDLNet_ResolveHost() failed: %s.\n\n", SDLNet_GetError()); SDLNet_UDP_Close(socket); return false; } // IPaddress* ip = SDLNet_UDP_GetPeerAddress(socket, -1); // ipAddress.host = ip->host; // ipAddress.port = ip->port; // printf("host: %d, port: %d\n", ipAddress.host, ipAddress.port); // ipAddress.host = 0x0100007F; // ipAddress.port = Network::info.var.clientPort; // printf("client addr: %s:%d\n", SDLNet_ResolveIP(&ipAddress), ipAddress.port); return true; } bool Client::closePort(){ SDLNet_UDP_Close(socket); return true; } bool Client::connect(){ connectionRequestPacket_t cr; cr.protocolVersion = NETWORK_PROTOCOL_VERSION; strncpy(cr.name, ci.name, CLIENT_MAX_NAME_LENGTH); for(int i=0;i<Network::info.var.client_maxConnectionAttempts;i++){ // alloc packet to send UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_CONNECTION_REQUEST, Network::server->ipAddress, &cr, sizeof(cr)); if(p == NULL){ error("(in Client::connect()): Couldn't alloc packet.\n\n"); return false; } // send request if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::connect()): Couldn't send packet.\n\n"); return false; } log("Connection request send to %s:%i (Try %i). Waiting for reply...\n", Network::info.var.server_ip, Network::info.var.server_port, i+1); SDL_Delay(1000); // wait for answer UDPpacket* answer = NULL; do{ answer = Network::receivePacket(socket); if( answer != NULL ){ if(answer->data[1] == PACKET_TYPE_CONNECTION_REQUEST_ACCEPTED){ log("Connection accepted by server.\n"); connectionRequestAcceptedPacket_t ca; PacketHandler::unwrapAndFreePacket(answer, &ca, sizeof(ca)); // Game::info.cvar.game_player_name->setValStr(ca.newName); // Game::info.cvar.game_player_name->updateVar(); strcpy(Game::info.var.player_name, ca.newName); // handle si part strcpy(Game::info.var.arena, ca.si.arena); Game::info.var.mode = ca.si.gamemode; strcpy(Network::info.var.server_name, ca.si.name); strcpy(Network::info.var.server_description, ca.si.description); Network::info.var.server_maxClients = ca.si.maxClients; Game::info.var.ghostTime = ca.si.ghostTime; if( ca.si.optionFlags & PACKET_OPTION_FLAG_GAME_USE_ARENA_CYCLE ) Game::info.var.useArenaCycle = true; if( ca.si.optionFlags & PACKET_OPTION_FLAG_GAME_ENABLE_FRIENDLY_FIRE ) Game::info.var.enableFriendlyFire = true; Network::server->si = ca.si; // add self to shadow server this->setName(ca.newName); this->clientId = ca.clientId; Network::server->clients[ca.clientId] = this; // this->team = Network::server->addClientToTeam(this, GAME_TEAM_SPECTATORS); // handle pi part (add other clients) for(int j=0;j<Network::server->si.maxClients;j++){ if(ca.pi.clientIds[j] != -1){ Client* c; if(Network::server->clients[j] == this){ c = this; }else{ c = new Client(); } c->ci = ca.pi.ci[j]; Network::server->clients[j] = c; log("Added client '%s' to shadow server.\n", c->ci.name); // THINKABOUTME: Hier lebende clients spawnen oder auf nΣchsten gamestate warten? // - Hier gibt's noch keine arena, also besser warten... } } log("Connected to '%s' as '%s'.\n", Network::info.var.server_name, ca.newName); return true; }else if(answer->data[1] == PACKET_TYPE_CONNECTION_REQUEST_DECLINED){ //log("Connection request declined by server. Reason:\n"); connectionRequestDeclinedPacket_t cd; PacketHandler::unwrapAndFreePacket(answer, &cd, sizeof(cd)); error("(in Client::connect()): Connection request declined by server. Reason: %s\n\n", cd.reason); return false; }else{ warn("(in Client::connect()): Received unexpected answer from server. Ignoring.\n\n"); PacketHandler::freePacket(answer); } } }while( answer != NULL ); } log("Couldn't connect to %s:%i. Giving up.\n", Network::info.var.server_ip, Network::info.var.server_port); return false; } bool Client::disconnect(){ // send disconnect event disconnectPacket_t d; d.clientId = clientId; if(d.clientId == -1){ error("(in Client::disconnect()): Local clientId is -1.\n\n"); return false; } UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_DISCONNECT, Network::server->ipAddress, &d, sizeof(d)); if(p == NULL){ error("(in Client::disconnect()): Couldn't alloc packet.\n\n"); return false; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::disconnect()): Couldn't send packet.\n\n"); return false; } log("Disconnect packet send.\n"); if( vehicle != NULL ){ Game::unspawnVehicle(vehicle); } Network::server->clients[d.clientId] = NULL; // will be deleted later! (in shutdownClient()) this->clientId = -1; return true; } int Client::getClientId(){ // for(int i=0;i<Network::server->maxClients;i++){ // if(Network::server->clients[i] != NULL && Network::server->clients[i] == this){ // return i; // } // } // // return -1; return clientId; } void Client::sendChatMessage(unsigned char mode, const char* message){ chatMessagePacket_t cm; cm.clientId = this->clientId; strncpy(cm.message, message, CON_MAX_STRING_LENGTH); cm.mode = mode; UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_CHAT_MESSAGE, Network::server->ipAddress, &cm, sizeof(cm)); if(p == NULL){ error("(in Client::sendChatMessage()): Couldn't alloc packet.\n\n"); return; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::sendChatMessage()): Couldn't send packet.\n\n"); return; } } void Client::sendVoiceMessage(unsigned char mode, char messageId){ voiceMessagePacket_t vm; vm.clientId = this->clientId; vm.messageId = messageId; vm.mode = mode; UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_VOICE_MESSAGE, Network::server->ipAddress, &vm, sizeof(vm)); if(p == NULL){ error("(in Client::sendVoiceMessage()): Couldn't alloc packet.\n\n"); return; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::sendVoiceMessage()): Couldn't send packet.\n\n"); return; } } void Client::sendClientstate(){ clientstatePacket_t cs; cs = this->cs; if( vehicle != NULL ){ // alive -> take vehicle vel, dir, up and let server approve values vectorCopy3d(vehicle->pos, cs.pos); vectorCopy3d(vehicle->vel_inp, cs.vel); // send INPUT vel!! vectorCopy3d(vehicle->dir, cs.dir); vectorCopy3d(vehicle->up, cs.up); cs.energy = (unsigned char)vehicle->energy; cs.armor = (unsigned char)vehicle->armor; }else{ // dead -> take cam pos (movement is unrestricted) vectorCopy3d(Game::cam.pos, cs.pos); vectorCopy3d(Game::cam.dir, cs.dir); vectorCopy3d(Game::cam.up, cs.up); vectorCopy3d(Game::cam.vel, cs.vel); cs.energy = 0; cs.armor = 0; } UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_CLIENTSTATE, Network::server->ipAddress, &cs, sizeof(cs)); if(p == NULL){ error("(in Client::sendClientstate()): Couldn't alloc packet.\n\n"); return; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::sendClientstate()): Couldn't send packet.\n\n"); return; } } void Client::sendClientSpawn(){ clientSpawnPacket_t cs; cs.clientId = this->clientId; cs.ci = this->ci; cs.cs = this->cs; // fill in the values we would like to have... cs.ci.team = (char)Game::info.cvar.game_player_team->getVal(); cs.ci.vehicle = (char)Game::info.cvar.game_player_vehicle->getVal(); cs.ci.weapon1 = (char)Game::info.cvar.game_player_weapon1->getVal(); cs.ci.weapon2 = (char)Game::info.cvar.game_player_weapon2->getVal(); cs.ci.weapon3 = (char)Game::info.cvar.game_player_weapon3->getVal(); cs.ci.weapon4 = (char)Game::info.cvar.game_player_weapon4->getVal(); UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_CLIENT_SPAWN, Network::server->ipAddress, &cs, sizeof(cs)); if(p == NULL){ error("(in Client::sendClientSpawn()): Couldn't alloc packet.\n\n"); return; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::sendClientSpawn()): Couldn't send packet.\n\n"); return; } } // send a suicide request void Client::sendClientKill(){ clientKillPacket_t ck; ck.killedClientId = this->clientId; ck.killerClientId = this->clientId; ck.weapon = GAME_WEAPON_NO_WEAPON; UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_CLIENT_KILL, Network::server->ipAddress, &ck, sizeof(ck)); if(p == NULL){ error("(in Client::sendClientKill()): Couldn't alloc packet.\n\n"); return; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::sendClientKill()): Couldn't send packet.\n\n"); return; } } void Client::sendShotSpawn(Shot* shot){ shotSpawnPacket_t ss; ss.clientId = this->clientId; ss.weaponId = shot->weaponId; ss.type = shot->type; vectorCopy3d(shot->pos, ss.pos); vectorCopy3d(shot->dir, ss.dir); vectorCopy3d(shot->up, ss.up); vectorCopy3d(shot->vel, ss.vel); UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_SHOT_SPAWN, Network::server->ipAddress, &ss, sizeof(ss)); if(p == NULL){ error("(in Client::sendShotSpawn()): Couldn't alloc packet.\n\n"); return; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::sendShotSpawn()): Couldn't send packet.\n\n"); return; } } void Client::sendPackets(){ unsigned long currentMillis = SDL_GetTicks(); // clientstate stuff if(!Game::info.var.clientGame){ // update cs on local server if( vehicle != NULL ){ // alive -> take vehicle vel, dir, up and let server approve values vectorCopy3d(vehicle->pos, cs.pos); vectorCopy3d(vehicle->vel_inp, cs.vel); vectorCopy3d(vehicle->dir, cs.dir); vectorCopy3d(vehicle->up, cs.up); cs.armor = (unsigned char)vehicle->armor; cs.energy = (unsigned char)vehicle->energy; }else{ // dead -> take cam pos (movement is unrestricted) vectorCopy3d(Game::cam.pos, cs.pos); vectorCopy3d(Game::cam.dir, cs.dir); vectorCopy3d(Game::cam.up, cs.up); vectorCopy3d(Game::cam.vel, cs.vel); } } // send cs if necessary (i.e. time has come and we're on a remote server) if(Game::info.var.clientGame && currentMillis - lastClientstateMillis > (unsigned long)Network::info.var.client_clientstateInterval){ // log("Sending clientstate...\n"); sendClientstate(); lastClientstateMillis = currentMillis; } // send spawn request if necessary if( nextSpawnMillis < currentMillis ){ if( //Game::info.cvar.game_player_team->getVal() != Game::info.var.player_team // wants to change team Game::info.cvar.game_player_team->getVal() != GAME_TEAM_SPECTATORS && Game::info.var.player_team == GAME_TEAM_SPECTATORS // wants to join game || (Game::info.var.player_team != GAME_TEAM_SPECTATORS && vehicle == NULL) // or regular respawn (playing and dead) ){ sendClientSpawn(); nextSpawnMillis = SDL_GetTicks() + Game::info.var.ghostTime; // schedule next try (if that one fails...) } } } void Client::receivePackets(){ // if we are connected to a remote server check if server is still alive if( Game::info.var.clientGame ){ unsigned long currentMillis = SDL_GetTicks(); if( ((currentMillis - lastPingMillis)/1000) % 5 > (unsigned long)5000 ){ // connection interrupted log("Connection to server interrupted.\n"); } if(currentMillis - lastPingMillis > (unsigned long)Network::info.var.client_maxServerIdleTime){ // disconnect error("(in Client::receivePackets()): Server is not responding. Disconnecting.\n\n"); // this->clientId = -1; Game::shutdown(); Gui::mainMenu->open(); } } // receive packets UDPpacket** packets = SDLNet_AllocPacketV(NETWORK_MAX_PACKETS_PER_FRAME, NETWORK_MAX_PACKET_SIZE); if(packets == NULL){ error("(in Client::receivePackets()): Unable to alloc packets.\n\n"); return; } int numReceived = SDLNet_UDP_RecvV(socket, packets); if(numReceived == -1){ error("(in Client::receivePackets()): SDLNet_UDP_RecvV failed: %s.\n\n", SDLNet_GetError()); return; } for(int i=0;i<numReceived;i++){ if(packets[i]->data[0] != NETWORK_FWP_PACKET_ID){ warn("(in Client::receivePackets()): Received unknown packet.\n\n"); continue; } handlePacket(packets[i]); } SDLNet_FreePacketV(packets); } void Client::handlePacket(UDPpacket* packet){ // printf("client::handlePacket(): received packet of type %i.\n", packet->data[1]); switch(packet->data[1]){ case PACKET_TYPE_PING: // log("Client::handlePacket(): Received ping packet.\n"); handlePing(packet); break; case PACKET_TYPE_DISCONNECT: // log("Client::handlePacket(): Received disconnect packet.\n"); handleDisconnect(packet); break; case PACKET_TYPE_CLIENT_CONNECTED: // log("Client::handlePacket(): Received clientConnected packet.\n"); handleClientConnected(packet); break; case PACKET_TYPE_CLIENT_DISCONNECTED: // log("Client::handlePacket(): Received clientDisconnected packet.\n"); handleClientDisconnected(packet); break; case PACKET_TYPE_CHAT_MESSAGE: // log("Client::handlePacket(): Received chatMessage packet.\n"); handleChatMessage(packet); break; case PACKET_TYPE_VOICE_MESSAGE: // log("Client::handlePacket(): Received voiceMessage packet.\n"); handleVoiceMessage(packet); break; case PACKET_TYPE_PLAYERINFO: // log("Client::handlePacket(): Received playerinfo packet.\n"); handlePlayerinfo(packet); break; case PACKET_TYPE_GAMESTATE: // log("Client::handlePacket(): Received gamestate packet.\n"); handleGamestate(packet); break; case PACKET_TYPE_CLIENT_SPAWN: // log("Client::handlePacket(): Received clientSpawn packet.\n"); handleClientSpawn(packet); break; case PACKET_TYPE_CLIENT_HURT: // log("Client::handlePacket(): Received clientHurt packet.\n"); handleClientHurt(packet); break; case PACKET_TYPE_CLIENT_KILL: // log("Client::handlePacket(): Received clientKill packet.\n"); handleClientKill(packet); break; case PACKET_TYPE_SHOT_SPAWN: // log("Client::handlePacket(): Received shotSpawn packet.\n"); handleShotSpawn(packet); break; case PACKET_TYPE_ARENA_CHANGE: // log("Client::handlePacket(): Received arenaChange packet.\n"); handleArenaChange(packet); break; default: warn("Client::handlePacket(): Received packet of unknown type. Ignoring.\n"); break; } // switch } void Client::emptyPacketQueue(){ int numLoops = 0; int numReceived = 0; // receive packets do{ UDPpacket** packets = SDLNet_AllocPacketV(NETWORK_MAX_PACKETS_PER_FRAME, NETWORK_MAX_PACKET_SIZE); if(packets == NULL){ error("(in Client::receivePackets()): Unable to alloc packets.\n\n"); return; } numReceived = SDLNet_UDP_RecvV(socket, packets); if(numReceived == -1){ error("(in Client::emptyPacketQueue()): SDLNet_UDP_RecvV failed: %s.\n\n", SDLNet_GetError()); return; } SDLNet_FreePacketV(packets); numLoops++; }while(numReceived > 0 && numLoops < 10); } void Client::handlePing(UDPpacket* packet){ pingPacket_t pp; if( !PacketHandler::unwrapPacket(packet, &pp, sizeof(pp)) ){ error("(Client::handlePing()): Couldn't unwrap packet.\n\n"); return; } if(pp.protocolVersion != Network::info.var.protocolVersion){ warn("(in Client::handlePing()): Received ping packet with invalid protocol version. Ignoring\n\n"); return; } this->lastPingMillis = SDL_GetTicks(); // remember time // fill in clientID and send it back to server pp.clientId = this->clientId; UDPpacket* p = PacketHandler::wrapPacket(PACKET_TYPE_PING, Network::server->ipAddress, &pp, sizeof(pp)); if(p == NULL){ error("(in Client::handlePing()): Couldn't alloc packet.\n\n"); return; } if( !Network::sendAndFreePacket(socket, p) ){ error("(in Client::handlePing()): Couldn't send packet.\n\n"); SDLNet_FreePacket(p); return; } } void Client::handleDisconnect(UDPpacket* packet){ //log("Server disconnected.\n"); disconnectPacket_t d; if( !PacketHandler::unwrapPacket(packet, &d, sizeof(d)) ){ error("(Client::handleDisconnect()): Couldn't unwrap packet.\n\n"); return; } error("(in Client::handleDisconnect()): Server disconnected. Reason: %s\n", d.reason); Network::server->clients[this->clientId] = NULL; this->clientId = -1; Game::shutdown(); Gui::mainMenu->open(); } void Client::handleClientConnected(UDPpacket* packet){ clientConnectedPacket_t cc; if( !PacketHandler::unwrapPacket(packet, &cc, sizeof(cc)) ){ error("(Client::handleClientConnected()): Couldn't unwrap packet.\n\n"); return; } if(cc.clientId < 0 || cc.clientId >= Network::server->si.maxClients){ warn("(in Client::handleClientConnected()): ClientId of new client out of bounds. Ignoring.\n\n."); return; } if( Network::server->clients[cc.clientId] != NULL ){ warn("(in Client::handleClientConnected()): ClientId of new client already in use. Overwriting.\n\n."); delete Network::server->clients[cc.clientId]; } Client* c = new Client(); Network::server->clients[cc.clientId] = c; c->ci = cc.ci; log("'%s' connected.\n", c->ci.name); } void Client::handleClientDisconnected(UDPpacket* packet){ clientDisconnectedPacket_t cd; if( !PacketHandler::unwrapPacket(packet, &cd, sizeof(cd)) ){ error("(Client::handleClientDisconnected()): Couldn't unwrap packet.\n\n"); return; } if(cd.clientId < 0 || cd.clientId >= Network::server->si.maxClients){ warn("(in Client::handleClientDisconnected()): ClientId of client out of bounds. Ignoring.\n\n."); return; } Client* c = Network::server->clients[cd.clientId]; if( c == NULL ){ warn("(in Client::handleClientDisconnected()): ClientId of client already free. Ignoring.\n\n."); return; } if( c->vehicle != NULL ){ Game::unspawnVehicle(c->vehicle); } log("'%s' disconnected. Reason: %s.\n", c->ci.name, cd.reason); Network::server->removeClient(c); } void Client::handleChatMessage(UDPpacket* packet){ //log("Server disconnected.\n"); chatMessagePacket_t cm; if( !PacketHandler::unwrapPacket(packet, &cm, sizeof(cm)) ){ error("(in Client::handleChatMessage()): Couldn't unwrap packet.\n\n"); return; } if( cm.mode == GAME_CHAT_MODE_SERVER ){ Gui::hud->messagebox->addChatMessage(NULL, &cm); return; } if(cm.clientId < 0 || cm.clientId >= Network::server->si.maxClients){ warn("(in Client::handleChatMessage()): ClientId out of bounds.\n\n"); return; } Client* c = Network::server->clients[cm.clientId]; if(c != NULL){ Gui::hud->messagebox->addChatMessage(c, &cm); }else{ warn("(in Client::handleChatMessage()): Received chat message from unknown client.\n\n"); } } void Client::handleVoiceMessage(UDPpacket* packet){ //log("Server disconnected.\n"); voiceMessagePacket_t vm; if( !PacketHandler::unwrapPacket(packet, &vm, sizeof(vm)) ){ error("(in Client::handleVoiceMessage()): Couldn't unwrap packet.\n\n"); return; } if(vm.clientId < 0 || vm.clientId >= Network::server->si.maxClients){ warn("(in Client::handleVoiceMessage()): ClientId out of bounds.\n\n"); return; } if( vm.messageId < 0 || vm.messageId >= GAME_NUM_VOICE_MESSAGES ){ warn("(in Client::handleVoiceMessage()): MessageId out of bounds.\n\n"); return; } Client* c = Network::server->clients[vm.clientId]; if(c != NULL){ if( Game::info.var.allowVoiceMessages >= 1 ){ chatMessagePacket_t cm; cm.clientId = vm.clientId; cm.mode = vm.mode; sprintf(cm.message, "[voicemessage '%s']", Game::getVoiceMessageName(vm.messageId)); Gui::hud->messagebox->addChatMessage(c, &cm); } if(Sound::info.var.enabled && Sound::info.var.playSamples && Game::info.var.allowVoiceMessages >= 2 && Game::preloadedGameMedia.voiceMessages[vm.messageId] != NULL ){ Sound::playSample(SOUND_RADIO_CHANNEL, Game::preloadedGameMedia.voiceMessages[vm.messageId]); } }else{ warn("(in Client::handleVoiceMessage()): Received voice message from unknown client.\n\n"); } } void Client::handlePlayerinfo(UDPpacket* packet){ playerinfoPacket_t pi; if( !PacketHandler::unwrapPacket(packet, &pi, sizeof(pi)) ){ error("(in Client::handlePlayerinfo()): Couldn't unwrap packet.\n\n"); return; } for(int j=0;j<Network::server->si.maxClients;j++){ if(pi.clientIds[j] != -1){ Client* c; c = Network::server->clients[j]; if( c == NULL ){ warn("(in Client::handlePlayerinfo()): Slot %i is in playerinfo but not connected. Adding new client...\n\n", j); //log("(Maybe I just missed the connection event. )\n"); //continue; c = new Client(); Network::server->clients[j] = c; } c->clientId = j; // THINKABOUTME: sowie so schon klar... c->ci = pi.ci[j]; }else if(pi.clientIds[j] == -1 && Network::server->clients[j] != NULL){ // missed disconnect? warn("(in Client::handlePlayerinfo()): Slot %i is empty in playerinfo but in shadow server. Removing client...\n\n", j); Network::server->removeClient(Network::server->clients[j]); } } } void Client::handleGamestate(UDPpacket* packet){ // log("Hab gamestate gekriegt!\n"); gamestatePacket_t gs; if( !PacketHandler::unwrapPacket(packet, &gs, sizeof(gs)) ){ error("(in Client::handleGamestate()): Couldn't unwrap packet.\n\n"); return; } for(int j=0;j<Network::server->si.maxClients;j++){ if(gs.clientIds[j] != -1){ Client* c; c = Network::server->clients[j]; if( c == NULL ){ warn("(in Client::handleGamestate()): Slot %i is in gamestate but not connected. Adding new client...\n\n", j); c = new Client(); c->setName("???"); // will be changed with next playerinfo Network::server->clients[j] = c; } c->cs = gs.cs[j]; if( c->ci.team != GAME_TEAM_SPECTATORS && c->cs.armor > 0 && c->vehicle == NULL ){ // missed spawn event? // warn("(in Client::handleGamestate()): Slot %i is alive in gamestate but not on shadow server. Spawning...\n\n", j); Game::spawnVehicle(c); } if( c->ci.team != GAME_TEAM_SPECTATORS && c->cs.armor == 0 && c->vehicle != NULL ){ // missed kill event? // warn("(in Client::handleGamestate()): Slot %i is dead in gamestate but not on shadow server. Unspawning...\n\n", j); Game::unspawnVehicle(c->vehicle); } if( c->vehicle != NULL ){ if( c != this ){ // keep local stuff to smoothen moves vectorCopy3d(c->cs.pos, c->vehicle->pos); vectorCopy3d(c->cs.dir, c->vehicle->dir); vectorCopy3d(c->cs.up, c->vehicle->up); vectorCopy3d(c->cs.vel, c->vehicle->vel_inp); c->vehicle->energy = c->cs.energy; // energy is handled on client } c->vehicle->armor = c->cs.armor; } }else if(gs.clientIds[j] == -1 && Network::server->clients[j] != NULL){ // missed disconnect? warn("(in Client::handleGamestate()): Slot %i is empty in gamestate but in shadow server. Removing client '%s'...\n\n", j, Network::server->clients[j]->ci.name); Network::server->removeClient(Network::server->clients[j]); } } } void Client::handleClientSpawn(UDPpacket* packet){ clientSpawnPacket_t cs; if( !PacketHandler::unwrapPacket(packet, &cs, sizeof(cs)) ){ error("(in Client::handleClientSpawn()): Couldn't unwrap packet.\n\n"); return; } Client* c = Network::server->clients[cs.clientId]; if( c == NULL ){ warn("(in Client::handleClientSpawn()): Slot %i is spawning but not connected. Adding new client...\n\n", cs.clientId); c = new Client(); Network::server->clients[cs.clientId] = c; } if( c->ci.team != cs.ci.team || cs.ci.team == GAME_TEAM_SPECTATORS ){ // log change team log("%s joined %s.\n", cs.ci.name, Game::getTeamName(cs.ci.team) ); } c->ci = cs.ci; c->cs = cs.cs; if( c == this ){ // UPDATE GAME CVARS!!!! Game::info.var.player_team = c->ci.team; Game::info.cvar.game_player_team->setVal(c->ci.team); // THINKABOUTME: to avoid respawns caused by changing teams Game::info.var.player_vehicle = c->ci.vehicle; Game::info.var.player_weapon1 = c->ci.weapon1; Game::info.var.player_weapon2 = c->ci.weapon2; Game::info.var.player_weapon3 = c->ci.weapon3; Game::info.var.player_weapon4 = c->ci.weapon4; } if( c->vehicle != NULL ){ Game::unspawnVehicle(c->vehicle); } Game::spawnVehicle(c); if( c->ci.team != GAME_TEAM_SPECTATORS ){ // log("%s has spawned for %s with a %s.\n", c->ci.name, Game::getTeamName(c->ci.team), Game::getVehicleName(c->ci.vehicle) ); } } void Client::handleClientHurt(UDPpacket* packet){ clientHurtPacket_t ch; if( !PacketHandler::unwrapPacket(packet, &ch, sizeof(ch)) ){ error("(in Client::handleClientHurt()): Couldn't unwrap packet.\n\n"); return; } Client* hurtClient = Network::server->clients[ch.hurtClientId]; Client* hurterClient = Network::server->clients[ch.hurterClientId]; if( hurtClient == NULL ){ warn("(in Client::handleClientHurt()): Received clientHurt packet with invalid hurtClientId. Ignoring.\n\n"); return; } if( hurterClient == NULL ){ // May have disconnected warn("(in Client::handleClientHurt()): Received clientHill packet with invalid hurterClientId.\n\n"); // return; } if( hurtClient->vehicle == NULL ){ warn("(in Client::handleClientHurt()): Received clientHurt packet with hurtClient that is already dead. Ignoring.\n\n"); return; } hurtClient->vehicle->takeDamage(ch.amount); } void Client::handleClientKill(UDPpacket* packet){ clientKillPacket_t ck; if( !PacketHandler::unwrapPacket(packet, &ck, sizeof(ck)) ){ error("(in Client::handleClientKill()): Couldn't unwrap packet.\n\n"); return; } Client* killedClient = Network::server->clients[ck.killedClientId]; Client* killerClient = Network::server->clients[ck.killerClientId]; if( killedClient == NULL ){ warn("(in Client::handleClientKill()): Received client kill packet with invalid killedClientId. Ignoring.\n\n"); return; } if( killerClient == NULL ){ // May have disconnected warn("(in Client::handleClientKill()): Received client kill packet with invalid killerClientId. Ignoring.\n\n"); //return; } if( killedClient->vehicle == NULL ){ warn("(in Client::handleClientKill()): Received client kill packet with killedClient that is already dead. Ignoring.\n\n"); return; } Game::killClient(killedClient, killerClient, ck.weapon); } void Client::handleShotSpawn(UDPpacket* packet){ shotSpawnPacket_t ss; if( !PacketHandler::unwrapPacket(packet, &ss, sizeof(ss)) ){ error("(in Client::handleShotSpawn()): Couldn't unwrap packet.\n\n"); return; } Game::spawnShot(&ss); } void Client::handleArenaChange(UDPpacket* packet){ arenaChangePacket_t ac; if( !PacketHandler::unwrapPacket(packet, &ac, sizeof(ac)) ){ error("(in Client::handleArenaChange()): Couldn't unwrap packet.\n\n"); return; } Game::info.cvar.game_arena->setValStr(ac.newArena); Game::info.cvar.game_arena->updateVar(); Gui::loadingMenu->open(); Gui::loadingMenu->updateStatusBar("changing arena"); Gui::loadingMenu->updateHeading("changing arena"); Gui::loadingMenu->updateSubHeading(Game::getModeName(Game::info.var.mode)); if( !Game::changeArena() ){ error("(in Client::handeArenaChange()): Game::changeArena() failed.\n\n"); Game::shutdown(); Gui::mainMenu->open(); } Network::server->resetClients(); emptyPacketQueue(); Gui::loadingMenu->updateStatusBar("awaiting GS"); // wait for answer unsigned long startWaitingMillis = SDL_GetTicks(); do{ log("Awaiting gamestate...\n"); UDPpacket** packets = SDLNet_AllocPacketV(NETWORK_MAX_PACKETS_PER_FRAME, NETWORK_MAX_PACKET_SIZE); if(packets == NULL){ error("(in Client::handleArenaChange()): Unable to alloc packets.\n\n"); return; } int numReceived = SDLNet_UDP_RecvV(socket, packets); if(numReceived == -1){ error("(in Client::handleArenaChange()): SDLNet_UDP_RecvV failed: %s.\n\n", SDLNet_GetError()); return; } for(int i=0;i<numReceived;i++){ if(packets[i]->data[0] != NETWORK_FWP_PACKET_ID){ warn("(in Client::handleArenaChange()): Received unknown packet.\n\n"); continue; } if(packets[i]->data[1] == PACKET_TYPE_GAMESTATE){ handleGamestate(packets[i]); SDLNet_FreePacketV(packets); // emptyPacketQueue(); Gui::loadingMenu->close(); log("Gamestate received. Re-entering Mainloop...\n"); Game::mainLoop(); return; // never reached??? } } SDLNet_FreePacketV(packets); SDL_Delay(1000); }while( SDL_GetTicks() < startWaitingMillis + Network::info.var.client_maxServerIdleTime ); Gui::loadingMenu->close(); error("(in Client::handleArenaChange()): Server is not responding. Disconnecting.\n\n"); Game::shutdown(); Gui::mainMenu->open(); }