]> git.mxchange.org Git - flightgear.git/blob - src/MultiPlayer/multiplaytxmgr.cxx
Latest MultiPlayer updates
[flightgear.git] / src / MultiPlayer / multiplaytxmgr.cxx
1 // multiplaytxmgr.cxx -- routines for transmitting multiplayer data
2 //                       for Flightgear
3 //
4 // Written by Duncan McCreanor, started February 2003.
5 // duncan.mccreanor@airservicesaustralia.com
6 //
7 // Copyright (C) 2003  Airservices Australia
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License as
11 // published by the Free Software Foundation; either version 2 of the
12 // License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 // General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 //
23
24 /******************************************************************
25 * $Id$
26 *
27 * Description: The multiplayer tx manager provides is used
28 * to send data to another player or a server for an
29 * interactive multiplayer FlightGear simulation.
30 *
31 ******************************************************************/
32
33 #include <sys/types.h>
34 #ifndef _MSC_VER
35 # include <sys/socket.h>
36 # include <netinet/in.h>
37 # include <arpa/inet.h>
38 #endif
39 #include <plib/netSocket.h>
40 #include <stdlib.h>
41
42 #include <simgear/debug/logstream.hxx>
43 #include <Main/fg_props.hxx>
44
45 #include "multiplaytxmgr.hxx"
46 #include "mpmessages.hxx"
47 #include "mpplayer.hxx"
48
49 // These constants are provided so that the ident command can list file versions.
50 const char sMULTIPLAYTXMGR_BID[] = "$Id$";
51 const char sMULTIPLAYTXMGR_HID[] = MULTIPLAYTXMGR_HID;
52
53
54
55 /******************************************************************
56 * Name: FGMultiplayTxMgr
57 * Description: Constructor.
58 ******************************************************************/
59 FGMultiplayTxMgr::FGMultiplayTxMgr() {
60
61     int iPlayerCnt;         // Count of players in player array
62
63     // Initialise private members
64     m_bInitialised = false;
65     mLocalPlayer = NULL;
66
67 }
68
69
70 /******************************************************************
71 * Name: ~FGMultiplayTxMgr
72 * Description: Destructor. Closes and deletes objects owned by
73 * this object.
74 ******************************************************************/
75 FGMultiplayTxMgr::~FGMultiplayTxMgr() {
76
77     Close();
78
79 }
80
81
82 /******************************************************************
83 * Name: init
84 * Description: Initialises multiplayer transmit
85 ******************************************************************/
86 bool FGMultiplayTxMgr::init(void) {
87
88
89     string sTxAddress;                          // Destination address
90     int iTxPort;
91     bool bSuccess = true;                       // Result of initialisation
92
93     // Initialise object if not already done
94     if (!m_bInitialised) {
95
96         // Set members from property values
97         string sTxAddress = fgGetString("/sim/multiplay/txhost");
98         iTxPort = fgGetInt("/sim/multiplay/txport");
99
100         SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayTxMgr::init - txaddress= "
101                                      << sTxAddress );
102         SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayTxMgr::init - txport= "
103                                      << iTxPort );
104         
105         if (iTxPort > 0) {
106
107
108             // Create and open tx socket
109             mDataTxSocket = new netSocket();
110             if (!mDataTxSocket->open(false)) {
111                 // Failed to open tx socket
112                 cerr << "FGMultiplayTxMgr::init - Failed to create data transmit socket" << endl;
113                 bSuccess = false;
114             } else {
115                 mDataTxSocket->setBroadcast(true);
116                 if (mDataTxSocket->connect(sTxAddress.c_str(), iTxPort) != 0) {
117                     // Failed to connect tx socket
118                     cerr << "FGMultiplayTxMgr::init - Failed to connect data transmit socket" << endl;
119                     bSuccess = false;
120                 }
121             }
122
123             // Create a player object for the local player
124             if (bSuccess) {
125                 mLocalPlayer = new MPPlayer();
126                 if (!mLocalPlayer->Open(fgGetString("/sim/multiplay/rxhost"), fgGetInt("/sim/multiplay/rxport"),
127                                         fgGetString("/sim/multiplay/callsign"), fgGetString("/sim/model/path"), true)) {
128                     cerr << "FGMultiplayTxMgr::init - Failed to create player object for local player" << endl;
129                     bSuccess = false;
130                 }
131             }
132
133         // If Tx port == zero then don't initialise
134         } else {
135
136             SG_LOG( SG_NETWORK, SG_WARN, "FGMultiplayTxMgr::init - Tx Port is zero. Multiplay out disabled." );
137             bSuccess = false;
138
139         }
140
141         // Save manager state
142         m_bInitialised = bSuccess;
143
144     } else {
145         SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Attempt to init object that is already opened" );
146         bSuccess = false;
147     }
148
149
150     /* Return true if init succeeds */
151     return bSuccess;
152
153 }
154
155
156 /******************************************************************
157 * Name: Close
158 * Description: Closes and deletes the local player object. Closes
159 * and deletes the tx socket. Resets the object state to unitialised.
160 ******************************************************************/
161 void FGMultiplayTxMgr::Close(void) {
162
163
164     // Delete local player
165     if (mLocalPlayer) {
166         delete mLocalPlayer;
167         mLocalPlayer = NULL;
168     }
169
170     // Delete socket
171     if (mDataTxSocket) {
172         mDataTxSocket->close();
173         delete mDataTxSocket;
174         mDataTxSocket = NULL;
175     }
176
177     m_bInitialised = false;
178
179 }
180
181
182 /******************************************************************
183 * Name: SendMyPosition
184 * Description: Sends the position data for the local position.
185 ******************************************************************/
186 void FGMultiplayTxMgr::SendMyPosition(const sgMat4 PlayerPosMat4) {
187
188     T_MsgHdr MsgHdr;
189     T_PositionMsg PosMsg;
190     char sMsg[sizeof(T_MsgHdr) + sizeof(T_PositionMsg)];
191
192     if (m_bInitialised) {
193         mLocalPlayer->SetPosition(PlayerPosMat4);
194         mLocalPlayer->FillPosMsg(&MsgHdr, &PosMsg);
195         memcpy(sMsg, &MsgHdr, sizeof(T_MsgHdr));
196         memcpy(sMsg + sizeof(T_MsgHdr), &PosMsg, sizeof(T_PositionMsg));
197         mDataTxSocket->send(sMsg, sizeof(T_MsgHdr) + sizeof(T_PositionMsg), 0);
198     }
199
200
201 }
202
203
204
205 /******************************************************************
206 * Name: SendTextMessage
207 * Description: Sends a message to the player. The message must
208 * contain a valid and correctly filled out header and optional
209 * message body.
210 ******************************************************************/
211 void FGMultiplayTxMgr::SendTextMessage(const string &sMsgText) const {
212
213     bool bResult = false;
214     T_MsgHdr MsgHdr;
215     T_ChatMsg ChatMsg;
216     int iNextBlockPosition = 0;
217     char sMsg[sizeof(T_MsgHdr) + sizeof(T_ChatMsg)];
218
219     if (m_bInitialised) {
220
221         mLocalPlayer->FillMsgHdr(&MsgHdr, CHAT_MSG_ID);
222
223         // Divide the text string into blocks that fit in the message
224         // and send the blocks.
225         while (iNextBlockPosition < sMsgText.length()) {
226             strncpy(ChatMsg.sText, sMsgText.substr(iNextBlockPosition, MAX_CHAT_MSG_LEN - 1).c_str(), MAX_CHAT_MSG_LEN);
227             ChatMsg.sText[MAX_CHAT_MSG_LEN - 1] = '\0';
228             memcpy(sMsg, &MsgHdr, sizeof(T_MsgHdr));
229             memcpy(sMsg + sizeof(T_MsgHdr), &ChatMsg, sizeof(T_ChatMsg));
230             mDataTxSocket->send(sMsg, sizeof(T_MsgHdr) + sizeof(T_ChatMsg), 0);
231             iNextBlockPosition += MAX_CHAT_MSG_LEN - 1;
232         }
233
234     }
235
236 }
237