Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
netclient_clients.cpp
Go to the documentation of this file.
1 #include "lin_time.h"
3 #include "networking/client.h"
4 #include "networking/netclient.h"
6 #include "networking/zonemgr.h"
9 #include "cmd/unit_generic.h"
10 #include "universe_util.h"
11 #include "cmd/unit_factory.h"
12 #include "networking/prediction.h"
13 #include "networking/fileutil.h"
16 
17 /*
18  ************************************************************
19  **** Adds an entering client in the actual zone ***
20  ************************************************************
21  */
22 void DoEnterExitAni( QVector pos, float size, bool enter )
23 {
24  static std::string enterclientani = vs_config->getVariable( "graphics", "enter_client_ani", "warp.ani" );
25  static std::string exitclientani = vs_config->getVariable( "graphics", "enter_client_ani", "warp.ani" );
26  std::string tmp = enter ? enterclientani : exitclientani;
27  if ( tmp.length() ) {
28  static float scale = XMLSupport::parse_float( vs_config->getVariable( "graphics", "client_anim_scale", "3" ) );
29  UniverseUtil::playAnimation( tmp, pos, size*scale );
30  }
31 }
32 Unit* NetClient::enterClient( NetBuffer &netbuf, ObjSerial cltserial )
33 {
34  //Should receive the name
35  string cltname = netbuf.getString();
36  string savestr = netbuf.getString();
37  string xmlstr = netbuf.getString();
38  Transformation trans = netbuf.getTransformation();
39  //If not a local player, add it in our array
40  Unit *shouldbenull = UniverseUtil::GetUnitFromSerial( cltserial );
41  //NETFIXME could be slow--but alas
42  if (NULL != shouldbenull) {
43  cout<<" not adding unit with serial number "<<cltserial<<" named "<<shouldbenull->name.get()<<" to system .";
44  return shouldbenull; //already exists
45  }
46  if ( !isLocalSerial( cltserial ) ) {
47  //We will ignore - starsys as if a client enters he is in the same system
48  //- pos since we received a ClientState
49  //- creds as we don't care about other players' credits for now
50  string starsys;
51  QVector pos;
52  float creds;
53  bool update = true;
54  vector< string >savedships;
55  string PLAYER_FACTION_STRING;
56  string *savegamestr = NULL;
57  if ( cltname.length() ) {
58  //Parse the save buffer
59  if (savestr.length() == 0) {
60  if (this->lastsave.size() && this->lastsave[0].length()
61  && this->callsign == cltname)
62  savestr = this->lastsave[0];
63  }
64  SaveGame save( "" );
65  save.ParseSaveGame( "", starsys, "", pos, update, creds, savedships, 0, savestr, false );
66 
67  PLAYER_FACTION_STRING = save.GetPlayerFaction();
68  //CREATES THE UNIT... GET SAVE AND XML FROM SERVER
69  //Use the first ship if there are more than one -> we don't handle multiple ships for now
70  //We name the flightgroup with the player name
71  if ( savedships.empty() ) {
72  cerr<<"savedships is empty!!!"<<endl;
73  cerr<<"SAVEGAME: "<<endl<<savestr<<"-------"<<endl;
74  cerr<<"SHIPCSV: "<<endl<<xmlstr<<"-------"<<endl;
75  return NULL;
76  } else {
77  cerr<<"Found saveship[0] = "<<savedships[0]<<endl;
78  }
79  cerr<<"NEW PLAYER POSITION : x="<<pos.i<<",y="<<pos.j<<"z="<<pos.k<<endl;
80 
81  cerr<<"SAFE PLATER POSITION: x="<<pos.i<<",y="<<pos.j<<"z="<<pos.k<<endl;
82  savegamestr = &xmlstr;
83  } else {
84  std::string::size_type wherepipe = xmlstr.find( "|" );
85  PLAYER_FACTION_STRING = ( (wherepipe != string::npos) ? xmlstr.substr( 0, wherepipe ) : xmlstr );
86  if (savestr == "Pilot" || savestr == "pilot")
87  savestr = "eject";
88  else if (savestr.find( ".cargo" ) == string::npos && PLAYER_FACTION_STRING == "upgrades")
89  savestr = "generic_cargo";
90  savedships.push_back( savestr );
91  if (wherepipe != string::npos)
92  cltname = xmlstr.substr( wherepipe+1 );
93  if (wherepipe == string::npos || cltname.length() == 0)
94  cltname = "Object_"+XMLSupport::tostring( cltserial );
95  }
96  Unit *un = UnitFactory::createUnit( savedships[0].c_str(),
97  false,
98  FactionUtil::GetFactionIndex( PLAYER_FACTION_STRING ),
99  string( "" ),
100  Flightgroup::newFlightgroup( cltname, savedships[0], PLAYER_FACTION_STRING,
101  "default", 1, 1, "", "", mission ),
102  0, savegamestr );
103  ClientPtr clt = this->AddClientObject( un, cltserial );
104 
105  //Assign new coordinates to client
106  un->SetPosition( trans.position );
107  un->curr_physical_state = trans;
108  un->BackupState();
109  DoEnterExitAni( trans.position, un->rSize(), true );
110  if (clt) {
111  clt->last_packet = un->old_state;
112  clt->prediction->InitInterpolation( un, un->old_state, 0, this->deltatime );
113 
114 //save.SetPlayerLocation(un->curr_physical_state.position);
115  clt->name = cltname;
116  clt->callsign = cltname;
117  string msg = clt->callsign+" entered the system";
118  UniverseUtil::IOmessage( 0, "game", "all", "#FFFF66"+msg+"#000000" );
119  }
120  return un;
121  }
122  return NULL;
123 }
124 
126 {
127  un->PrimeOrders(); //Allow you to communicate with it.
128  if (!cltserial)
129  cltserial = un->GetSerial();
130  {
131  Flightgroup *fg;
132  fg = un->getFlightgroup();
133  string fgname;
134  if (fg) fgname = ", fg "+fg->name;
135  COUT<<" >>> ENTERING CLIENT =( "<<cltserial
136  <<fgname<<" )= -----------------"<<endl;
137  }
138  ClientPtr clt = Clients.get( cltserial );
139  if (clt) {
140  //Client may exist if it jumped from a starsystem to another of if killed and respawned
141  COUT<<"Existing client #"<<cltserial<<endl;
142  } else if (!cltserial) {
143  COUT<<"Local client with serial 0: "<<un->name<<", "<<un->getFullname()<<endl;
144  return clt;
145  } else {
146  clt = Clients.insert( cltserial, new Client );
147  nbclients++;
148  COUT<<"New client #"<<cltserial<<" - now "<<nbclients<<" clients in system"<<endl;
149  }
150  if ( !isLocalSerial( cltserial ) ) {
151  clt->game_unit.SetUnit( un );
152  //Set all weapons to inactive
153  vector< Mount >
154  ::iterator i = un->mounts.begin(); //note to self: if vector<Mount *> is ever changed to vector<Mount> remove the const_ from the const_iterator
155  for (; i != un->mounts.end(); ++i)
156  (*i).status = Mount::INACTIVE;
157  un->SetNetworkMode( true );
158  un->SetSerial( cltserial );
159  //COUT<<"Addclient 4"<<endl;
160  un->BackupState();
161  clt->last_packet = un->old_state;
162  clt->prediction->InitInterpolation( un, un->old_state, 0, this->deltatime );
164  } else {
165  Unit *myun = this->game_unit.GetUnit();
166  Unit *cltun = clt->game_unit.GetUnit();
167  if ( cltun == NULL || cltserial != cltun->GetSerial() )
168  clt->game_unit.SetUnit( un ? un : getNetworkUnit( cltserial ) );
169  if ( myun == NULL || cltserial != myun->GetSerial() )
170  this->game_unit.SetUnit( un ? un : getNetworkUnit( cltserial ) );
171  }
172  return clt;
173 }
174 
175 /*
176  ************************************************************
177  **** Ask the server for the entering zone info ***
178  ************************************************************
179  */
180 
182 {
183  char tbuf[1024];
184  sprintf( tbuf, "%d", this->zone );
185  COUT<<__PRETTY_FUNCTION__<<" zone: "<<tbuf<<endl;
186  VsnetDownload::Client::Buffer buf( *this->clt_tcp_sock, tbuf, VSFileSystem::ZoneBuffer );
187  _downloadManagerClient->addItem( &buf );
188  timeval timeout = {10, 0};
189  while ( !buf.done() )
190  if (recvMsg( NULL, &timeout ) <= 0)
191  //NETFIXME: What if timeout or error occurs?
192  break;
193  const char *tmp = (char*) buf.getBuffer().get();
194  NetBuffer netbuf( tmp, buf.getSize() );
195  this->AddObjects( netbuf );
196 }
197 
199 {
200  char subcmd;
201  /*
202  * std::set<ObjSerial> enteredSerials;
203  * for (unsigned int i=0;i<_Universe->numPlayers();++i) {
204  * Unit*un=_Universe->AccessCockpit(i)->GetParent();
205  * if(un) enteredSerials.insert(un->GetSerial());
206  * }
207  */
208  //Loop until the end of the buffer
209  int offset = netbuf.getOffset();
210  while ( ( subcmd = netbuf.getChar() ) != ZoneMgr::End ) {
211  int noffset = netbuf.getOffset();
212  if (noffset == offset) {
213  COUT<<"ERROR Premature end of AddObjects buffer "<<std::hex
214  <<std::string( netbuf.getData(), netbuf.getSize() )<<std::endl;
215 
216  break;
217  }
218  offset = noffset; //to make sure we aren't at end of truncated buf
219  Unit *newunit = NULL;
220  ObjSerial serial = 0;
221  switch (subcmd)
222  {
223  case ZoneMgr::AddClient:
224  serial = netbuf.getSerial();
225 //enteredSerials.insert(serial);
226  newunit = this->enterClient( netbuf, serial );
227  break;
228  case ZoneMgr::AddUnit:
229  newunit = UnitFactory::parseUnitBuffer( netbuf );
230  AddClientObject( newunit );
231 //enteredSerials.insert(newunit->GetSerial());
232  break;
233  case ZoneMgr::AddNebula:
234  newunit = (Unit*) UnitFactory::parseNebulaBuffer( netbuf );
235  AddClientObject( newunit );
236 //enteredSerials.insert(newunit->GetSerial());
237  break;
238  case ZoneMgr::AddPlanet:
239  newunit = (Unit*) UnitFactory::parsePlanetBuffer( netbuf );
240  AddClientObject( newunit );
241 //enteredSerials.insert(newunit->GetSerial());
242  break;
244  newunit = (Unit*) UnitFactory::parseAsteroidBuffer( netbuf );
245  AddClientObject( newunit );
246 //enteredSerials.insert(newunit->GetSerial());
247  break;
248  case ZoneMgr::AddMissile:
249  newunit = (Unit*) UnitFactory::parseMissileBuffer( netbuf );
250  AddClientObject( newunit );
251 //enteredSerials.insert(newunit->GetSerial());
252  break;
253  default:
254  cerr<<"WARNING : Unknown sub "<<(int) subcmd<<" command in AddObjects"<<endl;
255  break;
256  }
257  if (newunit) {
258  serial = newunit->GetSerial();
259  cerr<<" *** Adding Unit "<<serial<<" "<<UnitUtil::getFactionName( newunit )<<" "<<newunit->getFullname()<<"; "
260  <<newunit->name.get()<<endl;
261  }
262  }
263  //NETFIXME: What is the point of killing off all non-networked units all the time?
264  /*
265  * Unit *un;
266  * for (un_iter it = UniverseUtil::getUnitList();
267  * un=(*it);
268  * ) {
269  * ++it;
270  * if (enteredSerials.find(un->GetSerial())==enteredSerials.end()) {
271  * un->Kill();//doesnt belong here..not an allowed serial
272  * //NETFIXME could result in star system being killed off one by one--need to differentiate that
273  * }
274  * }
275  */
276 }
277 
278 /*
279  ************************************************************
280  **** Removes an exiting client of the actual zone ***
281  ************************************************************
282  */
283 
284 void NetClient::removeClient( const Packet *packet )
285 {
286  ObjSerial cltserial = packet->getSerial();
287 
288  COUT<<" & HTONS(Serial) = "<<cltserial<<endl;
289  ClientPtr clt;
290  if ( !( clt = Clients.get( cltserial ) ) ) {
291  cerr<<"Error, client does not exists !!"<<endl;
292  return;
293 //exit( 1);
294  }
295  Unit *un = clt->game_unit.GetUnit();
296  if (un) {
297  DoEnterExitAni( un->Position(), un->rSize(), false );
298  //Removes the unit from starsystem, destroys it and delete client
300  }
301  nbclients--;
302  Clients.remove( cltserial );
303  if (un)
304  un->Kill();
305  COUT<<"Leaving client #"<<cltserial<<" - now "<<nbclients<<" clients in system"<<endl;
306  string msg = clt->callsign+" left the system";
307  UniverseUtil::IOmessage( 0, "game", "all", "#FFFF66"+msg+"#000000" );
308 }
309 
310 /*
311  ************************************************************
312  **** Send an update to server ***
313  ************************************************************
314  */
315 
317 {
318  Unit *un = this->game_unit.GetUnit();
319  if (!un)
320  return;
321  //Serial in ClientState is updated in UpdatePhysics code at ClientState creation (with pos, veloc...)
322  NetBuffer netbuf;
323  static bool debugPos = XMLSupport::parse_bool( vs_config->getVariable( "network", "debug_position_interpolation", "false" ) );
324  //Send the client state
325  if (debugPos) COUT<<"Sending ClientState == ";
326  if (debugPos) (*cs).display();
327  netbuf.addSerial( cs->getSerial() );
328  netbuf.addClientState( (*cs) );
329  if (netversion > 4960)
330  netbuf.addChar( cs->getSpecMult() > 1.0 ? 1 : 0 );
331  static bool aim_assist = XMLSupport::parse_bool( vs_config->getVariable( "network", "aim_assist", "true" ) );
332  Unit *targ;
333  if ( ( targ = un->Target() ) != NULL && aim_assist && un->Target()->GetSerial() != 0 /*networked unit*/ ) {
334  if (un->InRange( targ ) && !targ->graphicOptions.InWarp && !un->graphicOptions.InWarp) {
335  netbuf.addSerial( targ->GetSerial() );
336  netbuf.addVector( ( targ->Position()-cs->getPosition() ).Cast() );
337  netbuf.addVector( targ->Velocity );
338  }
339  }
340  send( CMD_POSUPDATE, netbuf, SENDANDFORGET, __FILE__, __LINE__ );
341 }
342 
343 /*
344  *************************************************************
345  **** Update another client position ***
346  *************************************************************
347  */
348 
349 void NetClient::receivePositions( unsigned int numUnits, unsigned int int_ts, NetBuffer &netbuf, double delta_t )
350 {
351  //Computes deltatime only when receiving a snapshot since we interpolate positions between 2 snapshots
352  //We don't want to consider a late snapshot
353 //cout << "netSnapshot ";
354  static bool debugPos = XMLSupport::parse_bool( vs_config->getVariable( "network", "debug_position_interpolation", "false" ) );
355  if (latest_timestamp <= int_ts) {
356  if (debugPos) COUT<<" *** SNAPSHOT is not late - evaluating"<<endl;
357  this->latest_timestamp = int_ts;
358  this->deltatime = delta_t;
359 
360  //Loop throught received snapshot
361  unsigned int i = 0, j = 0, k = 0;
362  int offset = netbuf.getOffset();
363  while ( (i+j+k) < numUnits ) {
364  ObjSerial sernum = 0;
365  unsigned char cmd;
366  bool localplayer = false;
367  ClientPtr clt;
368  Unit *un = NULL;
369 
370  //Get the ZoneMgr::SnapshotSubCommand from buffer
371  cmd = netbuf.getChar();
372  int noffset = netbuf.getOffset();
373  if (noffset == offset) {
374  COUT<<"ERROR Premature end of Snapshot buffer "<<std::hex
375  <<std::string( netbuf.getData(), netbuf.getSize() )<<std::endl;
376  break; //if buffer is already used up...
377  }
378  offset = noffset;
379 
380  //Get the serial number of current element
381  sernum = netbuf.getShort();
382  //First test if it is us
383  if (sernum == this->serial)
384  localplayer = true;
385  if ( !( clt = Clients.get( sernum ) ) ) {
386  //Test if it is a client or a unit
387  if ( !( un = UniverseUtil::GetUnitFromSerial( sernum ) ) )
388  COUT<<"WARNING : No client, no unit found for this serial ("<<sernum<<")"<<endl;
389  }
390  //Test if local player
391  else {
392  un = clt->game_unit.GetUnit();
393  if (un)
394  localplayer = _Universe->isPlayerStarship( un ) ? true : false;
395  }
396  if (cmd&ZoneMgr::FullUpdate) {
397  if (debugPos) COUT<<" *** SubCommand is FullUpdate ser="<<sernum<<endl;
398  ClientState cs;
399  float newEnergy;
400  //Do what needed with update
401  if (debugPos) COUT<<"Received ZoneMgr::FullUpdate ";
402  //Tell we received the ClientState so we can convert byte order from network to host
403  cs = netbuf.getClientState();
404  newEnergy = netbuf.getFloat();
405  if (cmd&ZoneMgr::SPECUpdate) {
406  cs.setSpecRamp( netbuf.getFloat() );
407  cs.setSpecMult( netbuf.getFloat() );
408  }
409  if (debugPos) COUT<<" *** cs="<<cs<<endl;
410 //NETFIXME: Why not set local player? It can't hurt...
411  if (un) {
412  if (!localplayer) {
413  //Get our "semi-ping" from server
414  //We received delay in ms so we convert it into seconds
415  //Backup old state
416  un->BackupState();
417  //Update concerned client with predicted position directly in network client list
418  cs.setUnitState( un );
419  if (clt) {
420  if ( clt->last_packet.getPosition() == QVector( 0, 0, 0 ) ) {
421  //Position previously uninitialized...
422  un->BackupState();
423  clt->last_packet = cs;
424  }
425  clt->setLatestTimestamp( int_ts );
426  clt->elapsed_since_packet = 0;
427  assert( clt->prediction );
428  clt->prediction->InitInterpolation( un,
429  clt->last_packet,
430  clt->getDeltatime(),
431  clt->getNextDeltatime() );
432  clt->last_packet = cs;
433  un->curr_physical_state = clt->prediction->Interpolate( un, 0 );
434  }
435  QVector predpos = un->curr_physical_state.position;
436  if (debugPos) cerr<<"Predicted location : x="<<predpos.i<<",y="<<predpos.j<<",z="<<predpos.k<<endl;
437  }
438  //Everyone gets energy updates.
439  un->energy = newEnergy;
440  }
441  i++;
442  } else if (cmd&ZoneMgr::PosUpdate) {
443  if (debugPos) COUT<<" *** SubCommand is PosUpdate ser="<<sernum<<endl;
444  QVector pos = netbuf.getQVector();
445  if (debugPos) COUT<<" *** pos="<<pos.i<<","<<pos.j<<","<<pos.k<<endl;
446  if ( un && (!localplayer) ) {
447  //Backup old state
448  un->BackupState();
449  //Set the new received position in curr_physical_state
450  un->curr_physical_state.position = pos;
451  if (clt) {
452  if ( clt->last_packet.getPosition() == QVector( 0, 0, 0 ) ) {
453  //Position previously uninitialized...
454  un->BackupState();
455  clt->last_packet.setPosition( pos );
456  }
457  clt->setLatestTimestamp( int_ts );
458  clt->elapsed_since_packet = 0;
459  assert( clt->prediction );
460  clt->prediction->InitInterpolation( un,
461  clt->last_packet,
462  clt->getDeltatime(),
463  clt->getNextDeltatime() );
464  clt->last_packet = un->old_state;
465  clt->last_packet.setPosition( pos );
466  un->curr_physical_state = clt->prediction->Interpolate( un, 0 );
467  }
468  } else if (localplayer) {
469  if (debugPos) cerr<<" IGNORING LOCAL PLAYER"<<endl;
470  }
471  j++;
472  } else {
473  k++;
474  }
475  if (cmd&ZoneMgr::DamageUpdate)
476  receiveUnitDamage( netbuf, un );
477  //NETFIXME: Not an exit condition. Just print a warning message and ignore the rest of the packet.
478  //NETFIXME: we should include a length field for each sub-packet so that we can safely ignore a part of the packet.
479  //COUT << " *** SubCommand is neither FullUpdate nor PosUpdate" << endl;
480  //return;
481 //<< " *** TERMINATING ***" << endl;
482 //VSExit( 1 );
483  }
484  } else {
485  COUT<<" *** SNAPSHOT is late - ignoring"<<endl;
486  }
487 }
488 
489 #define SETNOTNULL( un, param, val ) \
490  if (un) param = val; \
491  else \
492  val
493 
494 void NetClient::receiveUnitDamage( NetBuffer &netbuf, Unit *un )
495 {
496  unsigned int it = 0;
497  unsigned short damages;
498  damages = netbuf.getShort();
499  if (!un)
500  cerr<<"Received Damage Update for null unit"<<endl;
501  if (un && un->hull <= 0) {
502  cerr<<"Received Damage Update for dead unit "<<un->GetSerial()<<endl;
503  un->Destroy();
504  un = NULL; //Assume it is dead for the purposes of this function.
505  }
506  if (damages&Unit::SHIELD_DAMAGED) {
507  SETNOTNULL( un, un->shield, netbuf.getShield() );
508  }
509  if (damages&Unit::ARMOR_DAMAGED) {
510  SETNOTNULL( un, un->armor, netbuf.getArmor() );
511  SETNOTNULL( un, un->hull, netbuf.getFloat() );
512  if (un && un->hull < 0)
513  un->Destroy(); //show nice explosion effects until receive CMD_KILL
514  }
515  if (damages&Unit::COMPUTER_DAMAGED) {
516  SETNOTNULL( un, un->computer.itts, netbuf.getChar() );
517  SETNOTNULL( un, un->computer.radar.capability, netbuf.getChar() );
518  SETNOTNULL( un, un->limits.retro, netbuf.getFloat() );
519  SETNOTNULL( un, un->computer.radar.maxcone, netbuf.getFloat() );
520  SETNOTNULL( un, un->computer.radar.lockcone, netbuf.getFloat() );
521  SETNOTNULL( un, un->computer.radar.trackingcone, netbuf.getFloat() );
522  SETNOTNULL( un, un->computer.radar.maxrange, netbuf.getFloat() );
523  unsigned int numvdus = (unsigned int)(unsigned char)netbuf.getChar();
524  for (it = 0; it < numvdus; ++it) {
525  float dam = netbuf.getFloat8();
526  if (un && it < 1+UnitImages< void >::NUMGAUGES+MAXVDUS)
527  un->pImage->cockpit_damage[it] = dam;
528  }
529  }
530  if (damages&Unit::MOUNT_DAMAGED) {
531  SETNOTNULL( un, un->pImage->ecm, netbuf.getShort() );
532  unsigned int nummounts = (unsigned int)(unsigned short) netbuf.getShort();
533  for (it = 0; it < nummounts; ++it) {
534  Mount::STATUS tmpstatus = (Mount::STATUS) netbuf.getChar();
535  int ammo = netbuf.getInt32();
536  float ttl = netbuf.getFloat();
537  unsigned short size = netbuf.getShort();
538  if ( un && it < un->mounts.size() ) {
539  if (_Universe->isPlayerStarship( un ) == NULL || tmpstatus == Mount::UNCHOSEN || tmpstatus == Mount::DESTROYED)
540  un->mounts[it].status = tmpstatus;
541  //don't reset my mount status on me... that's my
542  un->mounts[it].ammo = ammo;
543  un->mounts[it].time_to_lock = ttl;
544  un->mounts[it].size = size;
545  }
546  }
547  }
548  if (damages&Unit::CARGOFUEL_DAMAGED) {
549  if (un) un->SetFuel( netbuf.getFloat() );
550 
551  else netbuf.getFloat();
552  if (un) un->SetAfterBurn( netbuf.getFloat() );
553 
554  else netbuf.getFloat();
555  SETNOTNULL( un, un->pImage->CargoVolume, netbuf.getFloat() );
556  SETNOTNULL( un, un->pImage->UpgradeVolume, netbuf.getFloat() );
557  //NRTFIXME: cargo unimplented.
558 //for( it=0; it<un->pImage->cargo.size(); it++)
559 //un->pImage->cargo[it].quantity = netbuf.getInt32();
560  }
561  if (damages&Unit::JUMP_DAMAGED) {
562  SETNOTNULL( un, un->shield.leak, netbuf.getChar() );
563  SETNOTNULL( un, un->shield.recharge, netbuf.getFloat() );
564  if (un) un->SetEnergyRecharge( netbuf.getFloat() );
565 
566  else netbuf.getFloat();
567  if (un) un->SetMaxEnergy( netbuf.getFloat() );
568 
569  else netbuf.getFloat();
570  SETNOTNULL( un, un->jump.energy, netbuf.getFloat() );
571  SETNOTNULL( un, un->jump.damage, netbuf.getChar() );
572  SETNOTNULL( un, un->pImage->repair_droid, netbuf.getChar() );
573  }
574  if (damages&Unit::CLOAK_DAMAGED) {
575  SETNOTNULL( un, un->cloaking, netbuf.getInt32() );
576  SETNOTNULL( un, un->pImage->cloakenergy, netbuf.getFloat() );
577  SETNOTNULL( un, un->cloakmin, netbuf.getInt32() );
578  SETNOTNULL( un, un->pImage->cloakrate, netbuf.getInt32() );
579  }
580  if (damages&Unit::LIMITS_DAMAGED) {
581  SETNOTNULL( un, un->computer.max_pitch_down, netbuf.getFloat() );
582  SETNOTNULL( un, un->computer.max_pitch_up, netbuf.getFloat() );
583  SETNOTNULL( un, un->computer.max_yaw_left, netbuf.getFloat() );
584  SETNOTNULL( un, un->computer.max_yaw_right, netbuf.getFloat() );
585  SETNOTNULL( un, un->computer.max_roll_left, netbuf.getFloat() );
586  SETNOTNULL( un, un->computer.max_roll_right, netbuf.getFloat() );
587  SETNOTNULL( un, un->limits.roll, netbuf.getFloat() );
588  SETNOTNULL( un, un->limits.yaw, netbuf.getFloat() );
589  SETNOTNULL( un, un->limits.pitch, netbuf.getFloat() );
590  SETNOTNULL( un, un->limits.lateral, netbuf.getFloat() );
591  }
592 }
593 
594 /*
595  ************************************************************
596  **** Says we are ready and going in game ***
597  ************************************************************
598  */
599 
601 {
602  NetBuffer netbuf;
603  Unit *un = this->game_unit.GetUnit();
604  if (!un)
605  cout<<"Trying to ingame dead unit";
606  //ClientState cs( this->serial, un->curr_physical_state, un->Velocity, Vector(0,0,0), 0);
607  //HERE SEND INITIAL CLIENTSTATE !! NOT NEEDED ANYMORE -> THE SERVER ALREADY KNOWS
608  //netbuf.addClientState( cs);
609  send( CMD_ADDCLIENT, netbuf, SENDRELIABLE, __FILE__, __LINE__ );
610  un->SetSerial( this->serial );
611  COUT<<"Sending ingame with serial #"<<this->serial<<endl;
612  this->ingame = true;
613  cerr<<"STARTING LOCATION : x="<<un->Position().i<<",y="<<un->Position().j<<",z="<<un->Position().k<<endl;
614 }
615 
616 /*
617  ************************************************************
618  **** Says we are still alive ***
619  ************************************************************
620  */
621 
623 {
624  /* WE NEED PING PACKET EVEN IN TCP MODE : THAT ALLOWS US TO COMPUTE A "SEMI-PING" TIME BETWEEN SERVER AND CLIENTS
625  * if( clt_sock.isTcp() == false )
626  * {
627  */
628  Unit *un = this->game_unit.GetUnit();
629  if (!un)
630  return;
631  Packet p;
632  p.send( CMD_PING, un->GetSerial(),
633  (char*) NULL, 0,
634  SENDANDFORGET, NULL, *this->lossy_socket,
635  __FILE__, PSEUDO__LINE__( 414 ) );
636  //}
637 }
638