From eed55b48b707153a6ba30a77f5f83acd65cf4915 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 30 Oct 2005 18:01:51 +0000 Subject: [PATCH] Oliver Schroeder: This is mainly an intermediate patch. I've restructured the network code. --- src/Main/fg_init.cxx | 10 +- src/Main/globals.hxx | 19 +- src/Main/main.cxx | 5 +- src/MultiPlayer/Makefile.am | 2 +- src/MultiPlayer/mpmessages.hxx | 12 +- src/MultiPlayer/mpplayer.cxx | 257 +++++++------- src/MultiPlayer/mpplayer.hxx | 83 ++--- src/MultiPlayer/multiplaymgr.cpp | 524 +++++++++++++++++++++++++++++ src/MultiPlayer/multiplaymgr.hpp | 85 +++++ src/MultiPlayer/multiplayrxmgr.cxx | 400 ---------------------- src/MultiPlayer/multiplayrxmgr.hxx | 108 ------ src/MultiPlayer/multiplaytxmgr.cxx | 246 -------------- src/MultiPlayer/multiplaytxmgr.hxx | 101 ------ src/MultiPlayer/tiny_xdr.cpp | 2 +- src/MultiPlayer/tiny_xdr.hpp | 2 +- src/Network/multiplay.cxx | 8 +- src/Network/multiplay.hxx | 3 +- 17 files changed, 781 insertions(+), 1086 deletions(-) create mode 100644 src/MultiPlayer/multiplaymgr.cpp create mode 100644 src/MultiPlayer/multiplaymgr.hpp delete mode 100644 src/MultiPlayer/multiplayrxmgr.cxx delete mode 100644 src/MultiPlayer/multiplayrxmgr.hxx delete mode 100644 src/MultiPlayer/multiplaytxmgr.cxx delete mode 100644 src/MultiPlayer/multiplaytxmgr.hxx diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index f20716dd6..7a52560d6 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -114,8 +114,7 @@ #include #ifdef FG_MPLAYER_AS -#include -#include +#include #endif #include @@ -1842,11 +1841,8 @@ bool fgInitSubsystems() { // 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 //////////////////////////////////////////////////////////////////////// diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index c02be6fee..c91df3c36 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -80,8 +80,7 @@ class FGModelMgr; class FGRouteMgr; class FGScenery; #ifdef FG_MPLAYER_AS -class FGMultiplayRxMgr; -class FGMultiplayTxMgr; +class FGMultiplayMgr; #endif class FGPanel; class FGTileMgr; @@ -214,9 +213,7 @@ private: #ifdef FG_MPLAYER_AS //Mulitplayer managers - FGMultiplayTxMgr *multiplayer_tx_mgr; - - FGMultiplayRxMgr *multiplayer_rx_mgr; + FGMultiplayMgr *multiplayer_mgr; #endif public: @@ -330,19 +327,13 @@ 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 () { diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 5bbd5c286..0858e06ff 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -76,8 +76,7 @@ #include #ifdef FG_MPLAYER_AS -#include -#include +#include #endif @@ -449,7 +448,7 @@ static void fgMainLoop( void ) { #ifdef FG_MPLAYER_AS // Update any multiplayer models - globals->get_multiplayer_rx_mgr()->Update(); + globals->get_multiplayer_mgr()->Update(); #endif // Run flight model diff --git a/src/MultiPlayer/Makefile.am b/src/MultiPlayer/Makefile.am index 9057a991c..c6c16f601 100644 --- a/src/MultiPlayer/Makefile.am +++ b/src/MultiPlayer/Makefile.am @@ -1,6 +1,6 @@ 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 diff --git a/src/MultiPlayer/mpmessages.hxx b/src/MultiPlayer/mpmessages.hxx index 65d00011a..c4a13eb6c 100644 --- a/src/MultiPlayer/mpmessages.hxx +++ b/src/MultiPlayer/mpmessages.hxx @@ -66,22 +66,22 @@ public: 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 }; diff --git a/src/MultiPlayer/mpplayer.cxx b/src/MultiPlayer/mpplayer.cxx index 45fad4b90..6ea20f53a 100644 --- a/src/MultiPlayer/mpplayer.cxx +++ b/src/MultiPlayer/mpplayer.cxx @@ -1,9 +1,12 @@ +////////////////////////////////////////////////////////////////////// +// // 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 @@ -19,6 +22,7 @@ // 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 @@ -44,10 +48,10 @@ #include #if !(defined(_MSC_VER) || defined(__MINGW32__)) -# include -# include -# include -# include +# include +# include +# include +# include #endif #include #include @@ -63,228 +67,214 @@ 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]); @@ -294,17 +284,22 @@ void MPPlayer::FillPosMsg(T_MsgHdr *MsgHdr, T_PositionMsg *PosMsg) { 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; @@ -317,16 +312,14 @@ void MPPlayer::FillMsgHdr(T_MsgHdr *MsgHdr, const int iMsgId) { } 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 diff --git a/src/MultiPlayer/mpplayer.hxx b/src/MultiPlayer/mpplayer.hxx index 04c5b648f..b2e7fda85 100644 --- a/src/MultiPlayer/mpplayer.hxx +++ b/src/MultiPlayer/mpplayer.hxx @@ -52,26 +52,23 @@ SG_USING_STD(string); // 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 @@ -80,84 +77,50 @@ public: * @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 diff --git a/src/MultiPlayer/multiplaymgr.cpp b/src/MultiPlayer/multiplaymgr.cpp new file mode 100644 index 000000000..126452c73 --- /dev/null +++ b/src/MultiPlayer/multiplaymgr.cpp @@ -0,0 +1,524 @@ +////////////////////////////////////////////////////////////////////// +// +// 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 +#endif + +#ifdef FG_MPLAYER_AS + +#include +#if !(defined(_MSC_VER) || defined(__MINGW32__)) +# include +# include +# include +#endif +#include +#include +#include +#include
+#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= "<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 + diff --git a/src/MultiPlayer/multiplaymgr.hpp b/src/MultiPlayer/multiplaymgr.hpp new file mode 100644 index 000000000..63add6b77 --- /dev/null +++ b/src/MultiPlayer/multiplaymgr.hpp @@ -0,0 +1,85 @@ +////////////////////////////////////////////////////////////////////// +// +// 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 +#endif + +#include STL_STRING +SG_USING_STD(string); +#include +SG_USING_STD(vector); + +#include +#include +#include
+ +// Maximum number of players that can exist at any time +// FIXME: use a list 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 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 + diff --git a/src/MultiPlayer/multiplayrxmgr.cxx b/src/MultiPlayer/multiplayrxmgr.cxx deleted file mode 100644 index 2129e9c52..000000000 --- a/src/MultiPlayer/multiplayrxmgr.cxx +++ /dev/null @@ -1,400 +0,0 @@ -// 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 -#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 -#if !(defined(_MSC_VER) || defined(__MINGW32__)) -# include -# include -# include -#endif -#include -#include - -#include -#include
- -#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 - diff --git a/src/MultiPlayer/multiplayrxmgr.hxx b/src/MultiPlayer/multiplayrxmgr.hxx deleted file mode 100644 index 5e836eb93..000000000 --- a/src/MultiPlayer/multiplayrxmgr.hxx +++ /dev/null @@ -1,108 +0,0 @@ -// 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 -#include - -// 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 - - - diff --git a/src/MultiPlayer/multiplaytxmgr.cxx b/src/MultiPlayer/multiplaytxmgr.cxx deleted file mode 100644 index 12570ffc7..000000000 --- a/src/MultiPlayer/multiplaytxmgr.cxx +++ /dev/null @@ -1,246 +0,0 @@ -// 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 -#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 -#if !(defined(_MSC_VER) || defined(__MINGW32__)) -# include -# include -# include -#endif -#include -#include - -#include -#include
- -#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 - diff --git a/src/MultiPlayer/multiplaytxmgr.hxx b/src/MultiPlayer/multiplaytxmgr.hxx deleted file mode 100644 index df9e80c4b..000000000 --- a/src/MultiPlayer/multiplaytxmgr.hxx +++ /dev/null @@ -1,101 +0,0 @@ -// 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 -#endif - -#include STL_STRING -SG_USING_STD(string); - -#include -#include - -// 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 - - - diff --git a/src/MultiPlayer/tiny_xdr.cpp b/src/MultiPlayer/tiny_xdr.cpp index ff994e393..2ec972795 100644 --- a/src/MultiPlayer/tiny_xdr.cpp +++ b/src/MultiPlayer/tiny_xdr.cpp @@ -2,7 +2,7 @@ // // 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. diff --git a/src/MultiPlayer/tiny_xdr.hpp b/src/MultiPlayer/tiny_xdr.hpp index aec182b00..7c66a8479 100644 --- a/src/MultiPlayer/tiny_xdr.hpp +++ b/src/MultiPlayer/tiny_xdr.hpp @@ -2,7 +2,7 @@ // // 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. diff --git a/src/Network/multiplay.cxx b/src/Network/multiplay.cxx index 0b6118b36..ebf511f88 100644 --- a/src/Network/multiplay.cxx +++ b/src/Network/multiplay.cxx @@ -107,7 +107,7 @@ bool FGMultiplay::process() { if (get_direction() == SG_IO_IN) { - globals->get_multiplayer_rx_mgr()->ProcessData(); + globals->get_multiplayer_mgr()->ProcessData(); } else if (get_direction() == SG_IO_OUT) { @@ -120,7 +120,7 @@ bool FGMultiplay::process() { sgQuat PlayerOrientation; sgMatrixToQuat(PlayerOrientation, posTrans); - globals->get_multiplayer_tx_mgr()->SendMyPosition(PlayerOrientation, PlayerPosition); + globals->get_multiplayer_mgr()->SendMyPosition(PlayerOrientation, PlayerPosition); } @@ -137,11 +137,11 @@ bool FGMultiplay::close() { 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(); } diff --git a/src/Network/multiplay.hxx b/src/Network/multiplay.hxx index c7459e21a..fd19a63e9 100644 --- a/src/Network/multiplay.hxx +++ b/src/Network/multiplay.hxx @@ -34,8 +34,7 @@ #include
#include
#include -#include -#include +#include #include "protocol.hxx" -- 2.39.5