]> git.mxchange.org Git - flightgear.git/blob - src/MultiPlayer/multiplaytxmgr.cxx
Multiplayer client/server system -- Message base class, "hello" message, and message...
[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 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #ifdef FG_MPLAYER_AS
29
30 /******************************************************************
31 * $Id$
32 *
33 * Description: The multiplayer tx manager provides is used
34 * to send data to another player or a server for an
35 * interactive multiplayer FlightGear simulation.
36 *
37 ******************************************************************/
38
39 #include <sys/types.h>
40 #if !(defined(_MSC_VER) || defined(__MINGW32__))
41 # include <sys/socket.h>
42 # include <netinet/in.h>
43 # include <arpa/inet.h>
44 #endif
45 #include <plib/netSocket.h>
46 #include <stdlib.h>
47
48 #include <simgear/debug/logstream.hxx>
49 #include <Main/fg_props.hxx>
50
51 #include "multiplaytxmgr.hxx"
52 #include "mpmessages.hxx"
53 #include "mpplayer.hxx"
54
55 // These constants are provided so that the ident command can list file versions.
56 const char sMULTIPLAYTXMGR_BID[] = "$Id$";
57 const char sMULTIPLAYTXMGR_HID[] = MULTIPLAYTXMGR_HID;
58
59
60
61 /******************************************************************
62 * Name: FGMultiplayTxMgr
63 * Description: Constructor.
64 ******************************************************************/
65 FGMultiplayTxMgr::FGMultiplayTxMgr() {
66
67     int iPlayerCnt;         // Count of players in player array
68
69     // Initialise private members
70     m_bInitialised = false;
71     mLocalPlayer = NULL;
72
73 }
74
75
76 /******************************************************************
77 * Name: ~FGMultiplayTxMgr
78 * Description: Destructor. Closes and deletes objects owned by
79 * this object.
80 ******************************************************************/
81 FGMultiplayTxMgr::~FGMultiplayTxMgr() {
82
83     Close();
84
85 }
86
87
88 /******************************************************************
89 * Name: init
90 * Description: Initialises multiplayer transmit
91 ******************************************************************/
92 bool FGMultiplayTxMgr::init(void) {
93
94
95     string sTxAddress;                          // Destination address
96     int iTxPort;
97     bool bSuccess = true;                       // Result of initialisation
98
99     // Initialise object if not already done
100     if (!m_bInitialised) {
101
102         // Set members from property values
103         string sTxAddress = fgGetString("/sim/multiplay/txhost");
104         iTxPort = fgGetInt("/sim/multiplay/txport");
105
106         SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayTxMgr::init - txaddress= "
107                                      << sTxAddress );
108         SG_LOG( SG_NETWORK, SG_INFO, "FGMultiplayTxMgr::init - txport= "
109                                      << iTxPort );
110         
111         if (iTxPort > 0) {
112
113
114             // Create and open tx socket
115             mDataTxSocket = new netSocket();
116             if (!mDataTxSocket->open(false)) {
117                 // Failed to open tx socket
118                 SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Failed to create data transmit socket" );
119                 bSuccess = false;
120             } else {
121                 mDataTxSocket->setBroadcast(true);
122                 if (mDataTxSocket->connect(sTxAddress.c_str(), iTxPort) != 0) {
123                     // Failed to connect tx socket
124                     SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Failed to connect data transmit socket" );
125                     bSuccess = false;
126                 }
127             }
128
129             // Create a player object for the local player
130             if (bSuccess) {
131                 mLocalPlayer = new MPPlayer();
132                 if (!mLocalPlayer->Open(fgGetString("/sim/multiplay/rxhost"), fgGetInt("/sim/multiplay/rxport"),
133                                         fgGetString("/sim/multiplay/callsign"), fgGetString("/sim/model/path"), true)) {
134                     SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Failed to create player object for local player" );
135                     bSuccess = false;
136                 }
137             }
138
139         // If Tx port == zero then don't initialise
140         } else {
141
142             SG_LOG( SG_NETWORK, SG_WARN, "FGMultiplayTxMgr::init - Tx Port is zero. Multiplay out disabled." );
143             bSuccess = false;
144
145         }
146
147         // Save manager state
148         m_bInitialised = bSuccess;
149
150     } else {
151         SG_LOG( SG_NETWORK, SG_ALERT, "FGMultiplayTxMgr::init - Attempt to init object that is already opened" );
152         bSuccess = false;
153     }
154
155
156     /* Return true if init succeeds */
157     return bSuccess;
158
159 }
160
161
162 /******************************************************************
163 * Name: Close
164 * Description: Closes and deletes the local player object. Closes
165 * and deletes the tx socket. Resets the object state to unitialised.
166 ******************************************************************/
167 void FGMultiplayTxMgr::Close(void) {
168
169
170     // Delete local player
171     if (mLocalPlayer) {
172         delete mLocalPlayer;
173         mLocalPlayer = NULL;
174     }
175
176     // Delete socket
177     if (mDataTxSocket) {
178         mDataTxSocket->close();
179         delete mDataTxSocket;
180         mDataTxSocket = NULL;
181     }
182
183     m_bInitialised = false;
184
185 }
186
187
188 /******************************************************************
189 * Name: SendMyPosition
190 * Description: Sends the position data for the local position.
191 ******************************************************************/
192 void FGMultiplayTxMgr::SendMyPosition(const sgMat4 PlayerPosMat4) {
193
194     T_MsgHdr MsgHdr;
195     T_PositionMsg PosMsg;
196     char sMsg[sizeof(T_MsgHdr) + sizeof(T_PositionMsg)];
197
198     if (m_bInitialised) {
199         mLocalPlayer->SetPosition(PlayerPosMat4);
200         mLocalPlayer->FillPosMsg(&MsgHdr, &PosMsg);
201         memcpy(sMsg, &MsgHdr, sizeof(T_MsgHdr));
202         memcpy(sMsg + sizeof(T_MsgHdr), &PosMsg, sizeof(T_PositionMsg));
203         mDataTxSocket->send(sMsg, sizeof(T_MsgHdr) + sizeof(T_PositionMsg), 0);
204     }
205
206
207 }
208
209
210
211 /******************************************************************
212 * Name: SendTextMessage
213 * Description: Sends a message to the player. The message must
214 * contain a valid and correctly filled out header and optional
215 * message body.
216 ******************************************************************/
217 void FGMultiplayTxMgr::SendTextMessage(const string &sMsgText) const {
218
219     bool bResult = false;
220     T_MsgHdr MsgHdr;
221     T_ChatMsg ChatMsg;
222     int iNextBlockPosition = 0;
223     char sMsg[sizeof(T_MsgHdr) + sizeof(T_ChatMsg)];
224
225     if (m_bInitialised) {
226
227         mLocalPlayer->FillMsgHdr(&MsgHdr, CHAT_MSG_ID);
228
229         // Divide the text string into blocks that fit in the message
230         // and send the blocks.
231         while (iNextBlockPosition < sMsgText.length()) {
232             strncpy(ChatMsg.sText, sMsgText.substr(iNextBlockPosition, MAX_CHAT_MSG_LEN - 1).c_str(), MAX_CHAT_MSG_LEN);
233             ChatMsg.sText[MAX_CHAT_MSG_LEN - 1] = '\0';
234             memcpy(sMsg, &MsgHdr, sizeof(T_MsgHdr));
235             memcpy(sMsg + sizeof(T_MsgHdr), &ChatMsg, sizeof(T_ChatMsg));
236             mDataTxSocket->send(sMsg, sizeof(T_MsgHdr) + sizeof(T_ChatMsg), 0);
237             iNextBlockPosition += MAX_CHAT_MSG_LEN - 1;
238         }
239
240     }
241
242 }
243
244 #endif // FG_MPLAYER_AS
245