22 #include "../vehicle.h" |
22 #include "../vehicle.h" |
23 #include "../station.h" |
23 #include "../station.h" |
24 #include "../variables.h" |
24 #include "../variables.h" |
25 #include "../genworld.h" |
25 #include "../genworld.h" |
26 #include "../helpers.hpp" |
26 #include "../helpers.hpp" |
|
27 #include "../fileio.h" |
27 |
28 |
28 // This file handles all the server-commands |
29 // This file handles all the server-commands |
29 |
30 |
30 static void NetworkHandleCommandQueue(NetworkTCPSocketHandler* cs); |
31 static void NetworkHandleCommandQueue(NetworkTCPSocketHandler* cs); |
31 |
32 |
193 |
194 |
194 Packet *p = NetworkSend_Init(PACKET_SERVER_CHECK_NEWGRFS); |
195 Packet *p = NetworkSend_Init(PACKET_SERVER_CHECK_NEWGRFS); |
195 const GRFConfig *c; |
196 const GRFConfig *c; |
196 uint grf_count = 0; |
197 uint grf_count = 0; |
197 |
198 |
198 for (c = _grfconfig; c != NULL; c = c->next) grf_count++; |
199 for (c = _grfconfig; c != NULL; c = c->next) { |
|
200 if (!HASBIT(c->flags, GCF_STATIC)) grf_count++; |
|
201 } |
199 |
202 |
200 p->Send_uint8 (grf_count); |
203 p->Send_uint8 (grf_count); |
201 for (c = _grfconfig; c != NULL; c = c->next) { |
204 for (c = _grfconfig; c != NULL; c = c->next) { |
202 cs->Send_GRFIdentifier(p, c); |
205 if (!HASBIT(c->flags, GCF_STATIC)) cs->Send_GRFIdentifier(p, c); |
203 } |
206 } |
204 |
207 |
205 cs->Send_Packet(p); |
208 cs->Send_Packet(p); |
206 } |
209 } |
207 |
210 |
305 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); |
308 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); |
306 return; |
309 return; |
307 } |
310 } |
308 |
311 |
309 if (cs->status == STATUS_AUTH) { |
312 if (cs->status == STATUS_AUTH) { |
310 char filename[256]; |
313 const char *filename = "network_server.tmp"; |
311 Packet *p; |
314 Packet *p; |
312 |
315 |
313 // Make a dump of the current game |
316 // Make a dump of the current game |
314 snprintf(filename, lengthof(filename), "%s%snetwork_server.tmp", _paths.autosave_dir, PATHSEP); |
317 if (SaveOrLoad(filename, SL_SAVE, AUTOSAVE_DIR) != SL_OK) error("network savedump failed"); |
315 if (SaveOrLoad(filename, SL_SAVE) != SL_OK) error("network savedump failed"); |
318 |
316 |
319 file_pointer = FioFOpenFile(filename, "rb", AUTOSAVE_DIR); |
317 file_pointer = fopen(filename, "rb"); |
|
318 fseek(file_pointer, 0, SEEK_END); |
320 fseek(file_pointer, 0, SEEK_END); |
319 |
321 |
320 if (ftell(file_pointer) == 0) error("network savedump failed - zero sized savegame?"); |
322 if (ftell(file_pointer) == 0) error("network savedump failed - zero sized savegame?"); |
321 |
323 |
322 // Now send the _frame_counter and how many packets are coming |
324 // Now send the _frame_counter and how many packets are coming |
487 p->Send_uint32(cp->p2); |
489 p->Send_uint32(cp->p2); |
488 p->Send_uint32(cp->tile); |
490 p->Send_uint32(cp->tile); |
489 p->Send_string(cp->text); |
491 p->Send_string(cp->text); |
490 p->Send_uint8 (cp->callback); |
492 p->Send_uint8 (cp->callback); |
491 p->Send_uint32(cp->frame); |
493 p->Send_uint32(cp->frame); |
|
494 p->Send_bool (cp->my_cmd); |
492 |
495 |
493 cs->Send_Packet(p); |
496 cs->Send_Packet(p); |
494 } |
497 } |
495 |
498 |
496 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkTCPSocketHandler *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg) |
499 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkTCPSocketHandler *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg) |
830 { |
833 { |
831 NetworkTCPSocketHandler *new_cs; |
834 NetworkTCPSocketHandler *new_cs; |
832 const NetworkClientInfo *ci; |
835 const NetworkClientInfo *ci; |
833 byte callback; |
836 byte callback; |
834 |
837 |
835 CommandPacket *cp = MallocT<CommandPacket>(1); |
|
836 |
|
837 // The client was never joined.. so this is impossible, right? |
838 // The client was never joined.. so this is impossible, right? |
838 // Ignore the packet, give the client a warning, and close his connection |
839 // Ignore the packet, give the client a warning, and close his connection |
839 if (cs->status < STATUS_DONE_MAP || cs->has_quit) { |
840 if (cs->status < STATUS_DONE_MAP || cs->has_quit) { |
840 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
841 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
841 return; |
842 return; |
842 } |
843 } |
843 |
844 |
|
845 CommandPacket *cp = MallocT<CommandPacket>(1); |
844 cp->player = (Owner)p->Recv_uint8(); |
846 cp->player = (Owner)p->Recv_uint8(); |
845 cp->cmd = p->Recv_uint32(); |
847 cp->cmd = p->Recv_uint32(); |
846 cp->p1 = p->Recv_uint32(); |
848 cp->p1 = p->Recv_uint32(); |
847 cp->p2 = p->Recv_uint32(); |
849 cp->p2 = p->Recv_uint32(); |
848 cp->tile = p->Recv_uint32(); |
850 cp->tile = p->Recv_uint32(); |
849 p->Recv_string(cp->text, lengthof(cp->text)); |
851 p->Recv_string(cp->text, lengthof(cp->text)); |
850 |
852 |
851 callback = p->Recv_uint8(); |
853 callback = p->Recv_uint8(); |
852 |
854 |
853 if (cs->has_quit) return; |
855 if (cs->has_quit) { |
|
856 free(cp); |
|
857 return; |
|
858 } |
854 |
859 |
855 ci = DEREF_CLIENT_INFO(cs); |
860 ci = DEREF_CLIENT_INFO(cs); |
856 |
861 |
857 /* Check if cp->cmd is valid */ |
862 /* Check if cp->cmd is valid */ |
858 if (!IsValidCommand(cp->cmd)) { |
863 if (!IsValidCommand(cp->cmd)) { |
859 IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci)); |
864 IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci)); |
860 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
865 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
|
866 free(cp); |
861 return; |
867 return; |
862 } |
868 } |
863 |
869 |
864 if (!CheckCommandFlags(cp, ci)) { |
870 if (!CheckCommandFlags(cp, ci)) { |
865 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED); |
871 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED); |
|
872 free(cp); |
866 return; |
873 return; |
867 } |
874 } |
868 |
875 |
869 /** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs |
876 /** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs |
870 * to match the player in the packet. If it doesn't, the client has done |
877 * to match the player in the packet. If it doesn't, the client has done |
872 */ |
879 */ |
873 if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) { |
880 if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) { |
874 IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...", |
881 IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...", |
875 ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1); |
882 ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1); |
876 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH); |
883 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH); |
|
884 free(cp); |
877 return; |
885 return; |
878 } |
886 } |
879 |
887 |
880 /** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the |
888 /** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the |
881 * player the correct ID, the server injects p2 and executes the command. Any other p1 |
889 * player the correct ID, the server injects p2 and executes the command. Any other p1 |
883 * @see CmdPlayerCtrl() players.c:655 |
891 * @see CmdPlayerCtrl() players.c:655 |
884 */ |
892 */ |
885 if (cp->cmd == CMD_PLAYER_CTRL) { |
893 if (cp->cmd == CMD_PLAYER_CTRL) { |
886 if (cp->p1 != 0) { |
894 if (cp->p1 != 0) { |
887 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER); |
895 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER); |
|
896 free(cp); |
888 return; |
897 return; |
889 } |
898 } |
890 |
899 |
891 /* XXX - Execute the command as a valid player. Normally this would be done by a |
900 /* XXX - Execute the command as a valid player. Normally this would be done by a |
892 * spectator, but that is not allowed any commands. So do an impersonation. The drawback |
901 * spectator, but that is not allowed any commands. So do an impersonation. The drawback |
905 FOR_ALL_CLIENTS(new_cs) { |
914 FOR_ALL_CLIENTS(new_cs) { |
906 if (new_cs->status >= STATUS_MAP) { |
915 if (new_cs->status >= STATUS_MAP) { |
907 // Callbacks are only send back to the client who sent them in the |
916 // Callbacks are only send back to the client who sent them in the |
908 // first place. This filters that out. |
917 // first place. This filters that out. |
909 cp->callback = (new_cs != cs) ? 0 : callback; |
918 cp->callback = (new_cs != cs) ? 0 : callback; |
|
919 cp->my_cmd = (new_cs == cs); |
910 NetworkAddCommandQueue(new_cs, cp); |
920 NetworkAddCommandQueue(new_cs, cp); |
911 } |
921 } |
912 } |
922 } |
913 |
923 |
914 cp->callback = 0; |
924 cp->callback = 0; |
|
925 cp->my_cmd = false; |
915 // Queue the command on the server |
926 // Queue the command on the server |
916 if (_local_command_queue == NULL) { |
927 if (_local_command_queue == NULL) { |
917 _local_command_queue = cp; |
928 _local_command_queue = cp; |
918 } else { |
929 } else { |
919 // Find last packet |
930 // Find last packet |
1082 |
1093 |
1083 // Display the message locally (so you know you have sent it) |
1094 // Display the message locally (so you know you have sent it) |
1084 if (ci != NULL && show_local) { |
1095 if (ci != NULL && show_local) { |
1085 if (from_index == NETWORK_SERVER_INDEX) { |
1096 if (from_index == NETWORK_SERVER_INDEX) { |
1086 char name[NETWORK_NAME_LENGTH]; |
1097 char name[NETWORK_NAME_LENGTH]; |
1087 StringID str = IsValidPlayer(ci_to->client_playas) ? GetPlayer(ci_to->client_playas)->name_1 : (uint16)STR_NETWORK_SPECTATORS; |
1098 StringID str = IsValidPlayer(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS; |
|
1099 SetDParam(0, ci_to->client_playas); |
1088 GetString(name, str, lastof(name)); |
1100 GetString(name, str, lastof(name)); |
1089 NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg); |
1101 NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg); |
1090 } else { |
1102 } else { |
1091 FOR_ALL_CLIENTS(cs) { |
1103 FOR_ALL_CLIENTS(cs) { |
1092 if (cs->index == from_index) { |
1104 if (cs->index == from_index) { |
1251 memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo)); |
1263 memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo)); |
1252 _network_player_info[p->index].months_empty = months_empty; |
1264 _network_player_info[p->index].months_empty = months_empty; |
1253 ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password)); |
1265 ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password)); |
1254 |
1266 |
1255 // Grap the company name |
1267 // Grap the company name |
1256 SetDParam(0, p->name_1); |
1268 SetDParam(0, p->index); |
1257 SetDParam(1, p->name_2); |
1269 GetString(_network_player_info[p->index].company_name, STR_COMPANY_NAME, lastof(_network_player_info[p->index].company_name)); |
1258 GetString(_network_player_info[p->index].company_name, STR_JUST_STRING, lastof(_network_player_info[p->index].company_name)); |
|
1259 |
1270 |
1260 // Check the income |
1271 // Check the income |
1261 if (_cur_year - 1 == p->inaugurated_year) { |
1272 if (_cur_year - 1 == p->inaugurated_year) { |
1262 // The player is here just 1 year, so display [2], else display[1] |
1273 // The player is here just 1 year, so display [2], else display[1] |
1263 for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) { |
1274 for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) { |
1270 } |
1281 } |
1271 |
1282 |
1272 // Set some general stuff |
1283 // Set some general stuff |
1273 _network_player_info[p->index].inaugurated_year = p->inaugurated_year; |
1284 _network_player_info[p->index].inaugurated_year = p->inaugurated_year; |
1274 _network_player_info[p->index].company_value = p->old_economy[0].company_value; |
1285 _network_player_info[p->index].company_value = p->old_economy[0].company_value; |
1275 _network_player_info[p->index].money = p->money64; |
1286 _network_player_info[p->index].money = p->player_money; |
1276 _network_player_info[p->index].performance = p->old_economy[0].performance_history; |
1287 _network_player_info[p->index].performance = p->old_economy[0].performance_history; |
1277 } |
1288 } |
1278 |
1289 |
1279 // Go through all vehicles and count the type of vehicles |
1290 // Go through all vehicles and count the type of vehicles |
1280 FOR_ALL_VEHICLES(v) { |
1291 FOR_ALL_VEHICLES(v) { |