1 /* $Id: servercommunicator.cpp,v 1.8.4.1 2006/03/09 14:59:42 chfreund Exp $ */
2
3 // #include "tcpconnection.hpp"
4 #include "servercommunicator.hpp"
5 // #include "clientcommunicator.hpp"
6 #include "clientconnection.hpp"
7 #include "clientconnectionlistener.hpp"
8 #include "clientconnectiondirect.hpp"
9 #include "gamereplay.hpp"
10 #include "wopsettings.hpp"
11
ServerCommunicator(World * world,GameReplay * replay)12 ServerCommunicator::ServerCommunicator( World* world, GameReplay* replay )
13 : m_directConnection( 0 ), m_world( world ), m_frameSequenceCounter( 0 ),
14 m_replay( replay ) {
15 // initialize vector with unused client ids
16 // m_freeClientIDs.reserve(256);
17 for ( Uint8 i = 0; i < 255; i++ ) {
18 m_freeClientIDs.push_back( i );
19 }
20
21 // add TCP listener
22 ClientConnectionListenerTCP* listener = new ClientConnectionListenerTCP( this, 0xb8b8 );
23 m_listeners.push_back( listener );
24 }
25
~ServerCommunicator()26 ServerCommunicator::~ServerCommunicator() {
27 // delete all listeners
28 for ( unsigned int i = 0; i < m_listeners.size(); i++ ) {
29 ClientConnectionListener* listener = m_listeners[i];
30 delete listener;
31 }
32 // delete all connections
33 for ( std::vector<ClientConnection*>::iterator it = m_idleConnections.begin();
34 it != m_idleConnections.end(); it++ )
35 delete *it;
36 for ( std::vector<ClientConnection*>::iterator it = m_activeConnections.begin();
37 it != m_activeConnections.end(); it++ )
38 delete *it;
39 /* if ( m_directConnection )
40 delete m_directConnection;*/
41 }
42
listenForClients()43 void ServerCommunicator::listenForClients() {
44 for ( std::vector<ClientConnectionListener*>::iterator it = m_listeners.begin();
45 it != m_listeners.end(); it++ ) {
46 while ( ClientConnection* connection = (*it)->getNewConnection( m_freeClientIDs.front() ) ) {
47 LOG( 2 ) INFO( "ServerCommunicator::listenForClients: adding new connection\n" );
48 addConnection( connection );
49 // connection->openConnection( clientID );
50 }
51 }
52 }
53
collectEvents()54 void ServerCommunicator::collectEvents() {
55 DBG( 5 ) INFO( "ServerCommunicator::collectEvents: collecting events\n" );
56
57 std::vector<Player*> playerVector = m_world->getPlayerList();
58
59 // Collect game events from all active connected clients
60 for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
61 ClientConnection* connection = m_activeConnections[c];
62 EventMessage* eventMessage = connection->getEventMessage();
63 if ( eventMessage ) {
64 // Copy the events for all players in this client in the global
65 // echo message
66 for ( Uint8 p = 0; p < connection->getNumberConnectedPlayers(); p++ ) {
67 // get global index for player
68 Uint8 index = m_world->getPlayerIndex( connection->getGlobalPlayerNumber( p ) );
69 if ( index >= m_world->getNumberPlayers() ) {
70 DBG( 2 ) INFO( "ServerCommunicator::collectEvents: player with ID %d not found in player vector -> ignoring event\n", connection->getGlobalPlayerNumber( p ) );
71 continue;
72 }
73 // store event at the right position
74 if ( p < eventMessage->numberEvents ) {
75 m_echoMessage.event[index] = eventMessage->event[p];
76 // check for replay bookmark
77 if ( m_replay ) {
78 static int bookmarkDeadTime = 0;
79 if ( bookmarkDeadTime > 0 )
80 bookmarkDeadTime--;
81 else if ( eventMessage->event[p].testAnyActions( Event::INSERT_REPLAY_BOOKMARK ) ) {
82 LOG( 1 ) INFO( "ServerCommunicator::collectEvents: inserting replay bookmark\n" );
83 m_replay->addBookmark();
84 bookmarkDeadTime = 25 * 5; // 5 seconds bookmark dead time
85 }
86 }
87 }
88 else {
89 m_echoMessage.event[index] = Event::EMPTY;
90 }
91 }
92
93 delete eventMessage;
94 }
95 else {
96 DBG( 2 ) INFO( "ServerCommunicator::collectEvents: no event message "
97 " from connection %d, lag is now %d\n", c, connection->getLag() );
98 for ( Uint8 p = 0; p < connection->getNumberConnectedPlayers(); p++ ) {
99 Uint8 index = m_world->getPlayerIndex( connection->getGlobalPlayerNumber( p ) );
100 if ( index >= m_world->getNumberPlayers() ) {
101 DBG( 2 ) INFO( "ServerCommunicator::collectEvents: player with ID %d not found in player vector -> setting event nonetheless to N_A\n", connection->getGlobalPlayerNumber( p ) );
102 continue;
103 }
104
105 m_echoMessage.event[index] = Event::N_A;
106 }
107 }
108 }
109 }
110
broadcastEcho()111 void ServerCommunicator::broadcastEcho() {
112 m_echoMessage.frame = m_world->getFrame();
113 m_echoMessage.randomCounter = m_world->getRandom().getCounter();
114 m_echoMessage.numberMessages = m_frameSequenceCounter;
115
116 DBG( 5 ) INFO( "ServerCommunicator::broadcastEcho: bc echo for frame %d (random = %d, messages = %d)\n", m_echoMessage.frame, m_echoMessage.randomCounter, m_echoMessage.numberMessages );
117 for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
118 ClientConnection* connection = m_activeConnections[c];
119 connection->sendEchoMessage( &m_echoMessage );
120 }
121 }
122
handleMessages()123 void ServerCommunicator::handleMessages() {
124 Message* message;
125 m_frameSequenceCounter = 0;
126 for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
127 ClientConnection* connection = m_activeConnections[c];
128 while ( ( message = connection->getMessage() ) ) {
129 // Handle the message properly
130 switch ( message->type ) {
131 case Message::ADD_PLAYER: {
132 DBG( 2 ) INFO( "ServerCommunicator::handleMessages: handling ADD_PLAYER message\n" );
133 AddPlayerMessage* addPlayerMessage =
134 static_cast<AddPlayerMessage*>( message );
135 Player* player = addPlayerMessage->player;
136
137 Uint8 playerID = m_world->getNextPlayerID();
138 addPlayerMessage->globalPlayerNumber = playerID;
139 player->setPlayerID( playerID );
140 connection->setGlobalPlayerNumber( connection->getNumberConnectedPlayers(),
141 playerID );
142
143 // TODO: Can we assume that the new player is added to the end of the player vector?
144 Uint8 index = m_world->getNumberPlayers();
145 DBG( 2 ) INFO( "Setting action for player %d to %x\n", index, Event::EMPTY );
146 m_echoMessage.event[index].setAction( Event::EMPTY );
147 connection->addPlayer();
148
149 // store event in replay
150 if ( m_replay ) m_replay->addPlayerEnter( *player );
151
152 m_world->addPlayer( player );
153 addPlayerMessage->frame = m_world->getFrame();
154 addPlayerMessage->frameSequenceIndex = m_frameSequenceCounter++;
155 broadcastMessage( addPlayerMessage );
156 break;
157 }
158 case Message::CHAT: {
159 DBG( 2 ) INFO( "ServerCommunicator::handleMessages: handling CHAT message\n" );
160 ChatMessage* chatMessage =
161 static_cast<ChatMessage*>( message );
162 m_frameSequenceCounter++;
163 // store message in replay
164 if ( m_replay ) m_replay->addChatMessage( chatMessage->message );
165 broadcastMessage( chatMessage );
166 break;
167 }
168 case Message::QUIT: {
169 DBG( 2 ) INFO( "ServerCommunicator::handleMessages: handling QUIT message\n" );
170 // disabled to avoid compiler warning, Tom
171 //QuitMessage* quitMessage =
172 // static_cast<QuitMessage*>( message );
173 connection->closeConnection();
174 break;
175 }
176 default:
177 ASSERT( false, "ServerCommunicator::handleMessages: don't know how to handle message of type %d\n", message->type );
178 break;
179 }
180 delete message;
181 }
182 }
183
184 // Handle messages from idle connections
185 for ( unsigned int c = 0; c < m_idleConnections.size(); c++ ) {
186 ClientConnection* connection = m_idleConnections[c];
187 while ( ( message = connection->getMessage() ) ) {
188 DBG( 2 ) INFO( "ServerCommunicator::handleMessages: got message from idle connection %d\n", c );
189 if ( message->type != Message::REQUEST ) {
190 LOG( 2 ) INFO( "ServerCommunicator::handleMessages: can only handle REQUEST messages from idle clients\n" );
191 delete message;
192 continue;
193 }
194
195 RequestMessage* requestMessage = static_cast<RequestMessage*>( message );
196
197 if ( requestMessage->request == Message::WORLD ) {
198 WorldMessage* worldMessage = NEW WorldMessage();
199 worldMessage->world = m_world;
200 DBG( 2 ) INFO( "ServerCommunicator::handleMessages: send world to the client\n" );
201 connection->setCompression( true );
202 connection->setProgressListener( this );
203 connection->sendMessage( worldMessage );
204 connection->setCompression( false );
205 connection->setProgressListener( 0 );
206 delete worldMessage;
207 // change client state from 'idle' to 'active'
208 m_idleConnections.erase( m_idleConnections.begin() + c );
209 c--;
210 m_activeConnections.push_back( connection );
211 }
212 else if ( requestMessage->request == Message::INFO ) {
213 WopSettings* settings = WopSettings::getInstance();
214 InfoMessage infoMessage;
215 infoMessage.theme = settings->getTheme();
216 infoMessage.gamemode = settings->getGameMode();
217 infoMessage.numberPlayers = m_world->getNumberPlayers();
218 for ( int p = 0; p < m_world->getNumberPlayers(); p++ ) {
219 infoMessage.player.push_back( m_world->getPlayer( p ) );
220 }
221 connection->sendMessage( &infoMessage );
222 }
223 else {
224 LOG( 2 ) INFO( "ServerCommunicator::handleMessages: cannot handle request of type %d\n",
225 requestMessage->request );
226 }
227
228 delete requestMessage;
229 }
230 }
231
232 // Remove disconnected clients
233 for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
234 ClientConnection* connection = m_activeConnections[c];
235 if ( !connection->isConnected() ) {
236 DBG( 2 ) INFO( "ServerCommunicator::handleMessages: removing active client %d\n", c );
237 cleanupConnection( connection );
238 // recover client ID
239 Uint8 clientID = connection->getId();
240 m_freeClientIDs.push_back( clientID );
241 delete connection;
242 m_activeConnections.erase( m_activeConnections.begin() + c );
243 c--;
244 }
245 }
246 for ( unsigned int c = 0; c < m_idleConnections.size(); c++ ) {
247 ClientConnection* connection = m_idleConnections[c];
248 if ( !connection->isConnected() ) {
249 DBG( 2 ) INFO( "ServerCommunicator::handleMessages: removing idle client %d\n", c );
250 // cleanupConnection( connection );
251 // recover client ID
252 Uint8 clientID = connection->getId();
253 m_freeClientIDs.push_back( clientID );
254 delete connection;
255 m_idleConnections.erase( m_idleConnections.begin() + c );
256 c--;
257 }
258 }
259 }
260
addConnection(ClientConnection * connection)261 Uint8 ServerCommunicator::addConnection( ClientConnection* connection ) {
262 INFO( "ServerCommunicator::addConnection: client is connecting\n" );
263 Uint8 newClientID = m_freeClientIDs.front();
264 m_freeClientIDs.pop_front();
265 m_idleConnections.push_back( connection );
266 return newClientID;
267 }
268
getDirectConnection(ServerConnectionDirect * serverConnection)269 ClientConnectionDirect* ServerCommunicator::getDirectConnection
270 ( ServerConnectionDirect* serverConnection ) {
271 // INFO( "ServerCommunicator::getDirectConnection: local client is connecting\n" );
272 ClientConnectionDirect* clientConnection =
273 new ClientConnectionDirect( this, serverConnection );
274 // m_connections.push_back( clientConnection );
275 return clientConnection;
276 }
277
broadcastMessage(Message * message)278 void ServerCommunicator::broadcastMessage( Message* message ) {
279 for ( std::vector<ClientConnection*>::iterator it =
280 m_activeConnections.begin(); it != m_activeConnections.end(); it++ ) {
281 ClientConnection* connection = *it;
282 connection->sendMessage( message );
283 }
284 }
285
cleanupConnection(ClientConnection * connection)286 void ServerCommunicator::cleanupConnection( ClientConnection* connection ) {
287 // Remove all players from this client
288 for ( Uint8 p = 0; p < connection->getNumberConnectedPlayers(); p++ ) {
289 Uint8 globalPlayerID = connection->getGlobalPlayerNumber( p );
290
291 // fetch player
292 Player* player = m_world->getPlayerByID( globalPlayerID );
293 // store event in replay
294 if ( m_replay ) m_replay->addPlayerQuit( globalPlayerID );
295 // remove player from world
296 m_world->removePlayer( globalPlayerID );
297 // delete player object
298 delete player;
299
300 // inform all clients
301 RemovePlayerMessage message;
302 message.playerNumber = globalPlayerID;
303 message.frame = m_world->getFrame();
304 message.frameSequenceIndex = m_frameSequenceCounter++;
305
306 broadcastMessage( &message );
307 }
308 }
309
sendProgress(Sint32 size,Sint32 sent)310 void ServerCommunicator::sendProgress( Sint32 size, Sint32 sent ) {
311 // inform all active clients about sync progress
312 SyncProgressMessage message;
313 message.messageSize = size;
314 message.dataSent = sent;
315 for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
316 ClientConnection* connection = m_activeConnections[c];
317 connection->sendEchoMessage( &message );
318 }
319 }
320
recvProgress(Sint32 size,Sint32 received)321 void ServerCommunicator::recvProgress( Sint32 size, Sint32 received ) {
322 }
323