OpenTTD Source 20250312-master-gcdcc6b491d
network_client.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "../stdafx.h"
11#include "network_gui.h"
12#include "../saveload/saveload.h"
13#include "../saveload/saveload_filter.h"
14#include "../command_func.h"
15#include "../console_func.h"
16#include "../strings_func.h"
17#include "../window_func.h"
18#include "../company_func.h"
19#include "../company_base.h"
20#include "../company_gui.h"
21#include "../company_cmd.h"
22#include "../core/random_func.hpp"
23#include "../timer/timer_game_tick.h"
24#include "../timer/timer_game_calendar.h"
25#include "../gfx_func.h"
26#include "../error.h"
27#include "../rev.h"
28#include "network.h"
29#include "network_base.h"
30#include "network_client.h"
31#include "network_gamelist.h"
32#include "../core/backup_type.hpp"
33#include "../thread.h"
34#include "../social_integration.h"
35
36#include "table/strings.h"
37
38#include "../safeguards.h"
39
40/* This file handles all the client-commands */
41
44 using Buffer = std::deque<uint8_t>;
45
47 Buffer::const_iterator iterator;
48 size_t read_bytes = 0;
49
52 {
53 }
54
62 static inline ssize_t TransferOutMemCopy(PacketReader *destination, const char *source, size_t amount)
63 {
64 std::copy_n(source, amount, std::back_inserter(destination->buffer));
65 return amount;
66 }
67
73 {
74 assert(this->read_bytes == 0);
76 }
77
78 size_t Read(uint8_t *rbuf, size_t size) override
79 {
80 /* Limit the amount to read to whatever we still have. */
81 size_t read_size = std::min(this->buffer.size() - this->read_bytes, size);
82
83 std::copy_n(this->iterator, read_size, rbuf);
84 std::advance(this->iterator, read_size);
85 this->read_bytes += read_size;
86
87 return read_size;
88 }
89
90 void Reset() override
91 {
92 this->read_bytes = 0;
93 this->iterator = this->buffer.cbegin();
94 }
95};
96
97
102{
103 static FiosNumberedSaveName _netsave_ctr("netsave");
104 DoAutoOrNetsave(_netsave_ctr);
105}
106
107
112ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string) : NetworkGameSocketHandler(s), connection_string(connection_string)
113{
116}
117
126
128{
130 if (this->IsPendingDeletion()) return status;
131
132 assert(this->sock != INVALID_SOCKET);
133
134 if (!this->HasClientQuit()) {
135 Debug(net, 3, "Closed client connection {}", this->client_id);
136
137 this->SendPackets(true);
138
139 /* Wait a number of ticks so our leave message can reach the server.
140 * This is especially needed for Windows servers as they seem to get
141 * the "socket is closed" message before receiving our leave message,
142 * which would trigger the server to close the connection as well. */
144 }
145
146 this->DeferDeletion();
147
148 return status;
149}
150
156{
157 if (this->IsPendingDeletion()) return;
158
159 /* First, send a CLIENT_ERROR to the server, so it knows we are
160 * disconnected (and why!) */
161 NetworkErrorCode errorno;
162
163 /* We just want to close the connection.. */
166 this->CloseConnection(res);
167 _networking = false;
168
170 return;
171 }
172
173 switch (res) {
174 case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
175 case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
176 case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
177 default: errorno = NETWORK_ERROR_GENERAL; break;
178 }
179
182 /* This means the server closed the connection. Emergency save is
183 * already created if this was appropriate during handling of the
184 * disconnect. */
185 this->CloseConnection(res);
186 } else {
187 /* This means we as client made a boo-boo. */
188 SendError(errorno);
189
190 /* Close connection before we make an emergency save, as the save can
191 * take a bit of time; better that the server doesn't stall while we
192 * are doing the save, and already disconnects us. */
193 this->CloseConnection(res);
195 }
196
198
199 if (_game_mode != GM_MENU) _switch_mode = SM_MENU;
200 _networking = false;
201}
202
203
210{
211 if (my_client->CanSendReceive()) {
213 if (res != NETWORK_RECV_STATUS_OKAY) {
214 /* The client made an error of which we can not recover.
215 * Close the connection and drop back to the main menu. */
217 return false;
218 }
219 }
220 return _networking;
221}
222
225{
227 if (my_client != nullptr) my_client->CheckConnection();
228}
229
235{
237
239
241
242 /* Check if we are in sync! */
243 if (_sync_frame != 0) {
245#ifdef NETWORK_SEND_DOUBLE_SEED
246 if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
247#else
248 if (_sync_seed_1 != _random.state[0]) {
249#endif
250 ShowNetworkError(STR_NETWORK_ERROR_DESYNC);
251 Debug(desync, 1, "sync_err: {:08x}; {:02x}", TimerGameEconomy::date, TimerGameEconomy::date_fract);
252 Debug(net, 0, "Sync error detected");
254 return false;
255 }
256
257 /* If this is the first time we have a sync-frame, we
258 * need to let the server know that we are ready and at the same
259 * frame as it is.. so we can start playing! */
261 _network_first_time = false;
262 SendAck();
263 }
264
265 _sync_frame = 0;
266 } else if (_sync_frame < _frame_counter) {
267 Debug(net, 1, "Missed frame for sync-test: {} / {}", _sync_frame, _frame_counter);
268 _sync_frame = 0;
269 }
270 }
271
272 return true;
273}
274
275
278
280static uint32_t last_ack_frame;
281
286
289
290/***********
291 * Sending functions
292 ************/
293
296{
297 Debug(net, 9, "Client::SendJoin()");
298
299 Debug(net, 9, "Client::status = JOIN");
301 Debug(net, 9, "Client::join_status = AUTHORIZING");
302 _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
304
305 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_JOIN);
306 p->Send_string(GetNetworkRevisionString());
307 p->Send_uint32(_openttd_newgrf_version);
308 my_client->SendPacket(std::move(p));
309
311}
312
313NetworkRecvStatus ClientNetworkGameSocketHandler::SendIdentify()
314{
315 Debug(net, 9, "Client::SendIdentify()");
316
317 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_IDENTIFY);
318 p->Send_string(_settings_client.network.client_name); // Client name
319 p->Send_uint8(_network_join.company); // PlayAs
320 my_client->SendPacket(std::move(p));
322}
323
326{
327 Debug(net, 9, "Client::SendNewGRFsOk()");
328
329 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_NEWGRFS_CHECKED);
330 my_client->SendPacket(std::move(p));
332}
333
339{
340 Debug(net, 9, "Client::SendAuthResponse()");
341
342 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_AUTH_RESPONSE);
343 my_client->authentication_handler->SendResponse(*p);
344 my_client->SendPacket(std::move(p));
345
347}
348
351{
352 Debug(net, 9, "Client::SendGetMap()");
353
354 Debug(net, 9, "Client::status = MAP_WAIT");
356
357 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_GETMAP);
358 my_client->SendPacket(std::move(p));
360}
361
364{
365 Debug(net, 9, "Client::SendMapOk()");
366
367 Debug(net, 9, "Client::status = ACTIVE");
369
370 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_MAP_OK);
371 my_client->SendPacket(std::move(p));
373}
374
377{
378 Debug(net, 9, "Client::SendAck()");
379
380 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_ACK);
381
382 p->Send_uint32(_frame_counter);
383 p->Send_uint8 (my_client->token);
384 my_client->SendPacket(std::move(p));
386}
387
393{
394 Debug(net, 9, "Client::SendCommand(): cmd={}", cp.cmd);
395
396 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_COMMAND);
397 my_client->NetworkGameSocketHandler::SendCommand(*p, cp);
398
399 my_client->SendPacket(std::move(p));
401}
402
404NetworkRecvStatus ClientNetworkGameSocketHandler::SendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data)
405{
406 Debug(net, 9, "Client::SendChat(): action={}, type={}, dest={}", action, type, dest);
407
408 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_CHAT);
409
410 p->Send_uint8 (action);
411 p->Send_uint8 (type);
412 p->Send_uint32(dest);
413 p->Send_string(msg);
414 p->Send_uint64(data);
415
416 my_client->SendPacket(std::move(p));
418}
419
422{
423 Debug(net, 9, "Client::SendError(): errorno={}", errorno);
424
425 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_ERROR);
426
427 p->Send_uint8(errorno);
428 my_client->SendPacket(std::move(p));
430}
431
437{
438 Debug(net, 9, "Client::SendSetName()");
439
440 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_SET_NAME);
441
442 p->Send_string(name);
443 my_client->SendPacket(std::move(p));
445}
446
451{
452 Debug(net, 9, "Client::SendQuit()");
453
454 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_QUIT);
455
456 my_client->SendPacket(std::move(p));
458}
459
465NetworkRecvStatus ClientNetworkGameSocketHandler::SendRCon(const std::string &pass, const std::string &command)
466{
467 Debug(net, 9, "Client::SendRCon()");
468
469 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_RCON);
470 p->Send_string(pass);
471 p->Send_string(command);
472 my_client->SendPacket(std::move(p));
474}
475
481{
482 Debug(net, 9, "Client::SendMove(): company={}", company);
483
484 auto p = std::make_unique<Packet>(my_client, PACKET_CLIENT_MOVE);
485 p->Send_uint8(company);
486 my_client->SendPacket(std::move(p));
488}
489
498
499
500/***********
501 * Receiving functions
502 ************/
503
504extern bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, std::shared_ptr<struct LoadFilter> lf);
505
507{
508 Debug(net, 9, "Client::Receive_SERVER_FULL()");
509
510 /* We try to join a server which is full */
511 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SERVER_FULL), {}, WL_CRITICAL);
512
514}
515
517{
518 Debug(net, 9, "Client::Receive_SERVER_BANNED()");
519
520 /* We try to join a server where we are banned */
521 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SERVER_BANNED), {}, WL_CRITICAL);
522
524}
525
526/* This packet contains info about the client (playas and name)
527 * as client we save this in NetworkClientInfo, linked via 'client_id'
528 * which is always an unique number on a server. */
530{
533 CompanyID playas = (CompanyID)p.Recv_uint8();
534
535 Debug(net, 9, "Client::Receive_SERVER_CLIENT_INFO(): client_id={}, playas={}", client_id, playas);
536
537 std::string name = p.Recv_string(NETWORK_NAME_LENGTH);
538 std::string public_key = p.Recv_string(NETWORK_PUBLIC_KEY_LENGTH);
539
542 /* The server validates the name when receiving it from clients, so when it is wrong
543 * here something went really wrong. In the best case the packet got malformed on its
544 * way too us, in the worst case the server is broken or compromised. */
546
548 if (ci != nullptr) {
549 if (playas == ci->client_playas && name.compare(ci->client_name) != 0) {
550 /* Client name changed, display the change */
551 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, name);
552 } else if (playas != ci->client_playas) {
553 /* The client changed from client-player..
554 * Do not display that for now */
555 }
556
557 /* Make sure we're in the company the server tells us to be in,
558 * for the rare case that we get moved while joining. */
560
561 ci->client_playas = playas;
562 ci->client_name = name;
563 ci->public_key = public_key;
564
566
568 }
569
570 /* There are at most as many ClientInfo as ClientSocket objects in a
571 * server. Having more info than a server can have means something
572 * has gone wrong somewhere, i.e. the server has more info than it
573 * has actual clients. That means the server is feeding us an invalid
574 * state. So, bail out! This server is broken. */
576
577 /* We don't have this client_id yet, find an empty client_id, and put the data there */
579 ci->client_playas = playas;
580 if (client_id == _network_own_client_id) this->SetInfo(ci);
581
582 ci->client_name = name;
583 ci->public_key = public_key;
584
586
588}
589
591{
592 static const StringID network_error_strings[] = {
593 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_GENERAL
594 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_DESYNC
595 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_SAVEGAME_FAILED
596 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_CONNECTION_LOST
597 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_ILLEGAL_PACKET
598 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NEWGRF_MISMATCH
599 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_AUTHORIZED
600 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NOT_EXPECTED
601 STR_NETWORK_ERROR_WRONG_REVISION, // NETWORK_ERROR_WRONG_REVISION
602 STR_NETWORK_ERROR_LOSTCONNECTION, // NETWORK_ERROR_NAME_IN_USE
603 STR_NETWORK_ERROR_WRONG_PASSWORD, // NETWORK_ERROR_WRONG_PASSWORD
604 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_COMPANY_MISMATCH
605 STR_NETWORK_ERROR_KICKED, // NETWORK_ERROR_KICKED
606 STR_NETWORK_ERROR_CHEATER, // NETWORK_ERROR_CHEATER
607 STR_NETWORK_ERROR_SERVER_FULL, // NETWORK_ERROR_FULL
608 STR_NETWORK_ERROR_TOO_MANY_COMMANDS, // NETWORK_ERROR_TOO_MANY_COMMANDS
609 STR_NETWORK_ERROR_TIMEOUT_PASSWORD, // NETWORK_ERROR_TIMEOUT_PASSWORD
610 STR_NETWORK_ERROR_TIMEOUT_COMPUTER, // NETWORK_ERROR_TIMEOUT_COMPUTER
611 STR_NETWORK_ERROR_TIMEOUT_MAP, // NETWORK_ERROR_TIMEOUT_MAP
612 STR_NETWORK_ERROR_TIMEOUT_JOIN, // NETWORK_ERROR_TIMEOUT_JOIN
613 STR_NETWORK_ERROR_INVALID_CLIENT_NAME, // NETWORK_ERROR_INVALID_CLIENT_NAME
614 STR_NETWORK_ERROR_NOT_ON_ALLOW_LIST, // NETWORK_ERROR_NOT_ON_ALLOW_LIST
615 STR_NETWORK_ERROR_SERVER_ERROR, // NETWORK_ERROR_NO_AUTHENTICATION_METHOD_AVAILABLE
616 };
617 static_assert(lengthof(network_error_strings) == NETWORK_ERROR_END);
618
620
621 Debug(net, 9, "Client::Receive_SERVER_ERROR(): error={}", error);
622
623 StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
624 if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
625 /* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
626 if (error == NETWORK_ERROR_KICKED && p.CanReadFromPacket(1)) {
628 GetEncodedString(STR_NETWORK_ERROR_KICK_MESSAGE, p.Recv_string(NETWORK_CHAT_LENGTH)),
630 } else {
632 }
633
634 /* Perform an emergency save if we had already entered the game */
636
638}
639
641{
643
644 uint grf_count = p.Recv_uint8();
646
647 Debug(net, 9, "Client::Receive_SERVER_CHECK_NEWGRFS(): grf_count={}", grf_count);
648
649 /* Check all GRFs */
650 for (; grf_count > 0; grf_count--) {
652 DeserializeGRFIdentifier(p, c);
653
654 /* Check whether we know this GRF */
655 const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, &c.md5sum);
656 if (f == nullptr) {
657 /* We do not know this GRF, bail out of initialization */
658 Debug(grf, 0, "NewGRF {:08X} not found; checksum {}", std::byteswap(c.grfid), FormatArrayAsHex(c.md5sum));
660 }
661 }
662
663 if (ret == NETWORK_RECV_STATUS_OKAY) {
664 /* Start receiving the map */
665 return SendNewGRFsOk();
666 }
667
668 /* NewGRF mismatch, bail out */
669 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_NEWGRF_MISMATCH), {}, WL_CRITICAL);
670 return ret;
671}
672
674 virtual void SendResponse() override { MyClient::SendAuthResponse(); }
675 virtual void AskUserForPassword(std::shared_ptr<NetworkAuthenticationPasswordRequest> request) override
676 {
677 if (!_network_join.server_password.empty()) {
678 request->Reply(_network_join.server_password);
679 } else {
680 ShowNetworkNeedPassword(request);
681 }
682 }
683};
684
686{
688 Debug(net, 9, "Client::status = AUTH_GAME");
689 this->status = STATUS_AUTH_GAME;
690
691 Debug(net, 9, "Client::Receive_SERVER_AUTH_REQUEST()");
692
693 if (this->authentication_handler == nullptr) {
694 this->authentication_handler = NetworkAuthenticationClientHandler::Create(std::make_shared<ClientGamePasswordRequestHandler>(),
696 }
697 switch (this->authentication_handler->ReceiveRequest(p)) {
699 return SendAuthResponse();
700
703
705 default:
707 }
708}
709
711{
713
714 Debug(net, 9, "Client::Receive_SERVER_ENABLE_ENCRYPTION()");
715
716 if (!this->authentication_handler->ReceiveEnableEncryption(p)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
717
718 this->receive_encryption_handler = this->authentication_handler->CreateServerToClientEncryptionHandler();
719 this->send_encryption_handler = this->authentication_handler->CreateClientToServerEncryptionHandler();
720 this->authentication_handler = nullptr;
721
722 Debug(net, 9, "Client::status = ENCRYPTED");
723 this->status = STATUS_ENCRYPTED;
724
725 return this->SendIdentify();
726}
727
729{
730 if (this->status < STATUS_ENCRYPTED || this->status >= STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
731 Debug(net, 9, "Client::status = AUTHORIZED");
733
735
736 Debug(net, 9, "Client::Receive_SERVER_WELCOME(): client_id={}", _network_own_client_id);
737
738 /* Start receiving the map */
739 return SendGetMap();
740}
741
743{
744 /* We set the internal wait state when requesting the map. */
746
747 Debug(net, 9, "Client::Receive_SERVER_WAIT()");
748
749 /* But... only now we set the join status to waiting, instead of requesting. */
750 Debug(net, 9, "Client::join_status = WAITING");
751 _network_join_status = NETWORK_JOIN_STATUS_WAITING;
754
756}
757
759{
760 if (this->status < STATUS_AUTHORIZED || this->status >= STATUS_MAP) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
761 Debug(net, 9, "Client::status = MAP");
762 this->status = STATUS_MAP;
763
764 if (this->savegame != nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
765
766 this->savegame = std::make_shared<PacketReader>();
767
769
770 Debug(net, 9, "Client::Receive_SERVER_MAP_BEGIN(): frame_counter={}", _frame_counter);
771
774
775 Debug(net, 9, "Client::join_status = DOWNLOADING");
776 _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
778
780}
781
794
796{
798 if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
799
800 /* We are still receiving data, put it to the file */
801 this->savegame->AddPacket(p);
802
803 _network_join_bytes = static_cast<uint32_t>(this->savegame->buffer.size());
805
807}
808
810{
812 if (this->savegame == nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
813
814 Debug(net, 9, "Client::Receive_SERVER_MAP_DONE()");
815
816 Debug(net, 9, "Client::join_status = PROCESSING");
817 _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
819
820 this->savegame->Reset();
821
822 /* The map is done downloading, load it */
824
825 /* Set the abstract filetype. This is read during savegame load. */
827
828 bool load_success = SafeLoad({}, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, this->savegame);
829 this->savegame = nullptr;
830
831 /* Long savegame loads shouldn't affect the lag calculation! */
832 this->last_packet = std::chrono::steady_clock::now();
833
834 if (!load_success) {
835 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SAVEGAMEERROR), {}, WL_CRITICAL);
837 }
838 /* If the savegame has successfully loaded, ALL windows have been removed,
839 * only toolbar/statusbar and gamefield are visible */
840
841 /* Say we received the map and loaded it correctly! */
842 SendMapOk();
843
844 /* As we skipped switch-mode, update the time we "switched". */
845 _game_session_stats.start_time = std::chrono::steady_clock::now();
846 _game_session_stats.savegame_size = std::nullopt;
847
848 ShowClientList();
849
850 /* New company/spectator (invalid company) or company we want to join is not active
851 * Switch local company to spectator and await the server's judgement */
854
856 /* We have arrived and ready to start playing; send a command to make a new company;
857 * the server will give us a client-id and let us in */
858 Debug(net, 9, "Client::join_status = REGISTERING");
859 _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
860 ShowJoinStatusWindow();
862 }
863 } else {
864 /* take control over an existing company */
866 }
867
869
871}
872
874{
876
879#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
880 /* Test if the server supports this option
881 * and if we are at the frame the server is */
882#ifdef NETWORK_SEND_DOUBLE_SEED
883 if (p.CanReadFromPacket(sizeof(uint32_t) + sizeof(uint32_t))) {
884#else
885 if (p.CanReadFromPacket(sizeof(uint32_t))) {
886#endif
889#ifdef NETWORK_SEND_DOUBLE_SEED
890 _sync_seed_2 = p.Recv_uint32();
891#endif
892 }
893#endif
894 /* Receive the token. */
895 if (p.CanReadFromPacket(sizeof(uint8_t))) this->token = p.Recv_uint8();
896
897 /* Let the server know that we received this frame correctly
898 * We do this only once per day, to save some bandwidth ;) */
901 Debug(net, 7, "Sent ACK at {}", _frame_counter);
902 SendAck();
903 }
904
906}
907
909{
911
914#ifdef NETWORK_SEND_DOUBLE_SEED
915 _sync_seed_2 = p.Recv_uint32();
916#endif
917
918 Debug(net, 9, "Client::Receive_SERVER_SYNC(): sync_frame={}, sync_seed_1={}", _sync_frame, _sync_seed_1);
919
921}
922
924{
926
927 CommandPacket cp;
928 const char *err = this->ReceiveCommand(p, cp);
929 cp.frame = p.Recv_uint32();
930 cp.my_cmd = p.Recv_bool();
931
932 Debug(net, 9, "Client::Receive_SERVER_COMMAND(): cmd={}, frame={}", cp.cmd, cp.frame);
933
934 if (err != nullptr) {
935 IConsolePrint(CC_WARNING, "Dropping server connection due to {}.", err);
937 }
938
939 this->incoming_queue.push_back(cp);
940
942}
943
945{
947
948 std::string name;
949 const NetworkClientInfo *ci = nullptr, *ci_to;
950
953 bool self_send = p.Recv_bool();
954 std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
955 int64_t data = p.Recv_uint64();
956
957 Debug(net, 9, "Client::Receive_SERVER_CHAT(): action={}, client_id={}, self_send={}", action, client_id, self_send);
958
960 if (ci_to == nullptr) return NETWORK_RECV_STATUS_OKAY;
961
962 /* Did we initiate the action locally? */
963 if (self_send) {
964 switch (action) {
965 case NETWORK_ACTION_CHAT_CLIENT:
966 /* For speaking to client we need the client-name */
967 name = ci_to->client_name;
969 break;
970
971 /* For speaking to company, we need the company-name */
972 case NETWORK_ACTION_CHAT_COMPANY: {
973 StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
974
975 name = GetString(str, ci_to->client_playas);
977 break;
978 }
979
981 }
982 } else {
983 /* Display message from somebody else */
984 name = ci_to->client_name;
985 ci = ci_to;
986 }
987
988 if (ci != nullptr) {
989 NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), self_send, name, msg, data);
990 }
992}
993
995{
997
998 std::string source = p.Recv_string(NETWORK_CHAT_LENGTH);
999 TextColour colour = (TextColour)p.Recv_uint16();
1000 std::string user = p.Recv_string(NETWORK_CHAT_LENGTH);
1001 std::string msg = p.Recv_string(NETWORK_CHAT_LENGTH);
1002
1003 Debug(net, 9, "Client::Receive_SERVER_EXTERNAL_CHAT(): source={}", source);
1004
1006
1007 NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, source);
1008
1010}
1011
1013{
1015
1017
1018 Debug(net, 9, "Client::Receive_SERVER_ERROR_QUIT(): client_id={}", client_id);
1019
1021 if (ci != nullptr) {
1022 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "", GetNetworkErrorMsg((NetworkErrorCode)p.Recv_uint8()));
1023 delete ci;
1024 }
1025
1027
1029}
1030
1032{
1034
1036
1037 Debug(net, 9, "Client::Receive_SERVER_QUIT(): client_id={}", client_id);
1038
1040 if (ci != nullptr) {
1041 NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "", STR_NETWORK_MESSAGE_CLIENT_LEAVING);
1042 delete ci;
1043 } else {
1044 Debug(net, 1, "Unknown client ({}) is leaving the game", client_id);
1045 }
1046
1048
1049 /* If we come here it means we could not locate the client.. strange :s */
1051}
1052
1054{
1056
1058
1059 Debug(net, 9, "Client::Receive_SERVER_JOIN(): client_id={}", client_id);
1060
1062 if (ci != nullptr) {
1063 NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name);
1064 }
1065
1067
1069}
1070
1072{
1073 Debug(net, 9, "Client::Receive_SERVER_SHUTDOWN()");
1074
1075 /* Only when we're trying to join we really
1076 * care about the server shutting down. */
1077 if (this->status >= STATUS_JOIN) {
1078 ShowErrorMessage(GetEncodedString(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN), {}, WL_CRITICAL);
1079 }
1080
1082
1084}
1085
1087{
1088 Debug(net, 9, "Client::Receive_SERVER_NEWGAME()");
1089
1090 /* Only when we're trying to join we really
1091 * care about the server shutting down. */
1092 if (this->status >= STATUS_JOIN) {
1093 /* To throttle the reconnects a bit, every clients waits its
1094 * Client ID modulo 16 + 1 (value 0 means no reconnect).
1095 * This way reconnects should be spread out a bit. */
1097 ShowErrorMessage(GetEncodedString(STR_NETWORK_MESSAGE_SERVER_REBOOT), {}, WL_CRITICAL);
1098 }
1099
1101
1103}
1104
1106{
1108
1109 Debug(net, 9, "Client::Receive_SERVER_RCON()");
1110
1111 TextColour colour_code = (TextColour)p.Recv_uint16();
1113
1114 std::string rcon_out = p.Recv_string(NETWORK_RCONCOMMAND_LENGTH);
1115
1116 IConsolePrint(colour_code, rcon_out);
1117
1119}
1120
1122{
1124
1125 /* Nothing more in this packet... */
1127 CompanyID company_id = (CompanyID)p.Recv_uint8();
1128
1129 Debug(net, 9, "Client::Receive_SERVER_MOVE(): client_id={}, comapny_id={}", client_id, company_id);
1130
1131 if (client_id == 0) {
1132 /* definitely an invalid client id, debug message and do nothing. */
1133 Debug(net, 1, "Received invalid client index = 0");
1135 }
1136
1138 /* Just make sure we do not try to use a client_index that does not exist */
1139 if (ci == nullptr) return NETWORK_RECV_STATUS_OKAY;
1140
1141 /* if not valid player, force spectator, else check player exists */
1142 if (!Company::IsValidID(company_id)) company_id = COMPANY_SPECTATOR;
1143
1145 SetLocalCompany(company_id);
1146 }
1147
1149}
1150
1152{
1154
1155 _network_server_max_companies = p.Recv_uint8();
1157
1159
1160 Debug(net, 9, "Client::Receive_SERVER_CONFIG_UPDATE(): max_companies={}", _network_server_max_companies);
1161
1163}
1164
1169{
1170 /* Only once we're authorized we can expect a steady stream of packets. */
1171 if (this->status < STATUS_AUTHORIZED) return;
1172
1173 /* 5 seconds are roughly twice the server's "you're slow" threshold (1 game day). */
1174 std::chrono::steady_clock::duration lag = std::chrono::steady_clock::now() - this->last_packet;
1175 if (lag < std::chrono::seconds(5)) return;
1176
1177 /* 20 seconds are (way) more than 4 game days after which
1178 * the server will forcefully disconnect you. */
1179 if (lag > std::chrono::seconds(20)) {
1181 return;
1182 }
1183
1184 /* Prevent showing the lag message every tick; just update it when needed. */
1185 static std::chrono::steady_clock::duration last_lag = {};
1186 if (std::chrono::duration_cast<std::chrono::seconds>(last_lag) == std::chrono::duration_cast<std::chrono::seconds>(lag)) return;
1187
1188 last_lag = lag;
1190 GetEncodedString(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION),
1191 GetEncodedString(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, std::chrono::duration_cast<std::chrono::seconds>(lag).count()),
1192 WL_INFO);
1193}
1194
1195
1198{
1199 /* Set the frame-counter to 0 so nothing happens till we are ready */
1200 _frame_counter = 0;
1202 last_ack_frame = 0;
1203
1204 Debug(net, 9, "Client::NetworkClient_Connected()");
1205
1206 /* Request the game-info */
1208}
1209
1215void NetworkClientSendRcon(const std::string &password, const std::string &command)
1216{
1217 MyClient::SendRCon(password, command);
1218}
1219
1225{
1226 MyClient::SendMove(company_id);
1227}
1228
1234{
1236 /* If our company is changing owner, go to spectators */
1238
1240 if (ci->client_playas != cid) continue;
1241 NetworkTextMessage(NETWORK_ACTION_COMPANY_SPECTATOR, CC_DEFAULT, false, ci->client_name);
1242 ci->client_playas = COMPANY_SPECTATOR;
1243 }
1244
1245 cur_company.Restore();
1246}
1247
1255bool NetworkIsValidClientName(const std::string_view client_name)
1256{
1257 if (client_name.empty()) return false;
1258 if (client_name[0] == ' ') return false;
1259 return true;
1260}
1261
1277bool NetworkValidateClientName(std::string &client_name)
1278{
1279 StrTrimInPlace(client_name);
1280 if (NetworkIsValidClientName(client_name)) return true;
1281
1282 ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_BAD_PLAYER_NAME), {}, WL_ERROR);
1283 return false;
1284}
1285
1297
1302void NetworkUpdateClientName(const std::string &client_name)
1303{
1305 if (ci == nullptr) return;
1306
1307 /* Don't change the name if it is the same as the old name */
1308 if (client_name.compare(ci->client_name) != 0) {
1309 if (!_network_server) {
1310 MyClient::SendSetName(client_name);
1311 } else {
1312 /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */
1313 std::string temporary_name = client_name;
1314 if (NetworkMakeClientNameUnique(temporary_name)) {
1315 NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name);
1316 ci->client_name = temporary_name;
1318 }
1319 }
1320 }
1321}
1322
1331void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data)
1332{
1333 MyClient::SendChat(action, type, dest, msg, data);
1334}
1335
1342{
1343 /* Only companies actually playing can speak to team. Eg spectators cannot */
1345
1346 for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
1347 if (ci->client_playas == cio->client_playas && ci != cio) return true;
1348 }
1349
1350 return false;
1351}
1352
1361
virtual void AskUserForPassword(std::shared_ptr< NetworkAuthenticationPasswordRequest > request) override
Callback to trigger asking the user for the password.
virtual void SendResponse() override
Callback to trigger sending the response for the password request.
Class for handling the client side of the game connection.
NetworkRecvStatus Receive_SERVER_QUIT(Packet &p) override
Notification that a client left the game: uint32_t ID of the client.
static ClientNetworkGameSocketHandler * my_client
This is us!
static NetworkRecvStatus SendQuit()
Tell the server we would like to quit.
NetworkRecvStatus Receive_SERVER_SYNC(Packet &p) override
Sends a sync-check to the client: uint32_t Frame counter.
NetworkRecvStatus Receive_SERVER_ENABLE_ENCRYPTION(Packet &p) override
Indication to the client that authentication is complete and encryption has to be used from here on f...
NetworkRecvStatus Receive_SERVER_MAP_SIZE(Packet &p) override
Sends the size of the map to the client.
static bool Receive()
Check whether we received/can send some data from/to the server and when that's the case handle it ap...
NetworkRecvStatus Receive_SERVER_MAP_DONE(Packet &p) override
Sends that all data of the map are sent to the client:
NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet &p) override
Send information about a client: uint32_t ID of the client (always unique on a server.
~ClientNetworkGameSocketHandler()
Clear whatever we assigned.
ServerStatus status
Status of the connection with the server.
NetworkRecvStatus Receive_SERVER_CHECK_NEWGRFS(Packet &p) override
Sends information about all used GRFs to the client: uint8_t Amount of GRFs (the following data is re...
static NetworkRecvStatus SendMove(CompanyID company)
Ask the server to move us.
NetworkRecvStatus Receive_SERVER_WAIT(Packet &p) override
Notification that another client is currently receiving the map: uint8_t Number of clients waiting in...
std::unique_ptr< class NetworkAuthenticationClientHandler > authentication_handler
The handler for the authentication.
std::shared_ptr< struct PacketReader > savegame
Packet reader for reading the savegame.
static bool IsConnected()
Check whether the client is actually connected (and in the game).
NetworkRecvStatus Receive_SERVER_EXTERNAL_CHAT(Packet &p) override
Sends a chat-packet for external source to the client: string Name of the source this message came fr...
uint8_t token
The token we need to send back to the server to prove we're the right client.
static NetworkRecvStatus SendSetName(const std::string &name)
Tell the server that we like to change the name of the client.
friend void NetworkExecuteLocalCommandQueue()
Execute all commands on the local command queue that ought to be executed this frame.
NetworkRecvStatus Receive_SERVER_ERROR_QUIT(Packet &p) override
Inform all clients that one client made an error and thus has quit/been disconnected: uint32_t ID of ...
static NetworkRecvStatus SendNewGRFsOk()
Tell the server we got all the NewGRFs.
static NetworkRecvStatus SendMapOk()
Tell the server we received the complete map.
void CheckConnection()
Check the connection's state, i.e.
NetworkRecvStatus Receive_SERVER_RCON(Packet &p) override
Send the result of an issues RCon command back to the client: uint16_t Colour code.
NetworkRecvStatus Receive_SERVER_BANNED(Packet &p) override
Notification that the client trying to join is banned.
NetworkRecvStatus Receive_SERVER_CONFIG_UPDATE(Packet &p) override
Update the clients knowledge of the max settings: uint8_t Maximum number of companies allowed.
void ClientError(NetworkRecvStatus res)
Handle an error coming from the client side.
NetworkRecvStatus Receive_SERVER_WELCOME(Packet &p) override
The client is joined and ready to receive their map: uint32_t Own client ID.
static NetworkRecvStatus SendAck()
Send an acknowledgement from the server's ticks.
NetworkRecvStatus Receive_SERVER_MAP_BEGIN(Packet &p) override
Sends that the server will begin with sending the map to the client: uint32_t Current frame.
NetworkRecvStatus Receive_SERVER_JOIN(Packet &p) override
A client joined (PACKET_CLIENT_MAP_OK), what usually directly follows is a PACKET_SERVER_CLIENT_INFO:...
static NetworkRecvStatus SendAuthResponse()
Set the game password as requested.
static NetworkRecvStatus SendRCon(const std::string &password, const std::string &command)
Send a console command.
static bool GameLoop()
Actual game loop for the client.
static void Send()
Send the packets of this socket handler.
@ STATUS_JOIN
We are trying to join a server.
@ STATUS_ENCRYPTED
The game authentication has completed and from here on the connection to the server is encrypted.
@ STATUS_MAP
The client is downloading the map.
@ STATUS_AUTH_GAME
Last action was requesting game (server) password.
@ STATUS_ACTIVE
The client is active within in the game.
@ STATUS_MAP_WAIT
The client is waiting as someone else is downloading the map.
@ STATUS_AUTHORIZED
The client is authorized at the server.
NetworkRecvStatus Receive_SERVER_CHAT(Packet &p) override
Sends a chat-packet to the client: uint8_t ID of the action (see NetworkAction).
NetworkRecvStatus Receive_SERVER_MOVE(Packet &p) override
Move a client from one company into another: uint32_t ID of the client.
static NetworkRecvStatus SendCommand(const CommandPacket &cp)
Send a command to the server.
NetworkRecvStatus Receive_SERVER_FRAME(Packet &p) override
Sends the current frame counter to the client: uint32_t Frame counter uint32_t Frame counter max (how...
static NetworkRecvStatus SendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data)
Send a chat-packet over the network.
NetworkRecvStatus Receive_SERVER_COMMAND(Packet &p) override
Sends a DoCommand to the client: uint8_t ID of the company (0..MAX_COMPANIES-1).
NetworkRecvStatus Receive_SERVER_NEWGAME(Packet &p) override
Let the clients know that the server is loading a new map.
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override
Close the network connection due to the given status.
static NetworkRecvStatus SendGetMap()
Request the map from the server.
ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string)
Create a new socket for the client side of the game connection.
NetworkRecvStatus Receive_SERVER_AUTH_REQUEST(Packet &p) override
Indication to the client that it needs to authenticate: uint8_t The NetworkAuthenticationMethod to us...
NetworkRecvStatus Receive_SERVER_MAP_DATA(Packet &p) override
Sends the data of the map to the client: Contains a part of the map (until max size of packet).
NetworkRecvStatus Receive_SERVER_ERROR(Packet &p) override
The client made an error: uint8_t Error code caused (see NetworkErrorCode).
static NetworkRecvStatus SendError(NetworkErrorCode errorno)
Send an error-packet over the network.
NetworkRecvStatus Receive_SERVER_SHUTDOWN(Packet &p) override
Let the clients know that the server is closing.
static NetworkRecvStatus SendJoin()
Tell the server we would like to join.
NetworkRecvStatus Receive_SERVER_FULL(Packet &p) override
Notification that the server is full.
@ AwaitUserInput
We have requested some user input, but must wait on that.
@ Invalid
We have received an invalid request.
@ ReadyForResponse
We do not have to wait for user input, and can immediately respond to the server.
static std::unique_ptr< NetworkAuthenticationClientHandler > Create(std::shared_ptr< NetworkAuthenticationPasswordRequestHandler > password_handler, std::string &secret_key, std::string &public_key)
Create a NetworkAuthenticationClientHandler.
Callback interface for client implementations to provide the handling of the password requests.
Base socket handler for all TCP sockets.
Definition tcp_game.h:141
NetworkRecvStatus ReceivePackets()
Do the actual receiving of packets.
Definition tcp_game.cpp:131
NetworkClientInfo * GetInfo() const
Gets the client info of this socket handler.
Definition tcp_game.h:515
ClientID client_id
Client identifier.
Definition tcp_game.h:486
CommandQueue incoming_queue
The command-queue awaiting handling.
Definition tcp_game.h:489
std::chrono::steady_clock::time_point last_packet
Time we received the last frame.
Definition tcp_game.h:490
void SetInfo(NetworkClientInfo *info)
Sets the client info for this socket handler.
Definition tcp_game.h:505
const char * ReceiveCommand(Packet &p, CommandPacket &cp)
Receives a command from the network.
NetworkRecvStatus CloseConnection(bool error=true) override
Functions to help ReceivePacket/SendPacket a bit A socket can make errors.
Definition tcp_game.cpp:40
void MarkClosed()
Mark the connection as closed.
Definition core.h:66
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition core.h:74
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition core.h:50
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition core.h:49
SOCKET sock
The socket currently connected to.
Definition tcp.h:38
virtual void SendPacket(std::unique_ptr< Packet > &&packet)
This function puts the packet in the send-queue and it is send as soon as possible.
Definition tcp.cpp:58
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition tcp.cpp:76
bool CanSendReceive()
Check whether this socket can send or receive something.
Definition tcp.cpp:194
static void EventEnterMultiplayer(uint map_width, uint map_height)
Event: user entered a multiplayer game.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
TextColour GetDrawStringCompanyColour(CompanyID company)
Get the colour for DrawString-subroutines which matches the colour of the company.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
void SetLocalCompany(CompanyID new_company)
Sets the local company and updates the settings that are set on a per-company basis to reflect the co...
CompanyID _current_company
Company currently doing an action.
@ CCA_NEW
Create a new company.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
static constexpr CompanyID COMPANY_NEW_COMPANY
The client wants a new company.
@ CRR_NONE
Dummy reason for actions that don't need one.
static const uint NETWORK_CHAT_LENGTH
The maximum length of a chat message, in bytes including '\0'.
Definition config.h:61
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including '\0'.
Definition config.h:53
static const uint NETWORK_PUBLIC_KEY_LENGTH
The maximum length of the hexadecimal encoded public keys, in bytes including '\0'.
Definition config.h:101
static const uint NETWORK_RCONCOMMAND_LENGTH
The maximum length of a rconsole command, in bytes including '\0'.
Definition config.h:59
void IConsolePrint(TextColour colour_code, const std::string &string)
Handle the printing of text entered into the console or redirected there by any other means.
Definition console.cpp:89
bool IsValidConsoleColour(TextColour c)
Check whether the given TextColour is valid for console usage.
static const TextColour CC_WARNING
Colour for warning lines.
static const TextColour CC_DEFAULT
Default colour of the console.
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition core.h:23
@ NETWORK_RECV_STATUS_DESYNC
A desync did occur.
Definition core.h:25
@ NETWORK_RECV_STATUS_CLIENT_QUIT
The connection is lost gracefully. Other clients are already informed of this leaving client.
Definition core.h:28
@ NETWORK_RECV_STATUS_SERVER_ERROR
The server told us we made an error.
Definition core.h:30
@ NETWORK_RECV_STATUS_SAVEGAME
Something went wrong (down)loading the savegame.
Definition core.h:27
@ NETWORK_RECV_STATUS_CLOSE_QUERY
Done querying the server.
Definition core.h:33
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition core.h:24
@ NETWORK_RECV_STATUS_NEWGRF_MISMATCH
We did not have the required NewGRFs.
Definition core.h:26
@ NETWORK_RECV_STATUS_SERVER_FULL
The server is full.
Definition core.h:31
@ NETWORK_RECV_STATUS_MALFORMED_PACKET
We apparently send a malformed packet.
Definition core.h:29
@ NETWORK_RECV_STATUS_SERVER_BANNED
The server has banned us.
Definition core.h:32
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
void ClearErrorMessages()
Clear all errors from the queue.
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition error.h:26
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
Definition error.h:27
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, const CommandCost &cc)
Display an error message in a window.
SaveLoadOperation
Operation performed on the file.
Definition fileio_type.h:53
@ SLO_LOAD
File is being loaded.
Definition fileio_type.h:55
DetailedFileType
Kinds of files in each AbstractFileType.
Definition fileio_type.h:29
@ DFT_GAME_FILE
Save game or scenario file.
Definition fileio_type.h:32
Subdirectory
The different kinds of subdirectories OpenTTD uses.
@ NO_DIRECTORY
A path without any base directory.
@ FT_SAVEGAME
old or new savegame
Definition fileio_type.h:18
GameSessionStats _game_session_stats
Statistics about the current session.
Definition gfx.cpp:51
SwitchMode _switch_mode
The next mainloop command.
Definition gfx.cpp:49
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:294
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition gfx_type.h:357
StringID GetNetworkErrorMsg(NetworkErrorCode err)
Retrieve the string id of an internal error number.
Definition network.cpp:310
uint32_t _frame_counter_server
The frame_counter of the server, if in network-mode.
Definition network.cpp:76
uint32_t _frame_counter
The current frame.
Definition network.cpp:78
uint8_t _network_reconnect
Reconnect timeout.
Definition network.cpp:72
bool _networking
are we in networking mode?
Definition network.cpp:65
bool _network_server
network-server is active
Definition network.cpp:66
uint32_t _sync_seed_1
Seed to compare during sync checks.
Definition network.cpp:81
uint32_t _sync_frame
The frame to perform the sync check.
Definition network.cpp:85
ClientID _network_own_client_id
Our client identifier.
Definition network.cpp:70
bool _network_first_time
Whether we have finished joining or not.
Definition network.cpp:86
uint32_t _frame_counter_max
To where we may go with our clients.
Definition network.cpp:77
Basic functions/variables used all over the place.
Base core network types and some helper functions to access them.
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, int64_t data)
Send a chat message.
void NetworkUpdateClientName(const std::string &client_name)
Send the server our name as callback from the setting.
NetworkJoinInfo _network_join
Information about the game to join to.
bool NetworkIsValidClientName(const std::string_view client_name)
Check whether the given client name is deemed valid for use in network games.
bool NetworkValidateOurClientName()
Convenience method for NetworkValidateClientName on _settings_client.network.client_name.
void ClientNetworkEmergencySave()
Create an emergency savegame when the network connection is lost.
static uint32_t last_ack_frame
Last frame we performed an ack.
bool NetworkMaxCompaniesReached()
Check if max_companies has been reached on the server (local check only).
uint NetworkMaxCompaniesAllowed()
Get the maximum number of companies that are allowed by the server.
void NetworkClientsToSpectators(CompanyID cid)
Move the clients of a company to the spectators.
static uint8_t _network_server_max_companies
Maximum number of companies of the currently joined server.
bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio)
Tell whether the client has team members who they can chat to.
std::string _network_server_name
The current name of the server you are on.
void NetworkClientRequestMove(CompanyID company_id)
Notify the server of this client wanting to be moved to another company.
bool NetworkValidateClientName(std::string &client_name)
Trim the given client name in place, i.e.
void NetworkClientSendRcon(const std::string &password, const std::string &command)
Send a remote console command.
Client part of the network protocol.
NetworkJoinInfo _network_join
Information about the game to join to.
void NetworkClient_Connected()
Is called after a client is connected to the server.
void NetworkUpdateClientInfo(ClientID client_id)
Send updated client info of a particular client.
Handling of the list of games.
NetworkJoinStatus _network_join_status
The status of joining.
uint8_t _network_join_waiting
The number of clients waiting in front of us.
uint32_t _network_join_bytes_total
The total number of bytes to download.
uint32_t _network_join_bytes
The number of bytes we already downloaded.
GUIs related to networking.
bool NetworkMakeClientNameUnique(std::string &new_name)
Check whether a name is unique, and otherwise try to make it unique.
DestType
Destination of our chat messages.
NetworkErrorCode
The error codes we send around in the protocols.
NetworkAction
Actions that can be used for NetworkTextMessage.
ClientID
'Unique' identifier to be given to clients
@ CLIENT_ID_SERVER
Servers always have this ID.
const GRFConfig * FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
Find a NewGRF in the scanned list.
@ FGCM_EXACT
Only find Grfs matching md5sum.
void StateGameLoop()
State controlling game loop.
Definition openttd.cpp:1206
GameMode
Mode which defines the state of the game.
Definition openttd.h:18
@ SM_MENU
Switch to game intro menu.
Definition openttd.h:33
Randomizer _random
Random used in the game state calculations.
void DoAutoOrNetsave(FiosNumberedSaveName &counter)
Create an autosave or netsave.
FileToSaveLoad _file_to_saveload
File to save or load in the openttd loop.
Definition saveload.cpp:64
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:57
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:277
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition string.cpp:80
void StrTrimInPlace(std::string &str)
Trim the spaces from given string in place, i.e.
Definition string.cpp:278
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:426
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Class to backup a specific variable and restore it later.
void Restore()
Restore the variable.
The buffer for writing a single string.
NetworkSettings network
settings related to the network
GUISettings gui
settings related to the GUI
Everything we need to know about a command to be able to execute it.
uint32_t frame
the frame in which this packet is executed
bool my_cmd
did the command originate from "me"
Commands cmd
command being executed.
void SetMode(FiosType ft)
Set the mode and file type of the file to save or load based on the type of file entry at the file sy...
A savegame name automatically numbered.
Definition fios.h:128
Information about GRF, used in the game and (part of it) in savegames.
Basic data to distinguish a GRF.
uint32_t grfid
GRF ID (defined by Action 0x08)
MD5Hash md5sum
MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
bool prefer_teamchat
choose the chat message target with <ENTER>, true=all clients, false=your team
std::chrono::steady_clock::time_point start_time
Time when the current game was started.
Definition openttd.h:56
std::optional< size_t > savegame_size
Size of the last saved savegame in bytes, or std::nullopt if not saved yet.
Definition openttd.h:58
Interface for filtering a savegame till it is loaded.
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:278
static debug_inline uint SizeX()
Get the size of the map along the X.
Definition map_func.h:269
Container for all information known about a client.
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition network.cpp:116
CompanyID client_playas
As which company is this client playing (CompanyID)
std::string client_name
Name of the client.
std::string public_key
The public key of the client.
Information required to join a server.
std::string server_password
The password of the server to join.
CompanyID company
The company to join.
std::string client_secret_key
The secret key of the client for authorized key logins.
uint8_t max_companies
maximum amount of companies
std::string client_name
name of the player (as client)
std::string client_public_key
The public key of the client for authorized key logins.
Read some packets, and when do use that data as initial load filter.
size_t Read(uint8_t *rbuf, size_t size) override
Read a given number of bytes from the savegame.
PacketReader()
Initialise everything.
size_t read_bytes
The total number of read bytes.
void AddPacket(Packet &p)
Add a packet to this buffer.
Buffer::const_iterator iterator
Buffer we're going to write to/read from.
void Reset() override
Reset this filter to read from the beginning of the file.
static ssize_t TransferOutMemCopy(PacketReader *destination, const char *source, size_t amount)
Simple wrapper around fwrite to be able to pass it to Packet's TransferOut.
Buffer buffer
Buffer with the raw save game data.
Internal entity of a packet.
Definition packet.h:43
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
Definition packet.cpp:332
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition packet.cpp:364
bool Recv_bool()
Read a boolean from the packet.
Definition packet.cpp:309
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition packet.cpp:347
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition packet.cpp:318
ssize_t TransferOut(F transfer_function, D destination, Args &&... args)
Transfer data from the packet to the given function.
Definition packet.h:141
bool CanReadFromPacket(size_t bytes_to_read, bool close_connection=false)
Is it safe to read from the packet, i.e.
Definition packet.cpp:219
std::string Recv_string(size_t length, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
Definition packet.cpp:425
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static size_t GetNumItems()
Returns number of valid items in the pool.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
uint32_t state[2]
The state of the randomizer.
@ PACKET_CLIENT_IDENTIFY
Client telling the server the client's name and requested company.
Definition tcp_game.h:68
@ PACKET_CLIENT_GETMAP
Client requests the actual map.
Definition tcp_game.h:79
@ PACKET_CLIENT_ERROR
A client reports an error to the server.
Definition tcp_game.h:124
@ PACKET_CLIENT_JOIN
The client telling the server it wants to join.
Definition tcp_game.h:37
@ PACKET_CLIENT_AUTH_RESPONSE
The client responds to the authentication request.
Definition tcp_game.h:64
@ PACKET_CLIENT_NEWGRFS_CHECKED
Client acknowledges that it has all required NewGRFs.
Definition tcp_game.h:72
@ PACKET_CLIENT_COMMAND
Client executed a command and sends it to the server.
Definition tcp_game.h:101
@ PACKET_CLIENT_SET_NAME
A client changes its name.
Definition tcp_game.h:118
@ PACKET_CLIENT_ACK
The client tells the server which frame it has executed.
Definition tcp_game.h:97
@ PACKET_CLIENT_RCON
Client asks the server to execute some command.
Definition tcp_game.h:110
@ PACKET_CLIENT_MAP_OK
Client tells the server that it received the whole map.
Definition tcp_game.h:85
@ PACKET_CLIENT_QUIT
A client tells the server it is going to quit.
Definition tcp_game.h:122
@ PACKET_CLIENT_MOVE
A client would like to be moved to another company.
Definition tcp_game.h:114
@ PACKET_CLIENT_CHAT
Client said something that should be distributed.
Definition tcp_game.h:105
void CSleep(int milliseconds)
Sleep on the current thread for a defined time.
Definition thread.h:24
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1143
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3224
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3106
@ WN_NETWORK_STATUS_WINDOW_JOIN
Network join status.
Definition window_type.h:41
@ WC_CLIENT_LIST
Client list; Window numbers:
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers: