void UnitFactory::addPlanetBuffer( NetBuffer &netbuf, QVector x, QVector y, float vely, const Vector &rotvel, float pos, float gravity, float radius, const char *filename, BLENDFUNC sr, BLENDFUNC ds, const vector< string > &dest, const QVector &orbitcent, Unit *parent, const GFXMaterial &ourmat, const std::vector< GFXLightLocal > &ligh, int faction, string fullname, bool inside_out, ObjSerial netcreate ) { netbuf.addChar( ZoneMgr::AddPlanet ); netbuf.addSerial( netcreate ); netbuf.addQVector( x ); netbuf.addQVector( y ); netbuf.addFloat( vely ); netbuf.addVector( Vector( rotvel ) ); netbuf.addFloat( pos ); netbuf.addFloat( gravity ); netbuf.addFloat( radius ); netbuf.addString( string( filename ) ); netbuf.addChar( sr ); netbuf.addChar( ds ); netbuf.addShort( dest.size() ); for (unsigned int i = 0; i < dest.size(); i++) netbuf.addString( dest[i] ); netbuf.addQVector( QVector( orbitcent ) ); netbuf.addSerial( parent->GetSerial() ); netbuf.addGFXMaterial( ourmat ); netbuf.addShort( ligh.size() ); for (unsigned int j = 0; j < ligh.size(); j++) netbuf.addGFXLightLocal( ligh[j] ); netbuf.addInt32( faction ); netbuf.addString( fullname ); netbuf.addChar( inside_out ); }
/* ************************************************************ **** Create a new character *** ************************************************************ */ bool NetClient::selectShip( unsigned int ship ) { if (lastsave.empty() || lastsave[0] == "") { NetBuffer netbuf; string shipname; netbuf.addShort( (unsigned short) ship ); if ( ship < ship_select_list.size() ) shipname = ship_select_list[ship]; netbuf.addString( shipname ); Packet p; p.send( CMD_CHOOSESHIP, 0, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE, NULL, *clt_tcp_sock, __FILE__, PSEUDO__LINE__( 628 ) ); string err; int ret = loginLoop( err ); if (ret != 1 || lastsave.size() < 2 || lastsave[0] == "") { cout<<"Error in CHOOSEHIP: "<<err <<"choice="<<ship<<"("<<shipname<<"), max="<<ret<<endl; return false; } } return true; }
void NetClient::synchronizeTime( SOCKETALT *udpsock ) { int i = 0; int timeout = 0; int recv; timeval tv = {1, 0}; //Timeout after 1 second, request send again. double ping; //use deltaTime? double pingavg = 0.; double timeavg = 0.; std::map< double, double >times; //sorted container. double initialTime = queryTime(); static int NUM_TIMES = XMLSupport::parse_int( vs_config->getVariable( "network", "servertime_calibration", "10" ) ); static int UDP_TIMEOUT = XMLSupport::parse_int( vs_config->getVariable( "network", "udp_timeout", "1" ) ); static int clt_port_read = XMLSupport::parse_int( vs_config->getVariable( "network", "udp_listen_port", "6778" ) ); if (clt_port_read > 65535 || clt_port_read <= 0) clt_port_read = 0; static int clt_port_read_max = XMLSupport::parse_int( vs_config->getVariable( "network", "udp_listen_port_max", "6778" ) ); if (clt_port_read_max > 65535 || clt_port_read_max <= 0) clt_port_read_max = clt_port_read; unsigned short clt_port = (unsigned short) clt_port_read; unsigned short clt_port_max = (unsigned short) clt_port_read_max; if (clt_port_max < clt_port) clt_port_max = clt_port; static string nettransport = vs_config->getVariable( "network", "transport", "udp" ); //std::string addr; unsigned short port = this->_serverport; //getConfigServerAddress(addr, port); if ( !( udpsock != NULL && udpsock->setRemoteAddress( NetUIBase::lookupHost( this->_serverip.c_str(), port ) ) ) ) { do *this->clt_udp_sock = NetUIUDP::createSocket( this->_serverip.c_str(), port, clt_port, _sock_set ); while ( ( !this->clt_udp_sock->valid() ) && (clt_port++) ); } else { this->clt_udp_sock = udpsock; } COUT<<"created UDP socket ("<<this->_serverip<<","<<port<<", listen on "<<clt_port<<") -> "<<this->clt_udp_sock<<endl; if (nettransport == "udp") { //NETFIXME: Keep trying ports until a connection is established. COUT<<"Default lossy transport configured to UDP."<<endl; this->lossy_socket = clt_udp_sock; } else { COUT<<"Default lossy transport configured to TCP (behind firewall)."<<endl; this->lossy_socket = clt_tcp_sock; clt_port = 0; } this->clt_tcp_sock->set_block(); this->clt_udp_sock->set_block(); //Wait for NUM_TIMES (10) successful tries, or 10 consecutive 1-second timeouts //(we use UDP on the response (SENDANDFORGET) to improve timing accuracy). while (i < NUM_TIMES && timeout < UDP_TIMEOUT) { Packet packet; NetBuffer outData; outData.addShort( clt_port ); packet.send( CMD_SERVERTIME, 0, outData.getData(), outData.getDataLength(), //No data. SENDRELIABLE, NULL, *this->clt_tcp_sock, __FILE__, PSEUDO__LINE__( 343 ) ); recv = this->recvMsg( &packet, &tv ); //If we have no response. if (recv <= 0) { COUT<<"synchronizeTime() Timed out"<<endl; ++timeout; if (timeout >= UDP_TIMEOUT) { if (this->lossy_socket->isTcp() == false) { if (clt_port < clt_port_max && !udpsock) { NetUIUDP::disconnectSaveUDP( *this->clt_udp_sock ); *this->clt_udp_sock = NetUIUDP::createSocket( this->_serverip.c_str(), port, clt_port, _sock_set ); clt_port++; COUT<<"Trying UDP port "<<clt_port<<"."<<endl; } else { //no UDP requests made it, fallback to TCP. this->lossy_socket = this->clt_tcp_sock; clt_port = 0; COUT<<"Setting default lossy transport to TCP (UDP timeout)."<<endl; } timeout = 0; } } } else if (packet.getCommand() == CMD_SERVERTIME) { //NETFIXME: obtain actual ping time //ping = getPingTime( &tv ); ping = exp( vsrandom.uniformInc( -10, 0 ) ); if (ping > 0 && ping < 1.) { ++i; NetBuffer data( packet.getData(), packet.getDataLength() ); double serverTime = data.getDouble(); double currentTime = queryTime(); serverTime += initialTime-currentTime; times.insert( std::multimap< double, double >::value_type( ping, serverTime-ping ) ); timeout = 0; } else { ++timeout; } } } this->clt_tcp_sock->set_nonblock(); this->clt_udp_sock->set_nonblock(); //std::sort(times[0], times[i]); if (i >= NUM_TIMES) { int mid = i/2; double median = 0.; double tot = 0.; int location = 0; std::map< double, double >::const_iterator iter; for (iter = times.begin(); iter != times.end(); ++iter) { if (location == mid) { median = iter->first; if (i%2 == 1) { ++iter; median += iter->first; } break; } ++location; } if (i%2 == 1) median /= 2; for (iter = times.begin(); iter != times.end(); ++iter) { double wdiff = exp( -10*(median-iter->first)*(median-iter->first) ); pingavg += wdiff*iter->first; timeavg += wdiff*iter->second; tot += wdiff; } pingavg /= tot; timeavg /= tot; } else { COUT<<"Error in time synchronization: connection ended or timed out."; } this->deltatime = pingavg; double newTime = timeavg+queryTime()-initialTime; COUT<<"Setting time to: New time: "<<newTime<<endl; setNewTime( newTime ); for (unsigned int cpnum = 0; cpnum < _Universe->numPlayers(); cpnum++) //Seems like a bad idea... shouldn't this rely on SIMULATION_ATOM? _Universe->AccessCockpit( cpnum )->TimeOfLastCollision = -200; cur_time = newTime; }
void NetServer::sendLoginAccept( ClientPtr clt, Cockpit *cp ) { COUT<<"enter "<<__PRETTY_FUNCTION__<<endl; //Verify that client already has a character NetBuffer netbuf; Unit *un = cp->GetParent(); if (!un) { sendLoginError( clt ); return; } //Put the save parts in buffers in order to load them properly netbuf.Reset(); string datestr = _Universe->current_stardate.GetFullTrekDate(); netbuf.addString( datestr ); netbuf.addString( clt->savegame[0] ); netbuf.addString( clt->savegame[1] ); Packet packet2; //Create a cockpit for the player and parse its savegame ObjSerial cltserial = un->GetSerial(); COUT<<">>> SEND LOGIN ACCEPT =( serial #"<<cltserial<<" )= --------------------------------------"<<endl; COUT<<"SAVE="<<clt->savegame[0].length()<<" bytes - XML="<<clt->savegame[1].length()<<" bytes"<<endl; cerr<<"SENDING STARDATE : "<<datestr<<endl; //Add the initial star system filename + hash if crypto++ support too string sysname = cp->savegame->GetStarSystem(); string relsys = sysname+".system"; netbuf.addString( relsys ); //Generate the starsystem before addclient so that it already contains serials StarSystem *sts = zonemgr->addZone( sysname ); #ifdef CRYPTO unsigned char *digest = new unsigned char[FileUtil::Hash.DigestSize()]; string sysxml; if ( !( sysxml = zonemgr->getSystem( relsys ) ).empty() ) FileUtil::HashStringCompute( sysxml, digest ); else if ( !sysname.empty() ) FileUtil::HashFileCompute( relsys, digest, SystemFile ); netbuf.addShort( FileUtil::Hash.DigestSize() ); netbuf.addBuffer( digest, FileUtil::Hash.DigestSize() ); delete[] digest; #else netbuf.addShort( 0 ); #endif int zoneid = _Universe->StarSystemIndex( sts ); netbuf.addShort( zoneid ); //Add system string to packet... //Long, I know, but is there any other way to keep all the proper graphics-related data that the server discards? //netbuf.addString( zonemgr->getSystem(sysname) ); packet2.send( LOGIN_ACCEPT, cltserial, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE, &clt->cltadr, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 241 ) ); //Now that we have a starsystem, we will want to make a mission. if (Mission::getNthPlayerMission( _Universe->whichPlayerStarship( un ), 0 ) == NULL) { if (active_missions.size() == 1) active_missions[0]->DirectorInitgame(); //Make a mission specially for this cockpit. unsigned int oldcp = _Universe->CurrentCockpit(); _Universe->SetActiveCockpit( cp ); _Universe->pushActiveStarSystem( _Universe->AccessCockpit()->activeStarSystem ); LoadMission( "", vs_config->getVariable( "server", "serverscript", "import server;my_obj=server.player()" ), false ); _Universe->popActiveStarSystem(); _Universe->SetActiveCockpit( oldcp ); } }