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
netserver_devices.cpp
Go to the documentation of this file.
1 #include "networking/netserver.h"
2 #include "networking/zonemgr.h"
8 #include "lin_time.h"
9 #include "save_util.h"
10 #include "universe_util.h"
11 
12 #include "cmd/pilot.h"
13 #include "cmd/ai/communication.h"
14 #include "cmd/ai/order.h"
15 
16 //WEAPON STUFF
17 
18 void NetServer::BroadcastTarget( ObjSerial serial, ObjSerial oldtarget, ObjSerial target, unsigned short zone )
19 {
20  Packet p;
21  NetBuffer netbuf;
22  netbuf.addSerial( target );
23  ClientPtr clt = this->getClientFromSerial( target );
24  if (clt)
25  p.send( CMD_TARGET, serial, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
26  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 24 ) );
27  netbuf.Reset();
28  netbuf.addSerial( 0 );
29  clt = this->getClientFromSerial( oldtarget );
30  if (clt)
31  p.send( CMD_TARGET, serial, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
32  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 34 ) );
33  clt = this->getClientFromSerial( serial );
34  if (clt && clt->netversion < 4951) {
35  //Old clients needed confirmation to target...
36  netbuf.Reset();
37  netbuf.addSerial( target );
38  p.send( CMD_TARGET, serial, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
39  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 34 ) );
40  }
41  /*
42  * netbuf.addSerial( target);
43  * p.bc_create( CMD_TARGET, serial,
44  * netbuf.getData(), netbuf.getDataLength(),
45  * SENDRELIABLE,
46  * __FILE__, PSEUDO__LINE__(26) );
47  * zonemgr->broadcast( zone, serial, &p, true ); // NETFIXME: Should unfire be TCP?
48  */
49 }
50 
51 void NetServer::BroadcastUnfire( ObjSerial serial, const vector< int > &weapon_indicies, unsigned short zone )
52 {
53  Packet p;
54  NetBuffer netbuf;
55 
56  //netbuf.addSerial( serial);
57  netbuf.addInt32( weapon_indicies.size() );
58  for (unsigned int i = 0; i < weapon_indicies.size(); i++)
59  netbuf.addInt32( weapon_indicies[i] );
60  //p.send( CMD_UNFIREREQUEST, serial, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE, NULL, this->clt_sock, __FILE__, __LINE__);
61  p.bc_create( CMD_UNFIREREQUEST, serial,
62  netbuf.getData(), netbuf.getDataLength(),
64  __FILE__, PSEUDO__LINE__( 1695 ) );
65  zonemgr->broadcast( zone, serial, &p, true ); //NETFIXME: Should unfire be TCP?
66 }
67 
68 //In BroadcastFire we must use the provided serial because it may not be the client's serial
69 //but may be a turret serial
71  const vector< int > &weapon_indicies,
72  ObjSerial missile_serial,
73  float player_energy,
74  unsigned short zone )
75 {
76  Packet p;
77  NetBuffer netbuf;
78  //bool found = false;
79 
80  netbuf.addFloat( player_energy );
81  netbuf.addSerial( missile_serial );
82  netbuf.addInt32( weapon_indicies.size() );
83  for (unsigned int i = 0; i < weapon_indicies.size(); i++)
84  netbuf.addInt32( weapon_indicies[i] );
85  p.bc_create( CMD_FIREREQUEST, serial,
86  netbuf.getData(), netbuf.getDataLength(),
88  __FILE__, PSEUDO__LINE__( 1710 ) );
89  //WARNING : WE WILL SEND THE INFO BACK TO THE CLIENT THAT HAS FIRED -> SHOULD USE broadcastNoSelf instead if we dont want that
90  zonemgr->broadcast( zone, serial, &p, true ); //NETFIXME: Should unfire be TCP?
91 }
92 
94  ObjSerial buyer,
95  ObjSerial seller,
96  const std::string &cargo,
97  float price,
98  float mass,
99  float volume,
100  bool mission,
101  unsigned int quantity,
102  int mountOffset,
103  int subunitOffset,
104  unsigned short zone )
105 {
106  Packet p;
107  NetBuffer netbuf;
108 
109  netbuf.addSerial( buyer ); //If the buyer is the player, it is buying cargo.
110  netbuf.addSerial( seller ); //If seller is the player, it is selling cargo.
111  netbuf.addInt32( quantity );
112  netbuf.addString( cargo );
113  netbuf.addFloat( price );
114  netbuf.addFloat( mass );
115  netbuf.addFloat( volume );
116  if (mission) {
117  netbuf.addInt32( 1 );
118  netbuf.addInt32( 1 );
119  } else {
120  netbuf.addInt32( (unsigned int) (mountOffset) );
121  netbuf.addInt32( (unsigned int) (subunitOffset) );
122  }
123  p.bc_create( CMD_CARGOUPGRADE, sender,
124  netbuf.getData(), netbuf.getDataLength(),
125  SENDRELIABLE,
126  __FILE__, PSEUDO__LINE__( 87 ) );
127  zonemgr->broadcast( zone, sender, &p, true ); //NETFIXME: Should unfire be TCP?
128 }
129 
130 void NetServer::sendCredits( ObjSerial serial, float creds )
131 {
132  Packet p;
133  NetBuffer netbuf;
134  netbuf.addFloat( creds );
135  ClientPtr clt = this->getClientFromSerial( serial );
136  if (!clt) return;
137  p.send( CMD_CREDITS, serial,
138  netbuf.getData(), netbuf.getDataLength(),
139  SENDRELIABLE, NULL, clt->tcp_sock,
140  __FILE__, PSEUDO__LINE__( 97 ) );
141 }
142 
144 {
145  unsigned int numCargo = un->numCargo();
146  if (!numCargo) return;
147  netbuf.addSerial( un->GetSerial() );
148  netbuf.addFloat( un->Mass );
149  netbuf.addFloat( un->pImage->CargoVolume );
150  netbuf.addFloat( un->pImage->UpgradeVolume );
151  netbuf.addInt32( numCargo );
152  for (unsigned int i = 0; i < numCargo; i++) {
153  const Cargo &carg = un->GetCargo( i );
154  netbuf.addInt32( carg.GetQuantity()*(carg.GetMissionFlag() ? -1 : 1) );
155  netbuf.addString( carg.GetContent() );
156  netbuf.addFloat( carg.GetPrice() );
157  netbuf.addFloat( carg.GetMass() );
158  netbuf.addFloat( carg.GetVolume() );
159  }
160 }
161 
163 {
164  ClientPtr clt = this->getClientFromSerial( cltser );
165  if (!clt) return;
166  NetBuffer netbuf;
167  Packet p2;
168  const Unit *un;
169  for (un_kiter iter = list.constIterator(); (un = *iter); ++iter) {
170  if (!un->GetSerial() || un->GetSerial() == cltser) continue;
171  addUnitCargoSnapshot( un, netbuf );
172  }
173  netbuf.addSerial( 0 );
174  p2.send( CMD_SNAPCARGO, 0, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
175  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 196 ) );
176 }
177 
179  unsigned short type,
180  int pos,
181  const string *key,
182  Mission *miss,
183  const string *strValue,
184  const float *floatValue )
185 {
186  /* Note to self: This function will do absolutely nothing
187  * until it is implemented. */
188  NetBuffer netbuf;
189  Packet p2;
190  Unit *un = _Universe->AccessCockpit( cp )->GetParent();
191  if (!un) return;
192  ClientPtr clt = this->getClientFromSerial( un->GetSerial() );
193  if (!clt) return;
194  netbuf.addShort( type );
195  if ( (type&Subcmd::StringValue) || (type&Subcmd::FloatValue) ) {
196  if (*key == "active_scripts" || *key == "mission_scripts")
197  return; //Don't send these to clients since they are huge.
198 
199  netbuf.addString( *key );
200  }
201  netbuf.addInt32( pos );
202  if (type&Subcmd::Objective) {
203  int num = miss->getPlayerMissionNumber();
204  netbuf.addInt32( num-1 );
205  }
206  if (type&Subcmd::SetValue) {
207  if ( (type&Subcmd::StringValue) || (type&Subcmd::Objective) )
208  netbuf.addString( *strValue );
209  if ( (type&Subcmd::FloatValue) || (type&Subcmd::Objective) )
210  netbuf.addFloat( *floatValue );
211  }
212  p2.send( CMD_SAVEDATA, 0, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
213  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 164 ) );
214 }
215 
216 void NetServer::sendMission( int cp, unsigned short packetType, string mission, int pos )
217 {
218  Packet p;
219  NetBuffer netbuf;
220  Unit *un = _Universe->AccessCockpit( cp )->GetParent();
221  if (!un) return;
222  ClientPtr clt = this->getClientFromSerial( un->GetSerial() );
223  if (!clt) return;
224  netbuf.addShort( packetType );
225  netbuf.addString( mission );
226  netbuf.addInt32( pos );
227 
228  p.send( CMD_MISSION, 0, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
229  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 186 ) );
230 }
231 
233  unsigned short zone,
234  float hull,
235  const Shield &shield,
236  const Armor &armor,
237  float ppercentage,
238  float spercentage,
239  float amt,
240  Vector &pnt,
241  Vector &normal,
242  GFXColor &color )
243 {
244  static ObjSerial lastserial;
245  static float timestamp = getNewTime();
246  float curtime = getNewTime();
247  static float mintime =
248  XMLSupport::parse_float( vs_config->getVariable( "network", "min_time_btw_damage_updates", ".25" ) );
249  if (lastserial != serial || curtime-timestamp > mintime) {
250  timestamp = curtime;
251  lastserial = serial;
252  Packet p;
253  NetBuffer netbuf;
254 
255  netbuf.addFloat( amt );
256  netbuf.addFloat( ppercentage );
257  netbuf.addFloat( spercentage );
258  netbuf.addVector( pnt );
259  netbuf.addVector( normal );
260  netbuf.addColor( color );
261  netbuf.addFloat( hull );
262  netbuf.addShield( shield );
263  netbuf.addArmor( armor );
264 
265  p.bc_create( CMD_DAMAGE, serial,
266  netbuf.getData(), netbuf.getDataLength(),
267  SENDRELIABLE,
268  __FILE__, PSEUDO__LINE__( 1729 ) );
269  //WARNING : WE WILL SEND THE INFO BACK TO THE CLIENT THAT HAS FIRED
270  zonemgr->broadcast( zone, serial, &p, false ); //NETFIXME: Should damages be TCP? NO..we have alternate method to deal with it
271  }
272 }
273 
274 void NetServer::sendCustom( int cp, const string &command, const string &args, const string &id )
275 {
276  Packet p2;
277  NetBuffer netbuf;
278 
279  Unit *un = _Universe->AccessCockpit( cp )->GetParent();
280  if (!un) {
281  fprintf( stderr, "Attempt to sendCustom NULL player %d ; CMD %s %s ; ID %s\n",
282  cp, command.c_str(), args.c_str(), id.c_str() );
283  return;
284  }
285  ClientPtr clt = this->getClientFromSerial( un->GetSerial() );
286  if (!clt) return;
287  netbuf.addString( command );
288  netbuf.addString( args );
289  netbuf.addString( id );
290 
291  p2.send( CMD_CUSTOM, un->GetSerial(), netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
292  NULL, clt->tcp_sock, __FILE__, __LINE__ );
293 }
294 
295 void NetServer::sendMessage( const string &from, const string &to, const string &message, float delay )
296 {
297  NetBuffer netbuf;
298  netbuf.addString( from );
299  netbuf.addString( message );
300  Packet p2;
301 
302  const char*tostr( to.c_str() );
303  if (to[0] == 'p') {
304  int playerto = -1;
305  sscanf( tostr+1, "%d", &playerto );
306  if ( playerto != -1 && (unsigned int) playerto < _Universe->numPlayers() ) {
307  Cockpit *cp = _Universe->AccessCockpit( playerto );
308  Unit *un = cp->GetParent();
309  if (!un) return;
310  ClientPtr clt = this->getClientFromSerial( un->GetSerial() );
311  if (!clt) return;
312  p2.send( CMD_TXTMESSAGE, 0, netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
313  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 223 ) );
314  }
315  } else {
316  p2.bc_create( CMD_TXTMESSAGE, 0,
317  netbuf.getData(), netbuf.getDataLength(),
318  SENDRELIABLE,
319  __FILE__, PSEUDO__LINE__( 229 ) );
320  if (to == "broadcast") {
321  for (ZoneMap::const_iterator iter = zonemgr->zones.begin();
322  iter != zonemgr->zones.end(); ++iter)
323  zonemgr->broadcast( (*iter).first, 0, &p2, false );
324  } else {
325  zonemgr->broadcast( _Universe->activeStarSystem()->GetZone(), 0, &p2, false );
326  }
327  }
328 }
329 
331 {
332  NetBuffer netbuf;
333  Client *clt = this->getClientFromSerial( to->GetSerial() ).get();
334  if (!clt) return;
335  if (c)
336  netbuf.addInt32( c->curstate );
337  else
338  netbuf.addInt32( -1 ); //don't actually say anything...
339  netbuf.addFloat( UnitUtil::getFactionRelation( from, to ) );
340  netbuf.addFloat( UnitUtil::getFactionRelation( to, from ) );
341  if (from->pilot) {
342  Pilot::relationmap::iterator i = from->pilot->effective_relationship.find( to );
343  if ( i == from->pilot->effective_relationship.end() )
344  netbuf.addFloat( 0.0 );
345  else
346  netbuf.addFloat( (*i).second );
347  } else {
348  netbuf.addFloat( 0.0 );
349  }
350  if (to->pilot) {
351  Pilot::relationmap::iterator i = to->pilot->effective_relationship.find( to );
352  if ( i == to->pilot->effective_relationship.end() )
353  netbuf.addFloat( 0.0 );
354  else
355  netbuf.addFloat( (*i).second );
356  } else {
357  netbuf.addFloat( 0.0 );
358  }
359  Packet p2;
360  p2.send( CMD_COMM, from->GetSerial(), netbuf.getData(), netbuf.getDataLength(),
361  SENDRELIABLE, NULL, clt->tcp_sock, __FILE__, __LINE__ );
362 }
363 
364 //zonemgr.cpp
365 extern void displayUnitInfo( Unit *un, const string callsign, const char *type );
366 
367 void NetServer::sendKill( ObjSerial serial, unsigned short zone )
368 {
369  Packet p;
370  Unit *un;
371 
372  //cerr<<"SENDING A KILL for serial "<<serial<<" in zone "<<zone<<endl;
373  //Find the client in the udp & tcp client lists in order to set it out of the game (not delete it yet)
374  ClientPtr clt = this->getClientFromSerial( serial );
375  if (clt)
376  un = clt->game_unit.GetUnit();
377  else
378  un = zonemgr->getUnit( serial, zone );
379  //It's the server's responsibility to kill missions in this case.
380  //NETFIXME: Note that the client might not hear the request to terminate missions.
381  int cp = _Universe->whichPlayerStarship( un );
382  if (cp >= 0) {
383  //Note 1 not 0 is to avoid killing the player's main mission.
384  Mission *mis;
385  while ( ( mis = Mission::getNthPlayerMission( cp, 1 ) ) )
386  mis->terminateMission();
387  }
388  p.bc_create( CMD_KILL, serial,
389  NULL, 0, SENDRELIABLE,
390  __FILE__, PSEUDO__LINE__( 1771 ) );
391  //WARNING : WE WILL SEND THE INFO BACK TO THE CLIENT THAT HAS FIRED
392  zonemgr->broadcast( zone, serial, &p, true );
393  if (!clt)
394  displayUnitInfo( un, string(), " *** KILLED a npc " );
395  /*
396  * un = zonemgr->getUnit( serial, zone);
397  * if (un) {
398  * zonemgr->removeUnit( un, zone);
399  * }
400  */
401  else
402  zonemgr->removeClient( clt );
403 }
404 
405 void NetServer::sendJumpFinal( ClientPtr clt, const string &server_ip, unsigned short server_port )
406 {
407  Packet p2;
408  NetBuffer buf;
409  buf.addString( server_ip );
410  buf.addShort( server_port );
411 
412  p2.send( CMD_JUMP, 0, buf.getData(), buf.getDataLength(), SENDRELIABLE, NULL, clt->tcp_sock, __FILE__, 148 );
413  if (clt && 0 /*dont discon until client requests it*/)
414  logoutList.push_back( clt );
415 }
416 
417 void NetServer::sendJump( Unit *un, Unit *dst, const string &dststr )
418 {
419  ClientPtr clt = this->getClientFromSerial( un->GetSerial() );
420  if (!clt) return;
421  int cpnum = -1;
422  if (clt && ( cpnum = _Universe->whichPlayerStarship( un ) ) >= 0 && un != NULL) {
423  WaitListEntry entry;
424  if ( waitList.find( clt->callsign ) != waitList.end() )
425  return;
426  std::string netbuf;
427  std::string fn = dststr;
428  if (getSaveStringLength( cpnum, "jump_from" ) < 1)
429  pushSaveString( cpnum, "jump_from", _Universe->activeStarSystem()->getFileName() );
430  else
431  putSaveString( cpnum, "jump_from", 0, _Universe->activeStarSystem()->getFileName() );
432  std::string savestr;
433  std::string csvstr;
434  SaveNetUtil::GetSaveStrings( cpnum, savestr, csvstr, true );
435  /*
436  * savestr = cp->savegame->WriteSaveGame (fn.c_str(),un->LocalPosition(),cp->credits,cp->unitfilename,-1,FactionUtil::GetFactionName(un->faction), false);
437  * csvstr = un->WriteUnitString();
438  */
439  std::string::size_type where = savestr.find( "^" );
440  addSimpleChar( netbuf, ACCT_SAVE_LOGOUT );
441  if (where != std::string::npos)
442  if ( dststr != savestr.substr( 0, where ) )
443  savestr = dststr+savestr.substr( where );
444  addSimpleString( netbuf, clt->callsign );
445  addSimpleString( netbuf, clt->passwd );
446  addSimpleString( netbuf, savestr );
447  addSimpleString( netbuf, csvstr );
448  clt->jumpok = 1;
449 
450  entry.type = WaitListEntry::JUMPING;
451  entry.t = clt;
452  entry.tcp = true;
453  waitList[clt->callsign] = entry;
454  clt->loginstate = Client::LOGGEDIN;
455  if (acct_sock)
456  acct_sock->sendstr( netbuf );
457  } else {
458  //do something intelligent for NPCs
459  }
460  /*
461  * if (0) {
462  * Packet p2;
463  * NetBuffer netbuf;
464  * string file_content;
465  * ClientPtr clt = this->getClientFromSerial( serial);
466  * if (!clt) {
467  * cerr<<"Client "<< serial<<" Trying to jump but cannot retrieve client struct \n";
468  * }
469  * // Send a CMD_JUMP to tell the client if the jump is allowed
470  * netbuf.addString( clt->jumpfile );
471  * netbuf.addSerial( serial);
472  * netbuf.addSerial( jumpserial);
473  *
474  * // DO NOT DO THAT : the client itself will ask to be removed and also to be added when it is allowed to do so
475  * // And remove the player from its old starsystem and set it out of game
476  * //this->removeClient( clt );
477  * // Have to set new starsystem here
478  * Cockpit * cp = _Universe->isPlayerStarship( clt->game_unit.GetUnit());
479  * cp->savegame->SetStarSystem( clt->jumpfile);
480  * StarSystem* sts = GetLoadedStarSystem( clt->jumpfile.c_str());
481  * unsigned short zoneid = _Universe->StarSystemIndex( sts);
482  * netbuf.addShort( zoneid);
483  *
484  * // Test whether the jump was accepted or not by server
485  * if( ok)
486  * {
487  * // If jumpfile is empty the hash was correct
488  * if( clt->jumpokOLD==1 )
489  * p2.bc_create( CMD_JUMP, serial,
490  * netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
491  * __FILE__, PSEUDO__LINE__(1164) );
492  * // New system file HASH is wrong tell the client with serial != player serial so he can ask for a new download
493  * else if( clt->jumpokOLD==2)
494  * p2.bc_create( CMD_JUMP, serial+1,
495  * netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
496  * __FILE__, PSEUDO__LINE__(1164) );
497  * zonemgr->broadcast( clt, &p2, true );
498  * }
499  */
500 
501  //Should broadcast JUMP so other client display jump anim too ?
502 }
503 
504 //NETFIXME: AI Units won't be removed when docking... this may be desired but may be confusing for clients.
505 
506 void NetServer::sendDockAuthorize( ObjSerial serial, ObjSerial utdw_serial, int docknum, unsigned short zone )
507 {
508  //Set client not ingame while docked
509  ClientPtr clt = this->getClientFromSerial( serial );
510  if (!clt) {
511  cerr<<"Client "<<serial<<" for dock autorization is NULL."<<endl;
512  return;
513  }
514  Unit *un = clt->game_unit.GetUnit();
515  if (!un)
516  return;
517 //StarSystem * currentsys = un->getStarSystem();
518  //Remove the unit from the system list
519 //currentsys->RemoveUnit( un );
520 
521  NetBuffer netbuf;
522  Packet p;
523  //Send a CMD_DOCK with serial, an ObjSerial = unit_to_dock_with_serial and an int = docking port num
524  netbuf.addSerial( utdw_serial );
525  netbuf.addInt32( 0 ); //docknum);
526  p.bc_create( CMD_DOCK, serial,
527  netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
528  __FILE__, PSEUDO__LINE__( 118 ) );
529  zonemgr->broadcast( zone, serial, &p, true );
530 
531  //Whoops... Make sure to de-ingame the client *AFTER* the CMD_DOCK has been broadcast!
532  clt->ingame = false;
533  //Set timestamps to 0 so we won't have prediction problem when undocking
534  clt->clearLatestTimestamp();
535 }
536 
537 void NetServer::sendDockDeny( ObjSerial serial, unsigned short zone )
538 {
539  //In fact do nothing
540 }
541 
543 {
544  Unit *un = clt->game_unit.GetUnit();
545  if (!un)
546  return;
547  ClientState cs( un );
548 
549  Packet p;
550  NetBuffer netbuf;
551  if (clt->netversion < 4951)
552  netbuf.addQVector( cs.getPosition() );
553  else
554  netbuf.addClientState( cs );
555  p.send( CMD_POSUPDATE, un->GetSerial(), netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
556  NULL, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 457 ) );
557 }
558 
559 void NetServer::sendUnDock( ObjSerial serial, ObjSerial utdwserial, unsigned short zone )
560 {
561  //Set client ingame
562  ClientPtr clt = this->getClientFromSerial( serial );
563  if (!clt) {
564  cerr<<"Client "<<serial<<" for dock autorization is NULL."<<endl;
565  return;
566  }
567  Unit *un = clt->game_unit.GetUnit();
568  if (!un)
569  return;
570  clt->ingame = true;
571  //Add the unit back into the system list
572 //StarSystem * currentsys = un->getStarSystem();
573 //currentsys->AddUnit( un );
574 
575  //SEND A CMD_UNDOCK TO OTHER CLIENTS IN THE ZONE with utdw serial
576  NetBuffer netbuf;
577  Packet p;
578  netbuf.addSerial( utdwserial );
579  p.bc_create( CMD_UNDOCK, serial,
580  netbuf.getData(), netbuf.getDataLength(), SENDRELIABLE,
581  __FILE__, PSEUDO__LINE__( 134 ) );
582  zonemgr->broadcast( zone, serial, &p, true );
583 
584  static bool autolanding_enable = XMLSupport::parse_bool( vs_config->getVariable( "physics", "AutoLandingEnable", "false" ) );
585  if (!autolanding_enable)
586  sendForcePosition( clt );
587 }
588