219 static size_t _transmit_file_size; |
219 static size_t _transmit_file_size; |
220 |
220 |
221 static FILE *_recv_file; |
221 static FILE *_recv_file; |
222 |
222 |
223 typedef struct NetworkGameInfo { |
223 typedef struct NetworkGameInfo { |
224 char server_name[40]; // name of the game |
224 char server_name[40]; // name of the game |
225 char server_revision[8]; // server game version |
225 char server_revision[8]; // server game version |
226 byte server_lang; // langid |
226 byte server_lang; // langid |
227 byte players_max; // max players allowed on server |
227 byte players_max; // max players allowed on server |
228 byte players_on; // current count of players on server |
228 byte players_on; // current count of players on server |
229 uint16 game_date; // current date |
229 uint16 game_date; // current date |
230 char game_password[10]; // should fit ... 14 chars |
230 char game_password[10]; // should fit ... 10 chars |
231 char map_name[40]; // map which is played ["random" for a randomized map] |
231 char map_name[40]; // map which is played ["random" for a randomized map] |
232 uint map_width; // map width / 8 |
232 uint map_width; // map width / 8 |
233 uint map_height; // map height / 8 |
233 uint map_height; // map height / 8 |
234 byte map_set; // graphical set |
234 byte map_set; // graphical set |
235 } NetworkGameInfo; |
235 } NetworkGameInfo; |
236 |
236 |
237 typedef struct NetworkGameList { |
237 typedef struct NetworkGameList { |
238 NetworkGameInfo item; |
238 NetworkGameInfo item; |
239 uint32 ip; |
239 uint32 ip; |
277 } |
277 } |
278 |
278 |
279 ////////////////////////////////////////////////////////////////////// |
279 ////////////////////////////////////////////////////////////////////// |
280 |
280 |
281 // ****************************** // |
281 // ****************************** // |
|
282 // * Network Error Handlers * // |
|
283 // ****************************** // |
|
284 |
|
285 static void NetworkHandleSaveGameError() { |
|
286 _networking_sync = false; |
|
287 _networking_queuing = true; |
|
288 _switch_mode = SM_MENU; |
|
289 _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR; |
|
290 } |
|
291 |
|
292 static void NetworkHandleConnectionLost() { |
|
293 _networking_sync = false; |
|
294 _networking_queuing = true; |
|
295 _switch_mode = SM_MENU; |
|
296 _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION; |
|
297 } |
|
298 static void NetworkHandleDeSync() { |
|
299 printf("fatal error: network sync error at frame %i\n",_frame_counter); |
|
300 { |
|
301 int i; |
|
302 for (i=15; i>=0; i--) printf("frame %i: [0]=%i, [1]=%i\n",_frame_counter-(i+1),_my_seed_list[i][0],_my_seed_list[i][1]); |
|
303 for (i=0; i<8; i++) printf("frame %i: [0]=%i, [1]=%i\n",_frame_counter+i,_future_seed[i].seed[0],_future_seed[i].seed[1]); |
|
304 } |
|
305 _networking_sync = false; |
|
306 _networking_queuing = true; |
|
307 _switch_mode = SM_MENU; |
|
308 _switch_mode_errorstr = STR_NETWORK_ERR_DESYNC; |
|
309 } |
|
310 |
|
311 // ****************************** // |
282 // * TCP Packets and Handlers * // |
312 // * TCP Packets and Handlers * // |
283 // ****************************** // |
313 // ****************************** // |
284 |
314 |
285 static QueuedCommand *AllocQueuedCommand(CommandQueue *nq) |
315 static QueuedCommand *AllocQueuedCommand(CommandQueue *nq) |
286 { |
316 { |
324 _my_seed_list[_frame_counter & 15][1] = _sync_seed_2; |
354 _my_seed_list[_frame_counter & 15][1] = _sync_seed_2; |
325 |
355 |
326 while (_num_future_seed) { |
356 while (_num_future_seed) { |
327 assert(_future_seed[0].frame >= _frame_counter); |
357 assert(_future_seed[0].frame >= _frame_counter); |
328 if (_future_seed[0].frame != _frame_counter) break; |
358 if (_future_seed[0].frame != _frame_counter) break; |
329 if (_future_seed[0].seed[0] != _sync_seed_1 ||_future_seed[0].seed[1] != _sync_seed_2) |
359 if (_future_seed[0].seed[0] != _sync_seed_1 ||_future_seed[0].seed[1] != _sync_seed_2) NetworkHandleDeSync(); |
330 error("!network sync error"); |
|
331 memcpy_overlapping(_future_seed, _future_seed + 1, --_num_future_seed * sizeof(FutureSeeds)); |
360 memcpy_overlapping(_future_seed, _future_seed + 1, --_num_future_seed * sizeof(FutureSeeds)); |
332 } |
361 } |
333 } |
362 } |
334 } |
363 } |
335 |
364 |
492 |
521 |
493 if (_frame_counter_srv <= _frame_counter) { |
522 if (_frame_counter_srv <= _frame_counter) { |
494 // we are ahead of the server check if the seed is in our list. |
523 // we are ahead of the server check if the seed is in our list. |
495 if (_frame_counter_srv + 16 > _frame_counter) { |
524 if (_frame_counter_srv + 16 > _frame_counter) { |
496 // the random seed exists in our array check it. |
525 // the random seed exists in our array check it. |
497 if (s1 != _my_seed_list[_frame_counter_srv & 0xF][0] || s2 != _my_seed_list[_frame_counter_srv & 0xF][1]) |
526 if (s1 != _my_seed_list[_frame_counter_srv & 0xF][0] || s2 != _my_seed_list[_frame_counter_srv & 0xF][1]) NetworkHandleDeSync(); |
498 error("!network is desynched\n"); |
|
499 } |
527 } |
500 } else { |
528 } else { |
501 // the server's frame has not been executed yet. store the server's seed in a list. |
529 // the server's frame has not been executed yet. store the server's seed in a list. |
502 if (_num_future_seed < lengthof(_future_seed)) { |
530 if (_num_future_seed < lengthof(_future_seed)) { |
503 _future_seed[_num_future_seed].frame = _frame_counter_srv; |
531 _future_seed[_num_future_seed].frame = _frame_counter_srv; |
535 // eof |
563 // eof |
536 if (_recv_file) { fclose(_recv_file); _recv_file = NULL; } |
564 if (_recv_file) { fclose(_recv_file); _recv_file = NULL; } |
537 |
565 |
538 // attempt loading the game. |
566 // attempt loading the game. |
539 _game_mode = GM_NORMAL; |
567 _game_mode = GM_NORMAL; |
540 if (SaveOrLoad("networkc.tmp", SL_LOAD) != SL_OK) error("network load failed"); |
568 if (SaveOrLoad("networkc.tmp", SL_LOAD) != SL_OK) { |
541 |
569 NetworkCoreDisconnect(); |
|
570 NetworkHandleSaveGameError(); |
|
571 return; |
|
572 } |
542 // sync to server. |
573 // sync to server. |
543 _networking_queuing = false; |
574 _networking_queuing = false; |
544 NetworkStartSync(false); |
575 NetworkStartSync(false); |
545 /* |
|
546 _networking_sync = true; |
|
547 _frame_counter = 0; // start executing at frame 0. |
|
548 _sync_seed_1 = _sync_seed_2 = 0; |
|
549 _num_future_seed = 0; |
|
550 memset(_my_seed_list, 0, sizeof(_my_seed_list)); */ |
|
551 |
576 |
552 if (_network_playas == 0) { |
577 if (_network_playas == 0) { |
553 // send a command to make a new player |
578 // send a command to make a new player |
554 _local_player = 0; |
579 _local_player = 0; |
555 NetworkSendCommand(0, 0, 0, CMD_PLAYER_CTRL, NULL); |
580 NetworkSendCommand(0, 0, 0, CMD_PLAYER_CTRL, NULL); |
975 #if !defined(__MORPHOS__) && !defined(__AMIGA__) |
1000 #if !defined(__MORPHOS__) && !defined(__AMIGA__) |
976 n = select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv); |
1001 n = select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv); |
977 #else |
1002 #else |
978 n = WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL); |
1003 n = WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL); |
979 #endif |
1004 #endif |
980 if (n == -1) error("select failed"); |
1005 if (n == -1) NetworkHandleConnectionLost(); |
981 |
1006 |
982 // accept clients.. |
1007 // accept clients.. |
983 if (_networking_server && FD_ISSET(_listensocket, &read_fd)) |
1008 if (_networking_server && FD_ISSET(_listensocket, &read_fd)) |
984 NetworkAcceptClients(); |
1009 NetworkAcceptClients(); |
985 |
1010 |
1256 if (client) { out_addr.sin_port = htons(_network_server_port); } else { out_addr.sin_port = htons(_network_client_port); }; |
1281 if (client) { out_addr.sin_port = htons(_network_server_port); } else { out_addr.sin_port = htons(_network_client_port); }; |
1257 bcptr = (byte *) &bcaddr; |
1282 bcptr = (byte *) &bcaddr; |
1258 bcptr[3]=255; |
1283 bcptr[3]=255; |
1259 out_addr.sin_addr.s_addr = bcaddr; |
1284 out_addr.sin_addr.s_addr = bcaddr; |
1260 res=sendto(udp,(char *) &packet,sizeof(packet),0,(struct sockaddr *) &out_addr,sizeof(out_addr)); |
1285 res=sendto(udp,(char *) &packet,sizeof(packet),0,(struct sockaddr *) &out_addr,sizeof(out_addr)); |
1261 if (res==-1) error("udp: broadcast error: %i",GET_LAST_ERROR()); |
1286 if (res==-1) DEBUG(misc,1)("udp: broadcast error: %i",GET_LAST_ERROR()); |
1262 i++; |
1287 i++; |
1263 } |
1288 } |
1264 |
1289 |
1265 } |
1290 } |
1266 |
1291 |
1444 if (!_network_available) return false; |
1469 if (!_network_available) return false; |
1445 |
1470 |
1446 if (strcmp((char *) b,"auto")==0) { |
1471 if (strcmp((char *) b,"auto")==0) { |
1447 // do autodetect |
1472 // do autodetect |
1448 NetworkUDPSearchGame(&b, &port); |
1473 NetworkUDPSearchGame(&b, &port); |
1449 } |
1474 } |
1450 |
1475 |
1451 if (port==0) { |
1476 if (port==0) { |
1452 // autodetection failed |
1477 // autodetection failed |
1453 if (_networking_override) NetworkLobbyShutdown(); |
1478 if (_networking_override) NetworkLobbyShutdown(); |
1454 ShowErrorMessage(-1, STR_NETWORK_ERR_NOSERVER, 0, 0); |
1479 ShowErrorMessage(-1, STR_NETWORK_ERR_NOSERVER, 0, 0); |
|
1480 _switch_mode_errorstr = STR_NETWORK_ERR_NOSERVER; |
1455 return false; |
1481 return false; |
1456 } |
1482 } |
|
1483 |
1457 NetworkInitialize(); |
1484 NetworkInitialize(); |
1458 _networking = NetworkConnect(b, port); |
1485 _networking = NetworkConnect(b, port); |
1459 if (_networking) { |
1486 if (_networking) { |
1460 NetworkLobbyShutdown(); |
1487 NetworkLobbyShutdown(); |
1461 } else { |
1488 } else { |
1462 if (_networking_override) NetworkLobbyShutdown(); |
1489 if (_networking_override) |
|
1490 NetworkLobbyShutdown(); |
|
1491 |
1463 ShowErrorMessage(-1, STR_NETWORK_ERR_NOCONNECTION,0,0); |
1492 ShowErrorMessage(-1, STR_NETWORK_ERR_NOCONNECTION,0,0); |
1464 } |
1493 _switch_mode_errorstr = STR_NETWORK_ERR_NOCONNECTION; |
|
1494 } |
1465 return _networking; |
1495 return _networking; |
1466 } |
1496 } |
1467 |
1497 |
1468 /* *************************************************** */ |
1498 /* *************************************************** */ |
1469 |
1499 |