1
0
Fork 0
flightgear/src/MultiPlayer/multiplaytxmgr.cxx
2003-04-20 19:42:07 +00:00

245 lines
7.7 KiB
C++

// 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_WARN, "FGMultiplayTxMgr::init - Tx Port is zero. Multiplay out disabled." );
bSuccess = false;
}
// Save manager state
m_bInitialised = bSuccess;
} else {
SG_LOG( SG_NETWORK, SG_ALERT, "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 sgMat4 PlayerPosMat4) {
T_MsgHdr MsgHdr;
T_PositionMsg PosMsg;
char sMsg[sizeof(T_MsgHdr) + sizeof(T_PositionMsg)];
if (m_bInitialised) {
mLocalPlayer->SetPosition(PlayerPosMat4);
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;
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