]> git.mxchange.org Git - flightgear.git/commitdiff
Move all MP code in src/MultiPlayer.
authorJames Turner <zakalawe@mac.com>
Sat, 13 Nov 2010 14:38:35 +0000 (14:38 +0000)
committerJames Turner <zakalawe@mac.com>
Sat, 28 May 2011 23:04:30 +0000 (00:04 +0100)
Allow the subsystem to be (re-)inited at runtime.

projects/VC90/FlightGear/FlightGear.vcproj
src/Main/fg_io.cxx
src/MultiPlayer/multiplaymgr.cxx
src/MultiPlayer/multiplaymgr.hxx
src/Network/CMakeLists.txt
src/Network/Makefile.am
src/Network/multiplay.cxx [deleted file]
src/Network/multiplay.hxx [deleted file]

index f7d56ff93a93c8dcdc03051a1c7fb8964e343b84..8d70c402801ade0a95cb1752a76a7a2f84ba6f81 100644 (file)
                                RelativePath="..\..\..\src\Network\jsclient.hxx"\r
                                >\r
                        </File>\r
-                       <File\r
-                               RelativePath="..\..\..\src\Network\multiplay.cxx"\r
-                               >\r
-                       </File>\r
-                       <File\r
-                               RelativePath="..\..\..\src\Network\multiplay.hxx"\r
-                               >\r
-                       </File>\r
                        <File\r
                                RelativePath="..\..\..\src\Network\native.cxx"\r
                                >\r
index 6d6be65f50c4724d635ace9520a15da23d7ddd29..c45b98f86d9318ee14d00104d4534b00874c86b7 100644 (file)
@@ -65,7 +65,7 @@
 #include <Network/ray.hxx>
 #include <Network/rul.hxx>
 #include <Network/generic.hxx>
-#include <Network/multiplay.hxx>
+
 #ifdef FG_HAVE_HLA
 #include <Network/HLA/hla.hxx>
 #endif
@@ -219,10 +219,23 @@ FGIO::parse_port_config( const string& config )
                return NULL;
            }
            string dir = tokens[1];
-           string rate = tokens[2];
+           int rate = atoi(tokens[2].c_str());
            string host = tokens[3];
-           string port = tokens[4];
-           return new FGMultiplay(dir, atoi(rate.c_str()), host, atoi(port.c_str()));
+
+            short port = atoi(tokens[4].c_str());    
+
+        // multiplay used to be handled by an FGProtocol, but no longer. This code
+        // retains compatability with existing command-line syntax
+          fgSetInt("/sim/multiplay/tx-rate-hz", rate);
+          if (dir == "in") {
+            fgSetInt("/sim/multiplay/rxport", port);
+            fgSetString("/sim/multiplay/rxhost", host.c_str());
+          } else if (dir == "out") {
+            fgSetInt("/sim/multiplay/txport", port);
+            fgSetString("/sim/multiplay/txhost", host.c_str());
+          }
+
+          return NULL;
 #ifdef FG_HAVE_HLA
        } else if ( protocol == "hla" ) {
            return new FGHLA(tokens);
@@ -343,20 +356,20 @@ FGIO::init()
     // appropriate FGIOChannel structures
     string_list::iterator i = globals->get_channel_options_list()->begin();
     string_list::iterator end = globals->get_channel_options_list()->end();
-    for (; i != end; ++i )
-    {
-       p = parse_port_config( *i );
-       if ( p != NULL ) {
-           p->open();
-           io_channels.push_back( p );
-           if ( !p->is_enabled() ) {
-               SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." );
-               exit(-1);
-           }
-       } else {
-           SG_LOG( SG_IO, SG_INFO, "I/O Channel parse failed." );
-       }
-    }
+    for (; i != end; ++i ) {
+      p = parse_port_config( *i );
+      if (!p) {
+        continue;
+      }
+      
+      p->open();
+      if ( !p->is_enabled() ) {
+        SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." );
+        delete p;
+      }
+      
+      io_channels.push_back( p );
+    } // of channel options iteration
 }
 
 void
index 9a541382786f10de1cabd9433d103e07ba0e5de4..a8f8623885181bf1c6f80e280ea5d08c0949e951 100644 (file)
 #include <simgear/props/props.hxx>
 
 #include <AIModel/AIManager.hxx>
+#include <AIModel/AIMultiplayer.hxx>
 #include <Main/fg_props.hxx>
 #include "multiplaymgr.hxx"
 #include "mpmessages.hxx"
+#include <FDM/flightProperties.hxx>
 
 using namespace std;
 
@@ -56,11 +58,18 @@ using namespace std;
 const char sMULTIPLAYMGR_BID[] = "$Id$";
 const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID;
 
+struct IdPropertyList {
+  unsigned id;
+  const char* name;
+  simgear::props::Type type;
+};
+static const IdPropertyList* findProperty(unsigned id);
+  
 // A static map of protocol property id values to property paths,
 // This should be extendable dynamically for every specific aircraft ...
 // For now only that static list
-const FGMultiplayMgr::IdPropertyList
-FGMultiplayMgr::sIdPropertyList[] = {
+static const IdPropertyList sIdPropertyList[] = {
   {100, "surface-positions/left-aileron-pos-norm",  simgear::props::FLOAT},
   {101, "surface-positions/right-aileron-pos-norm", simgear::props::FLOAT},
   {102, "surface-positions/elevator-pos-norm",      simgear::props::FLOAT},
@@ -229,34 +238,33 @@ FGMultiplayMgr::sIdPropertyList[] = {
   {10319, "sim/multiplay/generic/int[19]", simgear::props::INT}
 };
 
-const unsigned
-FGMultiplayMgr::numProperties = (sizeof(FGMultiplayMgr::sIdPropertyList)
-                                 / sizeof(FGMultiplayMgr::sIdPropertyList[0]));
+const unsigned int numProperties = (sizeof(sIdPropertyList)
+                                 / sizeof(sIdPropertyList[0]));
 
 // Look up a property ID using binary search.
 namespace
 {
   struct ComparePropertyId
   {
-    bool operator()(const FGMultiplayMgr::IdPropertyList& lhs,
-                    const FGMultiplayMgr::IdPropertyList& rhs)
+    bool operator()(const IdPropertyList& lhs,
+                    const IdPropertyList& rhs)
     {
       return lhs.id < rhs.id;
     }
-    bool operator()(const FGMultiplayMgr::IdPropertyList& lhs,
+    bool operator()(const IdPropertyList& lhs,
                     unsigned id)
     {
       return lhs.id < id;
     }
     bool operator()(unsigned id,
-                    const FGMultiplayMgr::IdPropertyList& rhs)
+                    const IdPropertyList& rhs)
     {
       return id < rhs.id;
     }
-  };
-    
+  };    
 }
-const FGMultiplayMgr::IdPropertyList* FGMultiplayMgr::findProperty(unsigned id)
+
+const IdPropertyList* findProperty(unsigned id)
 {
   std::pair<const IdPropertyList*, const IdPropertyList*> result
     = std::equal_range(sIdPropertyList, sIdPropertyList + numProperties, id,
@@ -276,8 +284,7 @@ namespace
     const xdr_data_t* xdr = data;
     while (xdr < end) {
       unsigned id = XDR_decode_uint32(*xdr);
-      const FGMultiplayMgr::IdPropertyList* plist
-        = FGMultiplayMgr::findProperty(id);
+      const IdPropertyList* plist = findProperty(id);
     
       if (plist) {
         xdr++;
@@ -336,6 +343,24 @@ namespace
     return true;
   }
 }
+
+class MPPropertyListener : public SGPropertyChangeListener
+{
+public:
+  MPPropertyListener(FGMultiplayMgr* mp) :
+    _multiplay(mp)
+  {
+  }
+
+  virtual void childAdded(SGPropertyNode*, SGPropertyNode*)
+  {
+    _multiplay->setPropertiesChanged();
+  }
+
+private:
+  FGMultiplayMgr* _multiplay;
+};
+
 //////////////////////////////////////////////////////////////////////
 //
 //  MultiplayMgr constructor
@@ -343,9 +368,9 @@ namespace
 //////////////////////////////////////////////////////////////////////
 FGMultiplayMgr::FGMultiplayMgr() 
 {
-  mSocket        = 0;
   mInitialised   = false;
   mHaveServer    = false;
+  mListener = NULL;
 } // FGMultiplayMgr::FGMultiplayMgr()
 //////////////////////////////////////////////////////////////////////
 
@@ -356,7 +381,7 @@ FGMultiplayMgr::FGMultiplayMgr()
 //////////////////////////////////////////////////////////////////////
 FGMultiplayMgr::~FGMultiplayMgr() 
 {
-  Close();
+  
 } // FGMultiplayMgr::~FGMultiplayMgr()
 //////////////////////////////////////////////////////////////////////
 
@@ -375,22 +400,36 @@ FGMultiplayMgr::init (void)
     SG_LOG(SG_NETWORK, SG_WARN, "FGMultiplayMgr::init - already initialised");
     return;
   }
+  
+  fgSetBool("/sim/multiplay/online", false);
+  
   //////////////////////////////////////////////////
   //  Set members from property values
   //////////////////////////////////////////////////
   short rxPort = fgGetInt("/sim/multiplay/rxport");
   string rxAddress = fgGetString("/sim/multiplay/rxhost");
-  short txPort = fgGetInt("/sim/multiplay/txport");
+  short txPort = fgGetInt("/sim/multiplay/txport", 5000);
   string txAddress = fgGetString("/sim/multiplay/txhost");
+  
+  int hz = fgGetInt("/sim/multiplay/tx-rate-hz", 10);
+  if (hz < 1) {
+    hz = 10;
+  }
+  
+  mDt = 1.0 / hz;
+  mTimeUntilSend = 0.0;
+  
   mCallsign = fgGetString("/sim/multiplay/callsign");
-  if (txPort > 0 && !txAddress.empty()) {
+  if (!txAddress.empty()) {
     mServer.set(txAddress.c_str(), txPort);
     if (strncmp (mServer.getHost(), "0.0.0.0", 8) == 0) {
       mHaveServer = false;
-      SG_LOG(SG_NETWORK, SG_DEBUG,
+      SG_LOG(SG_NETWORK, SG_WARN,
         "FGMultiplayMgr - could not resolve '"
         << txAddress << "', Multiplayermode disabled");
+      return;
     } else {
+        SG_LOG(SG_NETWORK, SG_INFO, "have server");
       mHaveServer = true;
     }
     if (rxPort <= 0)
@@ -408,11 +447,10 @@ FGMultiplayMgr::init (void)
   SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-rxaddress="<<rxAddress );
   SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-rxport= "<<rxPort);
   SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-callsign= "<<mCallsign);
-  Close(); // Should Init be called twice, close Socket first
-           // A memory leak was reported here by valgrind
-  mSocket = new simgear::Socket();
+  
+  mSocket.reset(new simgear::Socket());
   if (!mSocket->open(false)) {
-    SG_LOG( SG_NETWORK, SG_DEBUG,
+    SG_LOG( SG_NETWORK, SG_WARN,
             "FGMultiplayMgr::init - Failed to create data socket" );
     return;
   }
@@ -424,6 +462,11 @@ FGMultiplayMgr::init (void)
     return;
   }
   
+  mPropertiesChanged = true;
+  mListener = new MPPropertyListener(this);
+  globals->get_props()->addChangeListener(mListener, false);
+  
+  fgSetBool("/sim/multiplay/online", true);
   mInitialised = true;
 } // FGMultiplayMgr::init()
 //////////////////////////////////////////////////////////////////////
@@ -435,19 +478,39 @@ FGMultiplayMgr::init (void)
 //
 //////////////////////////////////////////////////////////////////////
 void
-FGMultiplayMgr::Close (void) 
+FGMultiplayMgr::shutdown (void) 
 {
-  mMultiPlayerMap.clear();
-
-  if (mSocket) {
+  fgSetBool("/sim/multiplay/online", false);
+  
+  if (mSocket.get()) {
     mSocket->close();
-    delete mSocket;
-    mSocket = 0;
+    mSocket.reset(); 
+  }
+  
+  MultiPlayerMap::iterator it = mMultiPlayerMap.begin(),
+    end = mMultiPlayerMap.end();
+  for (; it != end; ++it) {
+    it->second->setDie(true);
   }
+  mMultiPlayerMap.clear();
+  
+  if (mListener) {
+    globals->get_props()->removeChangeListener(mListener);
+    delete mListener;
+    mListener = NULL;
+  }
+  
   mInitialised = false;
 } // FGMultiplayMgr::Close(void)
 //////////////////////////////////////////////////////////////////////
 
+void
+FGMultiplayMgr::reinit()
+{
+  shutdown();
+  init();
+}
+
 //////////////////////////////////////////////////////////////////////
 //
 //  Description: Sends the position data for the local position.
@@ -757,7 +820,7 @@ FGMultiplayMgr::SendTextMessage(const string &MsgText)
 //  
 //////////////////////////////////////////////////////////////////////
 void
-FGMultiplayMgr::update(double) 
+FGMultiplayMgr::update(double dt
 {
   if (!mInitialised)
     return;
@@ -765,6 +828,14 @@ FGMultiplayMgr::update(double)
   /// Just for expiry
   long stamp = SGTimeStamp::now().getSeconds();
 
+  //////////////////////////////////////////////////
+  //  Send if required
+  //////////////////////////////////////////////////
+  mTimeUntilSend -= dt;
+  if (mTimeUntilSend <= 0.0) {
+    Send();
+  }
+
   //////////////////////////////////////////////////
   //  Read the receive socket and process any data
   //////////////////////////////////////////////////
@@ -813,7 +884,7 @@ FGMultiplayMgr::update(double)
               << "message has invalid protocol number!" );
       break;
     }
-    if (MsgHdr->MsgLen != bytes) {
+    if (static_cast<ssize_t>(MsgHdr->MsgLen) != bytes) {
       SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - "
              << "message from " << MsgHdr->Callsign << " has invalid length!");
       break;
@@ -854,6 +925,140 @@ FGMultiplayMgr::update(double)
 } // FGMultiplayMgr::ProcessData(void)
 //////////////////////////////////////////////////////////////////////
 
+void
+FGMultiplayMgr::Send()
+{
+  using namespace simgear;
+  
+  findProperties();
+    
+  // smooth the send rate, by adjusting based on the 'remainder' time, which
+  // is how -ve mTimeUntilSend is. Watch for large values and ignore them,
+  // however.
+    if ((mTimeUntilSend < 0.0) && (fabs(mTimeUntilSend) < mDt)) {
+      mTimeUntilSend = mDt + mTimeUntilSend;
+    } else {
+      mTimeUntilSend = mDt;
+    }
+
+    double sim_time = globals->get_sim_time_sec();
+    static double lastTime = 0.0;
+    
+   // SG_LOG(SG_GENERAL, SG_INFO, "actual dt=" << sim_time - lastTime);
+    lastTime = sim_time;
+    
+    FlightProperties ifce;
+
+    // put together a motion info struct, you will get that later
+    // from FGInterface directly ...
+    FGExternalMotionData motionInfo;
+
+    // The current simulation time we need to update for,
+    // note that the simulation time is updated before calling all the
+    // update methods. Thus it contains the time intervals *end* time.
+    // The FDM is already run, so the states belong to that time.
+    motionInfo.time = sim_time;
+    motionInfo.lag = mDt;
+
+    // These are for now converted from lat/lon/alt and euler angles.
+    // But this should change in FGInterface ...
+    double lon = ifce.get_Longitude();
+    double lat = ifce.get_Latitude();
+    // first the aprioriate structure for the geodetic one
+    SGGeod geod = SGGeod::fromRadFt(lon, lat, ifce.get_Altitude());
+    // Convert to cartesion coordinate
+    motionInfo.position = SGVec3d::fromGeod(geod);
+    
+    // The quaternion rotating from the earth centered frame to the
+    // horizontal local frame
+    SGQuatf qEc2Hl = SGQuatf::fromLonLatRad((float)lon, (float)lat);
+    // The orientation wrt the horizontal local frame
+    float heading = ifce.get_Psi();
+    float pitch = ifce.get_Theta();
+    float roll = ifce.get_Phi();
+    SGQuatf hlOr = SGQuatf::fromYawPitchRoll(heading, pitch, roll);
+    // The orientation of the vehicle wrt the earth centered frame
+    motionInfo.orientation = qEc2Hl*hlOr;
+
+    if (!globals->get_subsystem("flight")->is_suspended()) {
+      // velocities
+      motionInfo.linearVel = SG_FEET_TO_METER*SGVec3f(ifce.get_uBody(),
+                                                      ifce.get_vBody(),
+                                                      ifce.get_wBody());
+      motionInfo.angularVel = SGVec3f(ifce.get_P_body(),
+                                      ifce.get_Q_body(),
+                                      ifce.get_R_body());
+      
+      // accels, set that to zero for now.
+      // Angular accelerations are missing from the interface anyway,
+      // linear accelerations are screwed up at least for JSBSim.
+//  motionInfo.linearAccel = SG_FEET_TO_METER*SGVec3f(ifce.get_U_dot_body(),
+//                                                    ifce.get_V_dot_body(),
+//                                                    ifce.get_W_dot_body());
+      motionInfo.linearAccel = SGVec3f::zeros();
+      motionInfo.angularAccel = SGVec3f::zeros();
+    } else {
+      // if the interface is suspendend, prevent the client from
+      // wild extrapolations
+      motionInfo.linearVel = SGVec3f::zeros();
+      motionInfo.angularVel = SGVec3f::zeros();
+      motionInfo.linearAccel = SGVec3f::zeros();
+      motionInfo.angularAccel = SGVec3f::zeros();
+    }
+
+    // now send the properties
+    PropertyMap::iterator it;
+    for (it = mPropertyMap.begin(); it != mPropertyMap.end(); ++it) {
+      FGPropertyData* pData = new FGPropertyData;
+      pData->id = it->first;
+      pData->type = it->second->getType();
+      
+      switch (pData->type) {
+        case props::INT:
+        case props::LONG:
+        case props::BOOL:
+          pData->int_value = it->second->getIntValue();
+          break;
+        case props::FLOAT:
+        case props::DOUBLE:
+          pData->float_value = it->second->getFloatValue();
+          break;
+        case props::STRING:
+        case props::UNSPECIFIED:
+          {
+            // FIXME: We assume unspecified are strings for the moment.
+
+            const char* cstr = it->second->getStringValue();
+            int len = strlen(cstr);
+            
+            if (len > 0)
+            {            
+              pData->string_value = new char[len + 1];
+              strcpy(pData->string_value, cstr);
+            }
+            else
+            {
+              // Size 0 - ignore
+              pData->string_value = 0;            
+            }
+
+            //cout << " Sending property " << pData->id << " " << pData->type << " " <<  pData->string_value << "\n";
+            break;        
+          }
+        default:
+          // FIXME Currently default to a float. 
+          //cout << "Unknown type when iterating through props: " << pData->type << "\n";
+          pData->float_value = it->second->getFloatValue();
+          break;
+      }
+      
+      motionInfo.properties.push_back(pData);
+    }
+
+    SendMyPosition(motionInfo);
+}
+
+
 //////////////////////////////////////////////////////////////////////
 //
 //  handle a position message
@@ -1101,3 +1306,29 @@ FGMultiplayMgr::getMultiplayer(const std::string& callsign)
   else
     return 0;
 }
+
+void
+FGMultiplayMgr::findProperties()
+{
+  if (!mPropertiesChanged) {
+    return;
+  }
+  
+  mPropertiesChanged = false;
+  
+  for (unsigned i = 0; i < numProperties; ++i) {
+      const char* name = sIdPropertyList[i].name;
+      SGPropertyNode* pNode = globals->get_props()->getNode(name);
+      if (!pNode) {
+        continue;
+      }
+      
+      int id = sIdPropertyList[i].id;
+      if (mPropertyMap.find(id) != mPropertyMap.end()) {
+        continue; // already activated
+      }
+      
+      mPropertyMap[id] = pNode;
+      SG_LOG(SG_NETWORK, SG_DEBUG, "activating MP property:" << pNode->getPath());
+    }
+}
index 8475c0ef125df219c672f690f1521daf4e373a5d..daae68b5747f51cbc87fd7705ea617a5438860ae 100644 (file)
 
 #define MULTIPLAYTXMGR_HID "$Id$"
 
-#include "mpmessages.hxx"
 
 #include <string>
 #include <vector>
 
 #include <simgear/compiler.h>
 #include <simgear/props/props.hxx>
-#include <Main/globals.hxx>
 #include <simgear/io/raw_socket.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 
-#include <AIModel/AIMultiplayer.hxx>
-
-struct FGExternalMotionInfo;
+struct FGExternalMotionData;
+class MPPropertyListener;
+struct T_MsgHdr;
+class FGAIMultiplayer;
 
 class FGMultiplayMgr : public SGSubsystem
 {
-public:
-
-  struct IdPropertyList {
-    unsigned id;
-    const char* name;
-    simgear::props::Type type;
-  };
-  static const IdPropertyList sIdPropertyList[];
-  static const unsigned numProperties;
-
-  static const IdPropertyList* findProperty(unsigned id);
-  
+public:  
   FGMultiplayMgr();
   ~FGMultiplayMgr();
   
   virtual void init(void);
   virtual void update(double dt);
   
-  void Close(void);
+  virtual void shutdown(void);
+  virtual void reinit();
+  
   // transmitter
-  void SendMyPosition(const FGExternalMotionData& motionInfo);
+  
   void SendTextMessage(const string &sMsgText);
   // receiver
   
 private:
+  friend class MPPropertyListener;
+  
+  void setPropertiesChanged()
+  {
+    mPropertiesChanged = true;
+  }
+  
+  void findProperties();
+  
+  void Send();
+  void SendMyPosition(const FGExternalMotionData& motionInfo);
+
   union MsgBuf;
   FGAIMultiplayer* addMultiplayer(const std::string& callsign,
                                   const std::string& modelName);
@@ -87,11 +89,22 @@ private:
   typedef std::map<std::string, SGSharedPtr<FGAIMultiplayer> > MultiPlayerMap;
   MultiPlayerMap mMultiPlayerMap;
 
-  simgear::Socket* mSocket;
+  std::auto_ptr<simgear::Socket> mSocket;
   simgear::IPAddress mServer;
   bool mHaveServer;
   bool mInitialised;
   std::string mCallsign;
+  
+  // Map between the property id's from the multiplayers network packets
+  // and the property nodes
+  typedef std::map<unsigned int, SGSharedPtr<SGPropertyNode> > PropertyMap;
+  PropertyMap mPropertyMap;
+  
+  bool mPropertiesChanged;
+  MPPropertyListener* mListener;
+  
+  double mDt; // reciprocal of /sim/multiplay/tx-rate-hz
+  double mTimeUntilSend;
 };
 
 #endif
index 1f42c68c77961b26842c294c6ee6b6cfd7f7c9ad..3f0e202c27967196914466a711522c18125e82fb 100644 (file)
@@ -15,7 +15,6 @@ set(SOURCES
        jpg-httpd.cxx
        jsclient.cxx
        lfsglass.cxx
-       multiplay.cxx
        native.cxx
        native_ctrls.cxx
        native_fdm.cxx
index 0935d3ca44d5bda04d279c2d14a2cdc4513f32af..e4ecc3b10173630bf8c23317918552d2a431a108 100644 (file)
@@ -9,8 +9,6 @@ else
 JPEG_SERVER =
 endif
 
-MPLAYER_AS = multiplay.cxx multiplay.hxx
-
 libNetwork_a_SOURCES = \
        protocol.cxx protocol.hxx \
        ATC-Main.cxx ATC-Main.hxx \
@@ -33,7 +31,6 @@ libNetwork_a_SOURCES = \
        net_ctrls.hxx net_fdm.hxx net_fdm_mini.hxx net_gui.hxx \
         nmea.cxx nmea.hxx \
         opengc.cxx opengc.hxx opengc_data.hxx \
-       $(MPLAYER_AS) \
        props.cxx props.hxx \
        pve.cxx pve.hxx \
        ray.cxx ray.hxx \
diff --git a/src/Network/multiplay.cxx b/src/Network/multiplay.cxx
deleted file mode 100644 (file)
index ddedcce..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-// multiplay.cxx -- protocol object for multiplay in Flightgear
-//
-// Written by Diarmuid Tyson, started February 2003.
-// diarmuid.tyson@airservicesaustralia.com
-//
-// With addtions by Vivian Meazza, January 2006
-//
-// Copyright (C) 2003  Airservices Australia
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <simgear/compiler.h>
-
-#include <cstring>
-#include <iostream>
-#include <map>
-#include <string>
-
-#include <simgear/debug/logstream.hxx>
-#include <simgear/math/SGMath.hxx>
-
-#include <FDM/flightProperties.hxx>
-#include <MultiPlayer/mpmessages.hxx>
-
-#include "multiplay.hxx"
-
-using std::string;
-
-
-// These constants are provided so that the ident command can list file versions.
-const char sFG_MULTIPLAY_BID[] = "$Id$";
-const char sFG_MULTIPLAY_HID[] = FG_MULTIPLAY_HID;
-
-typedef std::set<std::string> string_set;
-
-class MPPropertyListener : public SGPropertyChangeListener
-{
-public:
-  MPPropertyListener(FGMultiplay* mp) :
-    _multiplay(mp)
-  {
-  }
-
-  virtual void childAdded(SGPropertyNode*, SGPropertyNode*)
-  {
-    _multiplay->setPropertiesChanged();
-  }
-
-private:
-  FGMultiplay* _multiplay;
-};
-
-/******************************************************************
-* Name: FGMultiplay
-* Description: Constructor.  Initialises the protocol and stores
-* host and port information.
-******************************************************************/
-FGMultiplay::FGMultiplay (const string &dir, const int rate, const string &host, const int port) {
-
-  set_hz(rate);
-
-  set_direction(dir);
-
-  if (get_direction() == SG_IO_IN) {
-
-    fgSetInt("/sim/multiplay/rxport", port);
-    fgSetString("/sim/multiplay/rxhost", host.c_str());
-
-  } else if (get_direction() == SG_IO_OUT) {
-
-    fgSetInt("/sim/multiplay/txport", port);
-    fgSetString("/sim/multiplay/txhost", host.c_str());
-
-  }
-
-  mPropertiesChanged = true;
-}
-
-
-/******************************************************************
-* Name: ~FGMultiplay
-* Description: Destructor.
-******************************************************************/
-FGMultiplay::~FGMultiplay () {
-}
-
-
-/******************************************************************
-* Name: open
-* Description: Enables the protocol.
-******************************************************************/
-bool FGMultiplay::open() {
-
-    if ( is_enabled() ) {
-       SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
-               << "is already in use, ignoring" );
-       return false;
-    }
-
-    set_enabled(true);
-    
-    mPropertiesChanged = true;
-    
-    MPPropertyListener* pl = new MPPropertyListener(this);
-    globals->get_props()->addChangeListener(pl, false);
-    return is_enabled();
-}
-
-void FGMultiplay::findProperties()
-{
-  if (!mPropertiesChanged) {
-    return;
-  }
-  
-  mPropertiesChanged = false;
-  
-  for (unsigned i = 0; i < FGMultiplayMgr::numProperties; ++i) {
-      const char* name = FGMultiplayMgr::sIdPropertyList[i].name;
-      SGPropertyNode* pNode = globals->get_props()->getNode(name);
-      if (!pNode) {
-        continue;
-      }
-      
-      int id = FGMultiplayMgr::sIdPropertyList[i].id;
-      if (mPropertyMap.find(id) != mPropertyMap.end()) {
-        continue; // already activated
-      }
-      
-      mPropertyMap[id] = pNode;
-      SG_LOG(SG_NETWORK, SG_INFO, "activating MP property:" << pNode->getPath());
-    }
-
-}
-
-
-/******************************************************************
-* Name: process
-* Description: Prompts the multiplayer mgr to either send
-* or receive data over the network
-******************************************************************/
-bool FGMultiplay::process() {
-  using namespace simgear;
-  if (get_direction() == SG_IO_OUT) {
-    findProperties();
-    
-    // check if we have left initialization phase. That will not provide
-    // interresting data, also the freeze in simulation time hurts the
-    // multiplayer clients
-    double sim_time = globals->get_sim_time_sec();
-//     if (sim_time < 20)
-//       return true;
-
-    FlightProperties ifce;
-
-    // put together a motion info struct, you will get that later
-    // from FGInterface directly ...
-    FGExternalMotionData motionInfo;
-
-    // The current simulation time we need to update for,
-    // note that the simulation time is updated before calling all the
-    // update methods. Thus it contains the time intervals *end* time.
-    // The FDM is already run, so the states belong to that time.
-    motionInfo.time = sim_time;
-
-    // The typical lag will be the reciprocal of the output frequency
-    double hz = get_hz();
-    if (hz != 0) // I guess we can test a double for exact zero in this case
-      motionInfo.lag = 1/get_hz();
-    else
-      motionInfo.lag = 0.1; //??
-
-    // These are for now converted from lat/lon/alt and euler angles.
-    // But this should change in FGInterface ...
-    double lon = ifce.get_Longitude();
-    double lat = ifce.get_Latitude();
-    // first the aprioriate structure for the geodetic one
-    SGGeod geod = SGGeod::fromRadFt(lon, lat, ifce.get_Altitude());
-    // Convert to cartesion coordinate
-    motionInfo.position = SGVec3d::fromGeod(geod);
-    
-    // The quaternion rotating from the earth centered frame to the
-    // horizontal local frame
-    SGQuatf qEc2Hl = SGQuatf::fromLonLatRad((float)lon, (float)lat);
-    // The orientation wrt the horizontal local frame
-    float heading = ifce.get_Psi();
-    float pitch = ifce.get_Theta();
-    float roll = ifce.get_Phi();
-    SGQuatf hlOr = SGQuatf::fromYawPitchRoll(heading, pitch, roll);
-    // The orientation of the vehicle wrt the earth centered frame
-    motionInfo.orientation = qEc2Hl*hlOr;
-
-    if (!globals->get_subsystem("flight")->is_suspended()) {
-      // velocities
-      motionInfo.linearVel = SG_FEET_TO_METER*SGVec3f(ifce.get_uBody(),
-                                                      ifce.get_vBody(),
-                                                      ifce.get_wBody());
-      motionInfo.angularVel = SGVec3f(ifce.get_P_body(),
-                                      ifce.get_Q_body(),
-                                      ifce.get_R_body());
-      
-      // accels, set that to zero for now.
-      // Angular accelerations are missing from the interface anyway,
-      // linear accelerations are screwed up at least for JSBSim.
-//  motionInfo.linearAccel = SG_FEET_TO_METER*SGVec3f(ifce.get_U_dot_body(),
-//                                                    ifce.get_V_dot_body(),
-//                                                    ifce.get_W_dot_body());
-      motionInfo.linearAccel = SGVec3f::zeros();
-      motionInfo.angularAccel = SGVec3f::zeros();
-    } else {
-      // if the interface is suspendend, prevent the client from
-      // wild extrapolations
-      motionInfo.linearVel = SGVec3f::zeros();
-      motionInfo.angularVel = SGVec3f::zeros();
-      motionInfo.linearAccel = SGVec3f::zeros();
-      motionInfo.angularAccel = SGVec3f::zeros();
-    }
-
-    // now send the properties
-    PropertyMap::iterator it;
-    for (it = mPropertyMap.begin(); it != mPropertyMap.end(); ++it) {
-      FGPropertyData* pData = new FGPropertyData;
-      pData->id = it->first;
-      pData->type = it->second->getType();
-      
-      switch (pData->type) {
-        case props::INT:
-        case props::LONG:
-        case props::BOOL:
-          pData->int_value = it->second->getIntValue();
-          break;
-        case props::FLOAT:
-        case props::DOUBLE:
-          pData->float_value = it->second->getFloatValue();
-          break;
-        case props::STRING:
-        case props::UNSPECIFIED:
-          {
-            // FIXME: We assume unspecified are strings for the moment.
-
-            const char* cstr = it->second->getStringValue();
-            int len = strlen(cstr);
-            
-            if (len > 0)
-            {            
-              pData->string_value = new char[len + 1];
-              strcpy(pData->string_value, cstr);
-            }
-            else
-            {
-              // Size 0 - ignore
-              pData->string_value = 0;            
-            }
-
-            //cout << " Sending property " << pData->id << " " << pData->type << " " <<  pData->string_value << "\n";
-            break;        
-          }
-        default:
-          // FIXME Currently default to a float. 
-          //cout << "Unknown type when iterating through props: " << pData->type << "\n";
-          pData->float_value = it->second->getFloatValue();
-          break;
-      }
-      
-      motionInfo.properties.push_back(pData);
-    }
-
-    FGMultiplayMgr* mpmgr = (FGMultiplayMgr*) globals->get_subsystem("mp");
-    mpmgr->SendMyPosition(motionInfo);
-  }
-
-  return true;
-}
-
-
-/******************************************************************
-* Name: close
-* Description:  Closes the multiplayer mgrs to stop any further
-* network processing
-******************************************************************/
-bool FGMultiplay::close()
-{
-  mPropertyMap.clear();
-  
-  FGMultiplayMgr* mgr = (FGMultiplayMgr*) globals->get_subsystem("mp");
-
-  if (mgr == 0) {
-    return false;
-  }
-
-  if (get_direction() == SG_IO_IN) {
-
-    mgr->Close();
-
-  } else if (get_direction() == SG_IO_OUT) {
-
-    mgr->Close();
-
-  }
-
-  return true;
-}
-
diff --git a/src/Network/multiplay.hxx b/src/Network/multiplay.hxx
deleted file mode 100644 (file)
index f596ea0..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// multiplay.hxx -- protocol object for multiplay in Flightgear
-//
-// Written by Diarmuid Tyson, started February 2003.
-// diarmuid.tyson@airservicesaustralia.com
-//
-// With additions by Vivian Meazza, January 2006
-//
-// Copyright (C) 2003  Airservices Australia
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-
-#ifndef _FG_MULTIPLAY_HXX
-#define _FG_MULTIPLAY_HXX
-
-#define FG_MULTIPLAY_HID "$Id$"
-
-#include <simgear/compiler.h>
-
-#include <string>
-
-#include <simgear/props/props.hxx>
-
-#include <Main/globals.hxx>
-#include <Main/fg_props.hxx>
-#include <Model/acmodel.hxx>
-#include <MultiPlayer/multiplaymgr.hxx>
-
-#include "protocol.hxx"
-
-using std::string;
-
-
-/****************************************************************
-* @version $Id$
-*
-* Description: FGMultiplay is an FGProtocol object used as the basic
-* interface for the multiplayer code into FlightGears generic IO
-* subsystem.  It only implements the basic FGProtocol methods: open(),
-* process() and close().  It does not use Sim Gear's IO channels, as
-* the MultiplayMgrs creates their own sockets through plib.
-*
-* It will set up it's direction and rate protocol properties when
-* created.  Subsequent calls to process will prompt the
-* MultiplayMgr to either send or receive data over the network.
-*
-******************************************************************/
-
-class FGMultiplay : public FGProtocol {
-public:
-
-    /** Constructor */
-    FGMultiplay (const string &dir, const int rate, const string &host, const int port);
-
-    /** Destructor. */
-    ~FGMultiplay ();
-
-    /** Enables the FGMultiplay object. */
-    bool open();
-
-    /** Tells the multiplayer_mgr to send/receive data.
-    */
-    bool process();
-
-    /** Closes the multiplayer_mgr.
-    */
-    bool close();
-
-    void setPropertiesChanged()
-    {
-      mPropertiesChanged = true;
-    }
-private:
-  bool mPropertiesChanged;
-  
-  void findProperties();
-  
-  // Map between the property id's from the multiplayers network packets
-  // and the property nodes
-  typedef std::map<unsigned, SGSharedPtr<SGPropertyNode> > PropertyMap;
-  PropertyMap mPropertyMap;
-};
-
-
-#endif // _FG_MULTIPLAY_HXX