]> git.mxchange.org Git - flightgear.git/blobdiff - src/MultiPlayer/multiplaymgr.cxx
Interim windows build fix
[flightgear.git] / src / MultiPlayer / multiplaymgr.cxx
index 060f2863875c86ca5b506b5b0f7b36145f7328af..fda9a271567d4948e29d9065bb238ed446973bce 100644 (file)
 #include <algorithm>
 #include <cstring>
 #include <errno.h>
-#include <osg/Math>             // isNaN
 
 #include <simgear/misc/stdint.hxx>
 #include <simgear/timing/timestamp.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/props/props.hxx>
+#include <simgear/structure/commands.hxx>
 
 #include <AIModel/AIManager.hxx>
 #include <AIModel/AIMultiplayer.hxx>
 #include <Main/fg_props.hxx>
+#include <Network/RemoteXMLRequest.hxx>
+#include <Network/HTTPClient.hxx>
 #include "multiplaymgr.hxx"
 #include "mpmessages.hxx"
 #include <FDM/flightProperties.hxx>
@@ -54,11 +56,6 @@ using namespace std;
 #define MAX_PACKET_SIZE 1200
 #define MAX_TEXT_SIZE 128
 
-// These constants are provided so that the ident 
-// command can list file versions
-const char sMULTIPLAYMGR_BID[] = "$Id$";
-const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID;
-
 struct IdPropertyList {
   unsigned id;
   const char* name;
@@ -174,6 +171,11 @@ static const IdPropertyList sIdPropertyList[] = {
 
   {1400, "scenery/events", simgear::props::STRING},
 
+  {1500, "instrumentation/transponder/transmitted-id", simgear::props::INT},
+  {1501, "instrumentation/transponder/altitude", simgear::props::INT},
+  {1502, "instrumentation/transponder/ident", simgear::props::BOOL},
+  {1503, "instrumentation/transponder/inputs/mode", simgear::props::INT},
+
   {10001, "sim/multiplay/transmission-freq-hz",  simgear::props::STRING},
   {10002, "sim/multiplay/chat",  simgear::props::STRING},
 
@@ -302,7 +304,7 @@ namespace
         case props::DOUBLE:
           {
             float val = XDR_decode_float(*xdr);
-            if (osg::isNaN(val))
+            if (SGMisc<float>::isNaN(val))
               return false;
             xdr++;
             break;
@@ -364,6 +366,104 @@ private:
   FGMultiplayMgr* _multiplay;
 };
 
+//////////////////////////////////////////////////////////////////////
+//
+//  handle command "multiplayer-connect"
+//  args:
+//  server: servername to connect (mandatory)
+//  txport: outgoing port number (default: 5000)
+//  rxport: incoming port number (default: 5000)
+//////////////////////////////////////////////////////////////////////
+static bool do_multiplayer_connect(const SGPropertyNode * arg) {
+       FGMultiplayMgr * self = (FGMultiplayMgr*) globals->get_subsystem("mp");
+       if (!self) {
+               SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
+               return false;
+       }
+
+       string servername = arg->getStringValue("servername", "");
+       if (servername.empty()) {
+               SG_LOG(SG_NETWORK, SG_WARN,
+                               "do_multiplayer.connect: no server name given, command ignored.");
+               return false;
+       }
+       int port = arg->getIntValue("rxport", -1);
+       if (port > 0 && port <= 0xffff) {
+               fgSetInt("/sim/multiplay/rxport", port);
+       }
+
+       port = arg->getIntValue("txport", -1);
+       if (port > 0 && port <= 0xffff) {
+               fgSetInt("/sim/multiplay/txport", port);
+       }
+
+       servername = servername.substr(0, servername.find_first_of(' '));
+       fgSetString("/sim/multiplay/txhost", servername);
+       self->reinit();
+       return true;
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+//  handle command "multiplayer-disconnect"
+//  disconnect args:
+//  none
+//////////////////////////////////////////////////////////////////////
+static bool do_multiplayer_disconnect(const SGPropertyNode * arg) {
+       FGMultiplayMgr * self = (FGMultiplayMgr*) globals->get_subsystem("mp");
+       if (!self) {
+               SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
+               return false;
+       }
+
+       fgSetString("/sim/multiplay/txhost", "");
+       self->reinit();
+       return true;
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+//  handle command "multiplayer-refreshserverlist"
+//  refreshserverlist args:
+//  none
+//
+//////////////////////////////////////////////////////////////////////
+static bool do_multiplayer_refreshserverlist(const SGPropertyNode * arg) {
+       FGMultiplayMgr * self = (FGMultiplayMgr*) globals->get_subsystem("mp");
+       if (!self) {
+               SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
+               return false;
+       }
+
+       FGHTTPClient* http = static_cast<FGHTTPClient*>(globals->get_subsystem("http"));
+       if (!http) {
+               SG_LOG(SG_IO, SG_ALERT,
+                               "do_multiplayer.refreshserverlist: HTTP client not running");
+               return false;
+       }
+
+       string url(
+                       fgGetString("/sim/multiplay/serverlist-url",
+                                       "http://liveries.flightgear.org/mpstatus/mpservers.xml"));
+
+       if (url.empty()) {
+               SG_LOG(SG_IO, SG_ALERT,
+                               "do_multiplayer.refreshserverlist: no URL given");
+               return false;
+       }
+
+       SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
+       SGPropertyNode *completeNode = fgGetNode("/sim/multiplay/got-servers", true);
+       SGPropertyNode *failureNode = fgGetNode("/sim/multiplay/get-servers-failure", true);
+       RemoteXMLRequest* req = new RemoteXMLRequest(url, targetnode);
+       req->setCompletionProp(completeNode);
+       req->setFailedProp(failureNode);
+       completeNode->setBoolValue(false);
+       failureNode->setBoolValue(false);
+       http->makeRequest(req);
+       return true;
+}
+
 //////////////////////////////////////////////////////////////////////
 //
 //  MultiplayMgr constructor
@@ -374,6 +474,9 @@ FGMultiplayMgr::FGMultiplayMgr()
   mInitialised   = false;
   mHaveServer    = false;
   mListener = NULL;
+  globals->get_commands()->addCommand("multiplayer-connect", do_multiplayer_connect);
+  globals->get_commands()->addCommand("multiplayer-disconnect", do_multiplayer_disconnect);
+  globals->get_commands()->addCommand("multiplayer-refreshserverlist", do_multiplayer_refreshserverlist);
 } // FGMultiplayMgr::FGMultiplayMgr()
 //////////////////////////////////////////////////////////////////////
 
@@ -384,7 +487,9 @@ FGMultiplayMgr::FGMultiplayMgr()
 //////////////////////////////////////////////////////////////////////
 FGMultiplayMgr::~FGMultiplayMgr() 
 {
-  
+   globals->get_commands()->removeCommand("multiplayer-connect");
+   globals->get_commands()->removeCommand("multiplayer-disconnect");
+   globals->get_commands()->removeCommand("multiplayer-refreshserverlist");
 } // FGMultiplayMgr::~FGMultiplayMgr()
 //////////////////////////////////////////////////////////////////////
 
@@ -403,9 +508,11 @@ FGMultiplayMgr::init (void)
     SG_LOG(SG_NETWORK, SG_WARN, "FGMultiplayMgr::init - already initialised");
     return;
   }
-  
-  fgSetBool("/sim/multiplay/online", false);
-  
+
+  SGPropertyNode* propOnline = fgGetNode("/sim/multiplay/online", true);
+  propOnline->setBoolValue(false);
+  propOnline->setAttribute(SGPropertyNode::PRESERVE, true);
+
   //////////////////////////////////////////////////
   //  Set members from property values
   //////////////////////////////////////////////////
@@ -423,24 +530,30 @@ FGMultiplayMgr::init (void)
   mTimeUntilSend = 0.0;
   
   mCallsign = fgGetString("/sim/multiplay/callsign");
+  fgGetNode("/sim/multiplay/callsign", true)->setAttribute(SGPropertyNode::PRESERVE, true);
+    
   if ((!txAddress.empty()) && (txAddress!="0")) {
     mServer.set(txAddress.c_str(), txPort);
     if (strncmp (mServer.getHost(), "0.0.0.0", 8) == 0) {
       mHaveServer = false;
       SG_LOG(SG_NETWORK, SG_ALERT,
-        "FGMultiplayMgr - Could not resolve '"
-        << txAddress << "'. Multiplayer mode disabled.");
+        "Cannot enable multiplayer mode: resolving MP server address '"
+        << txAddress << "' failed.");
       return;
     } else {
-        SG_LOG(SG_NETWORK, SG_INFO, "FGMultiplayMgr - have server");
+      SG_LOG(SG_NETWORK, SG_INFO, "FGMultiplayMgr - have server");
       mHaveServer = true;
     }
     if (rxPort <= 0)
       rxPort = txPort;
+  } else {
+    SG_LOG(SG_NETWORK, SG_INFO, "FGMultiplayMgr - multiplayer mode disabled (no MP server specificed).");
+    return;
   }
+
   if (rxPort <= 0) {
     SG_LOG(SG_NETWORK, SG_ALERT,
-      "FGMultiplayMgr - No receiver port. Multiplayer mode disabled.");
+      "Cannot enable multiplayer mode: No receiver port specified.");
     return;
   }
   if (mCallsign.empty())
