75 |
75 |
76 return hashed_password; |
76 return hashed_password; |
77 } |
77 } |
78 |
78 |
79 /** |
79 /** |
80 * Hash the current company password; used when the server 'player' sets his/her password. |
80 * Hash the current company password; used when the server 'company' sets his/her password. |
81 */ |
81 */ |
82 void HashCurrentCompanyPassword() |
82 void HashCurrentCompanyPassword() |
83 { |
83 { |
84 if (StrEmpty(_network_player_info[_local_player].password)) return; |
84 if (StrEmpty(_network_company_info[_local_company].password)) return; |
85 |
85 |
86 _password_game_seed = _settings_game.game_creation.generation_seed; |
86 _password_game_seed = _settings_game.game_creation.generation_seed; |
87 ttd_strlcpy(_password_server_unique_id, _settings_client.network.network_id, sizeof(_password_server_unique_id)); |
87 ttd_strlcpy(_password_server_unique_id, _settings_client.network.network_id, sizeof(_password_server_unique_id)); |
88 |
88 |
89 const char *new_pw = GenerateCompanyPasswordHash(_network_player_info[_local_player].password); |
89 const char *new_pw = GenerateCompanyPasswordHash(_network_company_info[_local_company].password); |
90 ttd_strlcpy(_network_player_info[_local_player].password, new_pw, sizeof(_network_player_info[_local_player].password)); |
90 ttd_strlcpy(_network_company_info[_local_company].password, new_pw, sizeof(_network_company_info[_local_company].password)); |
91 } |
91 } |
92 |
92 |
93 |
93 |
94 // ********** |
94 // ********** |
95 // Sending functions |
95 // Sending functions |
117 // |
117 // |
118 // Packet: CLIENT_JOIN |
118 // Packet: CLIENT_JOIN |
119 // Function: Try to join the server |
119 // Function: Try to join the server |
120 // Data: |
120 // Data: |
121 // String: OpenTTD Revision (norev000 if no revision) |
121 // String: OpenTTD Revision (norev000 if no revision) |
122 // String: Player Name (max NETWORK_NAME_LENGTH) |
122 // String: Client Name (max NETWORK_NAME_LENGTH) |
123 // uint8: Play as Player id (1..MAX_PLAYERS) |
123 // uint8: Play as Company id (1..MAX_COMPANIES) |
124 // uint8: Language ID |
124 // uint8: Language ID |
125 // String: Unique id to find the player back in server-listing |
125 // String: Unique id to find the client back in server-listing |
126 // |
126 // |
127 |
127 |
128 Packet *p; |
128 Packet *p; |
129 _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING; |
129 _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING; |
130 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0); |
130 InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0); |
131 |
131 |
132 p = NetworkSend_Init(PACKET_CLIENT_JOIN); |
132 p = NetworkSend_Init(PACKET_CLIENT_JOIN); |
133 p->Send_string(_openttd_revision); |
133 p->Send_string(_openttd_revision); |
134 p->Send_string(_settings_client.network.player_name); // Player name |
134 p->Send_string(_settings_client.network.client_name); // Client name |
135 p->Send_uint8 (_network_playas); // PlayAs |
135 p->Send_uint8 (_network_playas); // PlayAs |
136 p->Send_uint8 (NETLANG_ANY); // Language |
136 p->Send_uint8 (NETLANG_ANY); // Language |
137 p->Send_string(_settings_client.network.network_id); |
137 p->Send_string(_settings_client.network.network_id); |
138 MY_CLIENT->Send_Packet(p); |
138 MY_CLIENT->Send_Packet(p); |
139 } |
139 } |
211 { |
211 { |
212 // |
212 // |
213 // Packet: CLIENT_COMMAND |
213 // Packet: CLIENT_COMMAND |
214 // Function: Send a DoCommand to the Server |
214 // Function: Send a DoCommand to the Server |
215 // Data: |
215 // Data: |
216 // uint8: PlayerID (0..MAX_PLAYERS-1) |
216 // uint8: CompanyID (0..MAX_COMPANIES-1) |
217 // uint32: CommandID (see command.h) |
217 // uint32: CommandID (see command.h) |
218 // uint32: P1 (free variables used in DoCommand) |
218 // uint32: P1 (free variables used in DoCommand) |
219 // uint32: P2 |
219 // uint32: P2 |
220 // uint32: Tile |
220 // uint32: Tile |
221 // string: text |
221 // string: text |
222 // uint8: CallBackID (see callback_table.c) |
222 // uint8: CallBackID (see callback_table.c) |
223 // |
223 // |
224 |
224 |
225 Packet *p = NetworkSend_Init(PACKET_CLIENT_COMMAND); |
225 Packet *p = NetworkSend_Init(PACKET_CLIENT_COMMAND); |
226 |
226 |
227 p->Send_uint8 (cp->player); |
227 p->Send_uint8 (cp->company); |
228 p->Send_uint32(cp->cmd); |
228 p->Send_uint32(cp->cmd); |
229 p->Send_uint32(cp->p1); |
229 p->Send_uint32(cp->p1); |
230 p->Send_uint32(cp->p2); |
230 p->Send_uint32(cp->p2); |
231 p->Send_uint32((uint32)cp->tile); |
231 p->Send_uint32((uint32)cp->tile); |
232 p->Send_string(cp->text); |
232 p->Send_string(cp->text); |
242 // Packet: CLIENT_CHAT |
242 // Packet: CLIENT_CHAT |
243 // Function: Send a chat-packet to the serve |
243 // Function: Send a chat-packet to the serve |
244 // Data: |
244 // Data: |
245 // uint8: ActionID (see network_data.h, NetworkAction) |
245 // uint8: ActionID (see network_data.h, NetworkAction) |
246 // uint8: Destination Type (see network_data.h, DestType); |
246 // uint8: Destination Type (see network_data.h, DestType); |
247 // uint16: Destination Player |
247 // uint16: Destination Company/Client |
248 // String: Message (max NETWORK_CHAT_LENGTH) |
248 // String: Message (max NETWORK_CHAT_LENGTH) |
249 // |
249 // |
250 |
250 |
251 Packet *p = NetworkSend_Init(PACKET_CLIENT_CHAT); |
251 Packet *p = NetworkSend_Init(PACKET_CLIENT_CHAT); |
252 |
252 |
357 |
357 |
358 company_info_version = p->Recv_uint8(); |
358 company_info_version = p->Recv_uint8(); |
359 |
359 |
360 if (!MY_CLIENT->has_quit && company_info_version == NETWORK_COMPANY_INFO_VERSION) { |
360 if (!MY_CLIENT->has_quit && company_info_version == NETWORK_COMPANY_INFO_VERSION) { |
361 byte total; |
361 byte total; |
362 PlayerID current; |
362 CompanyID current; |
363 |
363 |
364 total = p->Recv_uint8(); |
364 total = p->Recv_uint8(); |
365 |
365 |
366 // There is no data at all.. |
366 // There is no data at all.. |
367 if (total == 0) return NETWORK_RECV_STATUS_CLOSE_QUERY; |
367 if (total == 0) return NETWORK_RECV_STATUS_CLOSE_QUERY; |
368 |
368 |
369 current = (Owner)p->Recv_uint8(); |
369 current = (Owner)p->Recv_uint8(); |
370 if (current >= MAX_PLAYERS) return NETWORK_RECV_STATUS_CLOSE_QUERY; |
370 if (current >= MAX_COMPANIES) return NETWORK_RECV_STATUS_CLOSE_QUERY; |
371 |
371 |
372 p->Recv_string(_network_player_info[current].company_name, sizeof(_network_player_info[current].company_name)); |
372 p->Recv_string(_network_company_info[current].company_name, sizeof(_network_company_info[current].company_name)); |
373 _network_player_info[current].inaugurated_year = p->Recv_uint32(); |
373 _network_company_info[current].inaugurated_year = p->Recv_uint32(); |
374 _network_player_info[current].company_value = p->Recv_uint64(); |
374 _network_company_info[current].company_value = p->Recv_uint64(); |
375 _network_player_info[current].money = p->Recv_uint64(); |
375 _network_company_info[current].money = p->Recv_uint64(); |
376 _network_player_info[current].income = p->Recv_uint64(); |
376 _network_company_info[current].income = p->Recv_uint64(); |
377 _network_player_info[current].performance = p->Recv_uint16(); |
377 _network_company_info[current].performance = p->Recv_uint16(); |
378 _network_player_info[current].use_password = p->Recv_bool(); |
378 _network_company_info[current].use_password = p->Recv_bool(); |
379 for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) |
379 for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) |
380 _network_player_info[current].num_vehicle[i] = p->Recv_uint16(); |
380 _network_company_info[current].num_vehicle[i] = p->Recv_uint16(); |
381 for (i = 0; i < NETWORK_STATION_TYPES; i++) |
381 for (i = 0; i < NETWORK_STATION_TYPES; i++) |
382 _network_player_info[current].num_station[i] = p->Recv_uint16(); |
382 _network_company_info[current].num_station[i] = p->Recv_uint16(); |
383 |
383 |
384 p->Recv_string(_network_player_info[current].players, sizeof(_network_player_info[current].players)); |
384 p->Recv_string(_network_company_info[current].clients, sizeof(_network_company_info[current].clients)); |
385 |
385 |
386 InvalidateWindow(WC_NETWORK_WINDOW, 0); |
386 InvalidateWindow(WC_NETWORK_WINDOW, 0); |
387 |
387 |
388 return NETWORK_RECV_STATUS_OKAY; |
388 return NETWORK_RECV_STATUS_OKAY; |
389 } |
389 } |
396 // which is always an unique number on a server. |
396 // which is always an unique number on a server. |
397 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO) |
397 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO) |
398 { |
398 { |
399 NetworkClientInfo *ci; |
399 NetworkClientInfo *ci; |
400 uint16 index = p->Recv_uint16(); |
400 uint16 index = p->Recv_uint16(); |
401 PlayerID playas = (Owner)p->Recv_uint8(); |
401 CompanyID playas = (CompanyID)p->Recv_uint8(); |
402 char name[NETWORK_NAME_LENGTH]; |
402 char name[NETWORK_NAME_LENGTH]; |
403 |
403 |
404 p->Recv_string(name, sizeof(name)); |
404 p->Recv_string(name, sizeof(name)); |
405 |
405 |
406 if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST; |
406 if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST; |
412 if (ci != NULL) { |
412 if (ci != NULL) { |
413 if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) { |
413 if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) { |
414 // Client name changed, display the change |
414 // Client name changed, display the change |
415 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", name); |
415 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", name); |
416 } else if (playas != ci->client_playas) { |
416 } else if (playas != ci->client_playas) { |
417 // The player changed from client-player.. |
417 // The client changed from client-player.. |
418 // Do not display that for now |
418 // Do not display that for now |
419 } |
419 } |
420 |
420 |
421 ci->client_playas = playas; |
421 ci->client_playas = playas; |
422 ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name)); |
422 ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name)); |
449 |
449 |
450 switch (error) { |
450 switch (error) { |
451 /* We made an error in the protocol, and our connection is closed.... */ |
451 /* We made an error in the protocol, and our connection is closed.... */ |
452 case NETWORK_ERROR_NOT_AUTHORIZED: |
452 case NETWORK_ERROR_NOT_AUTHORIZED: |
453 case NETWORK_ERROR_NOT_EXPECTED: |
453 case NETWORK_ERROR_NOT_EXPECTED: |
454 case NETWORK_ERROR_PLAYER_MISMATCH: |
454 case NETWORK_ERROR_COMPANY_MISMATCH: |
455 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR; |
455 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR; |
456 break; |
456 break; |
457 case NETWORK_ERROR_FULL: |
457 case NETWORK_ERROR_FULL: |
458 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL; |
458 _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL; |
459 break; |
459 break; |
620 * only toolbar/statusbar and gamefield are visible */ |
620 * only toolbar/statusbar and gamefield are visible */ |
621 |
621 |
622 // Say we received the map and loaded it correctly! |
622 // Say we received the map and loaded it correctly! |
623 SEND_COMMAND(PACKET_CLIENT_MAP_OK)(); |
623 SEND_COMMAND(PACKET_CLIENT_MAP_OK)(); |
624 |
624 |
625 /* New company/spectator (invalid player) or company we want to join is not active |
625 /* New company/spectator (invalid company) or company we want to join is not active |
626 * Switch local player to spectator and await the server's judgement */ |
626 * Switch local company to spectator and await the server's judgement */ |
627 if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayerID(_network_playas)) { |
627 if (_network_playas == COMPANY_NEW_COMPANY || !IsValidCompanyID(_network_playas)) { |
628 SetLocalPlayer(PLAYER_SPECTATOR); |
628 SetLocalCompany(COMPANY_SPECTATOR); |
629 |
629 |
630 if (_network_playas != PLAYER_SPECTATOR) { |
630 if (_network_playas != COMPANY_SPECTATOR) { |
631 /* We have arrived and ready to start playing; send a command to make a new player; |
631 /* We have arrived and ready to start playing; send a command to make a new company; |
632 * the server will give us a client-id and let us in */ |
632 * the server will give us a client-id and let us in */ |
633 _network_join_status = NETWORK_JOIN_STATUS_REGISTERING; |
633 _network_join_status = NETWORK_JOIN_STATUS_REGISTERING; |
634 ShowJoinStatusWindow(); |
634 ShowJoinStatusWindow(); |
635 NetworkSend_Command(0, 0, 0, CMD_PLAYER_CTRL, NULL); |
635 NetworkSend_Command(0, 0, 0, CMD_COMPANY_CTRL, NULL); |
636 } |
636 } |
637 } else { |
637 } else { |
638 // take control over an existing company |
638 // take control over an existing company |
639 SetLocalPlayer(_network_playas); |
639 SetLocalCompany(_network_playas); |
640 } |
640 } |
641 } |
641 } |
642 |
642 |
643 return NETWORK_RECV_STATUS_OKAY; |
643 return NETWORK_RECV_STATUS_OKAY; |
644 } |
644 } |
683 } |
683 } |
684 |
684 |
685 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND) |
685 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND) |
686 { |
686 { |
687 CommandPacket *cp = MallocT<CommandPacket>(1); |
687 CommandPacket *cp = MallocT<CommandPacket>(1); |
688 cp->player = (PlayerID)p->Recv_uint8(); |
688 cp->company = (CompanyID)p->Recv_uint8(); |
689 cp->cmd = p->Recv_uint32(); |
689 cp->cmd = p->Recv_uint32(); |
690 cp->p1 = p->Recv_uint32(); |
690 cp->p1 = p->Recv_uint32(); |
691 cp->p2 = p->Recv_uint32(); |
691 cp->p2 = p->Recv_uint32(); |
692 cp->tile = p->Recv_uint32(); |
692 cp->tile = p->Recv_uint32(); |
693 p->Recv_string(cp->text, sizeof(cp->text)); |
693 p->Recv_string(cp->text, sizeof(cp->text)); |
731 /* For speaking to client we need the client-name */ |
731 /* For speaking to client we need the client-name */ |
732 snprintf(name, sizeof(name), "%s", ci_to->client_name); |
732 snprintf(name, sizeof(name), "%s", ci_to->client_name); |
733 ci = NetworkFindClientInfoFromIndex(_network_own_client_index); |
733 ci = NetworkFindClientInfoFromIndex(_network_own_client_index); |
734 break; |
734 break; |
735 |
735 |
736 /* For speaking to company or giving money, we need the player-name */ |
736 /* For speaking to company or giving money, we need the company-name */ |
737 case NETWORK_ACTION_GIVE_MONEY: |
737 case NETWORK_ACTION_GIVE_MONEY: |
738 if (!IsValidPlayerID(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY; |
738 if (!IsValidCompanyID(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY; |
739 /* fallthrough */ |
739 /* fallthrough */ |
740 case NETWORK_ACTION_CHAT_COMPANY: { |
740 case NETWORK_ACTION_CHAT_COMPANY: { |
741 StringID str = IsValidPlayerID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS; |
741 StringID str = IsValidCompanyID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS; |
742 SetDParam(0, ci_to->client_playas); |
742 SetDParam(0, ci_to->client_playas); |
743 |
743 |
744 GetString(name, str, lastof(name)); |
744 GetString(name, str, lastof(name)); |
745 ci = NetworkFindClientInfoFromIndex(_network_own_client_index); |
745 ci = NetworkFindClientInfoFromIndex(_network_own_client_index); |
746 } break; |
746 } break; |
752 snprintf(name, sizeof(name), "%s", ci_to->client_name); |
752 snprintf(name, sizeof(name), "%s", ci_to->client_name); |
753 ci = ci_to; |
753 ci = ci_to; |
754 } |
754 } |
755 |
755 |
756 if (ci != NULL) |
756 if (ci != NULL) |
757 NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg); |
757 NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColor(ci->client_playas), self_send, name, "%s", msg); |
758 return NETWORK_RECV_STATUS_OKAY; |
758 return NETWORK_RECV_STATUS_OKAY; |
759 } |
759 } |
760 |
760 |
761 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT) |
761 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT) |
762 { |
762 { |
829 } |
829 } |
830 |
830 |
831 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME) |
831 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME) |
832 { |
832 { |
833 // To trottle the reconnects a bit, every clients waits |
833 // To trottle the reconnects a bit, every clients waits |
834 // his _local_player value before reconnecting |
834 // his _local_company value before reconnecting |
835 // PLAYER_SPECTATOR is currently 255, so to avoid long wait periods |
835 // COMPANY_SPECTATOR is currently 255, so to avoid long wait periods |
836 // set the max to 10. |
836 // set the max to 10. |
837 _network_reconnect = min(_local_player + 1, 10); |
837 _network_reconnect = min(_local_company + 1, 10); |
838 _switch_mode_errorstr = STR_NETWORK_SERVER_REBOOT; |
838 _switch_mode_errorstr = STR_NETWORK_SERVER_REBOOT; |
839 |
839 |
840 return NETWORK_RECV_STATUS_SERVER_ERROR; |
840 return NETWORK_RECV_STATUS_SERVER_ERROR; |
841 } |
841 } |
842 |
842 |
936 void NetworkClientSendRcon(const char *password, const char *command) |
936 void NetworkClientSendRcon(const char *password, const char *command) |
937 { |
937 { |
938 SEND_COMMAND(PACKET_CLIENT_RCON)(password, command); |
938 SEND_COMMAND(PACKET_CLIENT_RCON)(password, command); |
939 } |
939 } |
940 |
940 |
941 void NetworkUpdatePlayerName() |
941 void NetworkUpdateClientName() |
942 { |
942 { |
943 NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index); |
943 NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index); |
944 |
944 |
945 if (ci == NULL) return; |
945 if (ci == NULL) return; |
946 |
946 |
947 /* Don't change the name if it is the same as the old name */ |
947 /* Don't change the name if it is the same as the old name */ |
948 if (strcmp(ci->client_name, _settings_client.network.player_name) != 0) { |
948 if (strcmp(ci->client_name, _settings_client.network.client_name) != 0) { |
949 if (!_network_server) { |
949 if (!_network_server) { |
950 SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_settings_client.network.player_name); |
950 SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_settings_client.network.client_name); |
951 } else { |
951 } else { |
952 if (NetworkFindName(_settings_client.network.player_name)) { |
952 if (NetworkFindName(_settings_client.network.client_name)) { |
953 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _settings_client.network.player_name); |
953 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _settings_client.network.client_name); |
954 ttd_strlcpy(ci->client_name, _settings_client.network.player_name, sizeof(ci->client_name)); |
954 ttd_strlcpy(ci->client_name, _settings_client.network.client_name, sizeof(ci->client_name)); |
955 NetworkUpdateClientInfo(NETWORK_SERVER_INDEX); |
955 NetworkUpdateClientInfo(NETWORK_SERVER_INDEX); |
956 } |
956 } |
957 } |
957 } |
958 } |
958 } |
959 } |
959 } |
963 SEND_COMMAND(PACKET_CLIENT_CHAT)(action, type, dest, msg); |
963 SEND_COMMAND(PACKET_CLIENT_CHAT)(action, type, dest, msg); |
964 } |
964 } |
965 |
965 |
966 void NetworkClientSetPassword() |
966 void NetworkClientSetPassword() |
967 { |
967 { |
968 SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password); |
968 SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_company_info[_local_company].password); |
969 } |
969 } |
970 |
970 |
971 #endif /* ENABLE_NETWORK */ |
971 #endif /* ENABLE_NETWORK */ |