This is mainly an intermediate patch. I've restructured the network code.
#include <Traffic/TrafficMgr.hxx>
#ifdef FG_MPLAYER_AS
-#include <MultiPlayer/multiplaytxmgr.hxx>
-#include <MultiPlayer/multiplayrxmgr.hxx>
+#include <MultiPlayer/multiplaymgr.hpp>
#endif
#include <Environment/environment_mgr.hxx>
// Initialize multiplayer subsystem
////////////////////////////////////////////////////////////////////
- globals->set_multiplayer_tx_mgr(new FGMultiplayTxMgr);
- globals->get_multiplayer_tx_mgr()->init();
-
- globals->set_multiplayer_rx_mgr(new FGMultiplayRxMgr);
- globals->get_multiplayer_rx_mgr()->init();
+ globals->set_multiplayer_mgr(new FGMultiplayMgr);
+ globals->get_multiplayer_mgr()->init();
#endif
////////////////////////////////////////////////////////////////////////
class FGRouteMgr;
class FGScenery;
#ifdef FG_MPLAYER_AS
-class FGMultiplayRxMgr;
-class FGMultiplayTxMgr;
+class FGMultiplayMgr;
#endif
class FGPanel;
class FGTileMgr;
#ifdef FG_MPLAYER_AS
//Mulitplayer managers
- FGMultiplayTxMgr *multiplayer_tx_mgr;
-
- FGMultiplayRxMgr *multiplayer_rx_mgr;
+ FGMultiplayMgr *multiplayer_mgr;
#endif
public:
}
#ifdef FG_MPLAYER_AS
- inline FGMultiplayTxMgr *get_multiplayer_tx_mgr () { return multiplayer_tx_mgr; }
+ inline FGMultiplayMgr *get_multiplayer_mgr () { return multiplayer_mgr; }
- inline void set_multiplayer_tx_mgr (FGMultiplayTxMgr * mgr)
+ inline void set_multiplayer_mgr (FGMultiplayMgr * mgr)
{
- multiplayer_tx_mgr = mgr;
+ multiplayer_mgr = mgr;
}
- inline FGMultiplayRxMgr *get_multiplayer_rx_mgr () { return multiplayer_rx_mgr; }
-
- inline void set_multiplayer_rx_mgr (FGMultiplayRxMgr * mgr)
- {
- multiplayer_rx_mgr = mgr;
- }
#endif
inline string_list *get_channel_options_list () {
#include <GUI/new_gui.hxx>
#ifdef FG_MPLAYER_AS
-#include <MultiPlayer/multiplaytxmgr.hxx>
-#include <MultiPlayer/multiplayrxmgr.hxx>
+#include <MultiPlayer/multiplaymgr.hpp>
#endif
#ifdef FG_MPLAYER_AS
// Update any multiplayer models
- globals->get_multiplayer_rx_mgr()->Update();
+ globals->get_multiplayer_mgr()->Update();
#endif
// Run flight model
noinst_LIBRARIES = libMultiPlayer.a
-libMultiPlayer_a_SOURCES = multiplayrxmgr.cxx multiplayrxmgr.hxx multiplaytxmgr.cxx multiplaytxmgr.hxx mpplayer.cxx mpplayer.hxx mpmessages.hxx tiny_xdr.cpp tiny_xdr.hpp
+libMultiPlayer_a_SOURCES = multiplaymgr.cpp multiplaymgr.hpp mpplayer.cxx mpplayer.hxx mpmessages.hxx tiny_xdr.cpp tiny_xdr.hpp
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
xdr_data_t Magic; // Magic Value
xdr_data_t Version; // Protocoll version
xdr_data_t MsgId; // Message identifier
- xdr_data_t iMsgLen; // absolue length of message
- xdr_data_t lReplyAddress; // (player's receiver address
- xdr_data_t iReplyPort; // player's receiver port
- char sCallsign[MAX_CALLSIGN_LEN]; // Callsign used by the player
+ xdr_data_t MsgLen; // absolue length of message
+ xdr_data_t ReplyAddress; // (player's receiver address
+ xdr_data_t ReplyPort; // player's receiver port
+ char Callsign[MAX_CALLSIGN_LEN]; // Callsign used by the player
};
// Chat message
class T_ChatMsg {
public:
- char sText[MAX_CHAT_MSG_LEN]; // Text of chat message
+ char Text[MAX_CHAT_MSG_LEN]; // Text of chat message
};
// Position message
class T_PositionMsg {
public:
- char sModel[MAX_MODEL_NAME_LEN]; // Name of the aircraft model
+ char Model[MAX_MODEL_NAME_LEN]; // Name of the aircraft model
xdrPosition PlayerPosition; // players position
xdrOrientation PlayerOrientation; // players orientation
};
+//////////////////////////////////////////////////////////////////////
+//
// mpplayer.cxx -- routines for a player within a multiplayer Flightgear
//
// Written by Duncan McCreanor, started February 2003.
// duncan.mccreanor@airservicesaustralia.com
//
// Copyright (C) 2003 Airservices Australia
+// Copyright (C) 2005 Oliver Schroeder
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
+//////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
#include <config.h>
#include <stdlib.h>
#if !(defined(_MSC_VER) || defined(__MINGW32__))
-# include <netdb.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
#endif
#include <plib/netSocket.h>
#include <plib/sg.h>
const char sMPPLAYER_BID[] = "$Id$";
const char sMPPLAYER_HID[] = MPPLAYER_HID;
-
-/******************************************************************
-* Name: MPPlayer
-* Description: Constructor.
-******************************************************************/
-MPPlayer::MPPlayer() {
-
- // Initialise private members
- m_bInitialised = false;
- m_LastUpdate = 0;
+//////////////////////////////////////////////////////////////////////
+//
+// constructor
+//
+//////////////////////////////////////////////////////////////////////
+MPPlayer::MPPlayer()
+{
+ m_Initialised = false;
+ m_LastUpdate = 0;
+ m_Callsign = "none";
m_PlayerAddress.set("localhost", 0);
- m_sCallsign = "none";
-
-
-}
-
+} // MPPlayer::MPPlayer()
+//////////////////////////////////////////////////////////////////////
/******************************************************************
* Name: ~MPPlayer
* Description: Destructor.
******************************************************************/
-MPPlayer::~MPPlayer() {
-
+MPPlayer::~MPPlayer()
+{
Close();
-
}
-
/******************************************************************
* Name: Open
* Description: Initialises class.
******************************************************************/
-bool MPPlayer::Open(const string &sAddress, const int &iPort, const string &sCallsign, const string &sModelName, bool bLocalPlayer) {
-
- bool bSuccess = true;
-
- if (!m_bInitialised) {
-
- m_PlayerAddress.set(sAddress.c_str(), iPort);
- m_sCallsign = sCallsign;
- m_sModelName = sModelName;
- m_bLocalPlayer = bLocalPlayer;
- SG_LOG( SG_NETWORK, SG_ALERT, "Initialising " << m_sCallsign
- << " using '" << m_sModelName << "'" );
-
+bool
+MPPlayer::Open
+ (
+ const string &Address,
+ const int &Port,
+ const string &Callsign,
+ const string &ModelName,
+ bool LocalPlayer
+ )
+{
+ bool Success = true;
+
+ if (!m_Initialised)
+ {
+ m_PlayerAddress.set(Address.c_str(), Port);
+ m_Callsign = Callsign;
+ m_ModelName = ModelName;
+ m_LocalPlayer = LocalPlayer;
+ SG_LOG( SG_NETWORK, SG_ALERT, "Initialising " << m_Callsign
+ << " using '" << m_ModelName << "'" );
// If the player is remote then load the model
- if (!bLocalPlayer) {
+ if (!LocalPlayer)
+ {
try {
LoadModel();
} catch (...) {
- SG_LOG( SG_NETWORK, SG_ALERT, "Failed to load remote model '" << sModelName << "'." );
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "Failed to load remote model '" << ModelName << "'." );
return false;
}
}
-
- m_bInitialised = bSuccess;
-
- } else {
- SG_LOG( SG_NETWORK, SG_ALERT, "MPPlayer::Open - Attempt to open an already open player connection." );
- bSuccess = false;
+ m_Initialised = Success;
+ }
+ else
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT, "MPPlayer::Open - "
+ << "Attempt to open an already opened player connection." );
+ Success = false;
}
-
-
/* Return true if open succeeds */
- return bSuccess;
-
+ return Success;
}
-
/******************************************************************
* Name: Close
* Description: Resets the object.
******************************************************************/
-void MPPlayer::Close(void) {
-
+void
+MPPlayer::Close(void)
+{
// Remove the model from the game
- if (m_bInitialised && !m_bLocalPlayer) {
-
- // Disconnect the model from the transform, then the transform from the scene.
+ if (m_Initialised && !m_LocalPlayer)
+ {
+ // Disconnect the model from the transform,
+ // then the transform from the scene.
m_ModelTrans->removeKid(m_Model);
globals->get_scenery()->unregister_placement_transform(m_ModelTrans);
globals->get_scenery()->get_aircraft_branch()->removeKid( m_ModelTrans);
-
// Flush the model loader so that it erases the model from its list of
// models.
-// globals->get_model_lib()->flush1();
-
+ // globals->get_model_lib()->flush1();
// Assume that plib/ssg deletes the model and transform as their
// refcounts should be zero.
-
}
-
- m_bInitialised = false;
- m_bUpdated = false;
- m_LastUpdate = 0;
- m_sCallsign = "none";
-
+ m_Initialised = false;
+ m_Updated = false;
+ m_LastUpdate = 0;
+ m_Callsign = "none";
}
-
/******************************************************************
* Name: SetPosition
* Description: Updates position data held for this player and resets
* the last update time.
******************************************************************/
-void MPPlayer::SetPosition(const sgQuat PlayerOrientation,
- const sgdVec3 PlayerPosition) {
-
+void
+MPPlayer::SetPosition
+ (
+ const sgQuat PlayerOrientation,
+ const sgdVec3 PlayerPosition
+ )
+{
// Save the position matrix and update time
- if (m_bInitialised) {
+ if (m_Initialised)
+ {
sgdCopyVec3(m_ModelPosition, PlayerPosition);
sgCopyVec4(m_ModelOrientation, PlayerOrientation);
time(&m_LastUpdate);
- m_bUpdated = true;
+ m_Updated = true;
}
-
}
-
/******************************************************************
* Name: Draw
* Description: Updates the position for the player's model
* The state of the player's data is returned.
******************************************************************/
-MPPlayer::TPlayerDataState MPPlayer::Draw(void) {
-
+MPPlayer::TPlayerDataState
+MPPlayer::Draw (void)
+{
MPPlayer::TPlayerDataState eResult = PLAYER_DATA_NOT_AVAILABLE;
-
- if (m_bInitialised && !m_bLocalPlayer) {
- if ((time(NULL) - m_LastUpdate < TIME_TO_LIVE)) {
+ if (m_Initialised && !m_LocalPlayer)
+ {
+ if ((time(NULL) - m_LastUpdate < TIME_TO_LIVE))
+ {
// Peform an update if it has changed since the last update
- if (m_bUpdated) {
-
+ if (m_Updated)
+ {
// Transform and update player model
sgMat4 orMat;
sgMakeIdentMat4(orMat);
sgQuatToMatrix(orMat, m_ModelOrientation);
m_ModelTrans->setTransform(m_ModelPosition, orMat);
-
eResult = PLAYER_DATA_AVAILABLE;
-
// Clear the updated flag so that the position data
// is only available if it has changed
- m_bUpdated = false;
+ m_Updated = false;
}
-
- // Data has not been updated for some time.
- } else {
+ }
+ else
+ { // Data has not been updated for some time.
eResult = PLAYER_DATA_EXPIRED;
}
-
}
-
return eResult;
-
}
-
/******************************************************************
* Name: Callsign
* Description: Returns the player's callsign.
******************************************************************/
-string MPPlayer::Callsign(void) const {
-
- return m_sCallsign;
-
+string
+MPPlayer::Callsign(void) const
+{
+ return m_Callsign;
}
-
/******************************************************************
* Name: CompareCallsign
* Description: Returns true if the player's callsign matches
* the given callsign.
******************************************************************/
-bool MPPlayer::CompareCallsign(const char *sCallsign) const {
-
- return (m_sCallsign == sCallsign);
-
+bool
+MPPlayer::CompareCallsign(const char *Callsign) const
+{
+ return (m_Callsign == Callsign);
}
-
/******************************************************************
* Name: LoadModel
* Description: Loads the player's aircraft model.
******************************************************************/
-void MPPlayer::LoadModel(void) {
-
-
+void
+MPPlayer::LoadModel (void)
+{
m_ModelTrans = new ssgPlacementTransform;
-
// Load the model
m_Model = globals->get_model_lib()->load_model( globals->get_fg_root(),
- m_sModelName,
- globals->get_props(),
- globals->get_sim_time_sec() );
+ m_ModelName, globals->get_props(), globals->get_sim_time_sec() );
m_Model->clrTraversalMaskBits( SSGTRAV_HOT );
-
// Add model to transform
m_ModelTrans->addKid( m_Model );
-
// Place on scene under aircraft branch
globals->get_scenery()->get_aircraft_branch()->addKid( m_ModelTrans );
globals->get_scenery()->register_placement_transform( m_ModelTrans);
-
-
}
-
/******************************************************************
* Name: FillPosMsg
* Description: Populates the header and data for a position message.
******************************************************************/
-void MPPlayer::FillPosMsg(T_MsgHdr *MsgHdr, T_PositionMsg *PosMsg) {
-
+void
+MPPlayer::FillPosMsg
+ (
+ T_MsgHdr *MsgHdr,
+ T_PositionMsg *PosMsg
+ )
+{
FillMsgHdr(MsgHdr, POS_DATA_ID);
-
- strncpy(PosMsg->sModel, m_sModelName.c_str(), MAX_MODEL_NAME_LEN);
- PosMsg->sModel[MAX_MODEL_NAME_LEN - 1] = '\0';
- /*
- sgdCopyVec3(PosMsg->PlayerPosition, m_ModelPosition);
- sgCopyQuat(PosMsg->PlayerOrientation, m_ModelOrientation);
- */
+ strncpy(PosMsg->Model, m_ModelName.c_str(), MAX_MODEL_NAME_LEN);
+ PosMsg->Model[MAX_MODEL_NAME_LEN - 1] = '\0';
PosMsg->PlayerPosition[0] = XDR_encode_double (m_ModelPosition[0]);
PosMsg->PlayerPosition[1] = XDR_encode_double (m_ModelPosition[1]);
PosMsg->PlayerPosition[2] = XDR_encode_double (m_ModelPosition[2]);
PosMsg->PlayerOrientation[3] = XDR_encode_float (m_ModelOrientation[3]);
}
-
/******************************************************************
* Name: FillMsgHdr
* Description: Populates the header of a multiplayer message.
******************************************************************/
-void MPPlayer::FillMsgHdr(T_MsgHdr *MsgHdr, const int iMsgId) {
-
+void
+MPPlayer::FillMsgHdr
+ (
+ T_MsgHdr *MsgHdr,
+ const int MsgId
+ )
+{
struct in_addr address;
uint32_t len;
- switch (iMsgId) {
+ switch (MsgId)
+ {
case CHAT_MSG_ID:
len = sizeof(T_MsgHdr) + sizeof(T_ChatMsg);
break;
}
MsgHdr->Magic = XDR_encode_uint32 (MSG_MAGIC);
MsgHdr->Version = XDR_encode_uint32 (PROTO_VER);
- MsgHdr->MsgId = XDR_encode_uint32 (iMsgId);
- MsgHdr->iMsgLen = XDR_encode_uint32 (len);
+ MsgHdr->MsgId = XDR_encode_uint32 (MsgId);
+ MsgHdr->MsgLen = XDR_encode_uint32 (len);
// inet_addr returns address in network byte order
// no need to encode it
- MsgHdr->lReplyAddress = inet_addr( m_PlayerAddress.getHost() );
- MsgHdr->iReplyPort = XDR_encode_uint32 (m_PlayerAddress.getPort());
-
- strncpy(MsgHdr->sCallsign, m_sCallsign.c_str(), MAX_CALLSIGN_LEN);
- MsgHdr->sCallsign[MAX_CALLSIGN_LEN - 1] = '\0';
-
+ MsgHdr->ReplyAddress = inet_addr( m_PlayerAddress.getHost() );
+ MsgHdr->ReplyPort = XDR_encode_uint32 (m_PlayerAddress.getPort());
+ strncpy(MsgHdr->Callsign, m_Callsign.c_str(), MAX_CALLSIGN_LEN);
+ MsgHdr->Callsign[MAX_CALLSIGN_LEN - 1] = '\0';
}
#endif // FG_MPLAYER_AS
// Number of seconds before a player is consider to be lost
#define TIME_TO_LIVE 10
-
class ssgEntity;
class ssgPlacementTransform;
-
-class MPPlayer {
+class MPPlayer
+{
public:
-
- /** Constructor */
MPPlayer();
-
- /** Destructor. */
~MPPlayer();
-
/** Enumeration of the states for the player's data */
- enum PlayerDataState {PLAYER_DATA_NOT_AVAILABLE = 0, PLAYER_DATA_AVAILABLE, PLAYER_DATA_EXPIRED};
-
+ enum PlayerDataState
+ {
+ PLAYER_DATA_NOT_AVAILABLE = 0,
+ PLAYER_DATA_AVAILABLE,
+ PLAYER_DATA_EXPIRED
+ };
/** Player data state */
typedef enum PlayerDataState TPlayerDataState;
-
/** Initialises the class.
* @param sIP IP address or host name for sending data to the player
* @param sPort Port number for sending data to the player
* @param bLocalPlayer True if this player is the local player, else false
* @return True if class opens successfully, else false
*/
- bool Open(const string &sIP, const int &iPort, const string &sCallsign,
- const string &sModelName, const bool bLocalPlayer);
-
+ bool Open(const string &IP, const int &Port, const string &Callsign,
+ const string &ModelName, const bool LocalPlayer);
/** Closes the player connection */
void Close(void);
-
/** Sets the positioning matrix held for this player
* @param PlayerPosMat4 Matrix for positioning player's aircraft
*/
void SetPosition(const sgQuat PlayerOrientation,
const sgdVec3 PlayerPosition);
-
/** Transform and place model for player
*/
TPlayerDataState Draw(void);
-
/** Returns the callsign for the player
* @return Aircraft's callsign
*/
string Callsign(void) const;
-
/** Compares the player's callsign with the given callsign
* @param sCallsign Callsign to compare
* @return True if callsign matches
*/
- bool CompareCallsign(const char *sCallsign) const;
-
+ bool CompareCallsign(const char *Callsign) const;
/** Populates a position message for the player
* @param MsgHdr Header to be populated
* @param PosMsg Position message to be populated
*/
void FillPosMsg(T_MsgHdr *MsgHdr, T_PositionMsg *PosMsg);
-
/** Populates a mesage header with information for the player
* @param MsgHdr Header to be populated
* @param iMsgId Message type identifier to insert into header
*/
void FillMsgHdr(T_MsgHdr *MsgHdr, const int iMsgId);
-
-
private:
-
- /** Loads the model of the aircraft */
- void LoadModel(void);
-
- /** True if object is initialised */
- bool m_bInitialised;
-
- /** Position of the player's aircraft wrt the earth fixed global system */
- sgdVec3 m_ModelPosition;
-
- /** Orientation the player's aircraft wrt the earth fixed global system */
- sgQuat m_ModelOrientation;
-
- /** Used to remove player if no activity */
- time_t m_LastUpdate;
-
- /** Set when the player data is updated and cleared when read */
- bool m_bUpdated;
-
- /** Player's callsign */
- string m_sCallsign;
-
- /** Aircraft model name for player */
- string m_sModelName;
-
- /** The player's loaded model */
- ssgEntity *m_Model;
-
- /** Model transform */
- ssgPlacementTransform *m_ModelTrans;
-
- /** True if this player is the local player */
- bool m_bLocalPlayer;
-
- /** Address information for the player */
- netAddress m_PlayerAddress;
-
+ void LoadModel(void); // Loads the model of the aircraft
+ bool m_Initialised; // True if object is initialised
+ sgdVec3 m_ModelPosition; // players global position on earth
+ sgQuat m_ModelOrientation; // players global orientation
+ time_t m_LastUpdate; // last time update data received
+ bool m_Updated; // Set when the player data is updated
+ string m_Callsign; // players callsign
+ bool m_LocalPlayer; // true if player is the local player
+ string m_ModelName; // Aircraft model name for player
+ ssgEntity *m_Model; // The player's loaded model
+ netAddress m_PlayerAddress; // Address information for the player
+ ssgPlacementTransform *m_ModelTrans; // Model transform
};
#endif
--- /dev/null
+//////////////////////////////////////////////////////////////////////
+//
+// multiplaymgr.hpp
+//
+// Written by Duncan McCreanor, started February 2003.
+// duncan.mccreanor@airservicesaustralia.com
+//
+// Copyright (C) 2003 Airservices Australia
+// Copyright (C) 2005 Oliver Schroeder
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+//
+//////////////////////////////////////////////////////////////////////
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef FG_MPLAYER_AS
+
+#include <sys/types.h>
+#if !(defined(_MSC_VER) || defined(__MINGW32__))
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+#endif
+#include <plib/netSocket.h>
+#include <stdlib.h>
+#include <simgear/debug/logstream.hxx>
+#include <Main/fg_props.hxx>
+#include "multiplaymgr.hpp"
+#include "mpmessages.hxx"
+#include "mpplayer.hxx"
+#define MAX_PACKET_SIZE 1024
+
+// These constants are provided so that the ident
+// command can list file versions
+const char sMULTIPLAYMGR_BID[] =
+ "$Id$";
+const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID;
+
+//////////////////////////////////////////////////////////////////////
+//
+// MultiplayMgr constructor
+//
+//////////////////////////////////////////////////////////////////////
+FGMultiplayMgr::FGMultiplayMgr()
+{
+ m_Initialised = false;
+ m_LocalPlayer = NULL;
+ m_RxAddress = "0";
+ m_RxPort = 0;
+ m_Initialised = false;
+ m_HaveServer = false;
+} // FGMultiplayMgr::FGMultiplayMgr()
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// MultiplayMgr destructor
+//
+//////////////////////////////////////////////////////////////////////
+FGMultiplayMgr::~FGMultiplayMgr()
+{
+ Close();
+} // FGMultiplayMgr::~FGMultiplayMgr()
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// Initialise object
+//
+//////////////////////////////////////////////////////////////////////
+bool
+FGMultiplayMgr::init (void)
+{
+ string TxAddress; // Destination address
+ int TxPort;
+
+ //////////////////////////////////////////////////
+ // Initialise object if not already done
+ //////////////////////////////////////////////////
+ if (m_Initialised)
+ {
+ SG_LOG( SG_NETWORK, SG_WARN,
+ "FGMultiplayMgr::init - already initialised" );
+ return (false);
+ }
+ //////////////////////////////////////////////////
+ // Set members from property values
+ //////////////////////////////////////////////////
+ TxAddress = fgGetString ("/sim/multiplay/txhost");
+ TxPort = fgGetInt ("/sim/multiplay/txport");
+ m_Callsign = fgGetString ("/sim/multiplay/callsign");
+ m_RxAddress = fgGetString ("/sim/multiplay/rxhost");
+ m_RxPort = fgGetInt ("/sim/multiplay/rxport");
+ if (m_RxPort <= 0)
+ {
+ m_RxPort = 5000;
+ }
+ if (m_Callsign == "")
+ {
+ // FIXME: use getpwuid
+ m_Callsign = "JohnDoe";
+ }
+ if (m_RxAddress == "")
+ {
+ m_RxAddress = "127.0.0.1";
+ }
+ if ((TxPort > 0) && (TxAddress != ""))
+ {
+ m_HaveServer = true;
+ m_Server.set (TxAddress.c_str(), TxPort);
+ }
+ SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-txaddress= "<<TxAddress);
+ SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-txport= "<<TxPort );
+ SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-rxaddress="<<m_RxAddress );
+ SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-rxport= "<<m_RxPort);
+ SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-callsign= "<<m_Callsign);
+ m_DataSocket = new netSocket();
+ if (!m_DataSocket->open(false))
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::init - Failed to create data socket" );
+ return (false);
+ }
+ m_DataSocket->setBlocking(false);
+ m_DataSocket->setBroadcast(true);
+ if (m_DataSocket->bind(m_RxAddress.c_str(), m_RxPort) != 0)
+ {
+ perror("bind");
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::Open - Failed to bind receive socket" );
+ return (false);
+ }
+ m_LocalPlayer = new MPPlayer();
+ if (!m_LocalPlayer->Open(m_RxAddress, m_RxPort, m_Callsign,
+ fgGetString("/sim/model/path"), true))
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::init - Failed to create local player" );
+ return (false);
+ }
+ m_Initialised = true;
+ return (true);
+} // FGMultiplayMgr::init()
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// Closes and deletes the local player object. Closes
+// and deletes the tx socket. Resets the object state to unitialised.
+//
+//////////////////////////////////////////////////////////////////////
+void
+FGMultiplayMgr::Close (void)
+{
+ //////////////////////////////////////////////////
+ // Delete local player
+ //////////////////////////////////////////////////
+ if (m_LocalPlayer)
+ {
+ delete m_LocalPlayer;
+ m_LocalPlayer = NULL;
+ }
+ //////////////////////////////////////////////////
+ // Delete any existing players
+ //////////////////////////////////////////////////
+ t_MPClientListIterator CurrentPlayer;
+ t_MPClientListIterator P;
+ CurrentPlayer = m_MPClientList.begin ();
+ while (CurrentPlayer != m_MPClientList.end ())
+ {
+ P = CurrentPlayer;
+ delete (*P);
+ *P = 0;
+ CurrentPlayer = m_MPClientList.erase (P);
+ }
+ //////////////////////////////////////////////////
+ // Delete socket
+ //////////////////////////////////////////////////
+ if (m_DataSocket)
+ {
+ m_DataSocket->close();
+ delete m_DataSocket;
+ m_DataSocket = NULL;
+ }
+ m_Initialised = false;
+} // FGMultiplayMgr::Close(void)
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// Description: Sends the position data for the local position.
+//
+//////////////////////////////////////////////////////////////////////
+void
+FGMultiplayMgr::SendMyPosition
+ (
+ const sgQuat PlayerOrientation,
+ const sgdVec3 PlayerPosition
+ )
+{
+ T_MsgHdr MsgHdr;
+ T_PositionMsg PosMsg;
+ char Msg[sizeof(T_MsgHdr) + sizeof(T_PositionMsg)];
+
+ if ((! m_Initialised) || (! m_HaveServer))
+ {
+ if (! m_Initialised)
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::SendMyPosition - not initialised" );
+ if (! m_HaveServer)
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::SendMyPosition - no server" );
+ return;
+ }
+ m_LocalPlayer->SetPosition(PlayerOrientation, PlayerPosition);
+ m_LocalPlayer->FillPosMsg(&MsgHdr, &PosMsg);
+ memcpy(Msg, &MsgHdr, sizeof(T_MsgHdr));
+ memcpy(Msg + sizeof(T_MsgHdr), &PosMsg, sizeof(T_PositionMsg));
+ m_DataSocket->sendto (Msg,
+ sizeof(T_MsgHdr) + sizeof(T_PositionMsg), 0, &m_Server);
+} // FGMultiplayMgr::SendMyPosition()
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// Name: SendTextMessage
+// Description: Sends a message to the player. The message must
+// contain a valid and correctly filled out header and optional
+// message body.
+//
+//////////////////////////////////////////////////////////////////////
+void
+FGMultiplayMgr::SendTextMessage
+ (
+ const string &MsgText
+ ) const
+{
+ T_MsgHdr MsgHdr;
+ T_ChatMsg ChatMsg;
+ unsigned int iNextBlockPosition = 0;
+ char Msg[sizeof(T_MsgHdr) + sizeof(T_ChatMsg)];
+
+ if ((! m_Initialised) || (! m_HaveServer))
+ {
+ return;
+ }
+ m_LocalPlayer->FillMsgHdr(&MsgHdr, CHAT_MSG_ID);
+ //////////////////////////////////////////////////
+ // Divide the text string into blocks that fit
+ // in the message and send the blocks.
+ //////////////////////////////////////////////////
+ while (iNextBlockPosition < MsgText.length())
+ {
+ strncpy (ChatMsg.Text,
+ MsgText.substr(iNextBlockPosition, MAX_CHAT_MSG_LEN - 1).c_str(),
+ MAX_CHAT_MSG_LEN);
+ ChatMsg.Text[MAX_CHAT_MSG_LEN - 1] = '\0';
+ memcpy (Msg, &MsgHdr, sizeof(T_MsgHdr));
+ memcpy (Msg + sizeof(T_MsgHdr), &ChatMsg, sizeof(T_ChatMsg));
+ m_DataSocket->sendto (Msg,
+ sizeof(T_MsgHdr) + sizeof(T_ChatMsg), 0, &m_Server);
+ iNextBlockPosition += MAX_CHAT_MSG_LEN - 1;
+ }
+} // FGMultiplayMgr::SendTextMessage ()
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// Name: ProcessData
+// Description: Processes data waiting at the receive socket. The
+// processing ends when there is no more data at the socket.
+//
+//////////////////////////////////////////////////////////////////////
+void
+FGMultiplayMgr::ProcessData (void)
+{
+ char Msg[MAX_PACKET_SIZE]; // Buffer for received message
+ int Bytes; // Bytes received
+ T_MsgHdr* MsgHdr; // Pointer to header in received data
+ netAddress SenderAddress;
+
+ if (! m_Initialised)
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::ProcessData - not initialised" );
+ return;
+ }
+ //////////////////////////////////////////////////
+ // Read the receive socket and process any data
+ //////////////////////////////////////////////////
+ do {
+ //////////////////////////////////////////////////
+ // Although the recv call asks for
+ // MAX_PACKET_SIZE of data, the number of bytes
+ // returned will only be that of the next
+ // packet waiting to be processed.
+ //////////////////////////////////////////////////
+ Bytes = m_DataSocket->recvfrom (Msg, MAX_PACKET_SIZE, 0,
+ &SenderAddress);
+ //////////////////////////////////////////////////
+ // no Data received
+ //////////////////////////////////////////////////
+ if (Bytes <= 0)
+ {
+ if (errno != EAGAIN)
+ {
+ perror("FGMultiplayMgr::MP_ProcessData");
+ }
+ return;
+ }
+ if (Bytes <= (int)sizeof(MsgHdr))
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::MP_ProcessData - "
+ << "received message with insufficient data" );
+ return;
+ }
+ //////////////////////////////////////////////////
+ // Read header
+ //////////////////////////////////////////////////
+ MsgHdr = (T_MsgHdr *)Msg;
+ MsgHdr->Magic = XDR_decode_uint32 (MsgHdr->Magic);
+ MsgHdr->Version = XDR_decode_uint32 (MsgHdr->Version);
+ MsgHdr->MsgId = XDR_decode_uint32 (MsgHdr->MsgId);
+ MsgHdr->MsgLen = XDR_decode_uint32 (MsgHdr->MsgLen);
+ MsgHdr->ReplyPort = XDR_decode_uint32 (MsgHdr->ReplyPort);
+ if (MsgHdr->Magic != MSG_MAGIC)
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::MP_ProcessData - "
+ << "message has invalid magic number!" );
+ }
+ if (MsgHdr->Version != PROTO_VER)
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::MP_ProcessData - "
+ << "message has invalid protocoll number!" );
+ }
+ //////////////////////////////////////////////////
+ // Process the player data unless we generated it
+ //////////////////////////////////////////////////
+ if (m_Callsign == MsgHdr->Callsign)
+ {
+ return;
+ }
+ //////////////////////////////////////////////////
+ // Process messages
+ //////////////////////////////////////////////////
+ switch(MsgHdr->MsgId)
+ {
+ case CHAT_MSG_ID:
+ ProcessChatMsg ((char*) & Msg, SenderAddress);
+ break;
+ case POS_DATA_ID:
+ ProcessPosMsg ((char*) & Msg, SenderAddress);
+ break;
+ default:
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::MP_ProcessData - "
+ << "Unknown message Id received: "
+ << MsgHdr->MsgId );
+ break;
+ } // switch
+ } while (Bytes > 0);
+} // FGMultiplayMgr::ProcessData(void)
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// handle a position message
+//
+//////////////////////////////////////////////////////////////////////
+void
+FGMultiplayMgr::ProcessPosMsg
+ (
+ const char *Msg,
+ netAddress & SenderAddress
+ )
+{
+ T_PositionMsg* PosMsg; // Pointer to position message in received data
+ T_MsgHdr* MsgHdr; // Pointer to header in received data
+ bool ActivePlayer;
+ sgQuat Orientation;
+ sgdVec3 Position;
+ struct in_addr PlayerAddress;
+ t_MPClientListIterator CurrentPlayer;
+ int iPlayerCnt;
+ char *sIpAddress;
+
+ ActivePlayer = false;
+ MsgHdr = (T_MsgHdr *)Msg;
+ if (MsgHdr->MsgLen != sizeof(T_MsgHdr) + sizeof(T_PositionMsg))
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::MP_ProcessData - "
+ << "Position message received with insufficient data" );
+ return;
+ }
+ PosMsg = (T_PositionMsg *)(Msg + sizeof(T_MsgHdr));
+ Position[0] = XDR_decode_double (PosMsg->PlayerPosition[0]);
+ Position[1] = XDR_decode_double (PosMsg->PlayerPosition[1]);
+ Position[2] = XDR_decode_double (PosMsg->PlayerPosition[2]);
+ Orientation[0] = XDR_decode_float (PosMsg->PlayerOrientation[0]);
+ Orientation[1] = XDR_decode_float (PosMsg->PlayerOrientation[1]);
+ Orientation[2] = XDR_decode_float (PosMsg->PlayerOrientation[2]);
+ Orientation[3] = XDR_decode_float (PosMsg->PlayerOrientation[3]);
+ //////////////////////////////////////////////////
+ // Check if the player is already in the game
+ // by using the Callsign
+ //////////////////////////////////////////////////
+ for (CurrentPlayer = m_MPClientList.begin ();
+ CurrentPlayer != m_MPClientList.end ();
+ CurrentPlayer++)
+ {
+ if ((*CurrentPlayer)->CompareCallsign(MsgHdr->Callsign))
+ {
+ // Player found. Update the data for the player.
+ (*CurrentPlayer)->SetPosition(Orientation, Position);
+ ActivePlayer = true;
+ }
+ } // for (...)
+ if (ActivePlayer)
+ { // nothing more to do
+ return;
+ }
+ //////////////////////////////////////////////////
+ // Player not active, so add as new player
+ //////////////////////////////////////////////////
+ MPPlayer* NewPlayer;
+ NewPlayer = new MPPlayer;
+ NewPlayer->Open(SenderAddress.getHost(), MsgHdr->ReplyPort,
+ MsgHdr->Callsign, PosMsg->Model, false);
+ NewPlayer->SetPosition(Orientation, Position);
+ m_MPClientList.push_back (NewPlayer);
+} // FGMultiplayMgr::ProcessPosMsg()
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// handle a chat message
+// FIXME: display chat message withi flightgear
+//
+//////////////////////////////////////////////////////////////////////
+void
+FGMultiplayMgr::ProcessChatMsg
+ (
+ const char *Msg,
+ netAddress & SenderAddress
+ )
+{
+ T_ChatMsg* ChatMsg; // Pointer to chat message in received data
+ T_MsgHdr* MsgHdr; // Pointer to header in received data
+
+ MsgHdr = (T_MsgHdr *)Msg;
+ if (MsgHdr->MsgLen != sizeof(T_MsgHdr) + sizeof(T_ChatMsg))
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT,
+ "FGMultiplayMgr::MP_ProcessData - "
+ << "Chat message received with insufficient data" );
+ return;
+ }
+ ChatMsg = (T_ChatMsg *)(Msg + sizeof(T_MsgHdr));
+ SG_LOG ( SG_NETWORK, SG_ALERT,
+ "Chat [" << MsgHdr->Callsign << "]" << " " << ChatMsg->Text << endl);
+} // FGMultiplayMgr::ProcessChatMsg ()
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+//
+// For each active player, tell the player object
+// to update its position on the scene. If a player object
+// returns status information indicating that it has not
+// had an update for some time then the player is deleted.
+//
+//////////////////////////////////////////////////////////////////////
+void
+FGMultiplayMgr::Update (void)
+{
+ MPPlayer::TPlayerDataState ePlayerDataState;
+ t_MPClientListIterator CurrentPlayer;
+
+ CurrentPlayer = m_MPClientList.begin ();
+ while (CurrentPlayer != m_MPClientList.end ())
+ {
+ ePlayerDataState = (*CurrentPlayer)->Draw();
+ //////////////////////////////////////////////////
+ // If the player has not received an update for
+ // some time then assume that the player has quit.
+ //////////////////////////////////////////////////
+ if (ePlayerDataState == MPPlayer::PLAYER_DATA_EXPIRED)
+ {
+ SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayMgr::Update - "
+ << "Deleting player from game. Callsign: "
+ << (*CurrentPlayer)->Callsign() );
+ t_MPClientListIterator P;
+ P = CurrentPlayer;
+ delete (*P);
+ *P = 0;
+ CurrentPlayer = m_MPClientList.erase (P);
+ }
+ else CurrentPlayer++;
+ }
+} // FGMultiplayMgr::Update()
+//////////////////////////////////////////////////////////////////////
+
+#endif // FG_MPLAYER_AS
+
--- /dev/null
+//////////////////////////////////////////////////////////////////////
+//
+// multiplaymgr.hpp
+//
+// Written by Duncan McCreanor, started February 2003.
+// duncan.mccreanor@airservicesaustralia.com
+//
+// Copyright (C) 2003 Airservices Australia
+// Copyright (C) 2005 Oliver Schroeder
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+//
+//////////////////////////////////////////////////////////////////////
+
+#ifndef MULTIPLAYMGR_H
+#define MULTIPLAYMGR_H
+
+#define MULTIPLAYTXMGR_HID "$Id$"
+
+#include "mpplayer.hxx"
+#include "mpmessages.hxx"
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include STL_STRING
+SG_USING_STD(string);
+#include <vector>
+SG_USING_STD(vector);
+
+#include <simgear/compiler.h>
+#include <plib/netSocket.h>
+#include <Main/globals.hxx>
+
+// Maximum number of players that can exist at any time
+// FIXME: use a list<mplayer> instead
+#define MAX_PLAYERS 10
+
+class FGMultiplayMgr
+{
+public:
+ FGMultiplayMgr();
+ ~FGMultiplayMgr();
+ bool init(void);
+ void Close(void);
+ // transmitter
+ void SendMyPosition (const sgQuat PlayerOrientation,
+ const sgdVec3 PlayerPosition);
+ void SendTextMessage (const string &sMsgText) const;
+ // receiver
+ void ProcessData(void);
+ void ProcessPosMsg ( const char *Msg, netAddress & SenderAddress );
+ void ProcessChatMsg ( const char *Msg, netAddress & SenderAddress );
+ void Update(void);
+private:
+ typedef vector<MPPlayer*> t_MPClientList;
+ typedef t_MPClientList::iterator t_MPClientListIterator;
+ MPPlayer* m_LocalPlayer;
+ netSocket* m_DataSocket;
+ netAddress m_Server;
+ bool m_HaveServer;
+ bool m_Initialised;
+ t_MPClientList m_MPClientList;
+ string m_RxAddress;
+ int m_RxPort;
+ string m_Callsign;
+};
+
+#endif
+
+++ /dev/null
-// multiplayrxmgr.cxx -- routines for receiving multiplayer data
-// for Flightgear
-//
-// Written by Duncan McCreanor, started February 2003.
-// duncan.mccreanor@airservicesaustralia.com
-//
-// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef FG_MPLAYER_AS
-
-/******************************************************************
-* $Id$
-*
-* Description: The multiplayer rx manager provides control over
-* multiplayer data reception and processing for an interactive
-* multiplayer FlightGear simulation.
-*
-* The objects that hold player information are accessed via
-* a fixed size array. A fixed array is used since it provides
-* speed benefits over working with linked lists and is easier
-* to code. Also, there is no point allowing for an unlimited
-* number of players as too many players will slow the game
-* down to the point where it is unplayable.
-*
-* When player position data is received, the callsign of
-* the player is checked against existing players. If the
-* player does not exist, a new player is created in the
-* next free slot of the player array. If the player does
-* exist, the player's positional matrix is updated.
-*
-* The Update method is used to move the players on the
-* scene. The return value from calling MPPlayer::Draw
-* indicates the state of the player. If data for a player
-* has not been received data for some time, the player object
-* is deleted and the array element freed.
-*
-******************************************************************/
-
-#include <sys/types.h>
-#if !(defined(_MSC_VER) || defined(__MINGW32__))
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-#endif
-#include <plib/netSocket.h>
-#include <stdlib.h>
-
-#include <simgear/debug/logstream.hxx>
-#include <Main/fg_props.hxx>
-
-#include "multiplayrxmgr.hxx"
-#include "mpmessages.hxx"
-#include "mpplayer.hxx"
-
-#define MAX_PACKET_SIZE 1024
-
-// These constants are provided so that the ident command can list file versions.
-const char sMULTIPLAYTXMGR_BID[] = "$Id$";
-const char sMULTIPLAYRXMGR_HID[] = MULTIPLAYRXMGR_HID;
-
-
-
-/******************************************************************
-* Name: FGMultiplayRxMgr
-* Description: Constructor.
-******************************************************************/
-FGMultiplayRxMgr::FGMultiplayRxMgr() {
-
- int iPlayerCnt; // Count of players in player array
-
- // Initialise private members
- m_sRxAddress = "0";
- m_iRxPort = 0;
- m_bInitialised = false;
-
- // Clear the player array
- for (iPlayerCnt = 0; iPlayerCnt < MAX_PLAYERS; iPlayerCnt++) {
- m_Player[iPlayerCnt] = NULL;
- }
-
-}
-
-
-/******************************************************************
-* Name: ~FGMultiplayRxMgr
-* Description: Destructor. Closes and deletes objects owned by
-* this object.
-******************************************************************/
-FGMultiplayRxMgr::~FGMultiplayRxMgr() {
-
- Close();
-
-}
-
-
-/******************************************************************
-* Name: init
-* Description: Initialises multiplayer receive.
-******************************************************************/
-bool FGMultiplayRxMgr::init(void) {
-
- bool bSuccess = true; // Result of initialisation
-
- // Initialise object if not already done
- if (!m_bInitialised) {
-
- // Set members from property values
- m_sCallsign = fgGetString("/sim/multiplay/callsign");
- m_sRxAddress = fgGetString("/sim/multiplay/rxhost");
- m_iRxPort = fgGetInt("/sim/multiplay/rxport");
-
- SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayRxMgr::init - rxaddress= "
- << m_sRxAddress );
- SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayRxMgr::init - rxport= "
- << m_iRxPort);
- SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayRxMgr::init - callsign= "
- << m_sCallsign );
-
-
- // Create and open rx socket
- mDataRxSocket = new netSocket();
- if (!mDataRxSocket->open(false)) {
- // Failed to open rx socket
- SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayRxMgr::Open - Failed to create data receive socket" );
- bSuccess = false;
- } else {
-
- // Configure the socket
- mDataRxSocket->setBlocking(false);
- mDataRxSocket->setBroadcast(true);
- if (mDataRxSocket->bind(m_sRxAddress.c_str(), m_iRxPort) != 0) {
- perror("bind");
- // Failed to bind
- SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayRxMgr::Open - Failed to bind receive socket" );
- bSuccess = false;
- }
-
- }
-
- // Save manager state
- m_bInitialised = bSuccess;
-
- } else {
- SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayRxMgr::OpenRx - Receiver open requested when receiver is already open" );
- bSuccess = false;
- }
-
- /* Return true if open succeeds */
- return bSuccess;
-
-}
-
-
-/******************************************************************
-* Name: Close
-* Description: Closes and deletes and player connections. Closes
-* and deletes the rx socket. Resets the object state
-* to unitialised.
-******************************************************************/
-void FGMultiplayRxMgr::Close(void) {
-
- int iPlayerCnt; // Count of players in player array
-
- // Delete any existing players
- for (iPlayerCnt = 0; iPlayerCnt < MAX_PLAYERS; iPlayerCnt++) {
- if (m_Player[iPlayerCnt] != NULL) {
- delete m_Player[iPlayerCnt];
- m_Player[iPlayerCnt] = NULL;
- }
- }
-
- // Delete socket
- if (mDataRxSocket) {
- mDataRxSocket->close();
- delete mDataRxSocket;
- mDataRxSocket = NULL;
- }
-
- m_bInitialised = false;
-
-}
-
-
-/******************************************************************
-* Name: ProcessData
-* Description: Processes data waiting at the receive socket. The
-* processing ends when there is no more data at the socket.
-******************************************************************/
-void FGMultiplayRxMgr::ProcessData(void) {
-
- char sMsg[MAX_PACKET_SIZE]; // Buffer for received message
- int iBytes; // Bytes received
- T_MsgHdr *MsgHdr; // Pointer to header in received data
-
-
- if (! m_bInitialised) {
- return;
- }
-
- // Read the receive socket and process any data
- do {
-
- // Although the recv call asks for MAX_PACKET_SIZE of data,
- // the number of bytes returned will only be that of the next
- // packet waiting to be processed.
- iBytes = mDataRxSocket->recv(sMsg, MAX_PACKET_SIZE, 0);
-
- // no Data received
- if (iBytes <= 0) {
- if (errno != EAGAIN) {
- perror("FGMultiplayRxMgr::MP_ProcessData");
- }
- return;
- }
- if (iBytes <= (int)sizeof(MsgHdr)) {
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::MP_ProcessData - received message with insufficient data" );
- return;
- }
- // Read header
- MsgHdr = (T_MsgHdr *)sMsg;
- MsgHdr->Magic = XDR_decode_uint32 (MsgHdr->Magic);
- MsgHdr->Version = XDR_decode_uint32 (MsgHdr->Version);
- MsgHdr->MsgId = XDR_decode_uint32 (MsgHdr->MsgId);
- MsgHdr->iMsgLen = XDR_decode_uint32 (MsgHdr->iMsgLen);
- MsgHdr->iReplyPort = XDR_decode_uint32 (MsgHdr->iReplyPort);
- if (MsgHdr->Magic != MSG_MAGIC) {
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::MP_ProcessData - message has invalid magic number!" );
- }
- if (MsgHdr->Version != PROTO_VER) {
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::MP_ProcessData - message has invalid protocoll number!" );
- }
-
- // Process the player data unless we generated it
- if (m_sCallsign == MsgHdr->sCallsign) {
- return;
- }
-
- // Process messages
- switch(MsgHdr->MsgId) {
- case CHAT_MSG_ID:
- ProcessChatMsg ((char*) & sMsg);
- break;
-
- case POS_DATA_ID:
- ProcessPosMsg ((char*) & sMsg);
- break;
-
- default:
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::MP_ProcessData - Unknown message Id received: "
- << MsgHdr->MsgId );
- break;
- } // switch
- } while (iBytes > 0);
-
-}
-
-void FGMultiplayRxMgr::ProcessPosMsg ( const char *Msg ) {
-
- T_PositionMsg *PosMsg; // Pointer to position message in received data
- T_MsgHdr *MsgHdr; // Pointer to header in received data
- int iPlayerCnt; // Count of players in player array
- bool bActivePlayer = false; // The state of the player that sent the data
- sgQuat Orientation;
- sgdVec3 Position;
- char *sIpAddress; // Address information from header
- struct in_addr PlayerAddress; // Used for converting the player's address into dot notation
-
- MsgHdr = (T_MsgHdr *)Msg;
- if (MsgHdr->iMsgLen != sizeof(T_MsgHdr) + sizeof(T_PositionMsg)) {
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::MP_ProcessData - Position message received with insufficient data" );
- return;
- }
-
- PosMsg = (T_PositionMsg *)(Msg + sizeof(T_MsgHdr));
- Position[0] = XDR_decode_double (PosMsg->PlayerPosition[0]);
- Position[1] = XDR_decode_double (PosMsg->PlayerPosition[1]);
- Position[2] = XDR_decode_double (PosMsg->PlayerPosition[2]);
- Orientation[0] = XDR_decode_float (PosMsg->PlayerOrientation[0]);
- Orientation[1] = XDR_decode_float (PosMsg->PlayerOrientation[1]);
- Orientation[2] = XDR_decode_float (PosMsg->PlayerOrientation[2]);
- Orientation[3] = XDR_decode_float (PosMsg->PlayerOrientation[3]);
-
- // Check if the player is already in the game by using the Callsign.
- for (iPlayerCnt = 0; iPlayerCnt < MAX_PLAYERS; iPlayerCnt++) {
- if (m_Player[iPlayerCnt] != NULL) {
- if (m_Player[iPlayerCnt]->CompareCallsign(MsgHdr->sCallsign)) {
- // Player found. Update the data for the player.
- m_Player[iPlayerCnt]->SetPosition(Orientation, Position);
- bActivePlayer = true;
- }
- }
- }
-
- if (bActivePlayer) {
- // nothing more to do
- return;
- }
- // Player not active, so add as new player
- iPlayerCnt = 0;
- do {
- if (m_Player[iPlayerCnt] == NULL) {
- PlayerAddress.s_addr = MsgHdr->lReplyAddress; // which is unecoded
- sIpAddress = inet_ntoa(PlayerAddress);
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::ProcessRxData - Add new player. IP: " << sIpAddress
- << ", Call: " << MsgHdr->sCallsign
- << ", model: " << PosMsg->sModel);
- m_Player[iPlayerCnt] = new MPPlayer;
- m_Player[iPlayerCnt]->Open(sIpAddress, MsgHdr->iReplyPort,
- MsgHdr->sCallsign, PosMsg->sModel, false);
- m_Player[iPlayerCnt]->SetPosition(Orientation, Position);
- bActivePlayer = true;
- }
- iPlayerCnt++;
- } while (iPlayerCnt < MAX_PLAYERS && !bActivePlayer);
-
- // Check if the player was added
- if (!bActivePlayer) {
- if (iPlayerCnt == MAX_PLAYERS) {
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::MP_ProcessData - Unable to add new player ("
- << MsgHdr->sCallsign
- << "). Too many players." );
- }
- }
-
-}
-
-void FGMultiplayRxMgr::ProcessChatMsg ( const char *Msg ) {
-
- T_ChatMsg *ChatMsg; // Pointer to chat message in received data
- T_MsgHdr *MsgHdr; // Pointer to header in received data
-
- MsgHdr = (T_MsgHdr *)Msg;
- if (MsgHdr->iMsgLen != sizeof(T_MsgHdr) + sizeof(T_ChatMsg)) {
- SG_LOG( SG_NETWORK, SG_ALERT,
- "FGMultiplayRxMgr::MP_ProcessData - Chat message received with insufficient data" );
- return;
- }
-
- ChatMsg = (T_ChatMsg *)(Msg + sizeof(T_MsgHdr));
- SG_LOG( SG_NETWORK, SG_BULK, "Chat [" << MsgHdr->sCallsign << "]" << " " << ChatMsg->sText );
-}
-
-/******************************************************************
-* Name: Update
-* Description: For each active player, tell the player object
-* to update its position on the scene. If a player object
-* returns status information indicating that it has not
-* had an update for some time then the player is deleted.
-******************************************************************/
-void FGMultiplayRxMgr::Update(void) {
-
- MPPlayer::TPlayerDataState ePlayerDataState;
- int iPlayerId;
-
- for (iPlayerId = 0; iPlayerId < MAX_PLAYERS; iPlayerId++) {
- if (m_Player[iPlayerId] != NULL) {
- ePlayerDataState = m_Player[iPlayerId]->Draw();
-
- // If the player has not received an update for some
- // time then assume that the player has quit.
- if (ePlayerDataState == MPPlayer::PLAYER_DATA_EXPIRED) {
- SG_LOG( SG_NETWORK, SG_BULK, "FGMultiplayRxMgr::Update - Deleting player from game. Callsign: "
- << m_Player[iPlayerId]->Callsign() );
- delete m_Player[iPlayerId];
- m_Player[iPlayerId] = NULL;
- }
-
- }
- }
-
-}
-
-#endif // FG_MPLAYER_AS
-
+++ /dev/null
-// multiplayrxmgr.hxx -- routines for receiving multiplayer data
-// for Flghtgear
-//
-// Written by Duncan McCreanor, started February 2003.
-// duncan.mccreanor@airservicesaustralia.com
-//
-// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-
-#ifndef MULTIPLAYRXMGR_H
-#define MULTIPLAYRXMGR_H
-
-#define MULTIPLAYRXMGR_HID "$Id$"
-
-
-#include "mpplayer.hxx"
-#include "mpmessages.hxx"
-
-#include STL_STRING
-SG_USING_STD(string);
-
-#include <simgear/compiler.h>
-#include <plib/netSocket.h>
-
-// Maximum number of players that can exist at any time
-#define MAX_PLAYERS 10
-
-/****************************************************************
-* @version $Id$
-*
-* Description: The multiplay rx manager is responsible for
-* receiving and processing data from other players.
-
-* Data from remote players is read from the network and processed
-* via calling ProcessData. The models for the remote player are
-* positioned onto the scene by calling Update.
-*
-*******************************************************************/
-class FGMultiplayRxMgr {
-public:
-
- /** Constructor */
- FGMultiplayRxMgr();
-
- /** Destructor. */
- ~FGMultiplayRxMgr();
-
- /** Initialises the multiplayer receiver.
- * @return True if initialisation succeeds, else false
- */
- bool init(void);
-
- /** Initiates processing of any data waiting at the rx socket.
- */
- void ProcessData(void);
- void ProcessPosMsg ( const char *Msg );
- void ProcessChatMsg ( const char *Msg );
-
- /** Updates the model positions for the players
- */
- void Update(void);
-
- /** Closes the multiplayer manager. Stops any further player packet processing.
- */
- void Close(void);
-
-
-private:
-
-
- /** Holds the players that exist in the game */
- MPPlayer *m_Player[MAX_PLAYERS];
-
- /** Socket for receiving data from the server or another player */
- netSocket *mDataRxSocket;
-
- /** True if multiplay receive is initialised */
- bool m_bInitialised;
-
- /** Receive address for multiplayer messages */
- string m_sRxAddress;
-
- /** Receive port for multiplayer messages */
- int m_iRxPort;
-
- /** Local player's callsign */
- string m_sCallsign;
-
-};
-
-#endif
-
-
-
+++ /dev/null
-// multiplaytxmgr.cxx -- routines for transmitting multiplayer data
-// for Flightgear
-//
-// Written by Duncan McCreanor, started February 2003.
-// duncan.mccreanor@airservicesaustralia.com
-//
-// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef FG_MPLAYER_AS
-
-/******************************************************************
-* $Id$
-*
-* Description: The multiplayer tx manager provides is used
-* to send data to another player or a server for an
-* interactive multiplayer FlightGear simulation.
-*
-******************************************************************/
-
-#include <sys/types.h>
-#if !(defined(_MSC_VER) || defined(__MINGW32__))
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-#endif
-#include <plib/netSocket.h>
-#include <stdlib.h>
-
-#include <simgear/debug/logstream.hxx>
-#include <Main/fg_props.hxx>
-
-#include "multiplaytxmgr.hxx"
-#include "mpmessages.hxx"
-#include "mpplayer.hxx"
-
-// These constants are provided so that the ident command can list file versions.
-const char sMULTIPLAYTXMGR_BID[] = "$Id$";
-const char sMULTIPLAYTXMGR_HID[] = MULTIPLAYTXMGR_HID;
-
-
-
-/******************************************************************
-* Name: FGMultiplayTxMgr
-* Description: Constructor.
-******************************************************************/
-FGMultiplayTxMgr::FGMultiplayTxMgr() {
-
- // int iPlayerCnt; // Count of players in player array
-
- // Initialise private members
- m_bInitialised = false;
- mLocalPlayer = NULL;
-
-}
-
-
-/******************************************************************
-* Name: ~FGMultiplayTxMgr
-* Description: Destructor. Closes and deletes objects owned by
-* this object.
-******************************************************************/
-FGMultiplayTxMgr::~FGMultiplayTxMgr() {
-
- Close();
-
-}
-
-
-/******************************************************************
-* Name: init
-* Description: Initialises multiplayer transmit
-******************************************************************/
-bool FGMultiplayTxMgr::init(void) {
-
-
- string sTxAddress; // Destination address
- int iTxPort;
- bool bSuccess = true; // Result of initialisation
-
- // Initialise object if not already done
- if (!m_bInitialised) {
-
- // Set members from property values
- string sTxAddress = fgGetString("/sim/multiplay/txhost");
- iTxPort = fgGetInt("/sim/multiplay/txport");
-
- SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayTxMgr::init - txaddress= "
- << sTxAddress );
- SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayTxMgr::init - txport= "
- << iTxPort );
-
- if (iTxPort > 0) {
-
-
- // Create and open tx socket
- mDataTxSocket = new netSocket();
- if (!mDataTxSocket->open(false)) {
- // Failed to open tx socket
- SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Failed to create data transmit socket" );
- bSuccess = false;
- } else {
- mDataTxSocket->setBroadcast(true);
- if (mDataTxSocket->connect(sTxAddress.c_str(), iTxPort) != 0) {
- // Failed to connect tx socket
- SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Failed to connect data transmit socket" );
- bSuccess = false;
- }
- }
-
- // Create a player object for the local player
- if (bSuccess) {
- mLocalPlayer = new MPPlayer();
- if (!mLocalPlayer->Open(fgGetString("/sim/multiplay/rxhost"), fgGetInt("/sim/multiplay/rxport"),
- fgGetString("/sim/multiplay/callsign"), fgGetString("/sim/model/path"), true)) {
- SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Failed to create player object for local player" );
- bSuccess = false;
- }
- }
-
- // If Tx port == zero then don't initialise
- } else {
-
- SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayTxMgr::init - Tx Port is zero. Multiplay out disabled." );
- bSuccess = false;
-
- }
-
- // Save manager state
- m_bInitialised = bSuccess;
-
- } else {
- SG_LOG( SG_NETWORK, SG_WARN, "FGMultiplayTxMgr::init - Attempt to init object that is already opened" );
- bSuccess = false;
- }
-
-
- /* Return true if init succeeds */
- return bSuccess;
-
-}
-
-
-/******************************************************************
-* Name: Close
-* Description: Closes and deletes the local player object. Closes
-* and deletes the tx socket. Resets the object state to unitialised.
-******************************************************************/
-void FGMultiplayTxMgr::Close(void) {
-
-
- // Delete local player
- if (mLocalPlayer) {
- delete mLocalPlayer;
- mLocalPlayer = NULL;
- }
-
- // Delete socket
- if (mDataTxSocket) {
- mDataTxSocket->close();
- delete mDataTxSocket;
- mDataTxSocket = NULL;
- }
-
- m_bInitialised = false;
-
-}
-
-
-/******************************************************************
-* Name: SendMyPosition
-* Description: Sends the position data for the local position.
-******************************************************************/
-void FGMultiplayTxMgr::SendMyPosition(const sgQuat PlayerOrientation,
- const sgdVec3 PlayerPosition) {
-
- T_MsgHdr MsgHdr;
- T_PositionMsg PosMsg;
- char sMsg[sizeof(T_MsgHdr) + sizeof(T_PositionMsg)];
-
- if (m_bInitialised) {
- mLocalPlayer->SetPosition(PlayerOrientation, PlayerPosition);
- mLocalPlayer->FillPosMsg(&MsgHdr, &PosMsg);
- memcpy(sMsg, &MsgHdr, sizeof(T_MsgHdr));
- memcpy(sMsg + sizeof(T_MsgHdr), &PosMsg, sizeof(T_PositionMsg));
- mDataTxSocket->send(sMsg, sizeof(T_MsgHdr) + sizeof(T_PositionMsg), 0);
- }
-
-
-}
-
-
-
-/******************************************************************
-* Name: SendTextMessage
-* Description: Sends a message to the player. The message must
-* contain a valid and correctly filled out header and optional
-* message body.
-******************************************************************/
-void FGMultiplayTxMgr::SendTextMessage(const string &sMsgText) const {
-
- // bool bResult = false;
- T_MsgHdr MsgHdr;
- T_ChatMsg ChatMsg;
- unsigned int iNextBlockPosition = 0;
- char sMsg[sizeof(T_MsgHdr) + sizeof(T_ChatMsg)];
-
- if (m_bInitialised) {
-
- mLocalPlayer->FillMsgHdr(&MsgHdr, CHAT_MSG_ID);
-
- // Divide the text string into blocks that fit in the message
- // and send the blocks.
- while (iNextBlockPosition < sMsgText.length()) {
- strncpy(ChatMsg.sText, sMsgText.substr(iNextBlockPosition, MAX_CHAT_MSG_LEN - 1).c_str(), MAX_CHAT_MSG_LEN);
- ChatMsg.sText[MAX_CHAT_MSG_LEN - 1] = '\0';
- memcpy(sMsg, &MsgHdr, sizeof(T_MsgHdr));
- memcpy(sMsg + sizeof(T_MsgHdr), &ChatMsg, sizeof(T_ChatMsg));
- mDataTxSocket->send(sMsg, sizeof(T_MsgHdr) + sizeof(T_ChatMsg), 0);
- iNextBlockPosition += MAX_CHAT_MSG_LEN - 1;
- }
-
- }
-
-}
-
-#endif // FG_MPLAYER_AS
-
+++ /dev/null
-// multiplaytxmgr.hxx -- routines for transmitting multiplayer data
-// for Flghtgear
-//
-// Written by Duncan McCreanor, started February 2003.
-// duncan.mccreanor@airservicesaustralia.com
-//
-// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-
-#ifndef MULTIPLAYTXMGR_H
-#define MULTIPLAYTXMGR_H
-
-#define MULTIPLAYTXMGR_HID "$Id$"
-
-
-#include "mpplayer.hxx"
-#include "mpmessages.hxx"
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include STL_STRING
-SG_USING_STD(string);
-
-#include <simgear/compiler.h>
-#include <plib/netSocket.h>
-
-// Maximum number of players that can exist at any time
-#define MAX_PLAYERS 10
-
-/****************************************************************
-* @version $Id$
-*
-* Description: The multiplay tx manager is responsible for
-* sending data to another player or a multiplayer server.
-*
-* The position information for the local player is transmitted
-* on each call to SendMyPosition.
-*
-*******************************************************************/
-class FGMultiplayTxMgr {
-public:
-
- /** Constructor */
- FGMultiplayTxMgr();
-
- /** Destructor. */
- ~FGMultiplayTxMgr();
-
- /** Initialises the multiplayer transmitter.
- * @return True if initialisation succeeds, else false
- */
- bool init(void);
-
- /** Sends the position data for the local player
- * @param PlayerPosMat4 Transformation matrix for the player's position
- */
- void SendMyPosition(const sgQuat PlayerOrientation, const sgdVec3 PlayerPosition);
-
- /** Sends a tex chat message.
- * @param sMsgText Message text to send
- */
- void SendTextMessage(const string &sMsgText) const;
-
- /** Closes the multiplayer manager. Stops any further player packet processing.
- */
- void Close(void);
-
-
-private:
-
- /** The local player */
- MPPlayer *mLocalPlayer;
-
- /** Socket for sending to the server or another player if playing point to point */
- netSocket *mDataTxSocket;
-
- /** True if multiplay transmit is initialised */
- bool m_bInitialised;
-
-};
-
-#endif
-
-
-
//
// Tiny XDR implementation for flightgear
// written by Oliver Schroeder
-// released to the puiblic domain
+// released to the public domain
//
// This implementation is not complete, but implements
// everything we need.
//
// Tiny XDR implementation for flightgear
// written by Oliver Schroeder
-// released to the puiblic domain
+// released to the public domain
//
// This implementation is not complete, but implements
// everything we need.
if (get_direction() == SG_IO_IN) {
- globals->get_multiplayer_rx_mgr()->ProcessData();
+ globals->get_multiplayer_mgr()->ProcessData();
} else if (get_direction() == SG_IO_OUT) {
sgQuat PlayerOrientation;
sgMatrixToQuat(PlayerOrientation, posTrans);
- globals->get_multiplayer_tx_mgr()->SendMyPosition(PlayerOrientation, PlayerPosition);
+ globals->get_multiplayer_mgr()->SendMyPosition(PlayerOrientation, PlayerPosition);
}
if (get_direction() == SG_IO_IN) {
- globals->get_multiplayer_rx_mgr()->Close();
+ globals->get_multiplayer_mgr()->Close();
} else if (get_direction() == SG_IO_OUT) {
- globals->get_multiplayer_tx_mgr()->Close();
+// globals->get_multiplayer_mgr()->Close();
}
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Model/acmodel.hxx>
-#include <MultiPlayer/multiplaytxmgr.hxx>
-#include <MultiPlayer/multiplayrxmgr.hxx>
+#include <MultiPlayer/multiplaymgr.hpp>
#include "protocol.hxx"