@@ -453,14 +566,14 @@ FGMultiplayMgr::init (void)
   
   mSocket.reset(new simgear::Socket());
   if (!mSocket->open(false)) {
-    SG_LOG( SG_NETWORK, SG_WARN,
-            "FGMultiplayMgr - Failed to create data socket." );
+    SG_LOG( SG_NETWORK, SG_ALERT,
+            "Cannot enable multiplayer mode: creating data socket failed." );
     return;
   }
   mSocket->setBlocking(false);
   if (mSocket->bind(rxAddress.c_str(), rxPort) != 0) {
     SG_LOG( SG_NETWORK, SG_ALERT,
-            "FGMultiplayMgr - Failed to bind receive socket. Multiplayer mode disabled. "
+            "Cannot enable multiplayer mode: binding receive socket failed. "
             << strerror(errno) << "(errno " << errno << ")");
     return;
   }
@@ -471,6 +584,14 @@ FGMultiplayMgr::init (void)
   
   fgSetBool("/sim/multiplay/online", true);
   mInitialised = true;
+
+  SG_LOG(SG_NETWORK, SG_ALERT, "Multiplayer mode active!");
+
+  if (!fgGetBool("/sim/ai/enabled"))
+  {
+      // multiplayer depends on AI module
+      fgSetBool("/sim/ai/enabled", true);
+  }
 } // FGMultiplayMgr::init()
 //////////////////////////////////////////////////////////////////////
 
@@ -597,8 +718,8 @@ FGMultiplayMgr::isSane(const FGExternalMotionData& motionInfo)
 {
     // check for corrupted data (NaNs)
     bool isCorrupted = false;
-    isCorrupted |= ((osg::isNaN(motionInfo.time           )) ||
-                    (osg::isNaN(motionInfo.lag            )) ||
+    isCorrupted |= ((SGMisc<double>::isNaN(motionInfo.time           )) ||
+                    (SGMisc<double>::isNaN(motionInfo.lag            )) ||
                     (osg::isNaN(motionInfo.orientation(3) )));
     for (unsigned i = 0; (i < 3)&&(!isCorrupted); ++i)
     {
@@ -662,15 +783,30 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo)
       motionInfo.orientation.getAngleAxis(angleAxis);
       for (unsigned i = 0 ; i < 3; ++i)
         PosMsg->orientation[i] = XDR_encode_float (angleAxis(i));
-      for (unsigned i = 0 ; i < 3; ++i)
-        PosMsg->linearVel[i] = XDR_encode_float (motionInfo.linearVel(i));
-      for (unsigned i = 0 ; i < 3; ++i)
-        PosMsg->angularVel[i] = XDR_encode_float (motionInfo.angularVel(i));
-      for (unsigned i = 0 ; i < 3; ++i)
-        PosMsg->linearAccel[i] = XDR_encode_float (motionInfo.linearAccel(i));
-      for (unsigned i = 0 ; i < 3; ++i)
-        PosMsg->angularAccel[i] = XDR_encode_float (motionInfo.angularAccel(i));
-
+      if (fgGetBool("/sim/crashed",true))
+      {
+        for (unsigned i = 0 ; i < 3; ++i)
+        {
+          // no speed or acceleration sent when crashed, for better mp patch
+          PosMsg->linearVel[i] = XDR_encode_float (0.0);
+          PosMsg->angularVel[i] = XDR_encode_float (0.0);
+          PosMsg->linearAccel[i] = XDR_encode_float (0.0);
+          PosMsg->angularAccel[i] = XDR_encode_float (0.0);
+        }
+      }
+      else
+      {
+        //including speed up time in velocity and acceleration
+        double timeAccel = fgGetDouble("/sim/speed-up");
+        for (unsigned i = 0 ; i < 3; ++i)
+          PosMsg->linearVel[i] = XDR_encode_float (motionInfo.linearVel(i) * timeAccel);
+        for (unsigned i = 0 ; i < 3; ++i)
+          PosMsg->angularVel[i] = XDR_encode_float (motionInfo.angularVel(i) * timeAccel);
+        for (unsigned i = 0 ; i < 3; ++i)
+          PosMsg->linearAccel[i] = XDR_encode_float (motionInfo.linearAccel(i) * timeAccel * timeAccel);
+        for (unsigned i = 0 ; i < 3; ++i)
+          PosMsg->angularAccel[i] = XDR_encode_float (motionInfo.angularAccel(i) * timeAccel * timeAccel);
+      }
       xdr_data_t* ptr = msgBuf.properties();
       std::vector<FGPropertyData*>::const_iterator it;
       it = motionInfo.properties.begin();
@@ -963,10 +1099,10 @@ FGMultiplayMgr::Send()
     }
 
     double sim_time = globals->get_sim_time_sec();
-    static double lastTime = 0.0;
+//    static double lastTime = 0.0;
     
    // SG_LOG(SG_GENERAL, SG_INFO, "actual dt=" << sim_time - lastTime);
-    lastTime = sim_time;
+//    lastTime = sim_time;
     
     FlightProperties ifce;
 
@@ -1307,7 +1443,7 @@ FGMultiplayMgr::addMultiplayer(const std::string& callsign,
   mp->setCallSign(callsign);
   mMultiPlayerMap[callsign] = mp;
 
-  FGAIManager *aiMgr = (FGAIManager*)globals->get_subsystem("ai_model");
+  FGAIManager *aiMgr = (FGAIManager*)globals->get_subsystem("ai-model");
   if (aiMgr) {
     aiMgr->attach(mp);