00001
00002
00003 #ifdef ENABLE_NETWORK
00004
00005 #include "../stdafx.h"
00006 #include "../debug.h"
00007 #include "../openttd.h"
00008 #include "network_data.h"
00009 #include "core/tcp.h"
00010 #include "network_client.h"
00011 #include "network_gamelist.h"
00012 #include "network_gui.h"
00013 #include "../saveload.h"
00014 #include "../command_func.h"
00015 #include "../console.h"
00016 #include "../variables.h"
00017 #include "../ai/ai.h"
00018 #include "../core/alloc_func.hpp"
00019 #include "../fileio.h"
00020 #include "../md5.h"
00021 #include "../strings_func.h"
00022 #include "../window_func.h"
00023 #include "../string_func.h"
00024 #include "../player_func.h"
00025 #include "../player_base.h"
00026 #include "../player_gui.h"
00027
00028 #include "table/strings.h"
00029
00030
00031
00032
00033
00034 #define MY_CLIENT DEREF_CLIENT(0)
00035
00036 static uint32 last_ack_frame;
00037
00039 static uint32 _password_game_seed;
00041 static char _password_server_unique_id[NETWORK_UNIQUE_ID_LENGTH];
00042
00044 assert_compile(NETWORK_UNIQUE_ID_LENGTH == 16 * 2 + 1);
00045
00051 static const char *GenerateCompanyPasswordHash(const char *password)
00052 {
00053 if (StrEmpty(password)) return password;
00054
00055 char salted_password[NETWORK_UNIQUE_ID_LENGTH];
00056
00057 memset(salted_password, 0, sizeof(salted_password));
00058 snprintf(salted_password, sizeof(salted_password), "%s", password);
00059
00060 for (uint i = 0; i < NETWORK_UNIQUE_ID_LENGTH - 1; i++) salted_password[i] ^= _password_server_unique_id[i] ^ (_password_game_seed >> i);
00061
00062 Md5 checksum;
00063 uint8 digest[16];
00064 static char hashed_password[NETWORK_UNIQUE_ID_LENGTH];
00065
00066
00067 checksum.Append((const uint8*)salted_password, sizeof(salted_password) - 1);
00068 checksum.Finish(digest);
00069
00070 for (int di = 0; di < 16; di++) sprintf(hashed_password + di * 2, "%02x", digest[di]);
00071 hashed_password[lengthof(hashed_password) - 1] = '\0';
00072
00073 return hashed_password;
00074 }
00075
00079 void HashCurrentCompanyPassword()
00080 {
00081 if (StrEmpty(_network_player_info[_local_player].password)) return;
00082
00083 _password_game_seed = _patches.generation_seed;
00084 snprintf(_password_server_unique_id, sizeof(_password_server_unique_id), _network_unique_id);
00085
00086 const char *new_pw = GenerateCompanyPasswordHash(_network_player_info[_local_player].password);
00087 snprintf(_network_player_info[_local_player].password, sizeof(_network_player_info[_local_player].password), new_pw);
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)
00097 {
00098
00099
00100
00101
00102
00103
00104 Packet *p;
00105 _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
00106 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
00107
00108 p = NetworkSend_Init(PACKET_CLIENT_COMPANY_INFO);
00109 MY_CLIENT->Send_Packet(p);
00110 }
00111
00112 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_JOIN)
00113 {
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 extern const char _openttd_revision[];
00126 Packet *p;
00127 _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
00128 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
00129
00130 p = NetworkSend_Init(PACKET_CLIENT_JOIN);
00131 p->Send_string(_openttd_revision);
00132 p->Send_string(_network_player_name);
00133 p->Send_uint8 (_network_playas);
00134 p->Send_uint8 (NETLANG_ANY);
00135 p->Send_string(_network_unique_id);
00136 MY_CLIENT->Send_Packet(p);
00137 }
00138
00139 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
00140 {
00141
00142
00143
00144
00145
00146
00147 Packet *p = NetworkSend_Init(PACKET_CLIENT_NEWGRFS_CHECKED);
00148 MY_CLIENT->Send_Packet(p);
00149 }
00150
00151 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password)
00152 {
00153
00154
00155
00156
00157
00158
00159
00160 Packet *p = NetworkSend_Init(PACKET_CLIENT_PASSWORD);
00161 p->Send_uint8 (type);
00162 p->Send_string(type == NETWORK_GAME_PASSWORD ? password : GenerateCompanyPasswordHash(password));
00163 MY_CLIENT->Send_Packet(p);
00164 }
00165
00166 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GETMAP)
00167 {
00168
00169
00170
00171
00172
00173
00174
00175 Packet *p = NetworkSend_Init(PACKET_CLIENT_GETMAP);
00176 MY_CLIENT->Send_Packet(p);
00177 }
00178
00179 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_MAP_OK)
00180 {
00181
00182
00183
00184
00185
00186
00187
00188 Packet *p = NetworkSend_Init(PACKET_CLIENT_MAP_OK);
00189 MY_CLIENT->Send_Packet(p);
00190 }
00191
00192 DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK)
00193 {
00194
00195
00196
00197
00198
00199
00200
00201 Packet *p = NetworkSend_Init(PACKET_CLIENT_ACK);
00202
00203 p->Send_uint32(_frame_counter);
00204 MY_CLIENT->Send_Packet(p);
00205 }
00206
00207
00208 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(CommandPacket *cp)
00209 {
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 Packet *p = NetworkSend_Init(PACKET_CLIENT_COMMAND);
00224
00225 p->Send_uint8 (cp->player);
00226 p->Send_uint32(cp->cmd);
00227 p->Send_uint32(cp->p1);
00228 p->Send_uint32(cp->p2);
00229 p->Send_uint32((uint32)cp->tile);
00230 p->Send_string(cp->text);
00231 p->Send_uint8 (cp->callback);
00232
00233 MY_CLIENT->Send_Packet(p);
00234 }
00235
00236
00237 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType type, int dest, const char *msg)
00238 {
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 Packet *p = NetworkSend_Init(PACKET_CLIENT_CHAT);
00250
00251 p->Send_uint8 (action);
00252 p->Send_uint8 (type);
00253 p->Send_uint16(dest);
00254 p->Send_string(msg);
00255 MY_CLIENT->Send_Packet(p);
00256 }
00257
00258
00259 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno)
00260 {
00261
00262
00263
00264
00265
00266
00267 Packet *p = NetworkSend_Init(PACKET_CLIENT_ERROR);
00268
00269 p->Send_uint8(errorno);
00270 MY_CLIENT->Send_Packet(p);
00271 }
00272
00273 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password)
00274 {
00275
00276
00277
00278
00279
00280
00281 Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_PASSWORD);
00282
00283 p->Send_string(GenerateCompanyPasswordHash(password));
00284 MY_CLIENT->Send_Packet(p);
00285 }
00286
00287 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name)
00288 {
00289
00290
00291
00292
00293
00294
00295 Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_NAME);
00296
00297 p->Send_string(name);
00298 MY_CLIENT->Send_Packet(p);
00299 }
00300
00301
00302 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg)
00303 {
00304
00305
00306
00307
00308
00309
00310 Packet *p = NetworkSend_Init(PACKET_CLIENT_QUIT);
00311
00312 p->Send_string(leavemsg);
00313 MY_CLIENT->Send_Packet(p);
00314 }
00315
00316 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command)
00317 {
00318 Packet *p = NetworkSend_Init(PACKET_CLIENT_RCON);
00319 p->Send_string(pass);
00320 p->Send_string(command);
00321 MY_CLIENT->Send_Packet(p);
00322 }
00323
00324
00325
00326
00327
00328
00329
00330 extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm, Subdirectory subdir);
00331
00332 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FULL)
00333 {
00334
00335 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
00336 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
00337
00338 return NETWORK_RECV_STATUS_SERVER_FULL;
00339 }
00340
00341 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_BANNED)
00342 {
00343
00344 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_BANNED;
00345 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
00346
00347 return NETWORK_RECV_STATUS_SERVER_BANNED;
00348 }
00349
00350 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO)
00351 {
00352 byte company_info_version;
00353 int i;
00354
00355 company_info_version = p->Recv_uint8();
00356
00357 if (!MY_CLIENT->has_quit && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
00358 byte total;
00359 PlayerID current;
00360
00361 total = p->Recv_uint8();
00362
00363
00364 if (total == 0) return NETWORK_RECV_STATUS_CLOSE_QUERY;
00365
00366 current = (Owner)p->Recv_uint8();
00367 if (!IsValidPlayer(current)) return NETWORK_RECV_STATUS_CLOSE_QUERY;
00368
00369 p->Recv_string(_network_player_info[current].company_name, sizeof(_network_player_info[current].company_name));
00370 _network_player_info[current].inaugurated_year = p->Recv_uint32();
00371 _network_player_info[current].company_value = p->Recv_uint64();
00372 _network_player_info[current].money = p->Recv_uint64();
00373 _network_player_info[current].income = p->Recv_uint64();
00374 _network_player_info[current].performance = p->Recv_uint16();
00375 _network_player_info[current].use_password = p->Recv_bool();
00376 for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
00377 _network_player_info[current].num_vehicle[i] = p->Recv_uint16();
00378 for (i = 0; i < NETWORK_STATION_TYPES; i++)
00379 _network_player_info[current].num_station[i] = p->Recv_uint16();
00380
00381 p->Recv_string(_network_player_info[current].players, sizeof(_network_player_info[current].players));
00382
00383 InvalidateWindow(WC_NETWORK_WINDOW, 0);
00384
00385 return NETWORK_RECV_STATUS_OKAY;
00386 }
00387
00388 return NETWORK_RECV_STATUS_CLOSE_QUERY;
00389 }
00390
00391
00392
00393
00394 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
00395 {
00396 NetworkClientInfo *ci;
00397 uint16 index = p->Recv_uint16();
00398 PlayerID playas = (Owner)p->Recv_uint8();
00399 char name[NETWORK_NAME_LENGTH];
00400
00401 p->Recv_string(name, sizeof(name));
00402
00403 if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
00404
00405
00406 if (index == _network_own_client_index) _network_playas = playas;
00407
00408 ci = NetworkFindClientInfoFromIndex(index);
00409 if (ci != NULL) {
00410 if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
00411
00412 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", name);
00413 } else if (playas != ci->client_playas) {
00414
00415
00416 }
00417
00418 ci->client_playas = playas;
00419 ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
00420
00421 InvalidateWindow(WC_CLIENT_LIST, 0);
00422
00423 return NETWORK_RECV_STATUS_OKAY;
00424 }
00425
00426
00427 ci = NetworkFindClientInfoFromIndex(NETWORK_EMPTY_INDEX);
00428 if (ci != NULL) {
00429 ci->client_index = index;
00430 ci->client_playas = playas;
00431
00432 ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
00433
00434 InvalidateWindow(WC_CLIENT_LIST, 0);
00435
00436 return NETWORK_RECV_STATUS_OKAY;
00437 }
00438
00439
00440 return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00441 }
00442
00443 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
00444 {
00445 NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8();
00446
00447 switch (error) {
00448
00449 case NETWORK_ERROR_NOT_AUTHORIZED:
00450 case NETWORK_ERROR_NOT_EXPECTED:
00451 case NETWORK_ERROR_PLAYER_MISMATCH:
00452 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR;
00453 break;
00454 case NETWORK_ERROR_FULL:
00455 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
00456 break;
00457 case NETWORK_ERROR_WRONG_REVISION:
00458 _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_REVISION;
00459 break;
00460 case NETWORK_ERROR_WRONG_PASSWORD:
00461 _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_PASSWORD;
00462 break;
00463 case NETWORK_ERROR_KICKED:
00464 _switch_mode_errorstr = STR_NETWORK_ERR_KICKED;
00465 break;
00466 case NETWORK_ERROR_CHEATER:
00467 _switch_mode_errorstr = STR_NETWORK_ERR_CHEATER;
00468 break;
00469 default:
00470 _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
00471 }
00472
00473 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
00474
00475 return NETWORK_RECV_STATUS_SERVER_ERROR;
00476 }
00477
00478 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)
00479 {
00480 uint grf_count = p->Recv_uint8();
00481 NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY;
00482
00483
00484 for (; grf_count > 0; grf_count--) {
00485 GRFConfig c;
00486 MY_CLIENT->Recv_GRFIdentifier(p, &c);
00487
00488
00489 const GRFConfig *f = FindGRFConfig(c.grfid, c.md5sum);
00490 if (f == NULL) {
00491
00492 char buf[sizeof(c.md5sum) * 2 + 1];
00493 md5sumToString(buf, lastof(buf), c.md5sum);
00494 DEBUG(grf, 0, "NewGRF %08X not found; checksum %s", BSWAP32(c.grfid), buf);
00495 ret = NETWORK_RECV_STATUS_NEWGRF_MISMATCH;
00496 }
00497 }
00498
00499 if (ret == NETWORK_RECV_STATUS_OKAY) {
00500
00501 SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)();
00502 } else {
00503
00504 _switch_mode_errorstr = STR_NETWORK_ERR_NEWGRF_MISMATCH;
00505 }
00506 return ret;
00507 }
00508
00509 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
00510 {
00511 NetworkPasswordType type = (NetworkPasswordType)p->Recv_uint8();
00512
00513 switch (type) {
00514 case NETWORK_COMPANY_PASSWORD:
00515
00516 _password_game_seed = p->Recv_uint32();
00517 p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
00518 if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00519
00520 case NETWORK_GAME_PASSWORD:
00521 ShowNetworkNeedPassword(type);
00522 return NETWORK_RECV_STATUS_OKAY;
00523
00524 default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00525 }
00526 }
00527
00528 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
00529 {
00530 _network_own_client_index = p->Recv_uint16();
00531
00532
00533 _password_game_seed = p->Recv_uint32();
00534 p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
00535
00536
00537 SEND_COMMAND(PACKET_CLIENT_GETMAP)();
00538 return NETWORK_RECV_STATUS_OKAY;
00539 }
00540
00541 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
00542 {
00543 _network_join_status = NETWORK_JOIN_STATUS_WAITING;
00544 _network_join_waiting = p->Recv_uint8();
00545 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
00546
00547
00548 DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." );
00549 DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting);
00550
00551 return NETWORK_RECV_STATUS_OKAY;
00552 }
00553
00554 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
00555 {
00556 static FILE *file_pointer;
00557
00558 byte maptype;
00559
00560 maptype = p->Recv_uint8();
00561
00562 if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
00563
00564
00565 if (maptype == MAP_PACKET_START) {
00566 file_pointer = FioFOpenFile("network_client.tmp", "wb", AUTOSAVE_DIR);;
00567 if (file_pointer == NULL) {
00568 _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
00569 return NETWORK_RECV_STATUS_SAVEGAME;
00570 }
00571
00572 _frame_counter = _frame_counter_server = _frame_counter_max = p->Recv_uint32();
00573
00574 _network_join_kbytes = 0;
00575 _network_join_kbytes_total = p->Recv_uint32() / 1024;
00576
00577
00578
00579
00580
00581
00582 if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
00583 if (_network_join_kbytes_total == 0) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
00584
00585 _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
00586 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
00587
00588
00589 return NETWORK_RECV_STATUS_OKAY;
00590 }
00591
00592 if (maptype == MAP_PACKET_NORMAL) {
00593
00594 fwrite(p->buffer + p->pos, 1, p->size - p->pos, file_pointer);
00595
00596 _network_join_kbytes = ftell(file_pointer) / 1024;
00597 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
00598 }
00599
00600
00601 if (maptype == MAP_PACKET_END) {
00602 fclose(file_pointer);
00603
00604 _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
00605 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
00606
00607
00608 if (!SafeSaveOrLoad("network_client.tmp", SL_LOAD, GM_NORMAL, AUTOSAVE_DIR)) {
00609 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
00610 _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
00611 return NETWORK_RECV_STATUS_SAVEGAME;
00612 }
00613
00614
00615
00616 _opt_ptr = &_opt;
00617
00618
00619 SEND_COMMAND(PACKET_CLIENT_MAP_OK)();
00620
00621
00622
00623 if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayer(_network_playas) ||
00624 !GetPlayer(_network_playas)->is_active) {
00625
00626 SetLocalPlayer(PLAYER_SPECTATOR);
00627
00628 if (_network_playas != PLAYER_SPECTATOR) {
00629
00630
00631 _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
00632 ShowJoinStatusWindow();
00633 NetworkSend_Command(0, 0, 0, CMD_PLAYER_CTRL, NULL);
00634 }
00635 } else {
00636
00637 SetLocalPlayer(_network_playas);
00638 }
00639 }
00640
00641 return NETWORK_RECV_STATUS_OKAY;
00642 }
00643
00644 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FRAME)
00645 {
00646 _frame_counter_server = p->Recv_uint32();
00647 _frame_counter_max = p->Recv_uint32();
00648 #ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
00649
00650
00651 if (p->pos < p->size) {
00652 _sync_frame = _frame_counter_server;
00653 _sync_seed_1 = p->Recv_uint32();
00654 #ifdef NETWORK_SEND_DOUBLE_SEED
00655 _sync_seed_2 = p->Recv_uint32();
00656 #endif
00657 }
00658 #endif
00659 DEBUG(net, 5, "Received FRAME %d", _frame_counter_server);
00660
00661
00662
00663 if (!_network_first_time && last_ack_frame < _frame_counter) {
00664 last_ack_frame = _frame_counter + DAY_TICKS;
00665 DEBUG(net, 4, "Sent ACK at %d", _frame_counter);
00666 SEND_COMMAND(PACKET_CLIENT_ACK)();
00667 }
00668
00669 return NETWORK_RECV_STATUS_OKAY;
00670 }
00671
00672 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SYNC)
00673 {
00674 _sync_frame = p->Recv_uint32();
00675 _sync_seed_1 = p->Recv_uint32();
00676 #ifdef NETWORK_SEND_DOUBLE_SEED
00677 _sync_seed_2 = p->Recv_uint32();
00678 #endif
00679
00680 return NETWORK_RECV_STATUS_OKAY;
00681 }
00682
00683 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
00684 {
00685 CommandPacket *cp = MallocT<CommandPacket>(1);
00686 cp->player = (PlayerID)p->Recv_uint8();
00687 cp->cmd = p->Recv_uint32();
00688 cp->p1 = p->Recv_uint32();
00689 cp->p2 = p->Recv_uint32();
00690 cp->tile = p->Recv_uint32();
00691 p->Recv_string(cp->text, sizeof(cp->text));
00692 cp->callback = p->Recv_uint8();
00693 cp->frame = p->Recv_uint32();
00694 cp->my_cmd = p->Recv_bool();
00695 cp->next = NULL;
00696
00697
00698
00699
00700 if (_local_command_queue == NULL) {
00701 _local_command_queue = cp;
00702 } else {
00703
00704 CommandPacket *c = _local_command_queue;
00705 while (c->next != NULL) c = c->next;
00706 c->next = cp;
00707 }
00708
00709 return NETWORK_RECV_STATUS_OKAY;
00710 }
00711
00712 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
00713 {
00714 char name[NETWORK_NAME_LENGTH], msg[MAX_TEXT_MSG_LEN];
00715 const NetworkClientInfo *ci = NULL, *ci_to;
00716
00717 NetworkAction action = (NetworkAction)p->Recv_uint8();
00718 uint16 index = p->Recv_uint16();
00719 bool self_send = p->Recv_bool();
00720 p->Recv_string(msg, MAX_TEXT_MSG_LEN);
00721
00722 ci_to = NetworkFindClientInfoFromIndex(index);
00723 if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY;
00724
00725
00726 if (self_send) {
00727 switch (action) {
00728 case NETWORK_ACTION_CHAT_CLIENT:
00729
00730 snprintf(name, sizeof(name), "%s", ci_to->client_name);
00731 ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
00732 break;
00733
00734
00735 case NETWORK_ACTION_GIVE_MONEY:
00736 if (!IsValidPlayer(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY;
00737
00738 case NETWORK_ACTION_CHAT_COMPANY: {
00739 StringID str = IsValidPlayer(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
00740 SetDParam(0, ci_to->client_playas);
00741
00742 GetString(name, str, lastof(name));
00743 ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
00744 } break;
00745
00746 default: NOT_REACHED(); break;
00747 }
00748 } else {
00749
00750 snprintf(name, sizeof(name), "%s", ci_to->client_name);
00751 ci = ci_to;
00752 }
00753
00754 if (ci != NULL)
00755 NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg);
00756 return NETWORK_RECV_STATUS_OKAY;
00757 }
00758
00759 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
00760 {
00761 char str[100];
00762 uint16 index;
00763 NetworkClientInfo *ci;
00764
00765 index = p->Recv_uint16();
00766 GetNetworkErrorMsg(str, (NetworkErrorCode)p->Recv_uint8(), lastof(str));
00767
00768 ci = NetworkFindClientInfoFromIndex(index);
00769 if (ci != NULL) {
00770 NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
00771
00772
00773 ci->client_index = NETWORK_EMPTY_INDEX;
00774 }
00775
00776 InvalidateWindow(WC_CLIENT_LIST, 0);
00777
00778 return NETWORK_RECV_STATUS_OKAY;
00779 }
00780
00781 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
00782 {
00783 char str[100];
00784 uint16 index;
00785 NetworkClientInfo *ci;
00786
00787 index = p->Recv_uint16();
00788 p->Recv_string(str, lengthof(str));
00789
00790 ci = NetworkFindClientInfoFromIndex(index);
00791 if (ci != NULL) {
00792 NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
00793
00794
00795 ci->client_index = NETWORK_EMPTY_INDEX;
00796 } else {
00797 DEBUG(net, 0, "Unknown client (%d) is leaving the game", index);
00798 }
00799
00800 InvalidateWindow(WC_CLIENT_LIST, 0);
00801
00802
00803 return NETWORK_RECV_STATUS_OKAY;
00804 }
00805
00806 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
00807 {
00808 uint16 index;
00809 NetworkClientInfo *ci;
00810
00811 index = p->Recv_uint16();
00812
00813 ci = NetworkFindClientInfoFromIndex(index);
00814 if (ci != NULL)
00815 NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, ci->client_name, "");
00816
00817 InvalidateWindow(WC_CLIENT_LIST, 0);
00818
00819 return NETWORK_RECV_STATUS_OKAY;
00820 }
00821
00822 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN)
00823 {
00824 _switch_mode_errorstr = STR_NETWORK_SERVER_SHUTDOWN;
00825
00826 return NETWORK_RECV_STATUS_SERVER_ERROR;
00827 }
00828
00829 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME)
00830 {
00831
00832
00833
00834
00835 _network_reconnect = min(_local_player + 1, 10);
00836 _switch_mode_errorstr = STR_NETWORK_SERVER_REBOOT;
00837
00838 return NETWORK_RECV_STATUS_SERVER_ERROR;
00839 }
00840
00841 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
00842 {
00843 char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
00844 uint16 color_code;
00845
00846 color_code = p->Recv_uint16();
00847 p->Recv_string(rcon_out, sizeof(rcon_out));
00848
00849 IConsolePrint(color_code, rcon_out);
00850
00851 return NETWORK_RECV_STATUS_OKAY;
00852 }
00853
00854
00855
00856
00857 typedef NetworkRecvStatus NetworkClientPacket(Packet *p);
00858
00859
00860
00861
00862
00863 static NetworkClientPacket* const _network_client_packet[] = {
00864 RECEIVE_COMMAND(PACKET_SERVER_FULL),
00865 RECEIVE_COMMAND(PACKET_SERVER_BANNED),
00866 NULL,
00867 RECEIVE_COMMAND(PACKET_SERVER_ERROR),
00868 NULL,
00869 RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO),
00870 RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO),
00871 RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD),
00872 NULL,
00873 RECEIVE_COMMAND(PACKET_SERVER_WELCOME),
00874 NULL,
00875 RECEIVE_COMMAND(PACKET_SERVER_WAIT),
00876 RECEIVE_COMMAND(PACKET_SERVER_MAP),
00877 NULL,
00878 RECEIVE_COMMAND(PACKET_SERVER_JOIN),
00879 RECEIVE_COMMAND(PACKET_SERVER_FRAME),
00880 RECEIVE_COMMAND(PACKET_SERVER_SYNC),
00881 NULL,
00882 NULL,
00883 RECEIVE_COMMAND(PACKET_SERVER_COMMAND),
00884 NULL,
00885 RECEIVE_COMMAND(PACKET_SERVER_CHAT),
00886 NULL,
00887 NULL,
00888 NULL,
00889 NULL,
00890 RECEIVE_COMMAND(PACKET_SERVER_QUIT),
00891 RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT),
00892 RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN),
00893 RECEIVE_COMMAND(PACKET_SERVER_NEWGAME),
00894 RECEIVE_COMMAND(PACKET_SERVER_RCON),
00895 NULL,
00896 RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS),
00897 NULL,
00898 };
00899
00900
00901 assert_compile(lengthof(_network_client_packet) == PACKET_END);
00902
00903
00904 void NetworkClient_Connected()
00905 {
00906
00907 _frame_counter = 0;
00908 _frame_counter_server = 0;
00909 last_ack_frame = 0;
00910
00911 SEND_COMMAND(PACKET_CLIENT_JOIN)();
00912 }
00913
00914
00915 NetworkRecvStatus NetworkClient_ReadPackets(NetworkTCPSocketHandler *cs)
00916 {
00917 Packet *p;
00918 NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY;
00919
00920 while (res == NETWORK_RECV_STATUS_OKAY && (p = cs->Recv_Packet(&res)) != NULL) {
00921 byte type = p->Recv_uint8();
00922 if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->has_quit) {
00923 res = _network_client_packet[type](p);
00924 } else {
00925 res = NETWORK_RECV_STATUS_MALFORMED_PACKET;
00926 DEBUG(net, 0, "[client] received invalid packet type %d", type);
00927 }
00928
00929 delete p;
00930 }
00931
00932 return res;
00933 }
00934
00935 #endif