Rev 136 | Rev 153 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | // network.cpp |
2 | |||
3 | #include "common.h" |
||
4 | |||
5 | |||
6 | // prototypes of local functions |
||
7 | static void StartThread_ListenToServer (void *thread_parms); |
||
8 | static void EvaluateServerReply (player_t *player); |
||
9 | |||
10 | |||
11 | bool PlayerNetwork_Init (player_t *player) |
||
12 | { |
||
13 | // this function initializes the network layer and connects to the chess server |
||
14 | |||
15 | WSADATA wsaData; |
||
16 | struct hostent *hostinfo; |
||
17 | struct sockaddr_in service; |
||
18 | unsigned long nonblocking_mode; |
||
19 | char ascii_hostname[256]; |
||
20 | |||
21 | onlineplayers = NULL; // ensure the online players array is empty |
||
22 | onlineplayer_count = 0; // and reset the online players count |
||
23 | onlineplayers_updated = false; |
||
24 | |||
25 | soughtgames = NULL; // ensure the sought games array is empty |
||
26 | soughtgame_count = 0; // and reset the sought games count |
||
27 | soughtgames_updated = false; |
||
28 | lastsought_time = 0; |
||
29 | |||
30 | chatterchannels = NULL; // ensure the chatter channels array is empty |
||
31 | chatterchannel_count = 0; // and reset the chatter channels count |
||
32 | chatterchannels_updated = false; |
||
33 | selected_chatterchannel = NULL; |
||
34 | |||
35 | PlayerCards_Init (); // initialize the player cards array |
||
36 | Challenges_Init (); // initialize the challenges array |
||
37 | Interlocutors_Init (); // initialize the interlocutors array |
||
38 | |||
39 | server_motd[0] = 0; // reset the server MOTD |
||
40 | |||
41 | player->is_connected = false; // remember we aren't connected yet |
||
42 | player->is_logged_in = false; // and not logged in either |
||
43 | player->is_in_game = false; // we aren't in game either |
||
44 | player->game_number = 0; |
||
45 | player->remaining_seconds = 0; |
||
46 | player->our_socket = INVALID_SOCKET; // and that we have no socket yet |
||
47 | player->name[0] = 0; // player name undefined |
||
48 | |||
49 | // initialize WinSock |
||
50 | if (WSAStartup (MAKEWORD (2, 2), &wsaData) != 0) |
||
51 | { |
||
52 | messagebox.hWndParent = hMainWnd; |
||
53 | wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage")); |
||
54 | wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed")); |
||
55 | messagebox.flags = MB_ICONWARNING | MB_OK; |
||
56 | DialogBox_Message (&messagebox); // display a modeless error message box |
||
57 | |||
58 | PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message |
||
59 | return (false); |
||
60 | } |
||
61 | |||
62 | // get the chess server's IP address from the host name |
||
63 | ConvertTo7BitASCII (ascii_hostname, sizeof (ascii_hostname), options.network.server_address); |
||
64 | hostinfo = gethostbyname (ascii_hostname); |
||
65 | if (hostinfo == NULL) |
||
66 | { |
||
67 | messagebox.hWndParent = hMainWnd; |
||
68 | wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage")); |
||
69 | wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed")); |
||
70 | messagebox.flags = MB_ICONWARNING | MB_OK; |
||
71 | DialogBox_Message (&messagebox); // display a modeless error message box |
||
72 | |||
73 | PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message |
||
74 | return (false); |
||
75 | } |
||
76 | |||
77 | // fill in the sockaddr server structure with the server hostinfo data |
||
78 | service.sin_family = AF_INET; |
||
79 | service.sin_addr.s_addr = inet_addr (inet_ntoa (*(struct in_addr *) hostinfo->h_addr_list[0])); |
||
80 | service.sin_port = htons (options.network.server_port); |
||
81 | |||
82 | // create our socket |
||
83 | if ((player->our_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) |
||
84 | { |
||
85 | messagebox.hWndParent = hMainWnd; |
||
86 | wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage")); |
||
87 | wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed")); |
||
88 | messagebox.flags = MB_ICONWARNING | MB_OK; |
||
89 | DialogBox_Message (&messagebox); // display a modeless error message box |
||
90 | |||
91 | PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message |
||
92 | return (false); |
||
93 | } |
||
94 | |||
95 | // connect the game to the chess server using that socket |
||
96 | if (connect (player->our_socket, (struct sockaddr *) &service, sizeof (service)) == -1) |
||
97 | { |
||
98 | messagebox.hWndParent = hMainWnd; |
||
99 | wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage")); |
||
100 | wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed")); |
||
101 | messagebox.flags = MB_ICONWARNING | MB_OK; |
||
102 | DialogBox_Message (&messagebox); // display a modeless error message box |
||
103 | |||
104 | PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message |
||
105 | return (false); |
||
106 | } |
||
107 | |||
108 | // set it to be non-blocking (but only AFTER the connection is made) |
||
109 | nonblocking_mode = 1; |
||
110 | if (ioctlsocket (player->our_socket, FIONBIO, &nonblocking_mode) == SOCKET_ERROR) |
||
111 | { |
||
112 | messagebox.hWndParent = hMainWnd; |
||
113 | wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage")); |
||
114 | wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_NetworkInitializationFailed")); |
||
115 | messagebox.flags = MB_ICONWARNING | MB_OK; |
||
116 | DialogBox_Message (&messagebox); // display a modeless error message box |
||
117 | |||
118 | PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message |
||
119 | return (false); |
||
120 | } |
||
121 | |||
122 | // initialize the debug log file |
||
123 | Debug_Init (L"Chess server output.txt"); |
||
124 | |||
125 | player->is_connected = true; // remember we are connected |
||
126 | return (true); // finished, we have a valid, connected socket |
||
127 | } |
||
128 | |||
129 | |||
130 | void PlayerNetwork_Shutdown (player_t *player) |
||
131 | { |
||
132 | // this function shutdowns the network layer |
||
133 | |||
134 | int chatterchannel_index; |
||
135 | |||
136 | // shutdown the socket if it is open. This will disconnect us from the server. |
||
137 | if (player->our_socket != INVALID_SOCKET) |
||
138 | closesocket (player->our_socket); // close the network socket |
||
139 | player->our_socket = INVALID_SOCKET; |
||
140 | |||
141 | player->is_connected = false; // remember we are no longer connected |
||
142 | player->is_logged_in = false; // and not logged in either |
||
143 | player->is_in_game = false; // we aren't in game either |
||
144 | player->game_number = 0; |
||
145 | player->remaining_seconds = 0; |
||
146 | player->name[0] = 0; // player name undefined |
||
147 | |||
148 | server_motd[0] = 0; // reset the server MOTD |
||
149 | |||
150 | // cycle through all chatter channels we know... |
||
151 | for (chatterchannel_index = 0; chatterchannel_index < chatterchannel_count; chatterchannel_index++) |
||
152 | { |
||
153 | SAFE_free ((void **) &chatterchannels[chatterchannel_index].members); // free their member list |
||
154 | chatterchannels[chatterchannel_index].member_count = 0; // reset their members count |
||
155 | } |
||
156 | SAFE_free ((void **) &chatterchannels); // free the chatter channels array |
||
157 | chatterchannel_count = 0; // and reset the chatter channels count |
||
158 | chatterchannels_updated = false; |
||
159 | selected_chatterchannel = NULL; |
||
160 | |||
161 | SAFE_free ((void **) &soughtgames); // free the sought games array |
||
162 | soughtgame_count = 0; // and reset the sought games count |
||
163 | soughtgames_updated = false; |
||
164 | |||
165 | SAFE_free ((void **) &onlineplayers); // free the online players array |
||
166 | onlineplayer_count = 0; // and reset the online players count |
||
167 | onlineplayers_updated = false; |
||
168 | |||
169 | Interlocutors_Shutdown (); // shutdown the interlocutors |
||
170 | Challenges_Shutdown (); // shutdown the challenges |
||
171 | PlayerCards_Shutdown (); // shutdown the player cards |
||
172 | |||
173 | // shutdown all possible opened UI windows |
||
174 | if (IsWindow (hChatterChannelsWnd)) |
||
175 | DestroyWindow (hChatterChannelsWnd); |
||
176 | hChatterChannelsWnd = NULL; |
||
177 | if (IsWindow (hGamesWnd)) |
||
178 | DestroyWindow (hGamesWnd); |
||
179 | hGamesWnd = NULL; |
||
180 | if (IsWindow (hMOTDWnd)) |
||
181 | DestroyWindow (hMOTDWnd); |
||
182 | hMOTDWnd = NULL; |
||
183 | if (IsWindow (hOpponentsWnd)) |
||
184 | DestroyWindow (hOpponentsWnd); |
||
185 | hOpponentsWnd = NULL; |
||
186 | if (IsWindow (hSoughtWnd)) |
||
187 | DestroyWindow (hSoughtWnd); |
||
188 | hSoughtWnd = NULL; |
||
189 | |||
190 | // shutdown WinSock |
||
191 | WSACleanup (); |
||
192 | |||
193 | return; // finished |
||
194 | } |
||
195 | |||
196 | |||
197 | bool PlayerNetwork_Think (player_t *player) |
||
198 | { |
||
199 | // this function is called once per game tick to listen to the network and react to what the server tells us. Returns TRUE |
||
200 | // if we need to update the scene. |
||
201 | |||
202 | player_t *local_player; |
||
203 | char *block_start; |
||
204 | char *block_end; |
||
205 | char *ascii_sendbuffer; // mallocated |
||
206 | wchar_t *widechar_buffer; // mallocated |
||
207 | wchar_t *widechar_line; |
||
208 | int send_retval; |
||
209 | int recv_retval; |
||
210 | int byte_index; |
||
211 | int rewrite_index; |
||
212 | int length; |
||
213 | bool do_update; |
||
214 | |||
215 | // are we NOT connected yet ? |
||
216 | if (!player->is_connected) |
||
217 | return (false); // consistency check: if we aren't connected, don't do anything |
||
218 | |||
219 | // are we NOT logged in yet AND is our socket valid AND is there nothing in the center of the screen yet ? |
||
220 | if (!player->is_logged_in && (player->our_socket != INVALID_SOCKET) && !the_scene.gui.central_text.is_displayed) |
||
221 | { |
||
140 | pmbaty | 222 | Scene_UpdateText (&the_scene.gui.central_text, RGBA_TO_RGBACOLOR (255, 255, 255, 191), DURATION_INFINITE, true, LOCALIZE (L"Connecting")); // display "connecting" in the middle of the screen |
1 | pmbaty | 223 | the_scene.gui.want_spinwheel = true; // start spinning wheel |
224 | } |
||
225 | |||
226 | do_update = false; // assume we don't need to update the scene until told otherwise |
||
227 | |||
228 | //////////////////////////// |
||
229 | // BEGIN listening to server |
||
230 | |||
231 | // proceed in filling the ascii buffer with what's coming |
||
232 | |||
233 | // get a hand on the end of the player's recv buffer and compute its remaining size |
||
234 | length = strlen (player->ascii_recvbuffer); |
||
235 | |||
236 | // if the server sent us something, append it to what we've received |
||
237 | recv_retval = recv (player->our_socket, &player->ascii_recvbuffer[length], player->recvbuffer_size - length, 0); |
||
238 | if (recv_retval > 0) |
||
239 | { |
||
240 | // parse all received data and eradicate all carriage returns. Also convert %'s to a safer glyph. |
||
241 | rewrite_index = 0; |
||
242 | for (byte_index = 0; byte_index < recv_retval; byte_index++) |
||
243 | if (player->ascii_recvbuffer[length + byte_index] != '\r') |
||
244 | { |
||
245 | if (player->ascii_recvbuffer[length + byte_index] == '%') |
||
246 | player->ascii_recvbuffer[length + rewrite_index] = '¤'; |
||
247 | else |
||
248 | player->ascii_recvbuffer[length + rewrite_index] = player->ascii_recvbuffer[length + byte_index]; |
||
249 | rewrite_index++; |
||
250 | } |
||
251 | player->ascii_recvbuffer[length + rewrite_index] = 0; // terminate the buffer ourselves |
||
252 | length = strlen (player->ascii_recvbuffer); // and update the new recvbuffer's length |
||
253 | } |
||
254 | else if (recv_retval == SOCKET_ERROR) |
||
255 | { |
||
256 | recv_retval = WSAGetLastError (); // ask Windows to be more specific about the error |
||
257 | if (recv_retval == WSAEWOULDBLOCK) |
||
258 | ; // it's okay. We're a non-blocking socket. |
||
259 | else if (recv_retval == WSAETIMEDOUT) |
||
260 | { |
||
261 | messagebox.hWndParent = hMainWnd; |
||
262 | wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage")); |
||
263 | wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_ConnectionToChessServerLost")); |
||
264 | messagebox.flags = MB_ICONWARNING | MB_OK; |
||
265 | DialogBox_Message (&messagebox); // display a modeless error message box |
||
266 | |||
267 | PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message |
||
268 | return (false); |
||
269 | } |
||
270 | } |
||
271 | |||
272 | // END listening to server |
||
273 | ////////////////////////// |
||
274 | |||
275 | ////////////////////////////////// |
||
276 | // BEGIN evaluating server replies |
||
277 | |||
278 | // are we NOT logged in yet ? |
||
279 | if (!player->is_logged_in) |
||
280 | { |
||
281 | // is it a login prompt ? |
||
282 | if ((length > 7) && (strcmp (&player->ascii_recvbuffer[length - 7], "login: ") == 0)) |
||
283 | { |
||
284 | Player_SendBuffer_Add (player, 1000, L"%s\n", options.network.login); // send the login string |
||
285 | player->ascii_recvbuffer[0] = 0; // and discard recvbuffer as we've processed this message |
||
286 | } |
||
287 | |||
288 | // else is it a password prompt ? |
||
289 | else if (((length > 10) && (strcmp (&player->ascii_recvbuffer[length - 10], "password: ") == 0)) |
||
290 | || ((length > 3) && (strcmp (&player->ascii_recvbuffer[length - 3], "\":\n") == 0))) |
||
291 | { |
||
292 | Player_SendBuffer_Add (player, 1000, L"%s\n", options.network.password); // send the password string |
||
293 | player->ascii_recvbuffer[0] = 0; // and discard recvbuffer as we've processed this message |
||
294 | } |
||
295 | |||
296 | // else is it a confirmation that we've successfully logged in ? |
||
297 | else if (((block_start = strstr (player->ascii_recvbuffer, "\n**** Starting FICS session as ")) != NULL) |
||
298 | && (block_end = strstr (player->ascii_recvbuffer, " ****\n"))) |
||
299 | { |
||
300 | player->is_logged_in = true; // remember we are logged in |
||
301 | the_scene.gui.central_text.disappear_time = current_time + 1.0f; // fade the "connecting" phrase out now (FIXME: ugly) |
||
302 | the_scene.gui.want_spinwheel = false; // stop spinning wheel |
||
303 | do_update = true; // and update the scene |
||
304 | |||
305 | block_start += 31; // skip the "\n**** Starting FICS session as " substring |
||
306 | local_player = Player_FindByType (PLAYER_HUMAN); // get a pointer to the local player |
||
307 | |||
308 | // copy out local player's login name, as reported by server, and convert it to wchar_t |
||
309 | for (byte_index = 0; (byte_index < WCHAR_SIZEOF (local_player->name)) && isalpha (block_start[byte_index]); byte_index++) |
||
310 | local_player->name[byte_index] = (wchar_t) block_start[byte_index]; // copy nickname one character after the other. Very dirty conversion. |
||
311 | if (byte_index < WCHAR_SIZEOF (local_player->name)) |
||
312 | local_player->name[byte_index] = 0; // finish the string ourselves |
||
313 | else |
||
314 | local_player->name[WCHAR_SIZEOF (local_player->name) - 1] = 0; // truncate it if neeeded |
||
315 | |||
316 | server_motd[0] = 0; // remember we haven't read the MOTD yet |
||
317 | the_board.reevaluate = true; // reeevaluate the board (to update the title bar) |
||
318 | |||
319 | // see if there's more data to parse after this message, in which case move it in place |
||
320 | length = strlen (block_end + 6); |
||
321 | if (length > 0) |
||
322 | memmove (player->ascii_recvbuffer, block_end + 6, length + 1); |
||
323 | else |
||
324 | player->ascii_recvbuffer[0] = 0; // else discard recvbuffer as we've processed this message |
||
325 | } |
||
326 | } |
||
327 | |||
328 | // else we are logged in |
||
329 | else |
||
330 | { |
||
331 | // see if we have a complete reply block (remember: percent sign was replaced with '¤') |
||
332 | block_end = strstr (player->ascii_recvbuffer, "\nfics¤ "); |
||
333 | |||
334 | // as long as we can find some... |
||
335 | while (block_end != NULL) |
||
336 | { |
||
337 | *block_end = 0; // break the string here |
||
338 | |||
339 | // convert the block to wide char and evaluate it, taking action if needed |
||
340 | ConvertToWideChar (player->recvbuffer, player->recvbuffer_size, player->ascii_recvbuffer); |
||
341 | Debug_Log (L"RECEIVED:[%s]\n", player->recvbuffer); // log what we've received |
||
342 | EvaluateServerReply (player); // and evaluate it |
||
343 | |||
344 | // see if there's more data to parse after this message, in which case move it in place |
||
345 | length = strlen (block_end + 7); |
||
346 | if (length > 0) |
||
347 | memmove (player->ascii_recvbuffer, block_end + 7, length + 1); |
||
348 | else |
||
349 | { |
||
350 | player->ascii_recvbuffer[0] = 0; |
||
351 | break; // it was the last prompt, so discard recvbuffer as we've processed this message |
||
352 | } |
||
353 | block_end = strstr (player->ascii_recvbuffer, "\nfics¤ "); // remember: percent sign was replaced with '¤' |
||
354 | } |
||
355 | } |
||
356 | |||
357 | // END evaluating server replies |
||
358 | //////////////////////////////// |
||
359 | |||
360 | // have we been notified that the current player just changed, has at least one move been played AND is it the remote player's turn now ? |
||
361 | if (the_board.has_playerchanged && (the_board.move_count > 1) && (Board_ColorToMove (&the_board) == player->color)) |
||
362 | { |
||
363 | Debug_Log (L"===Local player just played, sending the chosen move to chess server===\n"); |
||
364 | Player_SendBuffer_Add (player, 1000, L"%s\n", the_board.moves[the_board.move_count - 1].pgntext); // send the move string to the chess server |
||
365 | } |
||
366 | |||
367 | // has the user entered some chatter text ? |
||
368 | if (!the_scene.gui.is_entering_text && (the_scene.gui.entered_ccreply.text != NULL)) |
||
369 | { |
||
370 | // is player logged in AND has a chatter channel been selected ? if so, send chat string to server |
||
371 | if (player->is_logged_in && (selected_chatterchannel != NULL)) |
||
372 | Player_SendBuffer_Add (player, 1000, L"+channel %d\ntell %d %s\n", selected_chatterchannel->id, selected_chatterchannel->id, the_scene.gui.entered_ccreply.text); |
||
373 | |||
374 | // reset the entered text buffer |
||
375 | SAFE_free ((void **) &the_scene.gui.entered_ccreply.text); // reset the entered text buffer |
||
376 | the_scene.gui.entered_ccreply.text_length = 0; // and set its length to zero |
||
377 | } |
||
378 | |||
379 | // does the local player want to cancel its last move ? this can be either HIS move or HIS OPPONENTS's move... |
||
380 | local_player = Player_FindByType (PLAYER_HUMAN); // get a pointer to the local player |
||
381 | if ((local_player != NULL) && local_player->wants_cancel) |
||
382 | { |
||
383 | Player_SendBuffer_Add (player, 1000, L"takeback\n"); // send the takeback request to our opponent |
||
384 | Interlocutor_Notify (Interlocutor_FindOrCreate (player->name), LOCALIZE (L"Chat_TakebackRequestSent"), player->name); // send a notification to its chat window |
||
136 | pmbaty | 385 | the_board.game_state = STATE_PLAYING; // remember the game is now playing (in case we wanted to cancel the closing move of a finished game, this opens the game again) |
1 | pmbaty | 386 | local_player->wants_cancel = false; // don't do this all day long |
387 | } |
||
388 | if (player->wants_cancel) |
||
389 | { |
||
390 | Player_SendBuffer_Add (player, 1000, L"takeback\n"); // send the takeback request to our opponent |
||
391 | Interlocutor_Notify (Interlocutor_FindOrCreate (player->name), LOCALIZE (L"Chat_TakebackRequestSent"), player->name); // send a notification to its chat window |
||
136 | pmbaty | 392 | the_board.game_state = STATE_PLAYING; // remember the game is now playing (in case we wanted to cancel the closing move of a finished game, this opens the game again) |
1 | pmbaty | 393 | player->wants_cancel = false; // don't do this all day long |
394 | } |
||
395 | |||
396 | // if we have something to send, do it |
||
397 | if (!player->sendbuffer_locked && (player->sendbuffer[0] != 0) && (animation_endtime + 1.0f < current_time)) |
||
398 | { |
||
399 | // log what we're sending |
||
400 | Debug_Log (L"SENDING:[%s]\n", player->sendbuffer); |
||
401 | |||
402 | player->sendbuffer_locked = true; // lock the buffer |
||
403 | |||
404 | // now read line per line (mallocate a line buffer as large as necessary) |
||
405 | length = wcslen (player->sendbuffer) + 1 + 1; // +1 for \n, +1 for null terminator |
||
406 | ascii_sendbuffer = (char *) SAFE_malloc (length, sizeof (char), false); |
||
407 | widechar_buffer = (wchar_t *) SAFE_malloc (length, sizeof (wchar_t), false); |
||
408 | widechar_line = player->sendbuffer; // start at the first character |
||
409 | while ((widechar_line = wcsgets (widechar_buffer, length, widechar_line)) != NULL) |
||
410 | { |
||
411 | wcscat_s (widechar_buffer, length, L"\n"); // put the carriage return back |
||
412 | ConvertTo7BitASCII (ascii_sendbuffer, length, widechar_buffer); // convert to ASCII |
||
413 | send_retval = send (player->our_socket, ascii_sendbuffer, strlen (ascii_sendbuffer), 0); // send data |
||
414 | } |
||
415 | SAFE_free ((void **) &widechar_buffer); // we no longer need the line buffer, so free it |
||
416 | SAFE_free ((void **) &ascii_sendbuffer); |
||
417 | |||
418 | player->sendbuffer[0] = 0; // what we had to send has been sent, reset the send buffer |
||
419 | player->sendbuffer_locked = false; // and unlock it |
||
420 | |||
421 | // did send() report an error ? |
||
422 | if (send_retval == SOCKET_ERROR) |
||
423 | { |
||
424 | messagebox.hWndParent = hMainWnd; |
||
425 | wcscpy_s (messagebox.title, WCHAR_SIZEOF (messagebox.title), LOCALIZE (L"ImportantMessage")); |
||
426 | wcscpy_s (messagebox.text, WCHAR_SIZEOF (messagebox.text), LOCALIZE (L"Error_ConnectionToChessServerLost")); |
||
427 | messagebox.flags = MB_ICONERROR | MB_OK; |
||
428 | DialogBox_Message (&messagebox); // display a modeless error message box |
||
429 | |||
430 | PlayerNetwork_Shutdown (player); // on error, shutdown the network and display an error message |
||
431 | return (true); // on error, cancel |
||
432 | } |
||
433 | } |
||
434 | |||
435 | return (do_update); // finished |
||
436 | } |
||
437 | |||
438 | |||
439 | static void EvaluateServerReply (player_t *player) |
||
440 | { |
||
441 | // this function parses a network reply and evaluates it, deciding what to do |
||
442 | |||
443 | ////////////////////// |
||
444 | // OUT OF GAME REPLIES |
||
445 | |||
446 | // the MOTD is the first reply to be evaluated |
||
447 | EvaluateServerReply_MOTD (player); |
||
448 | |||
449 | // evaluate dangerous replies first, i.e. those that contain user-settable text |
||
450 | EvaluateServerReply_Announcement (player); |
||
451 | EvaluateServerReply_ChannelMessage (player); |
||
452 | EvaluateServerReply_PrivateMessage (player); |
||
453 | EvaluateServerReply_Finger (player); |
||
454 | |||
455 | // the less dangerous replies can now be evaluated without ambiguity |
||
456 | EvaluateServerReply_Seek (player); |
||
457 | EvaluateServerReply_Challenge (player); |
||
458 | EvaluateServerReply_ChallengeAccepted (player); |
||
459 | EvaluateServerReply_ChallengeDeclined (player); |
||
460 | EvaluateServerReply_Takeback (player); |
||
461 | EvaluateServerReply_TakebackDeclinedByOther (player); |
||
462 | EvaluateServerReply_TakebackDeclinedByYou (player); |
||
463 | EvaluateServerReply_PlayNotAllowed (player); |
||
464 | EvaluateServerReply_PlayUnexistent (player); |
||
465 | EvaluateServerReply_PlayWrongRating (player); |
||
466 | EvaluateServerReply_ChannelsAndMembers (player); |
||
467 | EvaluateServerReply_SoughtList (player); |
||
468 | EvaluateServerReply_PlayersList (player); |
||
469 | |||
470 | ////////////////// |
||
471 | // IN GAME REPLIES |
||
472 | |||
473 | EvaluateServerReply_GameStarting (player); |
||
474 | EvaluateServerReply_GameState (player); |
||
475 | EvaluateServerReply_GameResults (player); |
||
476 | |||
477 | return; // finished evaluating this reply |
||
478 | } |